From 946b2949d9729418799280bf2ac1e64e74fb86e1 Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Wed, 3 Mar 2021 12:20:32 -0800 Subject: [PATCH] Tests | Fix random test failures (#931) --- .../ExceptionsAlgorithmErrors.cs | 153 +++++++++--------- .../ExceptionsCertStore.cs | 10 +- .../AlwaysEncrypted/ConversionTests.cs | 7 +- .../TestFixtures/SQLSetupStrategy.cs | 7 +- .../SQL/ExceptionTest/ExceptionTest.cs | 19 ++- .../tests/ManualTests/SQL/UdtTest/UdtTest.cs | 79 +++++---- 6 files changed, 162 insertions(+), 113 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/ExceptionsAlgorithmErrors.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/ExceptionsAlgorithmErrors.cs index 39fb06a1c0..218d3bc79c 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/ExceptionsAlgorithmErrors.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/ExceptionsAlgorithmErrors.cs @@ -34,32 +34,32 @@ public void TestNullCEK() [PlatformSpecific(TestPlatforms.Windows)] public void TestInvalidKeySize() { - byte[] key = Utility.GenerateRandomBytes(48); + byte[] key = GenerateRandomBytes(48); for (int i = 0; i < key.Length; i++) { key[i] = 0x00; } TargetInvocationException e = Assert.Throws(() => - Utility.EncryptDataUsingAED(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, key, Utility.CColumnEncryptionType.Deterministic)); - string expectedMessage = "The column encryption key has been successfully decrypted but it's length: 48 does not match the length: 32 for algorithm 'AEAD_AES_256_CBC_HMAC_SHA256'. Verify the encrypted value of the column encryption key in the database.\r\nParameter name: encryptionKey"; - Assert.Contains(expectedMessage, e.InnerException.Message); + EncryptDataUsingAED(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, key, CColumnEncryptionType.Deterministic)); + string expectedMessage = @"The column encryption key has been successfully decrypted but it's length: 48 does not match the length: 32 for algorithm 'AEAD_AES_256_CBC_HMAC_SHA256'. Verify the encrypted value of the column encryption key in the database.\s+\(?Parameter (name: )?'?encryptionKey('\))?"; + Assert.Matches(expectedMessage, e.InnerException.Message); } [Fact] [PlatformSpecific(TestPlatforms.Windows)] public void TestInvalidEncryptionType() { - Object cipherMD = Utility.GetSqlCipherMetadata(0, 2, null, 3, 0x01); - Utility.AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP"); + Object cipherMD = GetSqlCipherMetadata(0, 2, null, 3, 0x01); + AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP"); byte[] plainText = Encoding.Unicode.GetBytes("HelloWorld"); - byte[] cipherText = Utility.EncryptDataUsingAED(plainText, CertFixture.cek, Utility.CColumnEncryptionType.Deterministic); + byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic); - string expectedMessage = "Encryption type '3' specified for the column in the database is either invalid or corrupted. Valid encryption types for algorithm 'AEAD_AES_256_CBC_HMAC_SHA256' are: 'Deterministic', 'Randomized'.\r\nParameter name: encryptionType"; - TargetInvocationException e = Assert.Throws(() => Utility.DecryptWithKey(cipherText, cipherMD, "testsrv")); - Assert.Contains(expectedMessage, e.InnerException.Message); + string expectedMessage = @"Encryption type '3' specified for the column in the database is either invalid or corrupted. Valid encryption types for algorithm 'AEAD_AES_256_CBC_HMAC_SHA256' are: 'Deterministic', 'Randomized'.\s+\(?Parameter (name: )?'?encryptionType('\))?"; + TargetInvocationException e = Assert.Throws(() => DecryptWithKey(cipherText, cipherMD, "testsrv")); + Assert.Matches(expectedMessage, e.InnerException.Message); - e = Assert.Throws(() => Utility.EncryptWithKey(plainText, cipherMD, "testsrv")); - Assert.Contains(expectedMessage, e.InnerException.Message); + e = Assert.Throws(() => EncryptWithKey(plainText, cipherMD, "testsrv")); + Assert.Matches(expectedMessage, e.InnerException.Message); } [Fact] @@ -67,10 +67,10 @@ public void TestInvalidEncryptionType() public void TestInvalidCipherText() { // Attempt to decrypt 53 random bytes - string expectedMessage = "Specified ciphertext has an invalid size of 53 bytes, which is below the minimum 65 bytes required for decryption.\r\nParameter name: cipherText"; - byte[] cipherText = Utility.GenerateRandomBytes(53); // minimum length is 65 - TargetInvocationException e = Assert.Throws(() => Utility.DecryptDataUsingAED(cipherText, CertFixture.cek, Utility.CColumnEncryptionType.Deterministic)); - Assert.Contains(expectedMessage, e.InnerException.Message); + string expectedMessage = @"Specified ciphertext has an invalid size of 53 bytes, which is below the minimum 65 bytes required for decryption.\s+\(?Parameter (name: )?'?cipherText('\))?"; + byte[] cipherText = GenerateRandomBytes(53); // minimum length is 65 + TargetInvocationException e = Assert.Throws(() => DecryptDataUsingAED(cipherText, CertFixture.cek, CColumnEncryptionType.Deterministic)); + Assert.Matches(expectedMessage, e.InnerException.Message); } [Fact] @@ -79,11 +79,11 @@ public void TestInvalidAlgorithmVersion() { string expectedMessage = "The specified ciphertext's encryption algorithm version '40' does not match the expected encryption algorithm version '01'.\r\nParameter name: cipherText"; byte[] plainText = Encoding.Unicode.GetBytes("Hello World"); - byte[] cipherText = Utility.EncryptDataUsingAED(plainText, CertFixture.cek, Utility.CColumnEncryptionType.Deterministic); + byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic); // Put a version number of 0x10 cipherText[0] = 0x40; - TargetInvocationException e = Assert.Throws(() => Utility.DecryptDataUsingAED(cipherText, CertFixture.cek, Utility.CColumnEncryptionType.Deterministic)); - Assert.Contains(expectedMessage, e.InnerException.Message); + TargetInvocationException e = Assert.Throws(() => DecryptDataUsingAED(cipherText, CertFixture.cek, CColumnEncryptionType.Deterministic)); + Assert.Matches(expectedMessage, e.InnerException.Message); } [Fact] @@ -92,14 +92,14 @@ public void TestInvalidAuthenticationTag() { string expectedMessage = "Specified ciphertext has an invalid authentication tag.\r\nParameter name: cipherText"; byte[] plainText = Encoding.Unicode.GetBytes("Hello World"); - byte[] cipherText = Utility.EncryptDataUsingAED(plainText, CertFixture.cek, Utility.CColumnEncryptionType.Deterministic); + byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic); // Zero out 4 bytes of authentication tag for (int i = 0; i < 4; i++) { cipherText[1] = 0x00; } - TargetInvocationException e = Assert.Throws(() => Utility.DecryptDataUsingAED(cipherText, CertFixture.cek, Utility.CColumnEncryptionType.Deterministic)); - Assert.Contains(expectedMessage, e.InnerException.Message); + TargetInvocationException e = Assert.Throws(() => DecryptDataUsingAED(cipherText, CertFixture.cek, CColumnEncryptionType.Deterministic)); + Assert.Matches(expectedMessage, e.InnerException.Message); } [Fact] @@ -107,15 +107,15 @@ public void TestInvalidAuthenticationTag() [PlatformSpecific(TestPlatforms.Windows)] public void TestNullColumnEncryptionAlgorithm() { - string expectedMessage = "Internal error. Encryption algorithm cannot be null. Valid algorithms are: 'AES_256_CBC', 'AEAD_AES_256_CBC_HMAC_SHA256'.\r\nParameter name: encryptionAlgorithm"; - Object cipherMD = Utility.GetSqlCipherMetadata(0, 0, null, 1, 0x01); - Utility.AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP"); + string expectedMessage = "Internal error. Encryption algorithm cannot be null."; + Object cipherMD = GetSqlCipherMetadata(0, 0, null, 1, 0x01); + AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP"); byte[] plainText = Encoding.Unicode.GetBytes("HelloWorld"); - byte[] cipherText = Utility.EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic); + byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic); - TargetInvocationException e = Assert.Throws(() => Utility.DecryptWithKey(cipherText, cipherMD, "testsrv")); + TargetInvocationException e = Assert.Throws(() => DecryptWithKey(cipherText, cipherMD, "testsrv")); Assert.Contains(expectedMessage, e.InnerException.Message); - e = Assert.Throws(() => Utility.EncryptWithKey(plainText, cipherMD, "testsrv")); + e = Assert.Throws(() => EncryptWithKey(plainText, cipherMD, "testsrv")); Assert.Contains(expectedMessage, e.InnerException.Message); } @@ -123,34 +123,39 @@ public void TestNullColumnEncryptionAlgorithm() [PlatformSpecific(TestPlatforms.Windows)] public void TestUnknownEncryptionAlgorithmId() { - string errorMessage = "Encryption algorithm id '3' for the column in the database is either invalid or corrupted. Valid encryption algorithm ids are: '1', '2'.\r\nParameter name: cipherAlgorithmId"; - Object cipherMD = Utility.GetSqlCipherMetadata(0, 3, null, 1, 0x01); - Utility.AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP"); + string errorMessage = @"Encryption algorithm id '3' for the column in the database is either invalid or corrupted. Valid encryption algorithm ids are: '1', '2'.\s+\(?Parameter (name: )?'?cipherAlgorithmId('\))?"; + Object cipherMD = GetSqlCipherMetadata(0, 3, null, 1, 0x01); + AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP"); byte[] plainText = Encoding.Unicode.GetBytes("HelloWorld"); - byte[] cipherText = Utility.EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic); + byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic); - Exception decryptEx = Assert.Throws(() => Utility.DecryptWithKey(plainText, cipherMD, "localhost")); - Assert.Equal(errorMessage, decryptEx.InnerException.Message); + Exception decryptEx = Assert.Throws(() => DecryptWithKey(plainText, cipherMD, "localhost")); + Assert.Matches(errorMessage, decryptEx.InnerException.Message); - Exception encryptEx = Assert.Throws(() => Utility.EncryptWithKey(plainText, cipherMD, "localhost")); - Assert.Equal(errorMessage, encryptEx.InnerException.Message); + Exception encryptEx = Assert.Throws(() => EncryptWithKey(plainText, cipherMD, "localhost")); + Assert.Matches(errorMessage, encryptEx.InnerException.Message); } [Fact] [PlatformSpecific(TestPlatforms.Windows)] public void TestUnknownCustomKeyStoreProvider() { - string errorMessage = "Failed to decrypt a column encryption key. Invalid key store provider name: 'Dummy_Provider'. A key store provider name must denote either a system key store provider or a registered custom key store provider. Valid system key store provider names are: 'MSSQL_CERTIFICATE_STORE', 'MSSQL_CNG_STORE', 'MSSQL_CSP_PROVIDER'. Valid (currently registered) custom key store provider names are: . Please verify key store provider information in column master key definitions in the database, and verify all custom key store providers used in your application are registered properly."; - Object cipherMD = Utility.GetSqlCipherMetadata(0, 1, null, 1, 0x03); - Utility.AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "Dummy_Provider", "RSA_OAEP"); + // Clear out the existing providers (to ensure test reliability) + ClearSqlConnectionProviders(); + + string errorMessage = "Failed to decrypt a column encryption key. Invalid key store provider name: 'Dummy_Provider'. A key store provider name must denote either a system key store provider or a registered custom key store provider."; + Object cipherMD = GetSqlCipherMetadata(0, 1, null, 1, 0x03); + AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "Dummy_Provider", "RSA_OAEP"); byte[] plainText = Encoding.Unicode.GetBytes("HelloWorld"); - byte[] cipherText = Utility.EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic); + byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic); + + Exception decryptEx = Assert.Throws(() => DecryptWithKey(plainText, cipherMD, "localhost")); + Assert.Contains(errorMessage, decryptEx.InnerException.Message); - Exception decryptEx = Assert.Throws(() => Utility.DecryptWithKey(plainText, cipherMD, "localhost")); - Assert.Equal(errorMessage, decryptEx.InnerException.Message); + Exception encryptEx = Assert.Throws(() => EncryptWithKey(plainText, cipherMD, "localhost")); + Assert.Contains(errorMessage, encryptEx.InnerException.Message); - Exception encryptEx = Assert.Throws(() => Utility.EncryptWithKey(plainText, cipherMD, "localhost")); - Assert.Equal(errorMessage, encryptEx.InnerException.Message); + ClearSqlConnectionProviders(); } [Fact] @@ -158,24 +163,24 @@ public void TestUnknownCustomKeyStoreProvider() [PlatformSpecific(TestPlatforms.Windows)] public void TestTceUnknownEncryptionAlgorithm() { - string errorMessage = "Encryption algorithm 'Dummy' for the column in the database is either invalid or corrupted. Valid algorithms are: 'AEAD_AES_256_CBC_HMAC_SHA256', 'AES_256_CBC'."; - Object cipherMD = Utility.GetSqlCipherMetadata(0, 0, "Dummy", 1, 0x01); - Utility.AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP"); + string errorMessage = "Encryption algorithm 'Dummy' for the column in the database is either invalid or corrupted."; + Object cipherMD = GetSqlCipherMetadata(0, 0, "Dummy", 1, 0x01); + AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP"); byte[] plainText = Encoding.Unicode.GetBytes("HelloWorld"); - byte[] cipherText = Utility.EncryptDataUsingAED(plainText, CertFixture.cek, Utility.CColumnEncryptionType.Deterministic); + byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic); - Exception decryptEx = Assert.Throws(() => Utility.DecryptWithKey(cipherText, cipherMD, "localhost")); - Assert.Equal(errorMessage, decryptEx.InnerException.Message); + Exception decryptEx = Assert.Throws(() => DecryptWithKey(cipherText, cipherMD, "localhost")); + Assert.Contains(errorMessage, decryptEx.InnerException.Message); - Exception encryptEx = Assert.Throws(() => Utility.EncryptWithKey(plainText, cipherMD, "localhost")); - Assert.Equal(errorMessage, encryptEx.InnerException.Message); + Exception encryptEx = Assert.Throws(() => EncryptWithKey(plainText, cipherMD, "localhost")); + Assert.Contains(errorMessage, encryptEx.InnerException.Message); } [Fact] [PlatformSpecific(TestPlatforms.Windows)] public void TestExceptionsFromCertStore() { - byte[] corruptedCek = Utility.GenerateInvalidEncryptedCek(CertFixture.cek, Utility.ECEKCorruption.SIGNATURE); + byte[] corruptedCek = GenerateInvalidEncryptedCek(CertFixture.cek, ECEKCorruption.SIGNATURE); // Pass a garbled encrypted CEK string[] errorMessages = { @@ -183,39 +188,40 @@ public void TestExceptionsFromCertStore() string.Format("Specified encrypted column encryption key signature does not match the signature computed with the column master key (certificate) in 'CurrentUser/My/{0}'. The encrypted column encryption key may be corrupt, or the specified path may be incorrect.\r\nParameter name: encryptedColumnEncryptionKey", CertFixture.thumbprint) }; - Object cipherMD = Utility.GetSqlCipherMetadata(0, 1, null, 1, 0x01); - Utility.AddEncryptionKeyToCipherMD(cipherMD, corruptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP"); + Object cipherMD = GetSqlCipherMetadata(0, 1, null, 1, 0x01); + AddEncryptionKeyToCipherMD(cipherMD, corruptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP"); byte[] plainText = Encoding.Unicode.GetBytes("HelloWorld"); - byte[] cipherText = Utility.EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic); + byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic); - Exception decryptEx = Assert.Throws(() => Utility.DecryptWithKey(cipherText, cipherMD, "localhost")); - Assert.Equal(errorMessages[0], decryptEx.InnerException.Message); + Exception decryptEx = Assert.Throws(() => DecryptWithKey(cipherText, cipherMD, "localhost")); + Assert.Matches(errorMessages[0], decryptEx.InnerException.Message); } [Fact] [PlatformSpecific(TestPlatforms.Windows)] public void TestExceptionsFromCustomKeyStore() { - string[] errorMessages = { - string.Format("Failed to decrypt a column encryption key using key store provider: 'DummyProvider'. Verify the properties of the column encryption key and its column master key in your database. The last 10 bytes of the encrypted column encryption key are: '{0}'.\r\nThe method or operation is not implemented.", BitConverter.ToString(CertFixture.encryptedCek, CertFixture.encryptedCek.Length-10, 10)), - string.Format("The method or operation is not implemented.") - }; + string errorMessage = "Failed to decrypt a column encryption key"; + // Clear out the existing providers (to ensure test reliability) + ClearSqlConnectionProviders(); + IDictionary customProviders = new Dictionary(); customProviders.Add("DummyProvider", new DummyKeyStoreProvider()); SqlConnection.RegisterColumnEncryptionKeyStoreProviders(customProviders); - Object cipherMD = Utility.GetSqlCipherMetadata(0, 1, null, 1, 0x01); - Utility.AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "DummyProvider", "DummyAlgo"); + object cipherMD = GetSqlCipherMetadata(0, 1, null, 1, 0x01); + AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "DummyProvider", "DummyAlgo"); byte[] plainText = Encoding.Unicode.GetBytes("HelloWorld"); - byte[] cipherText = Utility.EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic); + byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic); - Exception decryptEx = Assert.Throws(() => Utility.DecryptWithKey(cipherText, cipherMD, "localhost")); - Assert.Equal(errorMessages[0], decryptEx.InnerException.Message); - - Exception encryptEx = Assert.Throws(() => Utility.EncryptWithKey(plainText, cipherMD, "localhost")); - Assert.Equal(errorMessages[0], encryptEx.InnerException.Message); + Exception decryptEx = Assert.Throws(() => DecryptWithKey(cipherText, cipherMD, "localhost")); + Assert.Contains(errorMessage, decryptEx.InnerException.Message); + Exception encryptEx = Assert.Throws(() => EncryptWithKey(cipherText, cipherMD, "localhost")); + Assert.Contains(errorMessage, encryptEx.InnerException.Message); + + ClearSqlConnectionProviders(); } } @@ -231,10 +237,13 @@ public class CertFixture : IDisposable public CertFixture() { - certificate = Utility.CreateCertificate(); + if(certificate == null) + { + certificate = Utility.CreateCertificate(); + } thumbprint = certificate.Thumbprint; certificatePath = string.Format("CurrentUser/My/{0}", thumbprint); - cek = Utility.GenerateRandomBytes(32); + cek = GenerateRandomBytes(32); encryptedCek = provider.EncryptColumnEncryptionKey(certificatePath, "RSA_OAEP", cek); // Disable the cache to avoid false failures. diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/ExceptionsCertStore.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/ExceptionsCertStore.cs index 46706c3dee..7d2691d142 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/ExceptionsCertStore.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/ExceptionsCertStore.cs @@ -76,13 +76,19 @@ public class ExceptionCertFixture : IDisposable public ExceptionCertFixture() { - certificate = Utility.CreateCertificate(); + if(certificate == null) + { + certificate = Utility.CreateCertificate(); + } thumbprint = certificate.Thumbprint; certificatePath = string.Format("CurrentUser/My/{0}", thumbprint); cek = Utility.GenerateRandomBytes(32); encryptedCek = certStoreProvider.EncryptColumnEncryptionKey(certificatePath, "RSA_OAEP", cek); #if NET46 - masterKeyCertificateNPK = Utility.CreateCertificateWithNoPrivateKey(); + if(masterKeyCertificateNPK == null) + { + masterKeyCertificateNPK = Utility.CreateCertificateWithNoPrivateKey(); + } thumbprintNPK = masterKeyCertificateNPK.Thumbprint; masterKeyPathNPK = "CurrentUser/My/" + thumbprintNPK; #endif diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ConversionTests.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ConversionTests.cs index eb55710bcd..202358c829 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ConversionTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ConversionTests.cs @@ -29,7 +29,7 @@ public class ConversionTests : IDisposable private const decimal SmallMoneyMinValue = -214748.3648M; private const int MaxLength = 10000; private int NumberOfRows = DataTestUtility.EnclaveEnabled ? 10 : 100; - private readonly X509Certificate2 certificate; + private static X509Certificate2 certificate; private ColumnMasterKey columnMasterKey; private ColumnEncryptionKey columnEncryptionKey; private SqlColumnEncryptionCertificateStoreProvider certStoreProvider = new SqlColumnEncryptionCertificateStoreProvider(); @@ -55,7 +55,10 @@ public ColumnMetaData(SqlDbType columnType, int columnSize, int precision, int s public ConversionTests() { - certificate = CertificateUtility.CreateCertificate(); + if(certificate == null) + { + certificate = CertificateUtility.CreateCertificate(); + } columnMasterKey = new CspColumnMasterKey(DatabaseHelper.GenerateUniqueName("CMK"), certificate.Thumbprint, certStoreProvider, DataTestUtility.EnclaveEnabled); databaseObjects.Add(columnMasterKey); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs index 88edcae71f..8e0ed06878 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs @@ -13,7 +13,7 @@ public class SQLSetupStrategy : IDisposable { internal const string ColumnEncryptionAlgorithmName = @"AEAD_AES_256_CBC_HMAC_SHA256"; - protected internal readonly X509Certificate2 certificate; + protected static X509Certificate2 certificate; public string keyPath { get; internal set; } public Table ApiTestTable { get; private set; } public Table BulkCopyAETestTable { get; private set; } @@ -25,7 +25,10 @@ public class SQLSetupStrategy : IDisposable public SQLSetupStrategy() { - certificate = CertificateUtility.CreateCertificate(); + if(certificate == null) + { + certificate = CertificateUtility.CreateCertificate(); + } } protected SQLSetupStrategy(string customKeyPath) => keyPath = customKeyPath; diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ExceptionTest/ExceptionTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ExceptionTest/ExceptionTest.cs index 3190c9ed21..71ceaeb33c 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ExceptionTest/ExceptionTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ExceptionTest/ExceptionTest.cs @@ -128,11 +128,25 @@ public static void WarningsBeforeRowsTest() private static bool CheckThatExceptionsAreDistinctButHaveSameData(SqlException e1, SqlException e2) { Assert.True(e1 != e2, "FAILED: verification of exception cloning in subsequent connection attempts"); - Assert.False((e1 == null) || (e2 == null), "FAILED: One of exceptions is null, another is not"); bool equal = (e1.Message == e2.Message) && (e1.HelpLink == e2.HelpLink) && (e1.InnerException == e2.InnerException) - && (e1.Source == e2.Source) && (e1.Data.Count == e2.Data.Count) && (e1.Errors == e2.Errors); + && (e1.Source == e2.Source) && (e1.Data.Count == e2.Data.Count) && (e1.Errors.Count == e2.Errors.Count); + + for (int i = 0; i < e1.Errors.Count; i++) + { + equal = e1.Errors[i].Number == e2.Errors[i].Number + && e1.Errors[i].Message == e2.Errors[i].Message + && e1.Errors[i].LineNumber == e2.Errors[i].LineNumber + && e1.Errors[i].State == e2.Errors[i].State + && e1.Errors[i].Class == e2.Errors[i].Class + && e1.Errors[i].Server == e2.Errors[i].Server + && e1.Errors[i].Procedure == e2.Errors[i].Procedure + && e1.Errors[i].Source == e2.Errors[i].Source; + if (!equal) + break; + } + IDictionaryEnumerator enum1 = e1.Data.GetEnumerator(); IDictionaryEnumerator enum2 = e2.Data.GetEnumerator(); while (equal) @@ -144,7 +158,6 @@ private static bool CheckThatExceptionsAreDistinctButHaveSameData(SqlException e } Assert.True(equal, string.Format("FAILED: exceptions do not contain the same data (besides call stack):\nFirst: {0}\nSecond: {1}\n", e1, e2)); - return true; } diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UdtTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UdtTest.cs index 45b79f4ac2..fd56a4d80b 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UdtTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UdtTest.cs @@ -242,48 +242,63 @@ public void NullTest() p.UdtTypeName = "Utf8String"; p.Value = DBNull.Value; - using (SqlTransaction trans = conn.BeginTransaction()) + bool rerun = false; + do { - com.Transaction = trans; - using (SqlDataReader reader = com.ExecuteReader()) + try { - - Utf8String[] expectedValues = { - new Utf8String("this"), - new Utf8String("is"), - new Utf8String("a"), - new Utf8String("test") - }; - - int currentValue = 0; - do + using (SqlTransaction trans = conn.BeginTransaction()) { - while (reader.Read()) + com.Transaction = trans; + using (SqlDataReader reader = com.ExecuteReader()) { - DataTestUtility.AssertEqualsWithDescription(1, reader.FieldCount, "Unexpected FieldCount."); - if (currentValue < expectedValues.Length) + Utf8String[] expectedValues = { + new Utf8String("this"), + new Utf8String("is"), + new Utf8String("a"), + new Utf8String("test") + }; + + int currentValue = 0; + do { - DataTestUtility.AssertEqualsWithDescription(expectedValues[currentValue], reader.GetValue(0), "Unexpected Value."); - DataTestUtility.AssertEqualsWithDescription(expectedValues[currentValue], reader.GetSqlValue(0), "Unexpected SQL Value."); - } - else - { - DataTestUtility.AssertEqualsWithDescription(DBNull.Value, reader.GetValue(0), "Unexpected Value."); - - Utf8String sqlValue = (Utf8String)reader.GetSqlValue(0); - INullable iface = sqlValue as INullable; - Assert.True(iface != null, "Expected interface cast to return a non-null value."); - Assert.True(iface.IsNull, "Expected interface cast to have IsNull==true."); + while (reader.Read()) + { + DataTestUtility.AssertEqualsWithDescription(1, reader.FieldCount, "Unexpected FieldCount."); + if (currentValue < expectedValues.Length) + { + DataTestUtility.AssertEqualsWithDescription(expectedValues[currentValue], reader.GetValue(0), "Unexpected Value."); + DataTestUtility.AssertEqualsWithDescription(expectedValues[currentValue], reader.GetSqlValue(0), "Unexpected SQL Value."); + } + else + { + DataTestUtility.AssertEqualsWithDescription(DBNull.Value, reader.GetValue(0), "Unexpected Value."); + + Utf8String sqlValue = (Utf8String)reader.GetSqlValue(0); + INullable iface = sqlValue as INullable; + Assert.True(iface != null, "Expected interface cast to return a non-null value."); + Assert.True(iface.IsNull, "Expected interface cast to have IsNull==true."); + } + + currentValue++; + Assert.True(currentValue <= (expectedValues.Length + 1), "Expected to only hit one extra result."); + } } - - currentValue++; - Assert.True(currentValue <= (expectedValues.Length + 1), "Expected to only hit one extra result."); + while (reader.NextResult()); + DataTestUtility.AssertEqualsWithDescription(currentValue, (expectedValues.Length + 1), "Did not hit all expected values."); + rerun = false; } } - while (reader.NextResult()); - DataTestUtility.AssertEqualsWithDescription(currentValue, (expectedValues.Length + 1), "Did not hit all expected values."); + } + catch (SqlException e) + { + if(e.Message.Contains("Rerun the transaction")) + rerun = true; + else + throw e; } } + while(rerun); } } }