diff --git a/Yubico.Core/src/Yubico.Core.csproj b/Yubico.Core/src/Yubico.Core.csproj index b80c838b..b4924a02 100644 --- a/Yubico.Core/src/Yubico.Core.csproj +++ b/Yubico.Core/src/Yubico.Core.csproj @@ -107,9 +107,9 @@ limitations under the License. --> - + - + diff --git a/Yubico.Core/src/Yubico/Core/Devices/Hid/MacOSHidDevice.cs b/Yubico.Core/src/Yubico/Core/Devices/Hid/MacOSHidDevice.cs index afbdc62f..260c3d9a 100644 --- a/Yubico.Core/src/Yubico/Core/Devices/Hid/MacOSHidDevice.cs +++ b/Yubico.Core/src/Yubico/Core/Devices/Hid/MacOSHidDevice.cs @@ -50,7 +50,7 @@ public MacOSHidDevice(long entryId) : public static IEnumerable GetList() { Logger log = Log.GetLogger(); - using IDisposable logScope = log.BeginScope("MacOSHidDevice.GetList()"); + using IDisposable? logScope = log.BeginScope("MacOSHidDevice.GetList()"); IntPtr manager = IntPtr.Zero; IntPtr deviceSet = IntPtr.Zero; diff --git a/Yubico.Core/src/Yubico/Core/Devices/Hid/MacOSHidDeviceListener.cs b/Yubico.Core/src/Yubico/Core/Devices/Hid/MacOSHidDeviceListener.cs index f0ced0fe..6f0b9578 100644 --- a/Yubico.Core/src/Yubico/Core/Devices/Hid/MacOSHidDeviceListener.cs +++ b/Yubico.Core/src/Yubico/Core/Devices/Hid/MacOSHidDeviceListener.cs @@ -68,7 +68,7 @@ private void StopListening() private void ListeningThread() { const int runLoopTimeout = 10; // 10 seconds is arbitrary, pulled from Apple sample code - using IDisposable logScope = _log.BeginScope("MacOSHidDeviceListener.StartListening()"); + using IDisposable? logScope = _log.BeginScope("MacOSHidDeviceListener.StartListening()"); _log.LogInformation("HID listener thread started. ThreadID is {ThreadID}.", Environment.CurrentManagedThreadId); diff --git a/Yubico.Core/src/Yubico/Core/Devices/SmartCard/DesktopSmartCardConnection.cs b/Yubico.Core/src/Yubico/Core/Devices/SmartCard/DesktopSmartCardConnection.cs index 83a4307b..a8b6aaf8 100644 --- a/Yubico.Core/src/Yubico/Core/Devices/SmartCard/DesktopSmartCardConnection.cs +++ b/Yubico.Core/src/Yubico/Core/Devices/SmartCard/DesktopSmartCardConnection.cs @@ -33,7 +33,7 @@ private class TransactionScope : IDisposable { private readonly Logger _log = Log.GetLogger(); private readonly DesktopSmartCardConnection _thisConnection; - private readonly IDisposable _logScope; + private readonly IDisposable? _logScope; private bool _disposedValue; public TransactionScope(DesktopSmartCardConnection thisConnection) @@ -58,7 +58,7 @@ protected virtual void Dispose(bool disposing) if (disposing) { - _logScope.Dispose(); + _logScope?.Dispose(); } } diff --git a/Yubico.Core/src/Yubico/Core/Devices/SmartCard/DesktopSmartCardDevice.cs b/Yubico.Core/src/Yubico/Core/Devices/SmartCard/DesktopSmartCardDevice.cs index eb27357f..3a11217d 100644 --- a/Yubico.Core/src/Yubico/Core/Devices/SmartCard/DesktopSmartCardDevice.cs +++ b/Yubico.Core/src/Yubico/Core/Devices/SmartCard/DesktopSmartCardDevice.cs @@ -32,7 +32,7 @@ internal class DesktopSmartCardDevice : SmartCardDevice public static IReadOnlyList GetList() { Logger log = Log.GetLogger(); - using IDisposable logScope = log.BeginScope("SmartCardDevice.GetList()"); + using IDisposable? logScope = log.BeginScope("SmartCardDevice.GetList()"); uint result = SCardEstablishContext(SCARD_SCOPE.USER, out SCardContext context); log.SCardApiCall(nameof(SCardEstablishContext), result); diff --git a/Yubico.Core/src/Yubico/Core/Devices/SmartCard/SmartCardLoggerExtensions.cs b/Yubico.Core/src/Yubico/Core/Devices/SmartCard/SmartCardLoggerExtensions.cs index 78ee7e6b..f6224383 100644 --- a/Yubico.Core/src/Yubico/Core/Devices/SmartCard/SmartCardLoggerExtensions.cs +++ b/Yubico.Core/src/Yubico/Core/Devices/SmartCard/SmartCardLoggerExtensions.cs @@ -8,7 +8,7 @@ namespace Yubico.Core.Devices.SmartCard { internal static class SmartCardLoggerExtensions { - public static IDisposable BeginTransactionScope(this Logger logger, IDisposable transactionScope) => + public static IDisposable? BeginTransactionScope(this Logger logger, IDisposable transactionScope) => logger.BeginScope("Transaction[{TransactionID}]", transactionScope.GetHashCode()); public static void SCardApiCall(this Logger logger, string apiName, uint result) diff --git a/Yubico.Core/src/Yubico/Core/Logging/Logger.cs b/Yubico.Core/src/Yubico/Core/Logging/Logger.cs index 6b2f7fa8..53c110fd 100644 --- a/Yubico.Core/src/Yubico/Core/Logging/Logger.cs +++ b/Yubico.Core/src/Yubico/Core/Logging/Logger.cs @@ -122,6 +122,6 @@ public void Log( /// /// A disposable object that ends the logical operation scope on dispose. /// - public IDisposable BeginScope(TState state) => _logger.BeginScope(state); + public IDisposable? BeginScope(TState state) where TState : notnull => _logger.BeginScope(state); } } diff --git a/Yubico.Core/src/Yubico/Core/Logging/LoggerExtensions.cs b/Yubico.Core/src/Yubico/Core/Logging/LoggerExtensions.cs index f56dc284..579dd303 100644 --- a/Yubico.Core/src/Yubico/Core/Logging/LoggerExtensions.cs +++ b/Yubico.Core/src/Yubico/Core/Logging/LoggerExtensions.cs @@ -934,7 +934,7 @@ public static void SensitiveLog(this Logger logger, LogLevel logLevel, EventId e /// { /// } /// - public static IDisposable BeginScope( + public static IDisposable? BeginScope( this Logger logger, string messageFormat, params object?[] args) => diff --git a/Yubico.Core/tests/Yubico.Core.UnitTests.csproj b/Yubico.Core/tests/Yubico.Core.UnitTests.csproj index 5861e927..c07faf01 100644 --- a/Yubico.Core/tests/Yubico.Core.UnitTests.csproj +++ b/Yubico.Core/tests/Yubico.Core.UnitTests.csproj @@ -44,6 +44,11 @@ limitations under the License. --> + + + + + diff --git a/Yubico.Core/tests/Yubico/Core/Devices/Hid/HidTranslatorTests.cs b/Yubico.Core/tests/Yubico/Core/Devices/Hid/HidTranslatorTests.cs index 4fbbb3d6..a31bb99e 100644 --- a/Yubico.Core/tests/Yubico/Core/Devices/Hid/HidTranslatorTests.cs +++ b/Yubico.Core/tests/Yubico/Core/Devices/Hid/HidTranslatorTests.cs @@ -156,7 +156,7 @@ public void GetChar_GivenHidCode_ReturnsCorrectChar(KeyboardLayout layout, (char } #endif - private static IEnumerable GetTestData() + public static IEnumerable GetTestData() { // Originally, I hard-coded these, but I decided that it should do // this dynamically so that newly added keyboard layouts aren't left diff --git a/Yubico.Core/tests/Yubico/Core/Iso7816/ResponseApduTests.cs b/Yubico.Core/tests/Yubico/Core/Iso7816/ResponseApduTests.cs index 22d6a24e..c8467708 100644 --- a/Yubico.Core/tests/Yubico/Core/Iso7816/ResponseApduTests.cs +++ b/Yubico.Core/tests/Yubico/Core/Iso7816/ResponseApduTests.cs @@ -46,7 +46,7 @@ public void SW1_GivenResponseApdu_MatchesUpperByteOfSW() var responseApdu = new ResponseApdu(new byte[] { SW1, SW2 }); - Assert.Equal(responseApdu.SW >> 8, SW1); + Assert.Equal(SW1, responseApdu.SW >> 8); } [Fact] @@ -68,7 +68,7 @@ public void SW2_GivenResponseApdu_MatchesLowerByteOfSW() var responseApdu = new ResponseApdu(new byte[] { SW1, SW2 }); - Assert.Equal(responseApdu.SW & 0xFF, SW2); + Assert.Equal(SW2, responseApdu.SW & 0xFF); } [Fact] diff --git a/Yubico.DotNetPolyfills/src/Yubico.DotNetPolyfills.csproj b/Yubico.DotNetPolyfills/src/Yubico.DotNetPolyfills.csproj index 4b2952f4..4a0fdc69 100644 --- a/Yubico.DotNetPolyfills/src/Yubico.DotNetPolyfills.csproj +++ b/Yubico.DotNetPolyfills/src/Yubico.DotNetPolyfills.csproj @@ -53,10 +53,6 @@ limitations under the License. --> - - - - @@ -64,7 +60,7 @@ limitations under the License. --> - + diff --git a/Yubico.NET.SDK.sln b/Yubico.NET.SDK.sln index 25551979..266cd8de 100644 --- a/Yubico.NET.SDK.sln +++ b/Yubico.NET.SDK.sln @@ -75,7 +75,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{778EE2C1 build\CompilerSettings.props = build\CompilerSettings.props build\Directory.Build.props = build\Directory.Build.props build\Directory.Build.targets = build\Directory.Build.targets - build\PackageReferences.props = build\PackageReferences.props build\ProjectTypes.props = build\ProjectTypes.props build\Versions.props = build\Versions.props EndProjectSection diff --git a/Yubico.YubiKey/tests/integration/Yubico.YubiKey.IntegrationTests.csproj b/Yubico.YubiKey/tests/integration/Yubico.YubiKey.IntegrationTests.csproj index 34d2f235..76b31eb4 100644 --- a/Yubico.YubiKey/tests/integration/Yubico.YubiKey.IntegrationTests.csproj +++ b/Yubico.YubiKey/tests/integration/Yubico.YubiKey.IntegrationTests.csproj @@ -34,15 +34,18 @@ limitations under the License. --> + + + + + + + + + + PreserveNewest - - - - - - - diff --git a/Yubico.YubiKey/tests/integration/Yubico/YubiKey/Fido2/BioEnrollTests.cs b/Yubico.YubiKey/tests/integration/Yubico/YubiKey/Fido2/BioEnrollTests.cs index 847aaa8c..9570ec97 100644 --- a/Yubico.YubiKey/tests/integration/Yubico/YubiKey/Fido2/BioEnrollTests.cs +++ b/Yubico.YubiKey/tests/integration/Yubico/YubiKey/Fido2/BioEnrollTests.cs @@ -75,7 +75,7 @@ public void EnrollFingerprint_Succeeds() TemplateInfo templateInfo = fido2Session.EnrollFingerprint(firstName, 5000); Assert.NotNull(templateInfo.FriendlyName); - Assert.True(templateInfo.FriendlyName.Equals(firstName, StringComparison.Ordinal)); + Assert.Equal(firstName, templateInfo.FriendlyName); Assert.NotEmpty(templateInfo.TemplateId.ToArray()); fido2Session.SetBioTemplateFriendlyName(templateInfo.TemplateId, secondName); diff --git a/Yubico.YubiKey/tests/integration/Yubico/YubiKey/Fido2/Commands/BioEnrollmentCommandTests.cs b/Yubico.YubiKey/tests/integration/Yubico/YubiKey/Fido2/Commands/BioEnrollmentCommandTests.cs index 0af3fed5..44a45a54 100644 --- a/Yubico.YubiKey/tests/integration/Yubico/YubiKey/Fido2/Commands/BioEnrollmentCommandTests.cs +++ b/Yubico.YubiKey/tests/integration/Yubico/YubiKey/Fido2/Commands/BioEnrollmentCommandTests.cs @@ -128,7 +128,7 @@ public void EnumerateEnrollmentsCommand_Succeeds() Assert.Equal(ResponseStatus.Success, rsp.Status); IReadOnlyList templateInfos = rsp.GetData(); - Assert.Equal(1, templateInfos.Count); + _ = Assert.Single(templateInfos); } [Fact] diff --git a/Yubico.YubiKey/tests/integration/Yubico/YubiKey/Fido2/CredMgmtTests.cs b/Yubico.YubiKey/tests/integration/Yubico/YubiKey/Fido2/CredMgmtTests.cs index f6c81ca7..2cf3568d 100644 --- a/Yubico.YubiKey/tests/integration/Yubico/YubiKey/Fido2/CredMgmtTests.cs +++ b/Yubico.YubiKey/tests/integration/Yubico/YubiKey/Fido2/CredMgmtTests.cs @@ -131,7 +131,7 @@ public void UpdateUserInfo_Succeeds() IReadOnlyList credList = fido2Session.EnumerateCredentialsForRelyingParty(_bioFido2Fixture.RpInfoList[0].RelyingParty); - Assert.NotEqual(0, credList.Count); + Assert.NotEmpty(credList); fido2Session.ClearAuthToken(); fido2Session.AddPermissions(PinUvAuthTokenPermissions.AuthenticatorConfiguration, null); @@ -144,7 +144,7 @@ public void UpdateUserInfo_Succeeds() credList = fido2Session.EnumerateCredentialsForRelyingParty(_bioFido2Fixture.RpInfoList[0].RelyingParty); string displayName = credList[0].User.DisplayName??""; - Assert.True(displayName.Equals(updatedDisplayName)); + Assert.Equal(updatedDisplayName, displayName); } } } diff --git a/Yubico.YubiKey/tests/integration/Yubico/YubiKey/Fido2/MakeCredentialGetAssertionTests.cs b/Yubico.YubiKey/tests/integration/Yubico/YubiKey/Fido2/MakeCredentialGetAssertionTests.cs index 9efd14c8..d62334f8 100644 --- a/Yubico.YubiKey/tests/integration/Yubico/YubiKey/Fido2/MakeCredentialGetAssertionTests.cs +++ b/Yubico.YubiKey/tests/integration/Yubico/YubiKey/Fido2/MakeCredentialGetAssertionTests.cs @@ -66,8 +66,8 @@ public void MakeCredential_NonDiscoverable_GetAssertion_Succeeds() IReadOnlyList assertions = fido2.GetAssertions(gaParams); - Assert.Equal(1, assertions.Count); - Assert.Equal(1, assertions[0].NumberOfCredentials); + GetAssertionData assertion = Assert.Single(assertions); + Assert.Equal(1, assertion.NumberOfCredentials); } } @@ -103,7 +103,7 @@ public void MakeCredential_NoName_GetAssertion_Succeeds() IReadOnlyList assertions = fido2.GetAssertions(gaParams); - Assert.Equal(1, assertions.Count); + _ = Assert.Single(assertions); } } diff --git a/Yubico.YubiKey/tests/integration/Yubico/YubiKey/Oath/NoCollectorPasswordTests.cs b/Yubico.YubiKey/tests/integration/Yubico/YubiKey/Oath/NoCollectorPasswordTests.cs index cec55af8..9ae3005c 100644 --- a/Yubico.YubiKey/tests/integration/Yubico/YubiKey/Oath/NoCollectorPasswordTests.cs +++ b/Yubico.YubiKey/tests/integration/Yubico/YubiKey/Oath/NoCollectorPasswordTests.cs @@ -45,10 +45,10 @@ public void SetPassword_Succeeds() Assert.False(oathSession.IsPasswordProtected); IList credentialList = oathSession.GetCredentials(); - Assert.Equal(1, credentialList.Count); + _ = Assert.Single(credentialList); Credential cred = credentialList[0]; - Assert.NotNull(cred.Algorithm); + _ = Assert.NotNull(cred.Algorithm); if (!(cred.Algorithm is null)) { Assert.Equal(HashAlgorithm.Sha256, cred.Algorithm); @@ -65,7 +65,7 @@ public void SetPassword_Succeeds() Assert.True(oathSession.IsPasswordProtected); IList credentialList = oathSession.GetCredentials(); - Assert.Equal(1, credentialList.Count); + _ = Assert.Single(credentialList); } using (var oathSession = new OathSession(yubiKeyDevice)) @@ -84,10 +84,10 @@ public void SetPassword_Succeeds() Assert.True(isVerified); IList credentialList = oathSession.GetCredentials(); - Assert.Equal(1, credentialList.Count); + _ = Assert.Single(credentialList); Credential cred = credentialList[0]; - Assert.NotNull(cred.Algorithm); + _ = Assert.NotNull(cred.Algorithm); if (!(cred.Algorithm is null)) { Assert.Equal(HashAlgorithm.Sha256, cred.Algorithm); @@ -121,7 +121,7 @@ public void SetPassword_Succeeds() Assert.False(isSet); IList credentialList = oathSession.GetCredentials(); - Assert.Equal(1, credentialList.Count); + _ = Assert.Single(credentialList); } using (var oathSession = new OathSession(yubiKeyDevice)) @@ -138,7 +138,7 @@ public void SetPassword_Succeeds() Assert.False(isSet); IList credentialList = oathSession.GetCredentials(); - Assert.Equal(1, credentialList.Count); + _ = Assert.Single(credentialList); oathSession.ResetApplication(); } @@ -184,16 +184,16 @@ public void UnsetPassword_Succeeds() Assert.False(oathSession.IsPasswordProtected); IList credentialList = oathSession.GetCredentials(); - Assert.Equal(1, credentialList.Count); + _ = Assert.Single(credentialList); } using (var oathSession = new OathSession(yubiKeyDevice)) { IList credentialList = oathSession.GetCredentials(); - Assert.Equal(1, credentialList.Count); + _ = Assert.Single(credentialList); Credential cred = credentialList[0]; - Assert.NotNull(cred.Algorithm); + _ = Assert.NotNull(cred.Algorithm); if (!(cred.Algorithm is null)) { Assert.Equal(HashAlgorithm.Sha256, cred.Algorithm); @@ -295,16 +295,16 @@ public void VerifyPassword_UnsetNoCurrent_Succeeds() Assert.False(oathSession.IsPasswordProtected); IList credentialList = oathSession.GetCredentials(); - Assert.Equal(1, credentialList.Count); + _ = Assert.Single(credentialList); } using (var oathSession = new OathSession(yubiKeyDevice)) { IList credentialList = oathSession.GetCredentials(); - Assert.Equal(1, credentialList.Count); + _ = Assert.Single(credentialList); Credential cred = credentialList[0]; - Assert.NotNull(cred.Algorithm); + _ = Assert.NotNull(cred.Algorithm); if (!(cred.Algorithm is null)) { Assert.Equal(HashAlgorithm.Sha256, cred.Algorithm); @@ -340,7 +340,7 @@ public void PasswordNotSet_Verify_ReturnsFalse() Assert.False(oathSession.IsPasswordProtected); IList credentialList = oathSession.GetCredentials(); - Assert.Equal(1, credentialList.Count); + _ = Assert.Single(credentialList); oathSession.ResetApplication(); } diff --git a/Yubico.YubiKey/tests/sandbox/Yubico.YubiKey.TestApp.csproj b/Yubico.YubiKey/tests/sandbox/Yubico.YubiKey.TestApp.csproj index 6d986ee1..e4a59c01 100644 --- a/Yubico.YubiKey/tests/sandbox/Yubico.YubiKey.TestApp.csproj +++ b/Yubico.YubiKey/tests/sandbox/Yubico.YubiKey.TestApp.csproj @@ -34,11 +34,11 @@ limitations under the License. --> - - - - - + + + + + diff --git a/Yubico.YubiKey/tests/unit/Yubico.YubiKey.UnitTests.csproj b/Yubico.YubiKey/tests/unit/Yubico.YubiKey.UnitTests.csproj index 7dafe28a..cb2348ce 100644 --- a/Yubico.YubiKey/tests/unit/Yubico.YubiKey.UnitTests.csproj +++ b/Yubico.YubiKey/tests/unit/Yubico.YubiKey.UnitTests.csproj @@ -33,5 +33,10 @@ limitations under the License. --> + + + + + diff --git a/Yubico.YubiKey/tests/unit/Yubico/YubiKey/Oath/Commands/CalculateCredentialResponseTests .cs b/Yubico.YubiKey/tests/unit/Yubico/YubiKey/Oath/Commands/CalculateCredentialResponseTests .cs index bae463c7..68288e98 100644 --- a/Yubico.YubiKey/tests/unit/Yubico/YubiKey/Oath/Commands/CalculateCredentialResponseTests .cs +++ b/Yubico.YubiKey/tests/unit/Yubico/YubiKey/Oath/Commands/CalculateCredentialResponseTests .cs @@ -31,7 +31,7 @@ public void SuccessResponseApdu_NoCredential_ListCredentialsCorrectly() const byte sw2 = unchecked((byte)SWConstants.Success); var responseApdu = new ResponseApdu(new byte[] { sw1, sw2 }); - + var calculateCredentialResponse = new CalculateCredentialResponse(responseApdu, credential); Assert.Equal(SWConstants.Success, calculateCredentialResponse.StatusWord); @@ -80,6 +80,7 @@ public void Constructor_SuccessResponseApdu_FullResponse_ReturnResponseCorrectly var data = calculateCredentialResponse.GetData(); Assert.Equal(SWConstants.Success, calculateCredentialResponse.StatusWord); + Assert.NotNull(data.Value); Assert.NotEmpty(data.Value); } @@ -98,6 +99,7 @@ public void Constructor_SuccessResponseApdu_TruncatedResponse_ReturnResponseCorr var data = calculateCredentialResponse.GetData(); Assert.Equal(SWConstants.Success, calculateCredentialResponse.StatusWord); + Assert.NotNull(data.Value); Assert.NotEmpty(data.Value); } diff --git a/Yubico.YubiKey/tests/unit/Yubico/YubiKey/U2f/Commands/ResetCommandTests.cs b/Yubico.YubiKey/tests/unit/Yubico/YubiKey/U2f/Commands/ResetCommandTests.cs index f0ffc9b1..f481eb84 100644 --- a/Yubico.YubiKey/tests/unit/Yubico/YubiKey/U2f/Commands/ResetCommandTests.cs +++ b/Yubico.YubiKey/tests/unit/Yubico/YubiKey/U2f/Commands/ResetCommandTests.cs @@ -69,7 +69,7 @@ public void CreateCommandApdu_GetNcProperty_ReturnsCorrectLength() var command = new ResetCommand(); CommandApdu commandApdu = command.CreateCommandApdu(); - Assert.Equal(commandApdu.Nc, lengthHeader); + Assert.Equal(lengthHeader, commandApdu.Nc); } [Fact] diff --git a/Yubico.YubiKey/tests/unit/Yubico/YubiKey/U2f/Commands/VerifyFipsModeCommandTests.cs b/Yubico.YubiKey/tests/unit/Yubico/YubiKey/U2f/Commands/VerifyFipsModeCommandTests.cs index 9cd4727c..8ed75b10 100644 --- a/Yubico.YubiKey/tests/unit/Yubico/YubiKey/U2f/Commands/VerifyFipsModeCommandTests.cs +++ b/Yubico.YubiKey/tests/unit/Yubico/YubiKey/U2f/Commands/VerifyFipsModeCommandTests.cs @@ -69,7 +69,7 @@ public void CreateCommandApdu_GetNcProperty_ReturnsCorrectLength() var command = new VerifyFipsModeCommand(); CommandApdu commandApdu = command.CreateCommandApdu(); - Assert.Equal(commandApdu.Nc, lengthHeader); + Assert.Equal(lengthHeader, commandApdu.Nc); } [Fact] diff --git a/build/Directory.Build.props b/build/Directory.Build.props index 9b0df167..4d21e4d4 100644 --- a/build/Directory.Build.props +++ b/build/Directory.Build.props @@ -36,7 +36,4 @@ limitations under the License. --> - - - - \ No newline at end of file + diff --git a/build/PackageReferences.props b/build/PackageReferences.props deleted file mode 100644 index e0224c7f..00000000 --- a/build/PackageReferences.props +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/latestpackages/placeholder.txt b/build/latestpackages/placeholder.txt deleted file mode 100644 index 0494840c..00000000 --- a/build/latestpackages/placeholder.txt +++ /dev/null @@ -1 +0,0 @@ -DO NOT DELETE. Needed to pin otherwise empty directory in Git. \ No newline at end of file