diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs index 993bf36806..c6c74be757 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs @@ -440,17 +440,23 @@ internal bool TryReadChars(char[] chars, int charsOffset, int charsCount, out in { charsCopied = 0; int count = 0; + StringBuilder build = new StringBuilder(); + build.AppendLine($"TryReadChars({chars.Length}, {charsOffset}, {charsCount}, out int charsCopied)"); while (charsCopied < charsCount) { // check if the current buffer contains some bytes we need to copy and copy them // in a block + int bytesAvailable = _inBytesRead - _inBytesUsed; int bytesToRead = Math.Min( (charsCount - charsCopied) * 2, - unchecked((_inBytesRead - _inBytesUsed) & (int)0xFFFFFFFE) // if the result is odd take off the 0 to make it even + unchecked(bytesAvailable & (int)0xFFFFFFFE) // if the result is odd take off the 0 to make it even ); if (bytesToRead > 0) { + build.AppendLine($" ({count} bulk) bytesToRead {bytesToRead} = Math.Min(({charsCount} - {charsCopied}) * 2, unchecked({bytesAvailable} & (int)0xFFFFFFFE)"); + build.AppendLine($" ({count} before)(bytesAvailable {bytesAvailable}, _inBytesPacket {_inBytesPacket}, _inBytesRead {_inBytesRead}, _inBytesUsed {_inBytesUsed} "); + Buffer.BlockCopy( _inBuff, _inBytesUsed, @@ -459,15 +465,19 @@ internal bool TryReadChars(char[] chars, int charsOffset, int charsCount, out in bytesToRead ); - if ((_inBytesPacket - bytesToRead) < 0) - { - throw new Exception($"TryReadChars() {count} _inBytesPacket {_inBytesPacket}\n" + - $" bytesToRead = Math.Min(({charsCount} - {charsCopied}) * 2, unchecked(({_inBytesRead} - {_inBytesUsed}) & (int)0xFFFFFFFE)"); - } - - charsCopied = bytesToRead / 2; + charsCopied += bytesToRead / 2; _inBytesUsed += bytesToRead; _inBytesPacket -= bytesToRead; + + bytesAvailable = _inBytesRead - _inBytesUsed; + build.AppendLine($" ({count} after )(bytesAvailable {bytesAvailable}, _inBytesPacket {_inBytesPacket}, _inBytesRead {_inBytesRead}, _inBytesUsed {_inBytesUsed} "); + + if (_inBytesPacket < 0) + { + //throw new Exception($"TryReadChars() {count} _inBytesPacket {_inBytesPacket}\n" + + //$" bytesToRead = Math.Min(({charsCount} - {charsCopied}) * 2, unchecked(({_inBytesRead} - {_inBytesUsed}) & (int)0xFFFFFFFE)"); + throw new Exception("not enough bytes available to read" + Environment.NewLine + build.ToString()); + } } // if the number of chars requested is lower than the number copied then we need @@ -476,6 +486,10 @@ internal bool TryReadChars(char[] chars, int charsOffset, int charsCount, out in if (charsCopied < charsCount) { + bytesAvailable = _inBytesRead - _inBytesUsed; + build.AppendLine($" ({count} char) read 1 char and new packet"); + build.AppendLine($" ({count} before)(bytesAvailable {bytesAvailable}, _inBytesPacket {_inBytesPacket}, _inBytesRead {_inBytesRead}, _inBytesUsed {_inBytesUsed} "); + bool result = TryReadChar(out chars[charsOffset + charsCopied]); if (result) { @@ -485,7 +499,13 @@ internal bool TryReadChars(char[] chars, int charsOffset, int charsCount, out in { return false; } + + bytesAvailable = _inBytesRead - _inBytesUsed; + build.AppendLine($" ({count} after )(bytesAvailable {bytesAvailable}, _inBytesPacket {_inBytesPacket}, _inBytesRead {_inBytesRead}, _inBytesUsed {_inBytesUsed} "); } + + build.AppendLine($" ({count} end) charsCopied {charsCopied}"); + count += 1; } return true; diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVTests.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVTests.cs index 3f2b7a83fa..bb6ad94d70 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVTests.cs @@ -1,124 +1,124 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; -using System.Linq; -using Azure.Identity; -using Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider; -using Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup; -using Xunit; - -namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted -{ - public class AKVTest : IClassFixture - { - private readonly SQLSetupStrategyAzureKeyVault _fixture; - private readonly string _akvTableName; - - public AKVTest(SQLSetupStrategyAzureKeyVault fixture) - { - _fixture = fixture; - _akvTableName = fixture.AKVTestTable.Name; - - // Disable the cache to avoid false failures. - SqlConnection.ColumnEncryptionQueryMetadataCacheEnabled = false; - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE), nameof(DataTestUtility.IsAKVSetupAvailable))] - public void TestEncryptDecryptWithAKV() - { - SqlConnectionStringBuilder builder = new(DataTestUtility.TCPConnectionStringHGSVBS) - { - ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Enabled, - AttestationProtocol = SqlConnectionAttestationProtocol.NotSpecified, - EnclaveAttestationUrl = "" - }; - using SqlConnection sqlConnection = new (builder.ConnectionString); - - sqlConnection.Open(); - Customer customer = new(45, "Microsoft", "Corporation"); - - // Start a transaction and either commit or rollback based on the test variation. - using (SqlTransaction sqlTransaction = sqlConnection.BeginTransaction()) - { - DatabaseHelper.InsertCustomerData(sqlConnection, sqlTransaction, _akvTableName, customer); - sqlTransaction.Commit(); - } - - // Test INPUT parameter on an encrypted parameter - using SqlCommand sqlCommand = new ($"SELECT CustomerId, FirstName, LastName FROM [{_akvTableName}] WHERE FirstName = @firstName", - sqlConnection); - SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft"); - customerFirstParam.Direction = System.Data.ParameterDirection.Input; - customerFirstParam.ForceColumnEncryption = true; - - using SqlDataReader sqlDataReader = sqlCommand.ExecuteReader(); - DatabaseHelper.ValidateResultSet(sqlDataReader); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - [PlatformSpecific(TestPlatforms.Windows)] - public void TestRoundTripWithAKVAndCertStoreProvider() - { - using SQLSetupStrategyCertStoreProvider certStoreFixture = new (); - byte[] plainTextColumnEncryptionKey = ColumnEncryptionKey.GenerateRandomBytes(ColumnEncryptionKey.KeySizeInBytes); - byte[] encryptedColumnEncryptionKeyUsingAKV = _fixture.AkvStoreProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, @"RSA_OAEP", plainTextColumnEncryptionKey); - byte[] columnEncryptionKeyReturnedAKV2Cert = certStoreFixture.CertStoreProvider.DecryptColumnEncryptionKey(certStoreFixture.CspColumnMasterKey.KeyPath, @"RSA_OAEP", encryptedColumnEncryptionKeyUsingAKV); - Assert.True(plainTextColumnEncryptionKey.SequenceEqual(columnEncryptionKeyReturnedAKV2Cert), @"Roundtrip failed"); - - // Try the opposite. - byte[] encryptedColumnEncryptionKeyUsingCert = certStoreFixture.CertStoreProvider.EncryptColumnEncryptionKey(certStoreFixture.CspColumnMasterKey.KeyPath, @"RSA_OAEP", plainTextColumnEncryptionKey); - byte[] columnEncryptionKeyReturnedCert2AKV = _fixture.AkvStoreProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, @"RSA_OAEP", encryptedColumnEncryptionKeyUsingCert); - Assert.True(plainTextColumnEncryptionKey.SequenceEqual(columnEncryptionKeyReturnedCert2AKV), @"Roundtrip failed"); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE), nameof(DataTestUtility.IsAKVSetupAvailable))] - public void TestLocalCekCacheIsScopedToProvider() - { - SqlConnectionStringBuilder builder = new(DataTestUtility.TCPConnectionStringHGSVBS) - { - ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Enabled, - AttestationProtocol = SqlConnectionAttestationProtocol.NotSpecified, - EnclaveAttestationUrl = "" - }; - - using SqlConnection sqlConnection = new(builder.ConnectionString); - - sqlConnection.Open(); - - // Test INPUT parameter on an encrypted parameter - using SqlCommand sqlCommand = new($"SELECT CustomerId, FirstName, LastName FROM [{_akvTableName}] WHERE FirstName = @firstName", - sqlConnection); - SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft"); - customerFirstParam.Direction = System.Data.ParameterDirection.Input; - customerFirstParam.ForceColumnEncryption = true; - - SqlDataReader sqlDataReader = sqlCommand.ExecuteReader(); - sqlDataReader.Close(); - - SqlColumnEncryptionAzureKeyVaultProvider sqlColumnEncryptionAzureKeyVaultProvider = - new(new SqlClientCustomTokenCredential()); - - Dictionary customProvider = new() - { - { SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, sqlColumnEncryptionAzureKeyVaultProvider } - }; - - // execute a query using provider from command-level cache. this will cache the cek in the local cek cache - sqlCommand.RegisterColumnEncryptionKeyStoreProvidersOnCommand(customProvider); - SqlDataReader sqlDataReader2 = sqlCommand.ExecuteReader(); - sqlDataReader2.Close(); - - // global cek cache and local cek cache are populated above - // when using a new per-command provider, it will only use its local cek cache - // the following query should fail due to an empty cek cache and invalid credentials - customProvider[SqlColumnEncryptionAzureKeyVaultProvider.ProviderName] = - new SqlColumnEncryptionAzureKeyVaultProvider(new ClientSecretCredential("tenant", "client", "secret")); - sqlCommand.RegisterColumnEncryptionKeyStoreProvidersOnCommand(customProvider); - Exception ex = Assert.Throws(() => sqlCommand.ExecuteReader()); - Assert.StartsWith("The current credential is not configured to acquire tokens for tenant", ex.InnerException.Message); - } - } -} +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. + +//using System; +//using System.Collections.Generic; +//using System.Linq; +//using Azure.Identity; +//using Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider; +//using Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup; +//using Xunit; + +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted +//{ +// public class AKVTest : IClassFixture +// { +// private readonly SQLSetupStrategyAzureKeyVault _fixture; +// private readonly string _akvTableName; + +// public AKVTest(SQLSetupStrategyAzureKeyVault fixture) +// { +// _fixture = fixture; +// _akvTableName = fixture.AKVTestTable.Name; + +// // Disable the cache to avoid false failures. +// SqlConnection.ColumnEncryptionQueryMetadataCacheEnabled = false; +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public void TestEncryptDecryptWithAKV() +// { +// SqlConnectionStringBuilder builder = new(DataTestUtility.TCPConnectionStringHGSVBS) +// { +// ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Enabled, +// AttestationProtocol = SqlConnectionAttestationProtocol.NotSpecified, +// EnclaveAttestationUrl = "" +// }; +// using SqlConnection sqlConnection = new (builder.ConnectionString); + +// sqlConnection.Open(); +// Customer customer = new(45, "Microsoft", "Corporation"); + +// // Start a transaction and either commit or rollback based on the test variation. +// using (SqlTransaction sqlTransaction = sqlConnection.BeginTransaction()) +// { +// DatabaseHelper.InsertCustomerData(sqlConnection, sqlTransaction, _akvTableName, customer); +// sqlTransaction.Commit(); +// } + +// // Test INPUT parameter on an encrypted parameter +// using SqlCommand sqlCommand = new ($"SELECT CustomerId, FirstName, LastName FROM [{_akvTableName}] WHERE FirstName = @firstName", +// sqlConnection); +// SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft"); +// customerFirstParam.Direction = System.Data.ParameterDirection.Input; +// customerFirstParam.ForceColumnEncryption = true; + +// using SqlDataReader sqlDataReader = sqlCommand.ExecuteReader(); +// DatabaseHelper.ValidateResultSet(sqlDataReader); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// [PlatformSpecific(TestPlatforms.Windows)] +// public void TestRoundTripWithAKVAndCertStoreProvider() +// { +// using SQLSetupStrategyCertStoreProvider certStoreFixture = new (); +// byte[] plainTextColumnEncryptionKey = ColumnEncryptionKey.GenerateRandomBytes(ColumnEncryptionKey.KeySizeInBytes); +// byte[] encryptedColumnEncryptionKeyUsingAKV = _fixture.AkvStoreProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, @"RSA_OAEP", plainTextColumnEncryptionKey); +// byte[] columnEncryptionKeyReturnedAKV2Cert = certStoreFixture.CertStoreProvider.DecryptColumnEncryptionKey(certStoreFixture.CspColumnMasterKey.KeyPath, @"RSA_OAEP", encryptedColumnEncryptionKeyUsingAKV); +// Assert.True(plainTextColumnEncryptionKey.SequenceEqual(columnEncryptionKeyReturnedAKV2Cert), @"Roundtrip failed"); + +// // Try the opposite. +// byte[] encryptedColumnEncryptionKeyUsingCert = certStoreFixture.CertStoreProvider.EncryptColumnEncryptionKey(certStoreFixture.CspColumnMasterKey.KeyPath, @"RSA_OAEP", plainTextColumnEncryptionKey); +// byte[] columnEncryptionKeyReturnedCert2AKV = _fixture.AkvStoreProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, @"RSA_OAEP", encryptedColumnEncryptionKeyUsingCert); +// Assert.True(plainTextColumnEncryptionKey.SequenceEqual(columnEncryptionKeyReturnedCert2AKV), @"Roundtrip failed"); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public void TestLocalCekCacheIsScopedToProvider() +// { +// SqlConnectionStringBuilder builder = new(DataTestUtility.TCPConnectionStringHGSVBS) +// { +// ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Enabled, +// AttestationProtocol = SqlConnectionAttestationProtocol.NotSpecified, +// EnclaveAttestationUrl = "" +// }; + +// using SqlConnection sqlConnection = new(builder.ConnectionString); + +// sqlConnection.Open(); + +// // Test INPUT parameter on an encrypted parameter +// using SqlCommand sqlCommand = new($"SELECT CustomerId, FirstName, LastName FROM [{_akvTableName}] WHERE FirstName = @firstName", +// sqlConnection); +// SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft"); +// customerFirstParam.Direction = System.Data.ParameterDirection.Input; +// customerFirstParam.ForceColumnEncryption = true; + +// SqlDataReader sqlDataReader = sqlCommand.ExecuteReader(); +// sqlDataReader.Close(); + +// SqlColumnEncryptionAzureKeyVaultProvider sqlColumnEncryptionAzureKeyVaultProvider = +// new(new SqlClientCustomTokenCredential()); + +// Dictionary customProvider = new() +// { +// { SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, sqlColumnEncryptionAzureKeyVaultProvider } +// }; + +// // execute a query using provider from command-level cache. this will cache the cek in the local cek cache +// sqlCommand.RegisterColumnEncryptionKeyStoreProvidersOnCommand(customProvider); +// SqlDataReader sqlDataReader2 = sqlCommand.ExecuteReader(); +// sqlDataReader2.Close(); + +// // global cek cache and local cek cache are populated above +// // when using a new per-command provider, it will only use its local cek cache +// // the following query should fail due to an empty cek cache and invalid credentials +// customProvider[SqlColumnEncryptionAzureKeyVaultProvider.ProviderName] = +// new SqlColumnEncryptionAzureKeyVaultProvider(new ClientSecretCredential("tenant", "client", "secret")); +// sqlCommand.RegisterColumnEncryptionKeyStoreProvidersOnCommand(customProvider); +// Exception ex = Assert.Throws(() => sqlCommand.ExecuteReader()); +// Assert.StartsWith("The current credential is not configured to acquire tokens for tenant", ex.InnerException.Message); +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs index a9d69cd6e2..4e7d94c353 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs @@ -1,307 +1,307 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider; -using Azure.Identity; -using Xunit; -using Azure.Security.KeyVault.Keys; -using System.Reflection; -using System; -using System.Linq; -using System.Collections.Generic; -using System.Threading; -using System.Diagnostics.Tracing; -using System.Diagnostics; - -namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted -{ - public static class AKVUnitTests - { - const string EncryptionAlgorithm = "RSA_OAEP"; - public static readonly byte[] s_columnEncryptionKey = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 }; - private const string cekCacheName = "_columnEncryptionKeyCache"; - private const string signatureVerificationResultCacheName = "_columnMasterKeyMetadataSignatureVerificationCache"; - - private static void ValidateAKVTraces(List eventData, Guid threadActivityId) - { - Assert.NotNull(eventData); - Assert.NotEmpty(eventData); - int currentScope = 0; - - // Validate event data captured. - Assert.All(eventData, item => - { - Assert.Equal(DataTestUtility.AKVEventSourceName, item.EventSource.Name); - Assert.Equal(threadActivityId, item.ActivityId); - Assert.Equal(EventLevel.Informational, item.Level); - Assert.NotNull(item.Payload); - Assert.Single(item.Payload); - switch (item.EventId) - { - case 1: // Trace - Assert.Equal("WriteTrace", item.EventName); - Assert.Matches(@"Caller: \w+, Message: (\w\s*)*", item.Payload[0].ToString()); - break; - case 2: // Scope Enter - Assert.Equal("ScopeEnter", item.EventName); - Assert.Equal(EventOpcode.Start, item.Opcode); - Assert.Matches(@"Entered Scope: \w+, Caller: \w*", item.Payload[0].ToString()); - string str = item.Payload[0].ToString(); - int.TryParse(str.Substring(15, str.IndexOf(',') - 1), out currentScope); - break; - case 3: // Scope Exit - Assert.Equal("ScopeExit", item.EventName); - Assert.Equal(EventOpcode.Stop, item.Opcode); - if (currentScope != 0) - { - Assert.Equal(currentScope, (int)item.Payload[0]); - } - break; - default: - Assert.False(true, "Unexpected event occurred: " + item.Message); - break; - } - }); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public static void LegacyAuthenticationCallbackTest() - { - Guid activityId = Trace.CorrelationManager.ActivityId = Guid.NewGuid(); - using DataTestUtility.AKVEventListener AKVListener = new(); - - // SqlClientCustomTokenCredential implements legacy authentication callback to request access token at client-side. - SqlColumnEncryptionAzureKeyVaultProvider akvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(new SqlClientCustomTokenCredential()); - byte[] encryptedCek = akvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, s_columnEncryptionKey); - byte[] decryptedCek = akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, encryptedCek); - - Assert.Equal(s_columnEncryptionKey, decryptedCek); - ValidateAKVTraces(AKVListener.EventData, activityId); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public static void TokenCredentialTest() - { - Guid activityId = Trace.CorrelationManager.ActivityId = Guid.NewGuid(); - using DataTestUtility.AKVEventListener AKVListener = new(); - - ClientSecretCredential clientSecretCredential = new ClientSecretCredential(DataTestUtility.AKVTenantId, DataTestUtility.AKVClientId, DataTestUtility.AKVClientSecret); - SqlColumnEncryptionAzureKeyVaultProvider akvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(clientSecretCredential); - byte[] encryptedCek = akvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, s_columnEncryptionKey); - byte[] decryptedCek = akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, encryptedCek); - - Assert.Equal(s_columnEncryptionKey, decryptedCek); - ValidateAKVTraces(AKVListener.EventData, activityId); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public static void TokenCredentialRotationTest() - { - Guid activityId = Trace.CorrelationManager.ActivityId = Guid.NewGuid(); - using DataTestUtility.AKVEventListener AKVListener = new(); - - // SqlClientCustomTokenCredential implements a legacy authentication callback to request the access token from the client-side. - SqlColumnEncryptionAzureKeyVaultProvider oldAkvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(new SqlClientCustomTokenCredential()); - - ClientSecretCredential clientSecretCredential = new ClientSecretCredential(DataTestUtility.AKVTenantId, DataTestUtility.AKVClientId, DataTestUtility.AKVClientSecret); - SqlColumnEncryptionAzureKeyVaultProvider newAkvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(clientSecretCredential); - - byte[] encryptedCekWithNewProvider = newAkvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, s_columnEncryptionKey); - byte[] decryptedCekWithOldProvider = oldAkvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, encryptedCekWithNewProvider); - Assert.Equal(s_columnEncryptionKey, decryptedCekWithOldProvider); - - byte[] encryptedCekWithOldProvider = oldAkvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, s_columnEncryptionKey); - byte[] decryptedCekWithNewProvider = newAkvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, encryptedCekWithOldProvider); - Assert.Equal(s_columnEncryptionKey, decryptedCekWithNewProvider); - - ValidateAKVTraces(AKVListener.EventData, activityId); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public static void ReturnSpecifiedVersionOfKeyWhenItIsNotTheMostRecentVersion() - { - Uri keyPathUri = new Uri(DataTestUtility.AKVOriginalUrl); - Uri vaultUri = new Uri(keyPathUri.GetLeftPart(UriPartial.Authority)); - - //If key version is not specified then we cannot test. - if (KeyIsVersioned(keyPathUri)) - { - string keyName = keyPathUri.Segments[2]; - string keyVersion = keyPathUri.Segments[3]; - ClientSecretCredential clientSecretCredential = new ClientSecretCredential(DataTestUtility.AKVTenantId, DataTestUtility.AKVClientId, DataTestUtility.AKVClientSecret); - KeyClient keyClient = new KeyClient(vaultUri, clientSecretCredential); - KeyVaultKey currentVersionKey = keyClient.GetKey(keyName); - KeyVaultKey specifiedVersionKey = keyClient.GetKey(keyName, keyVersion); - - //If specified versioned key is the most recent version of the key then we cannot test. - if (!KeyIsLatestVersion(specifiedVersionKey, currentVersionKey)) - { - SqlColumnEncryptionAzureKeyVaultProvider azureKeyProvider = new SqlColumnEncryptionAzureKeyVaultProvider(clientSecretCredential); - // Perform an operation to initialize the internal caches - azureKeyProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVOriginalUrl, EncryptionAlgorithm, s_columnEncryptionKey); - - PropertyInfo keyCryptographerProperty = azureKeyProvider.GetType().GetProperty("KeyCryptographer", BindingFlags.NonPublic | BindingFlags.Instance); - var keyCryptographer = keyCryptographerProperty.GetValue(azureKeyProvider); - MethodInfo getKeyMethod = keyCryptographer.GetType().GetMethod("GetKey", BindingFlags.NonPublic | BindingFlags.Instance); - KeyVaultKey key = (KeyVaultKey)getKeyMethod.Invoke(keyCryptographer, new[] { DataTestUtility.AKVOriginalUrl }); - - Assert.Equal(keyVersion, key.Properties.Version); - } - } - } - - static bool KeyIsVersioned(Uri keyPath) => keyPath.Segments.Length > 3; - static bool KeyIsLatestVersion(KeyVaultKey specifiedVersionKey, KeyVaultKey currentVersionKey) => currentVersionKey.Properties.Version == specifiedVersionKey.Properties.Version; - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public static void ThrowWhenUrlHasLessThanThreeSegments() - { - SqlColumnEncryptionAzureKeyVaultProvider azureKeyProvider = new(new SqlClientCustomTokenCredential()); - string invalidKeyPath = "https://my-key-vault.vault.azure.net/keys"; - Exception ex1 = Assert.Throws(() => azureKeyProvider.EncryptColumnEncryptionKey(invalidKeyPath, EncryptionAlgorithm, s_columnEncryptionKey)); - Assert.Contains($"Invalid url specified: '{invalidKeyPath}'", ex1.Message); - Exception ex2 = Assert.Throws(() => azureKeyProvider.DecryptColumnEncryptionKey(invalidKeyPath, EncryptionAlgorithm, s_columnEncryptionKey)); - Assert.Contains($"Invalid url specified: '{invalidKeyPath}'", ex2.Message); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public static void DecryptedCekIsCachedDuringDecryption() - { - Guid activityId = Trace.CorrelationManager.ActivityId = Guid.NewGuid(); - using DataTestUtility.AKVEventListener AKVListener = new(); - - SqlColumnEncryptionAzureKeyVaultProvider akvProvider = new(new SqlClientCustomTokenCredential()); - byte[] plaintextKey1 = { 1, 2, 3 }; - byte[] plaintextKey2 = { 1, 2, 3 }; - byte[] plaintextKey3 = { 0, 1, 2, 3 }; - byte[] encryptedKey1 = akvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", plaintextKey1); - byte[] encryptedKey2 = akvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", plaintextKey2); - byte[] encryptedKey3 = akvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", plaintextKey3); - - byte[] decryptedKey1 = akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", encryptedKey1); - Assert.Equal(1, GetCacheCount(cekCacheName, akvProvider)); - Assert.Equal(plaintextKey1, decryptedKey1); - - decryptedKey1 = akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", encryptedKey1); - Assert.Equal(1, GetCacheCount(cekCacheName, akvProvider)); - Assert.Equal(plaintextKey1, decryptedKey1); - - byte[] decryptedKey2 = akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", encryptedKey2); - Assert.Equal(2, GetCacheCount(cekCacheName, akvProvider)); - Assert.Equal(plaintextKey2, decryptedKey2); - - byte[] decryptedKey3 = akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", encryptedKey3); - Assert.Equal(3, GetCacheCount(cekCacheName, akvProvider)); - Assert.Equal(plaintextKey3, decryptedKey3); - - ValidateAKVTraces(AKVListener.EventData, activityId); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public static void SignatureVerificationResultIsCachedDuringVerification() - { - Guid activityId = Trace.CorrelationManager.ActivityId = Guid.NewGuid(); - using DataTestUtility.AKVEventListener AKVListener = new(); - - SqlColumnEncryptionAzureKeyVaultProvider akvProvider = new(new SqlClientCustomTokenCredential()); - byte[] signature = akvProvider.SignColumnMasterKeyMetadata(DataTestUtility.AKVUrl, true); - byte[] signature2 = akvProvider.SignColumnMasterKeyMetadata(DataTestUtility.AKVUrl, true); - byte[] signatureWithoutEnclave = akvProvider.SignColumnMasterKeyMetadata(DataTestUtility.AKVUrl, false); - - Assert.True(akvProvider.VerifyColumnMasterKeyMetadata(DataTestUtility.AKVUrl, true, signature)); - Assert.Equal(1, GetCacheCount(signatureVerificationResultCacheName, akvProvider)); - - Assert.True(akvProvider.VerifyColumnMasterKeyMetadata(DataTestUtility.AKVUrl, true, signature)); - Assert.Equal(1, GetCacheCount(signatureVerificationResultCacheName, akvProvider)); - - Assert.True(akvProvider.VerifyColumnMasterKeyMetadata(DataTestUtility.AKVUrl, true, signature2)); - Assert.Equal(1, GetCacheCount(signatureVerificationResultCacheName, akvProvider)); - - Assert.True(akvProvider.VerifyColumnMasterKeyMetadata(DataTestUtility.AKVUrl, false, signatureWithoutEnclave)); - Assert.Equal(2, GetCacheCount(signatureVerificationResultCacheName, akvProvider)); - - ValidateAKVTraces(AKVListener.EventData, activityId); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public static void CekCacheEntryIsEvictedAfterTtlExpires() - { - Guid activityId = Trace.CorrelationManager.ActivityId = Guid.NewGuid(); - using DataTestUtility.AKVEventListener AKVListener = new(); - - SqlColumnEncryptionAzureKeyVaultProvider akvProvider = new(new SqlClientCustomTokenCredential()); - akvProvider.ColumnEncryptionKeyCacheTtl = TimeSpan.FromSeconds(5); - byte[] plaintextKey = { 1, 2, 3 }; - byte[] encryptedKey = akvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", plaintextKey); - - akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", encryptedKey); - Assert.True(CekCacheContainsKey(encryptedKey, akvProvider)); - Assert.Equal(1, GetCacheCount(cekCacheName, akvProvider)); - - Thread.Sleep(TimeSpan.FromSeconds(5)); - Assert.False(CekCacheContainsKey(encryptedKey, akvProvider)); - Assert.Equal(0, GetCacheCount(cekCacheName, akvProvider)); - - ValidateAKVTraces(AKVListener.EventData, activityId); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public static void CekCacheShouldBeDisabledWhenCustomProviderIsRegisteredGlobally() - { - if (SQLSetupStrategyAzureKeyVault.IsAKVProviderRegistered) - { - SqlConnection conn = new(); - FieldInfo globalCacheField = conn.GetType().GetField( - "s_globalCustomColumnEncryptionKeyStoreProviders", BindingFlags.Static | BindingFlags.NonPublic); - IReadOnlyDictionary globalProviders = - globalCacheField.GetValue(conn) as IReadOnlyDictionary; - - SqlColumnEncryptionAzureKeyVaultProvider akvProviderInGlobalCache = - globalProviders["AZURE_KEY_VAULT"] as SqlColumnEncryptionAzureKeyVaultProvider; - byte[] plaintextKey = { 1, 2, 3 }; - byte[] encryptedKey = akvProviderInGlobalCache.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", plaintextKey); - - akvProviderInGlobalCache.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", encryptedKey); - Assert.Equal(0, GetCacheCount(cekCacheName, akvProviderInGlobalCache)); - } - } - - private static int GetCacheCount(string cacheName, SqlColumnEncryptionAzureKeyVaultProvider akvProvider) - { - var cacheInstance = GetCacheInstance(cacheName, akvProvider); - Type cacheType = cacheInstance.GetType(); - PropertyInfo countProperty = cacheType.GetProperty("Count", BindingFlags.Instance | BindingFlags.NonPublic); - int countValue = (int)countProperty.GetValue(cacheInstance); - return countValue; - } - - private static bool CekCacheContainsKey(byte[] encryptedCek, SqlColumnEncryptionAzureKeyVaultProvider akvProvider) - { - var cacheInstance = GetCacheInstance("_columnEncryptionKeyCache", akvProvider); - Type cacheType = cacheInstance.GetType(); - MethodInfo containsMethod = cacheType.GetMethod("Contains", BindingFlags.Instance | BindingFlags.NonPublic); - bool containsResult = (bool)containsMethod.Invoke(cacheInstance, new object[] { ToHexString(encryptedCek) }); - return containsResult; - } - - private static object GetCacheInstance(string cacheName, SqlColumnEncryptionAzureKeyVaultProvider akvProvider) - { - Assembly akvProviderAssembly = typeof(SqlColumnEncryptionAzureKeyVaultProvider).Assembly; - Type akvProviderType = akvProviderAssembly.GetType( - "Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.SqlColumnEncryptionAzureKeyVaultProvider"); - FieldInfo cacheField = akvProviderType.GetField(cacheName, BindingFlags.Instance | BindingFlags.NonPublic); - return cacheField.GetValue(akvProvider); - } - - private static string ToHexString(byte[] source) - { - if (source is null) - { - return null; - } - - return "0x" + BitConverter.ToString(source).Replace("-", ""); - } - } -} +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. + +//using Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider; +//using Azure.Identity; +//using Xunit; +//using Azure.Security.KeyVault.Keys; +//using System.Reflection; +//using System; +//using System.Linq; +//using System.Collections.Generic; +//using System.Threading; +//using System.Diagnostics.Tracing; +//using System.Diagnostics; + +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted +//{ +// public static class AKVUnitTests +// { +// const string EncryptionAlgorithm = "RSA_OAEP"; +// public static readonly byte[] s_columnEncryptionKey = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 }; +// private const string cekCacheName = "_columnEncryptionKeyCache"; +// private const string signatureVerificationResultCacheName = "_columnMasterKeyMetadataSignatureVerificationCache"; + +// private static void ValidateAKVTraces(List eventData, Guid threadActivityId) +// { +// Assert.NotNull(eventData); +// Assert.NotEmpty(eventData); +// int currentScope = 0; + +// // Validate event data captured. +// Assert.All(eventData, item => +// { +// Assert.Equal(DataTestUtility.AKVEventSourceName, item.EventSource.Name); +// Assert.Equal(threadActivityId, item.ActivityId); +// Assert.Equal(EventLevel.Informational, item.Level); +// Assert.NotNull(item.Payload); +// Assert.Single(item.Payload); +// switch (item.EventId) +// { +// case 1: // Trace +// Assert.Equal("WriteTrace", item.EventName); +// Assert.Matches(@"Caller: \w+, Message: (\w\s*)*", item.Payload[0].ToString()); +// break; +// case 2: // Scope Enter +// Assert.Equal("ScopeEnter", item.EventName); +// Assert.Equal(EventOpcode.Start, item.Opcode); +// Assert.Matches(@"Entered Scope: \w+, Caller: \w*", item.Payload[0].ToString()); +// string str = item.Payload[0].ToString(); +// int.TryParse(str.Substring(15, str.IndexOf(',') - 1), out currentScope); +// break; +// case 3: // Scope Exit +// Assert.Equal("ScopeExit", item.EventName); +// Assert.Equal(EventOpcode.Stop, item.Opcode); +// if (currentScope != 0) +// { +// Assert.Equal(currentScope, (int)item.Payload[0]); +// } +// break; +// default: +// Assert.False(true, "Unexpected event occurred: " + item.Message); +// break; +// } +// }); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public static void LegacyAuthenticationCallbackTest() +// { +// Guid activityId = Trace.CorrelationManager.ActivityId = Guid.NewGuid(); +// using DataTestUtility.AKVEventListener AKVListener = new(); + +// // SqlClientCustomTokenCredential implements legacy authentication callback to request access token at client-side. +// SqlColumnEncryptionAzureKeyVaultProvider akvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(new SqlClientCustomTokenCredential()); +// byte[] encryptedCek = akvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, s_columnEncryptionKey); +// byte[] decryptedCek = akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, encryptedCek); + +// Assert.Equal(s_columnEncryptionKey, decryptedCek); +// ValidateAKVTraces(AKVListener.EventData, activityId); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public static void TokenCredentialTest() +// { +// Guid activityId = Trace.CorrelationManager.ActivityId = Guid.NewGuid(); +// using DataTestUtility.AKVEventListener AKVListener = new(); + +// ClientSecretCredential clientSecretCredential = new ClientSecretCredential(DataTestUtility.AKVTenantId, DataTestUtility.AKVClientId, DataTestUtility.AKVClientSecret); +// SqlColumnEncryptionAzureKeyVaultProvider akvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(clientSecretCredential); +// byte[] encryptedCek = akvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, s_columnEncryptionKey); +// byte[] decryptedCek = akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, encryptedCek); + +// Assert.Equal(s_columnEncryptionKey, decryptedCek); +// ValidateAKVTraces(AKVListener.EventData, activityId); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public static void TokenCredentialRotationTest() +// { +// Guid activityId = Trace.CorrelationManager.ActivityId = Guid.NewGuid(); +// using DataTestUtility.AKVEventListener AKVListener = new(); + +// // SqlClientCustomTokenCredential implements a legacy authentication callback to request the access token from the client-side. +// SqlColumnEncryptionAzureKeyVaultProvider oldAkvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(new SqlClientCustomTokenCredential()); + +// ClientSecretCredential clientSecretCredential = new ClientSecretCredential(DataTestUtility.AKVTenantId, DataTestUtility.AKVClientId, DataTestUtility.AKVClientSecret); +// SqlColumnEncryptionAzureKeyVaultProvider newAkvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(clientSecretCredential); + +// byte[] encryptedCekWithNewProvider = newAkvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, s_columnEncryptionKey); +// byte[] decryptedCekWithOldProvider = oldAkvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, encryptedCekWithNewProvider); +// Assert.Equal(s_columnEncryptionKey, decryptedCekWithOldProvider); + +// byte[] encryptedCekWithOldProvider = oldAkvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, s_columnEncryptionKey); +// byte[] decryptedCekWithNewProvider = newAkvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, encryptedCekWithOldProvider); +// Assert.Equal(s_columnEncryptionKey, decryptedCekWithNewProvider); + +// ValidateAKVTraces(AKVListener.EventData, activityId); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public static void ReturnSpecifiedVersionOfKeyWhenItIsNotTheMostRecentVersion() +// { +// Uri keyPathUri = new Uri(DataTestUtility.AKVOriginalUrl); +// Uri vaultUri = new Uri(keyPathUri.GetLeftPart(UriPartial.Authority)); + +// //If key version is not specified then we cannot test. +// if (KeyIsVersioned(keyPathUri)) +// { +// string keyName = keyPathUri.Segments[2]; +// string keyVersion = keyPathUri.Segments[3]; +// ClientSecretCredential clientSecretCredential = new ClientSecretCredential(DataTestUtility.AKVTenantId, DataTestUtility.AKVClientId, DataTestUtility.AKVClientSecret); +// KeyClient keyClient = new KeyClient(vaultUri, clientSecretCredential); +// KeyVaultKey currentVersionKey = keyClient.GetKey(keyName); +// KeyVaultKey specifiedVersionKey = keyClient.GetKey(keyName, keyVersion); + +// //If specified versioned key is the most recent version of the key then we cannot test. +// if (!KeyIsLatestVersion(specifiedVersionKey, currentVersionKey)) +// { +// SqlColumnEncryptionAzureKeyVaultProvider azureKeyProvider = new SqlColumnEncryptionAzureKeyVaultProvider(clientSecretCredential); +// // Perform an operation to initialize the internal caches +// azureKeyProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVOriginalUrl, EncryptionAlgorithm, s_columnEncryptionKey); + +// PropertyInfo keyCryptographerProperty = azureKeyProvider.GetType().GetProperty("KeyCryptographer", BindingFlags.NonPublic | BindingFlags.Instance); +// var keyCryptographer = keyCryptographerProperty.GetValue(azureKeyProvider); +// MethodInfo getKeyMethod = keyCryptographer.GetType().GetMethod("GetKey", BindingFlags.NonPublic | BindingFlags.Instance); +// KeyVaultKey key = (KeyVaultKey)getKeyMethod.Invoke(keyCryptographer, new[] { DataTestUtility.AKVOriginalUrl }); + +// Assert.Equal(keyVersion, key.Properties.Version); +// } +// } +// } + +// static bool KeyIsVersioned(Uri keyPath) => keyPath.Segments.Length > 3; +// static bool KeyIsLatestVersion(KeyVaultKey specifiedVersionKey, KeyVaultKey currentVersionKey) => currentVersionKey.Properties.Version == specifiedVersionKey.Properties.Version; + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public static void ThrowWhenUrlHasLessThanThreeSegments() +// { +// SqlColumnEncryptionAzureKeyVaultProvider azureKeyProvider = new(new SqlClientCustomTokenCredential()); +// string invalidKeyPath = "https://my-key-vault.vault.azure.net/keys"; +// Exception ex1 = Assert.Throws(() => azureKeyProvider.EncryptColumnEncryptionKey(invalidKeyPath, EncryptionAlgorithm, s_columnEncryptionKey)); +// Assert.Contains($"Invalid url specified: '{invalidKeyPath}'", ex1.Message); +// Exception ex2 = Assert.Throws(() => azureKeyProvider.DecryptColumnEncryptionKey(invalidKeyPath, EncryptionAlgorithm, s_columnEncryptionKey)); +// Assert.Contains($"Invalid url specified: '{invalidKeyPath}'", ex2.Message); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public static void DecryptedCekIsCachedDuringDecryption() +// { +// Guid activityId = Trace.CorrelationManager.ActivityId = Guid.NewGuid(); +// using DataTestUtility.AKVEventListener AKVListener = new(); + +// SqlColumnEncryptionAzureKeyVaultProvider akvProvider = new(new SqlClientCustomTokenCredential()); +// byte[] plaintextKey1 = { 1, 2, 3 }; +// byte[] plaintextKey2 = { 1, 2, 3 }; +// byte[] plaintextKey3 = { 0, 1, 2, 3 }; +// byte[] encryptedKey1 = akvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", plaintextKey1); +// byte[] encryptedKey2 = akvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", plaintextKey2); +// byte[] encryptedKey3 = akvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", plaintextKey3); + +// byte[] decryptedKey1 = akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", encryptedKey1); +// Assert.Equal(1, GetCacheCount(cekCacheName, akvProvider)); +// Assert.Equal(plaintextKey1, decryptedKey1); + +// decryptedKey1 = akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", encryptedKey1); +// Assert.Equal(1, GetCacheCount(cekCacheName, akvProvider)); +// Assert.Equal(plaintextKey1, decryptedKey1); + +// byte[] decryptedKey2 = akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", encryptedKey2); +// Assert.Equal(2, GetCacheCount(cekCacheName, akvProvider)); +// Assert.Equal(plaintextKey2, decryptedKey2); + +// byte[] decryptedKey3 = akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", encryptedKey3); +// Assert.Equal(3, GetCacheCount(cekCacheName, akvProvider)); +// Assert.Equal(plaintextKey3, decryptedKey3); + +// ValidateAKVTraces(AKVListener.EventData, activityId); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public static void SignatureVerificationResultIsCachedDuringVerification() +// { +// Guid activityId = Trace.CorrelationManager.ActivityId = Guid.NewGuid(); +// using DataTestUtility.AKVEventListener AKVListener = new(); + +// SqlColumnEncryptionAzureKeyVaultProvider akvProvider = new(new SqlClientCustomTokenCredential()); +// byte[] signature = akvProvider.SignColumnMasterKeyMetadata(DataTestUtility.AKVUrl, true); +// byte[] signature2 = akvProvider.SignColumnMasterKeyMetadata(DataTestUtility.AKVUrl, true); +// byte[] signatureWithoutEnclave = akvProvider.SignColumnMasterKeyMetadata(DataTestUtility.AKVUrl, false); + +// Assert.True(akvProvider.VerifyColumnMasterKeyMetadata(DataTestUtility.AKVUrl, true, signature)); +// Assert.Equal(1, GetCacheCount(signatureVerificationResultCacheName, akvProvider)); + +// Assert.True(akvProvider.VerifyColumnMasterKeyMetadata(DataTestUtility.AKVUrl, true, signature)); +// Assert.Equal(1, GetCacheCount(signatureVerificationResultCacheName, akvProvider)); + +// Assert.True(akvProvider.VerifyColumnMasterKeyMetadata(DataTestUtility.AKVUrl, true, signature2)); +// Assert.Equal(1, GetCacheCount(signatureVerificationResultCacheName, akvProvider)); + +// Assert.True(akvProvider.VerifyColumnMasterKeyMetadata(DataTestUtility.AKVUrl, false, signatureWithoutEnclave)); +// Assert.Equal(2, GetCacheCount(signatureVerificationResultCacheName, akvProvider)); + +// ValidateAKVTraces(AKVListener.EventData, activityId); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public static void CekCacheEntryIsEvictedAfterTtlExpires() +// { +// Guid activityId = Trace.CorrelationManager.ActivityId = Guid.NewGuid(); +// using DataTestUtility.AKVEventListener AKVListener = new(); + +// SqlColumnEncryptionAzureKeyVaultProvider akvProvider = new(new SqlClientCustomTokenCredential()); +// akvProvider.ColumnEncryptionKeyCacheTtl = TimeSpan.FromSeconds(5); +// byte[] plaintextKey = { 1, 2, 3 }; +// byte[] encryptedKey = akvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", plaintextKey); + +// akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", encryptedKey); +// Assert.True(CekCacheContainsKey(encryptedKey, akvProvider)); +// Assert.Equal(1, GetCacheCount(cekCacheName, akvProvider)); + +// Thread.Sleep(TimeSpan.FromSeconds(5)); +// Assert.False(CekCacheContainsKey(encryptedKey, akvProvider)); +// Assert.Equal(0, GetCacheCount(cekCacheName, akvProvider)); + +// ValidateAKVTraces(AKVListener.EventData, activityId); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public static void CekCacheShouldBeDisabledWhenCustomProviderIsRegisteredGlobally() +// { +// if (SQLSetupStrategyAzureKeyVault.IsAKVProviderRegistered) +// { +// SqlConnection conn = new(); +// FieldInfo globalCacheField = conn.GetType().GetField( +// "s_globalCustomColumnEncryptionKeyStoreProviders", BindingFlags.Static | BindingFlags.NonPublic); +// IReadOnlyDictionary globalProviders = +// globalCacheField.GetValue(conn) as IReadOnlyDictionary; + +// SqlColumnEncryptionAzureKeyVaultProvider akvProviderInGlobalCache = +// globalProviders["AZURE_KEY_VAULT"] as SqlColumnEncryptionAzureKeyVaultProvider; +// byte[] plaintextKey = { 1, 2, 3 }; +// byte[] encryptedKey = akvProviderInGlobalCache.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", plaintextKey); + +// akvProviderInGlobalCache.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", encryptedKey); +// Assert.Equal(0, GetCacheCount(cekCacheName, akvProviderInGlobalCache)); +// } +// } + +// private static int GetCacheCount(string cacheName, SqlColumnEncryptionAzureKeyVaultProvider akvProvider) +// { +// var cacheInstance = GetCacheInstance(cacheName, akvProvider); +// Type cacheType = cacheInstance.GetType(); +// PropertyInfo countProperty = cacheType.GetProperty("Count", BindingFlags.Instance | BindingFlags.NonPublic); +// int countValue = (int)countProperty.GetValue(cacheInstance); +// return countValue; +// } + +// private static bool CekCacheContainsKey(byte[] encryptedCek, SqlColumnEncryptionAzureKeyVaultProvider akvProvider) +// { +// var cacheInstance = GetCacheInstance("_columnEncryptionKeyCache", akvProvider); +// Type cacheType = cacheInstance.GetType(); +// MethodInfo containsMethod = cacheType.GetMethod("Contains", BindingFlags.Instance | BindingFlags.NonPublic); +// bool containsResult = (bool)containsMethod.Invoke(cacheInstance, new object[] { ToHexString(encryptedCek) }); +// return containsResult; +// } + +// private static object GetCacheInstance(string cacheName, SqlColumnEncryptionAzureKeyVaultProvider akvProvider) +// { +// Assembly akvProviderAssembly = typeof(SqlColumnEncryptionAzureKeyVaultProvider).Assembly; +// Type akvProviderType = akvProviderAssembly.GetType( +// "Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.SqlColumnEncryptionAzureKeyVaultProvider"); +// FieldInfo cacheField = akvProviderType.GetField(cacheName, BindingFlags.Instance | BindingFlags.NonPublic); +// return cacheField.GetValue(akvProvider); +// } + +// private static string ToHexString(byte[] source) +// { +// if (source is null) +// { +// return null; +// } + +// return "0x" + BitConverter.ToString(source).Replace("-", ""); +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CoreCryptoTests.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CoreCryptoTests.cs index 82456e8636..8d919475b1 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CoreCryptoTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CoreCryptoTests.cs @@ -1,122 +1,122 @@ -using Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Microsoft.Data.SqlClient; -using System.Diagnostics; -using Xunit; - -namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted -{ - public class CoreCryptoTests : IClassFixture - { - // Synapse: Always Encrypted not supported in Azure Synapse. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - [PlatformSpecific(TestPlatforms.Windows)] - public void TestAeadCryptoWithNativeBaseline() - { - // Initialize the reader for resource text file which has the native code generated baseline. - CryptoNativeBaselineReader cryptoNativeBaselineReader = new CryptoNativeBaselineReader(); - - // Read and initialized the crypto vectors from the resource text file. - cryptoNativeBaselineReader.InitializeCryptoVectors(); - - IList cryptoParametersListForTest = cryptoNativeBaselineReader.CryptoVectors; - - Assert.True(cryptoParametersListForTest.Count >= 1, @"Invalid number of AEAD test vectors. Expected at least 1."); - - // For each crypto vector, run the test to compare the output generated through sqlclient's code and the native code. - foreach (CryptoVector cryptoParameter in cryptoParametersListForTest) - { - // For Deterministic encryption, compare the result of encrypting the cell data (or plain text). - if (cryptoParameter.CryptoVectorEncryptionTypeVal == CryptoVectorEncryptionType.Deterministic) - { - TestEncryptionResultUsingAead(cryptoParameter.PlainText, - cryptoParameter.RootKey, - cryptoParameter.CryptoVectorEncryptionTypeVal == CryptoVectorEncryptionType.Deterministic ? CertificateUtility.CColumnEncryptionType.Deterministic : CertificateUtility.CColumnEncryptionType.Randomized, - cryptoParameter.FinalCell); - } - - // For Randomized and Deterministic encryption, try the decryption of final cell value and compare against the native code baseline's plain text. - TestDecryptionResultUsingAead(cryptoParameter.FinalCell, - cryptoParameter.RootKey, - cryptoParameter.CryptoVectorEncryptionTypeVal == CryptoVectorEncryptionType.Deterministic ? CertificateUtility.CColumnEncryptionType.Deterministic : CertificateUtility.CColumnEncryptionType.Randomized, - cryptoParameter.PlainText); - } - } - - // Synapse: Always Encrypted not supported in Azure Synapse. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - [PlatformSpecific(TestPlatforms.Windows)] - public void TestRsaCryptoWithNativeBaseline() - { - // Initialize the reader for resource text file which has the native code generated baseline. - CryptoNativeBaselineReader cryptoNativeBaselineReader = new CryptoNativeBaselineReader(); - - // Read and initialized the crypto vectors from the resource text file. - cryptoNativeBaselineReader.InitializeCryptoVectors(CryptNativeTestVectorType.Rsa); - - IList cryptoParametersListForTest = cryptoNativeBaselineReader.CryptoVectors; - - Assert.True(cryptoParametersListForTest.Count >= 3, @"Invalid number of RSA test vectors. Expected at least 3 (RSA Keypair + PFX + test vectors)."); - Assert.True(cryptoParametersListForTest[0].CryptNativeTestVectorTypeVal == CryptNativeTestVectorType.RsaKeyPair, @"First entry must be an RSA key pair."); - Assert.True(cryptoParametersListForTest[1].CryptNativeTestVectorTypeVal == CryptNativeTestVectorType.RsaPfx, @"2nd entry must be a PFX."); - - byte[] rsaKeyPair = cryptoParametersListForTest[0].RsaKeyPair; - byte[] rsaPfx = cryptoParametersListForTest[1].RsaKeyPair; - - // For each crypto vector, run the test to compare the output generated through sqlclient's code and the native code. - foreach (CryptoVector cryptoParameter in cryptoParametersListForTest) - { - if (cryptoParameter.CryptNativeTestVectorTypeVal == CryptNativeTestVectorType.Rsa) - { - // Verify that we are using the right padding scheme for RSA encryption - byte[] plaintext = CertificateUtility.DecryptRsaDirectly(rsaPfx, cryptoParameter.CiphertextCek, @"Test"); - Assert.True(cryptoParameter.PlaintextCek.SequenceEqual(plaintext), "Plaintext CEK Value does not match with the native code baseline."); - - // Verify that the signed blob is conforming to our envelope (SHA-256, PKCS 1 padding) - bool signatureVerified = CertificateUtility.VerifyRsaSignatureDirectly(cryptoParameter.HashedCek, cryptoParameter.SignedCek, rsaPfx); - Assert.True(signatureVerified, "Plaintext CEK signature scheme does not match with the native code baseline."); - - //// TODO: Programmatically install the in-memory PFX into the right store (based on path) & use the public API - //plaintext = Utility.VerifyRsaSignature(cryptoParameter.PathCek, cryptoParameter.FinalcellCek, rsaPfx); - //CError.Compare(cryptoParameter.PlaintextCek.SequenceEqual(plaintext), "Plaintext CEK Value does not match with the native code baseline (end to end)."); - } - } - } - - - /// - /// Helper function to test the result of encryption using Aead. - /// - /// - /// - /// - /// - private void TestEncryptionResultUsingAead(byte[] plainText, byte[] rootKey, CertificateUtility.CColumnEncryptionType encryptionType, byte[] expectedFinalCellValue) - { - // Encrypt. - byte[] encryptedCellData = CertificateUtility.EncryptDataUsingAED(plainText, rootKey, encryptionType); - Debug.Assert(encryptedCellData != null && encryptedCellData.Length > 0); - - Assert.True(encryptedCellData.SequenceEqual(expectedFinalCellValue), "Final Cell Value does not match with the native code baseline."); - } - - /// - /// Helper function to test the result of decryption using Aead. - /// - /// - /// - /// - /// - private void TestDecryptionResultUsingAead(byte[] cipherText, byte[] rootKey, CertificateUtility.CColumnEncryptionType encryptionType, byte[] expectedPlainText) - { - // Decrypt. - byte[] decryptedCellData = CertificateUtility.DecryptDataUsingAED(cipherText, rootKey, encryptionType); - Debug.Assert(decryptedCellData != null); - - Assert.True(decryptedCellData.SequenceEqual(expectedPlainText), "Decrypted cell data does not match with the native code baseline."); - } - } -} +//using Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup; +//using System; +//using System.Collections.Generic; +//using System.Linq; +//using System.Text; +//using Microsoft.Data.SqlClient; +//using System.Diagnostics; +//using Xunit; + +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted +//{ +// public class CoreCryptoTests : IClassFixture +// { +// // Synapse: Always Encrypted not supported in Azure Synapse. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// [PlatformSpecific(TestPlatforms.Windows)] +// public void TestAeadCryptoWithNativeBaseline() +// { +// // Initialize the reader for resource text file which has the native code generated baseline. +// CryptoNativeBaselineReader cryptoNativeBaselineReader = new CryptoNativeBaselineReader(); + +// // Read and initialized the crypto vectors from the resource text file. +// cryptoNativeBaselineReader.InitializeCryptoVectors(); + +// IList cryptoParametersListForTest = cryptoNativeBaselineReader.CryptoVectors; + +// Assert.True(cryptoParametersListForTest.Count >= 1, @"Invalid number of AEAD test vectors. Expected at least 1."); + +// // For each crypto vector, run the test to compare the output generated through sqlclient's code and the native code. +// foreach (CryptoVector cryptoParameter in cryptoParametersListForTest) +// { +// // For Deterministic encryption, compare the result of encrypting the cell data (or plain text). +// if (cryptoParameter.CryptoVectorEncryptionTypeVal == CryptoVectorEncryptionType.Deterministic) +// { +// TestEncryptionResultUsingAead(cryptoParameter.PlainText, +// cryptoParameter.RootKey, +// cryptoParameter.CryptoVectorEncryptionTypeVal == CryptoVectorEncryptionType.Deterministic ? CertificateUtility.CColumnEncryptionType.Deterministic : CertificateUtility.CColumnEncryptionType.Randomized, +// cryptoParameter.FinalCell); +// } + +// // For Randomized and Deterministic encryption, try the decryption of final cell value and compare against the native code baseline's plain text. +// TestDecryptionResultUsingAead(cryptoParameter.FinalCell, +// cryptoParameter.RootKey, +// cryptoParameter.CryptoVectorEncryptionTypeVal == CryptoVectorEncryptionType.Deterministic ? CertificateUtility.CColumnEncryptionType.Deterministic : CertificateUtility.CColumnEncryptionType.Randomized, +// cryptoParameter.PlainText); +// } +// } + +// // Synapse: Always Encrypted not supported in Azure Synapse. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// [PlatformSpecific(TestPlatforms.Windows)] +// public void TestRsaCryptoWithNativeBaseline() +// { +// // Initialize the reader for resource text file which has the native code generated baseline. +// CryptoNativeBaselineReader cryptoNativeBaselineReader = new CryptoNativeBaselineReader(); + +// // Read and initialized the crypto vectors from the resource text file. +// cryptoNativeBaselineReader.InitializeCryptoVectors(CryptNativeTestVectorType.Rsa); + +// IList cryptoParametersListForTest = cryptoNativeBaselineReader.CryptoVectors; + +// Assert.True(cryptoParametersListForTest.Count >= 3, @"Invalid number of RSA test vectors. Expected at least 3 (RSA Keypair + PFX + test vectors)."); +// Assert.True(cryptoParametersListForTest[0].CryptNativeTestVectorTypeVal == CryptNativeTestVectorType.RsaKeyPair, @"First entry must be an RSA key pair."); +// Assert.True(cryptoParametersListForTest[1].CryptNativeTestVectorTypeVal == CryptNativeTestVectorType.RsaPfx, @"2nd entry must be a PFX."); + +// byte[] rsaKeyPair = cryptoParametersListForTest[0].RsaKeyPair; +// byte[] rsaPfx = cryptoParametersListForTest[1].RsaKeyPair; + +// // For each crypto vector, run the test to compare the output generated through sqlclient's code and the native code. +// foreach (CryptoVector cryptoParameter in cryptoParametersListForTest) +// { +// if (cryptoParameter.CryptNativeTestVectorTypeVal == CryptNativeTestVectorType.Rsa) +// { +// // Verify that we are using the right padding scheme for RSA encryption +// byte[] plaintext = CertificateUtility.DecryptRsaDirectly(rsaPfx, cryptoParameter.CiphertextCek, @"Test"); +// Assert.True(cryptoParameter.PlaintextCek.SequenceEqual(plaintext), "Plaintext CEK Value does not match with the native code baseline."); + +// // Verify that the signed blob is conforming to our envelope (SHA-256, PKCS 1 padding) +// bool signatureVerified = CertificateUtility.VerifyRsaSignatureDirectly(cryptoParameter.HashedCek, cryptoParameter.SignedCek, rsaPfx); +// Assert.True(signatureVerified, "Plaintext CEK signature scheme does not match with the native code baseline."); + +// //// TODO: Programmatically install the in-memory PFX into the right store (based on path) & use the public API +// //plaintext = Utility.VerifyRsaSignature(cryptoParameter.PathCek, cryptoParameter.FinalcellCek, rsaPfx); +// //CError.Compare(cryptoParameter.PlaintextCek.SequenceEqual(plaintext), "Plaintext CEK Value does not match with the native code baseline (end to end)."); +// } +// } +// } + + +// /// +// /// Helper function to test the result of encryption using Aead. +// /// +// /// +// /// +// /// +// /// +// private void TestEncryptionResultUsingAead(byte[] plainText, byte[] rootKey, CertificateUtility.CColumnEncryptionType encryptionType, byte[] expectedFinalCellValue) +// { +// // Encrypt. +// byte[] encryptedCellData = CertificateUtility.EncryptDataUsingAED(plainText, rootKey, encryptionType); +// Debug.Assert(encryptedCellData != null && encryptedCellData.Length > 0); + +// Assert.True(encryptedCellData.SequenceEqual(expectedFinalCellValue), "Final Cell Value does not match with the native code baseline."); +// } + +// /// +// /// Helper function to test the result of decryption using Aead. +// /// +// /// +// /// +// /// +// /// +// private void TestDecryptionResultUsingAead(byte[] cipherText, byte[] rootKey, CertificateUtility.CColumnEncryptionType encryptionType, byte[] expectedPlainText) +// { +// // Decrypt. +// byte[] decryptedCellData = CertificateUtility.DecryptDataUsingAED(cipherText, rootKey, encryptionType); +// Debug.Assert(decryptedCellData != null); + +// Assert.True(decryptedCellData.SequenceEqual(expectedPlainText), "Decrypted cell data does not match with the native code baseline."); +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CspProviderExt.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CspProviderExt.cs index 49071def2e..d27a5fb667 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CspProviderExt.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CspProviderExt.cs @@ -1,230 +1,230 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Linq; -using System.Security.Cryptography.X509Certificates; -using Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup; -using Xunit; -using System.Collections.Generic; -using static Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.CertificateUtilityWin; -#if NET6_0_OR_GREATER -using System.Runtime.Versioning; -#endif - -namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted -{ - /// - /// Always Encrypted public CspProvider Manual tests. - /// TODO: These tests are marked as Windows only for now but should be run for all platforms once the Master Key is accessible to this app from Azure Key Vault. - /// -#if NET6_0_OR_GREATER - [SupportedOSPlatform("windows")] -#endif - [PlatformSpecific(TestPlatforms.Windows)] - public class CspProviderExt - { - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))] - [ClassData(typeof(AEConnectionStringProvider))] - public void TestKeysFromCertificatesCreatedWithMultipleCryptoProviders(string connectionString) - { - const string providersRegistryKeyPath = @"SOFTWARE\Microsoft\Cryptography\Defaults\Provider"; - Microsoft.Win32.RegistryKey defaultCryptoProvidersRegistryKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(providersRegistryKeyPath); - - foreach (string subKeyName in defaultCryptoProvidersRegistryKey.GetSubKeyNames()) - { - // NOTE: RSACryptoServiceProvider.SignData() fails for other providers when testing locally - if (!subKeyName.Contains(@"RSA and AES")) - { - Console.WriteLine(@"INFO: Skipping Certificate creation for {0}.", subKeyName); - continue; - } - string providerName; - string providerType; - string certificateName; - using (Microsoft.Win32.RegistryKey providerKey = defaultCryptoProvidersRegistryKey.OpenSubKey(subKeyName)) - { - // Get Provider Name and its type - providerName = providerKey.Name.Substring(providerKey.Name.LastIndexOf(@"\") + 1); - providerType = providerKey.GetValue(@"Type").ToString(); - - // Create a certificate from that provider - certificateName = string.Format(@"AETest - {0}", providerName); - } - - var extensions = new List>(); - CertificateOption certOption = new() - { - Subject = certificateName, - KeyExportPolicy = "Exportable", - CertificateStoreLocation = $"{StoreLocation.CurrentUser}\\My", - Provider = providerName, - Type = providerType, - }; - CreateCertificate(certOption); - SQLSetupStrategyCspExt sqlSetupStrategyCsp = null; - try - { - if (false == CertificateUtilityWin.CertificateExists(certificateName, StoreLocation.CurrentUser)) - { - Console.WriteLine(@"INFO: Certificate creation for provider {0} failed so skipping it.", providerName); - continue; - } - - X509Certificate2 cert = CertificateUtilityWin.GetCertificate(certificateName, StoreLocation.CurrentUser); - string cspPath = CertificateUtilityWin.GetCspPathFromCertificate(cert); - - if (string.IsNullOrEmpty(cspPath)) - { - Console.WriteLine(@"INFO: Certificate provider {0} is not a csp provider so skipping it.", providerName); - continue; - } - - Console.WriteLine("CSP path is {0}", cspPath); - - sqlSetupStrategyCsp = new SQLSetupStrategyCspExt(cspPath); - string tableName = sqlSetupStrategyCsp.CspProviderTable.Name; - - using SqlConnection sqlConn = new(connectionString); - sqlConn.Open(); - - Table.DeleteData(tableName, sqlConn); - - // insert 1 row data - Customer customer = new Customer(45, "Microsoft", "Corporation"); - - DatabaseHelper.InsertCustomerData(sqlConn, null, tableName, customer); - - // Test INPUT parameter on an encrypted parameter - using SqlCommand sqlCommand = new(@$"SELECT CustomerId, FirstName, LastName FROM [{tableName}] WHERE FirstName = @firstName", - sqlConn, null, SqlCommandColumnEncryptionSetting.Enabled); - SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft"); - customerFirstParam.Direction = System.Data.ParameterDirection.Input; - - using SqlDataReader sqlDataReader = sqlCommand.ExecuteReader(); - ValidateResultSet(sqlDataReader); - Console.WriteLine(@"INFO: Successfully validated using a certificate using provider:{0}", providerName); - } - finally - { - CertificateUtilityWin.RemoveCertificate(certificateName, StoreLocation.CurrentUser); - // clean up database resources - sqlSetupStrategyCsp?.Dispose(); - } - - } - } - - // [Fact(Skip="Run this in non-parallel mode")] or [ConditionalFact()] - [Fact(Skip = "Failing in TCE")] - public void TestRoundTripWithCSPAndCertStoreProvider() - { - const string providerName = "Microsoft Enhanced RSA and AES Cryptographic Provider"; - string providerType = "24"; - - string certificateName = string.Format(@"AETest - {0}", providerName); - CertificateOption options = new() - { - Subject = certificateName, - CertificateStoreLocation = StoreLocation.CurrentUser.ToString(), - Provider = providerName, - Type = providerType - }; - CertificateUtilityWin.CreateCertificate(options); - try - { - X509Certificate2 cert = CertificateUtilityWin.GetCertificate(certificateName, StoreLocation.CurrentUser); - string cspPath = CertificateUtilityWin.GetCspPathFromCertificate(cert); - string certificatePath = String.Concat(@"CurrentUser/my/", cert.Thumbprint); - - SqlColumnEncryptionCertificateStoreProvider certProvider = new SqlColumnEncryptionCertificateStoreProvider(); - SqlColumnEncryptionCspProvider cspProvider = new SqlColumnEncryptionCspProvider(); - byte[] columnEncryptionKey = DatabaseHelper.GenerateRandomBytes(32); - - byte[] encryptedColumnEncryptionKeyUsingCert = certProvider.EncryptColumnEncryptionKey(certificatePath, @"RSA_OAEP", columnEncryptionKey); - byte[] columnEncryptionKeyReturnedCert2CSP = cspProvider.DecryptColumnEncryptionKey(cspPath, @"RSA_OAEP", encryptedColumnEncryptionKeyUsingCert); - Assert.True(columnEncryptionKey.SequenceEqual(columnEncryptionKeyReturnedCert2CSP)); - - byte[] encryptedColumnEncryptionKeyUsingCSP = cspProvider.EncryptColumnEncryptionKey(cspPath, @"RSA_OAEP", columnEncryptionKey); - byte[] columnEncryptionKeyReturnedCSP2Cert = certProvider.DecryptColumnEncryptionKey(certificatePath, @"RSA_OAEP", encryptedColumnEncryptionKeyUsingCSP); - Assert.True(columnEncryptionKey.SequenceEqual(columnEncryptionKeyReturnedCSP2Cert)); - - } - finally - { - CertificateUtilityWin.RemoveCertificate(certificateName, StoreLocation.CurrentUser); - } - } - - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))] - [ClassData(typeof(AEConnectionStringProvider))] - public void TestEncryptDecryptWithCSP(string connectionString) - { - string providerName = @"Microsoft Enhanced RSA and AES Cryptographic Provider"; - string keyIdentifier = DataTestUtility.GetUniqueNameForSqlServer("CSP"); - - try - { - CertificateUtilityWin.RSAPersistKeyInCsp(providerName, keyIdentifier); - string cspPath = String.Concat(providerName, @"/", keyIdentifier); - - SQLSetupStrategyCspExt sqlSetupStrategyCsp = new SQLSetupStrategyCspExt(cspPath); - string tableName = sqlSetupStrategyCsp.CspProviderTable.Name; - - try - { - using SqlConnection sqlConn = new(connectionString); - sqlConn.Open(); - - Table.DeleteData(tableName, sqlConn); - - // insert 1 row data - Customer customer = new Customer(45, "Microsoft", "Corporation"); - - DatabaseHelper.InsertCustomerData(sqlConn, null, tableName, customer); - - // Test INPUT parameter on an encrypted parameter - using SqlCommand sqlCommand = new(@$"SELECT CustomerId, FirstName, LastName FROM [{tableName}] WHERE FirstName = @firstName", - sqlConn, null, SqlCommandColumnEncryptionSetting.Enabled); - SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft"); - Console.WriteLine(@"Exception: {0}"); - customerFirstParam.Direction = System.Data.ParameterDirection.Input; - - using SqlDataReader sqlDataReader = sqlCommand.ExecuteReader(); - ValidateResultSet(sqlDataReader); - } - finally - { - // clean up database resources - sqlSetupStrategyCsp.Dispose(); - } - } - finally - { - CertificateUtilityWin.RSADeleteKeyInCsp(providerName, keyIdentifier); - } - } - - /// - /// Validates that the results are the ones expected. - /// - /// - private void ValidateResultSet(SqlDataReader sqlDataReader) - { - int rowsFound = 0; - while (sqlDataReader.Read()) - { - if (sqlDataReader.FieldCount == 3) - { - Assert.Equal(45, sqlDataReader.GetInt32(0)); - Assert.Equal(@"Microsoft", sqlDataReader.GetString(1)); - Assert.Equal(@"Corporation", sqlDataReader.GetString(2)); - } - rowsFound++; - } - - Assert.Equal(1, rowsFound); - } - } -} +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. + +//using System; +//using System.Linq; +//using System.Security.Cryptography.X509Certificates; +//using Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup; +//using Xunit; +//using System.Collections.Generic; +//using static Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.CertificateUtilityWin; +//#if NET6_0_OR_GREATER +//using System.Runtime.Versioning; +//#endif + +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted +//{ +// /// +// /// Always Encrypted public CspProvider Manual tests. +// /// TODO: These tests are marked as Windows only for now but should be run for all platforms once the Master Key is accessible to this app from Azure Key Vault. +// /// +//#if NET6_0_OR_GREATER +// [SupportedOSPlatform("windows")] +//#endif +// [PlatformSpecific(TestPlatforms.Windows)] +// public class CspProviderExt +// { +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))] +// [ClassData(typeof(AEConnectionStringProvider))] +// public void TestKeysFromCertificatesCreatedWithMultipleCryptoProviders(string connectionString) +// { +// const string providersRegistryKeyPath = @"SOFTWARE\Microsoft\Cryptography\Defaults\Provider"; +// Microsoft.Win32.RegistryKey defaultCryptoProvidersRegistryKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(providersRegistryKeyPath); + +// foreach (string subKeyName in defaultCryptoProvidersRegistryKey.GetSubKeyNames()) +// { +// // NOTE: RSACryptoServiceProvider.SignData() fails for other providers when testing locally +// if (!subKeyName.Contains(@"RSA and AES")) +// { +// Console.WriteLine(@"INFO: Skipping Certificate creation for {0}.", subKeyName); +// continue; +// } +// string providerName; +// string providerType; +// string certificateName; +// using (Microsoft.Win32.RegistryKey providerKey = defaultCryptoProvidersRegistryKey.OpenSubKey(subKeyName)) +// { +// // Get Provider Name and its type +// providerName = providerKey.Name.Substring(providerKey.Name.LastIndexOf(@"\") + 1); +// providerType = providerKey.GetValue(@"Type").ToString(); + +// // Create a certificate from that provider +// certificateName = string.Format(@"AETest - {0}", providerName); +// } + +// var extensions = new List>(); +// CertificateOption certOption = new() +// { +// Subject = certificateName, +// KeyExportPolicy = "Exportable", +// CertificateStoreLocation = $"{StoreLocation.CurrentUser}\\My", +// Provider = providerName, +// Type = providerType, +// }; +// CreateCertificate(certOption); +// SQLSetupStrategyCspExt sqlSetupStrategyCsp = null; +// try +// { +// if (false == CertificateUtilityWin.CertificateExists(certificateName, StoreLocation.CurrentUser)) +// { +// Console.WriteLine(@"INFO: Certificate creation for provider {0} failed so skipping it.", providerName); +// continue; +// } + +// X509Certificate2 cert = CertificateUtilityWin.GetCertificate(certificateName, StoreLocation.CurrentUser); +// string cspPath = CertificateUtilityWin.GetCspPathFromCertificate(cert); + +// if (string.IsNullOrEmpty(cspPath)) +// { +// Console.WriteLine(@"INFO: Certificate provider {0} is not a csp provider so skipping it.", providerName); +// continue; +// } + +// Console.WriteLine("CSP path is {0}", cspPath); + +// sqlSetupStrategyCsp = new SQLSetupStrategyCspExt(cspPath); +// string tableName = sqlSetupStrategyCsp.CspProviderTable.Name; + +// using SqlConnection sqlConn = new(connectionString); +// sqlConn.Open(); + +// Table.DeleteData(tableName, sqlConn); + +// // insert 1 row data +// Customer customer = new Customer(45, "Microsoft", "Corporation"); + +// DatabaseHelper.InsertCustomerData(sqlConn, null, tableName, customer); + +// // Test INPUT parameter on an encrypted parameter +// using SqlCommand sqlCommand = new(@$"SELECT CustomerId, FirstName, LastName FROM [{tableName}] WHERE FirstName = @firstName", +// sqlConn, null, SqlCommandColumnEncryptionSetting.Enabled); +// SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft"); +// customerFirstParam.Direction = System.Data.ParameterDirection.Input; + +// using SqlDataReader sqlDataReader = sqlCommand.ExecuteReader(); +// ValidateResultSet(sqlDataReader); +// Console.WriteLine(@"INFO: Successfully validated using a certificate using provider:{0}", providerName); +// } +// finally +// { +// CertificateUtilityWin.RemoveCertificate(certificateName, StoreLocation.CurrentUser); +// // clean up database resources +// sqlSetupStrategyCsp?.Dispose(); +// } + +// } +// } + +// // [Fact(Skip="Run this in non-parallel mode")] or [ConditionalFact()] +// [Fact(Skip = "Failing in TCE")] +// public void TestRoundTripWithCSPAndCertStoreProvider() +// { +// const string providerName = "Microsoft Enhanced RSA and AES Cryptographic Provider"; +// string providerType = "24"; + +// string certificateName = string.Format(@"AETest - {0}", providerName); +// CertificateOption options = new() +// { +// Subject = certificateName, +// CertificateStoreLocation = StoreLocation.CurrentUser.ToString(), +// Provider = providerName, +// Type = providerType +// }; +// CertificateUtilityWin.CreateCertificate(options); +// try +// { +// X509Certificate2 cert = CertificateUtilityWin.GetCertificate(certificateName, StoreLocation.CurrentUser); +// string cspPath = CertificateUtilityWin.GetCspPathFromCertificate(cert); +// string certificatePath = String.Concat(@"CurrentUser/my/", cert.Thumbprint); + +// SqlColumnEncryptionCertificateStoreProvider certProvider = new SqlColumnEncryptionCertificateStoreProvider(); +// SqlColumnEncryptionCspProvider cspProvider = new SqlColumnEncryptionCspProvider(); +// byte[] columnEncryptionKey = DatabaseHelper.GenerateRandomBytes(32); + +// byte[] encryptedColumnEncryptionKeyUsingCert = certProvider.EncryptColumnEncryptionKey(certificatePath, @"RSA_OAEP", columnEncryptionKey); +// byte[] columnEncryptionKeyReturnedCert2CSP = cspProvider.DecryptColumnEncryptionKey(cspPath, @"RSA_OAEP", encryptedColumnEncryptionKeyUsingCert); +// Assert.True(columnEncryptionKey.SequenceEqual(columnEncryptionKeyReturnedCert2CSP)); + +// byte[] encryptedColumnEncryptionKeyUsingCSP = cspProvider.EncryptColumnEncryptionKey(cspPath, @"RSA_OAEP", columnEncryptionKey); +// byte[] columnEncryptionKeyReturnedCSP2Cert = certProvider.DecryptColumnEncryptionKey(certificatePath, @"RSA_OAEP", encryptedColumnEncryptionKeyUsingCSP); +// Assert.True(columnEncryptionKey.SequenceEqual(columnEncryptionKeyReturnedCSP2Cert)); + +// } +// finally +// { +// CertificateUtilityWin.RemoveCertificate(certificateName, StoreLocation.CurrentUser); +// } +// } + +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))] +// [ClassData(typeof(AEConnectionStringProvider))] +// public void TestEncryptDecryptWithCSP(string connectionString) +// { +// string providerName = @"Microsoft Enhanced RSA and AES Cryptographic Provider"; +// string keyIdentifier = DataTestUtility.GetUniqueNameForSqlServer("CSP"); + +// try +// { +// CertificateUtilityWin.RSAPersistKeyInCsp(providerName, keyIdentifier); +// string cspPath = String.Concat(providerName, @"/", keyIdentifier); + +// SQLSetupStrategyCspExt sqlSetupStrategyCsp = new SQLSetupStrategyCspExt(cspPath); +// string tableName = sqlSetupStrategyCsp.CspProviderTable.Name; + +// try +// { +// using SqlConnection sqlConn = new(connectionString); +// sqlConn.Open(); + +// Table.DeleteData(tableName, sqlConn); + +// // insert 1 row data +// Customer customer = new Customer(45, "Microsoft", "Corporation"); + +// DatabaseHelper.InsertCustomerData(sqlConn, null, tableName, customer); + +// // Test INPUT parameter on an encrypted parameter +// using SqlCommand sqlCommand = new(@$"SELECT CustomerId, FirstName, LastName FROM [{tableName}] WHERE FirstName = @firstName", +// sqlConn, null, SqlCommandColumnEncryptionSetting.Enabled); +// SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft"); +// Console.WriteLine(@"Exception: {0}"); +// customerFirstParam.Direction = System.Data.ParameterDirection.Input; + +// using SqlDataReader sqlDataReader = sqlCommand.ExecuteReader(); +// ValidateResultSet(sqlDataReader); +// } +// finally +// { +// // clean up database resources +// sqlSetupStrategyCsp.Dispose(); +// } +// } +// finally +// { +// CertificateUtilityWin.RSADeleteKeyInCsp(providerName, keyIdentifier); +// } +// } + +// /// +// /// Validates that the results are the ones expected. +// /// +// /// +// private void ValidateResultSet(SqlDataReader sqlDataReader) +// { +// int rowsFound = 0; +// while (sqlDataReader.Read()) +// { +// if (sqlDataReader.FieldCount == 3) +// { +// Assert.Equal(45, sqlDataReader.GetInt32(0)); +// Assert.Equal(@"Microsoft", sqlDataReader.GetString(1)); +// Assert.Equal(@"Corporation", sqlDataReader.GetString(2)); +// } +// rowsFound++; +// } + +// Assert.Equal(1, rowsFound); +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/EnclaveAzureDatabaseTests.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/EnclaveAzureDatabaseTests.cs index c372e39bca..571aa45c12 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/EnclaveAzureDatabaseTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/EnclaveAzureDatabaseTests.cs @@ -1,176 +1,176 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information.using System; - -using System; -using System.Collections.Generic; -using System.Security.Cryptography; -using System.Threading.Tasks; -using Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider; -using Microsoft.Data.SqlClient.ManualTesting.Tests; -using Xunit; -using Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup; - -namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted -{ - // This test class is for internal use only - public sealed class EnclaveAzureDatabaseTests : IDisposable - { - private ColumnMasterKey akvColumnMasterKey; - private ColumnEncryptionKey akvColumnEncryptionKey; - private SqlColumnEncryptionAzureKeyVaultProvider sqlColumnEncryptionAzureKeyVaultProvider; - private List databaseObjects = new List(); - private List connStrings = new List(); - - public EnclaveAzureDatabaseTests() - { - if (DataTestUtility.IsEnclaveAzureDatabaseSetup()) - { - sqlColumnEncryptionAzureKeyVaultProvider = new SqlColumnEncryptionAzureKeyVaultProvider(new SqlClientCustomTokenCredential()); - if (!SQLSetupStrategyAzureKeyVault.IsAKVProviderRegistered) - { - SQLSetupStrategyAzureKeyVault.RegisterGlobalProviders(sqlColumnEncryptionAzureKeyVaultProvider); - } - - akvColumnMasterKey = new AkvColumnMasterKey(DatabaseHelper.GenerateUniqueName("AKVCMK"), akvUrl: DataTestUtility.AKVUrl, sqlColumnEncryptionAzureKeyVaultProvider, DataTestUtility.EnclaveEnabled); - databaseObjects.Add(akvColumnMasterKey); - - akvColumnEncryptionKey = new ColumnEncryptionKey(DatabaseHelper.GenerateUniqueName("AKVCEK"), - akvColumnMasterKey, - sqlColumnEncryptionAzureKeyVaultProvider); - databaseObjects.Add(akvColumnEncryptionKey); - - SqlConnectionStringBuilder connString1 = new SqlConnectionStringBuilder(DataTestUtility.EnclaveAzureDatabaseConnString); - connString1.InitialCatalog = "testdb001"; - - SqlConnectionStringBuilder connString2 = new SqlConnectionStringBuilder(DataTestUtility.EnclaveAzureDatabaseConnString); - connString2.InitialCatalog = "testdb002"; - - connStrings.Add(connString1.ToString()); - connStrings.Add(connString2.ToString()); - - foreach (string connString in connStrings) - { - using (SqlConnection connection = new SqlConnection(connString)) - { - connection.Open(); - databaseObjects.ForEach(o => o.Create(connection)); - } - } - } - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsEnclaveAzureDatabaseSetup))] - public void ConnectToAzureDatabaseWithEnclave() - { - string tableName = DatabaseHelper.GenerateUniqueName("AzureTable"); - - foreach (string connString in connStrings) - { - using (SqlConnection sqlConnection = new SqlConnection(connString)) - { - sqlConnection.Open(); - - Customer customer = new Customer(1, @"Microsoft", @"Corporation"); - - try - { - CreateTable(sqlConnection, akvColumnEncryptionKey.Name, tableName); - InsertData(sqlConnection, tableName, customer); - VerifyData(sqlConnection, tableName, customer); - } - finally - { - DropTableIfExists(sqlConnection, tableName); - } - } - } - } - - private void CreateTable(SqlConnection sqlConnection, string cekName, string tableName) - { - string ColumnEncryptionAlgorithmName = @"AEAD_AES_256_CBC_HMAC_SHA_256"; - string sql = - $@"CREATE TABLE [dbo].[{tableName}] - ( - [CustomerId] [int] ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [{cekName}], ENCRYPTION_TYPE = RANDOMIZED, ALGORITHM = '{ColumnEncryptionAlgorithmName}'), - [FirstName] [nvarchar](50) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [{cekName}], ENCRYPTION_TYPE = RANDOMIZED, ALGORITHM = '{ColumnEncryptionAlgorithmName}'), - [LastName] [nvarchar](50) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [{cekName}], ENCRYPTION_TYPE = RANDOMIZED, ALGORITHM = '{ColumnEncryptionAlgorithmName}') - )"; - using (SqlCommand command = sqlConnection.CreateCommand()) - { - command.CommandText = sql; - command.ExecuteNonQuery(); - } - } - - private void InsertData(SqlConnection sqlConnection, string tableName, Customer newCustomer) - { - string insertSql = $"INSERT INTO [{tableName}] (CustomerId, FirstName, LastName) VALUES (@CustomerId, @FirstName, @LastName);"; - using (SqlTransaction sqlTransaction = sqlConnection.BeginTransaction()) - using (SqlCommand sqlCommand = new SqlCommand(insertSql, - connection: sqlConnection, transaction: sqlTransaction, - columnEncryptionSetting: SqlCommandColumnEncryptionSetting.Enabled)) - { - sqlCommand.Parameters.AddWithValue(@"CustomerId", newCustomer.Id); - sqlCommand.Parameters.AddWithValue(@"FirstName", newCustomer.FirstName); - sqlCommand.Parameters.AddWithValue(@"LastName", newCustomer.LastName); - sqlCommand.ExecuteNonQuery(); - sqlTransaction.Commit(); - } - } - - private void VerifyData(SqlConnection sqlConnection, string tableName, Customer customer) - { - // Test INPUT parameter on an encrypted parameter - using (SqlCommand sqlCommand = new SqlCommand($"SELECT CustomerId, FirstName, LastName FROM [{tableName}] WHERE FirstName = @firstName", - sqlConnection)) - { - SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft"); - customerFirstParam.Direction = System.Data.ParameterDirection.Input; - customerFirstParam.ForceColumnEncryption = true; - using (SqlDataReader sqlDataReader = sqlCommand.ExecuteReader()) - { - ValidateResultSet(sqlDataReader); - } - } - } - - private void ValidateResultSet(SqlDataReader sqlDataReader) - { - Assert.True(sqlDataReader.HasRows, "We didn't find any rows."); - while (sqlDataReader.Read()) - { - Assert.True(sqlDataReader.GetInt32(0) == 1, "Employee Id didn't match"); - Assert.True(sqlDataReader.GetString(1) == @"Microsoft", "Employee FirstName didn't match."); - Assert.True(sqlDataReader.GetString(2) == @"Corporation", "Employee LastName didn't match."); - } - } - - private void DropTableIfExists(SqlConnection sqlConnection, string tableName) - { - string cmdText = $@"IF EXISTS (select * from sys.objects where name = '{tableName}') BEGIN DROP TABLE [{tableName}] END"; - using (SqlCommand command = sqlConnection.CreateCommand()) - { - command.CommandText = cmdText; - command.ExecuteNonQuery(); - } - } - - public void Dispose() - { - if (DataTestUtility.IsEnclaveAzureDatabaseSetup()) - { - databaseObjects.Reverse(); - foreach (string connStr in connStrings) - { - using (SqlConnection sqlConnection = new SqlConnection(connStr)) - { - sqlConnection.Open(); - databaseObjects.ForEach(o => o.Drop(sqlConnection)); - } - } - } - } - } -} +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information.using System; + +//using System; +//using System.Collections.Generic; +//using System.Security.Cryptography; +//using System.Threading.Tasks; +//using Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider; +//using Microsoft.Data.SqlClient.ManualTesting.Tests; +//using Xunit; +//using Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup; + +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted +//{ +// // This test class is for internal use only +// public sealed class EnclaveAzureDatabaseTests : IDisposable +// { +// private ColumnMasterKey akvColumnMasterKey; +// private ColumnEncryptionKey akvColumnEncryptionKey; +// private SqlColumnEncryptionAzureKeyVaultProvider sqlColumnEncryptionAzureKeyVaultProvider; +// private List databaseObjects = new List(); +// private List connStrings = new List(); + +// public EnclaveAzureDatabaseTests() +// { +// if (DataTestUtility.IsEnclaveAzureDatabaseSetup()) +// { +// sqlColumnEncryptionAzureKeyVaultProvider = new SqlColumnEncryptionAzureKeyVaultProvider(new SqlClientCustomTokenCredential()); +// if (!SQLSetupStrategyAzureKeyVault.IsAKVProviderRegistered) +// { +// SQLSetupStrategyAzureKeyVault.RegisterGlobalProviders(sqlColumnEncryptionAzureKeyVaultProvider); +// } + +// akvColumnMasterKey = new AkvColumnMasterKey(DatabaseHelper.GenerateUniqueName("AKVCMK"), akvUrl: DataTestUtility.AKVUrl, sqlColumnEncryptionAzureKeyVaultProvider, DataTestUtility.EnclaveEnabled); +// databaseObjects.Add(akvColumnMasterKey); + +// akvColumnEncryptionKey = new ColumnEncryptionKey(DatabaseHelper.GenerateUniqueName("AKVCEK"), +// akvColumnMasterKey, +// sqlColumnEncryptionAzureKeyVaultProvider); +// databaseObjects.Add(akvColumnEncryptionKey); + +// SqlConnectionStringBuilder connString1 = new SqlConnectionStringBuilder(DataTestUtility.EnclaveAzureDatabaseConnString); +// connString1.InitialCatalog = "testdb001"; + +// SqlConnectionStringBuilder connString2 = new SqlConnectionStringBuilder(DataTestUtility.EnclaveAzureDatabaseConnString); +// connString2.InitialCatalog = "testdb002"; + +// connStrings.Add(connString1.ToString()); +// connStrings.Add(connString2.ToString()); + +// foreach (string connString in connStrings) +// { +// using (SqlConnection connection = new SqlConnection(connString)) +// { +// connection.Open(); +// databaseObjects.ForEach(o => o.Create(connection)); +// } +// } +// } +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsEnclaveAzureDatabaseSetup))] +// public void ConnectToAzureDatabaseWithEnclave() +// { +// string tableName = DatabaseHelper.GenerateUniqueName("AzureTable"); + +// foreach (string connString in connStrings) +// { +// using (SqlConnection sqlConnection = new SqlConnection(connString)) +// { +// sqlConnection.Open(); + +// Customer customer = new Customer(1, @"Microsoft", @"Corporation"); + +// try +// { +// CreateTable(sqlConnection, akvColumnEncryptionKey.Name, tableName); +// InsertData(sqlConnection, tableName, customer); +// VerifyData(sqlConnection, tableName, customer); +// } +// finally +// { +// DropTableIfExists(sqlConnection, tableName); +// } +// } +// } +// } + +// private void CreateTable(SqlConnection sqlConnection, string cekName, string tableName) +// { +// string ColumnEncryptionAlgorithmName = @"AEAD_AES_256_CBC_HMAC_SHA_256"; +// string sql = +// $@"CREATE TABLE [dbo].[{tableName}] +// ( +// [CustomerId] [int] ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [{cekName}], ENCRYPTION_TYPE = RANDOMIZED, ALGORITHM = '{ColumnEncryptionAlgorithmName}'), +// [FirstName] [nvarchar](50) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [{cekName}], ENCRYPTION_TYPE = RANDOMIZED, ALGORITHM = '{ColumnEncryptionAlgorithmName}'), +// [LastName] [nvarchar](50) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [{cekName}], ENCRYPTION_TYPE = RANDOMIZED, ALGORITHM = '{ColumnEncryptionAlgorithmName}') +// )"; +// using (SqlCommand command = sqlConnection.CreateCommand()) +// { +// command.CommandText = sql; +// command.ExecuteNonQuery(); +// } +// } + +// private void InsertData(SqlConnection sqlConnection, string tableName, Customer newCustomer) +// { +// string insertSql = $"INSERT INTO [{tableName}] (CustomerId, FirstName, LastName) VALUES (@CustomerId, @FirstName, @LastName);"; +// using (SqlTransaction sqlTransaction = sqlConnection.BeginTransaction()) +// using (SqlCommand sqlCommand = new SqlCommand(insertSql, +// connection: sqlConnection, transaction: sqlTransaction, +// columnEncryptionSetting: SqlCommandColumnEncryptionSetting.Enabled)) +// { +// sqlCommand.Parameters.AddWithValue(@"CustomerId", newCustomer.Id); +// sqlCommand.Parameters.AddWithValue(@"FirstName", newCustomer.FirstName); +// sqlCommand.Parameters.AddWithValue(@"LastName", newCustomer.LastName); +// sqlCommand.ExecuteNonQuery(); +// sqlTransaction.Commit(); +// } +// } + +// private void VerifyData(SqlConnection sqlConnection, string tableName, Customer customer) +// { +// // Test INPUT parameter on an encrypted parameter +// using (SqlCommand sqlCommand = new SqlCommand($"SELECT CustomerId, FirstName, LastName FROM [{tableName}] WHERE FirstName = @firstName", +// sqlConnection)) +// { +// SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft"); +// customerFirstParam.Direction = System.Data.ParameterDirection.Input; +// customerFirstParam.ForceColumnEncryption = true; +// using (SqlDataReader sqlDataReader = sqlCommand.ExecuteReader()) +// { +// ValidateResultSet(sqlDataReader); +// } +// } +// } + +// private void ValidateResultSet(SqlDataReader sqlDataReader) +// { +// Assert.True(sqlDataReader.HasRows, "We didn't find any rows."); +// while (sqlDataReader.Read()) +// { +// Assert.True(sqlDataReader.GetInt32(0) == 1, "Employee Id didn't match"); +// Assert.True(sqlDataReader.GetString(1) == @"Microsoft", "Employee FirstName didn't match."); +// Assert.True(sqlDataReader.GetString(2) == @"Corporation", "Employee LastName didn't match."); +// } +// } + +// private void DropTableIfExists(SqlConnection sqlConnection, string tableName) +// { +// string cmdText = $@"IF EXISTS (select * from sys.objects where name = '{tableName}') BEGIN DROP TABLE [{tableName}] END"; +// using (SqlCommand command = sqlConnection.CreateCommand()) +// { +// command.CommandText = cmdText; +// command.ExecuteNonQuery(); +// } +// } + +// public void Dispose() +// { +// if (DataTestUtility.IsEnclaveAzureDatabaseSetup()) +// { +// databaseObjects.Reverse(); +// foreach (string connStr in connStrings) +// { +// using (SqlConnection sqlConnection = new SqlConnection(connStr)) +// { +// sqlConnection.Open(); +// databaseObjects.ForEach(o => o.Drop(sqlConnection)); +// } +// } +// } +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/End2EndSmokeTests.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/End2EndSmokeTests.cs index 4862a41d03..25bc7aff6a 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/End2EndSmokeTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/End2EndSmokeTests.cs @@ -1,316 +1,316 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Threading.Tasks; -using System.Collections; -using System.Collections.Generic; -using Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup; -using Xunit; - -namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted -{ - public sealed class End2EndSmokeTests : IClassFixture, IDisposable - { - private SQLSetupStrategy fixture; - - private readonly string tableName; - - public End2EndSmokeTests(PlatformSpecificTestContext context) - { - fixture = context.Fixture; - tableName = fixture.End2EndSmokeTable.Name; - } - - // tests - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))] - [ClassData(typeof(TestSelectOnEncryptedNonEncryptedColumnsData))] - public void TestSelectOnEncryptedNonEncryptedColumns(string connString, string selectQuery, int totalColumnsInSelect, string[] types) - { - Assert.False(string.IsNullOrWhiteSpace(selectQuery), "FAILED: select query should not be null or empty."); - Assert.True(totalColumnsInSelect <= 3, "FAILED: totalColumnsInSelect should <= 3."); - - using (SqlConnection sqlConn = new SqlConnection(connString)) - { - sqlConn.Open(); - - Table.DeleteData(tableName, sqlConn); - - // insert 1 row data - Customer customer = new Customer(45, "Microsoft", "Corporation"); - - DatabaseHelper.InsertCustomerData(sqlConn, null, tableName, customer); - - using (SqlCommand sqlCommand = new SqlCommand(string.Format(selectQuery, tableName), - sqlConn, null, SqlCommandColumnEncryptionSetting.Enabled)) - { - using (SqlDataReader sqlDataReader = sqlCommand.ExecuteReader()) - { - Assert.True(sqlDataReader.HasRows, "FAILED: Select statement did not return any rows."); - - while (sqlDataReader.Read()) - { - DatabaseHelper.CompareResults(sqlDataReader, types, totalColumnsInSelect); - } - } - } - } - } - - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))] - [ClassData(typeof(TestSelectOnEncryptedNonEncryptedColumnsWithEncryptedParametersData))] - public void TestSelectOnEncryptedNonEncryptedColumnsWithEncryptedParameters(string connString, - bool sync, - string selectQuery, - int totalColumnsInSelect, - string[] types, - int numberofParameters, - object[] values) - { - Assert.False(string.IsNullOrWhiteSpace(selectQuery), "FAILED: select query should not be null or empty."); - Assert.True(totalColumnsInSelect <= 3, "FAILED: totalColumnsInSelect should <= 3."); - - using (SqlConnection sqlConn = new SqlConnection(connString)) - { - sqlConn.Open(); - - Table.DeleteData(tableName, sqlConn); - - // insert 1 row data - Customer customer = new Customer(45, "Microsoft", "Corporation"); - - DatabaseHelper.InsertCustomerData(sqlConn, null, tableName, customer); - - using (SqlCommand sqlCommand = new SqlCommand(string.Format(selectQuery, tableName), - sqlConn, null, SqlCommandColumnEncryptionSetting.Enabled)) - { - Assert.True(numberofParameters <= 3, "FAILED: No:of parameters should be <= 3."); - - int parameterIndex = 0; - - while (parameterIndex < numberofParameters * 3) - { - object value = null; - string parameterName = (string)values[parameterIndex]; - Assert.False(string.IsNullOrWhiteSpace(parameterName), "FAILED: parameterName should not be null or empty."); - - switch ((string)values[parameterIndex + 1]) - { - case "string": - value = (string)values[parameterIndex + 2]; - break; - - case "int": - value = (int)values[parameterIndex + 2]; - break; - - default: - Assert.True(false, "FAILED: No other data type is supported."); - break; - } - - sqlCommand.Parameters.AddWithValue(parameterName, value); - parameterIndex += 3; - } - - if (sync) - { - DatabaseHelper.VerifyResultsSync(sqlCommand, types, totalColumnsInSelect); - } - else - { - Task verifyTask = DatabaseHelper.VerifyResultsAsync(sqlCommand, types, totalColumnsInSelect); - verifyTask.Wait(); - } - } - } - } - - public void Dispose() - { - foreach (string connStrAE in DataTestUtility.AEConnStringsSetup) - { - using (SqlConnection sqlConnection = new SqlConnection(connStrAE)) - { - sqlConnection.Open(); - Table.DeleteData(fixture.End2EndSmokeTable.Name, sqlConnection); - } - } - } - } - - public class TestSelectOnEncryptedNonEncryptedColumnsData : IEnumerable - { - public IEnumerator GetEnumerator() - { - foreach (string connStrAE in DataTestUtility.AEConnStrings) - { - yield return new object[] { connStrAE, @"select CustomerId, FirstName, LastName from [{0}] ", 3, new string[] { @"int", @"string", @"string" } }; - yield return new object[] { connStrAE, @"select CustomerId, FirstName from [{0}] ", 2, new string[] { @"int", @"string" } }; - yield return new object[] { connStrAE, @"select LastName from [{0}] ", 1, new string[] { @"string" }}; - } - } - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } - - public class TestSelectOnEncryptedNonEncryptedColumnsWithEncryptedParametersData : IEnumerable - { - public IEnumerator GetEnumerator() - { - foreach (string connStrAE in DataTestUtility.AEConnStrings) - { - yield return new object[] { - connStrAE, - true, /*sync*/ - @"select CustomerId, FirstName, LastName from [{0}] where CustomerId = @CustomerId and FirstName = @FirstName", - 3, /*total number of columns in select statement*/ - new string[] { @"int", /*unencrypted datatype of first column in select statement*/ - @"string", /*unencrypted datatype of second column in select statement*/ - @"string" /*datatype of third column in select statement*/}, - 2, /*no:of input parameters*/ - new object[] { @"CustomerId", /*input parameter name*/ - @"int", /*input parameter data type*/ - 45, /*input parameter value*/ - @"FirstName", /*input parameter name*/ - @"string", /*input parameter data type*/ - @"Microsoft" /*input parameter value*/} - }; - - yield return new object[] { - connStrAE, - true, /*sync*/ - @"select CustomerId, FirstName, LastName from [{0}] where CustomerId = @CustomerId", - 3, /*total number of columns in select statement*/ - new string[] { @"int", /*unencrypted datatype of first column in select statement*/ - @"string", /*unencrypted datatype of second column in select statement*/ - @"string" /*datatype of third column in select statement*/}, - 1, /*no:of input parameters*/ - new object[] { @"CustomerId", /*input parameter name*/ - @"int", /*input parameter data type*/ - 45, /*input parameter value*/} - }; - - yield return new object[] { - connStrAE, - true, /*sync*/ - @"select CustomerId, FirstName, LastName from [{0}] where FirstName = @FirstName", - 3, /*total number of columns in select statement*/ - new string[] { @"int", /*unencrypted datatype of first column in select statement*/ - @"string", /*unencrypted datatype of second column in select statement*/ - @"string" /*datatype of third column in select statement*/}, - 1, /*no:of input parameters*/ - new object[] { @"FirstName", /*input parameter name*/ - @"string", /*input parameter data type*/ - @"Microsoft" /*input parameter value*/} - }; - - yield return new object[] { - connStrAE, - true, /*sync*/ - @"select CustomerId, FirstName, LastName from [{0}] where LastName = @LastName", - 3, /*total number of columns in select statement*/ - new string[] { @"int", /*unencrypted datatype of first column in select statement*/ - @"string", /*unencrypted datatype of second column in select statement*/ - @"string" /*datatype of third column in select statement*/}, - 1, /*no:of input parameters*/ - new object[] { @"LastName", /*input parameter name*/ - @"string", /*input parameter data type*/ - @"Corporation" /*input parameter value*/} - }; - - yield return new object[] { - connStrAE, - true, /*sync*/ - @"select CustomerId, FirstName from [{0}] where CustomerId = @CustomerId and FirstName = @FirstName", - 2, /*total number of columns in select statement*/ - new string[] { @"int", /*unencrypted datatype of first column in select statement*/ - @"string", /*unencrypted datatype of second column in select statement*/}, - 2, /*no:of input parameters*/ - new object[] { @"CustomerId", /*input parameter name*/ - @"int", /*input parameter data type*/ - 45, /*input parameter value*/ - @"FirstName", /*input parameter name*/ - @"string", /*input parameter data type*/ - @"Microsoft" /*input parameter value*/} - }; - - yield return new object[] { - connStrAE, - false, /*sync*/ - @"select CustomerId, FirstName, LastName from [{0}] where CustomerId = @CustomerId and FirstName = @FirstName", - 3, /*total number of columns in select statement*/ - new string[] { @"int", /*unencrypted datatype of first column in select statement*/ - @"string", /*unencrypted datatype of second column in select statement*/ - @"string" /*datatype of third column in select statement*/}, - 2, /*no:of input parameters*/ - new object[] { @"CustomerId", /*input parameter name*/ - @"int", /*input parameter data type*/ - 45, /*input parameter value*/ - @"FirstName", /*input parameter name*/ - @"string", /*input parameter data type*/ - @"Microsoft" /*input parameter value*/} - }; - - yield return new object[] { - connStrAE, - false, /*sync*/ - @"select CustomerId, FirstName, LastName from [{0}] where CustomerId = @CustomerId", - 3, /*total number of columns in select statement*/ - new string[] { @"int", /*unencrypted datatype of first column in select statement*/ - @"string", /*unencrypted datatype of second column in select statement*/ - @"string" /*datatype of third column in select statement*/}, - 1, /*no:of input parameters*/ - new object[] { @"CustomerId", /*input parameter name*/ - @"int", /*input parameter data type*/ - 45, /*input parameter value*/} - }; - - yield return new object[] { - connStrAE, - false, /*sync*/ - @"select CustomerId, FirstName, LastName from [{0}] where FirstName = @FirstName", - 3, /*total number of columns in select statement*/ - new string[] { @"int", /*unencrypted datatype of first column in select statement*/ - @"string", /*unencrypted datatype of second column in select statement*/ - @"string" /*datatype of third column in select statement*/}, - 1, /*no:of input parameters*/ - new object[] { @"FirstName", /*input parameter name*/ - @"string", /*input parameter data type*/ - @"Microsoft" /*input parameter value*/} - }; - - yield return new object[] { - connStrAE, - false, /*sync*/ - @"select CustomerId, FirstName, LastName from [{0}] where LastName = @LastName", - 3, /*total number of columns in select statement*/ - new string[] { @"int", /*unencrypted datatype of first column in select statement*/ - @"string", /*unencrypted datatype of second column in select statement*/ - @"string" /*datatype of third column in select statement*/}, - 1, /*no:of input parameters*/ - new object[] { @"LastName", /*input parameter name*/ - @"string", /*input parameter data type*/ - @"Corporation" /*input parameter value*/} - }; - - yield return new object[] { - connStrAE, - false, /*sync*/ - @"select CustomerId, FirstName from [{0}] where CustomerId = @CustomerId and FirstName = @FirstName", - 2, /*total number of columns in select statement*/ - new string[] { @"int", /*unencrypted datatype of first column in select statement*/ - @"string", /*unencrypted datatype of second column in select statement*/}, - 2, /*no:of input parameters*/ - new object[] { @"CustomerId", /*input parameter name*/ - @"int", /*input parameter data type*/ - 45, /*input parameter value*/ - @"FirstName", /*input parameter name*/ - @"string", /*input parameter data type*/ - @"Microsoft" /*input parameter value*/} - }; - } - } - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } -} +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. + +//using System; +//using System.Threading.Tasks; +//using System.Collections; +//using System.Collections.Generic; +//using Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup; +//using Xunit; + +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted +//{ +// public sealed class End2EndSmokeTests : IClassFixture, IDisposable +// { +// private SQLSetupStrategy fixture; + +// private readonly string tableName; + +// public End2EndSmokeTests(PlatformSpecificTestContext context) +// { +// fixture = context.Fixture; +// tableName = fixture.End2EndSmokeTable.Name; +// } + +// // tests +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))] +// [ClassData(typeof(TestSelectOnEncryptedNonEncryptedColumnsData))] +// public void TestSelectOnEncryptedNonEncryptedColumns(string connString, string selectQuery, int totalColumnsInSelect, string[] types) +// { +// Assert.False(string.IsNullOrWhiteSpace(selectQuery), "FAILED: select query should not be null or empty."); +// Assert.True(totalColumnsInSelect <= 3, "FAILED: totalColumnsInSelect should <= 3."); + +// using (SqlConnection sqlConn = new SqlConnection(connString)) +// { +// sqlConn.Open(); + +// Table.DeleteData(tableName, sqlConn); + +// // insert 1 row data +// Customer customer = new Customer(45, "Microsoft", "Corporation"); + +// DatabaseHelper.InsertCustomerData(sqlConn, null, tableName, customer); + +// using (SqlCommand sqlCommand = new SqlCommand(string.Format(selectQuery, tableName), +// sqlConn, null, SqlCommandColumnEncryptionSetting.Enabled)) +// { +// using (SqlDataReader sqlDataReader = sqlCommand.ExecuteReader()) +// { +// Assert.True(sqlDataReader.HasRows, "FAILED: Select statement did not return any rows."); + +// while (sqlDataReader.Read()) +// { +// DatabaseHelper.CompareResults(sqlDataReader, types, totalColumnsInSelect); +// } +// } +// } +// } +// } + +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))] +// [ClassData(typeof(TestSelectOnEncryptedNonEncryptedColumnsWithEncryptedParametersData))] +// public void TestSelectOnEncryptedNonEncryptedColumnsWithEncryptedParameters(string connString, +// bool sync, +// string selectQuery, +// int totalColumnsInSelect, +// string[] types, +// int numberofParameters, +// object[] values) +// { +// Assert.False(string.IsNullOrWhiteSpace(selectQuery), "FAILED: select query should not be null or empty."); +// Assert.True(totalColumnsInSelect <= 3, "FAILED: totalColumnsInSelect should <= 3."); + +// using (SqlConnection sqlConn = new SqlConnection(connString)) +// { +// sqlConn.Open(); + +// Table.DeleteData(tableName, sqlConn); + +// // insert 1 row data +// Customer customer = new Customer(45, "Microsoft", "Corporation"); + +// DatabaseHelper.InsertCustomerData(sqlConn, null, tableName, customer); + +// using (SqlCommand sqlCommand = new SqlCommand(string.Format(selectQuery, tableName), +// sqlConn, null, SqlCommandColumnEncryptionSetting.Enabled)) +// { +// Assert.True(numberofParameters <= 3, "FAILED: No:of parameters should be <= 3."); + +// int parameterIndex = 0; + +// while (parameterIndex < numberofParameters * 3) +// { +// object value = null; +// string parameterName = (string)values[parameterIndex]; +// Assert.False(string.IsNullOrWhiteSpace(parameterName), "FAILED: parameterName should not be null or empty."); + +// switch ((string)values[parameterIndex + 1]) +// { +// case "string": +// value = (string)values[parameterIndex + 2]; +// break; + +// case "int": +// value = (int)values[parameterIndex + 2]; +// break; + +// default: +// Assert.True(false, "FAILED: No other data type is supported."); +// break; +// } + +// sqlCommand.Parameters.AddWithValue(parameterName, value); +// parameterIndex += 3; +// } + +// if (sync) +// { +// DatabaseHelper.VerifyResultsSync(sqlCommand, types, totalColumnsInSelect); +// } +// else +// { +// Task verifyTask = DatabaseHelper.VerifyResultsAsync(sqlCommand, types, totalColumnsInSelect); +// verifyTask.Wait(); +// } +// } +// } +// } + +// public void Dispose() +// { +// foreach (string connStrAE in DataTestUtility.AEConnStringsSetup) +// { +// using (SqlConnection sqlConnection = new SqlConnection(connStrAE)) +// { +// sqlConnection.Open(); +// Table.DeleteData(fixture.End2EndSmokeTable.Name, sqlConnection); +// } +// } +// } +// } + +// public class TestSelectOnEncryptedNonEncryptedColumnsData : IEnumerable +// { +// public IEnumerator GetEnumerator() +// { +// foreach (string connStrAE in DataTestUtility.AEConnStrings) +// { +// yield return new object[] { connStrAE, @"select CustomerId, FirstName, LastName from [{0}] ", 3, new string[] { @"int", @"string", @"string" } }; +// yield return new object[] { connStrAE, @"select CustomerId, FirstName from [{0}] ", 2, new string[] { @"int", @"string" } }; +// yield return new object[] { connStrAE, @"select LastName from [{0}] ", 1, new string[] { @"string" }}; +// } +// } +// IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); +// } + +// public class TestSelectOnEncryptedNonEncryptedColumnsWithEncryptedParametersData : IEnumerable +// { +// public IEnumerator GetEnumerator() +// { +// foreach (string connStrAE in DataTestUtility.AEConnStrings) +// { +// yield return new object[] { +// connStrAE, +// true, /*sync*/ +// @"select CustomerId, FirstName, LastName from [{0}] where CustomerId = @CustomerId and FirstName = @FirstName", +// 3, /*total number of columns in select statement*/ +// new string[] { @"int", /*unencrypted datatype of first column in select statement*/ +// @"string", /*unencrypted datatype of second column in select statement*/ +// @"string" /*datatype of third column in select statement*/}, +// 2, /*no:of input parameters*/ +// new object[] { @"CustomerId", /*input parameter name*/ +// @"int", /*input parameter data type*/ +// 45, /*input parameter value*/ +// @"FirstName", /*input parameter name*/ +// @"string", /*input parameter data type*/ +// @"Microsoft" /*input parameter value*/} +// }; + +// yield return new object[] { +// connStrAE, +// true, /*sync*/ +// @"select CustomerId, FirstName, LastName from [{0}] where CustomerId = @CustomerId", +// 3, /*total number of columns in select statement*/ +// new string[] { @"int", /*unencrypted datatype of first column in select statement*/ +// @"string", /*unencrypted datatype of second column in select statement*/ +// @"string" /*datatype of third column in select statement*/}, +// 1, /*no:of input parameters*/ +// new object[] { @"CustomerId", /*input parameter name*/ +// @"int", /*input parameter data type*/ +// 45, /*input parameter value*/} +// }; + +// yield return new object[] { +// connStrAE, +// true, /*sync*/ +// @"select CustomerId, FirstName, LastName from [{0}] where FirstName = @FirstName", +// 3, /*total number of columns in select statement*/ +// new string[] { @"int", /*unencrypted datatype of first column in select statement*/ +// @"string", /*unencrypted datatype of second column in select statement*/ +// @"string" /*datatype of third column in select statement*/}, +// 1, /*no:of input parameters*/ +// new object[] { @"FirstName", /*input parameter name*/ +// @"string", /*input parameter data type*/ +// @"Microsoft" /*input parameter value*/} +// }; + +// yield return new object[] { +// connStrAE, +// true, /*sync*/ +// @"select CustomerId, FirstName, LastName from [{0}] where LastName = @LastName", +// 3, /*total number of columns in select statement*/ +// new string[] { @"int", /*unencrypted datatype of first column in select statement*/ +// @"string", /*unencrypted datatype of second column in select statement*/ +// @"string" /*datatype of third column in select statement*/}, +// 1, /*no:of input parameters*/ +// new object[] { @"LastName", /*input parameter name*/ +// @"string", /*input parameter data type*/ +// @"Corporation" /*input parameter value*/} +// }; + +// yield return new object[] { +// connStrAE, +// true, /*sync*/ +// @"select CustomerId, FirstName from [{0}] where CustomerId = @CustomerId and FirstName = @FirstName", +// 2, /*total number of columns in select statement*/ +// new string[] { @"int", /*unencrypted datatype of first column in select statement*/ +// @"string", /*unencrypted datatype of second column in select statement*/}, +// 2, /*no:of input parameters*/ +// new object[] { @"CustomerId", /*input parameter name*/ +// @"int", /*input parameter data type*/ +// 45, /*input parameter value*/ +// @"FirstName", /*input parameter name*/ +// @"string", /*input parameter data type*/ +// @"Microsoft" /*input parameter value*/} +// }; + +// yield return new object[] { +// connStrAE, +// false, /*sync*/ +// @"select CustomerId, FirstName, LastName from [{0}] where CustomerId = @CustomerId and FirstName = @FirstName", +// 3, /*total number of columns in select statement*/ +// new string[] { @"int", /*unencrypted datatype of first column in select statement*/ +// @"string", /*unencrypted datatype of second column in select statement*/ +// @"string" /*datatype of third column in select statement*/}, +// 2, /*no:of input parameters*/ +// new object[] { @"CustomerId", /*input parameter name*/ +// @"int", /*input parameter data type*/ +// 45, /*input parameter value*/ +// @"FirstName", /*input parameter name*/ +// @"string", /*input parameter data type*/ +// @"Microsoft" /*input parameter value*/} +// }; + +// yield return new object[] { +// connStrAE, +// false, /*sync*/ +// @"select CustomerId, FirstName, LastName from [{0}] where CustomerId = @CustomerId", +// 3, /*total number of columns in select statement*/ +// new string[] { @"int", /*unencrypted datatype of first column in select statement*/ +// @"string", /*unencrypted datatype of second column in select statement*/ +// @"string" /*datatype of third column in select statement*/}, +// 1, /*no:of input parameters*/ +// new object[] { @"CustomerId", /*input parameter name*/ +// @"int", /*input parameter data type*/ +// 45, /*input parameter value*/} +// }; + +// yield return new object[] { +// connStrAE, +// false, /*sync*/ +// @"select CustomerId, FirstName, LastName from [{0}] where FirstName = @FirstName", +// 3, /*total number of columns in select statement*/ +// new string[] { @"int", /*unencrypted datatype of first column in select statement*/ +// @"string", /*unencrypted datatype of second column in select statement*/ +// @"string" /*datatype of third column in select statement*/}, +// 1, /*no:of input parameters*/ +// new object[] { @"FirstName", /*input parameter name*/ +// @"string", /*input parameter data type*/ +// @"Microsoft" /*input parameter value*/} +// }; + +// yield return new object[] { +// connStrAE, +// false, /*sync*/ +// @"select CustomerId, FirstName, LastName from [{0}] where LastName = @LastName", +// 3, /*total number of columns in select statement*/ +// new string[] { @"int", /*unencrypted datatype of first column in select statement*/ +// @"string", /*unencrypted datatype of second column in select statement*/ +// @"string" /*datatype of third column in select statement*/}, +// 1, /*no:of input parameters*/ +// new object[] { @"LastName", /*input parameter name*/ +// @"string", /*input parameter data type*/ +// @"Corporation" /*input parameter value*/} +// }; + +// yield return new object[] { +// connStrAE, +// false, /*sync*/ +// @"select CustomerId, FirstName from [{0}] where CustomerId = @CustomerId and FirstName = @FirstName", +// 2, /*total number of columns in select statement*/ +// new string[] { @"int", /*unencrypted datatype of first column in select statement*/ +// @"string", /*unencrypted datatype of second column in select statement*/}, +// 2, /*no:of input parameters*/ +// new object[] { @"CustomerId", /*input parameter name*/ +// @"int", /*input parameter data type*/ +// 45, /*input parameter value*/ +// @"FirstName", /*input parameter name*/ +// @"string", /*input parameter data type*/ +// @"Microsoft" /*input parameter value*/} +// }; +// } +// } +// IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ExceptionTestAKVStore.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ExceptionTestAKVStore.cs index 6cb20a4351..8d9c6366f1 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ExceptionTestAKVStore.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ExceptionTestAKVStore.cs @@ -1,270 +1,270 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Security.Cryptography; -using Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider; -using Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup; -using Xunit; - -namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted -{ - public class ExceptionTestAKVStore : IClassFixture - { - private const string MasterKeyEncAlgo = "RSA_OAEP"; - private const string BadMasterKeyEncAlgo = "BadMasterKeyAlgorithm"; - - private SQLSetupStrategyAzureKeyVault fixture; - - private byte[] cek; - private byte[] encryptedCek; - - public ExceptionTestAKVStore(SQLSetupStrategyAzureKeyVault fixture) - { - this.fixture = fixture; - cek = ColumnEncryptionKey.GenerateRandomBytes(ColumnEncryptionKey.KeySizeInBytes); - encryptedCek = fixture.AkvStoreProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, MasterKeyEncAlgo, cek); - - // Disable the cache to avoid false failures. - SqlConnection.ColumnEncryptionQueryMetadataCacheEnabled = false; - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public void InvalidKeyEncryptionAlgorithm() - { - Exception ex1 = Assert.Throws(() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, BadMasterKeyEncAlgo, cek)); - Assert.Matches($@"Invalid key encryption algorithm specified: 'BadMasterKeyAlgorithm'. Expected value: 'RSA_OAEP' or 'RSA-OAEP'.\s+\(?Parameter (name: )?'?encryptionAlgorithm('\))?", ex1.Message); - - Exception ex2 = Assert.Throws(() => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, BadMasterKeyEncAlgo, cek)); - Assert.Matches($@"Invalid key encryption algorithm specified: 'BadMasterKeyAlgorithm'. Expected value: 'RSA_OAEP' or 'RSA-OAEP'.\s+\(?Parameter (name: )?'?encryptionAlgorithm('\))?", ex2.Message); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public void NullEncryptionAlgorithm() - { - Exception ex1 = Assert.Throws(() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, null, cek)); - Assert.Matches($@"Internal error. Key encryption algorithm cannot be null.\s+\(?Parameter (name: )?'?encryptionAlgorithm('\))?", ex1.Message); - Exception ex2 = Assert.Throws(() => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, null, cek)); - Assert.Matches($@"Internal error. Key encryption algorithm cannot be null.\s+\(?Parameter (name: )?'?encryptionAlgorithm('\))?", ex2.Message); - } - - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public void EmptyColumnEncryptionKey() - { - Exception ex1 = Assert.Throws(() => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, MasterKeyEncAlgo, new byte[] { })); - Assert.Matches($@"Internal error. Empty columnEncryptionKey specified.", ex1.Message); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public void NullColumnEncryptionKey() - { - Exception ex1 = Assert.Throws(() => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, MasterKeyEncAlgo, null)); - Assert.Matches($@"Value cannot be null.\s+\(?Parameter (name: )?'?columnEncryptionKey('\))?", ex1.Message); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public void EmptyEncryptedColumnEncryptionKey() - { - Exception ex1 = Assert.Throws(() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, MasterKeyEncAlgo, new byte[] { })); - Assert.Matches($@"Internal error. Empty encryptedColumnEncryptionKey specified", ex1.Message); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public void NullEncryptedColumnEncryptionKey() - { - Exception ex1 = Assert.Throws(() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, MasterKeyEncAlgo, null)); - Assert.Matches($@"Value cannot be null.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?", ex1.Message); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public void InvalidAlgorithmVersion() - { - byte[] encrypteCekLocal = ColumnEncryptionKey.GenerateInvalidEncryptedCek(encryptedCek, ColumnEncryptionKey.ECEKCorruption.ALGORITHM_VERSION); - Exception ex1 = Assert.Throws(() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, MasterKeyEncAlgo, encrypteCekLocal)); - Assert.Matches($@"Specified encrypted column encryption key contains an invalid encryption algorithm version '10'. Expected version is '01'.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?", ex1.Message); - - Exception ex2 = Assert.Throws(() => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_CORRUPT", encryptedCek)); - Assert.Contains("Invalid key encryption algorithm specified: 'RSA_CORRUPT'. Expected value: 'RSA_OAEP' or 'RSA-OAEP'.", ex2.Message); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public void InvalidCertificateSignature() - { - // Put an invalid signature - byte[] encrypteCekLocal = ColumnEncryptionKey.GenerateInvalidEncryptedCek(encryptedCek, ColumnEncryptionKey.ECEKCorruption.SIGNATURE); - string errorMessage = - $@"The specified encrypted column encryption key signature does not match the signature computed with the column master key \(Asymmetric key in Azure Key Vault\) in '{DataTestUtility.AKVUrl}'. The encrypted column encryption key may be corrupt, or the specified path may be incorrect.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?"; - - Exception ex1 = Assert.Throws(() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, MasterKeyEncAlgo, encrypteCekLocal)); - Assert.Matches(errorMessage, ex1.Message); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public void InvalidCipherTextLength() - { - // Put an invalid signature - byte[] encrypteCekLocal = ColumnEncryptionKey.GenerateInvalidEncryptedCek(encryptedCek, ColumnEncryptionKey.ECEKCorruption.CEK_LENGTH); - string errorMessage = $@"The specified encrypted column encryption key's ciphertext length: 251 does not match the ciphertext length: 256 when using column master key \(Azure Key Vault key\) in '{DataTestUtility.AKVUrl}'. The encrypted column encryption key may be corrupt, or the specified Azure Key Vault key path may be incorrect.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?"; - - Exception ex1 = Assert.Throws(() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, MasterKeyEncAlgo, encrypteCekLocal)); - Assert.Matches(errorMessage, ex1.Message); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public void InvalidSignatureInEncryptedCek() - { - byte[] encryptedCekLocal = ColumnEncryptionKey.GenerateInvalidEncryptedCek(encryptedCek, ColumnEncryptionKey.ECEKCorruption.SIGNATURE_LENGTH); - string errorMessage = $@"The specified encrypted column encryption key's signature length: 249 does not match the signature length: 256 when using column master key \(Azure Key Vault key\) in '{DataTestUtility.AKVUrl}'. The encrypted column encryption key may be corrupt, or the specified Azure Key Vault key path may be incorrect.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?"; - - Exception ex1 = Assert.Throws(() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, MasterKeyEncAlgo, encryptedCekLocal)); - Assert.Matches(errorMessage, ex1.Message); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public void InvalidURL() - { - char[] barePath = new char[32780]; - for (int i = 0; i < barePath.Length; i++) - { - barePath[i] = 'a'; - } - - string fakePath = new string(barePath); - string errorMessage = $@"Invalid url specified: '{fakePath}'.\s+\(?Parameter (name: )?'?masterKeyPath('\))?"; - - Exception ex1 = Assert.Throws(() => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(fakePath, MasterKeyEncAlgo, cek)); - Assert.Matches(errorMessage, ex1.Message); - - Exception ex2 = Assert.Throws(() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(fakePath, MasterKeyEncAlgo, encryptedCek)); - Assert.Matches(errorMessage, ex2.Message); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public void NullAKVKeyPath() - { - Exception ex1 = Assert.Throws( - () => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(null, MasterKeyEncAlgo, cek)); - Assert.Matches($@"Azure Key Vault key path cannot be null.\s+\(?Parameter (name: )?'?masterKeyPath('\))?", ex1.Message); - - Exception ex2 = Assert.Throws( - () => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(null, MasterKeyEncAlgo, encryptedCek)); - Assert.Matches($@"Internal error. Azure Key Vault key path cannot be null.\s+\(?Parameter (name: )?'?masterKeyPath('\))?", ex2.Message); - } - - [InlineData(null)] - [InlineData("")] - [InlineData(" ")] - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public void SignInvalidAKVPath(string masterKeyPath) - { - Exception ex = Assert.Throws(() => - { - SqlColumnEncryptionAzureKeyVaultProvider azureKeyProvider = new SqlColumnEncryptionAzureKeyVaultProvider( - new SqlClientCustomTokenCredential()); - azureKeyProvider.SignColumnMasterKeyMetadata(masterKeyPath, false); - }); - - if (masterKeyPath == null) - { - Assert.Matches("Internal error. Azure Key Vault key path cannot be null.", ex.Message); - } - else - { - Assert.Matches("Invalid Azure Key Vault key path specified", ex.Message); - } - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public void InvalidCertificatePath() - { - string dummyPathWithOnlyHost = @"https://www.microsoft.com"; - string invalidUrlErrorMessage = $@"Invalid url specified: '{dummyPathWithOnlyHost}'"; - string dummyPathWithInvalidKey = @"https://www.microsoft.vault.azure.com/keys/dummykey/dummykeyid"; - string invalidTrustedEndpointErrorMessage = $@"Invalid Azure Key Vault key path specified: '{dummyPathWithInvalidKey}'. Valid trusted endpoints: vault.azure.net, vault.azure.cn, vault.usgovcloudapi.net, vault.microsoftazure.de, managedhsm.azure.net, managedhsm.azure.cn, managedhsm.usgovcloudapi.net, managedhsm.microsoftazure.de.\s+\(?Parameter (name: )?'?masterKeyPath('\))?"; - - Exception ex = Assert.Throws( - () => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(dummyPathWithOnlyHost, MasterKeyEncAlgo, cek)); - Assert.Matches(invalidUrlErrorMessage, ex.Message); - - ex = Assert.Throws( - () => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(dummyPathWithInvalidKey, MasterKeyEncAlgo, cek)); - Assert.Matches(invalidTrustedEndpointErrorMessage, ex.Message); - - ex = Assert.Throws( - () => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(dummyPathWithOnlyHost, MasterKeyEncAlgo, encryptedCek)); - Assert.Matches(invalidUrlErrorMessage, ex.Message); - - ex = Assert.Throws( - () => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(dummyPathWithInvalidKey, MasterKeyEncAlgo, encryptedCek)); - Assert.Matches(invalidTrustedEndpointErrorMessage, ex.Message); - } - - [InlineData(true)] - [InlineData(false)] - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public void AkvStoreProviderVerifyFunctionWithInvalidSignature(bool fEnclaveEnabled) - { - //sign the cmk - byte[] cmkSignature = fixture.AkvStoreProvider.SignColumnMasterKeyMetadata(DataTestUtility.AKVUrl, allowEnclaveComputations: fEnclaveEnabled); - Assert.True(cmkSignature != null); - - // Expect failed verification for a toggle of enclaveEnabled bit - Assert.False(fixture.AkvStoreProvider.VerifyColumnMasterKeyMetadata(DataTestUtility.AKVUrl, allowEnclaveComputations: !fEnclaveEnabled, signature: cmkSignature)); - - // Prepare another cipherText buffer - byte[] tamperedCmkSignature = new byte[cmkSignature.Length]; - Buffer.BlockCopy(cmkSignature, 0, tamperedCmkSignature, 0, tamperedCmkSignature.Length); - - // Corrupt one byte at a time 10 times - using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) - { - byte[] randomIndexInCipherText = new byte[1]; - for (int i = 0; i < 10; i++) - { - Assert.True(fixture.AkvStoreProvider.VerifyColumnMasterKeyMetadata(DataTestUtility.AKVUrl, allowEnclaveComputations: fEnclaveEnabled, signature: tamperedCmkSignature), @"tamperedCmkSignature before tampering should be verified without any problems."); - - int startingByteIndex = 0; - rng.GetBytes(randomIndexInCipherText); - - tamperedCmkSignature[startingByteIndex + randomIndexInCipherText[0]] = (byte)(cmkSignature[startingByteIndex + randomIndexInCipherText[0]] + 1); - - // Expect failed verification for invalid signature bytes - Assert.False(fixture.AkvStoreProvider.VerifyColumnMasterKeyMetadata(DataTestUtility.AKVUrl, allowEnclaveComputations: fEnclaveEnabled, signature: tamperedCmkSignature)); - - // Fix up the corrupted byte - tamperedCmkSignature[startingByteIndex + randomIndexInCipherText[0]] = cmkSignature[startingByteIndex + randomIndexInCipherText[0]]; - } - } - } - - [InlineData(new object[] { new string[] { null } })] - [InlineData(new object[] { new string[] { "" } })] - [InlineData(new object[] { new string[] { " " } })] - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public void InvalidTrustedEndpoints(string[] trustedEndpoints) - { - Exception ex = Assert.Throws(() => - { - SqlColumnEncryptionAzureKeyVaultProvider azureKeyProvider = new SqlColumnEncryptionAzureKeyVaultProvider( - new SqlClientCustomTokenCredential(), trustedEndpoints); - }); - Assert.Matches("One or more of the elements in trustedEndpoints are null or empty or consist of only whitespace.", ex.Message); - } - - [InlineData(null)] - [InlineData("")] - [InlineData(" ")] - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] - public void InvalidTrustedEndpoint(string trustedEndpoint) - { - Exception ex = Assert.Throws(() => - { - SqlColumnEncryptionAzureKeyVaultProvider azureKeyProvider = new SqlColumnEncryptionAzureKeyVaultProvider( - new SqlClientCustomTokenCredential(), trustedEndpoint); - }); - Assert.Matches("One or more of the elements in trustedEndpoints are null or empty or consist of only whitespace.", ex.Message); - } - } -} +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. + +//using System; +//using System.Security.Cryptography; +//using Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider; +//using Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup; +//using Xunit; + +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted +//{ +// public class ExceptionTestAKVStore : IClassFixture +// { +// private const string MasterKeyEncAlgo = "RSA_OAEP"; +// private const string BadMasterKeyEncAlgo = "BadMasterKeyAlgorithm"; + +// private SQLSetupStrategyAzureKeyVault fixture; + +// private byte[] cek; +// private byte[] encryptedCek; + +// public ExceptionTestAKVStore(SQLSetupStrategyAzureKeyVault fixture) +// { +// this.fixture = fixture; +// cek = ColumnEncryptionKey.GenerateRandomBytes(ColumnEncryptionKey.KeySizeInBytes); +// encryptedCek = fixture.AkvStoreProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, MasterKeyEncAlgo, cek); + +// // Disable the cache to avoid false failures. +// SqlConnection.ColumnEncryptionQueryMetadataCacheEnabled = false; +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public void InvalidKeyEncryptionAlgorithm() +// { +// Exception ex1 = Assert.Throws(() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, BadMasterKeyEncAlgo, cek)); +// Assert.Matches($@"Invalid key encryption algorithm specified: 'BadMasterKeyAlgorithm'. Expected value: 'RSA_OAEP' or 'RSA-OAEP'.\s+\(?Parameter (name: )?'?encryptionAlgorithm('\))?", ex1.Message); + +// Exception ex2 = Assert.Throws(() => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, BadMasterKeyEncAlgo, cek)); +// Assert.Matches($@"Invalid key encryption algorithm specified: 'BadMasterKeyAlgorithm'. Expected value: 'RSA_OAEP' or 'RSA-OAEP'.\s+\(?Parameter (name: )?'?encryptionAlgorithm('\))?", ex2.Message); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public void NullEncryptionAlgorithm() +// { +// Exception ex1 = Assert.Throws(() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, null, cek)); +// Assert.Matches($@"Internal error. Key encryption algorithm cannot be null.\s+\(?Parameter (name: )?'?encryptionAlgorithm('\))?", ex1.Message); +// Exception ex2 = Assert.Throws(() => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, null, cek)); +// Assert.Matches($@"Internal error. Key encryption algorithm cannot be null.\s+\(?Parameter (name: )?'?encryptionAlgorithm('\))?", ex2.Message); +// } + + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public void EmptyColumnEncryptionKey() +// { +// Exception ex1 = Assert.Throws(() => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, MasterKeyEncAlgo, new byte[] { })); +// Assert.Matches($@"Internal error. Empty columnEncryptionKey specified.", ex1.Message); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public void NullColumnEncryptionKey() +// { +// Exception ex1 = Assert.Throws(() => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, MasterKeyEncAlgo, null)); +// Assert.Matches($@"Value cannot be null.\s+\(?Parameter (name: )?'?columnEncryptionKey('\))?", ex1.Message); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public void EmptyEncryptedColumnEncryptionKey() +// { +// Exception ex1 = Assert.Throws(() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, MasterKeyEncAlgo, new byte[] { })); +// Assert.Matches($@"Internal error. Empty encryptedColumnEncryptionKey specified", ex1.Message); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public void NullEncryptedColumnEncryptionKey() +// { +// Exception ex1 = Assert.Throws(() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, MasterKeyEncAlgo, null)); +// Assert.Matches($@"Value cannot be null.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?", ex1.Message); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public void InvalidAlgorithmVersion() +// { +// byte[] encrypteCekLocal = ColumnEncryptionKey.GenerateInvalidEncryptedCek(encryptedCek, ColumnEncryptionKey.ECEKCorruption.ALGORITHM_VERSION); +// Exception ex1 = Assert.Throws(() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, MasterKeyEncAlgo, encrypteCekLocal)); +// Assert.Matches($@"Specified encrypted column encryption key contains an invalid encryption algorithm version '10'. Expected version is '01'.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?", ex1.Message); + +// Exception ex2 = Assert.Throws(() => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_CORRUPT", encryptedCek)); +// Assert.Contains("Invalid key encryption algorithm specified: 'RSA_CORRUPT'. Expected value: 'RSA_OAEP' or 'RSA-OAEP'.", ex2.Message); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public void InvalidCertificateSignature() +// { +// // Put an invalid signature +// byte[] encrypteCekLocal = ColumnEncryptionKey.GenerateInvalidEncryptedCek(encryptedCek, ColumnEncryptionKey.ECEKCorruption.SIGNATURE); +// string errorMessage = +// $@"The specified encrypted column encryption key signature does not match the signature computed with the column master key \(Asymmetric key in Azure Key Vault\) in '{DataTestUtility.AKVUrl}'. The encrypted column encryption key may be corrupt, or the specified path may be incorrect.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?"; + +// Exception ex1 = Assert.Throws(() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, MasterKeyEncAlgo, encrypteCekLocal)); +// Assert.Matches(errorMessage, ex1.Message); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public void InvalidCipherTextLength() +// { +// // Put an invalid signature +// byte[] encrypteCekLocal = ColumnEncryptionKey.GenerateInvalidEncryptedCek(encryptedCek, ColumnEncryptionKey.ECEKCorruption.CEK_LENGTH); +// string errorMessage = $@"The specified encrypted column encryption key's ciphertext length: 251 does not match the ciphertext length: 256 when using column master key \(Azure Key Vault key\) in '{DataTestUtility.AKVUrl}'. The encrypted column encryption key may be corrupt, or the specified Azure Key Vault key path may be incorrect.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?"; + +// Exception ex1 = Assert.Throws(() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, MasterKeyEncAlgo, encrypteCekLocal)); +// Assert.Matches(errorMessage, ex1.Message); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public void InvalidSignatureInEncryptedCek() +// { +// byte[] encryptedCekLocal = ColumnEncryptionKey.GenerateInvalidEncryptedCek(encryptedCek, ColumnEncryptionKey.ECEKCorruption.SIGNATURE_LENGTH); +// string errorMessage = $@"The specified encrypted column encryption key's signature length: 249 does not match the signature length: 256 when using column master key \(Azure Key Vault key\) in '{DataTestUtility.AKVUrl}'. The encrypted column encryption key may be corrupt, or the specified Azure Key Vault key path may be incorrect.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?"; + +// Exception ex1 = Assert.Throws(() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, MasterKeyEncAlgo, encryptedCekLocal)); +// Assert.Matches(errorMessage, ex1.Message); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public void InvalidURL() +// { +// char[] barePath = new char[32780]; +// for (int i = 0; i < barePath.Length; i++) +// { +// barePath[i] = 'a'; +// } + +// string fakePath = new string(barePath); +// string errorMessage = $@"Invalid url specified: '{fakePath}'.\s+\(?Parameter (name: )?'?masterKeyPath('\))?"; + +// Exception ex1 = Assert.Throws(() => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(fakePath, MasterKeyEncAlgo, cek)); +// Assert.Matches(errorMessage, ex1.Message); + +// Exception ex2 = Assert.Throws(() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(fakePath, MasterKeyEncAlgo, encryptedCek)); +// Assert.Matches(errorMessage, ex2.Message); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public void NullAKVKeyPath() +// { +// Exception ex1 = Assert.Throws( +// () => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(null, MasterKeyEncAlgo, cek)); +// Assert.Matches($@"Azure Key Vault key path cannot be null.\s+\(?Parameter (name: )?'?masterKeyPath('\))?", ex1.Message); + +// Exception ex2 = Assert.Throws( +// () => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(null, MasterKeyEncAlgo, encryptedCek)); +// Assert.Matches($@"Internal error. Azure Key Vault key path cannot be null.\s+\(?Parameter (name: )?'?masterKeyPath('\))?", ex2.Message); +// } + +// [InlineData(null)] +// [InlineData("")] +// [InlineData(" ")] +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public void SignInvalidAKVPath(string masterKeyPath) +// { +// Exception ex = Assert.Throws(() => +// { +// SqlColumnEncryptionAzureKeyVaultProvider azureKeyProvider = new SqlColumnEncryptionAzureKeyVaultProvider( +// new SqlClientCustomTokenCredential()); +// azureKeyProvider.SignColumnMasterKeyMetadata(masterKeyPath, false); +// }); + +// if (masterKeyPath == null) +// { +// Assert.Matches("Internal error. Azure Key Vault key path cannot be null.", ex.Message); +// } +// else +// { +// Assert.Matches("Invalid Azure Key Vault key path specified", ex.Message); +// } +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public void InvalidCertificatePath() +// { +// string dummyPathWithOnlyHost = @"https://www.microsoft.com"; +// string invalidUrlErrorMessage = $@"Invalid url specified: '{dummyPathWithOnlyHost}'"; +// string dummyPathWithInvalidKey = @"https://www.microsoft.vault.azure.com/keys/dummykey/dummykeyid"; +// string invalidTrustedEndpointErrorMessage = $@"Invalid Azure Key Vault key path specified: '{dummyPathWithInvalidKey}'. Valid trusted endpoints: vault.azure.net, vault.azure.cn, vault.usgovcloudapi.net, vault.microsoftazure.de, managedhsm.azure.net, managedhsm.azure.cn, managedhsm.usgovcloudapi.net, managedhsm.microsoftazure.de.\s+\(?Parameter (name: )?'?masterKeyPath('\))?"; + +// Exception ex = Assert.Throws( +// () => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(dummyPathWithOnlyHost, MasterKeyEncAlgo, cek)); +// Assert.Matches(invalidUrlErrorMessage, ex.Message); + +// ex = Assert.Throws( +// () => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(dummyPathWithInvalidKey, MasterKeyEncAlgo, cek)); +// Assert.Matches(invalidTrustedEndpointErrorMessage, ex.Message); + +// ex = Assert.Throws( +// () => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(dummyPathWithOnlyHost, MasterKeyEncAlgo, encryptedCek)); +// Assert.Matches(invalidUrlErrorMessage, ex.Message); + +// ex = Assert.Throws( +// () => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(dummyPathWithInvalidKey, MasterKeyEncAlgo, encryptedCek)); +// Assert.Matches(invalidTrustedEndpointErrorMessage, ex.Message); +// } + +// [InlineData(true)] +// [InlineData(false)] +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public void AkvStoreProviderVerifyFunctionWithInvalidSignature(bool fEnclaveEnabled) +// { +// //sign the cmk +// byte[] cmkSignature = fixture.AkvStoreProvider.SignColumnMasterKeyMetadata(DataTestUtility.AKVUrl, allowEnclaveComputations: fEnclaveEnabled); +// Assert.True(cmkSignature != null); + +// // Expect failed verification for a toggle of enclaveEnabled bit +// Assert.False(fixture.AkvStoreProvider.VerifyColumnMasterKeyMetadata(DataTestUtility.AKVUrl, allowEnclaveComputations: !fEnclaveEnabled, signature: cmkSignature)); + +// // Prepare another cipherText buffer +// byte[] tamperedCmkSignature = new byte[cmkSignature.Length]; +// Buffer.BlockCopy(cmkSignature, 0, tamperedCmkSignature, 0, tamperedCmkSignature.Length); + +// // Corrupt one byte at a time 10 times +// using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) +// { +// byte[] randomIndexInCipherText = new byte[1]; +// for (int i = 0; i < 10; i++) +// { +// Assert.True(fixture.AkvStoreProvider.VerifyColumnMasterKeyMetadata(DataTestUtility.AKVUrl, allowEnclaveComputations: fEnclaveEnabled, signature: tamperedCmkSignature), @"tamperedCmkSignature before tampering should be verified without any problems."); + +// int startingByteIndex = 0; +// rng.GetBytes(randomIndexInCipherText); + +// tamperedCmkSignature[startingByteIndex + randomIndexInCipherText[0]] = (byte)(cmkSignature[startingByteIndex + randomIndexInCipherText[0]] + 1); + +// // Expect failed verification for invalid signature bytes +// Assert.False(fixture.AkvStoreProvider.VerifyColumnMasterKeyMetadata(DataTestUtility.AKVUrl, allowEnclaveComputations: fEnclaveEnabled, signature: tamperedCmkSignature)); + +// // Fix up the corrupted byte +// tamperedCmkSignature[startingByteIndex + randomIndexInCipherText[0]] = cmkSignature[startingByteIndex + randomIndexInCipherText[0]]; +// } +// } +// } + +// [InlineData(new object[] { new string[] { null } })] +// [InlineData(new object[] { new string[] { "" } })] +// [InlineData(new object[] { new string[] { " " } })] +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public void InvalidTrustedEndpoints(string[] trustedEndpoints) +// { +// Exception ex = Assert.Throws(() => +// { +// SqlColumnEncryptionAzureKeyVaultProvider azureKeyProvider = new SqlColumnEncryptionAzureKeyVaultProvider( +// new SqlClientCustomTokenCredential(), trustedEndpoints); +// }); +// Assert.Matches("One or more of the elements in trustedEndpoints are null or empty or consist of only whitespace.", ex.Message); +// } + +// [InlineData(null)] +// [InlineData("")] +// [InlineData(" ")] +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] +// public void InvalidTrustedEndpoint(string trustedEndpoint) +// { +// Exception ex = Assert.Throws(() => +// { +// SqlColumnEncryptionAzureKeyVaultProvider azureKeyProvider = new SqlColumnEncryptionAzureKeyVaultProvider( +// new SqlClientCustomTokenCredential(), trustedEndpoint); +// }); +// Assert.Matches("One or more of the elements in trustedEndpoints are null or empty or consist of only whitespace.", ex.Message); +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ExceptionsGenericError.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ExceptionsGenericError.cs index b3c51d7fbd..74bfda1d87 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ExceptionsGenericError.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ExceptionsGenericError.cs @@ -1,175 +1,175 @@ -using System; -using System.Data; -using Xunit; +//using System; +//using System.Data; +//using Xunit; -namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted -{ - public class ExceptionsGenericErrors : IClassFixture - { - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE), nameof(DataTestUtility.IsNotAzureServer), Skip = "ActiveIssue 10036")] - [ClassData(typeof(AEConnectionStringProvider))] - public void TestCommandOptionWithNoTceFeature(string connectionString) - { - SqlConnectionStringBuilder sb = new SqlConnectionStringBuilder(connectionString); - CertificateUtility.ChangeServerTceSetting(false, sb); // disable TCE on engine. - using (SqlConnection conn = CertificateUtility.GetOpenConnection(false, sb, fSuppressAttestation: true)) - { - using (SqlCommand cmd = new SqlCommand(ExceptionGenericErrorFixture.encryptedProcedureName, conn, null, SqlCommandColumnEncryptionSetting.Enabled)) - { - SqlParameter param = cmd.Parameters.AddWithValue("@c1", 2); - cmd.CommandType = CommandType.StoredProcedure; - string expectedErrorMessage = "SQL Server instance in use does not support column encryption."; - InvalidOperationException e = Assert.Throws(() => cmd.ExecuteNonQuery()); - Assert.Contains(expectedErrorMessage, e.Message); - } - } - // Turn on TCE now - CertificateUtility.ChangeServerTceSetting(true, sb); // enable tce - } +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted +//{ +// public class ExceptionsGenericErrors : IClassFixture +// { +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE), nameof(DataTestUtility.IsNotAzureServer), Skip = "ActiveIssue 10036")] +// [ClassData(typeof(AEConnectionStringProvider))] +// public void TestCommandOptionWithNoTceFeature(string connectionString) +// { +// SqlConnectionStringBuilder sb = new SqlConnectionStringBuilder(connectionString); +// CertificateUtility.ChangeServerTceSetting(false, sb); // disable TCE on engine. +// using (SqlConnection conn = CertificateUtility.GetOpenConnection(false, sb, fSuppressAttestation: true)) +// { +// using (SqlCommand cmd = new SqlCommand(ExceptionGenericErrorFixture.encryptedProcedureName, conn, null, SqlCommandColumnEncryptionSetting.Enabled)) +// { +// SqlParameter param = cmd.Parameters.AddWithValue("@c1", 2); +// cmd.CommandType = CommandType.StoredProcedure; +// string expectedErrorMessage = "SQL Server instance in use does not support column encryption."; +// InvalidOperationException e = Assert.Throws(() => cmd.ExecuteNonQuery()); +// Assert.Contains(expectedErrorMessage, e.Message); +// } +// } +// // Turn on TCE now +// CertificateUtility.ChangeServerTceSetting(true, sb); // enable tce +// } - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE), nameof(DataTestUtility.IsNotAzureServer))] - [ClassData(typeof(AEConnectionStringProvider))] - public void TestDataAdapterAndEncryptionSetting(string connectionString) - { - SqlConnectionStringBuilder sb = new SqlConnectionStringBuilder(connectionString); - // Create a new SqlCommand for select and delete - using (SqlConnection conn = CertificateUtility.GetOpenConnection(false, sb)) - { - using (SqlCommand cmdInsert = new SqlCommand(ExceptionGenericErrorFixture.encryptedProcedureName, conn, null, SqlCommandColumnEncryptionSetting.Enabled)) - using (SqlCommand cmdDelete = new SqlCommand($"delete {ExceptionGenericErrorFixture.encryptedTableName} where c1 = @c1", conn, null, SqlCommandColumnEncryptionSetting.Disabled)) - using (SqlDataAdapter adapter = new SqlDataAdapter($"select c1 from {ExceptionGenericErrorFixture.encryptedTableName}", conn)) - { - cmdInsert.CommandType = CommandType.StoredProcedure; - cmdInsert.Parameters.Add("@c1", SqlDbType.Int, 4, "c1"); - cmdInsert.UpdatedRowSource = UpdateRowSource.None; - cmdDelete.Parameters.Add("@c1", SqlDbType.Int, 4, "c1"); - cmdDelete.UpdatedRowSource = UpdateRowSource.None; - adapter.InsertCommand = cmdInsert; - adapter.DeleteCommand = cmdDelete; +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE), nameof(DataTestUtility.IsNotAzureServer))] +// [ClassData(typeof(AEConnectionStringProvider))] +// public void TestDataAdapterAndEncryptionSetting(string connectionString) +// { +// SqlConnectionStringBuilder sb = new SqlConnectionStringBuilder(connectionString); +// // Create a new SqlCommand for select and delete +// using (SqlConnection conn = CertificateUtility.GetOpenConnection(false, sb)) +// { +// using (SqlCommand cmdInsert = new SqlCommand(ExceptionGenericErrorFixture.encryptedProcedureName, conn, null, SqlCommandColumnEncryptionSetting.Enabled)) +// using (SqlCommand cmdDelete = new SqlCommand($"delete {ExceptionGenericErrorFixture.encryptedTableName} where c1 = @c1", conn, null, SqlCommandColumnEncryptionSetting.Disabled)) +// using (SqlDataAdapter adapter = new SqlDataAdapter($"select c1 from {ExceptionGenericErrorFixture.encryptedTableName}", conn)) +// { +// cmdInsert.CommandType = CommandType.StoredProcedure; +// cmdInsert.Parameters.Add("@c1", SqlDbType.Int, 4, "c1"); +// cmdInsert.UpdatedRowSource = UpdateRowSource.None; +// cmdDelete.Parameters.Add("@c1", SqlDbType.Int, 4, "c1"); +// cmdDelete.UpdatedRowSource = UpdateRowSource.None; +// adapter.InsertCommand = cmdInsert; +// adapter.DeleteCommand = cmdDelete; - DataSet dataset = new DataSet(); - adapter.Fill(dataset); - DataTable table = dataset.Tables[0]; - foreach (DataRow row in table.Rows) - { - row.Delete(); - } - DataRow rowInserted = table.NewRow(); - rowInserted["c1"] = 5; - table.Rows.Add(rowInserted); - adapter.UpdateBatchSize = 0; // remove batch size limit - // run batch update +// DataSet dataset = new DataSet(); +// adapter.Fill(dataset); +// DataTable table = dataset.Tables[0]; +// foreach (DataRow row in table.Rows) +// { +// row.Delete(); +// } +// DataRow rowInserted = table.NewRow(); +// rowInserted["c1"] = 5; +// table.Rows.Add(rowInserted); +// adapter.UpdateBatchSize = 0; // remove batch size limit +// // run batch update - string expectedErrorMessage = "SqlCommandColumnEncryptionSetting should be identical on all commands (SelectCommand, InsertCommand, UpdateCommand, DeleteCommand) when doing batch updates."; - InvalidOperationException e = Assert.Throws(() => adapter.Update(dataset)); - Assert.Contains(expectedErrorMessage, e.Message); - } - } - } +// string expectedErrorMessage = "SqlCommandColumnEncryptionSetting should be identical on all commands (SelectCommand, InsertCommand, UpdateCommand, DeleteCommand) when doing batch updates."; +// InvalidOperationException e = Assert.Throws(() => adapter.Update(dataset)); +// Assert.Contains(expectedErrorMessage, e.Message); +// } +// } +// } - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE), nameof(DataTestUtility.IsNotAzureServer))] - [ClassData(typeof(AEConnectionStringProvider))] - public void TestInvalidForceColumnEncryptionSetting(string connectionString) - { - SqlConnectionStringBuilder sb = new SqlConnectionStringBuilder(connectionString); - using (SqlConnection conn = CertificateUtility.GetOpenConnection(false, sb)) - { - using (SqlCommand cmd = new SqlCommand(ExceptionGenericErrorFixture.encryptedProcedureName, conn)) - { - SqlParameter param = cmd.Parameters.AddWithValue("@c1", 2); - param.ForceColumnEncryption = true; - cmd.CommandType = CommandType.StoredProcedure; - string expectedErrorMessage = $"Cannot set ForceColumnEncryption(true) for SqlParameter '@c1' because encryption is not enabled for the statement or procedure '{ExceptionGenericErrorFixture.encryptedProcedureName}'."; - InvalidOperationException e = Assert.Throws(() => cmd.ExecuteNonQuery()); - Assert.Contains(expectedErrorMessage, e.Message); - } - } - } +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE), nameof(DataTestUtility.IsNotAzureServer))] +// [ClassData(typeof(AEConnectionStringProvider))] +// public void TestInvalidForceColumnEncryptionSetting(string connectionString) +// { +// SqlConnectionStringBuilder sb = new SqlConnectionStringBuilder(connectionString); +// using (SqlConnection conn = CertificateUtility.GetOpenConnection(false, sb)) +// { +// using (SqlCommand cmd = new SqlCommand(ExceptionGenericErrorFixture.encryptedProcedureName, conn)) +// { +// SqlParameter param = cmd.Parameters.AddWithValue("@c1", 2); +// param.ForceColumnEncryption = true; +// cmd.CommandType = CommandType.StoredProcedure; +// string expectedErrorMessage = $"Cannot set ForceColumnEncryption(true) for SqlParameter '@c1' because encryption is not enabled for the statement or procedure '{ExceptionGenericErrorFixture.encryptedProcedureName}'."; +// InvalidOperationException e = Assert.Throws(() => cmd.ExecuteNonQuery()); +// Assert.Contains(expectedErrorMessage, e.Message); +// } +// } +// } - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE), nameof(DataTestUtility.IsNotAzureServer))] - [ClassData(typeof(AEConnectionStringProvider))] - public void TestParamUnexpectedEncryptionMD(string connectionString) - { - SqlConnectionStringBuilder sb = new SqlConnectionStringBuilder(connectionString); - using (SqlConnection conn = CertificateUtility.GetOpenConnection(true, sb)) - { - using (SqlCommand cmd = new SqlCommand(ExceptionGenericErrorFixture.encryptedProcedureName, conn)) - { - SqlParameter param = cmd.Parameters.AddWithValue("@c1", 2); - param.ForceColumnEncryption = true; - cmd.CommandType = CommandType.StoredProcedure; - string expectedErrorMessage = $"Cannot execute statement or procedure '{ExceptionGenericErrorFixture.encryptedProcedureName}' because ForceColumnEncryption(true) was set for SqlParameter '@c1' and the database expects this parameter to be sent as plaintext. This may be due to a configuration error."; - InvalidOperationException e = Assert.Throws(() => cmd.ExecuteNonQuery()); - Assert.Contains(expectedErrorMessage, e.Message); - } - } - } - } +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE), nameof(DataTestUtility.IsNotAzureServer))] +// [ClassData(typeof(AEConnectionStringProvider))] +// public void TestParamUnexpectedEncryptionMD(string connectionString) +// { +// SqlConnectionStringBuilder sb = new SqlConnectionStringBuilder(connectionString); +// using (SqlConnection conn = CertificateUtility.GetOpenConnection(true, sb)) +// { +// using (SqlCommand cmd = new SqlCommand(ExceptionGenericErrorFixture.encryptedProcedureName, conn)) +// { +// SqlParameter param = cmd.Parameters.AddWithValue("@c1", 2); +// param.ForceColumnEncryption = true; +// cmd.CommandType = CommandType.StoredProcedure; +// string expectedErrorMessage = $"Cannot execute statement or procedure '{ExceptionGenericErrorFixture.encryptedProcedureName}' because ForceColumnEncryption(true) was set for SqlParameter '@c1' and the database expects this parameter to be sent as plaintext. This may be due to a configuration error."; +// InvalidOperationException e = Assert.Throws(() => cmd.ExecuteNonQuery()); +// Assert.Contains(expectedErrorMessage, e.Message); +// } +// } +// } +// } - public sealed class ExceptionGenericErrorFixture : IDisposable - { - static public string encryptedTableName; - static public string encryptedProcedureName; +// public sealed class ExceptionGenericErrorFixture : IDisposable +// { +// static public string encryptedTableName; +// static public string encryptedProcedureName; - public ExceptionGenericErrorFixture() - { - SqlConnection.ColumnEncryptionQueryMetadataCacheEnabled = false; - CreateAndPopulateSimpleTable(); - } +// public ExceptionGenericErrorFixture() +// { +// SqlConnection.ColumnEncryptionQueryMetadataCacheEnabled = false; +// CreateAndPopulateSimpleTable(); +// } - private void CreateAndPopulateSimpleTable() - { - encryptedTableName = DatabaseHelper.GenerateUniqueName("encrypted"); - encryptedProcedureName = DatabaseHelper.GenerateUniqueName("encrypted"); - foreach (string connectionStr in DataTestUtility.AEConnStringsSetup) - { - using (SqlConnection conn = CertificateUtility.GetOpenConnection(false, new SqlConnectionStringBuilder(connectionStr))) - { - using (SqlCommand cmdCreate = new SqlCommand($"create table {encryptedTableName}(c1 int)", conn)) - { - cmdCreate.CommandType = CommandType.Text; - cmdCreate.ExecuteNonQuery(); - } - using (SqlCommand cmdInsert = new SqlCommand($"insert into {encryptedTableName} values(1)", conn)) - { - cmdInsert.CommandType = CommandType.Text; - cmdInsert.ExecuteNonQuery(); - } - using (SqlCommand cmdCreateProc = new SqlCommand($"create procedure {encryptedProcedureName}(@c1 int) as insert into {encryptedTableName} values (@c1)", conn)) - { - cmdCreateProc.CommandType = CommandType.Text; - cmdCreateProc.ExecuteNonQuery(); - } - } - } - } +// private void CreateAndPopulateSimpleTable() +// { +// encryptedTableName = DatabaseHelper.GenerateUniqueName("encrypted"); +// encryptedProcedureName = DatabaseHelper.GenerateUniqueName("encrypted"); +// foreach (string connectionStr in DataTestUtility.AEConnStringsSetup) +// { +// using (SqlConnection conn = CertificateUtility.GetOpenConnection(false, new SqlConnectionStringBuilder(connectionStr))) +// { +// using (SqlCommand cmdCreate = new SqlCommand($"create table {encryptedTableName}(c1 int)", conn)) +// { +// cmdCreate.CommandType = CommandType.Text; +// cmdCreate.ExecuteNonQuery(); +// } +// using (SqlCommand cmdInsert = new SqlCommand($"insert into {encryptedTableName} values(1)", conn)) +// { +// cmdInsert.CommandType = CommandType.Text; +// cmdInsert.ExecuteNonQuery(); +// } +// using (SqlCommand cmdCreateProc = new SqlCommand($"create procedure {encryptedProcedureName}(@c1 int) as insert into {encryptedTableName} values (@c1)", conn)) +// { +// cmdCreateProc.CommandType = CommandType.Text; +// cmdCreateProc.ExecuteNonQuery(); +// } +// } +// } +// } - public void Dispose() - { - // Do NOT remove certificate for concurrent consistency. Certificates are used for other test cases as well. - foreach (string connectionStr in DataTestUtility.AEConnStringsSetup) - { - SqlConnectionStringBuilder sb = new SqlConnectionStringBuilder(connectionStr); - using (SqlConnection conn = CertificateUtility.GetOpenConnection(false, sb)) - { - using (SqlCommand cmd = new SqlCommand($"drop table {encryptedTableName}", conn)) - { - cmd.CommandType = CommandType.Text; - cmd.ExecuteNonQuery(); +// public void Dispose() +// { +// // Do NOT remove certificate for concurrent consistency. Certificates are used for other test cases as well. +// foreach (string connectionStr in DataTestUtility.AEConnStringsSetup) +// { +// SqlConnectionStringBuilder sb = new SqlConnectionStringBuilder(connectionStr); +// using (SqlConnection conn = CertificateUtility.GetOpenConnection(false, sb)) +// { +// using (SqlCommand cmd = new SqlCommand($"drop table {encryptedTableName}", conn)) +// { +// cmd.CommandType = CommandType.Text; +// cmd.ExecuteNonQuery(); - cmd.CommandText = $"drop procedure {encryptedProcedureName}"; - cmd.ExecuteNonQuery(); - } - } +// cmd.CommandText = $"drop procedure {encryptedProcedureName}"; +// cmd.ExecuteNonQuery(); +// } +// } - // Only use traceoff for non-sysadmin role accounts, Azure accounts does not have the permission. - if (DataTestUtility.IsNotAzureServer()) - { - CertificateUtility.ChangeServerTceSetting(true, sb); - } - } - } - } -} +// // Only use traceoff for non-sysadmin role accounts, Azure accounts does not have the permission. +// if (DataTestUtility.IsNotAzureServer()) +// { +// CertificateUtility.ChangeServerTceSetting(true, sb); +// } +// } +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/SqlBulkCopyTruncation.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/SqlBulkCopyTruncation.cs index 32dd86cd94..307b8daacf 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/SqlBulkCopyTruncation.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/SqlBulkCopyTruncation.cs @@ -22,7 +22,7 @@ public SqlBulkCopyTruncation(PlatformSpecificTestContext context) _fixture = context.Fixture; tableNames = _fixture.sqlBulkTruncationTableNames; } - + /* [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))] [ClassData(typeof(AEConnectionStringProvider))] public void BulkCopyTestsInt(string connectionString) @@ -332,7 +332,7 @@ public void BulkCopyVarcharMax(string connectionString) TruncateTables("TabVarCharMaxSource", "TabVarCharMaxTarget", connectionString); } } - + */ [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))] [ClassData(typeof(AEConnectionStringProvider))] public void BulkCopyNVarchar(string connectionString) @@ -366,7 +366,7 @@ public void BulkCopyNVarcharMax(string connectionString) TruncateTables("TabNVarCharMaxSource", "TabNVarCharTarget", connectionString); } } - + /* [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))] [ClassData(typeof(AEConnectionStringProvider))] public void BulkCopyBinaryMax(string connectionString) @@ -529,7 +529,7 @@ public void BulkCopySmallChar(string connectionString) TruncateTables("TabSmallCharMaxTarget", "", connectionString); } } - + */ internal void TruncateTables(string sourceName, string targetName, string connectionString) { using (SqlConnection connection = new SqlConnection(connectionString)) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestTrustedMasterKeyPaths.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestTrustedMasterKeyPaths.cs index c617a990b8..9f470bf100 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestTrustedMasterKeyPaths.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestTrustedMasterKeyPaths.cs @@ -1,308 +1,308 @@ -using System; -using System.Collections.Generic; -using System.Security.Cryptography.X509Certificates; -using Xunit; - -namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted -{ - public class TestTrustedMasterKeyPaths : IClassFixture - { - private SQLSetupStrategyCertStoreProvider fixture; - private readonly string tableName; - private readonly string columnMasterKeyPath; - - public TestTrustedMasterKeyPaths(SQLSetupStrategyCertStoreProvider fixture) - { - columnMasterKeyPath = string.Format(@"{0}/{1}/{2}", StoreLocation.CurrentUser.ToString(), @"my", CertificateUtility.CreateCertificate().Thumbprint); - this.fixture = fixture; - tableName = fixture.TrustedMasterKeyPathsTestTable.Name; - } - - /// - /// Validates that the results are the ones expected. - /// - /// - private void ValidateResultSet(SqlDataReader sqlDataReader) - { - // Validate the result set - int rowsFound = 0; - while (sqlDataReader.Read()) - { - if (sqlDataReader.FieldCount == 3) - { - Assert.True(sqlDataReader.GetInt32(0) == 45, "Employee id didn't match."); - Assert.True(sqlDataReader.GetString(1) == @"Microsoft", "Employee FirstName didn't match."); - Assert.True(sqlDataReader.GetString(2) == @"Corporation", "Employee LastName didn't match."); - } - else if (sqlDataReader.FieldCount == 1) - { - Assert.True(sqlDataReader.GetString(0) == @"Microsoft" || sqlDataReader.GetString(0) == @"Corporation", "Employee FirstName didn't match."); - } - - rowsFound++; - } - Assert.True(rowsFound == 1, "Incorrect number of rows returned in first execution."); - } - - [PlatformSpecific(TestPlatforms.Windows)] - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))] - [ClassData(typeof(AEConnectionStringProvider))] - public void TestTrustedColumnEncryptionMasterKeyPathsWithNullDictionary(string connection) - { - SqlConnectionStringBuilder connBuilder = new SqlConnectionStringBuilder(connection); - connBuilder.ConnectTimeout = 10000; - string connStringNow = connBuilder.ToString(); - - // 1. Default should succeed. - if (SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Count != 0) - { - SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Clear(); - } - - using (SqlConnection sqlConnection = new SqlConnection(string.Concat(connStringNow, @";Column Encryption Setting = Enabled;"))) - { - sqlConnection.Open(); - - // Test INPUT parameter on an encrypted parameter - using (SqlCommand sqlCommand = new SqlCommand( - $@"SELECT CustomerId, FirstName, LastName - FROM [{tableName}] - WHERE FirstName = @firstName", - sqlConnection)) - { - SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft"); - customerFirstParam.Direction = System.Data.ParameterDirection.Input; - - using (SqlDataReader sqlDataReader = sqlCommand.ExecuteReader()) - { - ValidateResultSet(sqlDataReader); - } - } - } - // Clear out trusted key paths - SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Clear(); - } - - [PlatformSpecific(TestPlatforms.Windows)] - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))] - [ClassData(typeof(AEConnectionStringProvider))] - public void TestTrustedColumnEncryptionMasterKeyPathsWithOneServer(string connection) - { - SqlConnectionStringBuilder connBuilder = new SqlConnectionStringBuilder(connection); - connBuilder.ConnectTimeout = 10000; - string connStringNow = connBuilder.ToString(); - - // 2.. Test with valid key path - // - // Clear existing dictionary. - if (SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Count != 0) - { - SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Clear(); - } - - // Add the keypath to the trusted keypaths - List trustedKeyPaths = new List(); - trustedKeyPaths.Add(columnMasterKeyPath); - SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Add(connBuilder.DataSource, trustedKeyPaths); - - using (SqlConnection sqlConnection = new SqlConnection(string.Concat(connStringNow, @";Column Encryption Setting = Enabled;"))) - { - sqlConnection.Open(); - - // Test INPUT parameter on an encrypted parameter - using (SqlCommand sqlCommand = new SqlCommand( - $@"SELECT CustomerId, FirstName, LastName - FROM [{tableName}] - WHERE FirstName = @firstName", - sqlConnection)) - { - SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft"); - customerFirstParam.Direction = System.Data.ParameterDirection.Input; - - using (SqlDataReader sqlDataReader = sqlCommand.ExecuteReader()) - { - ValidateResultSet(sqlDataReader); - } - } - } - // Clear out trusted key paths - SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Clear(); - } - - [PlatformSpecific(TestPlatforms.Windows)] - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))] - [ClassData(typeof(AEConnectionStringProvider))] - public void TestTrustedColumnEncryptionMasterKeyPathsWithMultipleServers(string connection) - { - SqlConnectionStringBuilder connBuilder = new SqlConnectionStringBuilder(connection); - connBuilder.ConnectTimeout = 10000; - string connStringNow = connBuilder.ToString(); - - // 3. Test with multiple servers with multiple key paths - // - // Clear existing dictionary. - if (SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Count != 0) - { - SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Clear(); - } - - // Add entries for one server - List server1TrustedKeyPaths = new List(); - - // Add some random key paths - foreach (char c in new char[] { 'A', 'B' }) - { - string tempThumbprint = new string('F', CertificateUtility.CreateCertificate().Thumbprint.Length); - string invalidKeyPath = string.Format(@"{0}/my/{1}", StoreLocation.CurrentUser.ToString(), tempThumbprint); - server1TrustedKeyPaths.Add(invalidKeyPath); - } - - // Add the key path used by the test - server1TrustedKeyPaths.Add(columnMasterKeyPath); - - // Add it to the dictionary - SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Add(connBuilder.DataSource, server1TrustedKeyPaths); - - // Add entries for another server - List server2TrustedKeyPaths = new List(); - server2TrustedKeyPaths.Add(@"https://balneetestkeyvault.vault.azure.net/keys/CryptoTest4/f4eb1dbbe6a9446599efe3c952614e70"); - SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Add(@"randomeserver", server2TrustedKeyPaths); - - using (SqlConnection sqlConnection = new SqlConnection(string.Concat(connStringNow, @";Column Encryption Setting = Enabled;"))) - { - sqlConnection.Open(); - - // Test INPUT parameter on an encrypted parameter - using (SqlCommand sqlCommand = new SqlCommand( - $@"SELECT CustomerId, FirstName, LastName - FROM [{tableName}] - WHERE FirstName = @firstName", - sqlConnection)) - { - SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft"); - customerFirstParam.Direction = System.Data.ParameterDirection.Input; - - using (SqlDataReader sqlDataReader = sqlCommand.ExecuteReader()) - { - ValidateResultSet(sqlDataReader); - } - } - } - // Clear out trusted key paths - SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Clear(); - } - - [PlatformSpecific(TestPlatforms.Windows)] - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))] - [ClassData(typeof(AEConnectionStringProvider))] - public void TestTrustedColumnEncryptionMasterKeyPathsWithInvalidInputs(string connection) - { - SqlConnectionStringBuilder connBuilder = new SqlConnectionStringBuilder(connection); - connBuilder.ConnectTimeout = 10000; - string connStringNow = connBuilder.ToString(); - - // 1. Test with null List - // - // Clear existing dictionary. - if (SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Count != 0) - { - SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Clear(); - } - - // Clear any cache - CertificateUtility.CleanSqlClientCache(); - - // Prepare a dictionary with null list. - SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Add(connBuilder.DataSource, (List)null); - - using (SqlConnection sqlConnection = new SqlConnection(string.Concat(connStringNow, @";Column Encryption Setting = Enabled;"))) - { - sqlConnection.Open(); - - // Test INPUT parameter on an encrypted parameter - using (SqlCommand sqlCommand = new SqlCommand( - $@"SELECT CustomerId, FirstName, LastName - FROM [{tableName}] - WHERE FirstName = @firstName", - sqlConnection)) - { - SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft"); - customerFirstParam.Direction = System.Data.ParameterDirection.Input; - - string expectedErrorMessage = "not a trusted key path"; - ArgumentException e = Assert.Throws(() => sqlCommand.ExecuteReader()); - Assert.Contains(expectedErrorMessage, e.Message); - } - } - - // 2. Test with empty List - // - // Clear existing dictionary. - if (SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Count != 0) - { - SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Clear(); - } - - // Prepare dictionary with an empty list - List emptyKeyPathList = new List(); - SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Add(connBuilder.DataSource, emptyKeyPathList); - - using (SqlConnection sqlConnection = new SqlConnection(string.Concat(connStringNow, @";Column Encryption Setting = Enabled;"))) - { - sqlConnection.Open(); - - // Test INPUT parameter on an encrypted parameter - using (SqlCommand sqlCommand = new SqlCommand( - $@"SELECT CustomerId, FirstName, LastName - FROM [{tableName}] - WHERE FirstName = @firstName", - sqlConnection)) - { - SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft"); - customerFirstParam.Direction = System.Data.ParameterDirection.Input; - - string expectedErrorMessage = "not a trusted key path"; - ArgumentException e = Assert.Throws(() => sqlCommand.ExecuteReader()); - Assert.Contains(expectedErrorMessage, e.Message); - } - } - - // 3. Test with invalid key paths - // - // Clear existing dictionary. - if (SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Count != 0) - { - SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Clear(); - } - - // Prepare dictionary with invalid key path - List invalidKeyPathList = new List(); - string tempThumbprint = new string('F', CertificateUtility.CreateCertificate().Thumbprint.Length); - string invalidKeyPath = string.Format(@"{0}/my/{1}", StoreLocation.CurrentUser.ToString(), tempThumbprint); - invalidKeyPathList.Add(invalidKeyPath); - SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Add(connBuilder.DataSource, invalidKeyPathList); - - using (SqlConnection sqlConnection = new SqlConnection(string.Concat(connStringNow, @";Column Encryption Setting = Enabled;"))) - { - sqlConnection.Open(); - - // Test INPUT parameter on an encrypted parameter - using (SqlCommand sqlCommand = new SqlCommand( - $@"SELECT CustomerId, FirstName, LastName - FROM [{tableName}] - WHERE FirstName = @firstName", - sqlConnection)) - { - SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft"); - customerFirstParam.Direction = System.Data.ParameterDirection.Input; - string expectedErrorMessage = "not a trusted key path"; - ArgumentException e = Assert.Throws(() => sqlCommand.ExecuteReader()); - Assert.Contains(expectedErrorMessage, e.Message); - } - } - - // Clear out trusted key paths - SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Clear(); - } - } -} +//using System; +//using System.Collections.Generic; +//using System.Security.Cryptography.X509Certificates; +//using Xunit; + +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted +//{ +// public class TestTrustedMasterKeyPaths : IClassFixture +// { +// private SQLSetupStrategyCertStoreProvider fixture; +// private readonly string tableName; +// private readonly string columnMasterKeyPath; + +// public TestTrustedMasterKeyPaths(SQLSetupStrategyCertStoreProvider fixture) +// { +// columnMasterKeyPath = string.Format(@"{0}/{1}/{2}", StoreLocation.CurrentUser.ToString(), @"my", CertificateUtility.CreateCertificate().Thumbprint); +// this.fixture = fixture; +// tableName = fixture.TrustedMasterKeyPathsTestTable.Name; +// } + +// /// +// /// Validates that the results are the ones expected. +// /// +// /// +// private void ValidateResultSet(SqlDataReader sqlDataReader) +// { +// // Validate the result set +// int rowsFound = 0; +// while (sqlDataReader.Read()) +// { +// if (sqlDataReader.FieldCount == 3) +// { +// Assert.True(sqlDataReader.GetInt32(0) == 45, "Employee id didn't match."); +// Assert.True(sqlDataReader.GetString(1) == @"Microsoft", "Employee FirstName didn't match."); +// Assert.True(sqlDataReader.GetString(2) == @"Corporation", "Employee LastName didn't match."); +// } +// else if (sqlDataReader.FieldCount == 1) +// { +// Assert.True(sqlDataReader.GetString(0) == @"Microsoft" || sqlDataReader.GetString(0) == @"Corporation", "Employee FirstName didn't match."); +// } + +// rowsFound++; +// } +// Assert.True(rowsFound == 1, "Incorrect number of rows returned in first execution."); +// } + +// [PlatformSpecific(TestPlatforms.Windows)] +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))] +// [ClassData(typeof(AEConnectionStringProvider))] +// public void TestTrustedColumnEncryptionMasterKeyPathsWithNullDictionary(string connection) +// { +// SqlConnectionStringBuilder connBuilder = new SqlConnectionStringBuilder(connection); +// connBuilder.ConnectTimeout = 10000; +// string connStringNow = connBuilder.ToString(); + +// // 1. Default should succeed. +// if (SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Count != 0) +// { +// SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Clear(); +// } + +// using (SqlConnection sqlConnection = new SqlConnection(string.Concat(connStringNow, @";Column Encryption Setting = Enabled;"))) +// { +// sqlConnection.Open(); + +// // Test INPUT parameter on an encrypted parameter +// using (SqlCommand sqlCommand = new SqlCommand( +// $@"SELECT CustomerId, FirstName, LastName +// FROM [{tableName}] +// WHERE FirstName = @firstName", +// sqlConnection)) +// { +// SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft"); +// customerFirstParam.Direction = System.Data.ParameterDirection.Input; + +// using (SqlDataReader sqlDataReader = sqlCommand.ExecuteReader()) +// { +// ValidateResultSet(sqlDataReader); +// } +// } +// } +// // Clear out trusted key paths +// SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Clear(); +// } + +// [PlatformSpecific(TestPlatforms.Windows)] +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))] +// [ClassData(typeof(AEConnectionStringProvider))] +// public void TestTrustedColumnEncryptionMasterKeyPathsWithOneServer(string connection) +// { +// SqlConnectionStringBuilder connBuilder = new SqlConnectionStringBuilder(connection); +// connBuilder.ConnectTimeout = 10000; +// string connStringNow = connBuilder.ToString(); + +// // 2.. Test with valid key path +// // +// // Clear existing dictionary. +// if (SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Count != 0) +// { +// SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Clear(); +// } + +// // Add the keypath to the trusted keypaths +// List trustedKeyPaths = new List(); +// trustedKeyPaths.Add(columnMasterKeyPath); +// SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Add(connBuilder.DataSource, trustedKeyPaths); + +// using (SqlConnection sqlConnection = new SqlConnection(string.Concat(connStringNow, @";Column Encryption Setting = Enabled;"))) +// { +// sqlConnection.Open(); + +// // Test INPUT parameter on an encrypted parameter +// using (SqlCommand sqlCommand = new SqlCommand( +// $@"SELECT CustomerId, FirstName, LastName +// FROM [{tableName}] +// WHERE FirstName = @firstName", +// sqlConnection)) +// { +// SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft"); +// customerFirstParam.Direction = System.Data.ParameterDirection.Input; + +// using (SqlDataReader sqlDataReader = sqlCommand.ExecuteReader()) +// { +// ValidateResultSet(sqlDataReader); +// } +// } +// } +// // Clear out trusted key paths +// SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Clear(); +// } + +// [PlatformSpecific(TestPlatforms.Windows)] +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))] +// [ClassData(typeof(AEConnectionStringProvider))] +// public void TestTrustedColumnEncryptionMasterKeyPathsWithMultipleServers(string connection) +// { +// SqlConnectionStringBuilder connBuilder = new SqlConnectionStringBuilder(connection); +// connBuilder.ConnectTimeout = 10000; +// string connStringNow = connBuilder.ToString(); + +// // 3. Test with multiple servers with multiple key paths +// // +// // Clear existing dictionary. +// if (SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Count != 0) +// { +// SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Clear(); +// } + +// // Add entries for one server +// List server1TrustedKeyPaths = new List(); + +// // Add some random key paths +// foreach (char c in new char[] { 'A', 'B' }) +// { +// string tempThumbprint = new string('F', CertificateUtility.CreateCertificate().Thumbprint.Length); +// string invalidKeyPath = string.Format(@"{0}/my/{1}", StoreLocation.CurrentUser.ToString(), tempThumbprint); +// server1TrustedKeyPaths.Add(invalidKeyPath); +// } + +// // Add the key path used by the test +// server1TrustedKeyPaths.Add(columnMasterKeyPath); + +// // Add it to the dictionary +// SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Add(connBuilder.DataSource, server1TrustedKeyPaths); + +// // Add entries for another server +// List server2TrustedKeyPaths = new List(); +// server2TrustedKeyPaths.Add(@"https://balneetestkeyvault.vault.azure.net/keys/CryptoTest4/f4eb1dbbe6a9446599efe3c952614e70"); +// SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Add(@"randomeserver", server2TrustedKeyPaths); + +// using (SqlConnection sqlConnection = new SqlConnection(string.Concat(connStringNow, @";Column Encryption Setting = Enabled;"))) +// { +// sqlConnection.Open(); + +// // Test INPUT parameter on an encrypted parameter +// using (SqlCommand sqlCommand = new SqlCommand( +// $@"SELECT CustomerId, FirstName, LastName +// FROM [{tableName}] +// WHERE FirstName = @firstName", +// sqlConnection)) +// { +// SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft"); +// customerFirstParam.Direction = System.Data.ParameterDirection.Input; + +// using (SqlDataReader sqlDataReader = sqlCommand.ExecuteReader()) +// { +// ValidateResultSet(sqlDataReader); +// } +// } +// } +// // Clear out trusted key paths +// SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Clear(); +// } + +// [PlatformSpecific(TestPlatforms.Windows)] +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))] +// [ClassData(typeof(AEConnectionStringProvider))] +// public void TestTrustedColumnEncryptionMasterKeyPathsWithInvalidInputs(string connection) +// { +// SqlConnectionStringBuilder connBuilder = new SqlConnectionStringBuilder(connection); +// connBuilder.ConnectTimeout = 10000; +// string connStringNow = connBuilder.ToString(); + +// // 1. Test with null List +// // +// // Clear existing dictionary. +// if (SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Count != 0) +// { +// SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Clear(); +// } + +// // Clear any cache +// CertificateUtility.CleanSqlClientCache(); + +// // Prepare a dictionary with null list. +// SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Add(connBuilder.DataSource, (List)null); + +// using (SqlConnection sqlConnection = new SqlConnection(string.Concat(connStringNow, @";Column Encryption Setting = Enabled;"))) +// { +// sqlConnection.Open(); + +// // Test INPUT parameter on an encrypted parameter +// using (SqlCommand sqlCommand = new SqlCommand( +// $@"SELECT CustomerId, FirstName, LastName +// FROM [{tableName}] +// WHERE FirstName = @firstName", +// sqlConnection)) +// { +// SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft"); +// customerFirstParam.Direction = System.Data.ParameterDirection.Input; + +// string expectedErrorMessage = "not a trusted key path"; +// ArgumentException e = Assert.Throws(() => sqlCommand.ExecuteReader()); +// Assert.Contains(expectedErrorMessage, e.Message); +// } +// } + +// // 2. Test with empty List +// // +// // Clear existing dictionary. +// if (SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Count != 0) +// { +// SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Clear(); +// } + +// // Prepare dictionary with an empty list +// List emptyKeyPathList = new List(); +// SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Add(connBuilder.DataSource, emptyKeyPathList); + +// using (SqlConnection sqlConnection = new SqlConnection(string.Concat(connStringNow, @";Column Encryption Setting = Enabled;"))) +// { +// sqlConnection.Open(); + +// // Test INPUT parameter on an encrypted parameter +// using (SqlCommand sqlCommand = new SqlCommand( +// $@"SELECT CustomerId, FirstName, LastName +// FROM [{tableName}] +// WHERE FirstName = @firstName", +// sqlConnection)) +// { +// SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft"); +// customerFirstParam.Direction = System.Data.ParameterDirection.Input; + +// string expectedErrorMessage = "not a trusted key path"; +// ArgumentException e = Assert.Throws(() => sqlCommand.ExecuteReader()); +// Assert.Contains(expectedErrorMessage, e.Message); +// } +// } + +// // 3. Test with invalid key paths +// // +// // Clear existing dictionary. +// if (SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Count != 0) +// { +// SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Clear(); +// } + +// // Prepare dictionary with invalid key path +// List invalidKeyPathList = new List(); +// string tempThumbprint = new string('F', CertificateUtility.CreateCertificate().Thumbprint.Length); +// string invalidKeyPath = string.Format(@"{0}/my/{1}", StoreLocation.CurrentUser.ToString(), tempThumbprint); +// invalidKeyPathList.Add(invalidKeyPath); +// SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Add(connBuilder.DataSource, invalidKeyPathList); + +// using (SqlConnection sqlConnection = new SqlConnection(string.Concat(connStringNow, @";Column Encryption Setting = Enabled;"))) +// { +// sqlConnection.Open(); + +// // Test INPUT parameter on an encrypted parameter +// using (SqlCommand sqlCommand = new SqlCommand( +// $@"SELECT CustomerId, FirstName, LastName +// FROM [{tableName}] +// WHERE FirstName = @firstName", +// sqlConnection)) +// { +// SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft"); +// customerFirstParam.Direction = System.Data.ParameterDirection.Input; +// string expectedErrorMessage = "not a trusted key path"; +// ArgumentException e = Assert.Throws(() => sqlCommand.ExecuteReader()); +// Assert.Contains(expectedErrorMessage, e.Message); +// } +// } + +// // Clear out trusted key paths +// SqlConnection.ColumnEncryptionTrustedMasterKeyPaths.Clear(); +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/DDBasics/DDAsyncTest/DDAsyncTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/DDBasics/DDAsyncTest/DDAsyncTest.cs index bb1fd24a1f..c12332cbae 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/DDBasics/DDAsyncTest/DDAsyncTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/DDBasics/DDAsyncTest/DDAsyncTest.cs @@ -1,96 +1,96 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Xunit; +//using System; +//using System.Collections.Generic; +//using System.Threading.Tasks; +//using Xunit; -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ - public static class DDAsyncTest - { - #region <> - // TODO Synapse: Remove dependency on Northwind database by creating required table in setup. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public static void ExecuteCommand_WithNewConnection_ShouldPerformAsyncByDefault() - { - var executedProcessList = new List(); +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ +// public static class DDAsyncTest +// { +// #region <> +// // TODO Synapse: Remove dependency on Northwind database by creating required table in setup. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public static void ExecuteCommand_WithNewConnection_ShouldPerformAsyncByDefault() +// { +// var executedProcessList = new List(); - var task1 = ExecuteCommandWithNewConnectionAsync("A", "SELECT top 10 * FROM Orders", executedProcessList); - var task2 = ExecuteCommandWithNewConnectionAsync("B", "SELECT top 10 * FROM Products", executedProcessList); - //wait all before verifying the results - Task.WaitAll(task1, task2); +// var task1 = ExecuteCommandWithNewConnectionAsync("A", "SELECT top 10 * FROM Orders", executedProcessList); +// var task2 = ExecuteCommandWithNewConnectionAsync("B", "SELECT top 10 * FROM Products", executedProcessList); +// //wait all before verifying the results +// Task.WaitAll(task1, task2); - //verify whether it executed async - Assert.True(DoesProcessExecutedAsync(executedProcessList)); - } +// //verify whether it executed async +// Assert.True(DoesProcessExecutedAsync(executedProcessList)); +// } - private static bool DoesProcessExecutedAsync(IReadOnlyList executedProcessList) - { - for (var i = 1; i < executedProcessList.Count; i++) - { - if (executedProcessList[i] != executedProcessList[i - 1]) - { - return true; - } - } - return false; - } +// private static bool DoesProcessExecutedAsync(IReadOnlyList executedProcessList) +// { +// for (var i = 1; i < executedProcessList.Count; i++) +// { +// if (executedProcessList[i] != executedProcessList[i - 1]) +// { +// return true; +// } +// } +// return false; +// } - private static async Task ExecuteCommandWithNewConnectionAsync(string processName, string cmdText, ICollection executedProcessList) - { - using (var conn = new SqlConnection(DataTestUtility.TCPConnectionString)) - { - await conn.OpenAsync(); - var cmd = new SqlCommand(cmdText, conn); +// private static async Task ExecuteCommandWithNewConnectionAsync(string processName, string cmdText, ICollection executedProcessList) +// { +// using (var conn = new SqlConnection(DataTestUtility.TCPConnectionString)) +// { +// await conn.OpenAsync(); +// var cmd = new SqlCommand(cmdText, conn); - using (SqlDataReader reader = await cmd.ExecuteReaderAsync()) - { - while (await reader.ReadAsync()) - { - executedProcessList.Add(processName); - } - } - } - } - #endregion +// using (SqlDataReader reader = await cmd.ExecuteReaderAsync()) +// { +// while (await reader.ReadAsync()) +// { +// executedProcessList.Add(processName); +// } +// } +// } +// } +// #endregion - #region <> - // Synapse: Parallel query execution on the same connection is not supported. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public static void ExecuteCommand_WithSharedConnection_ShouldPerformAsyncByDefault() - { - var executedProcessList = new List(); +// #region <> +// // Synapse: Parallel query execution on the same connection is not supported. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public static void ExecuteCommand_WithSharedConnection_ShouldPerformAsyncByDefault() +// { +// var executedProcessList = new List(); - //for shared connection we need to add MARS capabilities - using (var conn = new SqlConnection((new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { MultipleActiveResultSets = true }).ConnectionString)) - { - conn.Open(); - var task1 = ExecuteCommandWithSharedConnectionAsync(conn, "C", "SELECT top 10 * FROM Orders", executedProcessList); - var task2 = ExecuteCommandWithSharedConnectionAsync(conn, "D", "SELECT top 10 * FROM Products", executedProcessList); - //wait all before verifying the results - Task.WaitAll(task1, task2); - } +// //for shared connection we need to add MARS capabilities +// using (var conn = new SqlConnection((new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { MultipleActiveResultSets = true }).ConnectionString)) +// { +// conn.Open(); +// var task1 = ExecuteCommandWithSharedConnectionAsync(conn, "C", "SELECT top 10 * FROM Orders", executedProcessList); +// var task2 = ExecuteCommandWithSharedConnectionAsync(conn, "D", "SELECT top 10 * FROM Products", executedProcessList); +// //wait all before verifying the results +// Task.WaitAll(task1, task2); +// } - //verify whether it executed async - Assert.True(DoesProcessExecutedAsync(executedProcessList)); - } +// //verify whether it executed async +// Assert.True(DoesProcessExecutedAsync(executedProcessList)); +// } - private static async Task ExecuteCommandWithSharedConnectionAsync(SqlConnection conn, string processName, string cmdText, ICollection executedProcessList) - { - var cmd = new SqlCommand(cmdText, conn); +// private static async Task ExecuteCommandWithSharedConnectionAsync(SqlConnection conn, string processName, string cmdText, ICollection executedProcessList) +// { +// var cmd = new SqlCommand(cmdText, conn); - using (SqlDataReader reader = await cmd.ExecuteReaderAsync()) - { - while (await reader.ReadAsync()) - { - executedProcessList.Add(processName); - } - } - } - #endregion - } -} +// using (SqlDataReader reader = await cmd.ExecuteReaderAsync()) +// { +// while (await reader.ReadAsync()) +// { +// executedProcessList.Add(processName); +// } +// } +// } +// #endregion +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/DDBasics/DDDataTypesTest/DDDataTypesTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/DDBasics/DDDataTypesTest/DDDataTypesTest.cs index 0d1e0e7e68..44c8024e9b 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/DDBasics/DDDataTypesTest/DDDataTypesTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/DDBasics/DDDataTypesTest/DDDataTypesTest.cs @@ -1,218 +1,218 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Data; -using System.Data.SqlTypes; -using System.Xml; -using Xunit; - -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ - public static class DDDataTypesTest - { - // Synapse: Cannot find data type 'XML'. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public static void XmlTest() - { - string tempTable = "xml_" + Guid.NewGuid().ToString().Replace('-', '_'); - string initStr = "create table " + tempTable + " (xml_col XML)"; - string insertNormStr = "INSERT " + tempTable + " VALUES('Hello World')"; - string insertParamStr = "INSERT " + tempTable + " VALUES(@x)"; - string queryStr = "select * from " + tempTable; - - using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) - { - conn.Open(); - - SqlCommand cmd = conn.CreateCommand(); - - cmd.CommandText = initStr; - cmd.ExecuteNonQuery(); - - try - { - cmd.CommandText = insertNormStr; - cmd.ExecuteNonQuery(); - - SqlCommand cmd2 = new SqlCommand(insertParamStr, conn); - - cmd2.Parameters.Add("@x", SqlDbType.Xml); - XmlReader xr = XmlReader.Create("data.xml"); - cmd2.Parameters[0].Value = new SqlXml(xr); - cmd2.ExecuteNonQuery(); - - cmd.CommandText = queryStr; - - using (SqlDataReader reader = cmd.ExecuteReader()) - { - int currentValue = 0; - string[] expectedValues = - { - "Hello World", - "12-2040-300300-4000400050000.01600000.98770000.9string variabletrueP10675199DT2H48M5.4775807S9999-12-30T23:59:59.9999999-08:0000000001-0002-0003-0405-060708010101AQIDBAUGBwgJCgsMDQ4PEA==http://www.abc.com/12-2040-300300-4000400050000.01600000.98770000.9string variabletrueP10675199DT2H48M5.4775807S9999-12-30T23:59:59.9999999-08:0000000001-0002-0003-0405-060708010101AQIDBAUGBwgJCgsMDQ4PEA==http://www.abc.com/2-20-300300400050000.01600000.98770000.9true1122-200400-30003000-4000040000500000.016000000.987700000.9string variable 2false-P10675199DT2H48M5.4775808S0001-01-01T00:00:00.0000000-08:0000000002-0001-0001-0807-060504030201EA8ODQwLCgkIBwYFBAMCAQ==" - }; - - while (reader.Read()) - { - Assert.True(currentValue < expectedValues.Length, "ERROR: Received more values than expected"); - - SqlXml sx = reader.GetSqlXml(0); - xr = sx.CreateReader(); - xr.Read(); - - DataTestUtility.AssertEqualsWithDescription(expectedValues[currentValue++], xr.ReadOuterXml(), "FAILED: Did not receive expected data"); - } - } - } - finally - { - cmd.CommandText = "drop table " + tempTable; - cmd.ExecuteNonQuery(); - } - } - } - - // Synapse: The statement failed. Column 'col1' has a data type that cannot participate in a columnstore index. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public static void MaxTypesTest() - { - string tempTable = "max_" + Guid.NewGuid().ToString().Replace('-', '_'); - string initStr = "create table " + tempTable + " (col1 varchar(max), col2 nvarchar(max), col3 varbinary(max))"; - - string insertNormStr = "INSERT " + tempTable + " VALUES('ASCIASCIASCIASCIASCIASCIThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first row', "; - insertNormStr += "N'This is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first row', "; - insertNormStr += "0x010100110011000111000111000011110000111100001111000001111100000111110000011111000001111100000111110000011111000001111100000111110000011111)"; - - string insertParamStr = "INSERT " + tempTable + " VALUES(@x, @y, @z)"; - string queryStr = "select * from " + tempTable; - - using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) - { - conn.Open(); - - SqlCommand cmd = conn.CreateCommand(); - - cmd.CommandText = initStr; - cmd.ExecuteNonQuery(); - - try - { - cmd.CommandText = insertNormStr; - cmd.ExecuteNonQuery(); - - SqlCommand cmd2 = new SqlCommand(insertParamStr, conn); - - cmd2.Parameters.Add("@x", SqlDbType.VarChar); - cmd2.Parameters.Add("@y", SqlDbType.NVarChar); - cmd2.Parameters.Add("@z", SqlDbType.VarBinary); - cmd2.Parameters[1].Value = "second line, Insert big, Insert Big, This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; - - byte[] bytes = new byte[2]; - - for (int i = 0; i < bytes.Length; ++i) - { - bytes[i] = 0xad; - } - cmd2.Parameters[2].Value = bytes; - cmd2.Parameters[0].Value = "This is second row ANSI value"; - cmd2.ExecuteNonQuery(); - - cmd.CommandText = queryStr; - - using (SqlDataReader reader = cmd.ExecuteReader()) - { - int currentValue = 0; - string[][] expectedValues = - { - new string[] - { - "ASCIASCIASCIASCIASCIASCIThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first row", - "This is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first row", - "010100110011000111000111000011110000111100001111000001111100000111110000011111000001111100000111110000011111000001111100000111110000011111" - }, - new string[] - { - "This is second row ANSI value", - "second line, Insert big, Insert Big, This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row", - "ADAD" - } - }; - - while (reader.Read()) - { - Assert.True(currentValue < expectedValues.Length, "ERROR: Received more values than expected"); - - char[] stringResult = reader.GetSqlChars(0).Value; - DataTestUtility.AssertEqualsWithDescription(expectedValues[currentValue][0], new string(stringResult, 0, stringResult.Length), "FAILED: Did not receive expected data"); - stringResult = reader.GetSqlChars(1).Value; - DataTestUtility.AssertEqualsWithDescription(expectedValues[currentValue][1], new string(stringResult, 0, stringResult.Length), "FAILED: Did not receive expected data"); - - byte[] bb = reader.GetSqlBytes(2).Value; - char[] cc = new char[bb.Length * 2]; - ConvertBinaryToChar(bb, cc); - - DataTestUtility.AssertEqualsWithDescription(expectedValues[currentValue][2], new string(cc, 0, cc.Length), "FAILED: Did not receive expected data"); - currentValue++; - } - } - } - finally - { - cmd.CommandText = "drop table " + tempTable; - cmd.ExecuteNonQuery(); - } - } - } - - private static char LocalByteToChar(int b) - { - char c; - - if ((b & 0xf) < 10) - { - c = (char)((b & 0xf) + '0'); - } - else - { - c = (char)((b & 0xf) - 10 + 'A'); - } - - return c; - } - - private static void ConvertBinaryToChar(byte[] bb, char[] cc) - { - for (int i = 0; i < bb.Length; ++i) - { - cc[2 * i] = LocalByteToChar((bb[i] >> 4) & 0xf); - cc[2 * i + 1] = LocalByteToChar(bb[i] & 0xf); - } - } - } -} +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. + +//using System; +//using System.Data; +//using System.Data.SqlTypes; +//using System.Xml; +//using Xunit; + +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ +// public static class DDDataTypesTest +// { +// // Synapse: Cannot find data type 'XML'. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public static void XmlTest() +// { +// string tempTable = "xml_" + Guid.NewGuid().ToString().Replace('-', '_'); +// string initStr = "create table " + tempTable + " (xml_col XML)"; +// string insertNormStr = "INSERT " + tempTable + " VALUES('Hello World')"; +// string insertParamStr = "INSERT " + tempTable + " VALUES(@x)"; +// string queryStr = "select * from " + tempTable; + +// using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) +// { +// conn.Open(); + +// SqlCommand cmd = conn.CreateCommand(); + +// cmd.CommandText = initStr; +// cmd.ExecuteNonQuery(); + +// try +// { +// cmd.CommandText = insertNormStr; +// cmd.ExecuteNonQuery(); + +// SqlCommand cmd2 = new SqlCommand(insertParamStr, conn); + +// cmd2.Parameters.Add("@x", SqlDbType.Xml); +// XmlReader xr = XmlReader.Create("data.xml"); +// cmd2.Parameters[0].Value = new SqlXml(xr); +// cmd2.ExecuteNonQuery(); + +// cmd.CommandText = queryStr; + +// using (SqlDataReader reader = cmd.ExecuteReader()) +// { +// int currentValue = 0; +// string[] expectedValues = +// { +// "Hello World", +// "12-2040-300300-4000400050000.01600000.98770000.9string variabletrueP10675199DT2H48M5.4775807S9999-12-30T23:59:59.9999999-08:0000000001-0002-0003-0405-060708010101AQIDBAUGBwgJCgsMDQ4PEA==http://www.abc.com/12-2040-300300-4000400050000.01600000.98770000.9string variabletrueP10675199DT2H48M5.4775807S9999-12-30T23:59:59.9999999-08:0000000001-0002-0003-0405-060708010101AQIDBAUGBwgJCgsMDQ4PEA==http://www.abc.com/2-20-300300400050000.01600000.98770000.9true1122-200400-30003000-4000040000500000.016000000.987700000.9string variable 2false-P10675199DT2H48M5.4775808S0001-01-01T00:00:00.0000000-08:0000000002-0001-0001-0807-060504030201EA8ODQwLCgkIBwYFBAMCAQ==" +// }; + +// while (reader.Read()) +// { +// Assert.True(currentValue < expectedValues.Length, "ERROR: Received more values than expected"); + +// SqlXml sx = reader.GetSqlXml(0); +// xr = sx.CreateReader(); +// xr.Read(); + +// DataTestUtility.AssertEqualsWithDescription(expectedValues[currentValue++], xr.ReadOuterXml(), "FAILED: Did not receive expected data"); +// } +// } +// } +// finally +// { +// cmd.CommandText = "drop table " + tempTable; +// cmd.ExecuteNonQuery(); +// } +// } +// } + +// // Synapse: The statement failed. Column 'col1' has a data type that cannot participate in a columnstore index. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public static void MaxTypesTest() +// { +// string tempTable = "max_" + Guid.NewGuid().ToString().Replace('-', '_'); +// string initStr = "create table " + tempTable + " (col1 varchar(max), col2 nvarchar(max), col3 varbinary(max))"; + +// string insertNormStr = "INSERT " + tempTable + " VALUES('ASCIASCIASCIASCIASCIASCIThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first row', "; +// insertNormStr += "N'This is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first row', "; +// insertNormStr += "0x010100110011000111000111000011110000111100001111000001111100000111110000011111000001111100000111110000011111000001111100000111110000011111)"; + +// string insertParamStr = "INSERT " + tempTable + " VALUES(@x, @y, @z)"; +// string queryStr = "select * from " + tempTable; + +// using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) +// { +// conn.Open(); + +// SqlCommand cmd = conn.CreateCommand(); + +// cmd.CommandText = initStr; +// cmd.ExecuteNonQuery(); + +// try +// { +// cmd.CommandText = insertNormStr; +// cmd.ExecuteNonQuery(); + +// SqlCommand cmd2 = new SqlCommand(insertParamStr, conn); + +// cmd2.Parameters.Add("@x", SqlDbType.VarChar); +// cmd2.Parameters.Add("@y", SqlDbType.NVarChar); +// cmd2.Parameters.Add("@z", SqlDbType.VarBinary); +// cmd2.Parameters[1].Value = "second line, Insert big, Insert Big, This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; +// cmd2.Parameters[1].Value += "This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row"; + +// byte[] bytes = new byte[2]; + +// for (int i = 0; i < bytes.Length; ++i) +// { +// bytes[i] = 0xad; +// } +// cmd2.Parameters[2].Value = bytes; +// cmd2.Parameters[0].Value = "This is second row ANSI value"; +// cmd2.ExecuteNonQuery(); + +// cmd.CommandText = queryStr; + +// using (SqlDataReader reader = cmd.ExecuteReader()) +// { +// int currentValue = 0; +// string[][] expectedValues = +// { +// new string[] +// { +// "ASCIASCIASCIASCIASCIASCIThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first row", +// "This is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first rowThis is the first row", +// "010100110011000111000111000011110000111100001111000001111100000111110000011111000001111100000111110000011111000001111100000111110000011111" +// }, +// new string[] +// { +// "This is second row ANSI value", +// "second line, Insert big, Insert Big, This is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second rowThis is the second row", +// "ADAD" +// } +// }; + +// while (reader.Read()) +// { +// Assert.True(currentValue < expectedValues.Length, "ERROR: Received more values than expected"); + +// char[] stringResult = reader.GetSqlChars(0).Value; +// DataTestUtility.AssertEqualsWithDescription(expectedValues[currentValue][0], new string(stringResult, 0, stringResult.Length), "FAILED: Did not receive expected data"); +// stringResult = reader.GetSqlChars(1).Value; +// DataTestUtility.AssertEqualsWithDescription(expectedValues[currentValue][1], new string(stringResult, 0, stringResult.Length), "FAILED: Did not receive expected data"); + +// byte[] bb = reader.GetSqlBytes(2).Value; +// char[] cc = new char[bb.Length * 2]; +// ConvertBinaryToChar(bb, cc); + +// DataTestUtility.AssertEqualsWithDescription(expectedValues[currentValue][2], new string(cc, 0, cc.Length), "FAILED: Did not receive expected data"); +// currentValue++; +// } +// } +// } +// finally +// { +// cmd.CommandText = "drop table " + tempTable; +// cmd.ExecuteNonQuery(); +// } +// } +// } + +// private static char LocalByteToChar(int b) +// { +// char c; + +// if ((b & 0xf) < 10) +// { +// c = (char)((b & 0xf) + '0'); +// } +// else +// { +// c = (char)((b & 0xf) - 10 + 'A'); +// } + +// return c; +// } + +// private static void ConvertBinaryToChar(byte[] bb, char[] cc) +// { +// for (int i = 0; i < bb.Length; ++i) +// { +// cc[2 * i] = LocalByteToChar((bb[i] >> 4) & 0xf); +// cc[2 * i + 1] = LocalByteToChar(bb[i] & 0xf); +// } +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/DDBasics/DDMARSTest/DDMARSTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/DDBasics/DDMARSTest/DDMARSTest.cs index ad057e587d..0df3603867 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/DDBasics/DDMARSTest/DDMARSTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/DDBasics/DDMARSTest/DDMARSTest.cs @@ -1,146 +1,146 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. -using Xunit; +//using Xunit; -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ - public static class DDMARSTest - { - // TODO Synapse: Remove dependency from Northwind database - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public static void TestMain() - { - string connstr = (new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { MultipleActiveResultSets = true }).ConnectionString; - string cmdText1 = "select * from Orders; select count(*) from Customers"; - string cmdText2 = "select * from Customers; select count(*) from Orders"; +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ +// public static class DDMARSTest +// { +// // TODO Synapse: Remove dependency from Northwind database +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public static void TestMain() +// { +// string connstr = (new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { MultipleActiveResultSets = true }).ConnectionString; +// string cmdText1 = "select * from Orders; select count(*) from Customers"; +// string cmdText2 = "select * from Customers; select count(*) from Orders"; - using (var conn = new SqlConnection(connstr)) - { - conn.Open(); +// using (var conn = new SqlConnection(connstr)) +// { +// conn.Open(); - using (SqlTransaction tran = conn.BeginTransaction()) - { - SqlCommand cmd1 = conn.CreateCommand(); - cmd1.Transaction = tran; - cmd1.CommandText = cmdText1; +// using (SqlTransaction tran = conn.BeginTransaction()) +// { +// SqlCommand cmd1 = conn.CreateCommand(); +// cmd1.Transaction = tran; +// cmd1.CommandText = cmdText1; - using (SqlDataReader reader1 = cmd1.ExecuteReader()) - { +// using (SqlDataReader reader1 = cmd1.ExecuteReader()) +// { - SqlCommand cmd2 = conn.CreateCommand(); - cmd2.Transaction = tran; - cmd2.CommandText = cmdText2; +// SqlCommand cmd2 = conn.CreateCommand(); +// cmd2.Transaction = tran; +// cmd2.CommandText = cmdText2; - using (SqlDataReader reader2 = cmd2.ExecuteReader()) - { - int actualOrderCount = 0; - while (reader1.Read()) - { - Assert.True(actualOrderCount <= expectedOrders.Length, "FAILED: Received more results than expected"); - DataTestUtility.AssertEqualsWithDescription(expectedOrders[actualOrderCount], reader1.GetValue(0), "FAILED: Received wrong value in order query at row " + actualOrderCount); - actualOrderCount++; - } - reader1.NextResult(); - reader1.Read(); - int customerCount = (int)reader1.GetValue(0); +// using (SqlDataReader reader2 = cmd2.ExecuteReader()) +// { +// int actualOrderCount = 0; +// while (reader1.Read()) +// { +// Assert.True(actualOrderCount <= expectedOrders.Length, "FAILED: Received more results than expected"); +// DataTestUtility.AssertEqualsWithDescription(expectedOrders[actualOrderCount], reader1.GetValue(0), "FAILED: Received wrong value in order query at row " + actualOrderCount); +// actualOrderCount++; +// } +// reader1.NextResult(); +// reader1.Read(); +// int customerCount = (int)reader1.GetValue(0); - int actualCustomerCount = 0; - while (reader2.Read()) - { - Assert.True(actualCustomerCount <= expectedCustomers.Length, "FAILED: Received more results than expected"); - DataTestUtility.AssertEqualsWithDescription(expectedCustomers[actualCustomerCount], reader2.GetValue(0), "FAILED: Received wrong value in customer query at row " + actualCustomerCount); - actualCustomerCount++; - } - reader2.NextResult(); - reader2.Read(); - int orderCount = (int)reader2.GetValue(0); +// int actualCustomerCount = 0; +// while (reader2.Read()) +// { +// Assert.True(actualCustomerCount <= expectedCustomers.Length, "FAILED: Received more results than expected"); +// DataTestUtility.AssertEqualsWithDescription(expectedCustomers[actualCustomerCount], reader2.GetValue(0), "FAILED: Received wrong value in customer query at row " + actualCustomerCount); +// actualCustomerCount++; +// } +// reader2.NextResult(); +// reader2.Read(); +// int orderCount = (int)reader2.GetValue(0); - DataTestUtility.AssertEqualsWithDescription(expectedCustomers.Length, customerCount, "FAILED: Count query returned incorrect Customer count"); - DataTestUtility.AssertEqualsWithDescription(expectedOrders.Length, orderCount, "FAILED: Count query returned incorrect Order count"); - } - } +// DataTestUtility.AssertEqualsWithDescription(expectedCustomers.Length, customerCount, "FAILED: Count query returned incorrect Customer count"); +// DataTestUtility.AssertEqualsWithDescription(expectedOrders.Length, orderCount, "FAILED: Count query returned incorrect Order count"); +// } +// } - cmd1.CommandText = "select @@trancount"; - int tranCount = (int)cmd1.ExecuteScalar(); - Assert.True(tranCount == 1, "FAILED: Expected a transaction count of 1, but actually received " + tranCount); +// cmd1.CommandText = "select @@trancount"; +// int tranCount = (int)cmd1.ExecuteScalar(); +// Assert.True(tranCount == 1, "FAILED: Expected a transaction count of 1, but actually received " + tranCount); - tran.Commit(); - } - } - } +// tran.Commit(); +// } +// } +// } - private static readonly int[] expectedOrders = - { - 10248, 10249, 10250, 10251, 10252, 10253, 10254, 10255, 10256, 10257, 10258, 10259, 10260, 10261, 10262, 10263, - 10264, 10265, 10266, 10267, 10268, 10269, 10270, 10271, 10272, 10273, 10274, 10275, 10276, 10277, 10278, 10279, - 10280, 10281, 10282, 10283, 10284, 10285, 10286, 10287, 10288, 10289, 10290, 10291, 10292, 10293, 10294, 10295, - 10296, 10297, 10298, 10299, 10300, 10301, 10302, 10303, 10304, 10305, 10306, 10307, 10308, 10309, 10310, 10311, - 10312, 10313, 10314, 10315, 10316, 10317, 10318, 10319, 10320, 10321, 10322, 10323, 10324, 10325, 10326, 10327, - 10328, 10329, 10330, 10331, 10332, 10333, 10334, 10335, 10336, 10337, 10338, 10339, 10340, 10341, 10342, 10343, - 10344, 10345, 10346, 10347, 10348, 10349, 10350, 10351, 10352, 10353, 10354, 10355, 10356, 10357, 10358, 10359, - 10360, 10361, 10362, 10363, 10364, 10365, 10366, 10367, 10368, 10369, 10370, 10371, 10372, 10373, 10374, 10375, - 10376, 10377, 10378, 10379, 10380, 10381, 10382, 10383, 10384, 10385, 10386, 10387, 10388, 10389, 10390, 10391, - 10392, 10393, 10394, 10395, 10396, 10397, 10398, 10399, 10400, 10401, 10402, 10403, 10404, 10405, 10406, 10407, - 10408, 10409, 10410, 10411, 10412, 10413, 10414, 10415, 10416, 10417, 10418, 10419, 10420, 10421, 10422, 10423, - 10424, 10425, 10426, 10427, 10428, 10429, 10430, 10431, 10432, 10433, 10434, 10435, 10436, 10437, 10438, 10439, - 10440, 10441, 10442, 10443, 10444, 10445, 10446, 10447, 10448, 10449, 10450, 10451, 10452, 10453, 10454, 10455, - 10456, 10457, 10458, 10459, 10460, 10461, 10462, 10463, 10464, 10465, 10466, 10467, 10468, 10469, 10470, 10471, - 10472, 10473, 10474, 10475, 10476, 10477, 10478, 10479, 10480, 10481, 10482, 10483, 10484, 10485, 10486, 10487, - 10488, 10489, 10490, 10491, 10492, 10493, 10494, 10495, 10496, 10497, 10498, 10499, 10500, 10501, 10502, 10503, - 10504, 10505, 10506, 10507, 10508, 10509, 10510, 10511, 10512, 10513, 10514, 10515, 10516, 10517, 10518, 10519, - 10520, 10521, 10522, 10523, 10524, 10525, 10526, 10527, 10528, 10529, 10530, 10531, 10532, 10533, 10534, 10535, - 10536, 10537, 10538, 10539, 10540, 10541, 10542, 10543, 10544, 10545, 10546, 10547, 10548, 10549, 10550, 10551, - 10552, 10553, 10554, 10555, 10556, 10557, 10558, 10559, 10560, 10561, 10562, 10563, 10564, 10565, 10566, 10567, - 10568, 10569, 10570, 10571, 10572, 10573, 10574, 10575, 10576, 10577, 10578, 10579, 10580, 10581, 10582, 10583, - 10584, 10585, 10586, 10587, 10588, 10589, 10590, 10591, 10592, 10593, 10594, 10595, 10596, 10597, 10598, 10599, - 10600, 10601, 10602, 10603, 10604, 10605, 10606, 10607, 10608, 10609, 10610, 10611, 10612, 10613, 10614, 10615, - 10616, 10617, 10618, 10619, 10620, 10621, 10622, 10623, 10624, 10625, 10626, 10627, 10628, 10629, 10630, 10631, - 10632, 10633, 10634, 10635, 10636, 10637, 10638, 10639, 10640, 10641, 10642, 10643, 10644, 10645, 10646, 10647, - 10648, 10649, 10650, 10651, 10652, 10653, 10654, 10655, 10656, 10657, 10658, 10659, 10660, 10661, 10662, 10663, - 10664, 10665, 10666, 10667, 10668, 10669, 10670, 10671, 10672, 10673, 10674, 10675, 10676, 10677, 10678, 10679, - 10680, 10681, 10682, 10683, 10684, 10685, 10686, 10687, 10688, 10689, 10690, 10691, 10692, 10693, 10694, 10695, - 10696, 10697, 10698, 10699, 10700, 10701, 10702, 10703, 10704, 10705, 10706, 10707, 10708, 10709, 10710, 10711, - 10712, 10713, 10714, 10715, 10716, 10717, 10718, 10719, 10720, 10721, 10722, 10723, 10724, 10725, 10726, 10727, - 10728, 10729, 10730, 10731, 10732, 10733, 10734, 10735, 10736, 10737, 10738, 10739, 10740, 10741, 10742, 10743, - 10744, 10745, 10746, 10747, 10748, 10749, 10750, 10751, 10752, 10753, 10754, 10755, 10756, 10757, 10758, 10759, - 10760, 10761, 10762, 10763, 10764, 10765, 10766, 10767, 10768, 10769, 10770, 10771, 10772, 10773, 10774, 10775, - 10776, 10777, 10778, 10779, 10780, 10781, 10782, 10783, 10784, 10785, 10786, 10787, 10788, 10789, 10790, 10791, - 10792, 10793, 10794, 10795, 10796, 10797, 10798, 10799, 10800, 10801, 10802, 10803, 10804, 10805, 10806, 10807, - 10808, 10809, 10810, 10811, 10812, 10813, 10814, 10815, 10816, 10817, 10818, 10819, 10820, 10821, 10822, 10823, - 10824, 10825, 10826, 10827, 10828, 10829, 10830, 10831, 10832, 10833, 10834, 10835, 10836, 10837, 10838, 10839, - 10840, 10841, 10842, 10843, 10844, 10845, 10846, 10847, 10848, 10849, 10850, 10851, 10852, 10853, 10854, 10855, - 10856, 10857, 10858, 10859, 10860, 10861, 10862, 10863, 10864, 10865, 10866, 10867, 10868, 10869, 10870, 10871, - 10872, 10873, 10874, 10875, 10876, 10877, 10878, 10879, 10880, 10881, 10882, 10883, 10884, 10885, 10886, 10887, - 10888, 10889, 10890, 10891, 10892, 10893, 10894, 10895, 10896, 10897, 10898, 10899, 10900, 10901, 10902, 10903, - 10904, 10905, 10906, 10907, 10908, 10909, 10910, 10911, 10912, 10913, 10914, 10915, 10916, 10917, 10918, 10919, - 10920, 10921, 10922, 10923, 10924, 10925, 10926, 10927, 10928, 10929, 10930, 10931, 10932, 10933, 10934, 10935, - 10936, 10937, 10938, 10939, 10940, 10941, 10942, 10943, 10944, 10945, 10946, 10947, 10948, 10949, 10950, 10951, - 10952, 10953, 10954, 10955, 10956, 10957, 10958, 10959, 10960, 10961, 10962, 10963, 10964, 10965, 10966, 10967, - 10968, 10969, 10970, 10971, 10972, 10973, 10974, 10975, 10976, 10977, 10978, 10979, 10980, 10981, 10982, 10983, - 10984, 10985, 10986, 10987, 10988, 10989, 10990, 10991, 10992, 10993, 10994, 10995, 10996, 10997, 10998, 10999, - 11000, 11001, 11002, 11003, 11004, 11005, 11006, 11007, 11008, 11009, 11010, 11011, 11012, 11013, 11014, 11015, - 11016, 11017, 11018, 11019, 11020, 11021, 11022, 11023, 11024, 11025, 11026, 11027, 11028, 11029, 11030, 11031, - 11032, 11033, 11034, 11035, 11036, 11037, 11038, 11039, 11040, 11041, 11042, 11043, 11044, 11045, 11046, 11047, - 11048, 11049, 11050, 11051, 11052, 11053, 11054, 11055, 11056, 11057, 11058, 11059, 11060, 11061, 11062, 11063, - 11064, 11065, 11066, 11067, 11068, 11069, 11070, 11071, 11072, 11073, 11074, 11075, 11076, 11077 - }; +// private static readonly int[] expectedOrders = +// { +// 10248, 10249, 10250, 10251, 10252, 10253, 10254, 10255, 10256, 10257, 10258, 10259, 10260, 10261, 10262, 10263, +// 10264, 10265, 10266, 10267, 10268, 10269, 10270, 10271, 10272, 10273, 10274, 10275, 10276, 10277, 10278, 10279, +// 10280, 10281, 10282, 10283, 10284, 10285, 10286, 10287, 10288, 10289, 10290, 10291, 10292, 10293, 10294, 10295, +// 10296, 10297, 10298, 10299, 10300, 10301, 10302, 10303, 10304, 10305, 10306, 10307, 10308, 10309, 10310, 10311, +// 10312, 10313, 10314, 10315, 10316, 10317, 10318, 10319, 10320, 10321, 10322, 10323, 10324, 10325, 10326, 10327, +// 10328, 10329, 10330, 10331, 10332, 10333, 10334, 10335, 10336, 10337, 10338, 10339, 10340, 10341, 10342, 10343, +// 10344, 10345, 10346, 10347, 10348, 10349, 10350, 10351, 10352, 10353, 10354, 10355, 10356, 10357, 10358, 10359, +// 10360, 10361, 10362, 10363, 10364, 10365, 10366, 10367, 10368, 10369, 10370, 10371, 10372, 10373, 10374, 10375, +// 10376, 10377, 10378, 10379, 10380, 10381, 10382, 10383, 10384, 10385, 10386, 10387, 10388, 10389, 10390, 10391, +// 10392, 10393, 10394, 10395, 10396, 10397, 10398, 10399, 10400, 10401, 10402, 10403, 10404, 10405, 10406, 10407, +// 10408, 10409, 10410, 10411, 10412, 10413, 10414, 10415, 10416, 10417, 10418, 10419, 10420, 10421, 10422, 10423, +// 10424, 10425, 10426, 10427, 10428, 10429, 10430, 10431, 10432, 10433, 10434, 10435, 10436, 10437, 10438, 10439, +// 10440, 10441, 10442, 10443, 10444, 10445, 10446, 10447, 10448, 10449, 10450, 10451, 10452, 10453, 10454, 10455, +// 10456, 10457, 10458, 10459, 10460, 10461, 10462, 10463, 10464, 10465, 10466, 10467, 10468, 10469, 10470, 10471, +// 10472, 10473, 10474, 10475, 10476, 10477, 10478, 10479, 10480, 10481, 10482, 10483, 10484, 10485, 10486, 10487, +// 10488, 10489, 10490, 10491, 10492, 10493, 10494, 10495, 10496, 10497, 10498, 10499, 10500, 10501, 10502, 10503, +// 10504, 10505, 10506, 10507, 10508, 10509, 10510, 10511, 10512, 10513, 10514, 10515, 10516, 10517, 10518, 10519, +// 10520, 10521, 10522, 10523, 10524, 10525, 10526, 10527, 10528, 10529, 10530, 10531, 10532, 10533, 10534, 10535, +// 10536, 10537, 10538, 10539, 10540, 10541, 10542, 10543, 10544, 10545, 10546, 10547, 10548, 10549, 10550, 10551, +// 10552, 10553, 10554, 10555, 10556, 10557, 10558, 10559, 10560, 10561, 10562, 10563, 10564, 10565, 10566, 10567, +// 10568, 10569, 10570, 10571, 10572, 10573, 10574, 10575, 10576, 10577, 10578, 10579, 10580, 10581, 10582, 10583, +// 10584, 10585, 10586, 10587, 10588, 10589, 10590, 10591, 10592, 10593, 10594, 10595, 10596, 10597, 10598, 10599, +// 10600, 10601, 10602, 10603, 10604, 10605, 10606, 10607, 10608, 10609, 10610, 10611, 10612, 10613, 10614, 10615, +// 10616, 10617, 10618, 10619, 10620, 10621, 10622, 10623, 10624, 10625, 10626, 10627, 10628, 10629, 10630, 10631, +// 10632, 10633, 10634, 10635, 10636, 10637, 10638, 10639, 10640, 10641, 10642, 10643, 10644, 10645, 10646, 10647, +// 10648, 10649, 10650, 10651, 10652, 10653, 10654, 10655, 10656, 10657, 10658, 10659, 10660, 10661, 10662, 10663, +// 10664, 10665, 10666, 10667, 10668, 10669, 10670, 10671, 10672, 10673, 10674, 10675, 10676, 10677, 10678, 10679, +// 10680, 10681, 10682, 10683, 10684, 10685, 10686, 10687, 10688, 10689, 10690, 10691, 10692, 10693, 10694, 10695, +// 10696, 10697, 10698, 10699, 10700, 10701, 10702, 10703, 10704, 10705, 10706, 10707, 10708, 10709, 10710, 10711, +// 10712, 10713, 10714, 10715, 10716, 10717, 10718, 10719, 10720, 10721, 10722, 10723, 10724, 10725, 10726, 10727, +// 10728, 10729, 10730, 10731, 10732, 10733, 10734, 10735, 10736, 10737, 10738, 10739, 10740, 10741, 10742, 10743, +// 10744, 10745, 10746, 10747, 10748, 10749, 10750, 10751, 10752, 10753, 10754, 10755, 10756, 10757, 10758, 10759, +// 10760, 10761, 10762, 10763, 10764, 10765, 10766, 10767, 10768, 10769, 10770, 10771, 10772, 10773, 10774, 10775, +// 10776, 10777, 10778, 10779, 10780, 10781, 10782, 10783, 10784, 10785, 10786, 10787, 10788, 10789, 10790, 10791, +// 10792, 10793, 10794, 10795, 10796, 10797, 10798, 10799, 10800, 10801, 10802, 10803, 10804, 10805, 10806, 10807, +// 10808, 10809, 10810, 10811, 10812, 10813, 10814, 10815, 10816, 10817, 10818, 10819, 10820, 10821, 10822, 10823, +// 10824, 10825, 10826, 10827, 10828, 10829, 10830, 10831, 10832, 10833, 10834, 10835, 10836, 10837, 10838, 10839, +// 10840, 10841, 10842, 10843, 10844, 10845, 10846, 10847, 10848, 10849, 10850, 10851, 10852, 10853, 10854, 10855, +// 10856, 10857, 10858, 10859, 10860, 10861, 10862, 10863, 10864, 10865, 10866, 10867, 10868, 10869, 10870, 10871, +// 10872, 10873, 10874, 10875, 10876, 10877, 10878, 10879, 10880, 10881, 10882, 10883, 10884, 10885, 10886, 10887, +// 10888, 10889, 10890, 10891, 10892, 10893, 10894, 10895, 10896, 10897, 10898, 10899, 10900, 10901, 10902, 10903, +// 10904, 10905, 10906, 10907, 10908, 10909, 10910, 10911, 10912, 10913, 10914, 10915, 10916, 10917, 10918, 10919, +// 10920, 10921, 10922, 10923, 10924, 10925, 10926, 10927, 10928, 10929, 10930, 10931, 10932, 10933, 10934, 10935, +// 10936, 10937, 10938, 10939, 10940, 10941, 10942, 10943, 10944, 10945, 10946, 10947, 10948, 10949, 10950, 10951, +// 10952, 10953, 10954, 10955, 10956, 10957, 10958, 10959, 10960, 10961, 10962, 10963, 10964, 10965, 10966, 10967, +// 10968, 10969, 10970, 10971, 10972, 10973, 10974, 10975, 10976, 10977, 10978, 10979, 10980, 10981, 10982, 10983, +// 10984, 10985, 10986, 10987, 10988, 10989, 10990, 10991, 10992, 10993, 10994, 10995, 10996, 10997, 10998, 10999, +// 11000, 11001, 11002, 11003, 11004, 11005, 11006, 11007, 11008, 11009, 11010, 11011, 11012, 11013, 11014, 11015, +// 11016, 11017, 11018, 11019, 11020, 11021, 11022, 11023, 11024, 11025, 11026, 11027, 11028, 11029, 11030, 11031, +// 11032, 11033, 11034, 11035, 11036, 11037, 11038, 11039, 11040, 11041, 11042, 11043, 11044, 11045, 11046, 11047, +// 11048, 11049, 11050, 11051, 11052, 11053, 11054, 11055, 11056, 11057, 11058, 11059, 11060, 11061, 11062, 11063, +// 11064, 11065, 11066, 11067, 11068, 11069, 11070, 11071, 11072, 11073, 11074, 11075, 11076, 11077 +// }; - private static readonly string[] expectedCustomers = - { - "ALFKI", "ANATR", "ANTON", "AROUT", "BERGS", "BLAUS", "BLONP", "BOLID", - "BONAP", "BOTTM", "BSBEV", "CACTU", "CENTC", "CHOPS", "COMMI", "CONSH", - "DRACD", "DUMON", "EASTC", "ERNSH", "FAMIA", "FISSA", "FOLIG", "FOLKO", - "FRANK", "FRANR", "FRANS", "FURIB", "GALED", "GODOS", "GOURL", "GREAL", - "GROSR", "HANAR", "HILAA", "HUNGC", "HUNGO", "ISLAT", "KOENE", "LACOR", - "LAMAI", "LAUGB", "LAZYK", "LEHMS", "LETSS", "LILAS", "LINOD", "LONEP", - "MAGAA", "MAISD", "MEREP", "MORGK", "NORTS", "OCEAN", "OLDWO", "OTTIK", - "PARIS", "PERIC", "PICCO", "PRINI", "QUEDE", "QUEEN", "QUICK", "RANCH", - "RATTC", "REGGC", "RICAR", "RICSU", "ROMEY", "SANTG", "SAVEA", "SEVES", - "SIMOB", "SPECD", "SPLIR", "SUPRD", "THEBI", "THECR", "TOMSP", "TORTU", - "TRADH", "TRAIH", "VAFFE", "VICTE", "VINET", "WANDK", "WARTH", "WELLI", - "WHITC", "WILMK", "WOLZA" - }; - } -} +// private static readonly string[] expectedCustomers = +// { +// "ALFKI", "ANATR", "ANTON", "AROUT", "BERGS", "BLAUS", "BLONP", "BOLID", +// "BONAP", "BOTTM", "BSBEV", "CACTU", "CENTC", "CHOPS", "COMMI", "CONSH", +// "DRACD", "DUMON", "EASTC", "ERNSH", "FAMIA", "FISSA", "FOLIG", "FOLKO", +// "FRANK", "FRANR", "FRANS", "FURIB", "GALED", "GODOS", "GOURL", "GREAL", +// "GROSR", "HANAR", "HILAA", "HUNGC", "HUNGO", "ISLAT", "KOENE", "LACOR", +// "LAMAI", "LAUGB", "LAZYK", "LEHMS", "LETSS", "LILAS", "LINOD", "LONEP", +// "MAGAA", "MAISD", "MEREP", "MORGK", "NORTS", "OCEAN", "OLDWO", "OTTIK", +// "PARIS", "PERIC", "PICCO", "PRINI", "QUEDE", "QUEEN", "QUICK", "RANCH", +// "RATTC", "REGGC", "RICAR", "RICSU", "ROMEY", "SANTG", "SAVEA", "SEVES", +// "SIMOB", "SPECD", "SPLIR", "SUPRD", "THEBI", "THECR", "TOMSP", "TORTU", +// "TRADH", "TRAIH", "VAFFE", "VICTE", "VINET", "WANDK", "WARTH", "WELLI", +// "WHITC", "WILMK", "WOLZA" +// }; +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/ProviderAgnostic/MultipleResultsTest/MultipleResultsTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/ProviderAgnostic/MultipleResultsTest/MultipleResultsTest.cs index 5b11b46b8c..746ba0c682 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/ProviderAgnostic/MultipleResultsTest/MultipleResultsTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/ProviderAgnostic/MultipleResultsTest/MultipleResultsTest.cs @@ -1,367 +1,367 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Data.Common; -using System.Diagnostics; -using System.IO; -using System.Runtime.InteropServices; -using System.Text; -using Xunit; - -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ - public class MultipleResultsTest - { - private StringBuilder _globalBuilder = new StringBuilder(); - private StringBuilder _outputBuilder; - private string[] _outputFilter; - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public void TestMain() - { - Assert.True(RunTestCoreAndCompareWithBaseline()); - } - - private void RunTest() - { - MultipleErrorHandling(new SqlConnection((new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { MultipleActiveResultSets = true }).ConnectionString)); - } - - private void MultipleErrorHandling(DbConnection connection) - { - try - { - Console.WriteLine("MultipleErrorHandling {0}", connection.GetType().Name); - Type expectedException = null; - if (connection is SqlConnection) - { - ((SqlConnection)connection).InfoMessage += delegate (object sender, SqlInfoMessageEventArgs args) - { - Console.WriteLine("*** SQL CONNECTION INFO MESSAGE : {0} ****", args.Message); - }; - expectedException = typeof(SqlException); - } - connection.Open(); - - using (DbCommand command = connection.CreateCommand()) - { - command.CommandText = - "PRINT N'0';\n" + - "SELECT num = 1, str = 'ABC';\n" + - "PRINT N'1';\n" + - "RAISERROR('Error 1', 15, 1);\n" + - "PRINT N'3';\n" + - "SELECT num = 2, str = 'ABC';\n" + - "PRINT N'4';\n" + - "RAISERROR('Error 2', 15, 1);\n" + - "PRINT N'5';\n" + - "SELECT num = 3, str = 'ABC';\n" + - "PRINT N'6';\n" + - "RAISERROR('Error 3', 15, 1);\n" + - "PRINT N'7';\n" + - "SELECT num = 4, str = 'ABC';\n" + - "PRINT N'8';\n" + - "RAISERROR('Error 4', 15, 1);\n" + - "PRINT N'9';\n" + - "SELECT num = 5, str = 'ABC';\n" + - "PRINT N'10';\n" + - "RAISERROR('Error 5', 15, 1);\n" + - "PRINT N'11';\n"; - - try - { - Console.WriteLine("**** ExecuteNonQuery *****"); - command.ExecuteNonQuery(); - } - catch (Exception e) - { - PrintException(expectedException, e); - } - - try - { - Console.WriteLine("**** ExecuteScalar ****"); - command.ExecuteScalar(); - } - catch (Exception e) - { - PrintException(expectedException, e); - } - - try - { - Console.WriteLine("**** ExecuteReader ****"); - using (DbDataReader reader = command.ExecuteReader()) - { - bool moreResults = true; - do - { - try - { - Console.WriteLine("NextResult"); - moreResults = reader.NextResult(); - } - catch (Exception e) - { - PrintException(expectedException, e); - } - } while (moreResults); - } - } - catch (Exception e) - { - PrintException(null, e); - } - } - } - catch (Exception e) - { - PrintException(null, e); - } - try - { - connection.Dispose(); - } - catch (Exception e) - { - PrintException(null, e); - } - } - - private bool RunTestCoreAndCompareWithBaseline() - { - string outputPath = "MultipleResultsTest.out"; - string baselinePath = "MultipleResultsTest.bsl"; - - var fstream = new FileStream(outputPath, FileMode.Create, FileAccess.Write, FileShare.Read); - var swriter = new StreamWriter(fstream, Encoding.UTF8); - // Convert all string writes of '\n' to '\r\n' so output files can be 'text' not 'binary' - var twriter = new CarriageReturnLineFeedReplacer(swriter); - Console.SetOut(twriter); // "redirect" Console.Out - - // Run Test - RunTest(); - - Console.Out.Flush(); - Console.Out.Dispose(); - - // Recover the standard output stream - StreamWriter standardOutput = new StreamWriter(Console.OpenStandardOutput()); - standardOutput.AutoFlush = true; - Console.SetOut(standardOutput); - - // Compare output file - var comparisonResult = FindDiffFromBaseline(baselinePath, outputPath); - - if (string.IsNullOrEmpty(comparisonResult)) - { - return true; - } - - Console.WriteLine("Test Failed!"); - Console.WriteLine("Please compare baseline : {0} with output :{1}", Path.GetFullPath(baselinePath), Path.GetFullPath(outputPath)); - Console.WriteLine("Comparison Results : "); - Console.WriteLine(comparisonResult); - return false; - } - - private void PrintException(Type expected, Exception e, params string[] values) - { - try - { - Debug.Assert(null != e, "PrintException: null exception"); - - _globalBuilder.Length = 0; - _globalBuilder.Append(e.GetType().Name).Append(": "); - - if (e is COMException) - { - _globalBuilder.Append("0x").Append((((COMException)e).HResult).ToString("X8")); - if (expected != e.GetType()) - { - _globalBuilder.Append(": ").Append(e.ToString()); - } - } - else - { - _globalBuilder.Append(e.Message); - } - AssemblyFilter(_globalBuilder); - Console.WriteLine(_globalBuilder.ToString()); - - if (expected != e.GetType()) - { - Console.WriteLine(e.StackTrace); - } - if (null != values) - { - foreach (string value in values) - { - Console.WriteLine(value); - } - } - if (null != e.InnerException) - { - PrintException(e.InnerException.GetType(), e.InnerException); - } - Console.Out.Flush(); - } - catch (Exception f) - { - Console.WriteLine(f); - } - } - - private string FindDiffFromBaseline(string baselinePath, string outputPath) - { - var expectedLines = File.ReadAllLines(baselinePath); - var outputLines = File.ReadAllLines(outputPath); - - var comparisonSb = new StringBuilder(); - - // Start compare results - var expectedLength = expectedLines.Length; - var outputLength = outputLines.Length; - var findDiffLength = Math.Min(expectedLength, outputLength); - - // Find diff for each lines - for (var lineNo = 0; lineNo < findDiffLength; lineNo++) - { - if (!expectedLines[lineNo].Equals(outputLines[lineNo])) - { - comparisonSb.AppendFormat("** DIFF at line {0} \n", lineNo); - comparisonSb.AppendFormat("A : {0} \n", outputLines[lineNo]); - comparisonSb.AppendFormat("E : {0} \n", expectedLines[lineNo]); - } - } - - var startIndex = findDiffLength - 1; - if (startIndex < 0) - startIndex = 0; - - if (findDiffLength < expectedLength) - { - comparisonSb.AppendFormat("** MISSING \n"); - for (var lineNo = startIndex; lineNo < expectedLength; lineNo++) - { - comparisonSb.AppendFormat("{0} : {1}", lineNo, expectedLines[lineNo]); - } - } - if (findDiffLength < outputLength) - { - comparisonSb.AppendFormat("** EXTRA \n"); - for (var lineNo = startIndex; lineNo < outputLength; lineNo++) - { - comparisonSb.AppendFormat("{0} : {1}", lineNo, outputLines[lineNo]); - } - } - - return comparisonSb.ToString(); - } - - private string AssemblyFilter(StreamWriter writer) - { - if (null == _outputBuilder) - { - _outputBuilder = new StringBuilder(); - } - _outputBuilder.Length = 0; - - byte[] utf8 = ((MemoryStream)writer.BaseStream).ToArray(); - string value = System.Text.Encoding.UTF8.GetString(utf8, 3, utf8.Length - 3); // skip 0xEF, 0xBB, 0xBF - _outputBuilder.Append(value); - AssemblyFilter(_outputBuilder); - return _outputBuilder.ToString(); - } - - private void AssemblyFilter(StringBuilder builder) - { - string[] filter = _outputFilter; - if (null == filter) - { - filter = new string[5]; - string tmp = typeof(System.Guid).AssemblyQualifiedName; - filter[0] = tmp.Substring(tmp.IndexOf(',')); - filter[1] = filter[0].Replace("mscorlib", "System"); - filter[2] = filter[0].Replace("mscorlib", "System.Data"); - filter[3] = filter[0].Replace("mscorlib", "System.Data.OracleClient"); - filter[4] = filter[0].Replace("mscorlib", "System.Xml"); - _outputFilter = filter; - } - - for (int i = 0; i < filter.Length; ++i) - { - builder.Replace(filter[i], ""); - } - } - - /// - /// special wrapper for the text writer to replace single "\n" with "\n" - /// - private sealed class CarriageReturnLineFeedReplacer : TextWriter - { - private TextWriter _output; - private int _lineFeedCount; - private bool _hasCarriageReturn; - - internal CarriageReturnLineFeedReplacer(TextWriter output) - { - if (output == null) - throw new ArgumentNullException(nameof(output)); - - _output = output; - } - - public int LineFeedCount - { - get { return _lineFeedCount; } - } - - public override Encoding Encoding - { - get { return _output.Encoding; } - } - - public override IFormatProvider FormatProvider - { - get { return _output.FormatProvider; } - } - - public override string NewLine - { - get { return _output.NewLine; } - set { _output.NewLine = value; } - } - - protected override void Dispose(bool disposing) - { - if (disposing) - { - ((IDisposable)_output).Dispose(); - } - _output = null; - } - - public override void Flush() - { - _output.Flush(); - } - - public override void Write(char value) - { - if ('\n' == value) - { - _lineFeedCount++; - if (!_hasCarriageReturn) - { // X'\n'Y -> X'\r\n'Y - _output.Write('\r'); - } - } - _hasCarriageReturn = '\r' == value; - _output.Write(value); - } - } - } -} +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. + +//using System; +//using System.Data.Common; +//using System.Diagnostics; +//using System.IO; +//using System.Runtime.InteropServices; +//using System.Text; +//using Xunit; + +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ +// public class MultipleResultsTest +// { +// private StringBuilder _globalBuilder = new StringBuilder(); +// private StringBuilder _outputBuilder; +// private string[] _outputFilter; + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public void TestMain() +// { +// Assert.True(RunTestCoreAndCompareWithBaseline()); +// } + +// private void RunTest() +// { +// MultipleErrorHandling(new SqlConnection((new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { MultipleActiveResultSets = true }).ConnectionString)); +// } + +// private void MultipleErrorHandling(DbConnection connection) +// { +// try +// { +// Console.WriteLine("MultipleErrorHandling {0}", connection.GetType().Name); +// Type expectedException = null; +// if (connection is SqlConnection) +// { +// ((SqlConnection)connection).InfoMessage += delegate (object sender, SqlInfoMessageEventArgs args) +// { +// Console.WriteLine("*** SQL CONNECTION INFO MESSAGE : {0} ****", args.Message); +// }; +// expectedException = typeof(SqlException); +// } +// connection.Open(); + +// using (DbCommand command = connection.CreateCommand()) +// { +// command.CommandText = +// "PRINT N'0';\n" + +// "SELECT num = 1, str = 'ABC';\n" + +// "PRINT N'1';\n" + +// "RAISERROR('Error 1', 15, 1);\n" + +// "PRINT N'3';\n" + +// "SELECT num = 2, str = 'ABC';\n" + +// "PRINT N'4';\n" + +// "RAISERROR('Error 2', 15, 1);\n" + +// "PRINT N'5';\n" + +// "SELECT num = 3, str = 'ABC';\n" + +// "PRINT N'6';\n" + +// "RAISERROR('Error 3', 15, 1);\n" + +// "PRINT N'7';\n" + +// "SELECT num = 4, str = 'ABC';\n" + +// "PRINT N'8';\n" + +// "RAISERROR('Error 4', 15, 1);\n" + +// "PRINT N'9';\n" + +// "SELECT num = 5, str = 'ABC';\n" + +// "PRINT N'10';\n" + +// "RAISERROR('Error 5', 15, 1);\n" + +// "PRINT N'11';\n"; + +// try +// { +// Console.WriteLine("**** ExecuteNonQuery *****"); +// command.ExecuteNonQuery(); +// } +// catch (Exception e) +// { +// PrintException(expectedException, e); +// } + +// try +// { +// Console.WriteLine("**** ExecuteScalar ****"); +// command.ExecuteScalar(); +// } +// catch (Exception e) +// { +// PrintException(expectedException, e); +// } + +// try +// { +// Console.WriteLine("**** ExecuteReader ****"); +// using (DbDataReader reader = command.ExecuteReader()) +// { +// bool moreResults = true; +// do +// { +// try +// { +// Console.WriteLine("NextResult"); +// moreResults = reader.NextResult(); +// } +// catch (Exception e) +// { +// PrintException(expectedException, e); +// } +// } while (moreResults); +// } +// } +// catch (Exception e) +// { +// PrintException(null, e); +// } +// } +// } +// catch (Exception e) +// { +// PrintException(null, e); +// } +// try +// { +// connection.Dispose(); +// } +// catch (Exception e) +// { +// PrintException(null, e); +// } +// } + +// private bool RunTestCoreAndCompareWithBaseline() +// { +// string outputPath = "MultipleResultsTest.out"; +// string baselinePath = "MultipleResultsTest.bsl"; + +// var fstream = new FileStream(outputPath, FileMode.Create, FileAccess.Write, FileShare.Read); +// var swriter = new StreamWriter(fstream, Encoding.UTF8); +// // Convert all string writes of '\n' to '\r\n' so output files can be 'text' not 'binary' +// var twriter = new CarriageReturnLineFeedReplacer(swriter); +// Console.SetOut(twriter); // "redirect" Console.Out + +// // Run Test +// RunTest(); + +// Console.Out.Flush(); +// Console.Out.Dispose(); + +// // Recover the standard output stream +// StreamWriter standardOutput = new StreamWriter(Console.OpenStandardOutput()); +// standardOutput.AutoFlush = true; +// Console.SetOut(standardOutput); + +// // Compare output file +// var comparisonResult = FindDiffFromBaseline(baselinePath, outputPath); + +// if (string.IsNullOrEmpty(comparisonResult)) +// { +// return true; +// } + +// Console.WriteLine("Test Failed!"); +// Console.WriteLine("Please compare baseline : {0} with output :{1}", Path.GetFullPath(baselinePath), Path.GetFullPath(outputPath)); +// Console.WriteLine("Comparison Results : "); +// Console.WriteLine(comparisonResult); +// return false; +// } + +// private void PrintException(Type expected, Exception e, params string[] values) +// { +// try +// { +// Debug.Assert(null != e, "PrintException: null exception"); + +// _globalBuilder.Length = 0; +// _globalBuilder.Append(e.GetType().Name).Append(": "); + +// if (e is COMException) +// { +// _globalBuilder.Append("0x").Append((((COMException)e).HResult).ToString("X8")); +// if (expected != e.GetType()) +// { +// _globalBuilder.Append(": ").Append(e.ToString()); +// } +// } +// else +// { +// _globalBuilder.Append(e.Message); +// } +// AssemblyFilter(_globalBuilder); +// Console.WriteLine(_globalBuilder.ToString()); + +// if (expected != e.GetType()) +// { +// Console.WriteLine(e.StackTrace); +// } +// if (null != values) +// { +// foreach (string value in values) +// { +// Console.WriteLine(value); +// } +// } +// if (null != e.InnerException) +// { +// PrintException(e.InnerException.GetType(), e.InnerException); +// } +// Console.Out.Flush(); +// } +// catch (Exception f) +// { +// Console.WriteLine(f); +// } +// } + +// private string FindDiffFromBaseline(string baselinePath, string outputPath) +// { +// var expectedLines = File.ReadAllLines(baselinePath); +// var outputLines = File.ReadAllLines(outputPath); + +// var comparisonSb = new StringBuilder(); + +// // Start compare results +// var expectedLength = expectedLines.Length; +// var outputLength = outputLines.Length; +// var findDiffLength = Math.Min(expectedLength, outputLength); + +// // Find diff for each lines +// for (var lineNo = 0; lineNo < findDiffLength; lineNo++) +// { +// if (!expectedLines[lineNo].Equals(outputLines[lineNo])) +// { +// comparisonSb.AppendFormat("** DIFF at line {0} \n", lineNo); +// comparisonSb.AppendFormat("A : {0} \n", outputLines[lineNo]); +// comparisonSb.AppendFormat("E : {0} \n", expectedLines[lineNo]); +// } +// } + +// var startIndex = findDiffLength - 1; +// if (startIndex < 0) +// startIndex = 0; + +// if (findDiffLength < expectedLength) +// { +// comparisonSb.AppendFormat("** MISSING \n"); +// for (var lineNo = startIndex; lineNo < expectedLength; lineNo++) +// { +// comparisonSb.AppendFormat("{0} : {1}", lineNo, expectedLines[lineNo]); +// } +// } +// if (findDiffLength < outputLength) +// { +// comparisonSb.AppendFormat("** EXTRA \n"); +// for (var lineNo = startIndex; lineNo < outputLength; lineNo++) +// { +// comparisonSb.AppendFormat("{0} : {1}", lineNo, outputLines[lineNo]); +// } +// } + +// return comparisonSb.ToString(); +// } + +// private string AssemblyFilter(StreamWriter writer) +// { +// if (null == _outputBuilder) +// { +// _outputBuilder = new StringBuilder(); +// } +// _outputBuilder.Length = 0; + +// byte[] utf8 = ((MemoryStream)writer.BaseStream).ToArray(); +// string value = System.Text.Encoding.UTF8.GetString(utf8, 3, utf8.Length - 3); // skip 0xEF, 0xBB, 0xBF +// _outputBuilder.Append(value); +// AssemblyFilter(_outputBuilder); +// return _outputBuilder.ToString(); +// } + +// private void AssemblyFilter(StringBuilder builder) +// { +// string[] filter = _outputFilter; +// if (null == filter) +// { +// filter = new string[5]; +// string tmp = typeof(System.Guid).AssemblyQualifiedName; +// filter[0] = tmp.Substring(tmp.IndexOf(',')); +// filter[1] = filter[0].Replace("mscorlib", "System"); +// filter[2] = filter[0].Replace("mscorlib", "System.Data"); +// filter[3] = filter[0].Replace("mscorlib", "System.Data.OracleClient"); +// filter[4] = filter[0].Replace("mscorlib", "System.Xml"); +// _outputFilter = filter; +// } + +// for (int i = 0; i < filter.Length; ++i) +// { +// builder.Replace(filter[i], ""); +// } +// } + +// /// +// /// special wrapper for the text writer to replace single "\n" with "\n" +// /// +// private sealed class CarriageReturnLineFeedReplacer : TextWriter +// { +// private TextWriter _output; +// private int _lineFeedCount; +// private bool _hasCarriageReturn; + +// internal CarriageReturnLineFeedReplacer(TextWriter output) +// { +// if (output == null) +// throw new ArgumentNullException(nameof(output)); + +// _output = output; +// } + +// public int LineFeedCount +// { +// get { return _lineFeedCount; } +// } + +// public override Encoding Encoding +// { +// get { return _output.Encoding; } +// } + +// public override IFormatProvider FormatProvider +// { +// get { return _output.FormatProvider; } +// } + +// public override string NewLine +// { +// get { return _output.NewLine; } +// set { _output.NewLine = value; } +// } + +// protected override void Dispose(bool disposing) +// { +// if (disposing) +// { +// ((IDisposable)_output).Dispose(); +// } +// _output = null; +// } + +// public override void Flush() +// { +// _output.Flush(); +// } + +// public override void Write(char value) +// { +// if ('\n' == value) +// { +// _lineFeedCount++; +// if (!_hasCarriageReturn) +// { // X'\n'Y -> X'\r\n'Y +// _output.Write('\r'); +// } +// } +// _hasCarriageReturn = '\r' == value; +// _output.Write(value); +// } +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/ProviderAgnostic/ReaderTest/ReaderTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/ProviderAgnostic/ReaderTest/ReaderTest.cs index 5d09be77f4..0333bb1998 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/ProviderAgnostic/ReaderTest/ReaderTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/ProviderAgnostic/ReaderTest/ReaderTest.cs @@ -1,468 +1,468 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Data.Common; -using System.IO; -using System.Text; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ - public static class ReaderTest - { - // TODO Synapse: Remove dependency from Northwind database - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public static void TestMain() - { - string connectionString = DataTestUtility.TCPConnectionString; - - string tempTable = DataTestUtility.GetUniqueNameForSqlServer("table"); - - DbProviderFactory provider = SqlClientFactory.Instance; - try - { - using (DbConnection con = provider.CreateConnection()) - { - con.ConnectionString = connectionString; - con.Open(); - - using (DbCommand cmd = provider.CreateCommand()) - { - cmd.Connection = con; - DbTransaction tx; - - #region <> - cmd.CommandText = "SELECT LastName, FirstName, Title, Address, City, Region, PostalCode, Country into " + tempTable + " from Employees where EmployeeID=0"; - cmd.ExecuteNonQuery(); - - #endregion - - tx = con.BeginTransaction(); - cmd.Transaction = tx; - - cmd.CommandText = "insert into " + tempTable + "(LastName, FirstName, Title, Address, City, Region, PostalCode, Country) values ('Doe', 'Jane' , 'Ms.', 'One Microsoft Way', 'Redmond', 'WA', '98052', 'USA')"; - cmd.ExecuteNonQuery(); - cmd.CommandText = "insert into " + tempTable + "(LastName, FirstName, Title, Address, City, Region, PostalCode, Country) values ('Doe', 'John' , 'Mr.', NULL, NULL, NULL, NULL, NULL)"; - cmd.ExecuteNonQuery(); - - tx.Commit(); - - cmd.Transaction = null; - string parameterName = "@p1"; - DbParameter p1 = cmd.CreateParameter(); - p1.ParameterName = parameterName; - p1.Value = "Doe"; - cmd.Parameters.Add(p1); - - cmd.CommandText = "select * from " + tempTable + " where LastName = " + parameterName; - - // Test GetValue + IsDBNull - using (DbDataReader rdr = cmd.ExecuteReader()) - { - StringBuilder actualResult = new StringBuilder(); - int currentValue = 0; - string[] expectedValues = - { - "Doe,Jane,Ms.,One Microsoft Way,Redmond,WA,98052,USA", - "Doe,John,Mr.,(NULL),(NULL),(NULL),(NULL),(NULL)" - }; - - while (rdr.Read()) - { - Assert.True(currentValue < expectedValues.Length, "ERROR: Received more values than expected"); - - for (int i = 0; i < rdr.FieldCount; i++) - { - if (i > 0) - { - actualResult.Append(","); - } - if (rdr.IsDBNull(i)) - { - actualResult.Append("(NULL)"); - } - else - { - actualResult.Append(rdr.GetValue(i)); - } - } - - DataTestUtility.AssertEqualsWithDescription(expectedValues[currentValue++], actualResult.ToString(), "FAILED: Did not receive expected data"); - actualResult.Clear(); - } - } - - // Test GetFieldValue + IsDBNull - using (DbDataReader rdr = cmd.ExecuteReader()) - { - StringBuilder actualResult = new StringBuilder(); - int currentValue = 0; - string[] expectedValues = - { - "Doe,Jane,Ms.,One Microsoft Way,Redmond,WA,98052,USA", - "Doe,John,Mr.,(NULL),(NULL),(NULL),(NULL),(NULL)" - }; - - while (rdr.Read()) - { - Assert.True(currentValue < expectedValues.Length, "ERROR: Received more values than expected"); - - for (int i = 0; i < rdr.FieldCount; i++) - { - if (i > 0) - { - actualResult.Append(","); - } - if (rdr.IsDBNull(i)) - { - actualResult.Append("(NULL)"); - } - else - { - if (rdr.GetFieldType(i) == typeof(bool)) - { - actualResult.Append(rdr.GetFieldValue(i)); - } - else if (rdr.GetFieldType(i) == typeof(decimal)) - { - actualResult.Append(rdr.GetFieldValue(i)); - } - else if (rdr.GetFieldType(i) == typeof(int)) - { - actualResult.Append(rdr.GetFieldValue(i)); - } - else - { - actualResult.Append(rdr.GetFieldValue(i)); - } - } - } - - DataTestUtility.AssertEqualsWithDescription(expectedValues[currentValue++], actualResult.ToString(), "FAILED: Did not receive expected data"); - actualResult.Clear(); - } - } - - // Test GetFieldValueAsync + IsDBNullAsync - using (DbDataReader rdr = cmd.ExecuteReaderAsync().Result) - { - StringBuilder actualResult = new StringBuilder(); - int currentValue = 0; - string[] expectedValues = - { - "Doe,Jane,Ms.,One Microsoft Way,Redmond,WA,98052,USA", - "Doe,John,Mr.,(NULL),(NULL),(NULL),(NULL),(NULL)" - }; - - while (rdr.ReadAsync().Result) - { - Assert.True(currentValue < expectedValues.Length, "ERROR: Received more values than expected"); - - for (int i = 0; i < rdr.FieldCount; i++) - { - if (i > 0) - { - actualResult.Append(","); - } - if (rdr.IsDBNullAsync(i).Result) - { - actualResult.Append("(NULL)"); - } - else - { - if (rdr.GetFieldType(i) == typeof(bool)) - { - actualResult.Append(rdr.GetFieldValueAsync(i).Result); - } - else if (rdr.GetFieldType(i) == typeof(decimal)) - { - actualResult.Append(rdr.GetFieldValueAsync(i).Result); - } - else if (rdr.GetFieldType(i) == typeof(int)) - { - actualResult.Append(rdr.GetFieldValue(i)); - } - else - { - actualResult.Append(rdr.GetFieldValueAsync(i).Result); - } - } - } - - DataTestUtility.AssertEqualsWithDescription(expectedValues[currentValue++], actualResult.ToString(), "FAILED: Did not receive expected data"); - actualResult.Clear(); - } - } - } - - // GetStream - byte[] correctBytes = { 0x12, 0x34, 0x56, 0x78 }; - string queryString; - string correctBytesAsString = "0x12345678"; - queryString = string.Format("SELECT CAST({0} AS BINARY(20)), CAST({0} AS IMAGE), CAST({0} AS VARBINARY(20))", correctBytesAsString); - using (var command = provider.CreateCommand()) - { - command.CommandText = queryString; - command.Connection = con; - using (var reader = command.ExecuteReader()) - { - reader.Read(); - for (int i = 0; i < reader.FieldCount; i++) - { - byte[] buffer = new byte[256]; - Stream stream = reader.GetStream(i); - int bytesRead = stream.Read(buffer, 0, buffer.Length); - for (int j = 0; j < correctBytes.Length; j++) - { - Assert.True(correctBytes[j] == buffer[j], "ERROR: Bytes do not match"); - } - } - } - } - - // GetTextReader - string[] correctStrings = { "Hello World", "\uFF8A\uFF9B\uFF70\uFF9C\uFF70\uFF99\uFF84\uFF9E" }; - string[] collations = { "Latin1_General_CI_AS", "Japanese_CI_AS" }; - - for (int j = 0; j < collations.Length; j++) - { - string substring = string.Format("(N'{0}' COLLATE {1})", correctStrings[j], collations[j]); - queryString = string.Format("SELECT CAST({0} AS CHAR(20)), CAST({0} AS NCHAR(20)), CAST({0} AS NTEXT), CAST({0} AS NVARCHAR(20)), CAST({0} AS TEXT), CAST({0} AS VARCHAR(20))", substring); - using (var command = provider.CreateCommand()) - { - command.CommandText = queryString; - command.Connection = con; - using (var reader = command.ExecuteReader()) - { - reader.Read(); - for (int i = 0; i < reader.FieldCount; i++) - { - char[] buffer = new char[256]; - TextReader textReader = reader.GetTextReader(i); - int charsRead = textReader.Read(buffer, 0, buffer.Length); - string stringRead = new string(buffer, 0, charsRead); - - Assert.True(stringRead == (string)reader.GetValue(i), "ERROR: Strings to not match"); - } - } - } - } - } - } - finally - { - using (DbConnection con = provider.CreateConnection()) - { - con.ConnectionString = connectionString; - con.Open(); - - using (DbCommand cmd = provider.CreateCommand()) - { - cmd.Connection = con; - cmd.CommandText = "drop table " + tempTable; - cmd.ExecuteNonQuery(); - } - } - } - } - - /// - /// Covers GetFieldValue for SqlBuffer class - /// - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public static void SqlDataReader_SqlBuffer_GetFieldValue() - { - string tableName = DataTestUtility.GetUniqueNameForSqlServer("SqlBuffer_GetFieldValue"); - DateTimeOffset dtoffset = DateTimeOffset.Now; - DateTime dt = DateTime.Now; - //Exclude the millisecond because of rounding at some points by SQL Server. - DateTime dateTime = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second); - //Arrange - DbProviderFactory provider = SqlClientFactory.Instance; - - using DbConnection con = provider.CreateConnection(); - con.ConnectionString = DataTestUtility.TCPConnectionString; - con.Open(); - string sqlQueryOne = $"CREATE TABLE {tableName} ([CustomerId] [int],[FirstName] [nvarchar](50),[BoolCol] [BIT],[ShortCol] [SMALLINT],[ByteCol] [TINYINT],[LongCol] [BIGINT]);"; - string sqlQueryTwo = $"ALTER TABLE {tableName} ADD [DoubleCol] [FLOAT],[SingleCol] [REAL],[GUIDCol] [uniqueidentifier],[DateTimeCol] [DateTime],[DecimalCol] [SmallMoney],[DateTimeOffsetCol] [DateTimeOffset], [DateCol] [Date], [TimeCol] [Time];"; - - try - { - using (DbCommand command = provider.CreateCommand()) - { - command.Connection = con; - command.CommandText = sqlQueryOne; - command.ExecuteNonQuery(); - } - using (DbCommand command = provider.CreateCommand()) - { - command.Connection = con; - command.CommandText = sqlQueryTwo; - command.ExecuteNonQuery(); - } - - System.Data.SqlTypes.SqlGuid sqlguid = new System.Data.SqlTypes.SqlGuid(Guid.NewGuid()); - - using (SqlCommand sqlCommand = new SqlCommand("", con as SqlConnection)) - { - sqlCommand.CommandText = $"INSERT INTO {tableName} " - + "VALUES (@CustomerId,@FirstName,@BoolCol,@ShortCol,@ByteCol,@LongCol,@DoubleCol,@SingleCol" - + ",@GUIDCol,@DateTimeCol,@DecimalCol,@DateTimeOffsetCol,@DateCol,@TimeCol)"; - sqlCommand.Parameters.AddWithValue(@"CustomerId", 1); - sqlCommand.Parameters.AddWithValue(@"FirstName", "Microsoft"); - sqlCommand.Parameters.AddWithValue(@"BoolCol", true); - sqlCommand.Parameters.AddWithValue(@"ShortCol", 3274); - sqlCommand.Parameters.AddWithValue(@"ByteCol", 253); - sqlCommand.Parameters.AddWithValue(@"LongCol", 922222222222); - sqlCommand.Parameters.AddWithValue(@"DoubleCol", 10.7); - sqlCommand.Parameters.AddWithValue(@"SingleCol", 123.546f); - sqlCommand.Parameters.AddWithValue(@"GUIDCol", sqlguid); - sqlCommand.Parameters.AddWithValue(@"DateTimeCol", dateTime); - sqlCommand.Parameters.AddWithValue(@"DecimalCol", 280); - sqlCommand.Parameters.AddWithValue(@"DateTimeOffsetCol", dtoffset); - sqlCommand.Parameters.AddWithValue(@"DateCol", new DateTime(2022, 10, 23)); - sqlCommand.Parameters.AddWithValue(@"TimeCol", new TimeSpan(0, 22, 7, 44)); - sqlCommand.ExecuteNonQuery(); - } - using (SqlCommand sqlCommand = new SqlCommand("", con as SqlConnection)) - { - sqlCommand.CommandText = "select top 1 * from " + tableName; - using (DbDataReader reader = sqlCommand.ExecuteReader()) - { - Assert.True(reader.Read()); - Assert.Equal(1, reader.GetFieldValue(0)); - Assert.Equal("Microsoft", reader.GetFieldValue(1)); - Assert.True(reader.GetFieldValue(2)); - Assert.Equal(3274, reader.GetFieldValue(3)); - Assert.Equal(253, reader.GetFieldValue(4)); - Assert.Equal(922222222222, reader.GetFieldValue(5)); - Assert.Equal(10.7, reader.GetFieldValue(6)); - Assert.Equal(123.546f, reader.GetFieldValue(7)); - Assert.Equal(sqlguid, reader.GetFieldValue(8)); - Assert.Equal(sqlguid.Value, reader.GetFieldValue(8).Value); - Assert.Equal(dateTime.ToString("dd/MM/yyyy HH:mm:ss.fff"), reader.GetFieldValue(9).ToString("dd/MM/yyyy HH:mm:ss.fff")); - Assert.Equal(280, reader.GetFieldValue(10)); - Assert.Equal(dtoffset, reader.GetFieldValue(11)); - Assert.Equal(new DateTime(2022, 10, 23), reader.GetFieldValue(12)); - Assert.Equal(new TimeSpan(0, 22, 7, 44), reader.GetFieldValue(13)); -#if NET6_0_OR_GREATER - Assert.Equal(new DateOnly(2022, 10, 23), reader.GetFieldValue(12)); - Assert.Equal(new TimeOnly(22, 7, 44), reader.GetFieldValue(13)); -#endif - } - } - } - finally - { - //cleanup - using (DbCommand cmd = provider.CreateCommand()) - { - cmd.Connection = con; - cmd.CommandText = "drop table " + tableName; - cmd.ExecuteNonQuery(); - } - } - } - -#if NET6_0_OR_GREATER - /// - /// Covers GetFieldValue for SqlBuffer class - /// - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public static async Task SqlDataReader_SqlBuffer_GetFieldValue_Async() - { - string tableName = DataTestUtility.GetUniqueNameForSqlServer("SqlBuffer_GetFieldValue_Async"); - DateTimeOffset dtoffset = DateTimeOffset.Now; - DateTime dt = DateTime.Now; - //Exclude the millisecond because of rounding at some points by SQL Server. - DateTime dateTime = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second); - //Arrange - DbProviderFactory provider = SqlClientFactory.Instance; - - using DbConnection con = provider.CreateConnection(); - con.ConnectionString = DataTestUtility.TCPConnectionString; - con.Open(); - string sqlQueryOne = $"CREATE TABLE {tableName} ([CustomerId] [int],[FirstName] [nvarchar](50),[BoolCol] [BIT],[ShortCol] [SMALLINT],[ByteCol] [TINYINT],[LongCol] [BIGINT]);"; - string sqlQueryTwo = $"ALTER TABLE {tableName} ADD [DoubleCol] [FLOAT],[SingleCol] [REAL],[GUIDCol] [uniqueidentifier],[DateTimeCol] [DateTime],[DecimalCol] [SmallMoney],[DateTimeOffsetCol] [DateTimeOffset], [DateCol] [Date], [TimeCol] [Time];"; - - try - { - using (DbCommand command = provider.CreateCommand()) - { - command.Connection = con; - command.CommandText = sqlQueryOne; - await command.ExecuteNonQueryAsync(); - } - using (DbCommand command = provider.CreateCommand()) - { - command.Connection = con; - command.CommandText = sqlQueryTwo; - await command.ExecuteNonQueryAsync(); - } - - System.Data.SqlTypes.SqlGuid sqlguid = new System.Data.SqlTypes.SqlGuid(Guid.NewGuid()); - - using (SqlCommand sqlCommand = new SqlCommand("", con as SqlConnection)) - { - sqlCommand.CommandText = $"INSERT INTO {tableName} " - + "VALUES (@CustomerId,@FirstName,@BoolCol,@ShortCol,@ByteCol,@LongCol,@DoubleCol,@SingleCol" - + ",@GUIDCol,@DateTimeCol,@DecimalCol,@DateTimeOffsetCol,@DateCol,@TimeCol)"; - sqlCommand.Parameters.AddWithValue(@"CustomerId", 1); - sqlCommand.Parameters.AddWithValue(@"FirstName", "Microsoft"); - sqlCommand.Parameters.AddWithValue(@"BoolCol", true); - sqlCommand.Parameters.AddWithValue(@"ShortCol", 3274); - sqlCommand.Parameters.AddWithValue(@"ByteCol", 253); - sqlCommand.Parameters.AddWithValue(@"LongCol", 922222222222); - sqlCommand.Parameters.AddWithValue(@"DoubleCol", 10.7); - sqlCommand.Parameters.AddWithValue(@"SingleCol", 123.546f); - sqlCommand.Parameters.AddWithValue(@"GUIDCol", sqlguid); - sqlCommand.Parameters.AddWithValue(@"DateTimeCol", dateTime); - sqlCommand.Parameters.AddWithValue(@"DecimalCol", 280); - sqlCommand.Parameters.AddWithValue(@"DateTimeOffsetCol", dtoffset); - sqlCommand.Parameters.AddWithValue(@"DateCol", new DateOnly(2022, 10, 23)); - sqlCommand.Parameters.AddWithValue(@"TimeCol", new TimeOnly(22, 7, 44)); - await sqlCommand.ExecuteNonQueryAsync(); - } - using (SqlCommand sqlCommand = new SqlCommand("", con as SqlConnection)) - { - sqlCommand.CommandText = "select top 1 * from " + tableName; - using (DbDataReader reader = await sqlCommand.ExecuteReaderAsync()) - { - Assert.True(reader.Read()); - Assert.Equal(1, await reader.GetFieldValueAsync(0)); - Assert.Equal("Microsoft", await reader.GetFieldValueAsync(1)); - Assert.True(await reader.GetFieldValueAsync(2)); - Assert.Equal(3274, await reader.GetFieldValueAsync(3)); - Assert.Equal(253, await reader.GetFieldValueAsync(4)); - Assert.Equal(922222222222, await reader.GetFieldValueAsync(5)); - Assert.Equal(10.7, await reader.GetFieldValueAsync(6)); - Assert.Equal(123.546f, await reader.GetFieldValueAsync(7)); - Assert.Equal(sqlguid, await reader.GetFieldValueAsync(8)); - Assert.Equal(sqlguid.Value, (await reader.GetFieldValueAsync(8)).Value); - Assert.Equal(dateTime.ToString("dd/MM/yyyy HH:mm:ss.fff"), (await reader.GetFieldValueAsync(9)).ToString("dd/MM/yyyy HH:mm:ss.fff")); - Assert.Equal(280, await reader.GetFieldValueAsync(10)); - Assert.Equal(dtoffset, await reader.GetFieldValueAsync(11)); - Assert.Equal(new DateTime(2022, 10, 23), await reader.GetFieldValueAsync(12)); - Assert.Equal(new TimeSpan(0, 22, 7, 44), await reader.GetFieldValueAsync(13)); - Assert.Equal(new DateOnly(2022, 10, 23), await reader.GetFieldValueAsync(12)); - Assert.Equal(new TimeOnly(22, 7, 44), await reader.GetFieldValueAsync(13)); - } - } - } - finally - { - //cleanup - using (DbCommand cmd = provider.CreateCommand()) - { - cmd.Connection = con; - cmd.CommandText = "drop table " + tableName; - await cmd.ExecuteNonQueryAsync(); - } - } - } -#endif - } -} +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. + +//using System; +//using System.Data.Common; +//using System.IO; +//using System.Text; +//using System.Threading.Tasks; +//using Xunit; + +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ +// public static class ReaderTest +// { +// // TODO Synapse: Remove dependency from Northwind database +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public static void TestMain() +// { +// string connectionString = DataTestUtility.TCPConnectionString; + +// string tempTable = DataTestUtility.GetUniqueNameForSqlServer("table"); + +// DbProviderFactory provider = SqlClientFactory.Instance; +// try +// { +// using (DbConnection con = provider.CreateConnection()) +// { +// con.ConnectionString = connectionString; +// con.Open(); + +// using (DbCommand cmd = provider.CreateCommand()) +// { +// cmd.Connection = con; +// DbTransaction tx; + +// #region <> +// cmd.CommandText = "SELECT LastName, FirstName, Title, Address, City, Region, PostalCode, Country into " + tempTable + " from Employees where EmployeeID=0"; +// cmd.ExecuteNonQuery(); + +// #endregion + +// tx = con.BeginTransaction(); +// cmd.Transaction = tx; + +// cmd.CommandText = "insert into " + tempTable + "(LastName, FirstName, Title, Address, City, Region, PostalCode, Country) values ('Doe', 'Jane' , 'Ms.', 'One Microsoft Way', 'Redmond', 'WA', '98052', 'USA')"; +// cmd.ExecuteNonQuery(); +// cmd.CommandText = "insert into " + tempTable + "(LastName, FirstName, Title, Address, City, Region, PostalCode, Country) values ('Doe', 'John' , 'Mr.', NULL, NULL, NULL, NULL, NULL)"; +// cmd.ExecuteNonQuery(); + +// tx.Commit(); + +// cmd.Transaction = null; +// string parameterName = "@p1"; +// DbParameter p1 = cmd.CreateParameter(); +// p1.ParameterName = parameterName; +// p1.Value = "Doe"; +// cmd.Parameters.Add(p1); + +// cmd.CommandText = "select * from " + tempTable + " where LastName = " + parameterName; + +// // Test GetValue + IsDBNull +// using (DbDataReader rdr = cmd.ExecuteReader()) +// { +// StringBuilder actualResult = new StringBuilder(); +// int currentValue = 0; +// string[] expectedValues = +// { +// "Doe,Jane,Ms.,One Microsoft Way,Redmond,WA,98052,USA", +// "Doe,John,Mr.,(NULL),(NULL),(NULL),(NULL),(NULL)" +// }; + +// while (rdr.Read()) +// { +// Assert.True(currentValue < expectedValues.Length, "ERROR: Received more values than expected"); + +// for (int i = 0; i < rdr.FieldCount; i++) +// { +// if (i > 0) +// { +// actualResult.Append(","); +// } +// if (rdr.IsDBNull(i)) +// { +// actualResult.Append("(NULL)"); +// } +// else +// { +// actualResult.Append(rdr.GetValue(i)); +// } +// } + +// DataTestUtility.AssertEqualsWithDescription(expectedValues[currentValue++], actualResult.ToString(), "FAILED: Did not receive expected data"); +// actualResult.Clear(); +// } +// } + +// // Test GetFieldValue + IsDBNull +// using (DbDataReader rdr = cmd.ExecuteReader()) +// { +// StringBuilder actualResult = new StringBuilder(); +// int currentValue = 0; +// string[] expectedValues = +// { +// "Doe,Jane,Ms.,One Microsoft Way,Redmond,WA,98052,USA", +// "Doe,John,Mr.,(NULL),(NULL),(NULL),(NULL),(NULL)" +// }; + +// while (rdr.Read()) +// { +// Assert.True(currentValue < expectedValues.Length, "ERROR: Received more values than expected"); + +// for (int i = 0; i < rdr.FieldCount; i++) +// { +// if (i > 0) +// { +// actualResult.Append(","); +// } +// if (rdr.IsDBNull(i)) +// { +// actualResult.Append("(NULL)"); +// } +// else +// { +// if (rdr.GetFieldType(i) == typeof(bool)) +// { +// actualResult.Append(rdr.GetFieldValue(i)); +// } +// else if (rdr.GetFieldType(i) == typeof(decimal)) +// { +// actualResult.Append(rdr.GetFieldValue(i)); +// } +// else if (rdr.GetFieldType(i) == typeof(int)) +// { +// actualResult.Append(rdr.GetFieldValue(i)); +// } +// else +// { +// actualResult.Append(rdr.GetFieldValue(i)); +// } +// } +// } + +// DataTestUtility.AssertEqualsWithDescription(expectedValues[currentValue++], actualResult.ToString(), "FAILED: Did not receive expected data"); +// actualResult.Clear(); +// } +// } + +// // Test GetFieldValueAsync + IsDBNullAsync +// using (DbDataReader rdr = cmd.ExecuteReaderAsync().Result) +// { +// StringBuilder actualResult = new StringBuilder(); +// int currentValue = 0; +// string[] expectedValues = +// { +// "Doe,Jane,Ms.,One Microsoft Way,Redmond,WA,98052,USA", +// "Doe,John,Mr.,(NULL),(NULL),(NULL),(NULL),(NULL)" +// }; + +// while (rdr.ReadAsync().Result) +// { +// Assert.True(currentValue < expectedValues.Length, "ERROR: Received more values than expected"); + +// for (int i = 0; i < rdr.FieldCount; i++) +// { +// if (i > 0) +// { +// actualResult.Append(","); +// } +// if (rdr.IsDBNullAsync(i).Result) +// { +// actualResult.Append("(NULL)"); +// } +// else +// { +// if (rdr.GetFieldType(i) == typeof(bool)) +// { +// actualResult.Append(rdr.GetFieldValueAsync(i).Result); +// } +// else if (rdr.GetFieldType(i) == typeof(decimal)) +// { +// actualResult.Append(rdr.GetFieldValueAsync(i).Result); +// } +// else if (rdr.GetFieldType(i) == typeof(int)) +// { +// actualResult.Append(rdr.GetFieldValue(i)); +// } +// else +// { +// actualResult.Append(rdr.GetFieldValueAsync(i).Result); +// } +// } +// } + +// DataTestUtility.AssertEqualsWithDescription(expectedValues[currentValue++], actualResult.ToString(), "FAILED: Did not receive expected data"); +// actualResult.Clear(); +// } +// } +// } + +// // GetStream +// byte[] correctBytes = { 0x12, 0x34, 0x56, 0x78 }; +// string queryString; +// string correctBytesAsString = "0x12345678"; +// queryString = string.Format("SELECT CAST({0} AS BINARY(20)), CAST({0} AS IMAGE), CAST({0} AS VARBINARY(20))", correctBytesAsString); +// using (var command = provider.CreateCommand()) +// { +// command.CommandText = queryString; +// command.Connection = con; +// using (var reader = command.ExecuteReader()) +// { +// reader.Read(); +// for (int i = 0; i < reader.FieldCount; i++) +// { +// byte[] buffer = new byte[256]; +// Stream stream = reader.GetStream(i); +// int bytesRead = stream.Read(buffer, 0, buffer.Length); +// for (int j = 0; j < correctBytes.Length; j++) +// { +// Assert.True(correctBytes[j] == buffer[j], "ERROR: Bytes do not match"); +// } +// } +// } +// } + +// // GetTextReader +// string[] correctStrings = { "Hello World", "\uFF8A\uFF9B\uFF70\uFF9C\uFF70\uFF99\uFF84\uFF9E" }; +// string[] collations = { "Latin1_General_CI_AS", "Japanese_CI_AS" }; + +// for (int j = 0; j < collations.Length; j++) +// { +// string substring = string.Format("(N'{0}' COLLATE {1})", correctStrings[j], collations[j]); +// queryString = string.Format("SELECT CAST({0} AS CHAR(20)), CAST({0} AS NCHAR(20)), CAST({0} AS NTEXT), CAST({0} AS NVARCHAR(20)), CAST({0} AS TEXT), CAST({0} AS VARCHAR(20))", substring); +// using (var command = provider.CreateCommand()) +// { +// command.CommandText = queryString; +// command.Connection = con; +// using (var reader = command.ExecuteReader()) +// { +// reader.Read(); +// for (int i = 0; i < reader.FieldCount; i++) +// { +// char[] buffer = new char[256]; +// TextReader textReader = reader.GetTextReader(i); +// int charsRead = textReader.Read(buffer, 0, buffer.Length); +// string stringRead = new string(buffer, 0, charsRead); + +// Assert.True(stringRead == (string)reader.GetValue(i), "ERROR: Strings to not match"); +// } +// } +// } +// } +// } +// } +// finally +// { +// using (DbConnection con = provider.CreateConnection()) +// { +// con.ConnectionString = connectionString; +// con.Open(); + +// using (DbCommand cmd = provider.CreateCommand()) +// { +// cmd.Connection = con; +// cmd.CommandText = "drop table " + tempTable; +// cmd.ExecuteNonQuery(); +// } +// } +// } +// } + +// /// +// /// Covers GetFieldValue for SqlBuffer class +// /// +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public static void SqlDataReader_SqlBuffer_GetFieldValue() +// { +// string tableName = DataTestUtility.GetUniqueNameForSqlServer("SqlBuffer_GetFieldValue"); +// DateTimeOffset dtoffset = DateTimeOffset.Now; +// DateTime dt = DateTime.Now; +// //Exclude the millisecond because of rounding at some points by SQL Server. +// DateTime dateTime = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second); +// //Arrange +// DbProviderFactory provider = SqlClientFactory.Instance; + +// using DbConnection con = provider.CreateConnection(); +// con.ConnectionString = DataTestUtility.TCPConnectionString; +// con.Open(); +// string sqlQueryOne = $"CREATE TABLE {tableName} ([CustomerId] [int],[FirstName] [nvarchar](50),[BoolCol] [BIT],[ShortCol] [SMALLINT],[ByteCol] [TINYINT],[LongCol] [BIGINT]);"; +// string sqlQueryTwo = $"ALTER TABLE {tableName} ADD [DoubleCol] [FLOAT],[SingleCol] [REAL],[GUIDCol] [uniqueidentifier],[DateTimeCol] [DateTime],[DecimalCol] [SmallMoney],[DateTimeOffsetCol] [DateTimeOffset], [DateCol] [Date], [TimeCol] [Time];"; + +// try +// { +// using (DbCommand command = provider.CreateCommand()) +// { +// command.Connection = con; +// command.CommandText = sqlQueryOne; +// command.ExecuteNonQuery(); +// } +// using (DbCommand command = provider.CreateCommand()) +// { +// command.Connection = con; +// command.CommandText = sqlQueryTwo; +// command.ExecuteNonQuery(); +// } + +// System.Data.SqlTypes.SqlGuid sqlguid = new System.Data.SqlTypes.SqlGuid(Guid.NewGuid()); + +// using (SqlCommand sqlCommand = new SqlCommand("", con as SqlConnection)) +// { +// sqlCommand.CommandText = $"INSERT INTO {tableName} " +// + "VALUES (@CustomerId,@FirstName,@BoolCol,@ShortCol,@ByteCol,@LongCol,@DoubleCol,@SingleCol" +// + ",@GUIDCol,@DateTimeCol,@DecimalCol,@DateTimeOffsetCol,@DateCol,@TimeCol)"; +// sqlCommand.Parameters.AddWithValue(@"CustomerId", 1); +// sqlCommand.Parameters.AddWithValue(@"FirstName", "Microsoft"); +// sqlCommand.Parameters.AddWithValue(@"BoolCol", true); +// sqlCommand.Parameters.AddWithValue(@"ShortCol", 3274); +// sqlCommand.Parameters.AddWithValue(@"ByteCol", 253); +// sqlCommand.Parameters.AddWithValue(@"LongCol", 922222222222); +// sqlCommand.Parameters.AddWithValue(@"DoubleCol", 10.7); +// sqlCommand.Parameters.AddWithValue(@"SingleCol", 123.546f); +// sqlCommand.Parameters.AddWithValue(@"GUIDCol", sqlguid); +// sqlCommand.Parameters.AddWithValue(@"DateTimeCol", dateTime); +// sqlCommand.Parameters.AddWithValue(@"DecimalCol", 280); +// sqlCommand.Parameters.AddWithValue(@"DateTimeOffsetCol", dtoffset); +// sqlCommand.Parameters.AddWithValue(@"DateCol", new DateTime(2022, 10, 23)); +// sqlCommand.Parameters.AddWithValue(@"TimeCol", new TimeSpan(0, 22, 7, 44)); +// sqlCommand.ExecuteNonQuery(); +// } +// using (SqlCommand sqlCommand = new SqlCommand("", con as SqlConnection)) +// { +// sqlCommand.CommandText = "select top 1 * from " + tableName; +// using (DbDataReader reader = sqlCommand.ExecuteReader()) +// { +// Assert.True(reader.Read()); +// Assert.Equal(1, reader.GetFieldValue(0)); +// Assert.Equal("Microsoft", reader.GetFieldValue(1)); +// Assert.True(reader.GetFieldValue(2)); +// Assert.Equal(3274, reader.GetFieldValue(3)); +// Assert.Equal(253, reader.GetFieldValue(4)); +// Assert.Equal(922222222222, reader.GetFieldValue(5)); +// Assert.Equal(10.7, reader.GetFieldValue(6)); +// Assert.Equal(123.546f, reader.GetFieldValue(7)); +// Assert.Equal(sqlguid, reader.GetFieldValue(8)); +// Assert.Equal(sqlguid.Value, reader.GetFieldValue(8).Value); +// Assert.Equal(dateTime.ToString("dd/MM/yyyy HH:mm:ss.fff"), reader.GetFieldValue(9).ToString("dd/MM/yyyy HH:mm:ss.fff")); +// Assert.Equal(280, reader.GetFieldValue(10)); +// Assert.Equal(dtoffset, reader.GetFieldValue(11)); +// Assert.Equal(new DateTime(2022, 10, 23), reader.GetFieldValue(12)); +// Assert.Equal(new TimeSpan(0, 22, 7, 44), reader.GetFieldValue(13)); +//#if NET6_0_OR_GREATER +// Assert.Equal(new DateOnly(2022, 10, 23), reader.GetFieldValue(12)); +// Assert.Equal(new TimeOnly(22, 7, 44), reader.GetFieldValue(13)); +//#endif +// } +// } +// } +// finally +// { +// //cleanup +// using (DbCommand cmd = provider.CreateCommand()) +// { +// cmd.Connection = con; +// cmd.CommandText = "drop table " + tableName; +// cmd.ExecuteNonQuery(); +// } +// } +// } + +//#if NET6_0_OR_GREATER +// /// +// /// Covers GetFieldValue for SqlBuffer class +// /// +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public static async Task SqlDataReader_SqlBuffer_GetFieldValue_Async() +// { +// string tableName = DataTestUtility.GetUniqueNameForSqlServer("SqlBuffer_GetFieldValue_Async"); +// DateTimeOffset dtoffset = DateTimeOffset.Now; +// DateTime dt = DateTime.Now; +// //Exclude the millisecond because of rounding at some points by SQL Server. +// DateTime dateTime = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second); +// //Arrange +// DbProviderFactory provider = SqlClientFactory.Instance; + +// using DbConnection con = provider.CreateConnection(); +// con.ConnectionString = DataTestUtility.TCPConnectionString; +// con.Open(); +// string sqlQueryOne = $"CREATE TABLE {tableName} ([CustomerId] [int],[FirstName] [nvarchar](50),[BoolCol] [BIT],[ShortCol] [SMALLINT],[ByteCol] [TINYINT],[LongCol] [BIGINT]);"; +// string sqlQueryTwo = $"ALTER TABLE {tableName} ADD [DoubleCol] [FLOAT],[SingleCol] [REAL],[GUIDCol] [uniqueidentifier],[DateTimeCol] [DateTime],[DecimalCol] [SmallMoney],[DateTimeOffsetCol] [DateTimeOffset], [DateCol] [Date], [TimeCol] [Time];"; + +// try +// { +// using (DbCommand command = provider.CreateCommand()) +// { +// command.Connection = con; +// command.CommandText = sqlQueryOne; +// await command.ExecuteNonQueryAsync(); +// } +// using (DbCommand command = provider.CreateCommand()) +// { +// command.Connection = con; +// command.CommandText = sqlQueryTwo; +// await command.ExecuteNonQueryAsync(); +// } + +// System.Data.SqlTypes.SqlGuid sqlguid = new System.Data.SqlTypes.SqlGuid(Guid.NewGuid()); + +// using (SqlCommand sqlCommand = new SqlCommand("", con as SqlConnection)) +// { +// sqlCommand.CommandText = $"INSERT INTO {tableName} " +// + "VALUES (@CustomerId,@FirstName,@BoolCol,@ShortCol,@ByteCol,@LongCol,@DoubleCol,@SingleCol" +// + ",@GUIDCol,@DateTimeCol,@DecimalCol,@DateTimeOffsetCol,@DateCol,@TimeCol)"; +// sqlCommand.Parameters.AddWithValue(@"CustomerId", 1); +// sqlCommand.Parameters.AddWithValue(@"FirstName", "Microsoft"); +// sqlCommand.Parameters.AddWithValue(@"BoolCol", true); +// sqlCommand.Parameters.AddWithValue(@"ShortCol", 3274); +// sqlCommand.Parameters.AddWithValue(@"ByteCol", 253); +// sqlCommand.Parameters.AddWithValue(@"LongCol", 922222222222); +// sqlCommand.Parameters.AddWithValue(@"DoubleCol", 10.7); +// sqlCommand.Parameters.AddWithValue(@"SingleCol", 123.546f); +// sqlCommand.Parameters.AddWithValue(@"GUIDCol", sqlguid); +// sqlCommand.Parameters.AddWithValue(@"DateTimeCol", dateTime); +// sqlCommand.Parameters.AddWithValue(@"DecimalCol", 280); +// sqlCommand.Parameters.AddWithValue(@"DateTimeOffsetCol", dtoffset); +// sqlCommand.Parameters.AddWithValue(@"DateCol", new DateOnly(2022, 10, 23)); +// sqlCommand.Parameters.AddWithValue(@"TimeCol", new TimeOnly(22, 7, 44)); +// await sqlCommand.ExecuteNonQueryAsync(); +// } +// using (SqlCommand sqlCommand = new SqlCommand("", con as SqlConnection)) +// { +// sqlCommand.CommandText = "select top 1 * from " + tableName; +// using (DbDataReader reader = await sqlCommand.ExecuteReaderAsync()) +// { +// Assert.True(reader.Read()); +// Assert.Equal(1, await reader.GetFieldValueAsync(0)); +// Assert.Equal("Microsoft", await reader.GetFieldValueAsync(1)); +// Assert.True(await reader.GetFieldValueAsync(2)); +// Assert.Equal(3274, await reader.GetFieldValueAsync(3)); +// Assert.Equal(253, await reader.GetFieldValueAsync(4)); +// Assert.Equal(922222222222, await reader.GetFieldValueAsync(5)); +// Assert.Equal(10.7, await reader.GetFieldValueAsync(6)); +// Assert.Equal(123.546f, await reader.GetFieldValueAsync(7)); +// Assert.Equal(sqlguid, await reader.GetFieldValueAsync(8)); +// Assert.Equal(sqlguid.Value, (await reader.GetFieldValueAsync(8)).Value); +// Assert.Equal(dateTime.ToString("dd/MM/yyyy HH:mm:ss.fff"), (await reader.GetFieldValueAsync(9)).ToString("dd/MM/yyyy HH:mm:ss.fff")); +// Assert.Equal(280, await reader.GetFieldValueAsync(10)); +// Assert.Equal(dtoffset, await reader.GetFieldValueAsync(11)); +// Assert.Equal(new DateTime(2022, 10, 23), await reader.GetFieldValueAsync(12)); +// Assert.Equal(new TimeSpan(0, 22, 7, 44), await reader.GetFieldValueAsync(13)); +// Assert.Equal(new DateOnly(2022, 10, 23), await reader.GetFieldValueAsync(12)); +// Assert.Equal(new TimeOnly(22, 7, 44), await reader.GetFieldValueAsync(13)); +// } +// } +// } +// finally +// { +// //cleanup +// using (DbCommand cmd = provider.CreateCommand()) +// { +// cmd.Connection = con; +// cmd.CommandText = "drop table " + tableName; +// await cmd.ExecuteNonQueryAsync(); +// } +// } +// } +//#endif +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AdapterTest/AdapterTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AdapterTest/AdapterTest.cs index d00a9cf8b1..9234085ef3 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AdapterTest/AdapterTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AdapterTest/AdapterTest.cs @@ -1,1885 +1,1885 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Data; -using System.Data.SqlTypes; -using System.Diagnostics; -using System.Globalization; -using System.Reflection; -using System.Text; -using Xunit; - -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ - public class AdapterTest - { - private char[] _appendNewLineIndentBuffer = new char[0]; - - // data value and server consts - private const string MagicName = "Magic"; - // Use a union statement so that Identity columns don't carry over - private const string _createTableQuery = "select * into {0} from Employees where EmployeeID < 3 union all (select * from Employees where 1 = 0)"; - private string _tempTable; - private string _tempKey; - private string _randomGuid; - - // data type - private decimal _c_numeric_val; - private long _c_bigint_val; - private byte[] _c_unique_val; - private Guid _c_guid_val; - private byte[] _c_varbinary_val; - private byte[] _c_binary_val; - private decimal _c_money_val; - private decimal _c_smallmoney_val; - private DateTime _c_datetime_val; - private DateTime _c_smalldatetime_val; - private string _c_nvarchar_val; - private string _c_nchar_val; - private string _c_varchar_val; - private string _c_char_val; - private int _c_int_val; - private short _c_smallint_val; - private byte _c_tinyint_val; - private bool _c_bit_val; - private double _c_float_val; - private float _c_real_val; - - private object[] _values; - - public AdapterTest() - { - // create random name for temp tables - _tempTable = DataTestUtility.GetUniqueName("AdapterTest"); - _tempTable = _tempTable.Replace('-', '_'); - - _randomGuid = Guid.NewGuid().ToString(); - _tempKey = "employee_id_key_" + Environment.TickCount.ToString() + _randomGuid; - _tempKey = _tempKey.Replace('-', '_'); - - InitDataValues(); - } - - // TODO Synapse: Remove Northwind dependency by creating required tables in setup. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public void SimpleFillTest() - { - using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) - using (SqlDataAdapter adapter = new SqlDataAdapter("SELECT EmployeeID, LastName, FirstName, Title, Address, City, Region, PostalCode, Country FROM Employees", conn)) - { - DataSet employeesSet = new DataSet(); - DataTestUtility.AssertEqualsWithDescription(0, employeesSet.Tables.Count, "Unexpected tables count before fill."); - adapter.Fill(employeesSet, "Employees"); - - DataTestUtility.AssertEqualsWithDescription(1, employeesSet.Tables.Count, "Unexpected tables count after fill."); - DataTestUtility.AssertEqualsWithDescription("Employees", employeesSet.Tables[0].TableName, "Unexpected table name."); - - DataTestUtility.AssertEqualsWithDescription(9, employeesSet.Tables["Employees"].Columns.Count, "Unexpected columns count."); - employeesSet.Tables["Employees"].Columns.Remove("LastName"); - employeesSet.Tables["Employees"].Columns.Remove("FirstName"); - employeesSet.Tables["Employees"].Columns.Remove("Title"); - DataTestUtility.AssertEqualsWithDescription(6, employeesSet.Tables["Employees"].Columns.Count, "Unexpected columns count after column removal."); - } - } - - // TODO Synapse: Remove Northwind dependency by creating required tables in setup. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public void PrepUnprepTest() - { - // share the connection - using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) - using (SqlCommand cmd = new SqlCommand("select * from shippers", connection)) - using (SqlDataAdapter sqlAdapter = new SqlDataAdapter()) - { - cmd.Connection.Open(); - - DataSet dataSet = new DataSet(); - sqlAdapter.TableMappings.Add("Table", "shippers"); - - cmd.CommandText = "Select * from shippers"; - sqlAdapter.SelectCommand = cmd; - sqlAdapter.Fill(dataSet); - - DataTestUtility.AssertEqualsWithDescription( - 3, dataSet.Tables[0].Rows.Count, - "Exec1: Unexpected number of shipper rows."); - - dataSet.Reset(); - sqlAdapter.Fill(dataSet); - - DataTestUtility.AssertEqualsWithDescription( - 3, dataSet.Tables[0].Rows.Count, - "Exec2: Unexpected number of shipper rows."); - - dataSet.Reset(); - cmd.CommandText = "select * from shippers where shipperId < 3"; - sqlAdapter.Fill(dataSet); - - DataTestUtility.AssertEqualsWithDescription( - 2, dataSet.Tables[0].Rows.Count, - "Exec3: Unexpected number of shipper rows."); - - dataSet.Reset(); - - sqlAdapter.Fill(dataSet); - DataTestUtility.AssertEqualsWithDescription( - 2, dataSet.Tables[0].Rows.Count, - "Exec4: Unexpected number of shipper rows."); - - cmd.CommandText = "select * from shippers"; - cmd.Prepare(); - - int i = 0; - using (SqlDataReader reader = cmd.ExecuteReader()) - { - DataTestUtility.AssertEqualsWithDescription(3, reader.FieldCount, "Unexpected FieldCount."); - - while (reader.Read()) - { - i++; - } - } - DataTestUtility.AssertEqualsWithDescription(3, i, "Unexpected read count."); - - cmd.CommandText = "select * from orders where orderid < @p1"; - cmd.Parameters.AddWithValue("@p1", 10250); - using (SqlDataReader reader = cmd.ExecuteReader()) - { - DataTestUtility.AssertEqualsWithDescription(14, reader.FieldCount, "Unexpected FieldCount."); - - i = 0; - while (reader.Read()) - { - i++; - } - } - DataTestUtility.AssertEqualsWithDescription(2, i, "Unexpected read count."); - - cmd.Parameters["@p1"].Value = 10249; - using (SqlDataReader reader = cmd.ExecuteReader()) - { - DataTestUtility.AssertEqualsWithDescription(14, reader.FieldCount, "Unexpected FieldCount."); - - i = 0; - while (reader.Read()) - { - i++; - } - } - DataTestUtility.AssertEqualsWithDescription(1, i, "Unexpected read count."); - } - } - - // Synapse: Create table statement contains a data type that is unsupported in Parallel Data Warehouse. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public void SqlVariantTest() - { - string tableName = DataTestUtility.GenerateObjectName(); - // good test for null values and unicode strings - using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) - using (SqlCommand cmd = new SqlCommand(null, conn)) - using (SqlDataAdapter sqlAdapter = new SqlDataAdapter()) - { - try - { - ExecuteNonQueryCommand("CREATE TABLE " + tableName + " (c0_bigint bigint, c1_variant sql_variant)"); - - cmd.Connection.Open(); - - // the ORDER BY clause tests that we correctly ignore the ORDER token - cmd.CommandText = "select * from " + tableName; - sqlAdapter.SelectCommand = cmd; - sqlAdapter.TableMappings.Add(tableName, "rowset"); - - // insert - sqlAdapter.InsertCommand = new SqlCommand() - { - CommandText = "INSERT INTO " + tableName + "(c0_bigint, c1_variant) " + - "VALUES (@bigint, @variant)" - }; - SqlParameter p = sqlAdapter.InsertCommand.Parameters.Add(new SqlParameter("@bigint", SqlDbType.BigInt)); - p.SourceColumn = "c0_bigint"; - p = sqlAdapter.InsertCommand.Parameters.Add(new SqlParameter("@variant", SqlDbType.Variant)); - p.SourceColumn = "c1_variant"; - sqlAdapter.InsertCommand.Connection = cmd.Connection; - - DataSet dataSet = new DataSet(); - sqlAdapter.FillSchema(dataSet, SchemaType.Mapped, tableName); - - DataRow datarow = null; - for (int i = 0; i < _values.Length; i++) - { - // add each variant type - datarow = dataSet.Tables[0].NewRow(); - datarow.ItemArray = new object[] { 1, _values[i] }; - datarow.Table.Rows.Add(datarow); - } - - sqlAdapter.Update(dataSet, tableName); - - // now reload and make sure we got the values we wrote out - dataSet.Reset(); - sqlAdapter.Fill(dataSet, tableName); - - DataColumnCollection cols = dataSet.Tables[0].Columns; - DataRowCollection rows = dataSet.Tables[0].Rows; - - Assert.True(rows.Count == _values.Length, "FAILED: SqlVariant didn't update all the rows!"); - - for (int i = 0; i < rows.Count; i++) - { - DataRow row = rows[i]; - object value = row[1]; - - if (_values[i].GetType() == typeof(byte[]) || _values[i].GetType() == typeof(Guid)) - { - byte[] bsrc; - byte[] bdst; - - if (_values[i].GetType() == typeof(Guid)) - { - bsrc = ((Guid)value).ToByteArray(); - bdst = ((Guid)(_values[i])).ToByteArray(); - } - else - { - bsrc = (byte[])value; - bdst = (byte[])_values[i]; - } - - Assert.True(ByteArraysEqual(bsrc, bdst), "FAILED: Byte arrays are unequal"); - } - else if (_values[i].GetType() == typeof(bool)) - { - Assert.True(Convert.ToBoolean(value) == (bool)_values[i], "FAILED: " + DBConvertToString(value) + " is not equal to " + DBConvertToString(_values[i])); - } - else - { - Assert.True(value.Equals(_values[i]), "FAILED: " + DBConvertToString(value) + " is not equal to " + DBConvertToString(_values[i])); - } - } - } - finally - { - DataTestUtility.DropTable(conn, tableName); - } - } - } - - // Synapse: The RETURN statement can only be used in user-defined functions. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public void ParameterTest_AllTypes() - { - string procName = DataTestUtility.GenerateObjectName(); - string spCreateAllTypes = - "CREATE PROCEDURE " + procName + " " + - "@Cnumeric numeric(10,2) OUTPUT, " + - "@Cunique uniqueidentifier OUTPUT, " + - "@Cnvarchar nvarchar(10) OUTPUT, " + - "@Cnchar nchar(10) OUTPUT, " + - "@Cbit bit OUTPUT, " + - "@Ctinyint tinyint OUTPUT, " + - "@Cvarbinary varbinary(16) OUTPUT, " + - "@Cbinary binary(16) OUTPUT, " + - "@Cchar char(10) OUTPUT, " + - "@Cmoney money OUTPUT, " + - "@Csmallmoney smallmoney OUTPUT, " + - "@Cint int OUTPUT, " + - "@Csmallint smallint OUTPUT, " + - "@Cfloat float OUTPUT, " + - "@Creal real OUTPUT, " + - "@Cdatetime datetime OUTPUT, " + - "@Csmalldatetime smalldatetime OUTPUT, " + - "@Cvarchar varchar(10) OUTPUT " + - "AS SELECT " + - "@Cnumeric=@Cnumeric, " + - "@Cunique=@Cunique, " + - "@Cnvarchar=@Cnvarchar, " + - "@Cnchar=@Cnchar, " + - "@Cbit=@Cbit, " + - "@Ctinyint=@Ctinyint, " + - "@Cvarbinary=@Cvarbinary, " + - "@Cbinary=@Cbinary, " + - "@Cchar=@Cchar, " + - "@Cmoney=@Cmoney, " + - "@Csmallmoney=@Csmallmoney, " + - "@Cint=@Cint, " + - "@Csmallint=@Csmallint, " + - "@Cfloat=@Cfloat, " + - "@Creal=@Creal, " + - "@Cdatetime=@Cdatetime, " + - "@Csmalldatetime=@Csmalldatetime, " + - "@Cvarchar=@Cvarchar " + - "RETURN(42)"; - - string spDropAllTypes = "DROP PROCEDURE " + procName; - bool dropSP = false; - - try - { - ExecuteNonQueryCommand(spCreateAllTypes); - dropSP = true; - - using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) - using (SqlCommand cmd = new SqlCommand(procName, conn)) - using (SqlDataAdapter sqlAdapter = new SqlDataAdapter()) - { - conn.Open(); - - SqlParameter param = cmd.Parameters.Add(new SqlParameter("@Cnumeric", SqlDbType.Decimal)); - param.Precision = 10; - param.Scale = 2; - param.Direction = ParameterDirection.InputOutput; - cmd.Parameters[0].Value = _c_numeric_val; - - param = cmd.Parameters.Add(new SqlParameter("@Cunique", SqlDbType.UniqueIdentifier)); - param.Direction = ParameterDirection.InputOutput; - cmd.Parameters[1].Value = _c_guid_val; - - cmd.Parameters.Add(new SqlParameter("@Cnvarchar", SqlDbType.NVarChar, 10)); - cmd.Parameters[2].Direction = ParameterDirection.InputOutput; - cmd.Parameters[2].Value = _c_nvarchar_val; - - cmd.Parameters.Add(new SqlParameter("@Cnchar", SqlDbType.NChar, 10)); - cmd.Parameters[3].Direction = ParameterDirection.InputOutput; - cmd.Parameters[3].Value = _c_nchar_val; - - param = cmd.Parameters.Add(new SqlParameter("@Cbit", SqlDbType.Bit)); - param.Direction = ParameterDirection.InputOutput; - cmd.Parameters[4].Value = _c_bit_val; - - param = cmd.Parameters.Add(new SqlParameter("@Ctinyint", SqlDbType.TinyInt)); - param.Direction = ParameterDirection.InputOutput; - cmd.Parameters[5].Value = _c_tinyint_val; - - cmd.Parameters.Add(new SqlParameter("@Cvarbinary", SqlDbType.VarBinary, 16)); - cmd.Parameters[6].Direction = ParameterDirection.InputOutput; - cmd.Parameters[6].Value = _c_varbinary_val; - - cmd.Parameters.Add(new SqlParameter("@Cbinary", SqlDbType.Binary, 16)); - cmd.Parameters[7].Direction = ParameterDirection.InputOutput; - cmd.Parameters[7].Value = _c_binary_val; - - cmd.Parameters.Add(new SqlParameter("@Cchar", SqlDbType.Char, 10)); - cmd.Parameters[8].Direction = ParameterDirection.InputOutput; - cmd.Parameters[8].Value = _c_char_val; - - param = cmd.Parameters.Add(new SqlParameter("@Cmoney", SqlDbType.Money)); - param.Direction = ParameterDirection.InputOutput; - param.Scale = 4; - cmd.Parameters[9].Value = _c_money_val; - - param = cmd.Parameters.Add(new SqlParameter("@Csmallmoney", SqlDbType.SmallMoney)); - param.Direction = ParameterDirection.InputOutput; - param.Scale = 4; - cmd.Parameters[10].Value = _c_smallmoney_val; - - param = cmd.Parameters.Add(new SqlParameter("@Cint", SqlDbType.Int)); - param.Direction = ParameterDirection.InputOutput; - cmd.Parameters[11].Value = _c_int_val; - - param = cmd.Parameters.Add(new SqlParameter("@Csmallint", SqlDbType.SmallInt)); - param.Direction = ParameterDirection.InputOutput; - cmd.Parameters[12].Value = _c_smallint_val; - - param = cmd.Parameters.Add(new SqlParameter("@Cfloat", SqlDbType.Float)); - param.Direction = ParameterDirection.InputOutput; - cmd.Parameters[13].Value = _c_float_val; - - param = cmd.Parameters.Add(new SqlParameter("@Creal", SqlDbType.Real)); - param.Direction = ParameterDirection.InputOutput; - cmd.Parameters[14].Value = _c_real_val; - - param = cmd.Parameters.Add(new SqlParameter("@Cdatetime", SqlDbType.DateTime)); - param.Direction = ParameterDirection.InputOutput; - cmd.Parameters[15].Value = _c_datetime_val; - - param = cmd.Parameters.Add(new SqlParameter("@Csmalldatetime", SqlDbType.SmallDateTime)); - param.Direction = ParameterDirection.InputOutput; - cmd.Parameters[16].Value = _c_smalldatetime_val; - - param = cmd.Parameters.Add(new SqlParameter("@Cvarchar", SqlDbType.VarChar, 10)); - param.Direction = ParameterDirection.InputOutput; - cmd.Parameters[17].Value = _c_varchar_val; - - param = cmd.Parameters.Add(new SqlParameter("@return", SqlDbType.Int)); - param.Direction = ParameterDirection.ReturnValue; - cmd.Parameters[18].Value = 17; // will be overwritten - - cmd.CommandType = CommandType.StoredProcedure; - cmd.ExecuteNonQuery(); - - string[] expectedStringValues = - { - "@Cnumeric : Decimal<42424242.42>", - null, - "@Cnvarchar : String:10<1234567890>", - "@Cnchar : String:10<1234567890>", - "@Cbit : Boolean", - "@Ctinyint : Byte<255>", - null, - null, - "@Cchar : String:10<1234567890>", - null, - null, - "@Cint : Int32<-1>", - "@Csmallint : Int16<-1>", - "@Cfloat : Double<12345678.2>", - "@Creal : Single<12345.1>", - null, - null, - "@Cvarchar : String:10<1234567890>", - "@return : Int32<42>" - }; - - for (int i = 0; i < cmd.Parameters.Count; i++) - { - param = cmd.Parameters[i]; - switch (param.SqlDbType) - { - case SqlDbType.Binary: - Assert.True(ByteArraysEqual(_c_binary_val, (byte[])param.Value), "FAILED: " + procName + ", Binary parameter"); - break; - case SqlDbType.VarBinary: - Assert.True(ByteArraysEqual(_c_varbinary_val, (byte[])param.Value), "FAILED: " + procName + ", VarBinary parameter"); - break; - case SqlDbType.UniqueIdentifier: - DataTestUtility.AssertEqualsWithDescription(_c_guid_val, (Guid)param.Value, "FAILED: " + procName + ", UniqueIdentifier parameter"); - break; - case SqlDbType.DateTime: - Assert.True(0 == DateTime.Compare((DateTime)param.Value, _c_datetime_val), "FAILED: " + procName + ", DateTime parameter"); - break; - case SqlDbType.SmallDateTime: - Assert.True(0 == DateTime.Compare((DateTime)param.Value, _c_smalldatetime_val), "FAILED: " + procName + ", SmallDateTime parameter"); - break; - case SqlDbType.Money: - Assert.True( - 0 == decimal.Compare((decimal)param.Value, _c_money_val), - string.Format("FAILED: " + procName + ", Money parameter. Expected: {0}. Actual: {1}.", _c_money_val, (decimal)param.Value)); - break; - case SqlDbType.SmallMoney: - Assert.True( - 0 == decimal.Compare((decimal)param.Value, _c_smallmoney_val), - string.Format("FAILED: " + procName + ", SmallMoney parameter. Expected: {0}. Actual: {1}.", _c_smallmoney_val, (decimal)param.Value)); - break; - default: - string actualValue = param.ParameterName + " : " + DBConvertToString(cmd.Parameters[i].Value); - DataTestUtility.AssertEqualsWithDescription(actualValue, expectedStringValues[i], "Unexpected parameter value."); - break; - } - } - } - } - finally - { - if (dropSP) - { - ExecuteNonQueryCommand(spDropAllTypes); - } - } - } - - // Synapse: The RETURN statement can only be used in user-defined functions. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public void ParameterTest_InOut() - { - string procName = DataTestUtility.GetUniqueName("P"); - // input, output - string spCreateInOut = - "CREATE PROCEDURE " + procName + " @in int, @inout int OUTPUT, @out nvarchar(8) OUTPUT " + - "AS SELECT @inout = (@in + @inout), @out = 'Success!' " + - "SELECT * From shippers where ShipperID = @in " + - "RETURN(42)"; - - string spDropInOut = "DROP PROCEDURE " + procName; - bool dropSP = false; - - try - { - ExecuteNonQueryCommand(spCreateInOut); - dropSP = true; - - using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) - using (SqlCommand cmd = new SqlCommand(procName, conn)) - using (SqlDataAdapter sqlAdapter = new SqlDataAdapter()) - { - conn.Open(); - - cmd.CommandType = CommandType.StoredProcedure; - cmd.Parameters.Add(new SqlParameter("@in", SqlDbType.Int)); - cmd.Parameters[0].Value = 2; - - SqlParameter param = cmd.Parameters.Add(new SqlParameter("@inout", SqlDbType.Int)); - param.Direction = ParameterDirection.InputOutput; - cmd.Parameters[1].Value = 1998; - - param = cmd.Parameters.Add(new SqlParameter("@out", SqlDbType.NVarChar, 8)); - param.Direction = ParameterDirection.Output; - - param = cmd.Parameters.Add(new SqlParameter("@ret", SqlDbType.Int)); - param.Direction = ParameterDirection.ReturnValue; - - DataSet dataSet = new DataSet(); - sqlAdapter.TableMappings.Add("Table", "shipper"); - sqlAdapter.SelectCommand = cmd; - sqlAdapter.Fill(dataSet); - - // check our ouput and return value params - Assert.True(VerifyOutputParams(cmd.Parameters), "FAILED: InputOutput parameter test with returned rows and bound return value!"); - - Assert.True(1 == dataSet.Tables[0].Rows.Count, "FAILED: Expected 1 row to be loaded in the dataSet!"); - - DataRow row = dataSet.Tables[0].Rows[0]; - Assert.True((int)row["ShipperId"] == 2, "FAILED: ShipperId column should be 2, not " + DBConvertToString(row["ShipperId"])); - - // remember to reset params - cmd.Parameters[0].Value = 2; - cmd.Parameters[1].Value = 1998; - cmd.Parameters[2].Value = Convert.DBNull; - cmd.Parameters[3].Value = Convert.DBNull; - - // now exec the same thing without a data set - cmd.ExecuteNonQuery(); - - // check our ouput and return value params - Assert.True(VerifyOutputParams(cmd.Parameters), "FAILED: InputOutput parameter test with no returned rows and bound return value!"); - - // now unbind the return value - cmd.Parameters.RemoveAt(3); - - // remember to reset input params - cmd.Parameters[0].Value = 1; // use 1, just for the heck of it - cmd.Parameters[1].Value = 1999; - cmd.Parameters[2].Value = Convert.DBNull; - - dataSet.Reset(); - - sqlAdapter.Fill(dataSet); - - // verify the ouptut parameter - Assert.True( - ((int)cmd.Parameters[1].Value == 2000) && - (0 == string.Compare(cmd.Parameters[2].Value.ToString(), "Success!", false, CultureInfo.InvariantCulture)), - "FAILED: unbound return value case, output param is not correct!"); - - Assert.True(1 == dataSet.Tables[0].Rows.Count, "FAILED: Expected 1 row to be loaded in the dataSet!"); - - row = dataSet.Tables[0].Rows[0]; - Assert.True((int)row["ShipperId"] == 1, "FAILED: ShipperId column should be 1, not " + DBConvertToString(row["ShipperId"])); - } - } - finally - { - if (dropSP) - { - ExecuteNonQueryCommand(spDropInOut); - } - } - } - - // TODO Synapse: Remove Northwind dependency by creating required tables in setup. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public void UpdateTest() - { - using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) - using (SqlCommand cmd = conn.CreateCommand()) - using (SqlDataAdapter adapter = new SqlDataAdapter()) - using (SqlDataAdapter adapterVerify = new SqlDataAdapter()) - { - conn.Open(); - - cmd.CommandText = string.Format(_createTableQuery, _tempTable); - cmd.ExecuteNonQuery(); - cmd.CommandText = "alter table " + _tempTable + " add constraint " + _tempKey + " primary key (EmployeeID)"; - cmd.ExecuteNonQuery(); - - try - { - PrepareUpdateCommands(adapter, conn, _tempTable); - - adapter.SelectCommand = new SqlCommand(string.Format("SELECT EmployeeID, LastName, FirstName, Title, Address, City, Region, PostalCode, Country from {0} where EmployeeID < 3", _tempTable), conn); - adapterVerify.SelectCommand = new SqlCommand("SELECT LastName, FirstName FROM " + _tempTable + " where FirstName='" + MagicName + "'", conn); - - adapter.TableMappings.Add(_tempTable, "rowset"); - adapterVerify.TableMappings.Add(_tempTable, "rowset"); - - DataSet dataSet = new DataSet(); - VerifyFillSchemaResult(adapter.FillSchema(dataSet, SchemaType.Mapped, _tempTable), new string[] { "rowset" }); - - // FillSchema - dataSet.Tables["rowset"].PrimaryKey = new DataColumn[] { dataSet.Tables["rowset"].Columns["EmployeeID"] }; - adapter.Fill(dataSet, _tempTable); - - // Fill from Database - Assert.True(dataSet.Tables[0].Rows.Count == 2, "FAILED: Fill after FillSchema should populate the dataSet with two rows!"); - - dataSet.AcceptChanges(); - - // Verify that set is empty - DataSet dataSetVerify = new DataSet(); - VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); - - // Insert - DataRow datarow = dataSet.Tables["rowset"].NewRow(); - datarow.ItemArray = new object[] { "11", "The Original", MagicName, "Engineer", "One Microsoft Way", "Redmond", "WA", "98052", "USA" }; - datarow.Table.Rows.Add(datarow); - - adapter.Update(dataSet, _tempTable); - - // Verify that set has one 'Magic' entry - VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); - - dataSet.AcceptChanges(); - - // Update - datarow = dataSet.Tables["rowset"].Rows.Find("11"); - datarow.BeginEdit(); - datarow.ItemArray = new object[] { "11", "The New and Improved", MagicName, "reenignE", "Yaw Tfosorcim Eno", "Dnomder", "WA", "52098", "ASU" }; - datarow.EndEdit(); - - adapter.Update(dataSet, _tempTable); - - // Verify that set has updated 'Magic' entry - VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); - - dataSet.AcceptChanges(); - - // Delete - dataSet.Tables["rowset"].Rows.Find("11").Delete(); - adapter.Update(dataSet, _tempTable); - - // Verify that set is empty - VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); - - dataSet.AcceptChanges(); - } - finally - { - DataTestUtility.DropTable(conn, _tempTable); - } - } - } - - // these next texts verify that 'bulk' operations work. If each command type modifies more than three rows, then we do a Prep/Exec instead of - // adhoc ExecuteSql. - // TODO Synapse: Remove Northwind dependency by creating required tables in setup. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public void BulkUpdateTest() - { - using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) - using (SqlCommand cmd = conn.CreateCommand()) - using (SqlDataAdapter adapter = new SqlDataAdapter()) - using (SqlDataAdapter adapterVerify = new SqlDataAdapter()) - { - conn.Open(); - - cmd.CommandText = string.Format(_createTableQuery, _tempTable); - cmd.ExecuteNonQuery(); - cmd.CommandText = "alter table " + _tempTable + " add constraint " + _tempKey + " primary key (EmployeeID)"; - cmd.ExecuteNonQuery(); - - try - { - PrepareUpdateCommands(adapter, conn, _tempTable); - - adapter.SelectCommand = new SqlCommand("SELECT EmployeeID, LastName, FirstName, Title, Address, City, Region, PostalCode, Country FROM " + _tempTable + " WHERE EmployeeID < 3", conn); - adapterVerify.SelectCommand = new SqlCommand("SELECT LastName, FirstName FROM " + _tempTable + " where FirstName='" + MagicName + "'", conn); - - adapter.TableMappings.Add(_tempTable, "rowset"); - adapterVerify.TableMappings.Add(_tempTable, "rowset"); - - DataSet dataSet = new DataSet(); - adapter.FillSchema(dataSet, SchemaType.Mapped, _tempTable); - - dataSet.Tables["rowset"].PrimaryKey = new DataColumn[] { dataSet.Tables["rowset"].Columns["EmployeeID"] }; - adapter.Fill(dataSet, _tempTable); - dataSet.AcceptChanges(); - - // Verify that set is empty - DataSet dataSetVerify = new DataSet(); - VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); - - // Bulk Insert (10 records) - DataRow datarow = null; - const int cOps = 5; - for (int i = 0; i < cOps * 2; i++) - { - datarow = dataSet.Tables["rowset"].NewRow(); - string sid = "99999000" + i.ToString(); - datarow.ItemArray = new object[] { sid, "Bulk Insert" + i.ToString(), MagicName, "Engineer", "One Microsoft Way", "Redmond", "WA", "98052", "USA" }; - datarow.Table.Rows.Add(datarow); - } - adapter.Update(dataSet, _tempTable); - - // Verify that set has 10 'Magic' entries - VerifyUpdateRow(adapterVerify, dataSetVerify, 10, _tempTable); - dataSet.AcceptChanges(); - - // Bulk Update (first 5) - for (int i = 0; i < cOps; i++) - { - string sid = "99999000" + i.ToString(); - datarow = dataSet.Tables["rowset"].Rows.Find(sid); - datarow.BeginEdit(); - datarow.ItemArray = new object[] { sid, "Bulk Update" + i.ToString(), MagicName, "reenignE", "Yaw Tfosorcim Eno", "Dnomder", "WA", "52098", "ASU" }; - datarow.EndEdit(); - } - - // Bulk Delete (last 5) - for (int i = cOps; i < cOps * 2; i++) - { - string sid = "99999000" + i.ToString(); - dataSet.Tables["rowset"].Rows.Find(sid).Delete(); - } - - // now update the dataSet with the insert and delete changes - adapter.Update(dataSet, _tempTable); - - // Verify that set has 5 'Magic' updated entries - VerifyUpdateRow(adapterVerify, dataSetVerify, 5, _tempTable); - dataSet.AcceptChanges(); - - // clean up the remaining 5 rows - for (int i = 0; i < cOps; i++) - { - string sid = "99999000" + i.ToString(); - dataSet.Tables["rowset"].Rows.Find(sid).Delete(); - } - adapter.Update(dataSet, _tempTable); - - // Verify that set has no entries - VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); - dataSet.AcceptChanges(); - } - finally - { - DataTestUtility.DropTable(conn, _tempTable); - } - } - } - - // Makes sure that we can refresh an identity column in the dataSet - // for a newly inserted row - // Synapse: Must declare the scalar variable "@@IDENTITY". - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public void UpdateRefreshTest() - { - string identTableName = DataTestUtility.GetUniqueName("ID_"); - string createIdentTable = - $"CREATE TABLE {identTableName} (id int IDENTITY," + - "LastName nvarchar(50) NULL," + - "Firstname nvarchar(50) NULL)"; - - string spName = DataTestUtility.GetUniqueName("sp_insert", withBracket: false); - string spCreateInsert = - $"CREATE PROCEDURE {spName}" + - "(@FirstName nvarchar(50), @LastName nvarchar(50), @id int OUTPUT) " + - "AS INSERT INTO " + _tempTable + " (FirstName, LastName) " + - "VALUES (@FirstName, @LastName); " + - "SELECT @id=@@IDENTITY"; - - string spDropInsert = $"DROP PROCEDURE {spName}"; - bool dropSP = false; - - using (SqlDataAdapter adapter = new SqlDataAdapter()) - using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) - using (SqlCommand cmd = new SqlCommand(null, conn)) - using (SqlCommand temp = new SqlCommand("SELECT id, LastName, FirstName into " + _tempTable + $" from {identTableName}", conn)) - using (SqlCommand tableClean = new SqlCommand("", conn)) - { - ExecuteNonQueryCommand(createIdentTable); - try - { - adapter.InsertCommand = new SqlCommand() - { - CommandText = spName, - CommandType = CommandType.StoredProcedure - }; - adapter.InsertCommand.Parameters.Add(new SqlParameter("@FirstName", SqlDbType.NVarChar, 50, "FirstName")); - adapter.InsertCommand.Parameters.Add(new SqlParameter("@LastName", SqlDbType.NVarChar, 50, "LastName")); - SqlParameter param = adapter.InsertCommand.Parameters.Add(new SqlParameter("@id", SqlDbType.Int)); - param.SourceColumn = "id"; - param.Direction = ParameterDirection.Output; - - adapter.InsertCommand.Parameters.Add(new SqlParameter("@badapple", SqlDbType.NVarChar, 50, "LastName")); - adapter.RowUpdating += new SqlRowUpdatingEventHandler(RowUpdating_UpdateRefreshTest); - adapter.RowUpdated += new SqlRowUpdatedEventHandler(RowUpdated_UpdateRefreshTest); - - adapter.InsertCommand.Connection = conn; - conn.Open(); - - temp.ExecuteNonQuery(); - - // start clean - tableClean.CommandText = "delete " + _tempTable; - tableClean.ExecuteNonQuery(); - tableClean.CommandText = spCreateInsert; - tableClean.ExecuteNonQuery(); - - dropSP = true; - - DataSet ds = new DataSet(); - adapter.TableMappings.Add("Table", _tempTable); - cmd.CommandText = "select * from " + _tempTable; - adapter.SelectCommand = cmd; - adapter.Fill(ds, "Table"); - - // Insert - DataRow row1 = ds.Tables[_tempTable].NewRow(); - row1.ItemArray = new object[] { 0, "Bond", "James" }; - row1.Table.Rows.Add(row1); - - DataRow row2 = ds.Tables[_tempTable].NewRow(); - row2.ItemArray = new object[] { 0, "Lee", "Bruce" }; - row2.Table.Rows.Add(row2); - - Assert.True((int)row1["id"] == 0 && (int)row2["id"] == 0, "FAILED: UpdateRefresh should not have values for identity columns"); - - adapter.Update(ds, "Table"); - - // should have values now - int i1 = (int)row1["id"]; - int i2 = (int)row2["id"]; - - Assert.True( - (i1 != 0) && (i2 != 0) && (i2 == (i1 + 1)), - string.Format("FAILED: UpdateRefresh, i2 should equal (i1 + 1). i1: {0}. i2: {1}.", i1, i2)); - } - finally - { - if (dropSP) - { - DataTestUtility.DropStoredProcedure(conn, spName); - DataTestUtility.DropTable(conn, _tempTable); - DataTestUtility.DropTable(conn, identTableName); - } - } - } - } - - // Synapse: Create table statement contains a data type that is unsupported in Parallel Data Warehouse. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public void UpdateNullTest() - { - string tableName = DataTestUtility.GenerateObjectName(); - string procName = DataTestUtility.GenerateObjectName(); - string createTable = "CREATE TABLE " + tableName + "(cvarbin VARBINARY(7000), cimage IMAGE)"; - - string createSP = - "CREATE PROCEDURE " + procName + " (@val_cvarbin VARBINARY(7000), @val_cimage IMAGE)" + - "AS INSERT INTO " + tableName + " (cvarbin, cimage)" + - "VALUES (@val_cvarbin, @val_cimage)"; - bool dropSP = false; - - - using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) - using (SqlCommand cmdInsert = new SqlCommand(procName, conn)) - using (SqlCommand cmdSelect = new SqlCommand("select * from " + tableName, conn)) - using (SqlCommand tableClean = new SqlCommand("delete " + tableName, conn)) - using (SqlDataAdapter adapter = new SqlDataAdapter()) - { - try - { - ExecuteNonQueryCommand(createTable); - ExecuteNonQueryCommand(createSP); - dropSP = true; - conn.Open(); - - cmdInsert.CommandType = CommandType.StoredProcedure; - SqlParameter p1 = cmdInsert.Parameters.Add(new SqlParameter("@val_cvarbin", SqlDbType.VarBinary, 7000)); - SqlParameter p2 = cmdInsert.Parameters.Add(new SqlParameter("@val_cimage", SqlDbType.Image, 8000)); - - tableClean.ExecuteNonQuery(); - p1.Value = Convert.DBNull; - p2.Value = Convert.DBNull; - int rowsAffected = cmdInsert.ExecuteNonQuery(); - DataTestUtility.AssertEqualsWithDescription(1, rowsAffected, "Unexpected number of rows inserted."); - - DataSet ds = new DataSet(); - adapter.SelectCommand = cmdSelect; - adapter.Fill(ds, "goofy"); - // should have 1 row in table (with two null entries) - DataTestUtility.AssertEqualsWithDescription(1, ds.Tables[0].Rows.Count, "Unexpected rows count."); - DataTestUtility.AssertEqualsWithDescription(DBNull.Value, ds.Tables[0].Rows[0][0], "Unexpected value."); - DataTestUtility.AssertEqualsWithDescription(DBNull.Value, ds.Tables[0].Rows[0][1], "Unexpected value."); - } - finally - { - if (dropSP) - { - DataTestUtility.DropStoredProcedure(conn, procName); - DataTestUtility.DropTable(conn, tableName); - } - } - } - } - - // Synapse: Create table statement contains a data type that is unsupported in Parallel Data Warehouse. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public void UpdateOffsetTest() - { - string tableName = DataTestUtility.GenerateObjectName(); - string procName = DataTestUtility.GenerateObjectName(); - string createTable = "CREATE TABLE " + tableName + "(cvarbin VARBINARY(7000), cimage IMAGE)"; - - string createSP = - "CREATE PROCEDURE " + procName + " (@val_cvarbin VARBINARY(7000), @val_cimage IMAGE)" + - "AS INSERT INTO " + tableName + " (cvarbin, cimage)" + - "VALUES (@val_cvarbin, @val_cimage)"; - bool dropSP = false; - - - using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) - using (SqlCommand cmdInsert = new SqlCommand(procName, conn)) - using (SqlCommand cmdSelect = new SqlCommand("select * from " + tableName, conn)) - using (SqlCommand tableClean = new SqlCommand("delete " + tableName, conn)) - using (SqlDataAdapter adapter = new SqlDataAdapter()) - { - try - { - ExecuteNonQueryCommand(createTable); - ExecuteNonQueryCommand(createSP); - dropSP = true; - conn.Open(); - - cmdInsert.CommandType = CommandType.StoredProcedure; - SqlParameter p1 = cmdInsert.Parameters.Add(new SqlParameter("@val_cvarbin", SqlDbType.VarBinary, 7000)); - SqlParameter p2 = cmdInsert.Parameters.Add(new SqlParameter("@val_cimage", SqlDbType.Image, 7000)); - - tableClean.ExecuteNonQuery(); - - byte[] b = new byte[7]; - b[0] = 0x01; - b[1] = 0x02; - b[2] = 0x03; - b[3] = 0x04; - b[4] = 0x05; - b[5] = 0x06; - b[6] = 0x07; - p1.Value = b; - p1.Size = 4; - - p2.Value = b; - p2.Size = 3; - p2.Offset = 4; - int rowsAffected = cmdInsert.ExecuteNonQuery(); - - DataSet ds = new DataSet(); - adapter.SelectCommand = cmdSelect; - adapter.Fill(ds, "goofy"); - - byte[] expectedBytes1 = { 0x01, 0x02, 0x03, 0x04 }; - byte[] val = (byte[])(ds.Tables[0].Rows[0][0]); - Assert.True(ByteArraysEqual(expectedBytes1, val), "FAILED: Test 1: Unequal byte arrays."); - - byte[] expectedBytes2 = { 0x05, 0x06, 0x07 }; - val = (byte[])(ds.Tables[0].Rows[0][1]); - Assert.True(ByteArraysEqual(expectedBytes2, val), "FAILED: Test 2: Unequal byte arrays."); - } - finally - { - if (dropSP) - { - DataTestUtility.DropStoredProcedure(conn, procName); - DataTestUtility.DropTable(conn, tableName); - } - } - } - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public void SelectAllTest() - { - // Test exceptions - using (SqlDataAdapter sqlAdapter = new SqlDataAdapter(new SqlCommand("select * from sys.columns", new SqlConnection(DataTestUtility.TCPConnectionString)))) - { - DataSet dataset = new DataSet(); - sqlAdapter.TableMappings.Add("View", "sys.columns"); - sqlAdapter.Fill(dataset); - } - } - - // AutoGen test - // TODO Synapse: Remove Northwind dependency by creating required tables in setup. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public void AutoGenUpdateTest() - { - using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) - using (SqlCommand cmd = conn.CreateCommand()) - using (SqlDataAdapter adapter = new SqlDataAdapter()) - using (SqlDataAdapter adapterVerify = new SqlDataAdapter()) - { - conn.Open(); - - cmd.CommandText = string.Format(_createTableQuery, _tempTable); - cmd.ExecuteNonQuery(); - cmd.CommandText = "alter table " + _tempTable + " add constraint " + _tempKey + " primary key (EmployeeID)"; - cmd.ExecuteNonQuery(); - - try - { - adapter.SelectCommand = new SqlCommand(string.Format("SELECT EmployeeID, LastName, FirstName, Title, Address, City, Region, PostalCode, Country from {0} where EmployeeID < 3", _tempTable), conn); - adapterVerify.SelectCommand = new SqlCommand("SELECT LastName, FirstName FROM " + _tempTable + " where FirstName='" + MagicName + "'", conn); - - adapter.TableMappings.Add(_tempTable, "rowset"); - adapterVerify.TableMappings.Add(_tempTable, "rowset"); - - // FillSchema - DataSet dataSet = new DataSet(); - VerifyFillSchemaResult(adapter.FillSchema(dataSet, SchemaType.Mapped, _tempTable), new string[] { "rowset" }); - - adapter.Fill(dataSet, _tempTable); - - // Fill from Database - Assert.True(dataSet.Tables[0].Rows.Count == 2, "FAILED: Fill after FillSchema should populate the dataSet with two rows!"); - - // Verify that set is empty - DataSet dataSetVerify = new DataSet(); - VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); - - SqlCommandBuilder builder = new SqlCommandBuilder(adapter); - - // Insert - DataRow datarow = dataSet.Tables["rowset"].NewRow(); - datarow.ItemArray = new object[] { "11", "The Original", MagicName, "Engineer", "One Microsoft Way", "Redmond", "WA", "98052", "USA" }; - datarow.Table.Rows.Add(datarow); - adapter.Update(dataSet, _tempTable); - - // Verify that set has one 'Magic' entry - VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); - - // Update - datarow = dataSet.Tables["rowset"].Rows.Find("11"); - datarow.BeginEdit(); - datarow.ItemArray = new object[] { "11", "The New and Improved", MagicName, "reenignE", "Yaw Tfosorcim Eno", "Dnomder", "WA", "52098", "ASU" }; - datarow.EndEdit(); - adapter.Update(dataSet, _tempTable); - - // Verify that set has updated 'Magic' entry - VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); - - // Delete - dataSet.Tables["rowset"].Rows.Find("11").Delete(); - adapter.Update(dataSet, _tempTable); - - // Verify that set is empty - VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); - } - finally - { - DataTestUtility.DropTable(conn, _tempTable); - } - } - } - - // Synapse: Dynamic SQL generation is not supported against a SelectCommand that does not return any base table information. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public void AutoGenErrorTest() - { - string identTableName = DataTestUtility.GetUniqueName("ID_"); - string createIdentTable = - $"CREATE TABLE {identTableName} (id int IDENTITY," + - "LastName nvarchar(50) NULL," + - "Firstname nvarchar(50) NULL)"; - - using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) - using (SqlCommand cmd = new SqlCommand($"SELECT * into {_tempTable} from {identTableName}", conn)) - using (SqlDataAdapter adapter = new SqlDataAdapter()) - { - try - { - ExecuteNonQueryCommand(createIdentTable); - - conn.Open(); - adapter.SelectCommand = new SqlCommand("select * from " + _tempTable, conn); - - cmd.ExecuteNonQuery(); - - // start clean - DataSet ds = new DataSet(); - adapter.Fill(ds, _tempTable); - - // Insert - DataRow row1 = ds.Tables[_tempTable].NewRow(); - row1.ItemArray = new object[] { 0, "Bond", "James" }; - row1.Table.Rows.Add(row1); - - // table has no key so we should get an error here when we try to autogen the delete command (note that all three - // update command types are generated here despite the fact that we are just doing an insert) - SqlCommandBuilder builder = new SqlCommandBuilder(adapter); - adapter.Update(ds, _tempTable); - } - finally - { - DataTestUtility.DropTable(conn, _tempTable); - DataTestUtility.DropTable(conn, identTableName); - } - } - } - - // These next tests verify that 'bulk' operations work. - // If each command type modifies more than three rows, then we do a Prep/Exec instead of - // adhoc ExecuteSql. - // TODO Synapse: Remove Northwind dependency nu creating required tables in setup. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public void AutoGenBulkUpdateTest() - { - using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) - using (SqlCommand cmd = conn.CreateCommand()) - using (SqlDataAdapter adapter = new SqlDataAdapter()) - using (SqlDataAdapter adapterVerify = new SqlDataAdapter()) - { - conn.Open(); - - cmd.CommandText = string.Format(_createTableQuery, _tempTable); - cmd.ExecuteNonQuery(); - cmd.CommandText = "alter table " + _tempTable + " add constraint " + _tempKey + " primary key (EmployeeID)"; - cmd.ExecuteNonQuery(); - - try - { - adapter.SelectCommand = new SqlCommand("SELECT EmployeeID, LastName, FirstName, Title, Address, City, Region, PostalCode, Country FROM " + _tempTable + " WHERE EmployeeID < 3", conn); - adapterVerify.SelectCommand = new SqlCommand("SELECT LastName, FirstName FROM " + _tempTable + " where FirstName='" + MagicName + "'", conn); - - adapter.TableMappings.Add(_tempTable, "rowset"); - adapterVerify.TableMappings.Add(_tempTable, "rowset"); - - DataSet dataSet = new DataSet(); - adapter.FillSchema(dataSet, SchemaType.Mapped, _tempTable); - - dataSet.Tables["rowset"].PrimaryKey = new DataColumn[] { dataSet.Tables["rowset"].Columns["EmployeeID"] }; - adapter.Fill(dataSet, _tempTable); - - // Verify that set is empty - DataSet dataSetVerify = new DataSet(); - VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); - - SqlCommandBuilder builder = new SqlCommandBuilder(adapter); - - // Bulk Insert (10 records) - DataRow datarow = null; - const int cOps = 5; - for (int i = 0; i < cOps * 2; i++) - { - datarow = dataSet.Tables["rowset"].NewRow(); - string sid = "99999000" + i.ToString(); - datarow.ItemArray = new object[] { sid, "Bulk Insert" + i.ToString(), MagicName, "Engineer", "One Microsoft Way", "Redmond", "WA", "98052", "USA" }; - datarow.Table.Rows.Add(datarow); - } - adapter.Update(dataSet, _tempTable); - // Verify that set has 10 'Magic' entries - VerifyUpdateRow(adapterVerify, dataSetVerify, 10, _tempTable); - dataSet.AcceptChanges(); - - // Bulk Update (first 5) - for (int i = 0; i < cOps; i++) - { - string sid = "99999000" + i.ToString(); - datarow = dataSet.Tables["rowset"].Rows.Find(sid); - datarow.BeginEdit(); - datarow.ItemArray = new object[] { sid, "Bulk Update" + i.ToString(), MagicName, "reenignE", "Yaw Tfosorcim Eno", "Dnomder", "WA", "52098", "ASU" }; - datarow.EndEdit(); - } - - // Bulk Delete (last 5) - for (int i = cOps; i < cOps * 2; i++) - { - string sid = "99999000" + i.ToString(); - dataSet.Tables["rowset"].Rows.Find(sid).Delete(); - } - - // now update the dataSet with the insert and delete changes - adapter.Update(dataSet, _tempTable); - // Verify that set has 5 'Magic' updated entries - VerifyUpdateRow(adapterVerify, dataSetVerify, 5, _tempTable); - - // clean up the remaining 5 rows - for (int i = 0; i < cOps; i++) - { - string sid = "99999000" + i.ToString(); - dataSet.Tables["rowset"].Rows.Find(sid).Delete(); - } - adapter.Update(dataSet, _tempTable); - // Verify that set has no entries - VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); - } - finally - { - DataTestUtility.DropTable(conn, _tempTable); - } - } - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public void TestDeriveParameters() - { - string procName = "Test_EmployeeSalesByCountry_" + _randomGuid + ""; - string spEmployeeSales = - "create procedure [dbo].[" + procName + "] " + - "@Beginning_Date DateTime, @Ending_Date DateTime AS " + - "SELECT Employees.Country, Employees.LastName, Employees.FirstName, Orders.ShippedDate, Orders.OrderID, \"Order Subtotals\".Subtotal AS SaleAmount " + - "FROM Employees INNER JOIN " + - "(Orders INNER JOIN \"Order Subtotals\" ON Orders.OrderID = \"Order Subtotals\".OrderID) " + - "ON Employees.EmployeeID = Orders.EmployeeID " + - "WHERE Orders.ShippedDate Between @Beginning_Date And @Ending_Date"; - string dropSpEmployeeSales = "drop procedure [dbo].[" + procName + "]"; - - string expectedParamResults = - "\"@RETURN_VALUE\" AS Int32 OF Int FOR Current \"\" " + - "0, 0, 0, ReturnValue, DEFAULT; " + - "\"@Beginning_Date\" AS DateTime OF DateTime FOR Current \"\" " + - "0, 0, 0, Input, DEFAULT; " + - "\"@Ending_Date\" AS DateTime OF DateTime FOR Current \"\" " + - "0, 0, 0, Input, DEFAULT; "; - - try - { - ExecuteNonQueryCommand(spEmployeeSales); - using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) - using (SqlCommand cmd = new SqlCommand(procName, connection)) - { - string errorMessage = string.Format(SystemDataResourceManager.Instance.ADP_DeriveParametersNotSupported, "SqlCommand", cmd.CommandType); - DataTestUtility.AssertThrowsWrapper( - () => SqlCommandBuilder.DeriveParameters(cmd), - errorMessage); - - errorMessage = string.Format(SystemDataResourceManager.Instance.ADP_OpenConnectionRequired, "DeriveParameters", ""); - cmd.CommandType = CommandType.StoredProcedure; - DataTestUtility.AssertThrowsWrapper( - () => SqlCommandBuilder.DeriveParameters(cmd), - errorMessage); - - connection.Open(); - - SqlCommandBuilder.DeriveParameters(cmd); - CheckParameters(cmd, expectedParamResults); - - cmd.CommandText = "Test_EmployeeSalesBy"; - errorMessage = string.Format(SystemDataResourceManager.Instance.ADP_NoStoredProcedureExists, cmd.CommandText); - DataTestUtility.AssertThrowsWrapper( - () => SqlCommandBuilder.DeriveParameters(cmd), - errorMessage); - - cmd.CommandText = procName; - SqlCommandBuilder.DeriveParameters(cmd); - CheckParameters(cmd, expectedParamResults); - } - } - finally - { - ExecuteNonQueryCommand(dropSpEmployeeSales); - } - } - - // Synapse: Parse error at line: 1, column: 65: Incorrect syntax near 'as'. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public void TestReadOnlyColumnMetadata() - { - using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) - { - connection.Open(); - using (SqlCommand command = connection.CreateCommand()) - { - command.CommandText = "Create table #t (ID int identity(1,1), sText varchar(12), sMemo as (convert(varchar,ID) + ' ' + sText))"; - command.ExecuteNonQuery(); - } - using (SqlDataAdapter dataAdapter = new SqlDataAdapter("Select * from #t", connection)) - { - using (SqlCommandBuilder commandBuilder = new SqlCommandBuilder(dataAdapter)) - { - using (SqlCommand cmd = commandBuilder.GetInsertCommand()) - { - DataTestUtility.AssertEqualsWithDescription("INSERT INTO [#t] ([sText]) VALUES (@p1)", cmd.CommandText, "Unexpected insert command."); - } - } - - using (DataTable dataTable = new DataTable()) - { - dataAdapter.FillSchema(dataTable, SchemaType.Mapped); - Dictionary expAutoIncrement = new Dictionary() - { - {"ID", true}, - {"sText", false}, - {"sMemo", false} - }; - Dictionary expReadOnly = new Dictionary() - { - {"ID", true}, - {"sText", false}, - {"sMemo", true} - }; - foreach (DataColumn dataColumn in dataTable.Columns) - { - DataTestUtility.AssertEqualsWithDescription(dataColumn.AutoIncrement, expAutoIncrement[dataColumn.ColumnName], "Unexpected AutoIncrement metadata."); - DataTestUtility.AssertEqualsWithDescription(dataColumn.ReadOnly, expReadOnly[dataColumn.ColumnName], "Unexpected ReadOnly metadata."); - } - } - } - } - } - - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - [InlineData(nameof(SqlCommandBuilder.GetInsertCommand), null)] - [InlineData(nameof(SqlCommandBuilder.GetInsertCommand), true)] - [InlineData(nameof(SqlCommandBuilder.GetInsertCommand), false)] - [InlineData(nameof(SqlCommandBuilder.GetUpdateCommand), null)] - [InlineData(nameof(SqlCommandBuilder.GetUpdateCommand), true)] - [InlineData(nameof(SqlCommandBuilder.GetUpdateCommand), false)] - [InlineData(nameof(SqlCommandBuilder.GetDeleteCommand), null)] - [InlineData(nameof(SqlCommandBuilder.GetDeleteCommand), false)] - [InlineData(nameof(SqlCommandBuilder.GetDeleteCommand), true)] - public void VerifyGetCommand(string methodName, bool? useColumnsForParameterNames) - { - using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) - { - connection.Open(); - using (SqlDataAdapter dataAdapter = new SqlDataAdapter("SELECT * FROM dbo.Customers", connection)) - { - using (SqlCommandBuilder commandBuilder = new SqlCommandBuilder(dataAdapter)) - { - object[] parameters = null; - Type[] parameterTypes = null; - if (useColumnsForParameterNames != null) - { - parameters = new object[] { useColumnsForParameterNames }; - parameterTypes = new Type[] { typeof(bool) }; - } - else - { - parameters = new object[] { }; - parameterTypes = new Type[] { }; - } - - MethodInfo method = commandBuilder.GetType().GetMethod(methodName, parameterTypes); - using (SqlCommand cmd = (SqlCommand)method.Invoke(commandBuilder, parameters)) - { - Assert.NotNull(cmd); - } - } - } - } - } - - #region Utility_Methods - private void CheckParameters(SqlCommand cmd, string expectedResults) - { - Debug.Assert(null != cmd, "DumpParameters: null SqlCommand"); - - string actualResults = ""; - StringBuilder builder = new StringBuilder(); - foreach (SqlParameter p in cmd.Parameters) - { - byte precision = p.Precision; - byte scale = p.Scale; - builder.Append("\"" + p.ParameterName + "\" AS " + p.DbType.ToString("G") + " OF " + p.SqlDbType.ToString("G") + " FOR " + p.SourceVersion.ToString("G") + " \"" + p.SourceColumn + "\" "); - builder.Append(p.Size.ToString() + ", " + precision.ToString() + ", " + scale.ToString() + ", " + p.Direction.ToString("G") + ", " + DBConvertToString(p.Value) + "; "); - } - actualResults = builder.ToString(); - - DataTestUtility.AssertEqualsWithDescription(expectedResults, actualResults, "Unexpected Parameter results."); - } - - private bool ByteArraysEqual(byte[] expectedBytes, byte[] actualBytes) - { - DataTestUtility.AssertEqualsWithDescription( - expectedBytes.Length, actualBytes.Length, - "Unexpected array length."); - - for (int i = 0; i < expectedBytes.Length; i++) - { - DataTestUtility.AssertEqualsWithDescription( - expectedBytes[i], actualBytes[i], - "Unexpected byte value."); - } - - return true; - } - - private void InitDataValues() - { - _c_numeric_val = new decimal(42424242.42); - _c_unique_val = new byte[16]; - _c_unique_val[0] = 0xba; - _c_unique_val[1] = 0xad; - _c_unique_val[2] = 0xf0; - _c_unique_val[3] = 0x0d; - _c_unique_val[4] = 0xba; - _c_unique_val[5] = 0xad; - _c_unique_val[6] = 0xf0; - _c_unique_val[7] = 0x0d; - _c_unique_val[8] = 0xba; - _c_unique_val[9] = 0xad; - _c_unique_val[10] = 0xf0; - _c_unique_val[11] = 0x0d; - _c_unique_val[12] = 0xba; - _c_unique_val[13] = 0xad; - _c_unique_val[14] = 0xf0; - _c_unique_val[15] = 0x0d; - _c_guid_val = new Guid(_c_unique_val); - _c_varbinary_val = _c_unique_val; - _c_binary_val = _c_unique_val; - _c_money_val = new decimal((double)123456789.99); - _c_smallmoney_val = new decimal((double)-6543.21); - _c_datetime_val = new DateTime(1971, 7, 20, 23, 59, 59); - _c_smalldatetime_val = new DateTime(1971, 7, 20, 23, 59, 0); - _c_nvarchar_val = "1234567890"; - _c_nchar_val = _c_nvarchar_val; - _c_varchar_val = _c_nvarchar_val; - _c_char_val = _c_nvarchar_val; - _c_int_val = unchecked((int)0xffffffff); - _c_smallint_val = unchecked((short)0xffff); - _c_tinyint_val = 0xff; - _c_bigint_val = 0x11ffffff; - _c_bit_val = true; - _c_float_val = (double)12345678.2; - _c_real_val = (float)12345.1; - - _values = new object[18]; - _values[0] = _c_numeric_val; - _values[1] = _c_smalldatetime_val; - _values[2] = _c_guid_val; - _values[3] = _c_varbinary_val; - _values[4] = _c_binary_val; - _values[5] = _c_money_val; - _values[6] = _c_smallmoney_val; - _values[7] = _c_nvarchar_val; - _values[8] = _c_varchar_val; - _values[9] = _c_char_val; - _values[10] = _c_int_val; - _values[11] = _c_smallint_val; - _values[12] = _c_tinyint_val; - _values[13] = _c_bigint_val; - _values[14] = _c_bit_val; - _values[15] = _c_float_val; - _values[16] = _c_real_val; - _values[17] = _c_datetime_val; - } - - private void VerifyFillSchemaResult(DataTable[] tables, string[] expectedTableNames) - { - DataTestUtility.AssertEqualsWithDescription(expectedTableNames.Length, tables.Length, "Unequal number of tables."); - for (int i = 0; i < tables.Length; i++) - { - DataTestUtility.AssertEqualsWithDescription(expectedTableNames[i], tables[i].TableName, "Unexpected DataTable TableName."); - } - } - - // Prepares the Insert, Update, and Delete command to test updating against Northwind.Employees - private void PrepareUpdateCommands(SqlDataAdapter adapter, SqlConnection conn, string table) - { - // insert - adapter.InsertCommand = new SqlCommand() - { - CommandText = "INSERT INTO " + table + "(EmployeeID, LastName, FirstName, Title, Address, City, Region, PostalCode, Country) " + - "VALUES (@EmployeeID, @LastName, @FirstName, @Title, @Address, @City, @Region, @PostalCode, @Country)" - }; - adapter.InsertCommand.Parameters.Add(new SqlParameter("@EmployeeID", SqlDbType.Int, 0, "EmployeeID")); - adapter.InsertCommand.Parameters.Add(new SqlParameter("@LastName", SqlDbType.NVarChar, 20, "LastName")); - adapter.InsertCommand.Parameters.Add(new SqlParameter("@FirstName", SqlDbType.NVarChar, 10, "FirstName")); - adapter.InsertCommand.Parameters.Add(new SqlParameter("@Title", SqlDbType.NVarChar, 30, "Title")); - adapter.InsertCommand.Parameters.Add(new SqlParameter("@Address", SqlDbType.NVarChar, 60, "Address")); - adapter.InsertCommand.Parameters.Add(new SqlParameter("@City", SqlDbType.NVarChar, 15, "City")); - adapter.InsertCommand.Parameters.Add(new SqlParameter("@Region", SqlDbType.NVarChar, 15, "Region")); - adapter.InsertCommand.Parameters.Add(new SqlParameter("@PostalCode", SqlDbType.NVarChar, 10, "PostalCode")); - adapter.InsertCommand.Parameters.Add(new SqlParameter("@Country", SqlDbType.NVarChar, 15, "Country")); - - adapter.InsertCommand.Connection = conn; - - // update - adapter.UpdateCommand = new SqlCommand() - { - CommandText = "UPDATE " + table + " SET " + - "EmployeeID = @EmployeeID, LastName = @LastName, FirstName = @FirstName, Title = @Title, Address = @Address, City = @City, Region = @Region, " + - "PostalCode = @PostalCode, Country = @Country WHERE (EmployeeID = @OldEmployeeID)" - }; - adapter.UpdateCommand.Parameters.Add(new SqlParameter("@EmployeeID", SqlDbType.Int, 0, "EmployeeID")); - adapter.UpdateCommand.Parameters.Add(new SqlParameter("@LastName", SqlDbType.NVarChar, 20, "LastName")); - adapter.UpdateCommand.Parameters.Add(new SqlParameter("@FirstName", SqlDbType.NVarChar, 10, "FirstName")); - adapter.UpdateCommand.Parameters.Add(new SqlParameter("@Title", SqlDbType.NVarChar, 30, "Title")); - adapter.UpdateCommand.Parameters.Add(new SqlParameter("@Address", SqlDbType.NVarChar, 60, "Address")); - adapter.UpdateCommand.Parameters.Add(new SqlParameter("@City", SqlDbType.NVarChar, 15, "City")); - adapter.UpdateCommand.Parameters.Add(new SqlParameter("@Region", SqlDbType.NVarChar, 15, "Region")); - adapter.UpdateCommand.Parameters.Add(new SqlParameter("@PostalCode", SqlDbType.NVarChar, 10, "PostalCode")); - adapter.UpdateCommand.Parameters.Add(new SqlParameter("@Country", SqlDbType.NVarChar, 15, "Country")); - - adapter.UpdateCommand.Parameters.Add(new SqlParameter("@OldEmployeeID", SqlDbType.Int, 0, "EmployeeID")).SourceVersion = DataRowVersion.Original; - adapter.UpdateCommand.Connection = conn; - - // - // delete - // - adapter.DeleteCommand = new SqlCommand() - { - CommandText = "DELETE FROM " + table + " WHERE (EmployeeID = @EmployeeID)" - }; - adapter.DeleteCommand.Parameters.Add(new SqlParameter("@EmployeeID", SqlDbType.Int, 0, "EmployeeID")); - adapter.DeleteCommand.Connection = conn; - } - - private void RowUpdating_UpdateRefreshTest(object sender, SqlRowUpdatingEventArgs e) - { - // make sure that we always get a cloned command back (which means that it should always have the badapple parameter!) - e.Command = (SqlCommand)((ICloneable)e.Command).Clone(); - DataTestUtility.AssertEqualsWithDescription("sp_insert", e.Command.CommandText.Substring(0, 9), "Unexpected command name."); - e.Command.Parameters.RemoveAt("@badapple"); - } - - private void RowUpdated_UpdateRefreshTest(object sender, SqlRowUpdatedEventArgs e) - { - DataTestUtility.AssertEqualsWithDescription("sp_insert", e.Command.CommandText.Substring(0, 9), "Unexpected command name."); - } - - private void VerifyUpdateRow(SqlDataAdapter sa, DataSet ds, int cRows, string table) - { - ds.Reset(); - sa.Fill(ds, table); - - // don't dump out all the data, just get the row count - if (cRows > 0) - { - Assert.True(ds.Tables[0].Rows.Count == cRows, "FAILED: expected " + cRows.ToString() + " rows but got " + ds.Tables[0].Rows.Count.ToString()); - } - - ds.Reset(); - } - - private bool VerifyOutputParams(SqlParameterCollection sqlParameters) - { - return - (int)sqlParameters[1].Value == 2000 && - (0 == string.Compare((string)sqlParameters[2].Value, "Success!", false, CultureInfo.InvariantCulture)) && - (int)sqlParameters[3].Value == 42; - } - - private string DBConvertToString(object value) - { - StringBuilder builder = new StringBuilder(); - WriteObject(builder, value, CultureInfo.InvariantCulture, null, 0, int.MaxValue); - return builder.ToString(); - } - - private void WriteObject(StringBuilder textBuilder, object value, CultureInfo cultureInfo, Hashtable used, int indent, int recursionLimit) - { - if (0 > --recursionLimit) - { - return; - } - if (null == value) - { - textBuilder.Append("DEFAULT"); - } - else if (Convert.IsDBNull(value)) - { - textBuilder.Append("ISNULL"); - } - else - { - Type valuetype = value.GetType(); - - if ((null != used) && (!valuetype.IsPrimitive)) - { - if (used.Contains(value)) - { - textBuilder.Append('#'); - textBuilder.Append(((int)used[value]).ToString(cultureInfo)); - return; - } - else - { - textBuilder.Append('#'); - textBuilder.Append(used.Count.ToString(cultureInfo)); - used.Add(value, used.Count); - } - } - if ((value is string) || (value is SqlString)) - { - if (value is SqlString) - { - value = ((SqlString)value).Value; - } - textBuilder.Append(valuetype.Name); - textBuilder.Append(":"); - textBuilder.Append(((string)value).Length); - textBuilder.Append("<"); - textBuilder.Append((string)value); - textBuilder.Append(">"); - } - else if ((value is DateTime) || (value is SqlDateTime)) - { - if (value is SqlDateTime) - { - value = ((SqlDateTime)value).Value; - } - textBuilder.Append(valuetype.Name); - textBuilder.Append("<"); - textBuilder.Append(((DateTime)value).ToString("s", cultureInfo)); - textBuilder.Append(">"); - } - else if ((value is float) || (value is SqlSingle)) - { - if (value is SqlSingle) - { - value = ((SqlSingle)value).Value; - } - textBuilder.Append(valuetype.Name); - textBuilder.Append("<"); - textBuilder.Append(((float)value).ToString(cultureInfo)); - textBuilder.Append(">"); - } - else if ((value is double) || (value is SqlDouble)) - { - if (value is SqlDouble) - { - value = ((SqlDouble)value).Value; - } - textBuilder.Append(valuetype.Name); - textBuilder.Append("<"); - textBuilder.Append(((double)value).ToString(cultureInfo)); - textBuilder.Append(">"); - } - else if ((value is decimal) || (value is SqlDecimal) || (value is SqlMoney)) - { - if (value is SqlDecimal) - { - value = ((SqlDecimal)value).Value; - } - else if (value is SqlMoney) - { - value = ((SqlMoney)value).Value; - } - textBuilder.Append(valuetype.Name); - textBuilder.Append("<"); - textBuilder.Append(((decimal)value).ToString(cultureInfo)); - textBuilder.Append(">"); - } - else if (value is INullable && ((INullable)value).IsNull) - { - textBuilder.Append(valuetype.Name); - textBuilder.Append(" ISNULL"); - } - else if (valuetype.IsArray) - { - textBuilder.Append(valuetype.Name); - Array array = (Array)value; - - if (1 < array.Rank) - { - textBuilder.Append("{"); - } - - for (int i = 0; i < array.Rank; ++i) - { - int count = array.GetUpperBound(i); - - textBuilder.Append(' '); - textBuilder.Append(count - array.GetLowerBound(i) + 1); - textBuilder.Append("{ "); - for (int k = array.GetLowerBound(i); k <= count; ++k) - { - AppendNewLineIndent(textBuilder, indent + 1); - textBuilder.Append(','); - WriteObject(textBuilder, array.GetValue(k), cultureInfo, used, 0, recursionLimit); - textBuilder.Append(' '); - } - AppendNewLineIndent(textBuilder, indent); - textBuilder.Append("}"); - } - if (1 < array.Rank) - { - textBuilder.Append('}'); - } - } - else if (value is ICollection) - { - textBuilder.Append(valuetype.Name); - ICollection collection = (ICollection)value; - object[] newvalue = new object[collection.Count]; - collection.CopyTo(newvalue, 0); - - textBuilder.Append(' '); - textBuilder.Append(newvalue.Length); - textBuilder.Append('{'); - for (int k = 0; k < newvalue.Length; ++k) - { - AppendNewLineIndent(textBuilder, indent + 1); - textBuilder.Append(','); - WriteObject(textBuilder, newvalue[k], cultureInfo, used, indent + 1, recursionLimit); - } - AppendNewLineIndent(textBuilder, indent); - textBuilder.Append('}'); - } - else if (value is Type) - { - textBuilder.Append(valuetype.Name); - textBuilder.Append('<'); - textBuilder.Append((value as Type).FullName); - textBuilder.Append('>'); - } - else if (valuetype.IsEnum) - { - textBuilder.Append(valuetype.Name); - textBuilder.Append('<'); - textBuilder.Append(Enum.GetName(valuetype, value)); - textBuilder.Append('>'); - } - else - { - string fullName = valuetype.FullName; - if ("System.ComponentModel.ExtendedPropertyDescriptor" == fullName) - { - textBuilder.Append(fullName); - } - else - { - FieldInfo[] fields = valuetype.GetFields(BindingFlags.Instance | BindingFlags.Public); - PropertyInfo[] properties = valuetype.GetProperties(BindingFlags.Instance | BindingFlags.Public); - - bool hasinfo = false; - if ((null != fields) && (0 < fields.Length)) - { - textBuilder.Append(fullName); - fullName = null; - - Array.Sort(fields, FieldInfoCompare.s_default); - for (int i = 0; i < fields.Length; ++i) - { - FieldInfo field = fields[i]; - - AppendNewLineIndent(textBuilder, indent + 1); - textBuilder.Append(field.Name); - textBuilder.Append('='); - object newvalue = field.GetValue(value); - WriteObject(textBuilder, newvalue, cultureInfo, used, indent + 1, recursionLimit); - } - hasinfo = true; - } - if ((null != properties) && (0 < properties.Length)) - { - if (null != fullName) - { - textBuilder.Append(fullName); - fullName = null; - } - - Array.Sort(properties, PropertyInfoCompare.s_default); - for (int i = 0; i < properties.Length; ++i) - { - PropertyInfo property = properties[i]; - if (property.CanRead) - { - ParameterInfo[] parameters = property.GetIndexParameters(); - if ((null == parameters) || (0 == parameters.Length)) - { - AppendNewLineIndent(textBuilder, indent + 1); - textBuilder.Append(property.Name); - textBuilder.Append('='); - object newvalue = null; - bool haveValue = false; - try - { - newvalue = property.GetValue(value, BindingFlags.Public | BindingFlags.GetProperty, null, null, CultureInfo.InvariantCulture); - haveValue = true; - } - catch (TargetInvocationException e) - { - textBuilder.Append(e.InnerException.GetType().Name); - textBuilder.Append(": "); - textBuilder.Append(e.InnerException.Message); - } - if (haveValue) - { - WriteObject(textBuilder, newvalue, cultureInfo, used, indent + 1, recursionLimit); - } - } - } - } - hasinfo = true; - } - if (!hasinfo) - { - textBuilder.Append(valuetype.Name); - textBuilder.Append('<'); - MethodInfo method = valuetype.GetMethod("ToString", new Type[] { typeof(IFormatProvider) }); - if (null != method) - { - textBuilder.Append((string)method.Invoke(value, new object[] { cultureInfo })); - } - else - { - string text = value.ToString(); - textBuilder.Append(text); - } - textBuilder.Append('>'); - } - } - } - } - } - - private void ExecuteNonQueryCommand(string cmdText) - { - using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) - using (SqlCommand cmd = conn.CreateCommand()) - { - conn.Open(); - cmd.CommandText = cmdText; - cmd.ExecuteNonQuery(); - } - } - - private void AppendNewLineIndent(StringBuilder textBuilder, int indent) - { - textBuilder.Append(Environment.NewLine); - char[] buf = _appendNewLineIndentBuffer; - if (buf.Length < indent * 4) - { - buf = new char[indent * 4]; - for (int i = 0; i < buf.Length; ++i) - { - buf[i] = ' '; - } - _appendNewLineIndentBuffer = buf; - } - textBuilder.Append(buf, 0, indent * 4); - } - - private class PropertyInfoCompare : IComparer - { - internal static PropertyInfoCompare s_default = new PropertyInfoCompare(); - - private PropertyInfoCompare() - { - } - - public int Compare(object x, object y) - { - string propertyInfoName1 = ((PropertyInfo)x).Name; - string propertyInfoName2 = ((PropertyInfo)y).Name; - - return CultureInfo.InvariantCulture.CompareInfo.Compare(propertyInfoName1, propertyInfoName2, CompareOptions.IgnoreCase); - } - } - - private class FieldInfoCompare : IComparer - { - internal static FieldInfoCompare s_default = new FieldInfoCompare(); - - private FieldInfoCompare() - { - } - - public int Compare(object x, object y) - { - string fieldInfoName1 = ((FieldInfo)x).Name; - string fieldInfoName2 = ((FieldInfo)y).Name; - - return CultureInfo.InvariantCulture.CompareInfo.Compare(fieldInfoName1, fieldInfoName2, CompareOptions.IgnoreCase); - } - } - #endregion - } -} +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. + +//using System; +//using System.Collections; +//using System.Collections.Generic; +//using System.Data; +//using System.Data.SqlTypes; +//using System.Diagnostics; +//using System.Globalization; +//using System.Reflection; +//using System.Text; +//using Xunit; + +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ +// public class AdapterTest +// { +// private char[] _appendNewLineIndentBuffer = new char[0]; + +// // data value and server consts +// private const string MagicName = "Magic"; +// // Use a union statement so that Identity columns don't carry over +// private const string _createTableQuery = "select * into {0} from Employees where EmployeeID < 3 union all (select * from Employees where 1 = 0)"; +// private string _tempTable; +// private string _tempKey; +// private string _randomGuid; + +// // data type +// private decimal _c_numeric_val; +// private long _c_bigint_val; +// private byte[] _c_unique_val; +// private Guid _c_guid_val; +// private byte[] _c_varbinary_val; +// private byte[] _c_binary_val; +// private decimal _c_money_val; +// private decimal _c_smallmoney_val; +// private DateTime _c_datetime_val; +// private DateTime _c_smalldatetime_val; +// private string _c_nvarchar_val; +// private string _c_nchar_val; +// private string _c_varchar_val; +// private string _c_char_val; +// private int _c_int_val; +// private short _c_smallint_val; +// private byte _c_tinyint_val; +// private bool _c_bit_val; +// private double _c_float_val; +// private float _c_real_val; + +// private object[] _values; + +// public AdapterTest() +// { +// // create random name for temp tables +// _tempTable = DataTestUtility.GetUniqueName("AdapterTest"); +// _tempTable = _tempTable.Replace('-', '_'); + +// _randomGuid = Guid.NewGuid().ToString(); +// _tempKey = "employee_id_key_" + Environment.TickCount.ToString() + _randomGuid; +// _tempKey = _tempKey.Replace('-', '_'); + +// InitDataValues(); +// } + +// // TODO Synapse: Remove Northwind dependency by creating required tables in setup. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public void SimpleFillTest() +// { +// using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) +// using (SqlDataAdapter adapter = new SqlDataAdapter("SELECT EmployeeID, LastName, FirstName, Title, Address, City, Region, PostalCode, Country FROM Employees", conn)) +// { +// DataSet employeesSet = new DataSet(); +// DataTestUtility.AssertEqualsWithDescription(0, employeesSet.Tables.Count, "Unexpected tables count before fill."); +// adapter.Fill(employeesSet, "Employees"); + +// DataTestUtility.AssertEqualsWithDescription(1, employeesSet.Tables.Count, "Unexpected tables count after fill."); +// DataTestUtility.AssertEqualsWithDescription("Employees", employeesSet.Tables[0].TableName, "Unexpected table name."); + +// DataTestUtility.AssertEqualsWithDescription(9, employeesSet.Tables["Employees"].Columns.Count, "Unexpected columns count."); +// employeesSet.Tables["Employees"].Columns.Remove("LastName"); +// employeesSet.Tables["Employees"].Columns.Remove("FirstName"); +// employeesSet.Tables["Employees"].Columns.Remove("Title"); +// DataTestUtility.AssertEqualsWithDescription(6, employeesSet.Tables["Employees"].Columns.Count, "Unexpected columns count after column removal."); +// } +// } + +// // TODO Synapse: Remove Northwind dependency by creating required tables in setup. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public void PrepUnprepTest() +// { +// // share the connection +// using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) +// using (SqlCommand cmd = new SqlCommand("select * from shippers", connection)) +// using (SqlDataAdapter sqlAdapter = new SqlDataAdapter()) +// { +// cmd.Connection.Open(); + +// DataSet dataSet = new DataSet(); +// sqlAdapter.TableMappings.Add("Table", "shippers"); + +// cmd.CommandText = "Select * from shippers"; +// sqlAdapter.SelectCommand = cmd; +// sqlAdapter.Fill(dataSet); + +// DataTestUtility.AssertEqualsWithDescription( +// 3, dataSet.Tables[0].Rows.Count, +// "Exec1: Unexpected number of shipper rows."); + +// dataSet.Reset(); +// sqlAdapter.Fill(dataSet); + +// DataTestUtility.AssertEqualsWithDescription( +// 3, dataSet.Tables[0].Rows.Count, +// "Exec2: Unexpected number of shipper rows."); + +// dataSet.Reset(); +// cmd.CommandText = "select * from shippers where shipperId < 3"; +// sqlAdapter.Fill(dataSet); + +// DataTestUtility.AssertEqualsWithDescription( +// 2, dataSet.Tables[0].Rows.Count, +// "Exec3: Unexpected number of shipper rows."); + +// dataSet.Reset(); + +// sqlAdapter.Fill(dataSet); +// DataTestUtility.AssertEqualsWithDescription( +// 2, dataSet.Tables[0].Rows.Count, +// "Exec4: Unexpected number of shipper rows."); + +// cmd.CommandText = "select * from shippers"; +// cmd.Prepare(); + +// int i = 0; +// using (SqlDataReader reader = cmd.ExecuteReader()) +// { +// DataTestUtility.AssertEqualsWithDescription(3, reader.FieldCount, "Unexpected FieldCount."); + +// while (reader.Read()) +// { +// i++; +// } +// } +// DataTestUtility.AssertEqualsWithDescription(3, i, "Unexpected read count."); + +// cmd.CommandText = "select * from orders where orderid < @p1"; +// cmd.Parameters.AddWithValue("@p1", 10250); +// using (SqlDataReader reader = cmd.ExecuteReader()) +// { +// DataTestUtility.AssertEqualsWithDescription(14, reader.FieldCount, "Unexpected FieldCount."); + +// i = 0; +// while (reader.Read()) +// { +// i++; +// } +// } +// DataTestUtility.AssertEqualsWithDescription(2, i, "Unexpected read count."); + +// cmd.Parameters["@p1"].Value = 10249; +// using (SqlDataReader reader = cmd.ExecuteReader()) +// { +// DataTestUtility.AssertEqualsWithDescription(14, reader.FieldCount, "Unexpected FieldCount."); + +// i = 0; +// while (reader.Read()) +// { +// i++; +// } +// } +// DataTestUtility.AssertEqualsWithDescription(1, i, "Unexpected read count."); +// } +// } + +// // Synapse: Create table statement contains a data type that is unsupported in Parallel Data Warehouse. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public void SqlVariantTest() +// { +// string tableName = DataTestUtility.GenerateObjectName(); +// // good test for null values and unicode strings +// using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) +// using (SqlCommand cmd = new SqlCommand(null, conn)) +// using (SqlDataAdapter sqlAdapter = new SqlDataAdapter()) +// { +// try +// { +// ExecuteNonQueryCommand("CREATE TABLE " + tableName + " (c0_bigint bigint, c1_variant sql_variant)"); + +// cmd.Connection.Open(); + +// // the ORDER BY clause tests that we correctly ignore the ORDER token +// cmd.CommandText = "select * from " + tableName; +// sqlAdapter.SelectCommand = cmd; +// sqlAdapter.TableMappings.Add(tableName, "rowset"); + +// // insert +// sqlAdapter.InsertCommand = new SqlCommand() +// { +// CommandText = "INSERT INTO " + tableName + "(c0_bigint, c1_variant) " + +// "VALUES (@bigint, @variant)" +// }; +// SqlParameter p = sqlAdapter.InsertCommand.Parameters.Add(new SqlParameter("@bigint", SqlDbType.BigInt)); +// p.SourceColumn = "c0_bigint"; +// p = sqlAdapter.InsertCommand.Parameters.Add(new SqlParameter("@variant", SqlDbType.Variant)); +// p.SourceColumn = "c1_variant"; +// sqlAdapter.InsertCommand.Connection = cmd.Connection; + +// DataSet dataSet = new DataSet(); +// sqlAdapter.FillSchema(dataSet, SchemaType.Mapped, tableName); + +// DataRow datarow = null; +// for (int i = 0; i < _values.Length; i++) +// { +// // add each variant type +// datarow = dataSet.Tables[0].NewRow(); +// datarow.ItemArray = new object[] { 1, _values[i] }; +// datarow.Table.Rows.Add(datarow); +// } + +// sqlAdapter.Update(dataSet, tableName); + +// // now reload and make sure we got the values we wrote out +// dataSet.Reset(); +// sqlAdapter.Fill(dataSet, tableName); + +// DataColumnCollection cols = dataSet.Tables[0].Columns; +// DataRowCollection rows = dataSet.Tables[0].Rows; + +// Assert.True(rows.Count == _values.Length, "FAILED: SqlVariant didn't update all the rows!"); + +// for (int i = 0; i < rows.Count; i++) +// { +// DataRow row = rows[i]; +// object value = row[1]; + +// if (_values[i].GetType() == typeof(byte[]) || _values[i].GetType() == typeof(Guid)) +// { +// byte[] bsrc; +// byte[] bdst; + +// if (_values[i].GetType() == typeof(Guid)) +// { +// bsrc = ((Guid)value).ToByteArray(); +// bdst = ((Guid)(_values[i])).ToByteArray(); +// } +// else +// { +// bsrc = (byte[])value; +// bdst = (byte[])_values[i]; +// } + +// Assert.True(ByteArraysEqual(bsrc, bdst), "FAILED: Byte arrays are unequal"); +// } +// else if (_values[i].GetType() == typeof(bool)) +// { +// Assert.True(Convert.ToBoolean(value) == (bool)_values[i], "FAILED: " + DBConvertToString(value) + " is not equal to " + DBConvertToString(_values[i])); +// } +// else +// { +// Assert.True(value.Equals(_values[i]), "FAILED: " + DBConvertToString(value) + " is not equal to " + DBConvertToString(_values[i])); +// } +// } +// } +// finally +// { +// DataTestUtility.DropTable(conn, tableName); +// } +// } +// } + +// // Synapse: The RETURN statement can only be used in user-defined functions. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public void ParameterTest_AllTypes() +// { +// string procName = DataTestUtility.GenerateObjectName(); +// string spCreateAllTypes = +// "CREATE PROCEDURE " + procName + " " + +// "@Cnumeric numeric(10,2) OUTPUT, " + +// "@Cunique uniqueidentifier OUTPUT, " + +// "@Cnvarchar nvarchar(10) OUTPUT, " + +// "@Cnchar nchar(10) OUTPUT, " + +// "@Cbit bit OUTPUT, " + +// "@Ctinyint tinyint OUTPUT, " + +// "@Cvarbinary varbinary(16) OUTPUT, " + +// "@Cbinary binary(16) OUTPUT, " + +// "@Cchar char(10) OUTPUT, " + +// "@Cmoney money OUTPUT, " + +// "@Csmallmoney smallmoney OUTPUT, " + +// "@Cint int OUTPUT, " + +// "@Csmallint smallint OUTPUT, " + +// "@Cfloat float OUTPUT, " + +// "@Creal real OUTPUT, " + +// "@Cdatetime datetime OUTPUT, " + +// "@Csmalldatetime smalldatetime OUTPUT, " + +// "@Cvarchar varchar(10) OUTPUT " + +// "AS SELECT " + +// "@Cnumeric=@Cnumeric, " + +// "@Cunique=@Cunique, " + +// "@Cnvarchar=@Cnvarchar, " + +// "@Cnchar=@Cnchar, " + +// "@Cbit=@Cbit, " + +// "@Ctinyint=@Ctinyint, " + +// "@Cvarbinary=@Cvarbinary, " + +// "@Cbinary=@Cbinary, " + +// "@Cchar=@Cchar, " + +// "@Cmoney=@Cmoney, " + +// "@Csmallmoney=@Csmallmoney, " + +// "@Cint=@Cint, " + +// "@Csmallint=@Csmallint, " + +// "@Cfloat=@Cfloat, " + +// "@Creal=@Creal, " + +// "@Cdatetime=@Cdatetime, " + +// "@Csmalldatetime=@Csmalldatetime, " + +// "@Cvarchar=@Cvarchar " + +// "RETURN(42)"; + +// string spDropAllTypes = "DROP PROCEDURE " + procName; +// bool dropSP = false; + +// try +// { +// ExecuteNonQueryCommand(spCreateAllTypes); +// dropSP = true; + +// using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) +// using (SqlCommand cmd = new SqlCommand(procName, conn)) +// using (SqlDataAdapter sqlAdapter = new SqlDataAdapter()) +// { +// conn.Open(); + +// SqlParameter param = cmd.Parameters.Add(new SqlParameter("@Cnumeric", SqlDbType.Decimal)); +// param.Precision = 10; +// param.Scale = 2; +// param.Direction = ParameterDirection.InputOutput; +// cmd.Parameters[0].Value = _c_numeric_val; + +// param = cmd.Parameters.Add(new SqlParameter("@Cunique", SqlDbType.UniqueIdentifier)); +// param.Direction = ParameterDirection.InputOutput; +// cmd.Parameters[1].Value = _c_guid_val; + +// cmd.Parameters.Add(new SqlParameter("@Cnvarchar", SqlDbType.NVarChar, 10)); +// cmd.Parameters[2].Direction = ParameterDirection.InputOutput; +// cmd.Parameters[2].Value = _c_nvarchar_val; + +// cmd.Parameters.Add(new SqlParameter("@Cnchar", SqlDbType.NChar, 10)); +// cmd.Parameters[3].Direction = ParameterDirection.InputOutput; +// cmd.Parameters[3].Value = _c_nchar_val; + +// param = cmd.Parameters.Add(new SqlParameter("@Cbit", SqlDbType.Bit)); +// param.Direction = ParameterDirection.InputOutput; +// cmd.Parameters[4].Value = _c_bit_val; + +// param = cmd.Parameters.Add(new SqlParameter("@Ctinyint", SqlDbType.TinyInt)); +// param.Direction = ParameterDirection.InputOutput; +// cmd.Parameters[5].Value = _c_tinyint_val; + +// cmd.Parameters.Add(new SqlParameter("@Cvarbinary", SqlDbType.VarBinary, 16)); +// cmd.Parameters[6].Direction = ParameterDirection.InputOutput; +// cmd.Parameters[6].Value = _c_varbinary_val; + +// cmd.Parameters.Add(new SqlParameter("@Cbinary", SqlDbType.Binary, 16)); +// cmd.Parameters[7].Direction = ParameterDirection.InputOutput; +// cmd.Parameters[7].Value = _c_binary_val; + +// cmd.Parameters.Add(new SqlParameter("@Cchar", SqlDbType.Char, 10)); +// cmd.Parameters[8].Direction = ParameterDirection.InputOutput; +// cmd.Parameters[8].Value = _c_char_val; + +// param = cmd.Parameters.Add(new SqlParameter("@Cmoney", SqlDbType.Money)); +// param.Direction = ParameterDirection.InputOutput; +// param.Scale = 4; +// cmd.Parameters[9].Value = _c_money_val; + +// param = cmd.Parameters.Add(new SqlParameter("@Csmallmoney", SqlDbType.SmallMoney)); +// param.Direction = ParameterDirection.InputOutput; +// param.Scale = 4; +// cmd.Parameters[10].Value = _c_smallmoney_val; + +// param = cmd.Parameters.Add(new SqlParameter("@Cint", SqlDbType.Int)); +// param.Direction = ParameterDirection.InputOutput; +// cmd.Parameters[11].Value = _c_int_val; + +// param = cmd.Parameters.Add(new SqlParameter("@Csmallint", SqlDbType.SmallInt)); +// param.Direction = ParameterDirection.InputOutput; +// cmd.Parameters[12].Value = _c_smallint_val; + +// param = cmd.Parameters.Add(new SqlParameter("@Cfloat", SqlDbType.Float)); +// param.Direction = ParameterDirection.InputOutput; +// cmd.Parameters[13].Value = _c_float_val; + +// param = cmd.Parameters.Add(new SqlParameter("@Creal", SqlDbType.Real)); +// param.Direction = ParameterDirection.InputOutput; +// cmd.Parameters[14].Value = _c_real_val; + +// param = cmd.Parameters.Add(new SqlParameter("@Cdatetime", SqlDbType.DateTime)); +// param.Direction = ParameterDirection.InputOutput; +// cmd.Parameters[15].Value = _c_datetime_val; + +// param = cmd.Parameters.Add(new SqlParameter("@Csmalldatetime", SqlDbType.SmallDateTime)); +// param.Direction = ParameterDirection.InputOutput; +// cmd.Parameters[16].Value = _c_smalldatetime_val; + +// param = cmd.Parameters.Add(new SqlParameter("@Cvarchar", SqlDbType.VarChar, 10)); +// param.Direction = ParameterDirection.InputOutput; +// cmd.Parameters[17].Value = _c_varchar_val; + +// param = cmd.Parameters.Add(new SqlParameter("@return", SqlDbType.Int)); +// param.Direction = ParameterDirection.ReturnValue; +// cmd.Parameters[18].Value = 17; // will be overwritten + +// cmd.CommandType = CommandType.StoredProcedure; +// cmd.ExecuteNonQuery(); + +// string[] expectedStringValues = +// { +// "@Cnumeric : Decimal<42424242.42>", +// null, +// "@Cnvarchar : String:10<1234567890>", +// "@Cnchar : String:10<1234567890>", +// "@Cbit : Boolean", +// "@Ctinyint : Byte<255>", +// null, +// null, +// "@Cchar : String:10<1234567890>", +// null, +// null, +// "@Cint : Int32<-1>", +// "@Csmallint : Int16<-1>", +// "@Cfloat : Double<12345678.2>", +// "@Creal : Single<12345.1>", +// null, +// null, +// "@Cvarchar : String:10<1234567890>", +// "@return : Int32<42>" +// }; + +// for (int i = 0; i < cmd.Parameters.Count; i++) +// { +// param = cmd.Parameters[i]; +// switch (param.SqlDbType) +// { +// case SqlDbType.Binary: +// Assert.True(ByteArraysEqual(_c_binary_val, (byte[])param.Value), "FAILED: " + procName + ", Binary parameter"); +// break; +// case SqlDbType.VarBinary: +// Assert.True(ByteArraysEqual(_c_varbinary_val, (byte[])param.Value), "FAILED: " + procName + ", VarBinary parameter"); +// break; +// case SqlDbType.UniqueIdentifier: +// DataTestUtility.AssertEqualsWithDescription(_c_guid_val, (Guid)param.Value, "FAILED: " + procName + ", UniqueIdentifier parameter"); +// break; +// case SqlDbType.DateTime: +// Assert.True(0 == DateTime.Compare((DateTime)param.Value, _c_datetime_val), "FAILED: " + procName + ", DateTime parameter"); +// break; +// case SqlDbType.SmallDateTime: +// Assert.True(0 == DateTime.Compare((DateTime)param.Value, _c_smalldatetime_val), "FAILED: " + procName + ", SmallDateTime parameter"); +// break; +// case SqlDbType.Money: +// Assert.True( +// 0 == decimal.Compare((decimal)param.Value, _c_money_val), +// string.Format("FAILED: " + procName + ", Money parameter. Expected: {0}. Actual: {1}.", _c_money_val, (decimal)param.Value)); +// break; +// case SqlDbType.SmallMoney: +// Assert.True( +// 0 == decimal.Compare((decimal)param.Value, _c_smallmoney_val), +// string.Format("FAILED: " + procName + ", SmallMoney parameter. Expected: {0}. Actual: {1}.", _c_smallmoney_val, (decimal)param.Value)); +// break; +// default: +// string actualValue = param.ParameterName + " : " + DBConvertToString(cmd.Parameters[i].Value); +// DataTestUtility.AssertEqualsWithDescription(actualValue, expectedStringValues[i], "Unexpected parameter value."); +// break; +// } +// } +// } +// } +// finally +// { +// if (dropSP) +// { +// ExecuteNonQueryCommand(spDropAllTypes); +// } +// } +// } + +// // Synapse: The RETURN statement can only be used in user-defined functions. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public void ParameterTest_InOut() +// { +// string procName = DataTestUtility.GetUniqueName("P"); +// // input, output +// string spCreateInOut = +// "CREATE PROCEDURE " + procName + " @in int, @inout int OUTPUT, @out nvarchar(8) OUTPUT " + +// "AS SELECT @inout = (@in + @inout), @out = 'Success!' " + +// "SELECT * From shippers where ShipperID = @in " + +// "RETURN(42)"; + +// string spDropInOut = "DROP PROCEDURE " + procName; +// bool dropSP = false; + +// try +// { +// ExecuteNonQueryCommand(spCreateInOut); +// dropSP = true; + +// using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) +// using (SqlCommand cmd = new SqlCommand(procName, conn)) +// using (SqlDataAdapter sqlAdapter = new SqlDataAdapter()) +// { +// conn.Open(); + +// cmd.CommandType = CommandType.StoredProcedure; +// cmd.Parameters.Add(new SqlParameter("@in", SqlDbType.Int)); +// cmd.Parameters[0].Value = 2; + +// SqlParameter param = cmd.Parameters.Add(new SqlParameter("@inout", SqlDbType.Int)); +// param.Direction = ParameterDirection.InputOutput; +// cmd.Parameters[1].Value = 1998; + +// param = cmd.Parameters.Add(new SqlParameter("@out", SqlDbType.NVarChar, 8)); +// param.Direction = ParameterDirection.Output; + +// param = cmd.Parameters.Add(new SqlParameter("@ret", SqlDbType.Int)); +// param.Direction = ParameterDirection.ReturnValue; + +// DataSet dataSet = new DataSet(); +// sqlAdapter.TableMappings.Add("Table", "shipper"); +// sqlAdapter.SelectCommand = cmd; +// sqlAdapter.Fill(dataSet); + +// // check our ouput and return value params +// Assert.True(VerifyOutputParams(cmd.Parameters), "FAILED: InputOutput parameter test with returned rows and bound return value!"); + +// Assert.True(1 == dataSet.Tables[0].Rows.Count, "FAILED: Expected 1 row to be loaded in the dataSet!"); + +// DataRow row = dataSet.Tables[0].Rows[0]; +// Assert.True((int)row["ShipperId"] == 2, "FAILED: ShipperId column should be 2, not " + DBConvertToString(row["ShipperId"])); + +// // remember to reset params +// cmd.Parameters[0].Value = 2; +// cmd.Parameters[1].Value = 1998; +// cmd.Parameters[2].Value = Convert.DBNull; +// cmd.Parameters[3].Value = Convert.DBNull; + +// // now exec the same thing without a data set +// cmd.ExecuteNonQuery(); + +// // check our ouput and return value params +// Assert.True(VerifyOutputParams(cmd.Parameters), "FAILED: InputOutput parameter test with no returned rows and bound return value!"); + +// // now unbind the return value +// cmd.Parameters.RemoveAt(3); + +// // remember to reset input params +// cmd.Parameters[0].Value = 1; // use 1, just for the heck of it +// cmd.Parameters[1].Value = 1999; +// cmd.Parameters[2].Value = Convert.DBNull; + +// dataSet.Reset(); + +// sqlAdapter.Fill(dataSet); + +// // verify the ouptut parameter +// Assert.True( +// ((int)cmd.Parameters[1].Value == 2000) && +// (0 == string.Compare(cmd.Parameters[2].Value.ToString(), "Success!", false, CultureInfo.InvariantCulture)), +// "FAILED: unbound return value case, output param is not correct!"); + +// Assert.True(1 == dataSet.Tables[0].Rows.Count, "FAILED: Expected 1 row to be loaded in the dataSet!"); + +// row = dataSet.Tables[0].Rows[0]; +// Assert.True((int)row["ShipperId"] == 1, "FAILED: ShipperId column should be 1, not " + DBConvertToString(row["ShipperId"])); +// } +// } +// finally +// { +// if (dropSP) +// { +// ExecuteNonQueryCommand(spDropInOut); +// } +// } +// } + +// // TODO Synapse: Remove Northwind dependency by creating required tables in setup. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public void UpdateTest() +// { +// using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) +// using (SqlCommand cmd = conn.CreateCommand()) +// using (SqlDataAdapter adapter = new SqlDataAdapter()) +// using (SqlDataAdapter adapterVerify = new SqlDataAdapter()) +// { +// conn.Open(); + +// cmd.CommandText = string.Format(_createTableQuery, _tempTable); +// cmd.ExecuteNonQuery(); +// cmd.CommandText = "alter table " + _tempTable + " add constraint " + _tempKey + " primary key (EmployeeID)"; +// cmd.ExecuteNonQuery(); + +// try +// { +// PrepareUpdateCommands(adapter, conn, _tempTable); + +// adapter.SelectCommand = new SqlCommand(string.Format("SELECT EmployeeID, LastName, FirstName, Title, Address, City, Region, PostalCode, Country from {0} where EmployeeID < 3", _tempTable), conn); +// adapterVerify.SelectCommand = new SqlCommand("SELECT LastName, FirstName FROM " + _tempTable + " where FirstName='" + MagicName + "'", conn); + +// adapter.TableMappings.Add(_tempTable, "rowset"); +// adapterVerify.TableMappings.Add(_tempTable, "rowset"); + +// DataSet dataSet = new DataSet(); +// VerifyFillSchemaResult(adapter.FillSchema(dataSet, SchemaType.Mapped, _tempTable), new string[] { "rowset" }); + +// // FillSchema +// dataSet.Tables["rowset"].PrimaryKey = new DataColumn[] { dataSet.Tables["rowset"].Columns["EmployeeID"] }; +// adapter.Fill(dataSet, _tempTable); + +// // Fill from Database +// Assert.True(dataSet.Tables[0].Rows.Count == 2, "FAILED: Fill after FillSchema should populate the dataSet with two rows!"); + +// dataSet.AcceptChanges(); + +// // Verify that set is empty +// DataSet dataSetVerify = new DataSet(); +// VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); + +// // Insert +// DataRow datarow = dataSet.Tables["rowset"].NewRow(); +// datarow.ItemArray = new object[] { "11", "The Original", MagicName, "Engineer", "One Microsoft Way", "Redmond", "WA", "98052", "USA" }; +// datarow.Table.Rows.Add(datarow); + +// adapter.Update(dataSet, _tempTable); + +// // Verify that set has one 'Magic' entry +// VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); + +// dataSet.AcceptChanges(); + +// // Update +// datarow = dataSet.Tables["rowset"].Rows.Find("11"); +// datarow.BeginEdit(); +// datarow.ItemArray = new object[] { "11", "The New and Improved", MagicName, "reenignE", "Yaw Tfosorcim Eno", "Dnomder", "WA", "52098", "ASU" }; +// datarow.EndEdit(); + +// adapter.Update(dataSet, _tempTable); + +// // Verify that set has updated 'Magic' entry +// VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); + +// dataSet.AcceptChanges(); + +// // Delete +// dataSet.Tables["rowset"].Rows.Find("11").Delete(); +// adapter.Update(dataSet, _tempTable); + +// // Verify that set is empty +// VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); + +// dataSet.AcceptChanges(); +// } +// finally +// { +// DataTestUtility.DropTable(conn, _tempTable); +// } +// } +// } + +// // these next texts verify that 'bulk' operations work. If each command type modifies more than three rows, then we do a Prep/Exec instead of +// // adhoc ExecuteSql. +// // TODO Synapse: Remove Northwind dependency by creating required tables in setup. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public void BulkUpdateTest() +// { +// using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) +// using (SqlCommand cmd = conn.CreateCommand()) +// using (SqlDataAdapter adapter = new SqlDataAdapter()) +// using (SqlDataAdapter adapterVerify = new SqlDataAdapter()) +// { +// conn.Open(); + +// cmd.CommandText = string.Format(_createTableQuery, _tempTable); +// cmd.ExecuteNonQuery(); +// cmd.CommandText = "alter table " + _tempTable + " add constraint " + _tempKey + " primary key (EmployeeID)"; +// cmd.ExecuteNonQuery(); + +// try +// { +// PrepareUpdateCommands(adapter, conn, _tempTable); + +// adapter.SelectCommand = new SqlCommand("SELECT EmployeeID, LastName, FirstName, Title, Address, City, Region, PostalCode, Country FROM " + _tempTable + " WHERE EmployeeID < 3", conn); +// adapterVerify.SelectCommand = new SqlCommand("SELECT LastName, FirstName FROM " + _tempTable + " where FirstName='" + MagicName + "'", conn); + +// adapter.TableMappings.Add(_tempTable, "rowset"); +// adapterVerify.TableMappings.Add(_tempTable, "rowset"); + +// DataSet dataSet = new DataSet(); +// adapter.FillSchema(dataSet, SchemaType.Mapped, _tempTable); + +// dataSet.Tables["rowset"].PrimaryKey = new DataColumn[] { dataSet.Tables["rowset"].Columns["EmployeeID"] }; +// adapter.Fill(dataSet, _tempTable); +// dataSet.AcceptChanges(); + +// // Verify that set is empty +// DataSet dataSetVerify = new DataSet(); +// VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); + +// // Bulk Insert (10 records) +// DataRow datarow = null; +// const int cOps = 5; +// for (int i = 0; i < cOps * 2; i++) +// { +// datarow = dataSet.Tables["rowset"].NewRow(); +// string sid = "99999000" + i.ToString(); +// datarow.ItemArray = new object[] { sid, "Bulk Insert" + i.ToString(), MagicName, "Engineer", "One Microsoft Way", "Redmond", "WA", "98052", "USA" }; +// datarow.Table.Rows.Add(datarow); +// } +// adapter.Update(dataSet, _tempTable); + +// // Verify that set has 10 'Magic' entries +// VerifyUpdateRow(adapterVerify, dataSetVerify, 10, _tempTable); +// dataSet.AcceptChanges(); + +// // Bulk Update (first 5) +// for (int i = 0; i < cOps; i++) +// { +// string sid = "99999000" + i.ToString(); +// datarow = dataSet.Tables["rowset"].Rows.Find(sid); +// datarow.BeginEdit(); +// datarow.ItemArray = new object[] { sid, "Bulk Update" + i.ToString(), MagicName, "reenignE", "Yaw Tfosorcim Eno", "Dnomder", "WA", "52098", "ASU" }; +// datarow.EndEdit(); +// } + +// // Bulk Delete (last 5) +// for (int i = cOps; i < cOps * 2; i++) +// { +// string sid = "99999000" + i.ToString(); +// dataSet.Tables["rowset"].Rows.Find(sid).Delete(); +// } + +// // now update the dataSet with the insert and delete changes +// adapter.Update(dataSet, _tempTable); + +// // Verify that set has 5 'Magic' updated entries +// VerifyUpdateRow(adapterVerify, dataSetVerify, 5, _tempTable); +// dataSet.AcceptChanges(); + +// // clean up the remaining 5 rows +// for (int i = 0; i < cOps; i++) +// { +// string sid = "99999000" + i.ToString(); +// dataSet.Tables["rowset"].Rows.Find(sid).Delete(); +// } +// adapter.Update(dataSet, _tempTable); + +// // Verify that set has no entries +// VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); +// dataSet.AcceptChanges(); +// } +// finally +// { +// DataTestUtility.DropTable(conn, _tempTable); +// } +// } +// } + +// // Makes sure that we can refresh an identity column in the dataSet +// // for a newly inserted row +// // Synapse: Must declare the scalar variable "@@IDENTITY". +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public void UpdateRefreshTest() +// { +// string identTableName = DataTestUtility.GetUniqueName("ID_"); +// string createIdentTable = +// $"CREATE TABLE {identTableName} (id int IDENTITY," + +// "LastName nvarchar(50) NULL," + +// "Firstname nvarchar(50) NULL)"; + +// string spName = DataTestUtility.GetUniqueName("sp_insert", withBracket: false); +// string spCreateInsert = +// $"CREATE PROCEDURE {spName}" + +// "(@FirstName nvarchar(50), @LastName nvarchar(50), @id int OUTPUT) " + +// "AS INSERT INTO " + _tempTable + " (FirstName, LastName) " + +// "VALUES (@FirstName, @LastName); " + +// "SELECT @id=@@IDENTITY"; + +// string spDropInsert = $"DROP PROCEDURE {spName}"; +// bool dropSP = false; + +// using (SqlDataAdapter adapter = new SqlDataAdapter()) +// using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) +// using (SqlCommand cmd = new SqlCommand(null, conn)) +// using (SqlCommand temp = new SqlCommand("SELECT id, LastName, FirstName into " + _tempTable + $" from {identTableName}", conn)) +// using (SqlCommand tableClean = new SqlCommand("", conn)) +// { +// ExecuteNonQueryCommand(createIdentTable); +// try +// { +// adapter.InsertCommand = new SqlCommand() +// { +// CommandText = spName, +// CommandType = CommandType.StoredProcedure +// }; +// adapter.InsertCommand.Parameters.Add(new SqlParameter("@FirstName", SqlDbType.NVarChar, 50, "FirstName")); +// adapter.InsertCommand.Parameters.Add(new SqlParameter("@LastName", SqlDbType.NVarChar, 50, "LastName")); +// SqlParameter param = adapter.InsertCommand.Parameters.Add(new SqlParameter("@id", SqlDbType.Int)); +// param.SourceColumn = "id"; +// param.Direction = ParameterDirection.Output; + +// adapter.InsertCommand.Parameters.Add(new SqlParameter("@badapple", SqlDbType.NVarChar, 50, "LastName")); +// adapter.RowUpdating += new SqlRowUpdatingEventHandler(RowUpdating_UpdateRefreshTest); +// adapter.RowUpdated += new SqlRowUpdatedEventHandler(RowUpdated_UpdateRefreshTest); + +// adapter.InsertCommand.Connection = conn; +// conn.Open(); + +// temp.ExecuteNonQuery(); + +// // start clean +// tableClean.CommandText = "delete " + _tempTable; +// tableClean.ExecuteNonQuery(); +// tableClean.CommandText = spCreateInsert; +// tableClean.ExecuteNonQuery(); + +// dropSP = true; + +// DataSet ds = new DataSet(); +// adapter.TableMappings.Add("Table", _tempTable); +// cmd.CommandText = "select * from " + _tempTable; +// adapter.SelectCommand = cmd; +// adapter.Fill(ds, "Table"); + +// // Insert +// DataRow row1 = ds.Tables[_tempTable].NewRow(); +// row1.ItemArray = new object[] { 0, "Bond", "James" }; +// row1.Table.Rows.Add(row1); + +// DataRow row2 = ds.Tables[_tempTable].NewRow(); +// row2.ItemArray = new object[] { 0, "Lee", "Bruce" }; +// row2.Table.Rows.Add(row2); + +// Assert.True((int)row1["id"] == 0 && (int)row2["id"] == 0, "FAILED: UpdateRefresh should not have values for identity columns"); + +// adapter.Update(ds, "Table"); + +// // should have values now +// int i1 = (int)row1["id"]; +// int i2 = (int)row2["id"]; + +// Assert.True( +// (i1 != 0) && (i2 != 0) && (i2 == (i1 + 1)), +// string.Format("FAILED: UpdateRefresh, i2 should equal (i1 + 1). i1: {0}. i2: {1}.", i1, i2)); +// } +// finally +// { +// if (dropSP) +// { +// DataTestUtility.DropStoredProcedure(conn, spName); +// DataTestUtility.DropTable(conn, _tempTable); +// DataTestUtility.DropTable(conn, identTableName); +// } +// } +// } +// } + +// // Synapse: Create table statement contains a data type that is unsupported in Parallel Data Warehouse. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public void UpdateNullTest() +// { +// string tableName = DataTestUtility.GenerateObjectName(); +// string procName = DataTestUtility.GenerateObjectName(); +// string createTable = "CREATE TABLE " + tableName + "(cvarbin VARBINARY(7000), cimage IMAGE)"; + +// string createSP = +// "CREATE PROCEDURE " + procName + " (@val_cvarbin VARBINARY(7000), @val_cimage IMAGE)" + +// "AS INSERT INTO " + tableName + " (cvarbin, cimage)" + +// "VALUES (@val_cvarbin, @val_cimage)"; +// bool dropSP = false; + + +// using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) +// using (SqlCommand cmdInsert = new SqlCommand(procName, conn)) +// using (SqlCommand cmdSelect = new SqlCommand("select * from " + tableName, conn)) +// using (SqlCommand tableClean = new SqlCommand("delete " + tableName, conn)) +// using (SqlDataAdapter adapter = new SqlDataAdapter()) +// { +// try +// { +// ExecuteNonQueryCommand(createTable); +// ExecuteNonQueryCommand(createSP); +// dropSP = true; +// conn.Open(); + +// cmdInsert.CommandType = CommandType.StoredProcedure; +// SqlParameter p1 = cmdInsert.Parameters.Add(new SqlParameter("@val_cvarbin", SqlDbType.VarBinary, 7000)); +// SqlParameter p2 = cmdInsert.Parameters.Add(new SqlParameter("@val_cimage", SqlDbType.Image, 8000)); + +// tableClean.ExecuteNonQuery(); +// p1.Value = Convert.DBNull; +// p2.Value = Convert.DBNull; +// int rowsAffected = cmdInsert.ExecuteNonQuery(); +// DataTestUtility.AssertEqualsWithDescription(1, rowsAffected, "Unexpected number of rows inserted."); + +// DataSet ds = new DataSet(); +// adapter.SelectCommand = cmdSelect; +// adapter.Fill(ds, "goofy"); +// // should have 1 row in table (with two null entries) +// DataTestUtility.AssertEqualsWithDescription(1, ds.Tables[0].Rows.Count, "Unexpected rows count."); +// DataTestUtility.AssertEqualsWithDescription(DBNull.Value, ds.Tables[0].Rows[0][0], "Unexpected value."); +// DataTestUtility.AssertEqualsWithDescription(DBNull.Value, ds.Tables[0].Rows[0][1], "Unexpected value."); +// } +// finally +// { +// if (dropSP) +// { +// DataTestUtility.DropStoredProcedure(conn, procName); +// DataTestUtility.DropTable(conn, tableName); +// } +// } +// } +// } + +// // Synapse: Create table statement contains a data type that is unsupported in Parallel Data Warehouse. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public void UpdateOffsetTest() +// { +// string tableName = DataTestUtility.GenerateObjectName(); +// string procName = DataTestUtility.GenerateObjectName(); +// string createTable = "CREATE TABLE " + tableName + "(cvarbin VARBINARY(7000), cimage IMAGE)"; + +// string createSP = +// "CREATE PROCEDURE " + procName + " (@val_cvarbin VARBINARY(7000), @val_cimage IMAGE)" + +// "AS INSERT INTO " + tableName + " (cvarbin, cimage)" + +// "VALUES (@val_cvarbin, @val_cimage)"; +// bool dropSP = false; + + +// using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) +// using (SqlCommand cmdInsert = new SqlCommand(procName, conn)) +// using (SqlCommand cmdSelect = new SqlCommand("select * from " + tableName, conn)) +// using (SqlCommand tableClean = new SqlCommand("delete " + tableName, conn)) +// using (SqlDataAdapter adapter = new SqlDataAdapter()) +// { +// try +// { +// ExecuteNonQueryCommand(createTable); +// ExecuteNonQueryCommand(createSP); +// dropSP = true; +// conn.Open(); + +// cmdInsert.CommandType = CommandType.StoredProcedure; +// SqlParameter p1 = cmdInsert.Parameters.Add(new SqlParameter("@val_cvarbin", SqlDbType.VarBinary, 7000)); +// SqlParameter p2 = cmdInsert.Parameters.Add(new SqlParameter("@val_cimage", SqlDbType.Image, 7000)); + +// tableClean.ExecuteNonQuery(); + +// byte[] b = new byte[7]; +// b[0] = 0x01; +// b[1] = 0x02; +// b[2] = 0x03; +// b[3] = 0x04; +// b[4] = 0x05; +// b[5] = 0x06; +// b[6] = 0x07; +// p1.Value = b; +// p1.Size = 4; + +// p2.Value = b; +// p2.Size = 3; +// p2.Offset = 4; +// int rowsAffected = cmdInsert.ExecuteNonQuery(); + +// DataSet ds = new DataSet(); +// adapter.SelectCommand = cmdSelect; +// adapter.Fill(ds, "goofy"); + +// byte[] expectedBytes1 = { 0x01, 0x02, 0x03, 0x04 }; +// byte[] val = (byte[])(ds.Tables[0].Rows[0][0]); +// Assert.True(ByteArraysEqual(expectedBytes1, val), "FAILED: Test 1: Unequal byte arrays."); + +// byte[] expectedBytes2 = { 0x05, 0x06, 0x07 }; +// val = (byte[])(ds.Tables[0].Rows[0][1]); +// Assert.True(ByteArraysEqual(expectedBytes2, val), "FAILED: Test 2: Unequal byte arrays."); +// } +// finally +// { +// if (dropSP) +// { +// DataTestUtility.DropStoredProcedure(conn, procName); +// DataTestUtility.DropTable(conn, tableName); +// } +// } +// } +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public void SelectAllTest() +// { +// // Test exceptions +// using (SqlDataAdapter sqlAdapter = new SqlDataAdapter(new SqlCommand("select * from sys.columns", new SqlConnection(DataTestUtility.TCPConnectionString)))) +// { +// DataSet dataset = new DataSet(); +// sqlAdapter.TableMappings.Add("View", "sys.columns"); +// sqlAdapter.Fill(dataset); +// } +// } + +// // AutoGen test +// // TODO Synapse: Remove Northwind dependency by creating required tables in setup. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public void AutoGenUpdateTest() +// { +// using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) +// using (SqlCommand cmd = conn.CreateCommand()) +// using (SqlDataAdapter adapter = new SqlDataAdapter()) +// using (SqlDataAdapter adapterVerify = new SqlDataAdapter()) +// { +// conn.Open(); + +// cmd.CommandText = string.Format(_createTableQuery, _tempTable); +// cmd.ExecuteNonQuery(); +// cmd.CommandText = "alter table " + _tempTable + " add constraint " + _tempKey + " primary key (EmployeeID)"; +// cmd.ExecuteNonQuery(); + +// try +// { +// adapter.SelectCommand = new SqlCommand(string.Format("SELECT EmployeeID, LastName, FirstName, Title, Address, City, Region, PostalCode, Country from {0} where EmployeeID < 3", _tempTable), conn); +// adapterVerify.SelectCommand = new SqlCommand("SELECT LastName, FirstName FROM " + _tempTable + " where FirstName='" + MagicName + "'", conn); + +// adapter.TableMappings.Add(_tempTable, "rowset"); +// adapterVerify.TableMappings.Add(_tempTable, "rowset"); + +// // FillSchema +// DataSet dataSet = new DataSet(); +// VerifyFillSchemaResult(adapter.FillSchema(dataSet, SchemaType.Mapped, _tempTable), new string[] { "rowset" }); + +// adapter.Fill(dataSet, _tempTable); + +// // Fill from Database +// Assert.True(dataSet.Tables[0].Rows.Count == 2, "FAILED: Fill after FillSchema should populate the dataSet with two rows!"); + +// // Verify that set is empty +// DataSet dataSetVerify = new DataSet(); +// VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); + +// SqlCommandBuilder builder = new SqlCommandBuilder(adapter); + +// // Insert +// DataRow datarow = dataSet.Tables["rowset"].NewRow(); +// datarow.ItemArray = new object[] { "11", "The Original", MagicName, "Engineer", "One Microsoft Way", "Redmond", "WA", "98052", "USA" }; +// datarow.Table.Rows.Add(datarow); +// adapter.Update(dataSet, _tempTable); + +// // Verify that set has one 'Magic' entry +// VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); + +// // Update +// datarow = dataSet.Tables["rowset"].Rows.Find("11"); +// datarow.BeginEdit(); +// datarow.ItemArray = new object[] { "11", "The New and Improved", MagicName, "reenignE", "Yaw Tfosorcim Eno", "Dnomder", "WA", "52098", "ASU" }; +// datarow.EndEdit(); +// adapter.Update(dataSet, _tempTable); + +// // Verify that set has updated 'Magic' entry +// VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); + +// // Delete +// dataSet.Tables["rowset"].Rows.Find("11").Delete(); +// adapter.Update(dataSet, _tempTable); + +// // Verify that set is empty +// VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); +// } +// finally +// { +// DataTestUtility.DropTable(conn, _tempTable); +// } +// } +// } + +// // Synapse: Dynamic SQL generation is not supported against a SelectCommand that does not return any base table information. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public void AutoGenErrorTest() +// { +// string identTableName = DataTestUtility.GetUniqueName("ID_"); +// string createIdentTable = +// $"CREATE TABLE {identTableName} (id int IDENTITY," + +// "LastName nvarchar(50) NULL," + +// "Firstname nvarchar(50) NULL)"; + +// using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) +// using (SqlCommand cmd = new SqlCommand($"SELECT * into {_tempTable} from {identTableName}", conn)) +// using (SqlDataAdapter adapter = new SqlDataAdapter()) +// { +// try +// { +// ExecuteNonQueryCommand(createIdentTable); + +// conn.Open(); +// adapter.SelectCommand = new SqlCommand("select * from " + _tempTable, conn); + +// cmd.ExecuteNonQuery(); + +// // start clean +// DataSet ds = new DataSet(); +// adapter.Fill(ds, _tempTable); + +// // Insert +// DataRow row1 = ds.Tables[_tempTable].NewRow(); +// row1.ItemArray = new object[] { 0, "Bond", "James" }; +// row1.Table.Rows.Add(row1); + +// // table has no key so we should get an error here when we try to autogen the delete command (note that all three +// // update command types are generated here despite the fact that we are just doing an insert) +// SqlCommandBuilder builder = new SqlCommandBuilder(adapter); +// adapter.Update(ds, _tempTable); +// } +// finally +// { +// DataTestUtility.DropTable(conn, _tempTable); +// DataTestUtility.DropTable(conn, identTableName); +// } +// } +// } + +// // These next tests verify that 'bulk' operations work. +// // If each command type modifies more than three rows, then we do a Prep/Exec instead of +// // adhoc ExecuteSql. +// // TODO Synapse: Remove Northwind dependency nu creating required tables in setup. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public void AutoGenBulkUpdateTest() +// { +// using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) +// using (SqlCommand cmd = conn.CreateCommand()) +// using (SqlDataAdapter adapter = new SqlDataAdapter()) +// using (SqlDataAdapter adapterVerify = new SqlDataAdapter()) +// { +// conn.Open(); + +// cmd.CommandText = string.Format(_createTableQuery, _tempTable); +// cmd.ExecuteNonQuery(); +// cmd.CommandText = "alter table " + _tempTable + " add constraint " + _tempKey + " primary key (EmployeeID)"; +// cmd.ExecuteNonQuery(); + +// try +// { +// adapter.SelectCommand = new SqlCommand("SELECT EmployeeID, LastName, FirstName, Title, Address, City, Region, PostalCode, Country FROM " + _tempTable + " WHERE EmployeeID < 3", conn); +// adapterVerify.SelectCommand = new SqlCommand("SELECT LastName, FirstName FROM " + _tempTable + " where FirstName='" + MagicName + "'", conn); + +// adapter.TableMappings.Add(_tempTable, "rowset"); +// adapterVerify.TableMappings.Add(_tempTable, "rowset"); + +// DataSet dataSet = new DataSet(); +// adapter.FillSchema(dataSet, SchemaType.Mapped, _tempTable); + +// dataSet.Tables["rowset"].PrimaryKey = new DataColumn[] { dataSet.Tables["rowset"].Columns["EmployeeID"] }; +// adapter.Fill(dataSet, _tempTable); + +// // Verify that set is empty +// DataSet dataSetVerify = new DataSet(); +// VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); + +// SqlCommandBuilder builder = new SqlCommandBuilder(adapter); + +// // Bulk Insert (10 records) +// DataRow datarow = null; +// const int cOps = 5; +// for (int i = 0; i < cOps * 2; i++) +// { +// datarow = dataSet.Tables["rowset"].NewRow(); +// string sid = "99999000" + i.ToString(); +// datarow.ItemArray = new object[] { sid, "Bulk Insert" + i.ToString(), MagicName, "Engineer", "One Microsoft Way", "Redmond", "WA", "98052", "USA" }; +// datarow.Table.Rows.Add(datarow); +// } +// adapter.Update(dataSet, _tempTable); +// // Verify that set has 10 'Magic' entries +// VerifyUpdateRow(adapterVerify, dataSetVerify, 10, _tempTable); +// dataSet.AcceptChanges(); + +// // Bulk Update (first 5) +// for (int i = 0; i < cOps; i++) +// { +// string sid = "99999000" + i.ToString(); +// datarow = dataSet.Tables["rowset"].Rows.Find(sid); +// datarow.BeginEdit(); +// datarow.ItemArray = new object[] { sid, "Bulk Update" + i.ToString(), MagicName, "reenignE", "Yaw Tfosorcim Eno", "Dnomder", "WA", "52098", "ASU" }; +// datarow.EndEdit(); +// } + +// // Bulk Delete (last 5) +// for (int i = cOps; i < cOps * 2; i++) +// { +// string sid = "99999000" + i.ToString(); +// dataSet.Tables["rowset"].Rows.Find(sid).Delete(); +// } + +// // now update the dataSet with the insert and delete changes +// adapter.Update(dataSet, _tempTable); +// // Verify that set has 5 'Magic' updated entries +// VerifyUpdateRow(adapterVerify, dataSetVerify, 5, _tempTable); + +// // clean up the remaining 5 rows +// for (int i = 0; i < cOps; i++) +// { +// string sid = "99999000" + i.ToString(); +// dataSet.Tables["rowset"].Rows.Find(sid).Delete(); +// } +// adapter.Update(dataSet, _tempTable); +// // Verify that set has no entries +// VerifyUpdateRow(adapterVerify, dataSetVerify, 0, _tempTable); +// } +// finally +// { +// DataTestUtility.DropTable(conn, _tempTable); +// } +// } +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public void TestDeriveParameters() +// { +// string procName = "Test_EmployeeSalesByCountry_" + _randomGuid + ""; +// string spEmployeeSales = +// "create procedure [dbo].[" + procName + "] " + +// "@Beginning_Date DateTime, @Ending_Date DateTime AS " + +// "SELECT Employees.Country, Employees.LastName, Employees.FirstName, Orders.ShippedDate, Orders.OrderID, \"Order Subtotals\".Subtotal AS SaleAmount " + +// "FROM Employees INNER JOIN " + +// "(Orders INNER JOIN \"Order Subtotals\" ON Orders.OrderID = \"Order Subtotals\".OrderID) " + +// "ON Employees.EmployeeID = Orders.EmployeeID " + +// "WHERE Orders.ShippedDate Between @Beginning_Date And @Ending_Date"; +// string dropSpEmployeeSales = "drop procedure [dbo].[" + procName + "]"; + +// string expectedParamResults = +// "\"@RETURN_VALUE\" AS Int32 OF Int FOR Current \"\" " + +// "0, 0, 0, ReturnValue, DEFAULT; " + +// "\"@Beginning_Date\" AS DateTime OF DateTime FOR Current \"\" " + +// "0, 0, 0, Input, DEFAULT; " + +// "\"@Ending_Date\" AS DateTime OF DateTime FOR Current \"\" " + +// "0, 0, 0, Input, DEFAULT; "; + +// try +// { +// ExecuteNonQueryCommand(spEmployeeSales); +// using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) +// using (SqlCommand cmd = new SqlCommand(procName, connection)) +// { +// string errorMessage = string.Format(SystemDataResourceManager.Instance.ADP_DeriveParametersNotSupported, "SqlCommand", cmd.CommandType); +// DataTestUtility.AssertThrowsWrapper( +// () => SqlCommandBuilder.DeriveParameters(cmd), +// errorMessage); + +// errorMessage = string.Format(SystemDataResourceManager.Instance.ADP_OpenConnectionRequired, "DeriveParameters", ""); +// cmd.CommandType = CommandType.StoredProcedure; +// DataTestUtility.AssertThrowsWrapper( +// () => SqlCommandBuilder.DeriveParameters(cmd), +// errorMessage); + +// connection.Open(); + +// SqlCommandBuilder.DeriveParameters(cmd); +// CheckParameters(cmd, expectedParamResults); + +// cmd.CommandText = "Test_EmployeeSalesBy"; +// errorMessage = string.Format(SystemDataResourceManager.Instance.ADP_NoStoredProcedureExists, cmd.CommandText); +// DataTestUtility.AssertThrowsWrapper( +// () => SqlCommandBuilder.DeriveParameters(cmd), +// errorMessage); + +// cmd.CommandText = procName; +// SqlCommandBuilder.DeriveParameters(cmd); +// CheckParameters(cmd, expectedParamResults); +// } +// } +// finally +// { +// ExecuteNonQueryCommand(dropSpEmployeeSales); +// } +// } + +// // Synapse: Parse error at line: 1, column: 65: Incorrect syntax near 'as'. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public void TestReadOnlyColumnMetadata() +// { +// using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) +// { +// connection.Open(); +// using (SqlCommand command = connection.CreateCommand()) +// { +// command.CommandText = "Create table #t (ID int identity(1,1), sText varchar(12), sMemo as (convert(varchar,ID) + ' ' + sText))"; +// command.ExecuteNonQuery(); +// } +// using (SqlDataAdapter dataAdapter = new SqlDataAdapter("Select * from #t", connection)) +// { +// using (SqlCommandBuilder commandBuilder = new SqlCommandBuilder(dataAdapter)) +// { +// using (SqlCommand cmd = commandBuilder.GetInsertCommand()) +// { +// DataTestUtility.AssertEqualsWithDescription("INSERT INTO [#t] ([sText]) VALUES (@p1)", cmd.CommandText, "Unexpected insert command."); +// } +// } + +// using (DataTable dataTable = new DataTable()) +// { +// dataAdapter.FillSchema(dataTable, SchemaType.Mapped); +// Dictionary expAutoIncrement = new Dictionary() +// { +// {"ID", true}, +// {"sText", false}, +// {"sMemo", false} +// }; +// Dictionary expReadOnly = new Dictionary() +// { +// {"ID", true}, +// {"sText", false}, +// {"sMemo", true} +// }; +// foreach (DataColumn dataColumn in dataTable.Columns) +// { +// DataTestUtility.AssertEqualsWithDescription(dataColumn.AutoIncrement, expAutoIncrement[dataColumn.ColumnName], "Unexpected AutoIncrement metadata."); +// DataTestUtility.AssertEqualsWithDescription(dataColumn.ReadOnly, expReadOnly[dataColumn.ColumnName], "Unexpected ReadOnly metadata."); +// } +// } +// } +// } +// } + +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// [InlineData(nameof(SqlCommandBuilder.GetInsertCommand), null)] +// [InlineData(nameof(SqlCommandBuilder.GetInsertCommand), true)] +// [InlineData(nameof(SqlCommandBuilder.GetInsertCommand), false)] +// [InlineData(nameof(SqlCommandBuilder.GetUpdateCommand), null)] +// [InlineData(nameof(SqlCommandBuilder.GetUpdateCommand), true)] +// [InlineData(nameof(SqlCommandBuilder.GetUpdateCommand), false)] +// [InlineData(nameof(SqlCommandBuilder.GetDeleteCommand), null)] +// [InlineData(nameof(SqlCommandBuilder.GetDeleteCommand), false)] +// [InlineData(nameof(SqlCommandBuilder.GetDeleteCommand), true)] +// public void VerifyGetCommand(string methodName, bool? useColumnsForParameterNames) +// { +// using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) +// { +// connection.Open(); +// using (SqlDataAdapter dataAdapter = new SqlDataAdapter("SELECT * FROM dbo.Customers", connection)) +// { +// using (SqlCommandBuilder commandBuilder = new SqlCommandBuilder(dataAdapter)) +// { +// object[] parameters = null; +// Type[] parameterTypes = null; +// if (useColumnsForParameterNames != null) +// { +// parameters = new object[] { useColumnsForParameterNames }; +// parameterTypes = new Type[] { typeof(bool) }; +// } +// else +// { +// parameters = new object[] { }; +// parameterTypes = new Type[] { }; +// } + +// MethodInfo method = commandBuilder.GetType().GetMethod(methodName, parameterTypes); +// using (SqlCommand cmd = (SqlCommand)method.Invoke(commandBuilder, parameters)) +// { +// Assert.NotNull(cmd); +// } +// } +// } +// } +// } + +// #region Utility_Methods +// private void CheckParameters(SqlCommand cmd, string expectedResults) +// { +// Debug.Assert(null != cmd, "DumpParameters: null SqlCommand"); + +// string actualResults = ""; +// StringBuilder builder = new StringBuilder(); +// foreach (SqlParameter p in cmd.Parameters) +// { +// byte precision = p.Precision; +// byte scale = p.Scale; +// builder.Append("\"" + p.ParameterName + "\" AS " + p.DbType.ToString("G") + " OF " + p.SqlDbType.ToString("G") + " FOR " + p.SourceVersion.ToString("G") + " \"" + p.SourceColumn + "\" "); +// builder.Append(p.Size.ToString() + ", " + precision.ToString() + ", " + scale.ToString() + ", " + p.Direction.ToString("G") + ", " + DBConvertToString(p.Value) + "; "); +// } +// actualResults = builder.ToString(); + +// DataTestUtility.AssertEqualsWithDescription(expectedResults, actualResults, "Unexpected Parameter results."); +// } + +// private bool ByteArraysEqual(byte[] expectedBytes, byte[] actualBytes) +// { +// DataTestUtility.AssertEqualsWithDescription( +// expectedBytes.Length, actualBytes.Length, +// "Unexpected array length."); + +// for (int i = 0; i < expectedBytes.Length; i++) +// { +// DataTestUtility.AssertEqualsWithDescription( +// expectedBytes[i], actualBytes[i], +// "Unexpected byte value."); +// } + +// return true; +// } + +// private void InitDataValues() +// { +// _c_numeric_val = new decimal(42424242.42); +// _c_unique_val = new byte[16]; +// _c_unique_val[0] = 0xba; +// _c_unique_val[1] = 0xad; +// _c_unique_val[2] = 0xf0; +// _c_unique_val[3] = 0x0d; +// _c_unique_val[4] = 0xba; +// _c_unique_val[5] = 0xad; +// _c_unique_val[6] = 0xf0; +// _c_unique_val[7] = 0x0d; +// _c_unique_val[8] = 0xba; +// _c_unique_val[9] = 0xad; +// _c_unique_val[10] = 0xf0; +// _c_unique_val[11] = 0x0d; +// _c_unique_val[12] = 0xba; +// _c_unique_val[13] = 0xad; +// _c_unique_val[14] = 0xf0; +// _c_unique_val[15] = 0x0d; +// _c_guid_val = new Guid(_c_unique_val); +// _c_varbinary_val = _c_unique_val; +// _c_binary_val = _c_unique_val; +// _c_money_val = new decimal((double)123456789.99); +// _c_smallmoney_val = new decimal((double)-6543.21); +// _c_datetime_val = new DateTime(1971, 7, 20, 23, 59, 59); +// _c_smalldatetime_val = new DateTime(1971, 7, 20, 23, 59, 0); +// _c_nvarchar_val = "1234567890"; +// _c_nchar_val = _c_nvarchar_val; +// _c_varchar_val = _c_nvarchar_val; +// _c_char_val = _c_nvarchar_val; +// _c_int_val = unchecked((int)0xffffffff); +// _c_smallint_val = unchecked((short)0xffff); +// _c_tinyint_val = 0xff; +// _c_bigint_val = 0x11ffffff; +// _c_bit_val = true; +// _c_float_val = (double)12345678.2; +// _c_real_val = (float)12345.1; + +// _values = new object[18]; +// _values[0] = _c_numeric_val; +// _values[1] = _c_smalldatetime_val; +// _values[2] = _c_guid_val; +// _values[3] = _c_varbinary_val; +// _values[4] = _c_binary_val; +// _values[5] = _c_money_val; +// _values[6] = _c_smallmoney_val; +// _values[7] = _c_nvarchar_val; +// _values[8] = _c_varchar_val; +// _values[9] = _c_char_val; +// _values[10] = _c_int_val; +// _values[11] = _c_smallint_val; +// _values[12] = _c_tinyint_val; +// _values[13] = _c_bigint_val; +// _values[14] = _c_bit_val; +// _values[15] = _c_float_val; +// _values[16] = _c_real_val; +// _values[17] = _c_datetime_val; +// } + +// private void VerifyFillSchemaResult(DataTable[] tables, string[] expectedTableNames) +// { +// DataTestUtility.AssertEqualsWithDescription(expectedTableNames.Length, tables.Length, "Unequal number of tables."); +// for (int i = 0; i < tables.Length; i++) +// { +// DataTestUtility.AssertEqualsWithDescription(expectedTableNames[i], tables[i].TableName, "Unexpected DataTable TableName."); +// } +// } + +// // Prepares the Insert, Update, and Delete command to test updating against Northwind.Employees +// private void PrepareUpdateCommands(SqlDataAdapter adapter, SqlConnection conn, string table) +// { +// // insert +// adapter.InsertCommand = new SqlCommand() +// { +// CommandText = "INSERT INTO " + table + "(EmployeeID, LastName, FirstName, Title, Address, City, Region, PostalCode, Country) " + +// "VALUES (@EmployeeID, @LastName, @FirstName, @Title, @Address, @City, @Region, @PostalCode, @Country)" +// }; +// adapter.InsertCommand.Parameters.Add(new SqlParameter("@EmployeeID", SqlDbType.Int, 0, "EmployeeID")); +// adapter.InsertCommand.Parameters.Add(new SqlParameter("@LastName", SqlDbType.NVarChar, 20, "LastName")); +// adapter.InsertCommand.Parameters.Add(new SqlParameter("@FirstName", SqlDbType.NVarChar, 10, "FirstName")); +// adapter.InsertCommand.Parameters.Add(new SqlParameter("@Title", SqlDbType.NVarChar, 30, "Title")); +// adapter.InsertCommand.Parameters.Add(new SqlParameter("@Address", SqlDbType.NVarChar, 60, "Address")); +// adapter.InsertCommand.Parameters.Add(new SqlParameter("@City", SqlDbType.NVarChar, 15, "City")); +// adapter.InsertCommand.Parameters.Add(new SqlParameter("@Region", SqlDbType.NVarChar, 15, "Region")); +// adapter.InsertCommand.Parameters.Add(new SqlParameter("@PostalCode", SqlDbType.NVarChar, 10, "PostalCode")); +// adapter.InsertCommand.Parameters.Add(new SqlParameter("@Country", SqlDbType.NVarChar, 15, "Country")); + +// adapter.InsertCommand.Connection = conn; + +// // update +// adapter.UpdateCommand = new SqlCommand() +// { +// CommandText = "UPDATE " + table + " SET " + +// "EmployeeID = @EmployeeID, LastName = @LastName, FirstName = @FirstName, Title = @Title, Address = @Address, City = @City, Region = @Region, " + +// "PostalCode = @PostalCode, Country = @Country WHERE (EmployeeID = @OldEmployeeID)" +// }; +// adapter.UpdateCommand.Parameters.Add(new SqlParameter("@EmployeeID", SqlDbType.Int, 0, "EmployeeID")); +// adapter.UpdateCommand.Parameters.Add(new SqlParameter("@LastName", SqlDbType.NVarChar, 20, "LastName")); +// adapter.UpdateCommand.Parameters.Add(new SqlParameter("@FirstName", SqlDbType.NVarChar, 10, "FirstName")); +// adapter.UpdateCommand.Parameters.Add(new SqlParameter("@Title", SqlDbType.NVarChar, 30, "Title")); +// adapter.UpdateCommand.Parameters.Add(new SqlParameter("@Address", SqlDbType.NVarChar, 60, "Address")); +// adapter.UpdateCommand.Parameters.Add(new SqlParameter("@City", SqlDbType.NVarChar, 15, "City")); +// adapter.UpdateCommand.Parameters.Add(new SqlParameter("@Region", SqlDbType.NVarChar, 15, "Region")); +// adapter.UpdateCommand.Parameters.Add(new SqlParameter("@PostalCode", SqlDbType.NVarChar, 10, "PostalCode")); +// adapter.UpdateCommand.Parameters.Add(new SqlParameter("@Country", SqlDbType.NVarChar, 15, "Country")); + +// adapter.UpdateCommand.Parameters.Add(new SqlParameter("@OldEmployeeID", SqlDbType.Int, 0, "EmployeeID")).SourceVersion = DataRowVersion.Original; +// adapter.UpdateCommand.Connection = conn; + +// // +// // delete +// // +// adapter.DeleteCommand = new SqlCommand() +// { +// CommandText = "DELETE FROM " + table + " WHERE (EmployeeID = @EmployeeID)" +// }; +// adapter.DeleteCommand.Parameters.Add(new SqlParameter("@EmployeeID", SqlDbType.Int, 0, "EmployeeID")); +// adapter.DeleteCommand.Connection = conn; +// } + +// private void RowUpdating_UpdateRefreshTest(object sender, SqlRowUpdatingEventArgs e) +// { +// // make sure that we always get a cloned command back (which means that it should always have the badapple parameter!) +// e.Command = (SqlCommand)((ICloneable)e.Command).Clone(); +// DataTestUtility.AssertEqualsWithDescription("sp_insert", e.Command.CommandText.Substring(0, 9), "Unexpected command name."); +// e.Command.Parameters.RemoveAt("@badapple"); +// } + +// private void RowUpdated_UpdateRefreshTest(object sender, SqlRowUpdatedEventArgs e) +// { +// DataTestUtility.AssertEqualsWithDescription("sp_insert", e.Command.CommandText.Substring(0, 9), "Unexpected command name."); +// } + +// private void VerifyUpdateRow(SqlDataAdapter sa, DataSet ds, int cRows, string table) +// { +// ds.Reset(); +// sa.Fill(ds, table); + +// // don't dump out all the data, just get the row count +// if (cRows > 0) +// { +// Assert.True(ds.Tables[0].Rows.Count == cRows, "FAILED: expected " + cRows.ToString() + " rows but got " + ds.Tables[0].Rows.Count.ToString()); +// } + +// ds.Reset(); +// } + +// private bool VerifyOutputParams(SqlParameterCollection sqlParameters) +// { +// return +// (int)sqlParameters[1].Value == 2000 && +// (0 == string.Compare((string)sqlParameters[2].Value, "Success!", false, CultureInfo.InvariantCulture)) && +// (int)sqlParameters[3].Value == 42; +// } + +// private string DBConvertToString(object value) +// { +// StringBuilder builder = new StringBuilder(); +// WriteObject(builder, value, CultureInfo.InvariantCulture, null, 0, int.MaxValue); +// return builder.ToString(); +// } + +// private void WriteObject(StringBuilder textBuilder, object value, CultureInfo cultureInfo, Hashtable used, int indent, int recursionLimit) +// { +// if (0 > --recursionLimit) +// { +// return; +// } +// if (null == value) +// { +// textBuilder.Append("DEFAULT"); +// } +// else if (Convert.IsDBNull(value)) +// { +// textBuilder.Append("ISNULL"); +// } +// else +// { +// Type valuetype = value.GetType(); + +// if ((null != used) && (!valuetype.IsPrimitive)) +// { +// if (used.Contains(value)) +// { +// textBuilder.Append('#'); +// textBuilder.Append(((int)used[value]).ToString(cultureInfo)); +// return; +// } +// else +// { +// textBuilder.Append('#'); +// textBuilder.Append(used.Count.ToString(cultureInfo)); +// used.Add(value, used.Count); +// } +// } +// if ((value is string) || (value is SqlString)) +// { +// if (value is SqlString) +// { +// value = ((SqlString)value).Value; +// } +// textBuilder.Append(valuetype.Name); +// textBuilder.Append(":"); +// textBuilder.Append(((string)value).Length); +// textBuilder.Append("<"); +// textBuilder.Append((string)value); +// textBuilder.Append(">"); +// } +// else if ((value is DateTime) || (value is SqlDateTime)) +// { +// if (value is SqlDateTime) +// { +// value = ((SqlDateTime)value).Value; +// } +// textBuilder.Append(valuetype.Name); +// textBuilder.Append("<"); +// textBuilder.Append(((DateTime)value).ToString("s", cultureInfo)); +// textBuilder.Append(">"); +// } +// else if ((value is float) || (value is SqlSingle)) +// { +// if (value is SqlSingle) +// { +// value = ((SqlSingle)value).Value; +// } +// textBuilder.Append(valuetype.Name); +// textBuilder.Append("<"); +// textBuilder.Append(((float)value).ToString(cultureInfo)); +// textBuilder.Append(">"); +// } +// else if ((value is double) || (value is SqlDouble)) +// { +// if (value is SqlDouble) +// { +// value = ((SqlDouble)value).Value; +// } +// textBuilder.Append(valuetype.Name); +// textBuilder.Append("<"); +// textBuilder.Append(((double)value).ToString(cultureInfo)); +// textBuilder.Append(">"); +// } +// else if ((value is decimal) || (value is SqlDecimal) || (value is SqlMoney)) +// { +// if (value is SqlDecimal) +// { +// value = ((SqlDecimal)value).Value; +// } +// else if (value is SqlMoney) +// { +// value = ((SqlMoney)value).Value; +// } +// textBuilder.Append(valuetype.Name); +// textBuilder.Append("<"); +// textBuilder.Append(((decimal)value).ToString(cultureInfo)); +// textBuilder.Append(">"); +// } +// else if (value is INullable && ((INullable)value).IsNull) +// { +// textBuilder.Append(valuetype.Name); +// textBuilder.Append(" ISNULL"); +// } +// else if (valuetype.IsArray) +// { +// textBuilder.Append(valuetype.Name); +// Array array = (Array)value; + +// if (1 < array.Rank) +// { +// textBuilder.Append("{"); +// } + +// for (int i = 0; i < array.Rank; ++i) +// { +// int count = array.GetUpperBound(i); + +// textBuilder.Append(' '); +// textBuilder.Append(count - array.GetLowerBound(i) + 1); +// textBuilder.Append("{ "); +// for (int k = array.GetLowerBound(i); k <= count; ++k) +// { +// AppendNewLineIndent(textBuilder, indent + 1); +// textBuilder.Append(','); +// WriteObject(textBuilder, array.GetValue(k), cultureInfo, used, 0, recursionLimit); +// textBuilder.Append(' '); +// } +// AppendNewLineIndent(textBuilder, indent); +// textBuilder.Append("}"); +// } +// if (1 < array.Rank) +// { +// textBuilder.Append('}'); +// } +// } +// else if (value is ICollection) +// { +// textBuilder.Append(valuetype.Name); +// ICollection collection = (ICollection)value; +// object[] newvalue = new object[collection.Count]; +// collection.CopyTo(newvalue, 0); + +// textBuilder.Append(' '); +// textBuilder.Append(newvalue.Length); +// textBuilder.Append('{'); +// for (int k = 0; k < newvalue.Length; ++k) +// { +// AppendNewLineIndent(textBuilder, indent + 1); +// textBuilder.Append(','); +// WriteObject(textBuilder, newvalue[k], cultureInfo, used, indent + 1, recursionLimit); +// } +// AppendNewLineIndent(textBuilder, indent); +// textBuilder.Append('}'); +// } +// else if (value is Type) +// { +// textBuilder.Append(valuetype.Name); +// textBuilder.Append('<'); +// textBuilder.Append((value as Type).FullName); +// textBuilder.Append('>'); +// } +// else if (valuetype.IsEnum) +// { +// textBuilder.Append(valuetype.Name); +// textBuilder.Append('<'); +// textBuilder.Append(Enum.GetName(valuetype, value)); +// textBuilder.Append('>'); +// } +// else +// { +// string fullName = valuetype.FullName; +// if ("System.ComponentModel.ExtendedPropertyDescriptor" == fullName) +// { +// textBuilder.Append(fullName); +// } +// else +// { +// FieldInfo[] fields = valuetype.GetFields(BindingFlags.Instance | BindingFlags.Public); +// PropertyInfo[] properties = valuetype.GetProperties(BindingFlags.Instance | BindingFlags.Public); + +// bool hasinfo = false; +// if ((null != fields) && (0 < fields.Length)) +// { +// textBuilder.Append(fullName); +// fullName = null; + +// Array.Sort(fields, FieldInfoCompare.s_default); +// for (int i = 0; i < fields.Length; ++i) +// { +// FieldInfo field = fields[i]; + +// AppendNewLineIndent(textBuilder, indent + 1); +// textBuilder.Append(field.Name); +// textBuilder.Append('='); +// object newvalue = field.GetValue(value); +// WriteObject(textBuilder, newvalue, cultureInfo, used, indent + 1, recursionLimit); +// } +// hasinfo = true; +// } +// if ((null != properties) && (0 < properties.Length)) +// { +// if (null != fullName) +// { +// textBuilder.Append(fullName); +// fullName = null; +// } + +// Array.Sort(properties, PropertyInfoCompare.s_default); +// for (int i = 0; i < properties.Length; ++i) +// { +// PropertyInfo property = properties[i]; +// if (property.CanRead) +// { +// ParameterInfo[] parameters = property.GetIndexParameters(); +// if ((null == parameters) || (0 == parameters.Length)) +// { +// AppendNewLineIndent(textBuilder, indent + 1); +// textBuilder.Append(property.Name); +// textBuilder.Append('='); +// object newvalue = null; +// bool haveValue = false; +// try +// { +// newvalue = property.GetValue(value, BindingFlags.Public | BindingFlags.GetProperty, null, null, CultureInfo.InvariantCulture); +// haveValue = true; +// } +// catch (TargetInvocationException e) +// { +// textBuilder.Append(e.InnerException.GetType().Name); +// textBuilder.Append(": "); +// textBuilder.Append(e.InnerException.Message); +// } +// if (haveValue) +// { +// WriteObject(textBuilder, newvalue, cultureInfo, used, indent + 1, recursionLimit); +// } +// } +// } +// } +// hasinfo = true; +// } +// if (!hasinfo) +// { +// textBuilder.Append(valuetype.Name); +// textBuilder.Append('<'); +// MethodInfo method = valuetype.GetMethod("ToString", new Type[] { typeof(IFormatProvider) }); +// if (null != method) +// { +// textBuilder.Append((string)method.Invoke(value, new object[] { cultureInfo })); +// } +// else +// { +// string text = value.ToString(); +// textBuilder.Append(text); +// } +// textBuilder.Append('>'); +// } +// } +// } +// } +// } + +// private void ExecuteNonQueryCommand(string cmdText) +// { +// using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) +// using (SqlCommand cmd = conn.CreateCommand()) +// { +// conn.Open(); +// cmd.CommandText = cmdText; +// cmd.ExecuteNonQuery(); +// } +// } + +// private void AppendNewLineIndent(StringBuilder textBuilder, int indent) +// { +// textBuilder.Append(Environment.NewLine); +// char[] buf = _appendNewLineIndentBuffer; +// if (buf.Length < indent * 4) +// { +// buf = new char[indent * 4]; +// for (int i = 0; i < buf.Length; ++i) +// { +// buf[i] = ' '; +// } +// _appendNewLineIndentBuffer = buf; +// } +// textBuilder.Append(buf, 0, indent * 4); +// } + +// private class PropertyInfoCompare : IComparer +// { +// internal static PropertyInfoCompare s_default = new PropertyInfoCompare(); + +// private PropertyInfoCompare() +// { +// } + +// public int Compare(object x, object y) +// { +// string propertyInfoName1 = ((PropertyInfo)x).Name; +// string propertyInfoName2 = ((PropertyInfo)y).Name; + +// return CultureInfo.InvariantCulture.CompareInfo.Compare(propertyInfoName1, propertyInfoName2, CompareOptions.IgnoreCase); +// } +// } + +// private class FieldInfoCompare : IComparer +// { +// internal static FieldInfoCompare s_default = new FieldInfoCompare(); + +// private FieldInfoCompare() +// { +// } + +// public int Compare(object x, object y) +// { +// string fieldInfoName1 = ((FieldInfo)x).Name; +// string fieldInfoName2 = ((FieldInfo)y).Name; + +// return CultureInfo.InvariantCulture.CompareInfo.Compare(fieldInfoName1, fieldInfoName2, CompareOptions.IgnoreCase); +// } +// } +// #endregion +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/AsyncCancelledConnectionsTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/AsyncCancelledConnectionsTest.cs index e71d6d62f6..baeb6351b0 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/AsyncCancelledConnectionsTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/AsyncCancelledConnectionsTest.cs @@ -1,289 +1,289 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Xunit; -using Xunit.Abstractions; +//using System; +//using System.Collections.Generic; +//using System.Diagnostics; +//using System.Text; +//using System.Threading; +//using System.Threading.Tasks; +//using Xunit; +//using Xunit.Abstractions; -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ - public class AsyncCancelledConnectionsTest - { - private readonly ITestOutputHelper _output; +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ +// public class AsyncCancelledConnectionsTest +// { +// private readonly ITestOutputHelper _output; - private const int NumberOfTasks = 100; // How many attempts to poison the connection pool we will try +// private const int NumberOfTasks = 100; // How many attempts to poison the connection pool we will try - private const int NumberOfNonPoisoned = 10; // Number of normal requests for each attempt +// private const int NumberOfNonPoisoned = 10; // Number of normal requests for each attempt - public AsyncCancelledConnectionsTest(ITestOutputHelper output) - { - _output = output; - } +// public AsyncCancelledConnectionsTest(ITestOutputHelper output) +// { +// _output = output; +// } - // Disabled on Azure since this test fails on concurrent runs on same database. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureServer))] - public void CancelAsyncConnections() - { - SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString); - builder.MultipleActiveResultSets = false; - RunCancelAsyncConnections(builder); - builder.MultipleActiveResultSets = true; - RunCancelAsyncConnections(builder); - } +// // Disabled on Azure since this test fails on concurrent runs on same database. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureServer))] +// public void CancelAsyncConnections() +// { +// SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString); +// builder.MultipleActiveResultSets = false; +// RunCancelAsyncConnections(builder); +// builder.MultipleActiveResultSets = true; +// RunCancelAsyncConnections(builder); +// } - private void RunCancelAsyncConnections(SqlConnectionStringBuilder connectionStringBuilder) - { - SqlConnection.ClearAllPools(); - _watch = Stopwatch.StartNew(); - _random = new Random(4); // chosen via fair dice role. - ParallelLoopResult results = new ParallelLoopResult(); - try - { - // Setup a timer so that we can see what is going on while our tasks run - using (new Timer(TimerCallback, state: null, dueTime: TimeSpan.FromSeconds(5), period: TimeSpan.FromSeconds(5))) - { - results = Parallel.For( - fromInclusive: 0, - toExclusive: NumberOfTasks, - (int i) => DoManyAsync(connectionStringBuilder).GetAwaiter().GetResult()); - } - } - catch (Exception ex) - { - _output.WriteLine(ex.ToString()); - } - while (!results.IsCompleted) - { - Thread.Sleep(50); - } - DisplaySummary(); - foreach (var detail in _exceptionDetails) - { - _output.WriteLine(detail); - } - Assert.Empty(_exceptionDetails); - } +// private void RunCancelAsyncConnections(SqlConnectionStringBuilder connectionStringBuilder) +// { +// SqlConnection.ClearAllPools(); +// _watch = Stopwatch.StartNew(); +// _random = new Random(4); // chosen via fair dice role. +// ParallelLoopResult results = new ParallelLoopResult(); +// try +// { +// // Setup a timer so that we can see what is going on while our tasks run +// using (new Timer(TimerCallback, state: null, dueTime: TimeSpan.FromSeconds(5), period: TimeSpan.FromSeconds(5))) +// { +// results = Parallel.For( +// fromInclusive: 0, +// toExclusive: NumberOfTasks, +// (int i) => DoManyAsync(connectionStringBuilder).GetAwaiter().GetResult()); +// } +// } +// catch (Exception ex) +// { +// _output.WriteLine(ex.ToString()); +// } +// while (!results.IsCompleted) +// { +// Thread.Sleep(50); +// } +// DisplaySummary(); +// foreach (var detail in _exceptionDetails) +// { +// _output.WriteLine(detail); +// } +// Assert.Empty(_exceptionDetails); +// } - // Display one row every 5'ish seconds - private void TimerCallback(object state) - { - lock (_lockObject) - { - DisplaySummary(); - } - } +// // Display one row every 5'ish seconds +// private void TimerCallback(object state) +// { +// lock (_lockObject) +// { +// DisplaySummary(); +// } +// } - private void DisplaySummary() - { - int count; - lock (_exceptionDetails) - { - count = _exceptionDetails.Count; - } +// private void DisplaySummary() +// { +// int count; +// lock (_exceptionDetails) +// { +// count = _exceptionDetails.Count; +// } - _output.WriteLine($"{_watch.Elapsed} {_continue} Started:{_start} Done:{_done} InFlight:{_inFlight} RowsRead:{_rowsRead} ResultRead:{_resultRead} PoisonedEnded:{_poisonedEnded} nonPoisonedExceptions:{_nonPoisonedExceptions} PoisonedCleanupExceptions:{_poisonCleanUpExceptions} Count:{count} Found:{_found}"); - } +// _output.WriteLine($"{_watch.Elapsed} {_continue} Started:{_start} Done:{_done} InFlight:{_inFlight} RowsRead:{_rowsRead} ResultRead:{_resultRead} PoisonedEnded:{_poisonedEnded} nonPoisonedExceptions:{_nonPoisonedExceptions} PoisonedCleanupExceptions:{_poisonCleanUpExceptions} Count:{count} Found:{_found}"); +// } - // This is the the main body that our Tasks run - private async Task DoManyAsync(SqlConnectionStringBuilder connectionStringBuilder) - { - Interlocked.Increment(ref _start); - Interlocked.Increment(ref _inFlight); +// // This is the the main body that our Tasks run +// private async Task DoManyAsync(SqlConnectionStringBuilder connectionStringBuilder) +// { +// Interlocked.Increment(ref _start); +// Interlocked.Increment(ref _inFlight); - using (SqlConnection marsConnection = new SqlConnection(connectionStringBuilder.ToString())) - { - if (connectionStringBuilder.MultipleActiveResultSets) - { - await marsConnection.OpenAsync(); - } +// using (SqlConnection marsConnection = new SqlConnection(connectionStringBuilder.ToString())) +// { +// if (connectionStringBuilder.MultipleActiveResultSets) +// { +// await marsConnection.OpenAsync(); +// } - // First poison - await DoOneAsync(marsConnection, connectionStringBuilder.ToString(), poison: true); +// // First poison +// await DoOneAsync(marsConnection, connectionStringBuilder.ToString(), poison: true); - for (int i = 0; i < NumberOfNonPoisoned && _continue; i++) - { - // now run some without poisoning - await DoOneAsync(marsConnection, connectionStringBuilder.ToString()); - } - } +// for (int i = 0; i < NumberOfNonPoisoned && _continue; i++) +// { +// // now run some without poisoning +// await DoOneAsync(marsConnection, connectionStringBuilder.ToString()); +// } +// } - Interlocked.Decrement(ref _inFlight); - Interlocked.Increment(ref _done); - } +// Interlocked.Decrement(ref _inFlight); +// Interlocked.Increment(ref _done); +// } - // This will do our work, open a connection, and run a query (that returns 4 results sets) - // if we are poisoning we will - // 1 - Interject some sleeps in the sql statement so that it will run long enough that we can cancel it - // 2 - Setup a time bomb task that will cancel the command a random amount of time later - private async Task DoOneAsync(SqlConnection marsConnection, string connectionString, bool poison = false) - { - try - { - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < 4; i++) - { - builder.AppendLine("SELECT name FROM sys.tables"); - if (poison && i < 3) - { - builder.AppendLine("WAITFOR DELAY '00:00:01'"); - } - } +// // This will do our work, open a connection, and run a query (that returns 4 results sets) +// // if we are poisoning we will +// // 1 - Interject some sleeps in the sql statement so that it will run long enough that we can cancel it +// // 2 - Setup a time bomb task that will cancel the command a random amount of time later +// private async Task DoOneAsync(SqlConnection marsConnection, string connectionString, bool poison = false) +// { +// try +// { +// StringBuilder builder = new StringBuilder(); +// for (int i = 0; i < 4; i++) +// { +// builder.AppendLine("SELECT name FROM sys.tables"); +// if (poison && i < 3) +// { +// builder.AppendLine("WAITFOR DELAY '00:00:01'"); +// } +// } - using (var connection = new SqlConnection(connectionString)) - { - if (marsConnection != null && marsConnection.State == System.Data.ConnectionState.Open) - { - await RunCommand(marsConnection, builder.ToString(), poison); - } - else - { - await connection.OpenAsync(); - await RunCommand(connection, builder.ToString(), poison); - } - } - } - catch (Exception ex) - { - if (!poison) - { - Interlocked.Increment(ref _nonPoisonedExceptions); +// using (var connection = new SqlConnection(connectionString)) +// { +// if (marsConnection != null && marsConnection.State == System.Data.ConnectionState.Open) +// { +// await RunCommand(marsConnection, builder.ToString(), poison); +// } +// else +// { +// await connection.OpenAsync(); +// await RunCommand(connection, builder.ToString(), poison); +// } +// } +// } +// catch (Exception ex) +// { +// if (!poison) +// { +// Interlocked.Increment(ref _nonPoisonedExceptions); - string details = ex.ToString(); - details = details.Substring(0, Math.Min(200, details.Length)); - lock (_exceptionDetails) - { - _exceptionDetails.Add(details); - } - } +// string details = ex.ToString(); +// details = details.Substring(0, Math.Min(200, details.Length)); +// lock (_exceptionDetails) +// { +// _exceptionDetails.Add(details); +// } +// } - if (ex.Message.Contains("The MARS TDS header contained errors.")) - { - _continue = false; - if (_found == 0) // This check is not really safe we may list more than one. - { - lock (_lockObject) - { - // You will notice that poison will be likely be false here, it is the normal commands that suffer - // Once we have successfully poisoned the connection pool, we may start to see some other request to poison fail just like the normal requests - _output.WriteLine($"{poison} {DateTime.UtcNow.ToString("O")}"); - _output.WriteLine(ex.ToString()); - } - } - Interlocked.Increment(ref _found); - } - } - } +// if (ex.Message.Contains("The MARS TDS header contained errors.")) +// { +// _continue = false; +// if (_found == 0) // This check is not really safe we may list more than one. +// { +// lock (_lockObject) +// { +// // You will notice that poison will be likely be false here, it is the normal commands that suffer +// // Once we have successfully poisoned the connection pool, we may start to see some other request to poison fail just like the normal requests +// _output.WriteLine($"{poison} {DateTime.UtcNow.ToString("O")}"); +// _output.WriteLine(ex.ToString()); +// } +// } +// Interlocked.Increment(ref _found); +// } +// } +// } - private async Task RunCommand(SqlConnection connection, string commandText, bool poison) - { - int rowsRead = 0; - int resultRead = 0; +// private async Task RunCommand(SqlConnection connection, string commandText, bool poison) +// { +// int rowsRead = 0; +// int resultRead = 0; - try - { - using (var command = connection.CreateCommand()) - { - Task timeBombTask = default; - try - { - // Setup our time bomb - if (poison) - { - timeBombTask = TimeBombAsync(command); - } +// try +// { +// using (var command = connection.CreateCommand()) +// { +// Task timeBombTask = default; +// try +// { +// // Setup our time bomb +// if (poison) +// { +// timeBombTask = TimeBombAsync(command); +// } - command.CommandText = commandText; +// command.CommandText = commandText; - // Attempt to read all of the data - using (var reader = await command.ExecuteReaderAsync()) - { - try - { - do - { - resultRead++; - while (await reader.ReadAsync() && _continue) - { - rowsRead++; - } - } - while (await reader.NextResultAsync() && _continue); - } - catch when (poison) - { - // This looks a little strange, we failed to read above so this should fail too - // But consider the case where this code is elsewhere (in the Dispose method of a class holding this logic) - try - { - while (await reader.NextResultAsync()) - { - } - } - catch - { - Interlocked.Increment(ref _poisonCleanUpExceptions); - } +// // Attempt to read all of the data +// using (var reader = await command.ExecuteReaderAsync()) +// { +// try +// { +// do +// { +// resultRead++; +// while (await reader.ReadAsync() && _continue) +// { +// rowsRead++; +// } +// } +// while (await reader.NextResultAsync() && _continue); +// } +// catch when (poison) +// { +// // This looks a little strange, we failed to read above so this should fail too +// // But consider the case where this code is elsewhere (in the Dispose method of a class holding this logic) +// try +// { +// while (await reader.NextResultAsync()) +// { +// } +// } +// catch +// { +// Interlocked.Increment(ref _poisonCleanUpExceptions); +// } - throw; - } - } - } - finally - { - // Make sure to clean up our time bomb - // It is unlikely, but the timebomb may get delayed in the Task Queue - // And we don't want it running after we dispose the command - if (timeBombTask != default) - { - await timeBombTask; - } - } - } - } - finally - { - Interlocked.Add(ref _rowsRead, rowsRead); - Interlocked.Add(ref _resultRead, resultRead); - if (poison) - { - Interlocked.Increment(ref _poisonedEnded); - } - } - } +// throw; +// } +// } +// } +// finally +// { +// // Make sure to clean up our time bomb +// // It is unlikely, but the timebomb may get delayed in the Task Queue +// // And we don't want it running after we dispose the command +// if (timeBombTask != default) +// { +// await timeBombTask; +// } +// } +// } +// } +// finally +// { +// Interlocked.Add(ref _rowsRead, rowsRead); +// Interlocked.Add(ref _resultRead, resultRead); +// if (poison) +// { +// Interlocked.Increment(ref _poisonedEnded); +// } +// } +// } - private async Task TimeBombAsync(SqlCommand command) - { - await SleepAsync(100, 3000); - command.Cancel(); - } +// private async Task TimeBombAsync(SqlCommand command) +// { +// await SleepAsync(100, 3000); +// command.Cancel(); +// } - private async Task SleepAsync(int minMs, int maxMs) - { - int delayMs; - lock (_random) - { - delayMs = _random.Next(minMs, maxMs); - } - await Task.Delay(delayMs); - } +// private async Task SleepAsync(int minMs, int maxMs) +// { +// int delayMs; +// lock (_random) +// { +// delayMs = _random.Next(minMs, maxMs); +// } +// await Task.Delay(delayMs); +// } - private Stopwatch _watch; +// private Stopwatch _watch; - private int _inFlight; - private int _start; - private int _done; - private int _rowsRead; - private int _resultRead; - private int _nonPoisonedExceptions; - private int _poisonedEnded; - private int _poisonCleanUpExceptions; - private bool _continue = true; - private int _found; - private Random _random; - private object _lockObject = new object(); +// private int _inFlight; +// private int _start; +// private int _done; +// private int _rowsRead; +// private int _resultRead; +// private int _nonPoisonedExceptions; +// private int _poisonedEnded; +// private int _poisonCleanUpExceptions; +// private bool _continue = true; +// private int _found; +// private Random _random; +// private object _lockObject = new object(); - private HashSet _exceptionDetails = new HashSet(); - } -} +// private HashSet _exceptionDetails = new HashSet(); +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/AsyncTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/AsyncTest.cs index 080a66b394..02038c5750 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/AsyncTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/AsyncTest.cs @@ -1,106 +1,106 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. -using System.Diagnostics; -using System.Threading.Tasks; -using Xunit; +//using System.Diagnostics; +//using System.Threading.Tasks; +//using Xunit; -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ - public static class AsyncTest - { - [ActiveIssue(5533)] // Async Operations slower than Sync operations - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public static void TestReadAsyncTimeConsumed() - { - const string sql = "SET NOCOUNT ON" - + " SELECT 'a'" - + " DECLARE @t DATETIME = SYSDATETIME()" - + " WHILE DATEDIFF(s, @t, SYSDATETIME()) < 20 BEGIN" - + " SELECT 2 x INTO #y" - + " DROP TABLE #y" - + " END" - + " SELECT 'b'"; - Task t = RunReadAsync(sql); - double elapsedSync = RunReadSync(sql); - t.Wait(); - double elapsedAsync = t.Result; - Assert.True(elapsedAsync < elapsedSync, "Asynchronous operation should be finished quicker than synchronous one"); - int limit = 100; - Assert.True(elapsedAsync < limit, $"Asynchronous operation should be finished within {limit}ms"); - } +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ +// public static class AsyncTest +// { +// [ActiveIssue(5533)] // Async Operations slower than Sync operations +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public static void TestReadAsyncTimeConsumed() +// { +// const string sql = "SET NOCOUNT ON" +// + " SELECT 'a'" +// + " DECLARE @t DATETIME = SYSDATETIME()" +// + " WHILE DATEDIFF(s, @t, SYSDATETIME()) < 20 BEGIN" +// + " SELECT 2 x INTO #y" +// + " DROP TABLE #y" +// + " END" +// + " SELECT 'b'"; +// Task t = RunReadAsync(sql); +// double elapsedSync = RunReadSync(sql); +// t.Wait(); +// double elapsedAsync = t.Result; +// Assert.True(elapsedAsync < elapsedSync, "Asynchronous operation should be finished quicker than synchronous one"); +// int limit = 100; +// Assert.True(elapsedAsync < limit, $"Asynchronous operation should be finished within {limit}ms"); +// } - private static async Task RunReadAsync(string sql) - { - double maxElapsedTimeMillisecond = 0; - using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) - { - await connection.OpenAsync(); - using (SqlCommand command = connection.CreateCommand()) - { - command.CommandText = sql; - using (SqlDataReader reader = await command.ExecuteReaderAsync()) - { - Task t; - Stopwatch stopwatch = new Stopwatch(); - do - { - do - { - stopwatch.Start(); - t = reader.ReadAsync(); - stopwatch.Stop(); - double elased = stopwatch.Elapsed.TotalMilliseconds; - if (maxElapsedTimeMillisecond < elased) - { - maxElapsedTimeMillisecond = elased; - } - } - while (await t); - } - while (reader.NextResult()); - } - } - } +// private static async Task RunReadAsync(string sql) +// { +// double maxElapsedTimeMillisecond = 0; +// using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) +// { +// await connection.OpenAsync(); +// using (SqlCommand command = connection.CreateCommand()) +// { +// command.CommandText = sql; +// using (SqlDataReader reader = await command.ExecuteReaderAsync()) +// { +// Task t; +// Stopwatch stopwatch = new Stopwatch(); +// do +// { +// do +// { +// stopwatch.Start(); +// t = reader.ReadAsync(); +// stopwatch.Stop(); +// double elased = stopwatch.Elapsed.TotalMilliseconds; +// if (maxElapsedTimeMillisecond < elased) +// { +// maxElapsedTimeMillisecond = elased; +// } +// } +// while (await t); +// } +// while (reader.NextResult()); +// } +// } +// } - return maxElapsedTimeMillisecond; - } +// return maxElapsedTimeMillisecond; +// } - private static double RunReadSync(string sql) - { - double maxElapsedTimeMillisecond = 0; - using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) - { - connection.Open(); - using (SqlCommand command = connection.CreateCommand()) - { - command.CommandText = sql; - using (SqlDataReader reader = command.ExecuteReader()) - { - bool result; - Stopwatch stopwatch = new Stopwatch(); - do - { - do - { - stopwatch.Start(); - result = reader.Read(); - stopwatch.Stop(); - double elased = stopwatch.Elapsed.TotalMilliseconds; - if (maxElapsedTimeMillisecond < elased) - { - maxElapsedTimeMillisecond = elased; - } - } - while (result); - } - while (reader.NextResult()); - } - } - } +// private static double RunReadSync(string sql) +// { +// double maxElapsedTimeMillisecond = 0; +// using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) +// { +// connection.Open(); +// using (SqlCommand command = connection.CreateCommand()) +// { +// command.CommandText = sql; +// using (SqlDataReader reader = command.ExecuteReader()) +// { +// bool result; +// Stopwatch stopwatch = new Stopwatch(); +// do +// { +// do +// { +// stopwatch.Start(); +// result = reader.Read(); +// stopwatch.Stop(); +// double elased = stopwatch.Elapsed.TotalMilliseconds; +// if (maxElapsedTimeMillisecond < elased) +// { +// maxElapsedTimeMillisecond = elased; +// } +// } +// while (result); +// } +// while (reader.NextResult()); +// } +// } +// } - return maxElapsedTimeMillisecond; - } - } -} +// return maxElapsedTimeMillisecond; +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/AsyncTimeoutTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/AsyncTimeoutTest.cs index b516fa1a11..e46c4e157e 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/AsyncTimeoutTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/AsyncTimeoutTest.cs @@ -1,210 +1,210 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Data; -using System.Threading.Tasks; -using System.Xml; -using Microsoft.Data.SqlClient.ManualTesting.Tests.SystemDataInternals; -using Xunit; - -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ - public static class AsyncTimeoutTest - { - static string delayQuery2s = "WAITFOR DELAY '00:00:02'"; - static string delayQuery10s = "WAITFOR DELAY '00:00:10'"; - - public enum AsyncAPI - { - ExecuteReaderAsync, - ExecuteScalarAsync, - ExecuteXmlReaderAsync - } - - // Synapse: WAITFOR DELAY not supported [Parse error at line: 1, column: 1: Incorrect syntax near 'WAITFOR'.] - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - [ClassData(typeof(AsyncTimeoutTestVariations))] - public static void TestDelayedAsyncTimeout(AsyncAPI api, string commonObj, int delayPeriod, bool marsEnabled) => - RunTest(api, commonObj, delayPeriod, marsEnabled); - - public class AsyncTimeoutTestVariations : IEnumerable - { - public IEnumerator GetEnumerator() - { - yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Connection", 8000, true }; - yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Connection", 5000, true }; - yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Connection", 0, true }; - yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Connection", 8000, false }; - yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Connection", 5000, false }; - yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Connection", 0, false }; - - yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Connection", 8000, true }; - yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Connection", 5000, true }; - yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Connection", 0, true }; - yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Connection", 8000, false }; - yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Connection", 5000, false }; - yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Connection", 0, false }; - - yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Connection", 8000, true }; - yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Connection", 5000, true }; - yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Connection", 0, true }; - yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Connection", 8000, false }; - yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Connection", 5000, false }; - yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Connection", 0, false }; - - yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Command", 8000, true }; - yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Command", 5000, true }; - yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Command", 0, true }; - yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Command", 8000, false }; - yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Command", 5000, false }; - yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Command", 0, false }; - - yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Command", 8000, true }; - yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Command", 5000, true }; - yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Command", 0, true }; - yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Command", 8000, false }; - yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Command", 5000, false }; - yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Command", 0, false }; - - yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Command", 8000, true }; - yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Command", 5000, true }; - yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Command", 0, true }; - yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Command", 8000, false }; - yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Command", 5000, false }; - yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Command", 0, false }; - } - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } - - private static void RunTest(AsyncAPI api, string commonObj, int timeoutDelay, bool marsEnabled) - { - string connString = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) - { - MultipleActiveResultSets = marsEnabled - }.ConnectionString; - - using (SqlConnection sqlConnection = new SqlConnection(connString)) - { - sqlConnection.Open(); - if (timeoutDelay != 0) - { - ConnectionHelper.SetEnforcedTimeout(sqlConnection, true, timeoutDelay); - } - switch (commonObj) - { - case "Connection": - QueryAndValidate(api, 1, delayQuery2s, 1, true, true, sqlConnection).Wait(); - QueryAndValidate(api, 2, delayQuery2s, 5, false, true, sqlConnection).Wait(); - QueryAndValidate(api, 3, delayQuery10s, 1, true, true, sqlConnection).Wait(); - QueryAndValidate(api, 4, delayQuery2s, 10, false, true, sqlConnection).Wait(); - break; - case "Command": - using (SqlCommand cmd = sqlConnection.CreateCommand()) - { - QueryAndValidate(api, 1, delayQuery2s, 1, true, false, sqlConnection, cmd).Wait(); - QueryAndValidate(api, 2, delayQuery2s, 5, false, false, sqlConnection, cmd).Wait(); - QueryAndValidate(api, 3, delayQuery10s, 1, true, false, sqlConnection, cmd).Wait(); - QueryAndValidate(api, 4, delayQuery2s, 10, false, false, sqlConnection, cmd).Wait(); - } - break; - } - } - } - - private static async Task QueryAndValidate(AsyncAPI api, int index, string delayQuery, int timeout, - bool timeoutExExpected = false, bool useTransaction = false, SqlConnection cn = null, SqlCommand cmd = null) - { - SqlTransaction tx = null; - try - { - if (cn != null) - { - if (cn.State != ConnectionState.Open) - { - await cn.OpenAsync(); - } - cmd = cn.CreateCommand(); - if (useTransaction) - { - tx = cn.BeginTransaction(IsolationLevel.ReadCommitted); - cmd.Transaction = tx; - } - } - - cmd.CommandTimeout = timeout; - if (api != AsyncAPI.ExecuteXmlReaderAsync) - { - cmd.CommandText = delayQuery + $";select {index} as Id;"; - } - else - { - cmd.CommandText = delayQuery + $";select {index} as Id FOR XML PATH;"; - } - - var result = -1; - switch (api) - { - case AsyncAPI.ExecuteReaderAsync: - using (SqlDataReader reader = await cmd.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var columnIndex = reader.GetOrdinal("Id"); - result = reader.GetInt32(columnIndex); - break; - } - } - break; - case AsyncAPI.ExecuteScalarAsync: - result = (int)await cmd.ExecuteScalarAsync().ConfigureAwait(false); - break; - case AsyncAPI.ExecuteXmlReaderAsync: - using (XmlReader reader = await cmd.ExecuteXmlReaderAsync().ConfigureAwait(false)) - { - try - { - Assert.True(reader.Settings.Async); - reader.ReadToDescendant("Id"); - result = reader.ReadElementContentAsInt(); - } - catch (Exception ex) - { - Assert.False(true, "Exception occurred: " + ex.Message); - } - } - break; - } - - if (result != index) - { - throw new Exception("High Alert! Wrong data received for index: " + index); - } - else - { - Assert.True(!timeoutExExpected && result == index); - } - } - catch (SqlException e) - { - if (!timeoutExExpected) - throw new Exception("Index " + index + " failed with: " + e.Message); - else - Assert.True(timeoutExExpected && e.Class == 11 && e.Number == -2); - } - finally - { - if (cn != null) - { - if (useTransaction) - tx.Commit(); - cn.Close(); - } - } - } - } -} +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. + +//using System; +//using System.Collections; +//using System.Collections.Generic; +//using System.Data; +//using System.Threading.Tasks; +//using System.Xml; +//using Microsoft.Data.SqlClient.ManualTesting.Tests.SystemDataInternals; +//using Xunit; + +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ +// public static class AsyncTimeoutTest +// { +// static string delayQuery2s = "WAITFOR DELAY '00:00:02'"; +// static string delayQuery10s = "WAITFOR DELAY '00:00:10'"; + +// public enum AsyncAPI +// { +// ExecuteReaderAsync, +// ExecuteScalarAsync, +// ExecuteXmlReaderAsync +// } + +// // Synapse: WAITFOR DELAY not supported [Parse error at line: 1, column: 1: Incorrect syntax near 'WAITFOR'.] +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// [ClassData(typeof(AsyncTimeoutTestVariations))] +// public static void TestDelayedAsyncTimeout(AsyncAPI api, string commonObj, int delayPeriod, bool marsEnabled) => +// RunTest(api, commonObj, delayPeriod, marsEnabled); + +// public class AsyncTimeoutTestVariations : IEnumerable +// { +// public IEnumerator GetEnumerator() +// { +// yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Connection", 8000, true }; +// yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Connection", 5000, true }; +// yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Connection", 0, true }; +// yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Connection", 8000, false }; +// yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Connection", 5000, false }; +// yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Connection", 0, false }; + +// yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Connection", 8000, true }; +// yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Connection", 5000, true }; +// yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Connection", 0, true }; +// yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Connection", 8000, false }; +// yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Connection", 5000, false }; +// yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Connection", 0, false }; + +// yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Connection", 8000, true }; +// yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Connection", 5000, true }; +// yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Connection", 0, true }; +// yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Connection", 8000, false }; +// yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Connection", 5000, false }; +// yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Connection", 0, false }; + +// yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Command", 8000, true }; +// yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Command", 5000, true }; +// yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Command", 0, true }; +// yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Command", 8000, false }; +// yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Command", 5000, false }; +// yield return new object[] { AsyncAPI.ExecuteReaderAsync, "Command", 0, false }; + +// yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Command", 8000, true }; +// yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Command", 5000, true }; +// yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Command", 0, true }; +// yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Command", 8000, false }; +// yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Command", 5000, false }; +// yield return new object[] { AsyncAPI.ExecuteScalarAsync, "Command", 0, false }; + +// yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Command", 8000, true }; +// yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Command", 5000, true }; +// yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Command", 0, true }; +// yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Command", 8000, false }; +// yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Command", 5000, false }; +// yield return new object[] { AsyncAPI.ExecuteXmlReaderAsync, "Command", 0, false }; +// } + +// IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); +// } + +// private static void RunTest(AsyncAPI api, string commonObj, int timeoutDelay, bool marsEnabled) +// { +// string connString = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) +// { +// MultipleActiveResultSets = marsEnabled +// }.ConnectionString; + +// using (SqlConnection sqlConnection = new SqlConnection(connString)) +// { +// sqlConnection.Open(); +// if (timeoutDelay != 0) +// { +// ConnectionHelper.SetEnforcedTimeout(sqlConnection, true, timeoutDelay); +// } +// switch (commonObj) +// { +// case "Connection": +// QueryAndValidate(api, 1, delayQuery2s, 1, true, true, sqlConnection).Wait(); +// QueryAndValidate(api, 2, delayQuery2s, 5, false, true, sqlConnection).Wait(); +// QueryAndValidate(api, 3, delayQuery10s, 1, true, true, sqlConnection).Wait(); +// QueryAndValidate(api, 4, delayQuery2s, 10, false, true, sqlConnection).Wait(); +// break; +// case "Command": +// using (SqlCommand cmd = sqlConnection.CreateCommand()) +// { +// QueryAndValidate(api, 1, delayQuery2s, 1, true, false, sqlConnection, cmd).Wait(); +// QueryAndValidate(api, 2, delayQuery2s, 5, false, false, sqlConnection, cmd).Wait(); +// QueryAndValidate(api, 3, delayQuery10s, 1, true, false, sqlConnection, cmd).Wait(); +// QueryAndValidate(api, 4, delayQuery2s, 10, false, false, sqlConnection, cmd).Wait(); +// } +// break; +// } +// } +// } + +// private static async Task QueryAndValidate(AsyncAPI api, int index, string delayQuery, int timeout, +// bool timeoutExExpected = false, bool useTransaction = false, SqlConnection cn = null, SqlCommand cmd = null) +// { +// SqlTransaction tx = null; +// try +// { +// if (cn != null) +// { +// if (cn.State != ConnectionState.Open) +// { +// await cn.OpenAsync(); +// } +// cmd = cn.CreateCommand(); +// if (useTransaction) +// { +// tx = cn.BeginTransaction(IsolationLevel.ReadCommitted); +// cmd.Transaction = tx; +// } +// } + +// cmd.CommandTimeout = timeout; +// if (api != AsyncAPI.ExecuteXmlReaderAsync) +// { +// cmd.CommandText = delayQuery + $";select {index} as Id;"; +// } +// else +// { +// cmd.CommandText = delayQuery + $";select {index} as Id FOR XML PATH;"; +// } + +// var result = -1; +// switch (api) +// { +// case AsyncAPI.ExecuteReaderAsync: +// using (SqlDataReader reader = await cmd.ExecuteReaderAsync().ConfigureAwait(false)) +// { +// while (await reader.ReadAsync().ConfigureAwait(false)) +// { +// var columnIndex = reader.GetOrdinal("Id"); +// result = reader.GetInt32(columnIndex); +// break; +// } +// } +// break; +// case AsyncAPI.ExecuteScalarAsync: +// result = (int)await cmd.ExecuteScalarAsync().ConfigureAwait(false); +// break; +// case AsyncAPI.ExecuteXmlReaderAsync: +// using (XmlReader reader = await cmd.ExecuteXmlReaderAsync().ConfigureAwait(false)) +// { +// try +// { +// Assert.True(reader.Settings.Async); +// reader.ReadToDescendant("Id"); +// result = reader.ReadElementContentAsInt(); +// } +// catch (Exception ex) +// { +// Assert.False(true, "Exception occurred: " + ex.Message); +// } +// } +// break; +// } + +// if (result != index) +// { +// throw new Exception("High Alert! Wrong data received for index: " + index); +// } +// else +// { +// Assert.True(!timeoutExExpected && result == index); +// } +// } +// catch (SqlException e) +// { +// if (!timeoutExExpected) +// throw new Exception("Index " + index + " failed with: " + e.Message); +// else +// Assert.True(timeoutExExpected && e.Class == 11 && e.Number == -2); +// } +// finally +// { +// if (cn != null) +// { +// if (useTransaction) +// tx.Commit(); +// cn.Close(); +// } +// } +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/BeginExecAsyncTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/BeginExecAsyncTest.cs index cdf89fbac1..8ed5daaf59 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/BeginExecAsyncTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/BeginExecAsyncTest.cs @@ -1,74 +1,74 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. -using System; -using Xunit; +//using System; +//using Xunit; -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ - public static class BeginExecAsyncTest - { - private static string GenerateCommandText() - { - int suffix = (new Random()).Next(5000); +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ +// public static class BeginExecAsyncTest +// { +// private static string GenerateCommandText() +// { +// int suffix = (new Random()).Next(5000); - string commandText = - $"CREATE TABLE #Shippers{suffix}(" + - $"[ShipperID][int] NULL," + - $"[CompanyName] [nvarchar] (40) NOT NULL," + - $"[Phone] [nvarchar] (24) NULL )" + - $"INSERT INTO #Shippers{suffix}" + - $"([CompanyName] " + - $",[Phone])" + - $"VALUES " + - $"('Acme Inc.' " + - $",'555-1212'); " + - $"WAITFOR DELAY '0:0:3'; " + - $"DELETE FROM #Shippers{suffix} WHERE ShipperID > 3;"; +// string commandText = +// $"CREATE TABLE #Shippers{suffix}(" + +// $"[ShipperID][int] NULL," + +// $"[CompanyName] [nvarchar] (40) NOT NULL," + +// $"[Phone] [nvarchar] (24) NULL )" + +// $"INSERT INTO #Shippers{suffix}" + +// $"([CompanyName] " + +// $",[Phone])" + +// $"VALUES " + +// $"('Acme Inc.' " + +// $",'555-1212'); " + +// $"WAITFOR DELAY '0:0:3'; " + +// $"DELETE FROM #Shippers{suffix} WHERE ShipperID > 3;"; - return commandText; - } +// return commandText; +// } - // Synapse: Parse error at line: 1, column: 201: Incorrect syntax near ';'. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public static void ExecuteTest() - { - using SqlConnection connection = new(DataTestUtility.TCPConnectionString); +// // Synapse: Parse error at line: 1, column: 201: Incorrect syntax near ';'. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public static void ExecuteTest() +// { +// using SqlConnection connection = new(DataTestUtility.TCPConnectionString); - using SqlCommand command = new(GenerateCommandText(), connection); - connection.Open(); +// using SqlCommand command = new(GenerateCommandText(), connection); +// connection.Open(); - IAsyncResult result = command.BeginExecuteNonQuery(); - while (!result.IsCompleted) - { - System.Threading.Thread.Sleep(100); - } +// IAsyncResult result = command.BeginExecuteNonQuery(); +// while (!result.IsCompleted) +// { +// System.Threading.Thread.Sleep(100); +// } - Assert.True(command.EndExecuteNonQuery(result) > 0, "FAILED: BeginExecuteNonQuery did not complete successfully."); - } +// Assert.True(command.EndExecuteNonQuery(result) > 0, "FAILED: BeginExecuteNonQuery did not complete successfully."); +// } - // Synapse: Parse error at line: 1, column: 201: Incorrect syntax near ';'. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public static void FailureTest() - { - using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) - { - SqlCommand command = new SqlCommand(GenerateCommandText(), connection); - connection.Open(); +// // Synapse: Parse error at line: 1, column: 201: Incorrect syntax near ';'. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public static void FailureTest() +// { +// using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) +// { +// SqlCommand command = new SqlCommand(GenerateCommandText(), connection); +// connection.Open(); - //Try to execute a synchronous query on same command - IAsyncResult result = command.BeginExecuteNonQuery(); - InvalidOperationException ex = Assert.Throws(() => command.ExecuteNonQuery()); +// //Try to execute a synchronous query on same command +// IAsyncResult result = command.BeginExecuteNonQuery(); +// InvalidOperationException ex = Assert.Throws(() => command.ExecuteNonQuery()); - while (!result.IsCompleted) - { - System.Threading.Thread.Sleep(100); - } +// while (!result.IsCompleted) +// { +// System.Threading.Thread.Sleep(100); +// } - Assert.True(result.IsCompleted, "FAILED: ExecuteNonQueryAsync Task did not complete successfully."); - Assert.True(command.EndExecuteNonQuery(result) > 0, "FAILED: No rows affected"); - } - } - } -} +// Assert.True(result.IsCompleted, "FAILED: ExecuteNonQueryAsync Task did not complete successfully."); +// Assert.True(command.EndExecuteNonQuery(result) > 0, "FAILED: No rows affected"); +// } +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/BeginExecReaderAsyncTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/BeginExecReaderAsyncTest.cs index daa58b1851..dcffee869a 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/BeginExecReaderAsyncTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/BeginExecReaderAsyncTest.cs @@ -1,86 +1,86 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. -using System; -using Xunit; +//using System; +//using Xunit; -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ - public static class BeginExecReaderAsyncTest - { - private static string GenerateCommandText() - { - int suffix = (new Random()).Next(5000); - string companyName = "M Inc."; - string phone = "777-1111"; +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ +// public static class BeginExecReaderAsyncTest +// { +// private static string GenerateCommandText() +// { +// int suffix = (new Random()).Next(5000); +// string companyName = "M Inc."; +// string phone = "777-1111"; - string commandText = - $"CREATE TABLE #Shippers{suffix}(" + - $"[ShipperID][int] NULL," + - $"[CompanyName] [nvarchar] (40) NOT NULL," + - $"[Phone] [nvarchar] (24) NULL )" + - $"INSERT INTO #Shippers{suffix}" + - $"([CompanyName] " + - $",[Phone])" + - $"VALUES " + - $"('{companyName}' " + - $",'{phone}'); " + - $"WAITFOR DELAY '0:0:3'; " + - $"select s.ShipperID, s.CompanyName, s.Phone " + - $"from #Shippers{suffix} s; "; +// string commandText = +// $"CREATE TABLE #Shippers{suffix}(" + +// $"[ShipperID][int] NULL," + +// $"[CompanyName] [nvarchar] (40) NOT NULL," + +// $"[Phone] [nvarchar] (24) NULL )" + +// $"INSERT INTO #Shippers{suffix}" + +// $"([CompanyName] " + +// $",[Phone])" + +// $"VALUES " + +// $"('{companyName}' " + +// $",'{phone}'); " + +// $"WAITFOR DELAY '0:0:3'; " + +// $"select s.ShipperID, s.CompanyName, s.Phone " + +// $"from #Shippers{suffix} s; "; - return commandText; - } +// return commandText; +// } - // Synapse: Parse error at line: 1, column: 198: Incorrect syntax near ';'. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public static void ExecuteTest() - { - using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) - { - SqlCommand command = new SqlCommand(GenerateCommandText(), connection); - connection.Open(); +// // Synapse: Parse error at line: 1, column: 198: Incorrect syntax near ';'. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public static void ExecuteTest() +// { +// using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) +// { +// SqlCommand command = new SqlCommand(GenerateCommandText(), connection); +// connection.Open(); - IAsyncResult result = command.BeginExecuteReader(); - while (!result.IsCompleted) - { - System.Threading.Thread.Sleep(100); - } - SqlDataReader reader = command.EndExecuteReader(result); - Assert.True(reader.HasRows, $"FAILED: Reader has no rows"); - } - } +// IAsyncResult result = command.BeginExecuteReader(); +// while (!result.IsCompleted) +// { +// System.Threading.Thread.Sleep(100); +// } +// SqlDataReader reader = command.EndExecuteReader(result); +// Assert.True(reader.HasRows, $"FAILED: Reader has no rows"); +// } +// } - // Synapse: Parse error at line: 1, column: 198: Incorrect syntax near ';'. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public static void BeginExecuteReaderWithCallback() - { - object state = new object(); - bool callbackExecutedFlag = false; +// // Synapse: Parse error at line: 1, column: 198: Incorrect syntax near ';'. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public static void BeginExecuteReaderWithCallback() +// { +// object state = new object(); +// bool callbackExecutedFlag = false; - using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) - using (SqlCommand command = new SqlCommand(GenerateCommandText(), connection)) - { - connection.Open(); +// using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) +// using (SqlCommand command = new SqlCommand(GenerateCommandText(), connection)) +// { +// connection.Open(); - Tuple stateAndCommand = new Tuple(state, command); +// Tuple stateAndCommand = new Tuple(state, command); - IAsyncResult result = command.BeginExecuteReader(ar => - { - Tuple asyncArgs = ar.AsyncState as Tuple; - Assert.NotNull(asyncArgs); +// IAsyncResult result = command.BeginExecuteReader(ar => +// { +// Tuple asyncArgs = ar.AsyncState as Tuple; +// Assert.NotNull(asyncArgs); - SqlDataReader reader = asyncArgs.Item2.EndExecuteReader(ar); - callbackExecutedFlag = true; - Assert.True(reader.HasRows, $"FAILED: Reader has no rows"); - Assert.Equal(state, asyncArgs.Item1); - }, stateAndCommand); +// SqlDataReader reader = asyncArgs.Item2.EndExecuteReader(ar); +// callbackExecutedFlag = true; +// Assert.True(reader.HasRows, $"FAILED: Reader has no rows"); +// Assert.Equal(state, asyncArgs.Item1); +// }, stateAndCommand); - System.Threading.Thread.Sleep(TimeSpan.FromSeconds(10)); +// System.Threading.Thread.Sleep(TimeSpan.FromSeconds(10)); - Assert.True(callbackExecutedFlag, $"FAILED: Callback did not executed"); - } - } - } -} +// Assert.True(callbackExecutedFlag, $"FAILED: Callback did not executed"); +// } +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/XmlReaderAsyncTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/XmlReaderAsyncTest.cs index 9d425b1b75..ecc0e831ee 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/XmlReaderAsyncTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AsyncTest/XmlReaderAsyncTest.cs @@ -1,98 +1,98 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. -using System; -using System.Xml; -using System.Xml.Linq; -using Xunit; +//using System; +//using System.Xml; +//using System.Xml.Linq; +//using Xunit; -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ - public static class XmlReaderAsyncTest - { - private const string CommandText = - "SELECT * from dbo.Customers FOR XML AUTO, XMLDATA;"; +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ +// public static class XmlReaderAsyncTest +// { +// private const string CommandText = +// "SELECT * from dbo.Customers FOR XML AUTO, XMLDATA;"; - // Synapse: Parse error at line: 1, column: 29: Incorrect syntax near 'FOR'. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public static void ExecuteTest() - { - using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) - using (SqlCommand command = new SqlCommand(CommandText, connection)) - { - connection.Open(); +// // Synapse: Parse error at line: 1, column: 29: Incorrect syntax near 'FOR'. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public static void ExecuteTest() +// { +// using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) +// using (SqlCommand command = new SqlCommand(CommandText, connection)) +// { +// connection.Open(); - IAsyncResult result = command.BeginExecuteXmlReader(); - while (!result.IsCompleted) - { - System.Threading.Thread.Sleep(100); - } +// IAsyncResult result = command.BeginExecuteXmlReader(); +// while (!result.IsCompleted) +// { +// System.Threading.Thread.Sleep(100); +// } - using (XmlReader xmlReader = command.EndExecuteXmlReader(result)) - { - // Issue #781: Test failed here as xmlReader.Settings.Async was set to false - Assert.True(xmlReader.Settings.Async); - xmlReader.ReadToDescendant("dbo.Customers"); - Assert.Equal("ALFKI", xmlReader["CustomerID"]); - } - } - } +// using (XmlReader xmlReader = command.EndExecuteXmlReader(result)) +// { +// // Issue #781: Test failed here as xmlReader.Settings.Async was set to false +// Assert.True(xmlReader.Settings.Async); +// xmlReader.ReadToDescendant("dbo.Customers"); +// Assert.Equal("ALFKI", xmlReader["CustomerID"]); +// } +// } +// } - // Synapse: Northwind dependency + Parse error at line: 1, column: 29: Incorrect syntax near 'FOR'. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public static void ExceptionTest() - { - using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) - using (SqlCommand command = new SqlCommand(CommandText, connection)) - { - connection.Open(); +// // Synapse: Northwind dependency + Parse error at line: 1, column: 29: Incorrect syntax near 'FOR'. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public static void ExceptionTest() +// { +// using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) +// using (SqlCommand command = new SqlCommand(CommandText, connection)) +// { +// connection.Open(); - //Try to execute a synchronous query on same command - IAsyncResult result = command.BeginExecuteXmlReader(); +// //Try to execute a synchronous query on same command +// IAsyncResult result = command.BeginExecuteXmlReader(); - Assert.Throws(delegate - { command.ExecuteXmlReader(); }); +// Assert.Throws(delegate +// { command.ExecuteXmlReader(); }); - while (!result.IsCompleted) - { - System.Threading.Thread.Sleep(100); - } +// while (!result.IsCompleted) +// { +// System.Threading.Thread.Sleep(100); +// } - using (XmlReader xmlReader = command.EndExecuteXmlReader(result)) - { - // Issue #781: Test failed here as xmlReader.Settings.Async was set to false - Assert.True(xmlReader.Settings.Async); - xmlReader.ReadToDescendant("dbo.Customers"); - Assert.Equal("ALFKI", xmlReader["CustomerID"]); - } - } - } +// using (XmlReader xmlReader = command.EndExecuteXmlReader(result)) +// { +// // Issue #781: Test failed here as xmlReader.Settings.Async was set to false +// Assert.True(xmlReader.Settings.Async); +// xmlReader.ReadToDescendant("dbo.Customers"); +// Assert.Equal("ALFKI", xmlReader["CustomerID"]); +// } +// } +// } - // Synapse: Parse error at line: 1, column: 29: Incorrect syntax near 'FOR'. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public static async void MoveToContentAsyncTest() - { - using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) - using (SqlCommand command = new SqlCommand(CommandText, connection)) - { - connection.Open(); +// // Synapse: Parse error at line: 1, column: 29: Incorrect syntax near 'FOR'. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public static async void MoveToContentAsyncTest() +// { +// using (SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString)) +// using (SqlCommand command = new SqlCommand(CommandText, connection)) +// { +// connection.Open(); - using (XmlReader xmlReader = await command.ExecuteXmlReaderAsync().ConfigureAwait(false)) - { - try - { - // Issue #781: Test failed here as xmlReader.Settings.Async was set to false - Assert.True(xmlReader.Settings.Async); - xmlReader.ReadToDescendant("dbo.Customers"); - Assert.Equal("ALFKI", xmlReader["CustomerID"]); - } - catch (Exception ex) - { - Assert.False(true, "Exception occurred: " + ex.Message); - } - } - } - } - } -} +// using (XmlReader xmlReader = await command.ExecuteXmlReaderAsync().ConfigureAwait(false)) +// { +// try +// { +// // Issue #781: Test failed here as xmlReader.Settings.Async was set to false +// Assert.True(xmlReader.Settings.Async); +// xmlReader.ReadToDescendant("dbo.Customers"); +// Assert.Equal("ALFKI", xmlReader["CustomerID"]); +// } +// catch (Exception ex) +// { +// Assert.False(true, "Exception occurred: " + ex.Message); +// } +// } +// } +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConfigurableIpPreferenceTest/ConfigurableIpPreferenceTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConfigurableIpPreferenceTest/ConfigurableIpPreferenceTest.cs index 8003660889..38819c85e8 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConfigurableIpPreferenceTest/ConfigurableIpPreferenceTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConfigurableIpPreferenceTest/ConfigurableIpPreferenceTest.cs @@ -1,125 +1,125 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. -using System; -using System.Collections.Generic; -using System.Data; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Reflection; -using Microsoft.Data.SqlClient.ManualTesting.Tests.SystemDataInternals; -using Xunit; +//using System; +//using System.Collections.Generic; +//using System.Data; +//using System.Linq; +//using System.Net; +//using System.Net.Sockets; +//using System.Reflection; +//using Microsoft.Data.SqlClient.ManualTesting.Tests.SystemDataInternals; +//using Xunit; -using static Microsoft.Data.SqlClient.ManualTesting.Tests.DataTestUtility; -using static Microsoft.Data.SqlClient.ManualTesting.Tests.DNSCachingTest; +//using static Microsoft.Data.SqlClient.ManualTesting.Tests.DataTestUtility; +//using static Microsoft.Data.SqlClient.ManualTesting.Tests.DNSCachingTest; -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ - public class ConfigurableIpPreferenceTest - { - private const string CnnPrefIPv6 = ";IPAddressPreference=IPv6First"; - private const string CnnPrefIPv4 = ";IPAddressPreference=IPv4First"; +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ +// public class ConfigurableIpPreferenceTest +// { +// private const string CnnPrefIPv6 = ";IPAddressPreference=IPv6First"; +// private const string CnnPrefIPv4 = ";IPAddressPreference=IPv4First"; - private static bool IsTCPConnectionStringSetup() => !string.IsNullOrEmpty(TCPConnectionString); - private static bool IsValidDataSource() - { - SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(TCPConnectionString); - int startIdx = builder.DataSource.IndexOf(':') + 1; - int endIdx = builder.DataSource.IndexOf(','); - string serverName; - if (endIdx == -1) - { - serverName = builder.DataSource.Substring(startIdx); - } - else - { - serverName = builder.DataSource.Substring(startIdx, endIdx - startIdx); - } +// private static bool IsTCPConnectionStringSetup() => !string.IsNullOrEmpty(TCPConnectionString); +// private static bool IsValidDataSource() +// { +// SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(TCPConnectionString); +// int startIdx = builder.DataSource.IndexOf(':') + 1; +// int endIdx = builder.DataSource.IndexOf(','); +// string serverName; +// if (endIdx == -1) +// { +// serverName = builder.DataSource.Substring(startIdx); +// } +// else +// { +// serverName = builder.DataSource.Substring(startIdx, endIdx - startIdx); +// } - List ipAddresses = Dns.GetHostAddresses(serverName).ToList(); - return ipAddresses.Exists(ip => ip.AddressFamily == AddressFamily.InterNetwork) && - ipAddresses.Exists(ip => ip.AddressFamily == AddressFamily.InterNetworkV6); - } +// List ipAddresses = Dns.GetHostAddresses(serverName).ToList(); +// return ipAddresses.Exists(ip => ip.AddressFamily == AddressFamily.InterNetwork) && +// ipAddresses.Exists(ip => ip.AddressFamily == AddressFamily.InterNetworkV6); +// } - [ConditionalTheory(nameof(IsTCPConnectionStringSetup), nameof(IsValidDataSource))] - [InlineData(CnnPrefIPv6)] - [InlineData(CnnPrefIPv4)] - [InlineData(";IPAddressPreference=UsePlatformDefault")] - public void ConfigurableIpPreference(string ipPreference) - { - using (SqlConnection connection = new SqlConnection(TCPConnectionString + ipPreference -#if NETFRAMEWORK - + ";TransparentNetworkIPResolution=false" // doesn't support in .NET Core -#endif - )) - { - connection.Open(); - Assert.Equal(ConnectionState.Open, connection.State); - Tuple DNSInfo = connection.GetSQLDNSInfo(); - if(ipPreference == CnnPrefIPv4) - { - Assert.NotNull(DNSInfo.Item2); //IPv4 - Assert.Null(DNSInfo.Item3); //IPv6 - } - else if(ipPreference == CnnPrefIPv6) - { - Assert.Null(DNSInfo.Item2); - Assert.NotNull(DNSInfo.Item3); - } - else - { - Assert.True((DNSInfo.Item2 != null && DNSInfo.Item3 == null) || (DNSInfo.Item2 == null && DNSInfo.Item3 != null)); - } - } - } +// [ConditionalTheory(nameof(IsTCPConnectionStringSetup), nameof(IsValidDataSource))] +// [InlineData(CnnPrefIPv6)] +// [InlineData(CnnPrefIPv4)] +// [InlineData(";IPAddressPreference=UsePlatformDefault")] +// public void ConfigurableIpPreference(string ipPreference) +// { +// using (SqlConnection connection = new SqlConnection(TCPConnectionString + ipPreference +//#if NETFRAMEWORK +// + ";TransparentNetworkIPResolution=false" // doesn't support in .NET Core +//#endif +// )) +// { +// connection.Open(); +// Assert.Equal(ConnectionState.Open, connection.State); +// Tuple DNSInfo = connection.GetSQLDNSInfo(); +// if(ipPreference == CnnPrefIPv4) +// { +// Assert.NotNull(DNSInfo.Item2); //IPv4 +// Assert.Null(DNSInfo.Item3); //IPv6 +// } +// else if(ipPreference == CnnPrefIPv6) +// { +// Assert.Null(DNSInfo.Item2); +// Assert.NotNull(DNSInfo.Item3); +// } +// else +// { +// Assert.True((DNSInfo.Item2 != null && DNSInfo.Item3 == null) || (DNSInfo.Item2 == null && DNSInfo.Item3 != null)); +// } +// } +// } - // Azure SQL Server doesn't support dual-stack IPv4 and IPv6 that is going to be supported by end of 2021. - [ConditionalTheory(typeof(DataTestUtility), nameof(DoesHostAddressContainBothIPv4AndIPv6), nameof(IsUsingManagedSNI))] - [InlineData(CnnPrefIPv6)] - [InlineData(CnnPrefIPv4)] - public void ConfigurableIpPreferenceManagedSni(string ipPreference) - => TestCachedConfigurableIpPreference(ipPreference, DNSCachingConnString); +// // Azure SQL Server doesn't support dual-stack IPv4 and IPv6 that is going to be supported by end of 2021. +// [ConditionalTheory(typeof(DataTestUtility), nameof(DoesHostAddressContainBothIPv4AndIPv6), nameof(IsUsingManagedSNI))] +// [InlineData(CnnPrefIPv6)] +// [InlineData(CnnPrefIPv4)] +// public void ConfigurableIpPreferenceManagedSni(string ipPreference) +// => TestCachedConfigurableIpPreference(ipPreference, DNSCachingConnString); - private void TestCachedConfigurableIpPreference(string ipPreference, string cnnString) - { - using (SqlConnection connection = new SqlConnection(cnnString + ipPreference)) - { - // each successful connection updates the dns cache entry for the data source - connection.Open(); - var SQLFallbackDNSCacheInstance = GetDnsCache(); +// private void TestCachedConfigurableIpPreference(string ipPreference, string cnnString) +// { +// using (SqlConnection connection = new SqlConnection(cnnString + ipPreference)) +// { +// // each successful connection updates the dns cache entry for the data source +// connection.Open(); +// var SQLFallbackDNSCacheInstance = GetDnsCache(); - // get the dns cache entry with the given key. parameters[1] will be initialized as the entry - object[] parameters = new object[] { connection.DataSource, null }; - SQLFallbackDNSCacheGetDNSInfo.Invoke(SQLFallbackDNSCacheInstance, parameters); - var dnsCacheEntry = parameters[1]; +// // get the dns cache entry with the given key. parameters[1] will be initialized as the entry +// object[] parameters = new object[] { connection.DataSource, null }; +// SQLFallbackDNSCacheGetDNSInfo.Invoke(SQLFallbackDNSCacheInstance, parameters); +// var dnsCacheEntry = parameters[1]; - const string AddrIPv4Property = "AddrIPv4"; - const string AddrIPv6Property = "AddrIPv6"; - const string FQDNProperty = "FQDN"; +// const string AddrIPv4Property = "AddrIPv4"; +// const string AddrIPv6Property = "AddrIPv6"; +// const string FQDNProperty = "FQDN"; - Assert.NotNull(dnsCacheEntry); - Assert.Equal(connection.DataSource, GetPropertyValueFromCacheEntry(FQDNProperty, dnsCacheEntry)); +// Assert.NotNull(dnsCacheEntry); +// Assert.Equal(connection.DataSource, GetPropertyValueFromCacheEntry(FQDNProperty, dnsCacheEntry)); - if (ipPreference == CnnPrefIPv4) - { - Assert.NotNull(GetPropertyValueFromCacheEntry(AddrIPv4Property, dnsCacheEntry)); - Assert.Null(GetPropertyValueFromCacheEntry(AddrIPv6Property, dnsCacheEntry)); - } - else if (ipPreference == CnnPrefIPv6) - { - string ipv6 = GetPropertyValueFromCacheEntry(AddrIPv6Property, dnsCacheEntry); - Assert.NotNull(ipv6); - Assert.Null(GetPropertyValueFromCacheEntry(AddrIPv4Property, dnsCacheEntry)); - } - } +// if (ipPreference == CnnPrefIPv4) +// { +// Assert.NotNull(GetPropertyValueFromCacheEntry(AddrIPv4Property, dnsCacheEntry)); +// Assert.Null(GetPropertyValueFromCacheEntry(AddrIPv6Property, dnsCacheEntry)); +// } +// else if (ipPreference == CnnPrefIPv6) +// { +// string ipv6 = GetPropertyValueFromCacheEntry(AddrIPv6Property, dnsCacheEntry); +// Assert.NotNull(ipv6); +// Assert.Null(GetPropertyValueFromCacheEntry(AddrIPv4Property, dnsCacheEntry)); +// } +// } - object GetDnsCache() => - SQLFallbackDNSCacheType.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public).GetValue(null); +// object GetDnsCache() => +// SQLFallbackDNSCacheType.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public).GetValue(null); - string GetPropertyValueFromCacheEntry(string property, object dnsCacheEntry) => - (string)SQLDNSInfoType.GetProperty(property).GetValue(dnsCacheEntry); - } - } -} +// string GetPropertyValueFromCacheEntry(string property, object dnsCacheEntry) => +// (string)SQLDNSInfoType.GetProperty(property).GetValue(dnsCacheEntry); +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectionPoolTest/ConnectionPoolTest.Debug.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectionPoolTest/ConnectionPoolTest.Debug.cs index 8f911fc2a8..965e2f540c 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectionPoolTest/ConnectionPoolTest.Debug.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectionPoolTest/ConnectionPoolTest.Debug.cs @@ -1,193 +1,193 @@ -using System; -using System.Runtime.ExceptionServices; -using System.Threading; -using System.Threading.Tasks; -using Xunit; -using static Microsoft.Data.SqlClient.ManualTesting.Tests.ConnectionPoolTest; - -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ - public static class ConnectionPoolTestDebug - { - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsUsingManagedSNI))] - [ClassData(typeof(ConnectionPoolConnectionStringProvider))] - public static void ReplacementConnectionUsesSemaphoreTest(string connectionString) - { - string newConnectionString = (new SqlConnectionStringBuilder(connectionString) { MaxPoolSize = 2, ConnectTimeout = 5 }).ConnectionString; - SqlConnection.ClearAllPools(); - - using SqlConnection liveConnection = new(newConnectionString); - using SqlConnection deadConnection = new(newConnectionString); - liveConnection.Open(); - deadConnection.Open(); - InternalConnectionWrapper deadConnectionInternal = new(deadConnection); - InternalConnectionWrapper liveConnectionInternal = new(liveConnection); - deadConnectionInternal.KillConnection(); - deadConnection.Close(); - liveConnection.Close(); - - Task[] tasks = new Task[3]; - Barrier syncBarrier = new(tasks.Length); - Func taskFunction = (() => ReplacementConnectionUsesSemaphoreTask(newConnectionString, syncBarrier)); - for (int i = 0; i < tasks.Length; i++) - { - tasks[i] = Task.Factory.StartNew(taskFunction); - } - - bool taskWithLiveConnection = false; - bool taskWithNewConnection = false; - bool taskWithCorrectException = false; - - Task waitAllTask = Task.Factory.ContinueWhenAll(tasks, (completedTasks) => - { - foreach (var item in completedTasks) - { - if (item.Status == TaskStatus.Faulted) - { - // One task should have a timeout exception - if ((!taskWithCorrectException) && (item.Exception.InnerException is InvalidOperationException) && (item.Exception.InnerException.Message.StartsWith(SystemDataResourceManager.Instance.ADP_PooledOpenTimeout))) - taskWithCorrectException = true; - else if (!taskWithCorrectException) - { - // Rethrow the unknown exception - ExceptionDispatchInfo exceptionInfo = ExceptionDispatchInfo.Capture(item.Exception); - exceptionInfo.Throw(); - } - } - else if (item.Status == TaskStatus.RanToCompletion) - { - // One task should get the live connection - if (item.Result.Equals(liveConnectionInternal)) - { - if (!taskWithLiveConnection) - taskWithLiveConnection = true; - } - else if (!item.Result.Equals(deadConnectionInternal) && !taskWithNewConnection) - taskWithNewConnection = true; - } - else - Console.WriteLine("ERROR: Task in unknown state: {0}", item.Status); - } - }); - - waitAllTask.Wait(); - Assert.True(taskWithLiveConnection && taskWithNewConnection && taskWithCorrectException, - $"Tasks didn't finish as expected.\n" + - $"Task with live connection: {taskWithLiveConnection}\n" + - $"Task with new connection: {taskWithNewConnection}\n" + - $"Task with correct exception: {taskWithCorrectException}\n"); - } - - /// - /// Tests if killing the connection using the InternalConnectionWrapper is working - /// - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsUsingManagedSNI))] - [ClassData(typeof(ConnectionPoolConnectionStringProvider))] - public static void KillConnectionTest(string connectionString) - { - InternalConnectionWrapper wrapper = null; - - using (SqlConnection connection = new(connectionString)) - { - connection.Open(); - wrapper = new InternalConnectionWrapper(connection); - - using SqlCommand command = new("SELECT 5;", connection); - - DataTestUtility.AssertEqualsWithDescription(5, command.ExecuteScalar(), "Incorrect scalar result."); - - wrapper.KillConnection(); - } - - using (SqlConnection connection2 = new(connectionString)) - { - connection2.Open(); - Assert.False(wrapper.IsInternalConnectionOf(connection2), "New connection has internal connection that was just killed"); - using SqlCommand command = new("SELECT 5;", connection2); - - DataTestUtility.AssertEqualsWithDescription(5, command.ExecuteScalar(), "Incorrect scalar result."); - } - } - - /// - /// Tests that cleanup removes connections that are unused for two cleanups - /// - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsUsingManagedSNI))] - [ClassData(typeof(ConnectionPoolConnectionStringProvider))] - public static void CleanupTest(string connectionString) - { - SqlConnection.ClearAllPools(); - - using SqlConnection conn1 = new(connectionString); - using SqlConnection conn2 = new(connectionString); - conn1.Open(); - conn2.Open(); - ConnectionPoolWrapper connectionPool = new(conn1); - Assert.Equal(2, connectionPool.ConnectionCount); - - connectionPool.Cleanup(); - Assert.Equal(2, connectionPool.ConnectionCount); - - conn1.Close(); - connectionPool.Cleanup(); - Assert.Equal(2, connectionPool.ConnectionCount); - - conn2.Close(); - connectionPool.Cleanup(); - Assert.Equal(1, connectionPool.ConnectionCount); - - connectionPool.Cleanup(); - Assert.Equal(0, connectionPool.ConnectionCount); - - using SqlConnection conn3 = new(connectionString); - conn3.Open(); - InternalConnectionWrapper internalConnection3 = new(conn3); - - conn3.Close(); - internalConnection3.KillConnection(); - Assert.Equal(1, connectionPool.ConnectionCount); - Assert.False(internalConnection3.IsConnectionAlive(), "Connection should not be alive"); - - connectionPool.Cleanup(); - Assert.Equal(1, connectionPool.ConnectionCount); - } - - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsUsingManagedSNI))] - [ClassData(typeof(ConnectionPoolConnectionStringProvider))] - public static void ReplacementConnectionObeys0TimeoutTest(string connectionString) - { - string newConnectionString = (new SqlConnectionStringBuilder(connectionString) { ConnectTimeout = 0 }).ConnectionString; - SqlConnection.ClearAllPools(); - - // Kick off proxy - using (ProxyServer proxy = ProxyServer.CreateAndStartProxy(newConnectionString, out newConnectionString)) - { - // Create one dead connection - using SqlConnection deadConnection = new(newConnectionString); - deadConnection.Open(); - InternalConnectionWrapper deadConnectionInternal = new(deadConnection); - deadConnectionInternal.KillConnection(); - - // Block one live connection - proxy.PauseCopying(); - Task blockedConnectionTask = Task.Run(() => ReplacementConnectionObeys0TimeoutTask(newConnectionString)); - Thread.Sleep(100); - Assert.Equal(TaskStatus.Running, blockedConnectionTask.Status); - - // Close and re-open the dead connection - deadConnection.Close(); - Task newConnectionTask = Task.Run(() => ReplacementConnectionObeys0TimeoutTask(newConnectionString)); - Thread.Sleep(100); - Assert.Equal(TaskStatus.Running, blockedConnectionTask.Status); - Assert.Equal(TaskStatus.Running, newConnectionTask.Status); - - // restart the proxy - proxy.ResumeCopying(); - - Task.WaitAll(blockedConnectionTask, newConnectionTask); - blockedConnectionTask.Result.Close(); - newConnectionTask.Result.Close(); - } - } - } -} +//using System; +//using System.Runtime.ExceptionServices; +//using System.Threading; +//using System.Threading.Tasks; +//using Xunit; +//using static Microsoft.Data.SqlClient.ManualTesting.Tests.ConnectionPoolTest; + +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ +// public static class ConnectionPoolTestDebug +// { +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsUsingManagedSNI))] +// [ClassData(typeof(ConnectionPoolConnectionStringProvider))] +// public static void ReplacementConnectionUsesSemaphoreTest(string connectionString) +// { +// string newConnectionString = (new SqlConnectionStringBuilder(connectionString) { MaxPoolSize = 2, ConnectTimeout = 5 }).ConnectionString; +// SqlConnection.ClearAllPools(); + +// using SqlConnection liveConnection = new(newConnectionString); +// using SqlConnection deadConnection = new(newConnectionString); +// liveConnection.Open(); +// deadConnection.Open(); +// InternalConnectionWrapper deadConnectionInternal = new(deadConnection); +// InternalConnectionWrapper liveConnectionInternal = new(liveConnection); +// deadConnectionInternal.KillConnection(); +// deadConnection.Close(); +// liveConnection.Close(); + +// Task[] tasks = new Task[3]; +// Barrier syncBarrier = new(tasks.Length); +// Func taskFunction = (() => ReplacementConnectionUsesSemaphoreTask(newConnectionString, syncBarrier)); +// for (int i = 0; i < tasks.Length; i++) +// { +// tasks[i] = Task.Factory.StartNew(taskFunction); +// } + +// bool taskWithLiveConnection = false; +// bool taskWithNewConnection = false; +// bool taskWithCorrectException = false; + +// Task waitAllTask = Task.Factory.ContinueWhenAll(tasks, (completedTasks) => +// { +// foreach (var item in completedTasks) +// { +// if (item.Status == TaskStatus.Faulted) +// { +// // One task should have a timeout exception +// if ((!taskWithCorrectException) && (item.Exception.InnerException is InvalidOperationException) && (item.Exception.InnerException.Message.StartsWith(SystemDataResourceManager.Instance.ADP_PooledOpenTimeout))) +// taskWithCorrectException = true; +// else if (!taskWithCorrectException) +// { +// // Rethrow the unknown exception +// ExceptionDispatchInfo exceptionInfo = ExceptionDispatchInfo.Capture(item.Exception); +// exceptionInfo.Throw(); +// } +// } +// else if (item.Status == TaskStatus.RanToCompletion) +// { +// // One task should get the live connection +// if (item.Result.Equals(liveConnectionInternal)) +// { +// if (!taskWithLiveConnection) +// taskWithLiveConnection = true; +// } +// else if (!item.Result.Equals(deadConnectionInternal) && !taskWithNewConnection) +// taskWithNewConnection = true; +// } +// else +// Console.WriteLine("ERROR: Task in unknown state: {0}", item.Status); +// } +// }); + +// waitAllTask.Wait(); +// Assert.True(taskWithLiveConnection && taskWithNewConnection && taskWithCorrectException, +// $"Tasks didn't finish as expected.\n" + +// $"Task with live connection: {taskWithLiveConnection}\n" + +// $"Task with new connection: {taskWithNewConnection}\n" + +// $"Task with correct exception: {taskWithCorrectException}\n"); +// } + +// /// +// /// Tests if killing the connection using the InternalConnectionWrapper is working +// /// +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsUsingManagedSNI))] +// [ClassData(typeof(ConnectionPoolConnectionStringProvider))] +// public static void KillConnectionTest(string connectionString) +// { +// InternalConnectionWrapper wrapper = null; + +// using (SqlConnection connection = new(connectionString)) +// { +// connection.Open(); +// wrapper = new InternalConnectionWrapper(connection); + +// using SqlCommand command = new("SELECT 5;", connection); + +// DataTestUtility.AssertEqualsWithDescription(5, command.ExecuteScalar(), "Incorrect scalar result."); + +// wrapper.KillConnection(); +// } + +// using (SqlConnection connection2 = new(connectionString)) +// { +// connection2.Open(); +// Assert.False(wrapper.IsInternalConnectionOf(connection2), "New connection has internal connection that was just killed"); +// using SqlCommand command = new("SELECT 5;", connection2); + +// DataTestUtility.AssertEqualsWithDescription(5, command.ExecuteScalar(), "Incorrect scalar result."); +// } +// } + +// /// +// /// Tests that cleanup removes connections that are unused for two cleanups +// /// +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsUsingManagedSNI))] +// [ClassData(typeof(ConnectionPoolConnectionStringProvider))] +// public static void CleanupTest(string connectionString) +// { +// SqlConnection.ClearAllPools(); + +// using SqlConnection conn1 = new(connectionString); +// using SqlConnection conn2 = new(connectionString); +// conn1.Open(); +// conn2.Open(); +// ConnectionPoolWrapper connectionPool = new(conn1); +// Assert.Equal(2, connectionPool.ConnectionCount); + +// connectionPool.Cleanup(); +// Assert.Equal(2, connectionPool.ConnectionCount); + +// conn1.Close(); +// connectionPool.Cleanup(); +// Assert.Equal(2, connectionPool.ConnectionCount); + +// conn2.Close(); +// connectionPool.Cleanup(); +// Assert.Equal(1, connectionPool.ConnectionCount); + +// connectionPool.Cleanup(); +// Assert.Equal(0, connectionPool.ConnectionCount); + +// using SqlConnection conn3 = new(connectionString); +// conn3.Open(); +// InternalConnectionWrapper internalConnection3 = new(conn3); + +// conn3.Close(); +// internalConnection3.KillConnection(); +// Assert.Equal(1, connectionPool.ConnectionCount); +// Assert.False(internalConnection3.IsConnectionAlive(), "Connection should not be alive"); + +// connectionPool.Cleanup(); +// Assert.Equal(1, connectionPool.ConnectionCount); +// } + +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsUsingManagedSNI))] +// [ClassData(typeof(ConnectionPoolConnectionStringProvider))] +// public static void ReplacementConnectionObeys0TimeoutTest(string connectionString) +// { +// string newConnectionString = (new SqlConnectionStringBuilder(connectionString) { ConnectTimeout = 0 }).ConnectionString; +// SqlConnection.ClearAllPools(); + +// // Kick off proxy +// using (ProxyServer proxy = ProxyServer.CreateAndStartProxy(newConnectionString, out newConnectionString)) +// { +// // Create one dead connection +// using SqlConnection deadConnection = new(newConnectionString); +// deadConnection.Open(); +// InternalConnectionWrapper deadConnectionInternal = new(deadConnection); +// deadConnectionInternal.KillConnection(); + +// // Block one live connection +// proxy.PauseCopying(); +// Task blockedConnectionTask = Task.Run(() => ReplacementConnectionObeys0TimeoutTask(newConnectionString)); +// Thread.Sleep(100); +// Assert.Equal(TaskStatus.Running, blockedConnectionTask.Status); + +// // Close and re-open the dead connection +// deadConnection.Close(); +// Task newConnectionTask = Task.Run(() => ReplacementConnectionObeys0TimeoutTask(newConnectionString)); +// Thread.Sleep(100); +// Assert.Equal(TaskStatus.Running, blockedConnectionTask.Status); +// Assert.Equal(TaskStatus.Running, newConnectionTask.Status); + +// // restart the proxy +// proxy.ResumeCopying(); + +// Task.WaitAll(blockedConnectionTask, newConnectionTask); +// blockedConnectionTask.Result.Close(); +// newConnectionTask.Result.Close(); +// } +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectionPoolTest/ConnectionPoolTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectionPoolTest/ConnectionPoolTest.cs index cfe74831f7..44ed491bae 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectionPoolTest/ConnectionPoolTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectionPoolTest/ConnectionPoolTest.cs @@ -1,247 +1,247 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ - public class ConnectionPoolConnectionStringProvider : IEnumerable - { - private static readonly string _TCPConnectionString = (new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { MultipleActiveResultSets = false, Pooling = true }).ConnectionString; - private static readonly string _tcpMarsConnStr = (new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { MultipleActiveResultSets = true, Pooling = true }).ConnectionString; - - public IEnumerator GetEnumerator() - { - yield return new object[] { _TCPConnectionString }; - if (DataTestUtility.IsNotAzureSynapse()) - { - yield return new object[] { _tcpMarsConnStr }; - } - } - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } - - // TODO Synapse: Fix these tests for Azure Synapse. - public static class ConnectionPoolTest - { - /// - /// Tests that using the same connection string results in the same pool\internal connection and a different string results in a different pool\internal connection - /// - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - [ClassData(typeof(ConnectionPoolConnectionStringProvider))] - public static void BasicConnectionPoolingTest(string connectionString) - { - SqlConnection.ClearAllPools(); - - InternalConnectionWrapper internalConnection; - ConnectionPoolWrapper connectionPool; - using (SqlConnection connection = new SqlConnection(connectionString)) - { - connection.Open(); - internalConnection = new InternalConnectionWrapper(connection); - connectionPool = new ConnectionPoolWrapper(connection); - } - - using (SqlConnection connection2 = new SqlConnection(connectionString)) - { - connection2.Open(); - Assert.True(internalConnection.IsInternalConnectionOf(connection2), "New connection does not use same internal connection"); - Assert.True(connectionPool.ContainsConnection(connection2), "New connection is in a different pool"); - } - - using (SqlConnection connection3 = new SqlConnection(connectionString + ";App=SqlConnectionPoolUnitTest;")) - { - connection3.Open(); - Assert.False(internalConnection.IsInternalConnectionOf(connection3), "Connection with different connection string uses same internal connection"); - Assert.False(connectionPool.ContainsConnection(connection3), "Connection with different connection string uses same connection pool"); - } - - connectionPool.Cleanup(); - - using (SqlConnection connection4 = new SqlConnection(connectionString)) - { - connection4.Open(); - Assert.True(internalConnection.IsInternalConnectionOf(connection4), "New connection does not use same internal connection"); - Assert.True(connectionPool.ContainsConnection(connection4), "New connection is in a different pool"); - } - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAADPasswordConnStrSetup), nameof(DataTestUtility.IsAADAuthorityURLSetup))] - public static void AccessTokenConnectionPoolingTest() - { - SqlConnection.ClearAllPools(); - - // Remove cred info and add invalid token - string[] credKeys = { "User ID", "Password", "UID", "PWD", "Authentication" }; - string connectionString = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys); - - using SqlConnection connection = new SqlConnection(connectionString); - connection.AccessToken = DataTestUtility.GetAccessToken(); - connection.Open(); - InternalConnectionWrapper internalConnection = new InternalConnectionWrapper(connection); - ConnectionPoolWrapper connectionPool = new ConnectionPoolWrapper(connection); - connection.Close(); - - using SqlConnection connection2 = new SqlConnection(connectionString); - connection2.AccessToken = DataTestUtility.GetAccessToken(); - connection2.Open(); - Assert.True(internalConnection.IsInternalConnectionOf(connection2), "New connection does not use same internal connection"); - Assert.True(connectionPool.ContainsConnection(connection2), "New connection is in a different pool"); - connection2.Close(); - - using SqlConnection connection3 = new SqlConnection(connectionString + ";App=SqlConnectionPoolUnitTest;"); - connection3.AccessToken = DataTestUtility.GetAccessToken(); - connection3.Open(); - Assert.False(internalConnection.IsInternalConnectionOf(connection3), "Connection with different connection string uses same internal connection"); - Assert.False(connectionPool.ContainsConnection(connection3), "Connection with different connection string uses same connection pool"); - connection3.Close(); - - connectionPool.Cleanup(); - - using SqlConnection connection4 = new SqlConnection(connectionString); - connection4.AccessToken = DataTestUtility.GetAccessToken(); - connection4.Open(); - Assert.True(internalConnection.IsInternalConnectionOf(connection4), "New connection does not use same internal connection"); - Assert.True(connectionPool.ContainsConnection(connection4), "New connection is in a different pool"); - connection4.Close(); - } - - /// - /// Tests if clearing all of the pools does actually remove the pools - /// - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - [ClassData(typeof(ConnectionPoolConnectionStringProvider))] - public static void ClearAllPoolsTest(string connectionString) - { - SqlConnection.ClearAllPools(); - Assert.True(0 == ConnectionPoolWrapper.AllConnectionPools().Length, "Pools exist after clearing all pools"); - - using (SqlConnection connection = new SqlConnection(connectionString)) - { - connection.Open(); - ConnectionPoolWrapper pool = new ConnectionPoolWrapper(connection); - connection.Close(); - ConnectionPoolWrapper[] allPools = ConnectionPoolWrapper.AllConnectionPools(); - - DataTestUtility.AssertEqualsWithDescription(1, allPools.Length, "Incorrect number of pools exist."); - Assert.True(allPools[0].Equals(pool), "Saved pool is not in the list of all pools"); - DataTestUtility.AssertEqualsWithDescription(1, pool.ConnectionCount, "Saved pool has incorrect number of connections"); - - SqlConnection.ClearAllPools(); - Assert.True(0 == ConnectionPoolWrapper.AllConnectionPools().Length, "Pools exist after clearing all pools"); - DataTestUtility.AssertEqualsWithDescription(0, pool.ConnectionCount, "Saved pool has incorrect number of connections."); - } - } - - /// - /// Checks if an 'emancipated' internal connection is reclaimed when a new connection is opened AND we hit max pool size - /// NOTE: 'emancipated' means that the internal connection's SqlConnection has fallen out of scope and has no references, but was not explicitly disposed\closed - /// - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - [ClassData(typeof(ConnectionPoolConnectionStringProvider))] - public static void ReclaimEmancipatedOnOpenTest(string connectionString) - { - string newConnectionString = (new SqlConnectionStringBuilder(connectionString) { MaxPoolSize = 1 }).ConnectionString; - SqlConnection.ClearAllPools(); - - InternalConnectionWrapper internalConnection = CreateEmancipatedConnection(newConnectionString); - ConnectionPoolWrapper connectionPool = internalConnection.ConnectionPool; - GC.Collect(); - GC.WaitForPendingFinalizers(); - - DataTestUtility.AssertEqualsWithDescription(1, connectionPool.ConnectionCount, "Wrong number of connections in the pool."); - DataTestUtility.AssertEqualsWithDescription(0, connectionPool.FreeConnectionCount, "Wrong number of free connections in the pool."); - - using (SqlConnection connection = new SqlConnection(newConnectionString)) - { - connection.Open(); - Assert.True(internalConnection.IsInternalConnectionOf(connection), "Connection has wrong internal connection"); - Assert.True(connectionPool.ContainsConnection(connection), "Connection is in wrong connection pool"); - } - } - - /// - /// Tests if, when max pool size is reached, Open() will block until a connection becomes available - /// - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - [ClassData(typeof(ConnectionPoolConnectionStringProvider))] - public static void MaxPoolWaitForConnectionTest(string connectionString) - { - string newConnectionString = (new SqlConnectionStringBuilder(connectionString) { MaxPoolSize = 1 }).ConnectionString; - SqlConnection.ClearAllPools(); - - using SqlConnection connection1 = new SqlConnection(newConnectionString); - connection1.Open(); - - InternalConnectionWrapper internalConnection = new InternalConnectionWrapper(connection1); - ConnectionPoolWrapper connectionPool = new ConnectionPoolWrapper(connection1); - ManualResetEventSlim taskAllowedToSpeak = new ManualResetEventSlim(false); - - Task waitTask = Task.Factory.StartNew(() => MaxPoolWaitForConnectionTask(newConnectionString, internalConnection, connectionPool, taskAllowedToSpeak)); - int count = 5; - while (waitTask.Status == TaskStatus.WaitingToRun && count-- > 0) - { - Thread.Sleep(200); - } - Assert.Equal(TaskStatus.Running, waitTask.Status); - - connection1.Close(); - taskAllowedToSpeak.Set(); - waitTask.Wait(); - Assert.Equal(TaskStatus.RanToCompletion, waitTask.Status); - } - - internal static InternalConnectionWrapper ReplacementConnectionUsesSemaphoreTask(string connectionString, Barrier syncBarrier) - { - InternalConnectionWrapper internalConnection = null; - - using (SqlConnection connection = new SqlConnection(connectionString)) - { - try - { - connection.Open(); - internalConnection = new InternalConnectionWrapper(connection); - } - catch - { - syncBarrier.SignalAndWait(); - throw; - } - - syncBarrier.SignalAndWait(); - } - - return internalConnection; - } - - private static InternalConnectionWrapper CreateEmancipatedConnection(string connectionString) - { - SqlConnection connection = new SqlConnection(connectionString); - connection.Open(); - return new InternalConnectionWrapper(connection); - } - - private static void MaxPoolWaitForConnectionTask(string connectionString, InternalConnectionWrapper internalConnection, ConnectionPoolWrapper connectionPool, ManualResetEventSlim waitToSpeak) - { - using SqlConnection connection = new SqlConnection(connectionString); - connection.Open(); - waitToSpeak.Wait(); - Assert.True(internalConnection.IsInternalConnectionOf(connection), "Connection has wrong internal connection"); - Assert.True(connectionPool.ContainsConnection(connection), "Connection is in wrong connection pool"); - } - - internal static SqlConnection ReplacementConnectionObeys0TimeoutTask(string connectionString) - { - SqlConnection connection = new SqlConnection(connectionString); - connection.Open(); - return connection; - } - } -} +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. + +//using System; +//using System.Collections; +//using System.Collections.Generic; +//using System.Threading; +//using System.Threading.Tasks; +//using Xunit; + +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ +// public class ConnectionPoolConnectionStringProvider : IEnumerable +// { +// private static readonly string _TCPConnectionString = (new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { MultipleActiveResultSets = false, Pooling = true }).ConnectionString; +// private static readonly string _tcpMarsConnStr = (new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { MultipleActiveResultSets = true, Pooling = true }).ConnectionString; + +// public IEnumerator GetEnumerator() +// { +// yield return new object[] { _TCPConnectionString }; +// if (DataTestUtility.IsNotAzureSynapse()) +// { +// yield return new object[] { _tcpMarsConnStr }; +// } +// } + +// IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); +// } + +// // TODO Synapse: Fix these tests for Azure Synapse. +// public static class ConnectionPoolTest +// { +// /// +// /// Tests that using the same connection string results in the same pool\internal connection and a different string results in a different pool\internal connection +// /// +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// [ClassData(typeof(ConnectionPoolConnectionStringProvider))] +// public static void BasicConnectionPoolingTest(string connectionString) +// { +// SqlConnection.ClearAllPools(); + +// InternalConnectionWrapper internalConnection; +// ConnectionPoolWrapper connectionPool; +// using (SqlConnection connection = new SqlConnection(connectionString)) +// { +// connection.Open(); +// internalConnection = new InternalConnectionWrapper(connection); +// connectionPool = new ConnectionPoolWrapper(connection); +// } + +// using (SqlConnection connection2 = new SqlConnection(connectionString)) +// { +// connection2.Open(); +// Assert.True(internalConnection.IsInternalConnectionOf(connection2), "New connection does not use same internal connection"); +// Assert.True(connectionPool.ContainsConnection(connection2), "New connection is in a different pool"); +// } + +// using (SqlConnection connection3 = new SqlConnection(connectionString + ";App=SqlConnectionPoolUnitTest;")) +// { +// connection3.Open(); +// Assert.False(internalConnection.IsInternalConnectionOf(connection3), "Connection with different connection string uses same internal connection"); +// Assert.False(connectionPool.ContainsConnection(connection3), "Connection with different connection string uses same connection pool"); +// } + +// connectionPool.Cleanup(); + +// using (SqlConnection connection4 = new SqlConnection(connectionString)) +// { +// connection4.Open(); +// Assert.True(internalConnection.IsInternalConnectionOf(connection4), "New connection does not use same internal connection"); +// Assert.True(connectionPool.ContainsConnection(connection4), "New connection is in a different pool"); +// } +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAADPasswordConnStrSetup), nameof(DataTestUtility.IsAADAuthorityURLSetup))] +// public static void AccessTokenConnectionPoolingTest() +// { +// SqlConnection.ClearAllPools(); + +// // Remove cred info and add invalid token +// string[] credKeys = { "User ID", "Password", "UID", "PWD", "Authentication" }; +// string connectionString = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys); + +// using SqlConnection connection = new SqlConnection(connectionString); +// connection.AccessToken = DataTestUtility.GetAccessToken(); +// connection.Open(); +// InternalConnectionWrapper internalConnection = new InternalConnectionWrapper(connection); +// ConnectionPoolWrapper connectionPool = new ConnectionPoolWrapper(connection); +// connection.Close(); + +// using SqlConnection connection2 = new SqlConnection(connectionString); +// connection2.AccessToken = DataTestUtility.GetAccessToken(); +// connection2.Open(); +// Assert.True(internalConnection.IsInternalConnectionOf(connection2), "New connection does not use same internal connection"); +// Assert.True(connectionPool.ContainsConnection(connection2), "New connection is in a different pool"); +// connection2.Close(); + +// using SqlConnection connection3 = new SqlConnection(connectionString + ";App=SqlConnectionPoolUnitTest;"); +// connection3.AccessToken = DataTestUtility.GetAccessToken(); +// connection3.Open(); +// Assert.False(internalConnection.IsInternalConnectionOf(connection3), "Connection with different connection string uses same internal connection"); +// Assert.False(connectionPool.ContainsConnection(connection3), "Connection with different connection string uses same connection pool"); +// connection3.Close(); + +// connectionPool.Cleanup(); + +// using SqlConnection connection4 = new SqlConnection(connectionString); +// connection4.AccessToken = DataTestUtility.GetAccessToken(); +// connection4.Open(); +// Assert.True(internalConnection.IsInternalConnectionOf(connection4), "New connection does not use same internal connection"); +// Assert.True(connectionPool.ContainsConnection(connection4), "New connection is in a different pool"); +// connection4.Close(); +// } + +// /// +// /// Tests if clearing all of the pools does actually remove the pools +// /// +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// [ClassData(typeof(ConnectionPoolConnectionStringProvider))] +// public static void ClearAllPoolsTest(string connectionString) +// { +// SqlConnection.ClearAllPools(); +// Assert.True(0 == ConnectionPoolWrapper.AllConnectionPools().Length, "Pools exist after clearing all pools"); + +// using (SqlConnection connection = new SqlConnection(connectionString)) +// { +// connection.Open(); +// ConnectionPoolWrapper pool = new ConnectionPoolWrapper(connection); +// connection.Close(); +// ConnectionPoolWrapper[] allPools = ConnectionPoolWrapper.AllConnectionPools(); + +// DataTestUtility.AssertEqualsWithDescription(1, allPools.Length, "Incorrect number of pools exist."); +// Assert.True(allPools[0].Equals(pool), "Saved pool is not in the list of all pools"); +// DataTestUtility.AssertEqualsWithDescription(1, pool.ConnectionCount, "Saved pool has incorrect number of connections"); + +// SqlConnection.ClearAllPools(); +// Assert.True(0 == ConnectionPoolWrapper.AllConnectionPools().Length, "Pools exist after clearing all pools"); +// DataTestUtility.AssertEqualsWithDescription(0, pool.ConnectionCount, "Saved pool has incorrect number of connections."); +// } +// } + +// /// +// /// Checks if an 'emancipated' internal connection is reclaimed when a new connection is opened AND we hit max pool size +// /// NOTE: 'emancipated' means that the internal connection's SqlConnection has fallen out of scope and has no references, but was not explicitly disposed\closed +// /// +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// [ClassData(typeof(ConnectionPoolConnectionStringProvider))] +// public static void ReclaimEmancipatedOnOpenTest(string connectionString) +// { +// string newConnectionString = (new SqlConnectionStringBuilder(connectionString) { MaxPoolSize = 1 }).ConnectionString; +// SqlConnection.ClearAllPools(); + +// InternalConnectionWrapper internalConnection = CreateEmancipatedConnection(newConnectionString); +// ConnectionPoolWrapper connectionPool = internalConnection.ConnectionPool; +// GC.Collect(); +// GC.WaitForPendingFinalizers(); + +// DataTestUtility.AssertEqualsWithDescription(1, connectionPool.ConnectionCount, "Wrong number of connections in the pool."); +// DataTestUtility.AssertEqualsWithDescription(0, connectionPool.FreeConnectionCount, "Wrong number of free connections in the pool."); + +// using (SqlConnection connection = new SqlConnection(newConnectionString)) +// { +// connection.Open(); +// Assert.True(internalConnection.IsInternalConnectionOf(connection), "Connection has wrong internal connection"); +// Assert.True(connectionPool.ContainsConnection(connection), "Connection is in wrong connection pool"); +// } +// } + +// /// +// /// Tests if, when max pool size is reached, Open() will block until a connection becomes available +// /// +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// [ClassData(typeof(ConnectionPoolConnectionStringProvider))] +// public static void MaxPoolWaitForConnectionTest(string connectionString) +// { +// string newConnectionString = (new SqlConnectionStringBuilder(connectionString) { MaxPoolSize = 1 }).ConnectionString; +// SqlConnection.ClearAllPools(); + +// using SqlConnection connection1 = new SqlConnection(newConnectionString); +// connection1.Open(); + +// InternalConnectionWrapper internalConnection = new InternalConnectionWrapper(connection1); +// ConnectionPoolWrapper connectionPool = new ConnectionPoolWrapper(connection1); +// ManualResetEventSlim taskAllowedToSpeak = new ManualResetEventSlim(false); + +// Task waitTask = Task.Factory.StartNew(() => MaxPoolWaitForConnectionTask(newConnectionString, internalConnection, connectionPool, taskAllowedToSpeak)); +// int count = 5; +// while (waitTask.Status == TaskStatus.WaitingToRun && count-- > 0) +// { +// Thread.Sleep(200); +// } +// Assert.Equal(TaskStatus.Running, waitTask.Status); + +// connection1.Close(); +// taskAllowedToSpeak.Set(); +// waitTask.Wait(); +// Assert.Equal(TaskStatus.RanToCompletion, waitTask.Status); +// } + +// internal static InternalConnectionWrapper ReplacementConnectionUsesSemaphoreTask(string connectionString, Barrier syncBarrier) +// { +// InternalConnectionWrapper internalConnection = null; + +// using (SqlConnection connection = new SqlConnection(connectionString)) +// { +// try +// { +// connection.Open(); +// internalConnection = new InternalConnectionWrapper(connection); +// } +// catch +// { +// syncBarrier.SignalAndWait(); +// throw; +// } + +// syncBarrier.SignalAndWait(); +// } + +// return internalConnection; +// } + +// private static InternalConnectionWrapper CreateEmancipatedConnection(string connectionString) +// { +// SqlConnection connection = new SqlConnection(connectionString); +// connection.Open(); +// return new InternalConnectionWrapper(connection); +// } + +// private static void MaxPoolWaitForConnectionTask(string connectionString, InternalConnectionWrapper internalConnection, ConnectionPoolWrapper connectionPool, ManualResetEventSlim waitToSpeak) +// { +// using SqlConnection connection = new SqlConnection(connectionString); +// connection.Open(); +// waitToSpeak.Wait(); +// Assert.True(internalConnection.IsInternalConnectionOf(connection), "Connection has wrong internal connection"); +// Assert.True(connectionPool.ContainsConnection(connection), "Connection is in wrong connection pool"); +// } + +// internal static SqlConnection ReplacementConnectionObeys0TimeoutTask(string connectionString) +// { +// SqlConnection connection = new SqlConnection(connectionString); +// connection.Open(); +// return connection; +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectionPoolTest/PoolBlockPeriodTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectionPoolTest/PoolBlockPeriodTest.cs index 7124d33766..241a9fd40f 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectionPoolTest/PoolBlockPeriodTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectionPoolTest/PoolBlockPeriodTest.cs @@ -1,169 +1,169 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. -using System; -using Xunit; +//using System; +//using Xunit; -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ - public class PoolBlockPeriodTest - { - private const string AzureEndpointSample = "nonexistent.database.windows.net"; - private const string AzureChinaEnpointSample = "nonexistent.database.chinacloudapi.cn"; - private const string AzureUSGovernmentEndpointSample = "nonexistent.database.usgovcloudapi.net"; - private const string AzureGermanEndpointSample = "nonexistent.database.cloudapi.de"; - private const string AzureEndpointMixedCaseSample = "nonexistent.database.WINDOWS.net"; - private const string NonExistentServer = "nonexistentserver"; - private const string PolicyKeyword = "PoolBlockingPeriod"; - private const string PortNumber = "1234"; - private const string InstanceName = "InstanceName"; - private const int ConnectionTimeout = 15; - private const int CompareMargin = 2; - private static bool AreConnectionStringsSetup() => DataTestUtility.AreConnStringsSetup(); +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ +// public class PoolBlockPeriodTest +// { +// private const string AzureEndpointSample = "nonexistent.database.windows.net"; +// private const string AzureChinaEnpointSample = "nonexistent.database.chinacloudapi.cn"; +// private const string AzureUSGovernmentEndpointSample = "nonexistent.database.usgovcloudapi.net"; +// private const string AzureGermanEndpointSample = "nonexistent.database.cloudapi.de"; +// private const string AzureEndpointMixedCaseSample = "nonexistent.database.WINDOWS.net"; +// private const string NonExistentServer = "nonexistentserver"; +// private const string PolicyKeyword = "PoolBlockingPeriod"; +// private const string PortNumber = "1234"; +// private const string InstanceName = "InstanceName"; +// private const int ConnectionTimeout = 15; +// private const int CompareMargin = 2; +// private static bool AreConnectionStringsSetup() => DataTestUtility.AreConnStringsSetup(); - [OuterLoop()] - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - [InlineData("Azure with Default Policy must Disable blocking (*.database.windows.net)", new object[] { AzureEndpointSample })] - [InlineData("Azure with Default Policy must Disable blocking (*.database.chinacloudapi.cn)", new object[] { AzureChinaEnpointSample })] - [InlineData("Azure with Default Policy must Disable blocking (*.database.usgovcloudapi.net)", new object[] { AzureUSGovernmentEndpointSample })] - [InlineData("Azure with Default Policy must Disable blocking (*.database.cloudapi.de)", new object[] { AzureGermanEndpointSample })] - [InlineData("Azure with Default Policy must Disable blocking (MIXED CASES) (*.database.WINDOWS.net)", new object[] { AzureEndpointMixedCaseSample })] - [InlineData("Azure with Default Policy must Disable blocking (PORT) (*.database.WINDOWS.net,1234)", new object[] { AzureEndpointMixedCaseSample + "," + PortNumber })] - [InlineData("Azure with Default Policy must Disable blocking (INSTANCE NAME) (*.database.WINDOWS.net,1234\\InstanceName)", new object[] { AzureEndpointMixedCaseSample + "," + PortNumber + "\\" + InstanceName })] - [InlineData("Azure with Auto Policy must Disable Blocking", new object[] { AzureEndpointSample, PoolBlockingPeriod.Auto })] - [InlineData("Azure with Always Policy must Enable Blocking", new object[] { AzureEndpointSample, PoolBlockingPeriod.AlwaysBlock })] - [InlineData("Azure with Never Policy must Disable Blocking", new object[] { AzureEndpointSample, PoolBlockingPeriod.NeverBlock })] - public void TestAzureBlockingPeriod(string description, object[] Params) - { - string _ = description; // Using C# Discards as workaround to the XUnit warning. - string serverName = Params[0] as string; - PoolBlockingPeriod? policy = null; - if (Params.Length > 1) - { - policy = (PoolBlockingPeriod)Params[1]; - } +// [OuterLoop()] +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// [InlineData("Azure with Default Policy must Disable blocking (*.database.windows.net)", new object[] { AzureEndpointSample })] +// [InlineData("Azure with Default Policy must Disable blocking (*.database.chinacloudapi.cn)", new object[] { AzureChinaEnpointSample })] +// [InlineData("Azure with Default Policy must Disable blocking (*.database.usgovcloudapi.net)", new object[] { AzureUSGovernmentEndpointSample })] +// [InlineData("Azure with Default Policy must Disable blocking (*.database.cloudapi.de)", new object[] { AzureGermanEndpointSample })] +// [InlineData("Azure with Default Policy must Disable blocking (MIXED CASES) (*.database.WINDOWS.net)", new object[] { AzureEndpointMixedCaseSample })] +// [InlineData("Azure with Default Policy must Disable blocking (PORT) (*.database.WINDOWS.net,1234)", new object[] { AzureEndpointMixedCaseSample + "," + PortNumber })] +// [InlineData("Azure with Default Policy must Disable blocking (INSTANCE NAME) (*.database.WINDOWS.net,1234\\InstanceName)", new object[] { AzureEndpointMixedCaseSample + "," + PortNumber + "\\" + InstanceName })] +// [InlineData("Azure with Auto Policy must Disable Blocking", new object[] { AzureEndpointSample, PoolBlockingPeriod.Auto })] +// [InlineData("Azure with Always Policy must Enable Blocking", new object[] { AzureEndpointSample, PoolBlockingPeriod.AlwaysBlock })] +// [InlineData("Azure with Never Policy must Disable Blocking", new object[] { AzureEndpointSample, PoolBlockingPeriod.NeverBlock })] +// public void TestAzureBlockingPeriod(string description, object[] Params) +// { +// string _ = description; // Using C# Discards as workaround to the XUnit warning. +// string serverName = Params[0] as string; +// PoolBlockingPeriod? policy = null; +// if (Params.Length > 1) +// { +// policy = (PoolBlockingPeriod)Params[1]; +// } - string connString = CreateConnectionString(serverName, policy); - PoolBlockingPeriodAzureTest(connString, policy); - } +// string connString = CreateConnectionString(serverName, policy); +// PoolBlockingPeriodAzureTest(connString, policy); +// } - [OuterLoop()] - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - [InlineData("NonAzure with Default Policy must Enable blocking", new object[] { NonExistentServer })] - [InlineData("NonAzure with Auto Policy must Enable Blocking", new object[] { NonExistentServer, PoolBlockingPeriod.Auto })] - [InlineData("NonAzure with Always Policy must Enable Blocking", new object[] { NonExistentServer, PoolBlockingPeriod.AlwaysBlock })] - [InlineData("NonAzure with Never Policy must Disable Blocking", new object[] { NonExistentServer, PoolBlockingPeriod.NeverBlock })] - [InlineData("NonAzure (which contains azure endpoint - nonexistent.WINDOWS.net) with Default Policy must Enable Blocking", new object[] { "nonexistent.windows.net" })] - [InlineData("NonAzure (which contains azure endpoint - nonexistent.database.windows.net.else) with Default Policy must Enable Blocking", new object[] { "nonexistent.database.windows.net.else" })] - public void TestNonAzureBlockingPeriod(string description, object[] Params) - { - string _ = description; // Using C# Discards as workaround to the XUnit warning. - string serverName = Params[0] as string; - PoolBlockingPeriod? policy = null; +// [OuterLoop()] +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// [InlineData("NonAzure with Default Policy must Enable blocking", new object[] { NonExistentServer })] +// [InlineData("NonAzure with Auto Policy must Enable Blocking", new object[] { NonExistentServer, PoolBlockingPeriod.Auto })] +// [InlineData("NonAzure with Always Policy must Enable Blocking", new object[] { NonExistentServer, PoolBlockingPeriod.AlwaysBlock })] +// [InlineData("NonAzure with Never Policy must Disable Blocking", new object[] { NonExistentServer, PoolBlockingPeriod.NeverBlock })] +// [InlineData("NonAzure (which contains azure endpoint - nonexistent.WINDOWS.net) with Default Policy must Enable Blocking", new object[] { "nonexistent.windows.net" })] +// [InlineData("NonAzure (which contains azure endpoint - nonexistent.database.windows.net.else) with Default Policy must Enable Blocking", new object[] { "nonexistent.database.windows.net.else" })] +// public void TestNonAzureBlockingPeriod(string description, object[] Params) +// { +// string _ = description; // Using C# Discards as workaround to the XUnit warning. +// string serverName = Params[0] as string; +// PoolBlockingPeriod? policy = null; - if (Params.Length > 1) - { - policy = (PoolBlockingPeriod)Params[1]; - } +// if (Params.Length > 1) +// { +// policy = (PoolBlockingPeriod)Params[1]; +// } - string connString = CreateConnectionString(serverName, policy); - PoolBlockingPeriodNonAzureTest(connString, policy); - } +// string connString = CreateConnectionString(serverName, policy); +// PoolBlockingPeriodNonAzureTest(connString, policy); +// } - [OuterLoop()] - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - [InlineData("Test policy with Auto (lowercase)", "auto")] - [InlineData("Test policy with Auto (PascalCase)", "Auto")] - [InlineData("Test policy with Always (lowercase)", "alwaysblock")] - [InlineData("Test policy with Always (PascalCase)", "AlwaysBlock")] - [InlineData("Test policy with Never (lowercase)", "neverblock")] - [InlineData("Test policy with Never (PascalCase)", "NeverBlock")] - public void TestSetPolicyWithVariations(string description, string policyString) - { - string _ = description; // Using C# Discards as workaround to the XUnit warning. - PoolBlockingPeriod? policy = null; - if (policyString.ToLower().Contains("auto")) - { - policy = PoolBlockingPeriod.Auto; - } - else if (policyString.ToLower().Contains("always")) - { - policy = PoolBlockingPeriod.AlwaysBlock; - } - else - { - policy = PoolBlockingPeriod.NeverBlock; - } - string connString = $"{CreateConnectionString(AzureEndpointSample, null)};{PolicyKeyword}={policyString}"; - PoolBlockingPeriodAzureTest(connString, policy); - } +// [OuterLoop()] +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// [InlineData("Test policy with Auto (lowercase)", "auto")] +// [InlineData("Test policy with Auto (PascalCase)", "Auto")] +// [InlineData("Test policy with Always (lowercase)", "alwaysblock")] +// [InlineData("Test policy with Always (PascalCase)", "AlwaysBlock")] +// [InlineData("Test policy with Never (lowercase)", "neverblock")] +// [InlineData("Test policy with Never (PascalCase)", "NeverBlock")] +// public void TestSetPolicyWithVariations(string description, string policyString) +// { +// string _ = description; // Using C# Discards as workaround to the XUnit warning. +// PoolBlockingPeriod? policy = null; +// if (policyString.ToLower().Contains("auto")) +// { +// policy = PoolBlockingPeriod.Auto; +// } +// else if (policyString.ToLower().Contains("always")) +// { +// policy = PoolBlockingPeriod.AlwaysBlock; +// } +// else +// { +// policy = PoolBlockingPeriod.NeverBlock; +// } +// string connString = $"{CreateConnectionString(AzureEndpointSample, null)};{PolicyKeyword}={policyString}"; +// PoolBlockingPeriodAzureTest(connString, policy); +// } - private void PoolBlockingPeriodNonAzureTest(string connStr, PoolBlockingPeriod? policy) - { - int firstErrorTimeInSecs = GetConnectionOpenTimeInSeconds(connStr); - int secondErrorTimeInSecs = GetConnectionOpenTimeInSeconds(connStr); - switch (policy) - { - case PoolBlockingPeriod.Auto: - case PoolBlockingPeriod.AlwaysBlock: - Assert.InRange(secondErrorTimeInSecs, 0, firstErrorTimeInSecs + CompareMargin); - break; - case PoolBlockingPeriod.NeverBlock: - Assert.InRange(secondErrorTimeInSecs, 1, 2 * ConnectionTimeout); - break; - } - } +// private void PoolBlockingPeriodNonAzureTest(string connStr, PoolBlockingPeriod? policy) +// { +// int firstErrorTimeInSecs = GetConnectionOpenTimeInSeconds(connStr); +// int secondErrorTimeInSecs = GetConnectionOpenTimeInSeconds(connStr); +// switch (policy) +// { +// case PoolBlockingPeriod.Auto: +// case PoolBlockingPeriod.AlwaysBlock: +// Assert.InRange(secondErrorTimeInSecs, 0, firstErrorTimeInSecs + CompareMargin); +// break; +// case PoolBlockingPeriod.NeverBlock: +// Assert.InRange(secondErrorTimeInSecs, 1, 2 * ConnectionTimeout); +// break; +// } +// } - private void PoolBlockingPeriodAzureTest(string connStr, PoolBlockingPeriod? policy) - { - int firstErrorTimeInSecs = GetConnectionOpenTimeInSeconds(connStr); - int secondErrorTimeInSecs = GetConnectionOpenTimeInSeconds(connStr); - switch (policy) - { - case PoolBlockingPeriod.AlwaysBlock: - Assert.InRange(secondErrorTimeInSecs, 0, firstErrorTimeInSecs + CompareMargin); - break; - case PoolBlockingPeriod.Auto: - case PoolBlockingPeriod.NeverBlock: - Assert.InRange(secondErrorTimeInSecs, 1, 2 * ConnectionTimeout); - break; - } - } +// private void PoolBlockingPeriodAzureTest(string connStr, PoolBlockingPeriod? policy) +// { +// int firstErrorTimeInSecs = GetConnectionOpenTimeInSeconds(connStr); +// int secondErrorTimeInSecs = GetConnectionOpenTimeInSeconds(connStr); +// switch (policy) +// { +// case PoolBlockingPeriod.AlwaysBlock: +// Assert.InRange(secondErrorTimeInSecs, 0, firstErrorTimeInSecs + CompareMargin); +// break; +// case PoolBlockingPeriod.Auto: +// case PoolBlockingPeriod.NeverBlock: +// Assert.InRange(secondErrorTimeInSecs, 1, 2 * ConnectionTimeout); +// break; +// } +// } - private int GetConnectionOpenTimeInSeconds(string connString) - { - using (SqlConnection conn = new SqlConnection(connString)) - { - System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch(); - try - { - stopwatch.Start(); - conn.Open(); - throw new Exception("Connection Open must expect an exception"); - } - catch (Exception) - { - stopwatch.Stop(); - } - return stopwatch.Elapsed.Seconds; - } - } +// private int GetConnectionOpenTimeInSeconds(string connString) +// { +// using (SqlConnection conn = new SqlConnection(connString)) +// { +// System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch(); +// try +// { +// stopwatch.Start(); +// conn.Open(); +// throw new Exception("Connection Open must expect an exception"); +// } +// catch (Exception) +// { +// stopwatch.Stop(); +// } +// return stopwatch.Elapsed.Seconds; +// } +// } - public string CreateConnectionString(string serverName, PoolBlockingPeriod? policy) - { - SqlConnectionStringBuilder connBuilder = new SqlConnectionStringBuilder(); - connBuilder.DataSource = serverName; - connBuilder.UserID = "user"; - connBuilder.Password = "password"; - connBuilder.InitialCatalog = "test"; - connBuilder.PersistSecurityInfo = true; - connBuilder.ConnectTimeout = 5; - if (policy != null) - { - connBuilder.PoolBlockingPeriod = policy.Value; - } - return connBuilder.ToString(); - } - } -} +// public string CreateConnectionString(string serverName, PoolBlockingPeriod? policy) +// { +// SqlConnectionStringBuilder connBuilder = new SqlConnectionStringBuilder(); +// connBuilder.DataSource = serverName; +// connBuilder.UserID = "user"; +// connBuilder.Password = "password"; +// connBuilder.InitialCatalog = "test"; +// connBuilder.PersistSecurityInfo = true; +// connBuilder.ConnectTimeout = 5; +// if (policy != null) +// { +// connBuilder.PoolBlockingPeriod = policy.Value; +// } +// return connBuilder.ToString(); +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectionPoolTest/TransactionPoolTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectionPoolTest/TransactionPoolTest.cs index d510b03953..99c72ada14 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectionPoolTest/TransactionPoolTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectionPoolTest/TransactionPoolTest.cs @@ -1,101 +1,101 @@ -using System.Transactions; -using Xunit; - -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ - public static class TransactionPoolTest - { - /// - /// Tests if connections in a distributed transaction are put into a transaction pool. Also checks that clearallpools - /// does not clear transaction connections and that the transaction root is put into "stasis" when closed - /// Synapse: only supports local transaction request. - /// - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - [ClassData(typeof(ConnectionPoolConnectionStringProvider))] - public static void BasicTransactionPoolTest(string connectionString) - { - SqlConnection.ClearAllPools(); - ConnectionPoolWrapper connectionPool = null; - - using (TransactionScope transScope = new()) - { - using SqlConnection connection1 = new(connectionString); - using SqlConnection connection2 = new(connectionString); - connection1.Open(); - connection2.Open(); - connectionPool = new ConnectionPoolWrapper(connection1); - - InternalConnectionWrapper internalConnection1 = new(connection1); - InternalConnectionWrapper internalConnection2 = new(connection2); - - Assert.True(internalConnection1.IsEnlistedInTransaction, "First connection not in transaction"); - Assert.True(internalConnection1.IsTransactionRoot, "First connection not transaction root"); - Assert.True(internalConnection2.IsEnlistedInTransaction, "Second connection not in transaction"); - Assert.False(internalConnection2.IsTransactionRoot, "Second connection is transaction root"); - - // Attempt to re-use root connection - connection1.Close(); - using SqlConnection connection3 = new(connectionString); - connection3.Open(); - - Assert.True(connectionPool.ContainsConnection(connection3), "New connection in wrong pool"); - Assert.True(internalConnection1.IsInternalConnectionOf(connection3), "Root connection was not re-used"); - - // Attempt to re-use non-root connection - connection2.Close(); - using SqlConnection connection4 = new(connectionString); - connection4.Open(); - Assert.True(internalConnection2.IsInternalConnectionOf(connection4), "Connection did not re-use expected internal connection"); - Assert.True(connectionPool.ContainsConnection(connection4), "New connection is in the wrong pool"); - connection4.Close(); - - // Use a different connection string - using SqlConnection connection5 = new(connectionString + ";App=SqlConnectionPoolUnitTest;"); - connection5.Open(); - Assert.False(internalConnection2.IsInternalConnectionOf(connection5), "Connection with different connection string re-used internal connection"); - Assert.False(connectionPool.ContainsConnection(connection5), "Connection with different connection string is in same pool"); - connection5.Close(); - - transScope.Complete(); - } - - Assert.Equal(2, connectionPool.ConnectionCount); - } - - /// - /// Checks that connections in the transaction pool are not cleaned out, and the root transaction is put into "stasis" when it ages - /// Synapse: only supports local transaction request. - /// - /// - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - [ClassData(typeof(ConnectionPoolConnectionStringProvider))] - public static void TransactionCleanupTest(string connectionString) - { - SqlConnection.ClearAllPools(); - ConnectionPoolWrapper connectionPool = null; - - using (TransactionScope transScope = new()) - { - using SqlConnection connection1 = new(connectionString); - using SqlConnection connection2 = new(connectionString); - connection1.Open(); - connection2.Open(); - InternalConnectionWrapper internalConnection1 = new(connection1); - connectionPool = new ConnectionPoolWrapper(connection1); - - connectionPool.Cleanup(); - Assert.Equal(2, connectionPool.ConnectionCount); - - connection1.Close(); - connection2.Close(); - connectionPool.Cleanup(); - Assert.Equal(2, connectionPool.ConnectionCount); - - connectionPool.Cleanup(); - Assert.Equal(2, connectionPool.ConnectionCount); - - transScope.Complete(); - } - } - } -} +//using System.Transactions; +//using Xunit; + +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ +// public static class TransactionPoolTest +// { +// /// +// /// Tests if connections in a distributed transaction are put into a transaction pool. Also checks that clearallpools +// /// does not clear transaction connections and that the transaction root is put into "stasis" when closed +// /// Synapse: only supports local transaction request. +// /// +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// [ClassData(typeof(ConnectionPoolConnectionStringProvider))] +// public static void BasicTransactionPoolTest(string connectionString) +// { +// SqlConnection.ClearAllPools(); +// ConnectionPoolWrapper connectionPool = null; + +// using (TransactionScope transScope = new()) +// { +// using SqlConnection connection1 = new(connectionString); +// using SqlConnection connection2 = new(connectionString); +// connection1.Open(); +// connection2.Open(); +// connectionPool = new ConnectionPoolWrapper(connection1); + +// InternalConnectionWrapper internalConnection1 = new(connection1); +// InternalConnectionWrapper internalConnection2 = new(connection2); + +// Assert.True(internalConnection1.IsEnlistedInTransaction, "First connection not in transaction"); +// Assert.True(internalConnection1.IsTransactionRoot, "First connection not transaction root"); +// Assert.True(internalConnection2.IsEnlistedInTransaction, "Second connection not in transaction"); +// Assert.False(internalConnection2.IsTransactionRoot, "Second connection is transaction root"); + +// // Attempt to re-use root connection +// connection1.Close(); +// using SqlConnection connection3 = new(connectionString); +// connection3.Open(); + +// Assert.True(connectionPool.ContainsConnection(connection3), "New connection in wrong pool"); +// Assert.True(internalConnection1.IsInternalConnectionOf(connection3), "Root connection was not re-used"); + +// // Attempt to re-use non-root connection +// connection2.Close(); +// using SqlConnection connection4 = new(connectionString); +// connection4.Open(); +// Assert.True(internalConnection2.IsInternalConnectionOf(connection4), "Connection did not re-use expected internal connection"); +// Assert.True(connectionPool.ContainsConnection(connection4), "New connection is in the wrong pool"); +// connection4.Close(); + +// // Use a different connection string +// using SqlConnection connection5 = new(connectionString + ";App=SqlConnectionPoolUnitTest;"); +// connection5.Open(); +// Assert.False(internalConnection2.IsInternalConnectionOf(connection5), "Connection with different connection string re-used internal connection"); +// Assert.False(connectionPool.ContainsConnection(connection5), "Connection with different connection string is in same pool"); +// connection5.Close(); + +// transScope.Complete(); +// } + +// Assert.Equal(2, connectionPool.ConnectionCount); +// } + +// /// +// /// Checks that connections in the transaction pool are not cleaned out, and the root transaction is put into "stasis" when it ages +// /// Synapse: only supports local transaction request. +// /// +// /// +// [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// [ClassData(typeof(ConnectionPoolConnectionStringProvider))] +// public static void TransactionCleanupTest(string connectionString) +// { +// SqlConnection.ClearAllPools(); +// ConnectionPoolWrapper connectionPool = null; + +// using (TransactionScope transScope = new()) +// { +// using SqlConnection connection1 = new(connectionString); +// using SqlConnection connection2 = new(connectionString); +// connection1.Open(); +// connection2.Open(); +// InternalConnectionWrapper internalConnection1 = new(connection1); +// connectionPool = new ConnectionPoolWrapper(connection1); + +// connectionPool.Cleanup(); +// Assert.Equal(2, connectionPool.ConnectionCount); + +// connection1.Close(); +// connection2.Close(); +// connectionPool.Cleanup(); +// Assert.Equal(2, connectionPool.ConnectionCount); + +// connectionPool.Cleanup(); +// Assert.Equal(2, connectionPool.ConnectionCount); + +// transScope.Complete(); +// } +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs index 70cae84d73..ae752a3cc9 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs @@ -1,720 +1,720 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Diagnostics; -using System.Security; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Identity.Client; -using Xunit; - -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ - public class AADConnectionsTest - { - class CustomSqlAuthenticationProvider : SqlAuthenticationProvider - { - string _appClientId; - - internal CustomSqlAuthenticationProvider(string appClientId) - { - _appClientId = appClientId; - } - - public override async Task AcquireTokenAsync(SqlAuthenticationParameters parameters) - { - string s_defaultScopeSuffix = "/.default"; - string scope = parameters.Resource.EndsWith(s_defaultScopeSuffix) ? parameters.Resource : parameters.Resource + s_defaultScopeSuffix; - - _ = parameters.ServerName; - _ = parameters.DatabaseName; - _ = parameters.ConnectionId; - - var cts = new CancellationTokenSource(); - cts.CancelAfter(parameters.ConnectionTimeout * 1000); - - string[] scopes = new string[] { scope }; - SecureString password = new SecureString(); - - AuthenticationResult result = await PublicClientApplicationBuilder.Create(_appClientId) - .WithAuthority(parameters.Authority) - .Build().AcquireTokenByUsernamePassword(scopes, parameters.UserId, parameters.Password) - .WithCorrelationId(parameters.ConnectionId) - .ExecuteAsync(cancellationToken: cts.Token); - - return new SqlAuthenticationToken(result.AccessToken, result.ExpiresOn); - } - - public override bool IsSupported(SqlAuthenticationMethod authenticationMethod) - { - return authenticationMethod.Equals(SqlAuthenticationMethod.ActiveDirectoryPassword); - } - } - - private static void ConnectAndDisconnect(string connectionString, SqlCredential credential = null) - { - using (SqlConnection conn = new SqlConnection(connectionString)) - { - if (credential != null) - { - conn.Credential = credential; - } - conn.Open(); - - Assert.True(conn.State == System.Data.ConnectionState.Open); - } - } - - private static bool AreConnStringsSetup() => DataTestUtility.AreConnStringsSetup(); - private static bool IsAzure() => !DataTestUtility.IsNotAzureServer(); - private static bool IsAccessTokenSetup() => DataTestUtility.IsAccessTokenSetup(); - private static bool IsAADConnStringsSetup() => DataTestUtility.IsAADPasswordConnStrSetup(); - private static bool IsManagedIdentitySetup() => DataTestUtility.ManagedIdentitySupported; - - [PlatformSpecific(TestPlatforms.Windows)] - [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] - public static void KustoDatabaseTest() - { - // This is a sample Kusto database that can be connected by any AD account. - using SqlConnection connection = new SqlConnection("Data Source=help.kusto.windows.net; Authentication=Active Directory Default;Trust Server Certificate=True;"); - connection.Open(); - Assert.True(connection.State == System.Data.ConnectionState.Open); - } - - [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] - public static void AccessTokenTest() - { - // Remove cred info and add invalid token - string[] credKeys = { "User ID", "Password", "UID", "PWD", "Authentication" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys); - - using (SqlConnection connection = new SqlConnection(connStr)) - { - connection.AccessToken = DataTestUtility.GetAccessToken(); - connection.Open(); - - Assert.True(connection.State == System.Data.ConnectionState.Open); - } - } - - [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] - public static void InvalidAccessTokenTest() - { - // Remove cred info and add invalid token - string[] credKeys = { "User ID", "Password", "UID", "PWD", "Authentication" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys); - - using (SqlConnection connection = new SqlConnection(connStr)) - { - connection.AccessToken = DataTestUtility.GetAccessToken() + "abc"; - SqlException e = Assert.Throws(() => connection.Open()); - - string expectedMessage = "Login failed for user"; - Assert.Contains(expectedMessage, e.Message); - } - } - - [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] - public static void AccessTokenWithAuthType() - { - // Remove cred info and add invalid token - string[] credKeys = { "User ID", "Password", "UID", "PWD" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys); - - using (SqlConnection connection = new SqlConnection(connStr)) - { - InvalidOperationException e = Assert.Throws(() => - connection.AccessToken = DataTestUtility.GetAccessToken()); - - string expectedMessage = "Cannot set the AccessToken property if 'Authentication' has been specified in the connection string."; - Assert.Contains(expectedMessage, e.Message); - } - } - - [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] - public static void AccessTokenWithCred() - { - // Remove cred info and add invalid token - string[] credKeys = { "Authentication" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys); - - using (SqlConnection connection = new SqlConnection(connStr)) - { - InvalidOperationException e = Assert.Throws(() => - connection.AccessToken = DataTestUtility.GetAccessToken()); - - string expectedMessage = "Cannot set the AccessToken property if 'UserID', 'UID', 'Password', or 'PWD' has been specified in connection string."; - Assert.Contains(expectedMessage, e.Message); - } - } - - [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] - public static void AccessTokenTestWithEmptyToken() - { - // Remove cred info and add invalid token - string[] credKeys = { "User ID", "Password", "UID", "PWD", "Authentication" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys); - - using (SqlConnection connection = new SqlConnection(connStr)) - { - connection.AccessToken = ""; - SqlException e = Assert.Throws(() => connection.Open()); - - string expectedMessage = "A connection was successfully established with the server, but then an error occurred during the login process."; - Assert.Contains(expectedMessage, e.Message); - } - } - - [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] - public static void AccessTokenTestWithIntegratedSecurityTrue() - { - // Remove cred info and add invalid token - string[] credKeys = { "User ID", "Password", "UID", "PWD", "Authentication" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + "Integrated Security=True;"; - - using (SqlConnection connection = new SqlConnection(connStr)) - { - InvalidOperationException e = Assert.Throws(() => connection.AccessToken = ""); - - string expectedMessage = "Cannot set the AccessToken property if the 'Integrated Security' connection string keyword has been set to 'true' or 'SSPI'."; - Assert.Contains(expectedMessage, e.Message); - } - } - - [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] - public static void InvalidAuthTypeTest() - { - // Remove cred info and add invalid token - string[] credKeys = { "Authentication" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + "Authentication=Active Directory Pass;"; - - ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStr)); - - string expectedMessage = "Invalid value for key 'authentication'."; - Assert.Contains(expectedMessage, e.Message, StringComparison.OrdinalIgnoreCase); - } - - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void AADPasswordWithIntegratedSecurityTrue() - { - string connStr = DataTestUtility.AADPasswordConnectionString + "Integrated Security=True;"; - - ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStr)); - - string expectedMessage = "Cannot use 'Authentication' with 'Integrated Security'."; - Assert.Contains(expectedMessage, e.Message); - } - - [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] - public static void AADPasswordWithWrongPassword() - { - string[] credKeys = { "Password", "PWD" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + "Password=TestPassword;"; - - Assert.Throws(() => ConnectAndDisconnect(connStr)); - - // We cannot verify error message with certainity as driver may cache token from other tests for current user - // and error message may change accordingly. - } - - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void GetAccessTokenByPasswordTest() - { - // Clear token cache for code coverage. - ActiveDirectoryAuthenticationProvider.ClearUserTokenCache(); - using (SqlConnection connection = new SqlConnection(DataTestUtility.AADPasswordConnectionString)) - { - connection.Open(); - Assert.True(connection.State == System.Data.ConnectionState.Open); - } - } - - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void TestADPasswordAuthentication() - { - // Connect to Azure DB with password and retrieve user name. - using (SqlConnection conn = new SqlConnection(DataTestUtility.AADPasswordConnectionString)) - { - conn.Open(); - using (SqlCommand sqlCommand = new SqlCommand - ( - cmdText: $"SELECT SUSER_SNAME();", - connection: conn, - transaction: null - )) - { - string customerId = (string)sqlCommand.ExecuteScalar(); - string expected = DataTestUtility.RetrieveValueFromConnStr(DataTestUtility.AADPasswordConnectionString, new string[] { "User ID", "UID" }); - Assert.Equal(expected, customerId); - } - } - } - - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void TestCustomProviderAuthentication() - { - SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, new CustomSqlAuthenticationProvider(DataTestUtility.ApplicationClientId)); - // Connect to Azure DB with password and retrieve user name using custom authentication provider - using (SqlConnection conn = new SqlConnection(DataTestUtility.AADPasswordConnectionString)) - { - conn.Open(); - using (SqlCommand sqlCommand = new SqlCommand - ( - cmdText: $"SELECT SUSER_SNAME();", - connection: conn, - transaction: null - )) - { - string customerId = (string)sqlCommand.ExecuteScalar(); - string expected = DataTestUtility.RetrieveValueFromConnStr(DataTestUtility.AADPasswordConnectionString, new string[] { "User ID", "UID" }); - Assert.Equal(expected, customerId); - } - } - // Reset to driver internal provider. - SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, new ActiveDirectoryAuthenticationProvider(DataTestUtility.ApplicationClientId)); - } - - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void ActiveDirectoryPasswordWithNoAuthType() - { - // connection fails with expected error message. - string[] AuthKey = { "Authentication" }; - string connStrWithNoAuthType = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, AuthKey); - Assert.Throws(() => ConnectAndDisconnect(connStrWithNoAuthType)); - } - - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void IntegratedAuthWithCred() - { - // connection fails with expected error message. - string[] AuthKey = { "Authentication" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, AuthKey) + "Authentication=Active Directory Integrated;"; - ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStr)); - - string[] expectedMessage = { "Cannot use 'Authentication=Active Directory Integrated' with 'User ID', 'UID', 'Password' or 'PWD' connection string keywords.", //netfx - "Cannot use 'Authentication=Active Directory Integrated' with 'Password' or 'PWD' connection string keywords." }; //netcore - Assert.Contains(e.Message, expectedMessage); - } - - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void MFAAuthWithPassword() - { - // connection fails with expected error message. - string[] AuthKey = { "Authentication" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, AuthKey) + "Authentication=Active Directory Interactive;"; - ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStr)); - - string expectedMessage = "Cannot use 'Authentication=Active Directory Interactive' with 'Password' or 'PWD' connection string keywords."; - Assert.Contains(expectedMessage, e.Message); - } - - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void EmptyPasswordInConnStrAADPassword() - { - // connection fails with expected error message. - string[] pwdKey = { "Password", "PWD" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, pwdKey) + "Password=;"; - SqlException e = Assert.Throws(() => ConnectAndDisconnect(connStr)); - - string user = DataTestUtility.FetchKeyInConnStr(DataTestUtility.AADPasswordConnectionString, new string[] { "User Id", "UID" }); - string expectedMessage = string.Format("Failed to authenticate the user {0} in Active Directory (Authentication=ActiveDirectoryPassword).", user); - Assert.Contains(expectedMessage, e.Message); - } - - [PlatformSpecific(TestPlatforms.Windows)] - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void EmptyCredInConnStrAADPassword() - { - // connection fails with expected error message. - string[] removeKeys = { "User ID", "Password", "UID", "PWD" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, removeKeys) + "User ID=; Password=;"; - SqlException e = Assert.Throws(() => ConnectAndDisconnect(connStr)); - - string expectedMessage = "Failed to authenticate the user in Active Directory (Authentication=ActiveDirectoryPassword)."; - Assert.Contains(expectedMessage, e.Message); - } - - [PlatformSpecific(TestPlatforms.AnyUnix)] - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void EmptyCredInConnStrAADPasswordAnyUnix() - { - // connection fails with expected error message. - string[] removeKeys = { "User ID", "Password", "UID", "PWD" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, removeKeys) + "User ID=; Password=;"; - SqlException e = Assert.Throws(() => ConnectAndDisconnect(connStr)); - - string expectedMessage = "MSAL cannot determine the username (UPN) of the currently logged in user.For Integrated Windows Authentication and Username/Password flows, please use .WithUsername() before calling ExecuteAsync()."; - Assert.Contains(expectedMessage, e.Message); - } - - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void AADPasswordWithInvalidUser() - { - // connection fails with expected error message. - string[] removeKeys = { "User ID", "UID" }; - string user = "testdotnet@domain.com"; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, removeKeys) + $"User ID={user}"; - SqlException e = Assert.Throws(() => ConnectAndDisconnect(connStr)); - - string expectedMessage = string.Format("Failed to authenticate the user {0} in Active Directory (Authentication=ActiveDirectoryPassword).", user); - Assert.Contains(expectedMessage, e.Message); - } - - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void NoCredentialsActiveDirectoryPassword() - { - // test Passes with correct connection string. - ConnectAndDisconnect(DataTestUtility.AADPasswordConnectionString); - - // connection fails with expected error message. - string[] credKeys = { "User ID", "Password", "UID", "PWD" }; - string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys); - InvalidOperationException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred)); - - string expectedMessage = "Either Credential or both 'User ID' and 'Password' (or 'UID' and 'PWD') connection string keywords must be specified, if 'Authentication=Active Directory Password'."; - Assert.Contains(expectedMessage, e.Message); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAADServicePrincipalSetup))] - public static void NoCredentialsActiveDirectoryServicePrincipal() - { - // test Passes with correct connection string. - string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, removeKeys) + - $"Authentication=Active Directory Service Principal; User ID={DataTestUtility.AADServicePrincipalId}; PWD={DataTestUtility.AADServicePrincipalSecret};"; - ConnectAndDisconnect(connStr); - - // connection fails with expected error message. - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + - "Authentication=Active Directory Service Principal;"; - InvalidOperationException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred)); - - string expectedMessage = "Either Credential or both 'User ID' and 'Password' (or 'UID' and 'PWD') connection string keywords must be specified, if 'Authentication=Active Directory Service Principal'."; - Assert.Contains(expectedMessage, e.Message); - } - - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void ActiveDirectoryDeviceCodeFlowWithUserIdMustFail() - { - // connection fails with expected error message. - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStrWithUID = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + - "Authentication=Active Directory Device Code Flow; UID=someuser;"; - ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithUID)); - - string expectedMessage = "Cannot use 'Authentication=Active Directory Device Code Flow' with 'User ID', 'UID', 'Password' or 'PWD' connection string keywords."; - Assert.Contains(expectedMessage, e.Message); - } - - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void ActiveDirectoryDeviceCodeFlowWithCredentialsMustFail() - { - // connection fails with expected error message. - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + - "Authentication=Active Directory Device Code Flow;"; - - SecureString str = new SecureString(); - foreach (char c in "hello") - { - str.AppendChar(c); - } - str.MakeReadOnly(); - SqlCredential credential = new SqlCredential("someuser", str); - InvalidOperationException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred, credential)); - - string expectedMessage = "Cannot set the Credential property if 'Authentication=Active Directory Device Code Flow' has been specified in the connection string."; - Assert.Contains(expectedMessage, e.Message); - } - - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void ActiveDirectoryManagedIdentityWithCredentialsMustFail() - { - // connection fails with expected error message. - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + - "Authentication=Active Directory Managed Identity;"; - - SecureString str = new SecureString(); - foreach (char c in "hello") - { - str.AppendChar(c); - } - str.MakeReadOnly(); - SqlCredential credential = new SqlCredential("someuser", str); - InvalidOperationException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred, credential)); - - string expectedMessage = "Cannot set the Credential property if 'Authentication=Active Directory Managed Identity' has been specified in the connection string."; - Assert.Contains(expectedMessage, e.Message); - } - - [ConditionalFact(nameof(IsAADConnStringsSetup), nameof(IsManagedIdentitySetup))] - public static void ActiveDirectoryManagedIdentityWithPasswordMustFail() - { - // connection fails with expected error message. - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + - "Authentication=Active Directory Managed Identity; Password=anything"; - - ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred)); - - string expectedMessage = "Cannot use 'Authentication=Active Directory Managed Identity' with 'Password' or 'PWD' connection string keywords."; - Assert.Contains(expectedMessage, e.Message); - } - - [InlineData("2445343 2343253")] - [InlineData("2445343$#^@@%2343253")] - [ConditionalTheory(nameof(IsAADConnStringsSetup), nameof(IsManagedIdentitySetup))] - public static void ActiveDirectoryManagedIdentityWithInvalidUserIdMustFail(string userId) - { - // connection fails with expected error message. - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + - $"Authentication=Active Directory Managed Identity; User Id={userId}"; - - SqlException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred)); - - string expectedMessage = "ManagedIdentityCredential authentication unavailable"; - Assert.Contains(expectedMessage, e.GetBaseException().Message); - } - - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void ActiveDirectoryMSIWithCredentialsMustFail() - { - // connection fails with expected error message. - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + - "Authentication=Active Directory MSI;"; - - SecureString str = new SecureString(); - foreach (char c in "hello") - { - str.AppendChar(c); - } - str.MakeReadOnly(); - SqlCredential credential = new SqlCredential("someuser", str); - InvalidOperationException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred, credential)); - - string expectedMessage = "Cannot set the Credential property if 'Authentication=Active Directory MSI' has been specified in the connection string."; - Assert.Contains(expectedMessage, e.Message); - } - - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void ActiveDirectoryMSIWithPasswordMustFail() - { - // connection fails with expected error message. - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + - "Authentication=ActiveDirectoryMSI; Password=anything"; - - ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred)); - - string expectedMessage = "Cannot use 'Authentication=Active Directory MSI' with 'Password' or 'PWD' connection string keywords."; - Assert.Contains(expectedMessage, e.Message); - } - - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void ActiveDirectoryDefaultWithCredentialsMustFail() - { - // connection fails with expected error message. - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + - "Authentication=Active Directory Default;"; - - SecureString str = new SecureString(); - foreach (char c in "hello") - { - str.AppendChar(c); - } - str.MakeReadOnly(); - SqlCredential credential = new SqlCredential("someuser", str); - InvalidOperationException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred, credential)); - - string expectedMessage = "Cannot set the Credential property if 'Authentication=Active Directory Default' has been specified in the connection string."; - Assert.Contains(expectedMessage, e.Message); - } - - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void ActiveDirectoryDefaultWithPasswordMustFail() - { - // connection fails with expected error message. - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + - "Authentication=ActiveDirectoryDefault; Password=anything"; - - ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred)); - - string expectedMessage = "Cannot use 'Authentication=Active Directory Default' with 'Password' or 'PWD' connection string keywords."; - Assert.Contains(expectedMessage, e.Message); - } - - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void ActiveDirectoryDefaultMustPass() - { - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + - "Authentication=ActiveDirectoryDefault;"; - - // Connection should be established using Managed Identity by default. - ConnectAndDisconnect(connStr); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsIntegratedSecuritySetup), nameof(DataTestUtility.AreConnStringsSetup))] - public static void ADInteractiveUsingSSPI() - { - // test Passes with correct connection string. - string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD", "Trusted_Connection", "Integrated Security" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.TCPConnectionString, removeKeys) + - $"Authentication=Active Directory Integrated;"; - ConnectAndDisconnect(connStr); - } - - // Test passes locally everytime, but in pieplines fails randomly with uncertainity. - // e.g. Second AAD connection too slow (802ms)! (More than 30% of the first (576ms).) - [ActiveIssue(16058)] - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void ConnectionSpeed() - { - var connString = DataTestUtility.AADPasswordConnectionString; - - //Ensure server endpoints are warm - using (var connectionDrill = new SqlConnection(connString)) - { - connectionDrill.Open(); - } - - SqlConnection.ClearAllPools(); - ActiveDirectoryAuthenticationProvider.ClearUserTokenCache(); - - Stopwatch firstConnectionTime = new Stopwatch(); - Stopwatch secondConnectionTime = new Stopwatch(); - - using (var connectionDrill = new SqlConnection(connString)) - { - firstConnectionTime.Start(); - connectionDrill.Open(); - firstConnectionTime.Stop(); - using (var connectionDrill2 = new SqlConnection(connString)) - { - secondConnectionTime.Start(); - connectionDrill2.Open(); - secondConnectionTime.Stop(); - } - } - - // Subsequent AAD connections within a short timeframe should use an auth token cached from the connection pool - // Second connection speed in tests was typically 10-15% of the first connection time. Using 30% since speeds may vary. - Assert.True(((double)secondConnectionTime.ElapsedMilliseconds / firstConnectionTime.ElapsedMilliseconds) < 0.30, $"Second AAD connection too slow ({secondConnectionTime.ElapsedMilliseconds}ms)! (More than 30% of the first ({firstConnectionTime.ElapsedMilliseconds}ms).)"); - } - - #region Managed Identity Authentication tests - - [ConditionalFact(nameof(IsAADConnStringsSetup), nameof(IsManagedIdentitySetup))] - public static void SystemAssigned_ManagedIdentityTest() - { - string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, removeKeys) + - $"Authentication=Active Directory Managed Identity;"; - ConnectAndDisconnect(connStr); - } - - [ConditionalFact(nameof(IsAADConnStringsSetup), nameof(IsManagedIdentitySetup))] - public static void UserAssigned_ManagedIdentityTest() - { - string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, removeKeys) + - $"Authentication=Active Directory Managed Identity; User Id={DataTestUtility.UserManagedIdentityClientId};"; - ConnectAndDisconnect(connStr); - } - - [ConditionalFact(nameof(IsAADConnStringsSetup), nameof(IsManagedIdentitySetup))] - public static void AccessToken_SystemManagedIdentityTest() - { - string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connectionString = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, removeKeys); - using (SqlConnection conn = new SqlConnection(connectionString)) - { - conn.AccessToken = DataTestUtility.GetSystemIdentityAccessToken(); - conn.Open(); - - Assert.True(conn.State == System.Data.ConnectionState.Open); - } - } - - [ConditionalFact(nameof(IsAADConnStringsSetup), nameof(IsManagedIdentitySetup))] - public static void AccessToken_UserManagedIdentityTest() - { - string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connectionString = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, removeKeys); - using (SqlConnection conn = new SqlConnection(connectionString)) - { - conn.AccessToken = DataTestUtility.GetUserIdentityAccessToken(); - conn.Open(); - - Assert.True(conn.State == System.Data.ConnectionState.Open); - } - } - - [ConditionalFact(nameof(AreConnStringsSetup), nameof(IsAzure), nameof(IsManagedIdentitySetup))] - public static void Azure_SystemManagedIdentityTest() - { - string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD", "Trusted_Connection", "Integrated Security" }; - string connectionString = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.TCPConnectionString, removeKeys) - + $"Authentication=Active Directory Managed Identity;"; - - using (SqlConnection conn = new SqlConnection(connectionString)) - { - conn.Open(); - - Assert.True(conn.State == System.Data.ConnectionState.Open); - } - } - - [ConditionalFact(nameof(AreConnStringsSetup), nameof(IsAzure), nameof(IsManagedIdentitySetup))] - public static void Azure_UserManagedIdentityTest() - { - string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD", "Trusted_Connection", "Integrated Security" }; - string connectionString = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.TCPConnectionString, removeKeys) - + $"Authentication=Active Directory Managed Identity; User Id={DataTestUtility.UserManagedIdentityClientId}"; - - using (SqlConnection conn = new SqlConnection(connectionString)) - { - conn.Open(); - - Assert.True(conn.State == System.Data.ConnectionState.Open); - } - } - - [ConditionalFact(nameof(AreConnStringsSetup), nameof(IsAzure), nameof(IsAccessTokenSetup), nameof(IsManagedIdentitySetup))] - public static void Azure_AccessToken_SystemManagedIdentityTest() - { - string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD", "Trusted_Connection", "Integrated Security" }; - string connectionString = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.TCPConnectionString, removeKeys); - using (SqlConnection conn = new SqlConnection(connectionString)) - { - conn.AccessToken = DataTestUtility.GetSystemIdentityAccessToken(); - conn.Open(); - - Assert.True(conn.State == System.Data.ConnectionState.Open); - } - } - - [ConditionalFact(nameof(AreConnStringsSetup), nameof(IsAzure), nameof(IsAccessTokenSetup), nameof(IsManagedIdentitySetup))] - public static void Azure_AccessToken_UserManagedIdentityTest() - { - string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD", "Trusted_Connection", "Integrated Security" }; - string connectionString = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.TCPConnectionString, removeKeys); - using (SqlConnection conn = new SqlConnection(connectionString)) - { - conn.AccessToken = DataTestUtility.GetUserIdentityAccessToken(); - conn.Open(); - - Assert.True(conn.State == System.Data.ConnectionState.Open); - } - } - #endregion - } -} +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. + +//using System; +//using System.Diagnostics; +//using System.Security; +//using System.Threading; +//using System.Threading.Tasks; +//using Microsoft.Identity.Client; +//using Xunit; + +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ +// public class AADConnectionsTest +// { +// class CustomSqlAuthenticationProvider : SqlAuthenticationProvider +// { +// string _appClientId; + +// internal CustomSqlAuthenticationProvider(string appClientId) +// { +// _appClientId = appClientId; +// } + +// public override async Task AcquireTokenAsync(SqlAuthenticationParameters parameters) +// { +// string s_defaultScopeSuffix = "/.default"; +// string scope = parameters.Resource.EndsWith(s_defaultScopeSuffix) ? parameters.Resource : parameters.Resource + s_defaultScopeSuffix; + +// _ = parameters.ServerName; +// _ = parameters.DatabaseName; +// _ = parameters.ConnectionId; + +// var cts = new CancellationTokenSource(); +// cts.CancelAfter(parameters.ConnectionTimeout * 1000); + +// string[] scopes = new string[] { scope }; +// SecureString password = new SecureString(); + +// AuthenticationResult result = await PublicClientApplicationBuilder.Create(_appClientId) +// .WithAuthority(parameters.Authority) +// .Build().AcquireTokenByUsernamePassword(scopes, parameters.UserId, parameters.Password) +// .WithCorrelationId(parameters.ConnectionId) +// .ExecuteAsync(cancellationToken: cts.Token); + +// return new SqlAuthenticationToken(result.AccessToken, result.ExpiresOn); +// } + +// public override bool IsSupported(SqlAuthenticationMethod authenticationMethod) +// { +// return authenticationMethod.Equals(SqlAuthenticationMethod.ActiveDirectoryPassword); +// } +// } + +// private static void ConnectAndDisconnect(string connectionString, SqlCredential credential = null) +// { +// using (SqlConnection conn = new SqlConnection(connectionString)) +// { +// if (credential != null) +// { +// conn.Credential = credential; +// } +// conn.Open(); + +// Assert.True(conn.State == System.Data.ConnectionState.Open); +// } +// } + +// private static bool AreConnStringsSetup() => DataTestUtility.AreConnStringsSetup(); +// private static bool IsAzure() => !DataTestUtility.IsNotAzureServer(); +// private static bool IsAccessTokenSetup() => DataTestUtility.IsAccessTokenSetup(); +// private static bool IsAADConnStringsSetup() => DataTestUtility.IsAADPasswordConnStrSetup(); +// private static bool IsManagedIdentitySetup() => DataTestUtility.ManagedIdentitySupported; + +// [PlatformSpecific(TestPlatforms.Windows)] +// [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] +// public static void KustoDatabaseTest() +// { +// // This is a sample Kusto database that can be connected by any AD account. +// using SqlConnection connection = new SqlConnection("Data Source=help.kusto.windows.net; Authentication=Active Directory Default;Trust Server Certificate=True;"); +// connection.Open(); +// Assert.True(connection.State == System.Data.ConnectionState.Open); +// } + +// [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] +// public static void AccessTokenTest() +// { +// // Remove cred info and add invalid token +// string[] credKeys = { "User ID", "Password", "UID", "PWD", "Authentication" }; +// string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys); + +// using (SqlConnection connection = new SqlConnection(connStr)) +// { +// connection.AccessToken = DataTestUtility.GetAccessToken(); +// connection.Open(); + +// Assert.True(connection.State == System.Data.ConnectionState.Open); +// } +// } + +// [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] +// public static void InvalidAccessTokenTest() +// { +// // Remove cred info and add invalid token +// string[] credKeys = { "User ID", "Password", "UID", "PWD", "Authentication" }; +// string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys); + +// using (SqlConnection connection = new SqlConnection(connStr)) +// { +// connection.AccessToken = DataTestUtility.GetAccessToken() + "abc"; +// SqlException e = Assert.Throws(() => connection.Open()); + +// string expectedMessage = "Login failed for user"; +// Assert.Contains(expectedMessage, e.Message); +// } +// } + +// [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] +// public static void AccessTokenWithAuthType() +// { +// // Remove cred info and add invalid token +// string[] credKeys = { "User ID", "Password", "UID", "PWD" }; +// string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys); + +// using (SqlConnection connection = new SqlConnection(connStr)) +// { +// InvalidOperationException e = Assert.Throws(() => +// connection.AccessToken = DataTestUtility.GetAccessToken()); + +// string expectedMessage = "Cannot set the AccessToken property if 'Authentication' has been specified in the connection string."; +// Assert.Contains(expectedMessage, e.Message); +// } +// } + +// [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] +// public static void AccessTokenWithCred() +// { +// // Remove cred info and add invalid token +// string[] credKeys = { "Authentication" }; +// string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys); + +// using (SqlConnection connection = new SqlConnection(connStr)) +// { +// InvalidOperationException e = Assert.Throws(() => +// connection.AccessToken = DataTestUtility.GetAccessToken()); + +// string expectedMessage = "Cannot set the AccessToken property if 'UserID', 'UID', 'Password', or 'PWD' has been specified in connection string."; +// Assert.Contains(expectedMessage, e.Message); +// } +// } + +// [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] +// public static void AccessTokenTestWithEmptyToken() +// { +// // Remove cred info and add invalid token +// string[] credKeys = { "User ID", "Password", "UID", "PWD", "Authentication" }; +// string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys); + +// using (SqlConnection connection = new SqlConnection(connStr)) +// { +// connection.AccessToken = ""; +// SqlException e = Assert.Throws(() => connection.Open()); + +// string expectedMessage = "A connection was successfully established with the server, but then an error occurred during the login process."; +// Assert.Contains(expectedMessage, e.Message); +// } +// } + +// [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] +// public static void AccessTokenTestWithIntegratedSecurityTrue() +// { +// // Remove cred info and add invalid token +// string[] credKeys = { "User ID", "Password", "UID", "PWD", "Authentication" }; +// string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + "Integrated Security=True;"; + +// using (SqlConnection connection = new SqlConnection(connStr)) +// { +// InvalidOperationException e = Assert.Throws(() => connection.AccessToken = ""); + +// string expectedMessage = "Cannot set the AccessToken property if the 'Integrated Security' connection string keyword has been set to 'true' or 'SSPI'."; +// Assert.Contains(expectedMessage, e.Message); +// } +// } + +// [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] +// public static void InvalidAuthTypeTest() +// { +// // Remove cred info and add invalid token +// string[] credKeys = { "Authentication" }; +// string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + "Authentication=Active Directory Pass;"; + +// ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStr)); + +// string expectedMessage = "Invalid value for key 'authentication'."; +// Assert.Contains(expectedMessage, e.Message, StringComparison.OrdinalIgnoreCase); +// } + +// [ConditionalFact(nameof(IsAADConnStringsSetup))] +// public static void AADPasswordWithIntegratedSecurityTrue() +// { +// string connStr = DataTestUtility.AADPasswordConnectionString + "Integrated Security=True;"; + +// ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStr)); + +// string expectedMessage = "Cannot use 'Authentication' with 'Integrated Security'."; +// Assert.Contains(expectedMessage, e.Message); +// } + +// [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] +// public static void AADPasswordWithWrongPassword() +// { +// string[] credKeys = { "Password", "PWD" }; +// string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + "Password=TestPassword;"; + +// Assert.Throws(() => ConnectAndDisconnect(connStr)); + +// // We cannot verify error message with certainity as driver may cache token from other tests for current user +// // and error message may change accordingly. +// } + +// [ConditionalFact(nameof(IsAADConnStringsSetup))] +// public static void GetAccessTokenByPasswordTest() +// { +// // Clear token cache for code coverage. +// ActiveDirectoryAuthenticationProvider.ClearUserTokenCache(); +// using (SqlConnection connection = new SqlConnection(DataTestUtility.AADPasswordConnectionString)) +// { +// connection.Open(); +// Assert.True(connection.State == System.Data.ConnectionState.Open); +// } +// } + +// [ConditionalFact(nameof(IsAADConnStringsSetup))] +// public static void TestADPasswordAuthentication() +// { +// // Connect to Azure DB with password and retrieve user name. +// using (SqlConnection conn = new SqlConnection(DataTestUtility.AADPasswordConnectionString)) +// { +// conn.Open(); +// using (SqlCommand sqlCommand = new SqlCommand +// ( +// cmdText: $"SELECT SUSER_SNAME();", +// connection: conn, +// transaction: null +// )) +// { +// string customerId = (string)sqlCommand.ExecuteScalar(); +// string expected = DataTestUtility.RetrieveValueFromConnStr(DataTestUtility.AADPasswordConnectionString, new string[] { "User ID", "UID" }); +// Assert.Equal(expected, customerId); +// } +// } +// } + +// [ConditionalFact(nameof(IsAADConnStringsSetup))] +// public static void TestCustomProviderAuthentication() +// { +// SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, new CustomSqlAuthenticationProvider(DataTestUtility.ApplicationClientId)); +// // Connect to Azure DB with password and retrieve user name using custom authentication provider +// using (SqlConnection conn = new SqlConnection(DataTestUtility.AADPasswordConnectionString)) +// { +// conn.Open(); +// using (SqlCommand sqlCommand = new SqlCommand +// ( +// cmdText: $"SELECT SUSER_SNAME();", +// connection: conn, +// transaction: null +// )) +// { +// string customerId = (string)sqlCommand.ExecuteScalar(); +// string expected = DataTestUtility.RetrieveValueFromConnStr(DataTestUtility.AADPasswordConnectionString, new string[] { "User ID", "UID" }); +// Assert.Equal(expected, customerId); +// } +// } +// // Reset to driver internal provider. +// SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, new ActiveDirectoryAuthenticationProvider(DataTestUtility.ApplicationClientId)); +// } + +// [ConditionalFact(nameof(IsAADConnStringsSetup))] +// public static void ActiveDirectoryPasswordWithNoAuthType() +// { +// // connection fails with expected error message. +// string[] AuthKey = { "Authentication" }; +// string connStrWithNoAuthType = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, AuthKey); +// Assert.Throws(() => ConnectAndDisconnect(connStrWithNoAuthType)); +// } + +// [ConditionalFact(nameof(IsAADConnStringsSetup))] +// public static void IntegratedAuthWithCred() +// { +// // connection fails with expected error message. +// string[] AuthKey = { "Authentication" }; +// string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, AuthKey) + "Authentication=Active Directory Integrated;"; +// ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStr)); + +// string[] expectedMessage = { "Cannot use 'Authentication=Active Directory Integrated' with 'User ID', 'UID', 'Password' or 'PWD' connection string keywords.", //netfx +// "Cannot use 'Authentication=Active Directory Integrated' with 'Password' or 'PWD' connection string keywords." }; //netcore +// Assert.Contains(e.Message, expectedMessage); +// } + +// [ConditionalFact(nameof(IsAADConnStringsSetup))] +// public static void MFAAuthWithPassword() +// { +// // connection fails with expected error message. +// string[] AuthKey = { "Authentication" }; +// string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, AuthKey) + "Authentication=Active Directory Interactive;"; +// ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStr)); + +// string expectedMessage = "Cannot use 'Authentication=Active Directory Interactive' with 'Password' or 'PWD' connection string keywords."; +// Assert.Contains(expectedMessage, e.Message); +// } + +// [ConditionalFact(nameof(IsAADConnStringsSetup))] +// public static void EmptyPasswordInConnStrAADPassword() +// { +// // connection fails with expected error message. +// string[] pwdKey = { "Password", "PWD" }; +// string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, pwdKey) + "Password=;"; +// SqlException e = Assert.Throws(() => ConnectAndDisconnect(connStr)); + +// string user = DataTestUtility.FetchKeyInConnStr(DataTestUtility.AADPasswordConnectionString, new string[] { "User Id", "UID" }); +// string expectedMessage = string.Format("Failed to authenticate the user {0} in Active Directory (Authentication=ActiveDirectoryPassword).", user); +// Assert.Contains(expectedMessage, e.Message); +// } + +// [PlatformSpecific(TestPlatforms.Windows)] +// [ConditionalFact(nameof(IsAADConnStringsSetup))] +// public static void EmptyCredInConnStrAADPassword() +// { +// // connection fails with expected error message. +// string[] removeKeys = { "User ID", "Password", "UID", "PWD" }; +// string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, removeKeys) + "User ID=; Password=;"; +// SqlException e = Assert.Throws(() => ConnectAndDisconnect(connStr)); + +// string expectedMessage = "Failed to authenticate the user in Active Directory (Authentication=ActiveDirectoryPassword)."; +// Assert.Contains(expectedMessage, e.Message); +// } + +// [PlatformSpecific(TestPlatforms.AnyUnix)] +// [ConditionalFact(nameof(IsAADConnStringsSetup))] +// public static void EmptyCredInConnStrAADPasswordAnyUnix() +// { +// // connection fails with expected error message. +// string[] removeKeys = { "User ID", "Password", "UID", "PWD" }; +// string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, removeKeys) + "User ID=; Password=;"; +// SqlException e = Assert.Throws(() => ConnectAndDisconnect(connStr)); + +// string expectedMessage = "MSAL cannot determine the username (UPN) of the currently logged in user.For Integrated Windows Authentication and Username/Password flows, please use .WithUsername() before calling ExecuteAsync()."; +// Assert.Contains(expectedMessage, e.Message); +// } + +// [ConditionalFact(nameof(IsAADConnStringsSetup))] +// public static void AADPasswordWithInvalidUser() +// { +// // connection fails with expected error message. +// string[] removeKeys = { "User ID", "UID" }; +// string user = "testdotnet@domain.com"; +// string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, removeKeys) + $"User ID={user}"; +// SqlException e = Assert.Throws(() => ConnectAndDisconnect(connStr)); + +// string expectedMessage = string.Format("Failed to authenticate the user {0} in Active Directory (Authentication=ActiveDirectoryPassword).", user); +// Assert.Contains(expectedMessage, e.Message); +// } + +// [ConditionalFact(nameof(IsAADConnStringsSetup))] +// public static void NoCredentialsActiveDirectoryPassword() +// { +// // test Passes with correct connection string. +// ConnectAndDisconnect(DataTestUtility.AADPasswordConnectionString); + +// // connection fails with expected error message. +// string[] credKeys = { "User ID", "Password", "UID", "PWD" }; +// string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys); +// InvalidOperationException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred)); + +// string expectedMessage = "Either Credential or both 'User ID' and 'Password' (or 'UID' and 'PWD') connection string keywords must be specified, if 'Authentication=Active Directory Password'."; +// Assert.Contains(expectedMessage, e.Message); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAADServicePrincipalSetup))] +// public static void NoCredentialsActiveDirectoryServicePrincipal() +// { +// // test Passes with correct connection string. +// string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; +// string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, removeKeys) + +// $"Authentication=Active Directory Service Principal; User ID={DataTestUtility.AADServicePrincipalId}; PWD={DataTestUtility.AADServicePrincipalSecret};"; +// ConnectAndDisconnect(connStr); + +// // connection fails with expected error message. +// string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; +// string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + +// "Authentication=Active Directory Service Principal;"; +// InvalidOperationException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred)); + +// string expectedMessage = "Either Credential or both 'User ID' and 'Password' (or 'UID' and 'PWD') connection string keywords must be specified, if 'Authentication=Active Directory Service Principal'."; +// Assert.Contains(expectedMessage, e.Message); +// } + +// [ConditionalFact(nameof(IsAADConnStringsSetup))] +// public static void ActiveDirectoryDeviceCodeFlowWithUserIdMustFail() +// { +// // connection fails with expected error message. +// string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; +// string connStrWithUID = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + +// "Authentication=Active Directory Device Code Flow; UID=someuser;"; +// ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithUID)); + +// string expectedMessage = "Cannot use 'Authentication=Active Directory Device Code Flow' with 'User ID', 'UID', 'Password' or 'PWD' connection string keywords."; +// Assert.Contains(expectedMessage, e.Message); +// } + +// [ConditionalFact(nameof(IsAADConnStringsSetup))] +// public static void ActiveDirectoryDeviceCodeFlowWithCredentialsMustFail() +// { +// // connection fails with expected error message. +// string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; +// string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + +// "Authentication=Active Directory Device Code Flow;"; + +// SecureString str = new SecureString(); +// foreach (char c in "hello") +// { +// str.AppendChar(c); +// } +// str.MakeReadOnly(); +// SqlCredential credential = new SqlCredential("someuser", str); +// InvalidOperationException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred, credential)); + +// string expectedMessage = "Cannot set the Credential property if 'Authentication=Active Directory Device Code Flow' has been specified in the connection string."; +// Assert.Contains(expectedMessage, e.Message); +// } + +// [ConditionalFact(nameof(IsAADConnStringsSetup))] +// public static void ActiveDirectoryManagedIdentityWithCredentialsMustFail() +// { +// // connection fails with expected error message. +// string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; +// string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + +// "Authentication=Active Directory Managed Identity;"; + +// SecureString str = new SecureString(); +// foreach (char c in "hello") +// { +// str.AppendChar(c); +// } +// str.MakeReadOnly(); +// SqlCredential credential = new SqlCredential("someuser", str); +// InvalidOperationException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred, credential)); + +// string expectedMessage = "Cannot set the Credential property if 'Authentication=Active Directory Managed Identity' has been specified in the connection string."; +// Assert.Contains(expectedMessage, e.Message); +// } + +// [ConditionalFact(nameof(IsAADConnStringsSetup), nameof(IsManagedIdentitySetup))] +// public static void ActiveDirectoryManagedIdentityWithPasswordMustFail() +// { +// // connection fails with expected error message. +// string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; +// string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + +// "Authentication=Active Directory Managed Identity; Password=anything"; + +// ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred)); + +// string expectedMessage = "Cannot use 'Authentication=Active Directory Managed Identity' with 'Password' or 'PWD' connection string keywords."; +// Assert.Contains(expectedMessage, e.Message); +// } + +// [InlineData("2445343 2343253")] +// [InlineData("2445343$#^@@%2343253")] +// [ConditionalTheory(nameof(IsAADConnStringsSetup), nameof(IsManagedIdentitySetup))] +// public static void ActiveDirectoryManagedIdentityWithInvalidUserIdMustFail(string userId) +// { +// // connection fails with expected error message. +// string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; +// string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + +// $"Authentication=Active Directory Managed Identity; User Id={userId}"; + +// SqlException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred)); + +// string expectedMessage = "ManagedIdentityCredential authentication unavailable"; +// Assert.Contains(expectedMessage, e.GetBaseException().Message); +// } + +// [ConditionalFact(nameof(IsAADConnStringsSetup))] +// public static void ActiveDirectoryMSIWithCredentialsMustFail() +// { +// // connection fails with expected error message. +// string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; +// string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + +// "Authentication=Active Directory MSI;"; + +// SecureString str = new SecureString(); +// foreach (char c in "hello") +// { +// str.AppendChar(c); +// } +// str.MakeReadOnly(); +// SqlCredential credential = new SqlCredential("someuser", str); +// InvalidOperationException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred, credential)); + +// string expectedMessage = "Cannot set the Credential property if 'Authentication=Active Directory MSI' has been specified in the connection string."; +// Assert.Contains(expectedMessage, e.Message); +// } + +// [ConditionalFact(nameof(IsAADConnStringsSetup))] +// public static void ActiveDirectoryMSIWithPasswordMustFail() +// { +// // connection fails with expected error message. +// string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; +// string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + +// "Authentication=ActiveDirectoryMSI; Password=anything"; + +// ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred)); + +// string expectedMessage = "Cannot use 'Authentication=Active Directory MSI' with 'Password' or 'PWD' connection string keywords."; +// Assert.Contains(expectedMessage, e.Message); +// } + +// [ConditionalFact(nameof(IsAADConnStringsSetup))] +// public static void ActiveDirectoryDefaultWithCredentialsMustFail() +// { +// // connection fails with expected error message. +// string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; +// string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + +// "Authentication=Active Directory Default;"; + +// SecureString str = new SecureString(); +// foreach (char c in "hello") +// { +// str.AppendChar(c); +// } +// str.MakeReadOnly(); +// SqlCredential credential = new SqlCredential("someuser", str); +// InvalidOperationException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred, credential)); + +// string expectedMessage = "Cannot set the Credential property if 'Authentication=Active Directory Default' has been specified in the connection string."; +// Assert.Contains(expectedMessage, e.Message); +// } + +// [ConditionalFact(nameof(IsAADConnStringsSetup))] +// public static void ActiveDirectoryDefaultWithPasswordMustFail() +// { +// // connection fails with expected error message. +// string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; +// string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + +// "Authentication=ActiveDirectoryDefault; Password=anything"; + +// ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred)); + +// string expectedMessage = "Cannot use 'Authentication=Active Directory Default' with 'Password' or 'PWD' connection string keywords."; +// Assert.Contains(expectedMessage, e.Message); +// } + +// [ConditionalFact(nameof(IsAADConnStringsSetup))] +// public static void ActiveDirectoryDefaultMustPass() +// { +// string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; +// string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + +// "Authentication=ActiveDirectoryDefault;"; + +// // Connection should be established using Managed Identity by default. +// ConnectAndDisconnect(connStr); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsIntegratedSecuritySetup), nameof(DataTestUtility.AreConnStringsSetup))] +// public static void ADInteractiveUsingSSPI() +// { +// // test Passes with correct connection string. +// string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD", "Trusted_Connection", "Integrated Security" }; +// string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.TCPConnectionString, removeKeys) + +// $"Authentication=Active Directory Integrated;"; +// ConnectAndDisconnect(connStr); +// } + +// // Test passes locally everytime, but in pieplines fails randomly with uncertainity. +// // e.g. Second AAD connection too slow (802ms)! (More than 30% of the first (576ms).) +// [ActiveIssue(16058)] +// [ConditionalFact(nameof(IsAADConnStringsSetup))] +// public static void ConnectionSpeed() +// { +// var connString = DataTestUtility.AADPasswordConnectionString; + +// //Ensure server endpoints are warm +// using (var connectionDrill = new SqlConnection(connString)) +// { +// connectionDrill.Open(); +// } + +// SqlConnection.ClearAllPools(); +// ActiveDirectoryAuthenticationProvider.ClearUserTokenCache(); + +// Stopwatch firstConnectionTime = new Stopwatch(); +// Stopwatch secondConnectionTime = new Stopwatch(); + +// using (var connectionDrill = new SqlConnection(connString)) +// { +// firstConnectionTime.Start(); +// connectionDrill.Open(); +// firstConnectionTime.Stop(); +// using (var connectionDrill2 = new SqlConnection(connString)) +// { +// secondConnectionTime.Start(); +// connectionDrill2.Open(); +// secondConnectionTime.Stop(); +// } +// } + +// // Subsequent AAD connections within a short timeframe should use an auth token cached from the connection pool +// // Second connection speed in tests was typically 10-15% of the first connection time. Using 30% since speeds may vary. +// Assert.True(((double)secondConnectionTime.ElapsedMilliseconds / firstConnectionTime.ElapsedMilliseconds) < 0.30, $"Second AAD connection too slow ({secondConnectionTime.ElapsedMilliseconds}ms)! (More than 30% of the first ({firstConnectionTime.ElapsedMilliseconds}ms).)"); +// } + +// #region Managed Identity Authentication tests + +// [ConditionalFact(nameof(IsAADConnStringsSetup), nameof(IsManagedIdentitySetup))] +// public static void SystemAssigned_ManagedIdentityTest() +// { +// string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; +// string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, removeKeys) + +// $"Authentication=Active Directory Managed Identity;"; +// ConnectAndDisconnect(connStr); +// } + +// [ConditionalFact(nameof(IsAADConnStringsSetup), nameof(IsManagedIdentitySetup))] +// public static void UserAssigned_ManagedIdentityTest() +// { +// string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; +// string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, removeKeys) + +// $"Authentication=Active Directory Managed Identity; User Id={DataTestUtility.UserManagedIdentityClientId};"; +// ConnectAndDisconnect(connStr); +// } + +// [ConditionalFact(nameof(IsAADConnStringsSetup), nameof(IsManagedIdentitySetup))] +// public static void AccessToken_SystemManagedIdentityTest() +// { +// string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; +// string connectionString = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, removeKeys); +// using (SqlConnection conn = new SqlConnection(connectionString)) +// { +// conn.AccessToken = DataTestUtility.GetSystemIdentityAccessToken(); +// conn.Open(); + +// Assert.True(conn.State == System.Data.ConnectionState.Open); +// } +// } + +// [ConditionalFact(nameof(IsAADConnStringsSetup), nameof(IsManagedIdentitySetup))] +// public static void AccessToken_UserManagedIdentityTest() +// { +// string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; +// string connectionString = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, removeKeys); +// using (SqlConnection conn = new SqlConnection(connectionString)) +// { +// conn.AccessToken = DataTestUtility.GetUserIdentityAccessToken(); +// conn.Open(); + +// Assert.True(conn.State == System.Data.ConnectionState.Open); +// } +// } + +// [ConditionalFact(nameof(AreConnStringsSetup), nameof(IsAzure), nameof(IsManagedIdentitySetup))] +// public static void Azure_SystemManagedIdentityTest() +// { +// string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD", "Trusted_Connection", "Integrated Security" }; +// string connectionString = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.TCPConnectionString, removeKeys) +// + $"Authentication=Active Directory Managed Identity;"; + +// using (SqlConnection conn = new SqlConnection(connectionString)) +// { +// conn.Open(); + +// Assert.True(conn.State == System.Data.ConnectionState.Open); +// } +// } + +// [ConditionalFact(nameof(AreConnStringsSetup), nameof(IsAzure), nameof(IsManagedIdentitySetup))] +// public static void Azure_UserManagedIdentityTest() +// { +// string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD", "Trusted_Connection", "Integrated Security" }; +// string connectionString = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.TCPConnectionString, removeKeys) +// + $"Authentication=Active Directory Managed Identity; User Id={DataTestUtility.UserManagedIdentityClientId}"; + +// using (SqlConnection conn = new SqlConnection(connectionString)) +// { +// conn.Open(); + +// Assert.True(conn.State == System.Data.ConnectionState.Open); +// } +// } + +// [ConditionalFact(nameof(AreConnStringsSetup), nameof(IsAzure), nameof(IsAccessTokenSetup), nameof(IsManagedIdentitySetup))] +// public static void Azure_AccessToken_SystemManagedIdentityTest() +// { +// string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD", "Trusted_Connection", "Integrated Security" }; +// string connectionString = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.TCPConnectionString, removeKeys); +// using (SqlConnection conn = new SqlConnection(connectionString)) +// { +// conn.AccessToken = DataTestUtility.GetSystemIdentityAccessToken(); +// conn.Open(); + +// Assert.True(conn.State == System.Data.ConnectionState.Open); +// } +// } + +// [ConditionalFact(nameof(AreConnStringsSetup), nameof(IsAzure), nameof(IsAccessTokenSetup), nameof(IsManagedIdentitySetup))] +// public static void Azure_AccessToken_UserManagedIdentityTest() +// { +// string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD", "Trusted_Connection", "Integrated Security" }; +// string connectionString = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.TCPConnectionString, removeKeys); +// using (SqlConnection conn = new SqlConnection(connectionString)) +// { +// conn.AccessToken = DataTestUtility.GetUserIdentityAccessToken(); +// conn.Open(); + +// Assert.True(conn.State == System.Data.ConnectionState.Open); +// } +// } +// #endregion +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/ConnectionBehaviorTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/ConnectionBehaviorTest.cs index 5b108400b0..d6bfef5f92 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/ConnectionBehaviorTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/ConnectionBehaviorTest.cs @@ -1,63 +1,63 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. -using System.Data; -using System.Threading.Tasks; -using Xunit; +//using System.Data; +//using System.Threading.Tasks; +//using Xunit; -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ - public class ConnectionBehaviorTest - { - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public void ConnectionBehaviorClose() - { - using (SqlConnection sqlConnection = new SqlConnection((new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { MaxPoolSize = 1 }).ConnectionString)) - { - using (SqlCommand command = new SqlCommand("SELECT '1'", sqlConnection)) - { - sqlConnection.Open(); - using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection)) - { - while (reader.Read()) - { - string result = reader[0].ToString(); - } - } +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ +// public class ConnectionBehaviorTest +// { +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public void ConnectionBehaviorClose() +// { +// using (SqlConnection sqlConnection = new SqlConnection((new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { MaxPoolSize = 1 }).ConnectionString)) +// { +// using (SqlCommand command = new SqlCommand("SELECT '1'", sqlConnection)) +// { +// sqlConnection.Open(); +// using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection)) +// { +// while (reader.Read()) +// { +// string result = reader[0].ToString(); +// } +// } - Assert.Equal(ConnectionState.Closed, sqlConnection.State); - } - } - } +// Assert.Equal(ConnectionState.Closed, sqlConnection.State); +// } +// } +// } - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public void ConnectionBehaviorCloseAsync() - { - using (SqlConnection sqlConnection = new SqlConnection((new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { MaxPoolSize = 1 }).ConnectionString)) - { - Task result = VerifyConnectionBehaviorCloseAsync(sqlConnection); - bool value = result.Result; - } - } +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public void ConnectionBehaviorCloseAsync() +// { +// using (SqlConnection sqlConnection = new SqlConnection((new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { MaxPoolSize = 1 }).ConnectionString)) +// { +// Task result = VerifyConnectionBehaviorCloseAsync(sqlConnection); +// bool value = result.Result; +// } +// } - private async Task VerifyConnectionBehaviorCloseAsync(SqlConnection sqlConnection) - { - using (SqlCommand command = new SqlCommand("SELECT '1'", sqlConnection)) - { - await sqlConnection.OpenAsync(); - using (SqlDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.CloseConnection)) - { - while (reader.Read()) - { - string result = reader[0].ToString(); - } - } +// private async Task VerifyConnectionBehaviorCloseAsync(SqlConnection sqlConnection) +// { +// using (SqlCommand command = new SqlCommand("SELECT '1'", sqlConnection)) +// { +// await sqlConnection.OpenAsync(); +// using (SqlDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.CloseConnection)) +// { +// while (reader.Read()) +// { +// string result = reader[0].ToString(); +// } +// } - Assert.Equal(ConnectionState.Closed, sqlConnection.State); - } +// Assert.Equal(ConnectionState.Closed, sqlConnection.State); +// } - return true; - } - } -} +// return true; +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/ConnectivityTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/ConnectivityTest.cs index 489a414ce9..b77a9f4de8 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/ConnectivityTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/ConnectivityTest.cs @@ -1,497 +1,497 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Security.Principal; -using System.Threading; -using Microsoft.Win32; -using Xunit; - -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ - public static class ConnectivityTest - { - private const string COL_SPID = "SPID"; - private const string COL_PROGRAM_NAME = "ProgramName"; - private const string COL_HOSTNAME = "HostName"; - private static readonly string s_databaseName = "d_" + Guid.NewGuid().ToString().Replace('-', '_'); - private static readonly string s_tableName = DataTestUtility.GenerateObjectName(); - private static readonly string s_connectionString = DataTestUtility.TCPConnectionString; - private static readonly string s_dbConnectionString = new SqlConnectionStringBuilder(s_connectionString) { InitialCatalog = s_databaseName }.ConnectionString; - private static readonly string s_createDatabaseCmd = $"CREATE DATABASE {s_databaseName}"; - private static readonly string s_createTableCmd = $"CREATE TABLE {s_tableName} (NAME NVARCHAR(40), AGE INT)"; - private static readonly string s_alterDatabaseSingleCmd = $"ALTER DATABASE {s_databaseName} SET SINGLE_USER WITH ROLLBACK IMMEDIATE;"; - private static readonly string s_alterDatabaseMultiCmd = $"ALTER DATABASE {s_databaseName} SET MULTI_USER WITH ROLLBACK IMMEDIATE;"; - private static readonly string s_selectTableCmd = $"SELECT COUNT(*) FROM {s_tableName}"; - private static readonly string s_dropDatabaseCmd = $"DROP DATABASE {s_databaseName}"; - - // Synapse: Stored procedure sp_who2 does not exist or is not supported. - // Synapse: SqlConnection.ServerProcessId is always retrieved as 0. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public static void EnvironmentHostNameSPIDTest() - { - SqlConnectionStringBuilder builder = new(DataTestUtility.TCPConnectionString) - { - Pooling = true, - ApplicationName = "HostNameTest" - }; - - using (SqlConnection sqlConnection = new(builder.ConnectionString)) - { - sqlConnection.Open(); - int sqlClientSPID = sqlConnection.ServerProcessId; - int sessionSpid; - - using (SqlCommand cmd = new("SELECT @@SPID", sqlConnection)) - using (SqlDataReader reader = cmd.ExecuteReader()) - { - reader.Read(); - sessionSpid = reader.GetInt16(0); - } - - // Confirm Server process id is same as result of SELECT @@SPID - Assert.Equal(sessionSpid, sqlClientSPID); - - // Confirm once again SPID on SqlConnection directly - Assert.Equal(sessionSpid, sqlConnection.ServerProcessId); - - using (SqlCommand command = new("sp_who2", sqlConnection)) - using (SqlDataReader reader = command.ExecuteReader()) - { - while (reader.Read()) - { - int programNameOrdinal = reader.GetOrdinal(COL_PROGRAM_NAME); - string programName = reader.GetString(programNameOrdinal); - - int spidOrdinal = reader.GetOrdinal(COL_SPID); - string spid = reader.GetString(spidOrdinal); - - if (programName != null && programName.Trim().Equals(builder.ApplicationName) && short.Parse(spid) == sessionSpid) - { - // Get the hostname - int hostnameOrdinal = reader.GetOrdinal(COL_HOSTNAME); - string hostnameFromServer = reader.GetString(hostnameOrdinal); - string expectedMachineName = Environment.MachineName.ToUpper(); - string hostNameFromServer = hostnameFromServer.Trim().ToUpper(); - Assert.Matches(expectedMachineName, hostNameFromServer); - return; - } - } - } - // Confirm Server Process Id stays the same after query execution - Assert.Equal(sessionSpid, sqlConnection.ServerProcessId); - } - Assert.True(false, "No non-empty hostname found for the application"); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public static async void ConnectionTimeoutInfiniteTest() - { - // Exercise the special-case infinite connect timeout code path - SqlConnectionStringBuilder builder = new(DataTestUtility.TCPConnectionString) - { - ConnectTimeout = 0 // Infinite - }; - - using SqlConnection conn = new(builder.ConnectionString); - CancellationTokenSource cts = new(30000); - // Will throw TaskCanceledException and fail the test in the event of a hang - await conn.OpenAsync(cts.Token); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public static void ConnectionTimeoutTestWithThread() - { - const int timeoutSec = 5; - const int numOfTry = 2; - const int numOfThreads = 5; - - SqlConnectionStringBuilder builder = new(DataTestUtility.TCPConnectionString) - { - DataSource = "invalidhost", - ConnectTimeout = timeoutSec - }; - string connStrNotAvailable = builder.ConnectionString; - - for (int i = 0; i < numOfThreads; ++i) - { - new ConnectionWorker(connStrNotAvailable, numOfTry); - } - - ConnectionWorker.Start(); - ConnectionWorker.Stop(); - - double timeTotal = 0; - - foreach (ConnectionWorker w in ConnectionWorker.WorkerList) - { - timeTotal += w.TimeElapsed; - } - double timeElapsed = timeTotal / Convert.ToDouble(ConnectionWorker.WorkerList.Count); - int threshold = timeoutSec * numOfTry * 2 * 1000; - - Assert.True(timeElapsed < threshold); - } - - // Synapse: Catalog view 'sysprocesses' is not supported in this version. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public static void LocalProcessIdTest() - { - SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString); - string sqlProviderName = builder.ApplicationName; - string sqlProviderProcessID = Process.GetCurrentProcess().Id.ToString(); - - using (SqlConnection sqlConnection = new SqlConnection(builder.ConnectionString)) - { - sqlConnection.Open(); - string strCommand = $"SELECT PROGRAM_NAME,HOSTPROCESS FROM SYS.SYSPROCESSES WHERE PROGRAM_NAME LIKE ('%{sqlProviderName}%')"; - using (SqlCommand command = new SqlCommand(strCommand, sqlConnection)) - { - using (SqlDataReader reader = command.ExecuteReader()) - { - bool processIdFound = false; - while (reader.Read()) - { - Assert.Equal(sqlProviderName, reader.GetString(0).Trim()); - if (sqlProviderProcessID == reader.GetString(1).Trim()) - { - processIdFound = true; - } - } - Assert.True(processIdFound); - } - } - } - } - public class ConnectionWorker : IDisposable - { - private static List s_workerList = new(); - private ManualResetEventSlim _doneEvent = new(false); - private double _timeElapsed; - private Thread _thread; - private string _connectionString; - private int _numOfTry; - - public ConnectionWorker(string connectionString, int numOfTry) - { - s_workerList.Add(this); - _connectionString = connectionString; - _numOfTry = numOfTry; - _thread = new Thread(new ThreadStart(SqlConnectionOpen)); - } - - public static List WorkerList => s_workerList; - - public double TimeElapsed => _timeElapsed; - - public static void Start() - { - foreach (ConnectionWorker w in s_workerList) - { - w._thread.Start(); - } - } - - public static void Stop() - { - foreach (ConnectionWorker w in s_workerList) - { - w._doneEvent.Wait(); - } - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - _doneEvent.Dispose(); - } - } - - public void SqlConnectionOpen() - { - Stopwatch sw = new Stopwatch(); - double totalTime = 0; - for (int i = 0; i < _numOfTry; ++i) - { - using (SqlConnection con = new(_connectionString)) - { - sw.Start(); - try - { - con.Open(); - } - catch { } - sw.Stop(); - } - totalTime += sw.Elapsed.TotalMilliseconds; - sw.Reset(); - } - _timeElapsed = totalTime / Convert.ToDouble(_numOfTry); - - _doneEvent.Set(); - } - } - - // Synapse: Parse error at line: 1, column: 59: Incorrect syntax near 'SINGLE_USER' - No support for MULTI_USER - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureServer))] - public static void ConnectionKilledTest() - { - try - { - // Setup Database and Table. - DataTestUtility.RunNonQuery(s_connectionString, s_createDatabaseCmd); - DataTestUtility.RunNonQuery(s_dbConnectionString, s_createTableCmd); - - // Kill all the connections and set Database to SINGLE_USER Mode. - DataTestUtility.RunNonQuery(s_connectionString, s_alterDatabaseSingleCmd, 4); - // Set Database back to MULTI_USER Mode - DataTestUtility.RunNonQuery(s_connectionString, s_alterDatabaseMultiCmd, 4); - - // Execute SELECT statement. - DataTestUtility.RunNonQuery(s_dbConnectionString, s_selectTableCmd); - } - finally - { - // Kill all the connections, set Database to SINGLE_USER Mode and drop Database - DataTestUtility.RunNonQuery(s_connectionString, s_alterDatabaseSingleCmd, 4); - DataTestUtility.RunNonQuery(s_connectionString, s_dropDatabaseCmd, 4); - } - } - - // Synapse: KILL not supported on Azure Synapse - Parse error at line: 1, column: 6: Incorrect syntax near '105'. - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - public static void ConnectionResiliencySPIDTest() - { - SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) - { - ConnectRetryCount = 0, - ConnectRetryInterval = 5 - }; - - // No connection resiliency - using (SqlConnection conn = new(builder.ConnectionString)) - { - conn.Open(); - InternalConnectionWrapper wrapper = new(conn, true, builder.ConnectionString); - using SqlCommand cmd = conn.CreateCommand(); - cmd.CommandText = "SELECT @@SPID"; - wrapper.KillConnectionByTSql(); - bool cmdSuccess = false; - try - { - cmd.ExecuteScalar(); - cmdSuccess = true; - } - // Windows always throws SqlException. Unix sometimes throws AggregateException against Azure SQL DB. - catch (Exception ex) when (ex is SqlException || ex is AggregateException) { } - Assert.False(cmdSuccess); - } - - builder.ConnectRetryCount = 2; - // Also check SPID changes with connection resiliency - using (SqlConnection conn = new(builder.ConnectionString)) - { - conn.Open(); - int clientSPID = conn.ServerProcessId; - int serverSPID = 0; - InternalConnectionWrapper wrapper = new(conn, true, builder.ConnectionString); - using SqlCommand cmd = conn.CreateCommand(); - cmd.CommandText = "SELECT @@SPID"; - using (SqlDataReader reader = cmd.ExecuteReader()) - while (reader.Read()) - { - serverSPID = reader.GetInt16(0); - } - - Assert.Equal(serverSPID, clientSPID); - // Also check SPID after query execution - Assert.Equal(serverSPID, conn.ServerProcessId); - - wrapper.KillConnectionByTSql(); - - // Connection resiliency should reconnect transparently - using (SqlDataReader reader = cmd.ExecuteReader()) - while (reader.Read()) - { - serverSPID = reader.GetInt16(0); - } - - // SPID should match server's SPID - Assert.Equal(serverSPID, conn.ServerProcessId); - } - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsTCPConnectionStringPasswordIncluded))] - public static void ConnectionStringPersistentInfoTest() - { - SqlConnectionStringBuilder connectionStringBuilder = new(DataTestUtility.TCPConnectionString) - { - PersistSecurityInfo = false - }; - string cnnString = connectionStringBuilder.ConnectionString; - - connectionStringBuilder.Clear(); - using (SqlConnection sqlCnn = new(cnnString)) - { - sqlCnn.Open(); - connectionStringBuilder.ConnectionString = sqlCnn.ConnectionString; - Assert.True(string.IsNullOrEmpty(connectionStringBuilder.Password), "Password must not persist according to set the PersistSecurityInfo by false!"); - } - - connectionStringBuilder.ConnectionString = DataTestUtility.TCPConnectionString; - connectionStringBuilder.PersistSecurityInfo = true; - cnnString = connectionStringBuilder.ConnectionString; - - connectionStringBuilder.Clear(); - using (SqlConnection sqlCnn = new(cnnString)) - { - sqlCnn.Open(); - connectionStringBuilder.ConnectionString = sqlCnn.ConnectionString; - Assert.True(!string.IsNullOrEmpty(connectionStringBuilder.Password), "Password must persist according to set the PersistSecurityInfo by true!"); - } - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public static void ConnectionOpenDisableRetry() - { - SqlConnectionStringBuilder connectionStringBuilder = new(DataTestUtility.TCPConnectionString) - { - InitialCatalog = "DoesNotExist0982532435423", - Pooling = false, - ConnectTimeout=15 - }; - using SqlConnection sqlConnection = new(connectionStringBuilder.ConnectionString); - Stopwatch timer = new(); - - timer.Start(); - Assert.Throws(() => sqlConnection.Open(SqlConnectionOverrides.OpenWithoutRetry)); - timer.Stop(); - TimeSpan duration = timer.Elapsed; - Assert.True(duration.Seconds < 2, $"Connection Open() without retries took longer than expected. Expected < 2 sec. Took {duration.Seconds} sec."); - - timer.Restart(); - Assert.Throws(() => sqlConnection.Open()); - timer.Stop(); - duration = timer.Elapsed; - Assert.True(duration.Seconds > 5, $"Connection Open() with retries took less time than expected. Expect > 5 sec with transient fault handling. Took {duration.Seconds} sec."); // sqlConnection.Open(); - } - - private const string ConnectToPath = "SOFTWARE\\Microsoft\\MSSQLServer\\Client\\ConnectTo"; - private static bool CanCreateAliases() - { - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || - !DataTestUtility.IsTCPConnStringSetup()) - { - return false; - } - - using (WindowsIdentity identity = WindowsIdentity.GetCurrent()) - { - WindowsPrincipal principal = new(identity); - if (!principal.IsInRole(WindowsBuiltInRole.Administrator)) - { - return false; - } - } - - using RegistryKey key = Registry.LocalMachine.OpenSubKey(ConnectToPath, true); - if (key == null) - { - // Registry not writable - return false; - } - - SqlConnectionStringBuilder b = new(DataTestUtility.TCPConnectionString); - if (!DataTestUtility.ParseDataSource(b.DataSource, out string hostname, out int port, out string instanceName) || - !string.IsNullOrEmpty(instanceName)) - { - return false; - } - - return true; - } - - [PlatformSpecific(TestPlatforms.Windows)] - [ConditionalFact(nameof(CanCreateAliases))] - public static void ConnectionAliasTest() - { - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - throw new Exception("Alias test only valid on Windows"); - } - - if (!CanCreateAliases()) - { - throw new Exception("Unable to create aliases in this environment. Windows + Admin + non-instance data source required."); - } - - SqlConnectionStringBuilder b = new(DataTestUtility.TCPConnectionString); - if (!DataTestUtility.ParseDataSource(b.DataSource, out string hostname, out int port, out string instanceName) || - !string.IsNullOrEmpty(instanceName)) - { - // Only works with connection strings that parse successfully and don't include an instance name - throw new Exception("Unable to create aliases in this configuration. Parsable data source without instance required."); - } - - b.DataSource = "TESTALIAS-" + Guid.NewGuid().ToString().Replace("-", ""); - using RegistryKey key = Registry.LocalMachine.OpenSubKey(ConnectToPath, true); - key.SetValue(b.DataSource, "DBMSSOCN," + hostname + "," + (port == -1 ? 1433 : port)); - try - { - using SqlConnection sqlConnection = new(b.ConnectionString); - sqlConnection.Open(); - } - finally - { - key.DeleteValue(b.DataSource); - } - } - - private static bool CanUseDacConnection() - { - if (!DataTestUtility.IsTCPConnStringSetup()) - { - return false; - } - - SqlConnectionStringBuilder b = new(DataTestUtility.TCPConnectionString); - if (!DataTestUtility.ParseDataSource(b.DataSource, out string hostname, out int port, out string instanceName)) - { - return false; - } - - if ("localhost".Equals(hostname.ToLower()) && (port.Equals(-1) || port.Equals(1433)) && - string.IsNullOrEmpty(instanceName) && b.UserID != null && b.UserID.ToLower().Equals("sa")) - { - return true; - } - - return false; - } - - [ConditionalFact(nameof(CanUseDacConnection))] - public static void DacConnectionTest() - { - if (!CanUseDacConnection()) - { - throw new Exception("Unable to use a DAC connection in this environment. Localhost + sa credentials required."); - } - - SqlConnectionStringBuilder b = new(DataTestUtility.TCPConnectionString); - b.DataSource = "admin:localhost"; - using SqlConnection sqlConnection = new(b.ConnectionString); - sqlConnection.Open(); - } - } -} +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. + +//using System; +//using System.Collections.Generic; +//using System.Diagnostics; +//using System.Runtime.InteropServices; +//using System.Security.Principal; +//using System.Threading; +//using Microsoft.Win32; +//using Xunit; + +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ +// public static class ConnectivityTest +// { +// private const string COL_SPID = "SPID"; +// private const string COL_PROGRAM_NAME = "ProgramName"; +// private const string COL_HOSTNAME = "HostName"; +// private static readonly string s_databaseName = "d_" + Guid.NewGuid().ToString().Replace('-', '_'); +// private static readonly string s_tableName = DataTestUtility.GenerateObjectName(); +// private static readonly string s_connectionString = DataTestUtility.TCPConnectionString; +// private static readonly string s_dbConnectionString = new SqlConnectionStringBuilder(s_connectionString) { InitialCatalog = s_databaseName }.ConnectionString; +// private static readonly string s_createDatabaseCmd = $"CREATE DATABASE {s_databaseName}"; +// private static readonly string s_createTableCmd = $"CREATE TABLE {s_tableName} (NAME NVARCHAR(40), AGE INT)"; +// private static readonly string s_alterDatabaseSingleCmd = $"ALTER DATABASE {s_databaseName} SET SINGLE_USER WITH ROLLBACK IMMEDIATE;"; +// private static readonly string s_alterDatabaseMultiCmd = $"ALTER DATABASE {s_databaseName} SET MULTI_USER WITH ROLLBACK IMMEDIATE;"; +// private static readonly string s_selectTableCmd = $"SELECT COUNT(*) FROM {s_tableName}"; +// private static readonly string s_dropDatabaseCmd = $"DROP DATABASE {s_databaseName}"; + +// // Synapse: Stored procedure sp_who2 does not exist or is not supported. +// // Synapse: SqlConnection.ServerProcessId is always retrieved as 0. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public static void EnvironmentHostNameSPIDTest() +// { +// SqlConnectionStringBuilder builder = new(DataTestUtility.TCPConnectionString) +// { +// Pooling = true, +// ApplicationName = "HostNameTest" +// }; + +// using (SqlConnection sqlConnection = new(builder.ConnectionString)) +// { +// sqlConnection.Open(); +// int sqlClientSPID = sqlConnection.ServerProcessId; +// int sessionSpid; + +// using (SqlCommand cmd = new("SELECT @@SPID", sqlConnection)) +// using (SqlDataReader reader = cmd.ExecuteReader()) +// { +// reader.Read(); +// sessionSpid = reader.GetInt16(0); +// } + +// // Confirm Server process id is same as result of SELECT @@SPID +// Assert.Equal(sessionSpid, sqlClientSPID); + +// // Confirm once again SPID on SqlConnection directly +// Assert.Equal(sessionSpid, sqlConnection.ServerProcessId); + +// using (SqlCommand command = new("sp_who2", sqlConnection)) +// using (SqlDataReader reader = command.ExecuteReader()) +// { +// while (reader.Read()) +// { +// int programNameOrdinal = reader.GetOrdinal(COL_PROGRAM_NAME); +// string programName = reader.GetString(programNameOrdinal); + +// int spidOrdinal = reader.GetOrdinal(COL_SPID); +// string spid = reader.GetString(spidOrdinal); + +// if (programName != null && programName.Trim().Equals(builder.ApplicationName) && short.Parse(spid) == sessionSpid) +// { +// // Get the hostname +// int hostnameOrdinal = reader.GetOrdinal(COL_HOSTNAME); +// string hostnameFromServer = reader.GetString(hostnameOrdinal); +// string expectedMachineName = Environment.MachineName.ToUpper(); +// string hostNameFromServer = hostnameFromServer.Trim().ToUpper(); +// Assert.Matches(expectedMachineName, hostNameFromServer); +// return; +// } +// } +// } +// // Confirm Server Process Id stays the same after query execution +// Assert.Equal(sessionSpid, sqlConnection.ServerProcessId); +// } +// Assert.True(false, "No non-empty hostname found for the application"); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public static async void ConnectionTimeoutInfiniteTest() +// { +// // Exercise the special-case infinite connect timeout code path +// SqlConnectionStringBuilder builder = new(DataTestUtility.TCPConnectionString) +// { +// ConnectTimeout = 0 // Infinite +// }; + +// using SqlConnection conn = new(builder.ConnectionString); +// CancellationTokenSource cts = new(30000); +// // Will throw TaskCanceledException and fail the test in the event of a hang +// await conn.OpenAsync(cts.Token); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public static void ConnectionTimeoutTestWithThread() +// { +// const int timeoutSec = 5; +// const int numOfTry = 2; +// const int numOfThreads = 5; + +// SqlConnectionStringBuilder builder = new(DataTestUtility.TCPConnectionString) +// { +// DataSource = "invalidhost", +// ConnectTimeout = timeoutSec +// }; +// string connStrNotAvailable = builder.ConnectionString; + +// for (int i = 0; i < numOfThreads; ++i) +// { +// new ConnectionWorker(connStrNotAvailable, numOfTry); +// } + +// ConnectionWorker.Start(); +// ConnectionWorker.Stop(); + +// double timeTotal = 0; + +// foreach (ConnectionWorker w in ConnectionWorker.WorkerList) +// { +// timeTotal += w.TimeElapsed; +// } +// double timeElapsed = timeTotal / Convert.ToDouble(ConnectionWorker.WorkerList.Count); +// int threshold = timeoutSec * numOfTry * 2 * 1000; + +// Assert.True(timeElapsed < threshold); +// } + +// // Synapse: Catalog view 'sysprocesses' is not supported in this version. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public static void LocalProcessIdTest() +// { +// SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString); +// string sqlProviderName = builder.ApplicationName; +// string sqlProviderProcessID = Process.GetCurrentProcess().Id.ToString(); + +// using (SqlConnection sqlConnection = new SqlConnection(builder.ConnectionString)) +// { +// sqlConnection.Open(); +// string strCommand = $"SELECT PROGRAM_NAME,HOSTPROCESS FROM SYS.SYSPROCESSES WHERE PROGRAM_NAME LIKE ('%{sqlProviderName}%')"; +// using (SqlCommand command = new SqlCommand(strCommand, sqlConnection)) +// { +// using (SqlDataReader reader = command.ExecuteReader()) +// { +// bool processIdFound = false; +// while (reader.Read()) +// { +// Assert.Equal(sqlProviderName, reader.GetString(0).Trim()); +// if (sqlProviderProcessID == reader.GetString(1).Trim()) +// { +// processIdFound = true; +// } +// } +// Assert.True(processIdFound); +// } +// } +// } +// } +// public class ConnectionWorker : IDisposable +// { +// private static List s_workerList = new(); +// private ManualResetEventSlim _doneEvent = new(false); +// private double _timeElapsed; +// private Thread _thread; +// private string _connectionString; +// private int _numOfTry; + +// public ConnectionWorker(string connectionString, int numOfTry) +// { +// s_workerList.Add(this); +// _connectionString = connectionString; +// _numOfTry = numOfTry; +// _thread = new Thread(new ThreadStart(SqlConnectionOpen)); +// } + +// public static List WorkerList => s_workerList; + +// public double TimeElapsed => _timeElapsed; + +// public static void Start() +// { +// foreach (ConnectionWorker w in s_workerList) +// { +// w._thread.Start(); +// } +// } + +// public static void Stop() +// { +// foreach (ConnectionWorker w in s_workerList) +// { +// w._doneEvent.Wait(); +// } +// } + +// public void Dispose() +// { +// Dispose(true); +// GC.SuppressFinalize(this); +// } + +// protected virtual void Dispose(bool disposing) +// { +// if (disposing) +// { +// _doneEvent.Dispose(); +// } +// } + +// public void SqlConnectionOpen() +// { +// Stopwatch sw = new Stopwatch(); +// double totalTime = 0; +// for (int i = 0; i < _numOfTry; ++i) +// { +// using (SqlConnection con = new(_connectionString)) +// { +// sw.Start(); +// try +// { +// con.Open(); +// } +// catch { } +// sw.Stop(); +// } +// totalTime += sw.Elapsed.TotalMilliseconds; +// sw.Reset(); +// } +// _timeElapsed = totalTime / Convert.ToDouble(_numOfTry); + +// _doneEvent.Set(); +// } +// } + +// // Synapse: Parse error at line: 1, column: 59: Incorrect syntax near 'SINGLE_USER' - No support for MULTI_USER +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureServer))] +// public static void ConnectionKilledTest() +// { +// try +// { +// // Setup Database and Table. +// DataTestUtility.RunNonQuery(s_connectionString, s_createDatabaseCmd); +// DataTestUtility.RunNonQuery(s_dbConnectionString, s_createTableCmd); + +// // Kill all the connections and set Database to SINGLE_USER Mode. +// DataTestUtility.RunNonQuery(s_connectionString, s_alterDatabaseSingleCmd, 4); +// // Set Database back to MULTI_USER Mode +// DataTestUtility.RunNonQuery(s_connectionString, s_alterDatabaseMultiCmd, 4); + +// // Execute SELECT statement. +// DataTestUtility.RunNonQuery(s_dbConnectionString, s_selectTableCmd); +// } +// finally +// { +// // Kill all the connections, set Database to SINGLE_USER Mode and drop Database +// DataTestUtility.RunNonQuery(s_connectionString, s_alterDatabaseSingleCmd, 4); +// DataTestUtility.RunNonQuery(s_connectionString, s_dropDatabaseCmd, 4); +// } +// } + +// // Synapse: KILL not supported on Azure Synapse - Parse error at line: 1, column: 6: Incorrect syntax near '105'. +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// public static void ConnectionResiliencySPIDTest() +// { +// SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) +// { +// ConnectRetryCount = 0, +// ConnectRetryInterval = 5 +// }; + +// // No connection resiliency +// using (SqlConnection conn = new(builder.ConnectionString)) +// { +// conn.Open(); +// InternalConnectionWrapper wrapper = new(conn, true, builder.ConnectionString); +// using SqlCommand cmd = conn.CreateCommand(); +// cmd.CommandText = "SELECT @@SPID"; +// wrapper.KillConnectionByTSql(); +// bool cmdSuccess = false; +// try +// { +// cmd.ExecuteScalar(); +// cmdSuccess = true; +// } +// // Windows always throws SqlException. Unix sometimes throws AggregateException against Azure SQL DB. +// catch (Exception ex) when (ex is SqlException || ex is AggregateException) { } +// Assert.False(cmdSuccess); +// } + +// builder.ConnectRetryCount = 2; +// // Also check SPID changes with connection resiliency +// using (SqlConnection conn = new(builder.ConnectionString)) +// { +// conn.Open(); +// int clientSPID = conn.ServerProcessId; +// int serverSPID = 0; +// InternalConnectionWrapper wrapper = new(conn, true, builder.ConnectionString); +// using SqlCommand cmd = conn.CreateCommand(); +// cmd.CommandText = "SELECT @@SPID"; +// using (SqlDataReader reader = cmd.ExecuteReader()) +// while (reader.Read()) +// { +// serverSPID = reader.GetInt16(0); +// } + +// Assert.Equal(serverSPID, clientSPID); +// // Also check SPID after query execution +// Assert.Equal(serverSPID, conn.ServerProcessId); + +// wrapper.KillConnectionByTSql(); + +// // Connection resiliency should reconnect transparently +// using (SqlDataReader reader = cmd.ExecuteReader()) +// while (reader.Read()) +// { +// serverSPID = reader.GetInt16(0); +// } + +// // SPID should match server's SPID +// Assert.Equal(serverSPID, conn.ServerProcessId); +// } +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsTCPConnectionStringPasswordIncluded))] +// public static void ConnectionStringPersistentInfoTest() +// { +// SqlConnectionStringBuilder connectionStringBuilder = new(DataTestUtility.TCPConnectionString) +// { +// PersistSecurityInfo = false +// }; +// string cnnString = connectionStringBuilder.ConnectionString; + +// connectionStringBuilder.Clear(); +// using (SqlConnection sqlCnn = new(cnnString)) +// { +// sqlCnn.Open(); +// connectionStringBuilder.ConnectionString = sqlCnn.ConnectionString; +// Assert.True(string.IsNullOrEmpty(connectionStringBuilder.Password), "Password must not persist according to set the PersistSecurityInfo by false!"); +// } + +// connectionStringBuilder.ConnectionString = DataTestUtility.TCPConnectionString; +// connectionStringBuilder.PersistSecurityInfo = true; +// cnnString = connectionStringBuilder.ConnectionString; + +// connectionStringBuilder.Clear(); +// using (SqlConnection sqlCnn = new(cnnString)) +// { +// sqlCnn.Open(); +// connectionStringBuilder.ConnectionString = sqlCnn.ConnectionString; +// Assert.True(!string.IsNullOrEmpty(connectionStringBuilder.Password), "Password must persist according to set the PersistSecurityInfo by true!"); +// } +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public static void ConnectionOpenDisableRetry() +// { +// SqlConnectionStringBuilder connectionStringBuilder = new(DataTestUtility.TCPConnectionString) +// { +// InitialCatalog = "DoesNotExist0982532435423", +// Pooling = false, +// ConnectTimeout=15 +// }; +// using SqlConnection sqlConnection = new(connectionStringBuilder.ConnectionString); +// Stopwatch timer = new(); + +// timer.Start(); +// Assert.Throws(() => sqlConnection.Open(SqlConnectionOverrides.OpenWithoutRetry)); +// timer.Stop(); +// TimeSpan duration = timer.Elapsed; +// Assert.True(duration.Seconds < 2, $"Connection Open() without retries took longer than expected. Expected < 2 sec. Took {duration.Seconds} sec."); + +// timer.Restart(); +// Assert.Throws(() => sqlConnection.Open()); +// timer.Stop(); +// duration = timer.Elapsed; +// Assert.True(duration.Seconds > 5, $"Connection Open() with retries took less time than expected. Expect > 5 sec with transient fault handling. Took {duration.Seconds} sec."); // sqlConnection.Open(); +// } + +// private const string ConnectToPath = "SOFTWARE\\Microsoft\\MSSQLServer\\Client\\ConnectTo"; +// private static bool CanCreateAliases() +// { +// if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || +// !DataTestUtility.IsTCPConnStringSetup()) +// { +// return false; +// } + +// using (WindowsIdentity identity = WindowsIdentity.GetCurrent()) +// { +// WindowsPrincipal principal = new(identity); +// if (!principal.IsInRole(WindowsBuiltInRole.Administrator)) +// { +// return false; +// } +// } + +// using RegistryKey key = Registry.LocalMachine.OpenSubKey(ConnectToPath, true); +// if (key == null) +// { +// // Registry not writable +// return false; +// } + +// SqlConnectionStringBuilder b = new(DataTestUtility.TCPConnectionString); +// if (!DataTestUtility.ParseDataSource(b.DataSource, out string hostname, out int port, out string instanceName) || +// !string.IsNullOrEmpty(instanceName)) +// { +// return false; +// } + +// return true; +// } + +// [PlatformSpecific(TestPlatforms.Windows)] +// [ConditionalFact(nameof(CanCreateAliases))] +// public static void ConnectionAliasTest() +// { +// if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) +// { +// throw new Exception("Alias test only valid on Windows"); +// } + +// if (!CanCreateAliases()) +// { +// throw new Exception("Unable to create aliases in this environment. Windows + Admin + non-instance data source required."); +// } + +// SqlConnectionStringBuilder b = new(DataTestUtility.TCPConnectionString); +// if (!DataTestUtility.ParseDataSource(b.DataSource, out string hostname, out int port, out string instanceName) || +// !string.IsNullOrEmpty(instanceName)) +// { +// // Only works with connection strings that parse successfully and don't include an instance name +// throw new Exception("Unable to create aliases in this configuration. Parsable data source without instance required."); +// } + +// b.DataSource = "TESTALIAS-" + Guid.NewGuid().ToString().Replace("-", ""); +// using RegistryKey key = Registry.LocalMachine.OpenSubKey(ConnectToPath, true); +// key.SetValue(b.DataSource, "DBMSSOCN," + hostname + "," + (port == -1 ? 1433 : port)); +// try +// { +// using SqlConnection sqlConnection = new(b.ConnectionString); +// sqlConnection.Open(); +// } +// finally +// { +// key.DeleteValue(b.DataSource); +// } +// } + +// private static bool CanUseDacConnection() +// { +// if (!DataTestUtility.IsTCPConnStringSetup()) +// { +// return false; +// } + +// SqlConnectionStringBuilder b = new(DataTestUtility.TCPConnectionString); +// if (!DataTestUtility.ParseDataSource(b.DataSource, out string hostname, out int port, out string instanceName)) +// { +// return false; +// } + +// if ("localhost".Equals(hostname.ToLower()) && (port.Equals(-1) || port.Equals(1433)) && +// string.IsNullOrEmpty(instanceName) && b.UserID != null && b.UserID.ToLower().Equals("sa")) +// { +// return true; +// } + +// return false; +// } + +// [ConditionalFact(nameof(CanUseDacConnection))] +// public static void DacConnectionTest() +// { +// if (!CanUseDacConnection()) +// { +// throw new Exception("Unable to use a DAC connection in this environment. Localhost + sa credentials required."); +// } + +// SqlConnectionStringBuilder b = new(DataTestUtility.TCPConnectionString); +// b.DataSource = "admin:localhost"; +// using SqlConnection sqlConnection = new(b.ConnectionString); +// sqlConnection.Open(); +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/TcpDefaultForAzureTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/TcpDefaultForAzureTest.cs index f8271dfdc4..7acac0abd8 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/TcpDefaultForAzureTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/TcpDefaultForAzureTest.cs @@ -1,145 +1,145 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Diagnostics; -using Xunit; - -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ - [OuterLoop("Takes minutes on some networks")] - public static class TcpDefaultForAzureTest - { - private const string NP = "Named Pipes Provider"; - private const string TCP = "TCP Provider"; - private const string InvalidHostname = "invalidHostname"; - private const string ErrorMessage = "A network-related or instance-specific error occurred while establishing a connection to SQL Server."; - - private static string[] AzureExtensions; - private static SqlConnectionStringBuilder builder; - - static TcpDefaultForAzureTest() - { - AzureExtensions = new string[] - { - ".database.windows.net", - ".database.cloudapi.de", - ".database.usgovcloudapi.net", - ".database.chinacloudapi.cn" - }; - - builder = new SqlConnectionStringBuilder(); - builder.ConnectTimeout = 1; - } - - // Synapse: Named Pipes not supported for Azure Synapse - // Expected protocol TCP Provider in the error message, but received: A network-related or instance-specific error occurred while establishing a connection to SQL Server. - // The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. - // (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server) - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - [PlatformSpecific(TestPlatforms.Windows)] - public static void NonAzureNoProtocolConnectionTestWindows() - { - builder.DataSource = InvalidHostname; -#if NETFRAMEWORK - CheckConnectionFailure(builder.ConnectionString, NP); -#else - CheckConnectionFailure(builder.ConnectionString, DataTestUtility.IsUsingManagedSNI() ? TCP : NP); -#endif - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] - [PlatformSpecific(TestPlatforms.Linux)] - public static void NonAzureNoProtocolConnectionTestLinux() - { - builder.DataSource = InvalidHostname; - // On Linux, TCP is the preferred protocol in use. - CheckConnectionFailure(builder.ConnectionString, TCP); - } - - [Fact] - public static void NonAzureTcpConnectionTest() - { - builder.DataSource = "tcp:" + InvalidHostname; - CheckConnectionFailure(builder.ConnectionString, TCP); - } - - [Fact] - [PlatformSpecific(TestPlatforms.Windows)] // NP NonAzure connection fails correctly on Windows - public static void NonAzureNpConnectionTest() - { - builder.DataSource = "np:\\\\" + InvalidHostname + "\\pipe\\sql\\query"; - CheckConnectionFailure(builder.ConnectionString, NP); - } - - [Fact] - public static void AzureNoProtocolConnectionTest() - { - foreach (string extension in AzureExtensions) - { - builder.DataSource = InvalidHostname + extension; - CheckConnectionFailure(builder.ConnectionString, TCP); - } - } - - [Fact] - public static void AzureTcpConnectionTest() - { - foreach (string extension in AzureExtensions) - { - builder.DataSource = "tcp:" + InvalidHostname + extension; - CheckConnectionFailure(builder.ConnectionString, TCP); - } - } - - [Fact] - [PlatformSpecific(TestPlatforms.Windows)] // NP Azure connection fails correctly on Windows - public static void AzureNpConnectionTest() - { - foreach (string extension in AzureExtensions) - { - builder.DataSource = "np:\\\\" + InvalidHostname + extension + "\\pipe\\sql\\query"; - CheckConnectionFailure(builder.ConnectionString, NP); - } - } - - private static void CheckConnectionFailure(string connString, string protocol) - { - Debug.Assert(!string.IsNullOrWhiteSpace(connString)); - - string errorMessage = Connect(connString); - - Assert.True(errorMessage != null, "Did not receive any error message"); - Assert.True(errorMessage.Contains(ErrorMessage), string.Format("Expected error message {0}, but received: {1}", ErrorMessage, errorMessage)); - - if (protocol != null) - { - Assert.True( - errorMessage.Contains(string.Format("provider: {0}, error", protocol)), - string.Format("Expected protocol {0} in the error message, but received: {1}", protocol, errorMessage)); - } - } - - private static string Connect(string connString) - { - Debug.Assert(!string.IsNullOrWhiteSpace(connString)); - - string errorMessage = null; - using (SqlConnection connection = new SqlConnection(connString)) - { - try - { - connection.Open(); - connection.Close(); - } - catch (Exception e) - { - errorMessage = e.Message; - } - } - - return errorMessage; - } - } -} +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. + +//using System; +//using System.Diagnostics; +//using Xunit; + +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ +// [OuterLoop("Takes minutes on some networks")] +// public static class TcpDefaultForAzureTest +// { +// private const string NP = "Named Pipes Provider"; +// private const string TCP = "TCP Provider"; +// private const string InvalidHostname = "invalidHostname"; +// private const string ErrorMessage = "A network-related or instance-specific error occurred while establishing a connection to SQL Server."; + +// private static string[] AzureExtensions; +// private static SqlConnectionStringBuilder builder; + +// static TcpDefaultForAzureTest() +// { +// AzureExtensions = new string[] +// { +// ".database.windows.net", +// ".database.cloudapi.de", +// ".database.usgovcloudapi.net", +// ".database.chinacloudapi.cn" +// }; + +// builder = new SqlConnectionStringBuilder(); +// builder.ConnectTimeout = 1; +// } + +// // Synapse: Named Pipes not supported for Azure Synapse +// // Expected protocol TCP Provider in the error message, but received: A network-related or instance-specific error occurred while establishing a connection to SQL Server. +// // The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. +// // (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server) +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// [PlatformSpecific(TestPlatforms.Windows)] +// public static void NonAzureNoProtocolConnectionTestWindows() +// { +// builder.DataSource = InvalidHostname; +//#if NETFRAMEWORK +// CheckConnectionFailure(builder.ConnectionString, NP); +//#else +// CheckConnectionFailure(builder.ConnectionString, DataTestUtility.IsUsingManagedSNI() ? TCP : NP); +//#endif +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] +// [PlatformSpecific(TestPlatforms.Linux)] +// public static void NonAzureNoProtocolConnectionTestLinux() +// { +// builder.DataSource = InvalidHostname; +// // On Linux, TCP is the preferred protocol in use. +// CheckConnectionFailure(builder.ConnectionString, TCP); +// } + +// [Fact] +// public static void NonAzureTcpConnectionTest() +// { +// builder.DataSource = "tcp:" + InvalidHostname; +// CheckConnectionFailure(builder.ConnectionString, TCP); +// } + +// [Fact] +// [PlatformSpecific(TestPlatforms.Windows)] // NP NonAzure connection fails correctly on Windows +// public static void NonAzureNpConnectionTest() +// { +// builder.DataSource = "np:\\\\" + InvalidHostname + "\\pipe\\sql\\query"; +// CheckConnectionFailure(builder.ConnectionString, NP); +// } + +// [Fact] +// public static void AzureNoProtocolConnectionTest() +// { +// foreach (string extension in AzureExtensions) +// { +// builder.DataSource = InvalidHostname + extension; +// CheckConnectionFailure(builder.ConnectionString, TCP); +// } +// } + +// [Fact] +// public static void AzureTcpConnectionTest() +// { +// foreach (string extension in AzureExtensions) +// { +// builder.DataSource = "tcp:" + InvalidHostname + extension; +// CheckConnectionFailure(builder.ConnectionString, TCP); +// } +// } + +// [Fact] +// [PlatformSpecific(TestPlatforms.Windows)] // NP Azure connection fails correctly on Windows +// public static void AzureNpConnectionTest() +// { +// foreach (string extension in AzureExtensions) +// { +// builder.DataSource = "np:\\\\" + InvalidHostname + extension + "\\pipe\\sql\\query"; +// CheckConnectionFailure(builder.ConnectionString, NP); +// } +// } + +// private static void CheckConnectionFailure(string connString, string protocol) +// { +// Debug.Assert(!string.IsNullOrWhiteSpace(connString)); + +// string errorMessage = Connect(connString); + +// Assert.True(errorMessage != null, "Did not receive any error message"); +// Assert.True(errorMessage.Contains(ErrorMessage), string.Format("Expected error message {0}, but received: {1}", ErrorMessage, errorMessage)); + +// if (protocol != null) +// { +// Assert.True( +// errorMessage.Contains(string.Format("provider: {0}, error", protocol)), +// string.Format("Expected protocol {0} in the error message, but received: {1}", protocol, errorMessage)); +// } +// } + +// private static string Connect(string connString) +// { +// Debug.Assert(!string.IsNullOrWhiteSpace(connString)); + +// string errorMessage = null; +// using (SqlConnection connection = new SqlConnection(connString)) +// { +// try +// { +// connection.Open(); +// connection.Close(); +// } +// catch (Exception e) +// { +// errorMessage = e.Message; +// } +// } + +// return errorMessage; +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DNSCachingTest/DNSCachingTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DNSCachingTest/DNSCachingTest.cs index a23efff073..9ede0d130a 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DNSCachingTest/DNSCachingTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DNSCachingTest/DNSCachingTest.cs @@ -1,78 +1,78 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. -using System; -using System.Collections.Generic; -using System.Reflection; -using Xunit; +//using System; +//using System.Collections.Generic; +//using System.Reflection; +//using Xunit; -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ - public class DNSCachingTest - { - public static Assembly systemData = Assembly.GetAssembly(typeof(SqlConnection)); - public static Type SQLFallbackDNSCacheType = systemData.GetType("Microsoft.Data.SqlClient.SQLFallbackDNSCache"); - public static Type SQLDNSInfoType = systemData.GetType("Microsoft.Data.SqlClient.SQLDNSInfo"); - public static MethodInfo SQLFallbackDNSCacheGetDNSInfo = SQLFallbackDNSCacheType.GetMethod("GetDNSInfo", BindingFlags.Instance | BindingFlags.NonPublic); +// public class DNSCachingTest +// { +// public static Assembly systemData = Assembly.GetAssembly(typeof(SqlConnection)); +// public static Type SQLFallbackDNSCacheType = systemData.GetType("Microsoft.Data.SqlClient.SQLFallbackDNSCache"); +// public static Type SQLDNSInfoType = systemData.GetType("Microsoft.Data.SqlClient.SQLDNSInfo"); +// public static MethodInfo SQLFallbackDNSCacheGetDNSInfo = SQLFallbackDNSCacheType.GetMethod("GetDNSInfo", BindingFlags.Instance | BindingFlags.NonPublic); - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsDNSCachingSetup))] - public void DNSCachingIsSupportedFlag() - { - string expectedDNSCachingSupportedCR = DataTestUtility.IsDNSCachingSupportedCR ? "true" : "false"; - string expectedDNSCachingSupportedTR = DataTestUtility.IsDNSCachingSupportedTR ? "true" : "false"; +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsDNSCachingSetup))] +// public void DNSCachingIsSupportedFlag() +// { +// string expectedDNSCachingSupportedCR = DataTestUtility.IsDNSCachingSupportedCR ? "true" : "false"; +// string expectedDNSCachingSupportedTR = DataTestUtility.IsDNSCachingSupportedTR ? "true" : "false"; - using(SqlConnection connection = new SqlConnection(DataTestUtility.DNSCachingConnString)) - { - connection.Open(); +// using(SqlConnection connection = new SqlConnection(DataTestUtility.DNSCachingConnString)) +// { +// connection.Open(); - IDictionary dictionary = connection.RetrieveInternalInfo(); - bool ret = dictionary.TryGetValue("SQLDNSCachingSupportedState", out object val); - ret = dictionary.TryGetValue("SQLDNSCachingSupportedStateBeforeRedirect", out object valBeforeRedirect); - string isSupportedStateTR = (string)val; - string isSupportedStateCR = (string)valBeforeRedirect; - Assert.Equal(expectedDNSCachingSupportedCR, isSupportedStateCR); - Assert.Equal(expectedDNSCachingSupportedTR, isSupportedStateTR); - } - } +// IDictionary dictionary = connection.RetrieveInternalInfo(); +// bool ret = dictionary.TryGetValue("SQLDNSCachingSupportedState", out object val); +// ret = dictionary.TryGetValue("SQLDNSCachingSupportedStateBeforeRedirect", out object valBeforeRedirect); +// string isSupportedStateTR = (string)val; +// string isSupportedStateCR = (string)valBeforeRedirect; +// Assert.Equal(expectedDNSCachingSupportedCR, isSupportedStateCR); +// Assert.Equal(expectedDNSCachingSupportedTR, isSupportedStateTR); +// } +// } - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsDNSCachingSetup))] - public void DNSCachingGetDNSInfo() - { - using(SqlConnection connection = new SqlConnection(DataTestUtility.DNSCachingConnString)) - { - connection.Open(); - } +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsDNSCachingSetup))] +// public void DNSCachingGetDNSInfo() +// { +// using(SqlConnection connection = new SqlConnection(DataTestUtility.DNSCachingConnString)) +// { +// connection.Open(); +// } - var SQLFallbackDNSCacheInstance = SQLFallbackDNSCacheType.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public).GetValue(null); +// var SQLFallbackDNSCacheInstance = SQLFallbackDNSCacheType.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public).GetValue(null); - var serverList = new List>(); - serverList.Add(new KeyValuePair(DataTestUtility.DNSCachingServerCR, DataTestUtility.IsDNSCachingSupportedCR)); - serverList.Add(new KeyValuePair(DataTestUtility.DNSCachingServerTR, DataTestUtility.IsDNSCachingSupportedTR)); +// var serverList = new List>(); +// serverList.Add(new KeyValuePair(DataTestUtility.DNSCachingServerCR, DataTestUtility.IsDNSCachingSupportedCR)); +// serverList.Add(new KeyValuePair(DataTestUtility.DNSCachingServerTR, DataTestUtility.IsDNSCachingSupportedTR)); - foreach(var server in serverList) - { - object[] parameters; - bool ret; +// foreach(var server in serverList) +// { +// object[] parameters; +// bool ret; - if (!string.IsNullOrEmpty(server.Key)) - { - parameters = new object[] { server.Key, null }; - ret = (bool)SQLFallbackDNSCacheGetDNSInfo.Invoke(SQLFallbackDNSCacheInstance, parameters); +// if (!string.IsNullOrEmpty(server.Key)) +// { +// parameters = new object[] { server.Key, null }; +// ret = (bool)SQLFallbackDNSCacheGetDNSInfo.Invoke(SQLFallbackDNSCacheInstance, parameters); - if (server.Value) - { - Assert.NotNull(parameters[1]); - Assert.Equal(server.Key, (string)SQLDNSInfoType.GetProperty("FQDN").GetValue(parameters[1])); - } - else - { - Assert.Null(parameters[1]); - } - } - } - } - } -} +// if (server.Value) +// { +// Assert.NotNull(parameters[1]); +// Assert.Equal(server.Key, (string)SQLDNSInfoType.GetProperty("FQDN").GetValue(parameters[1])); +// } +// else +// { +// Assert.Null(parameters[1]); +// } +// } +// } +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataBaseSchemaTest/ConnectionSchemaTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataBaseSchemaTest/ConnectionSchemaTest.cs index 283ddc5c63..78f65ac1c2 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataBaseSchemaTest/ConnectionSchemaTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataBaseSchemaTest/ConnectionSchemaTest.cs @@ -1,129 +1,129 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using System.Data; -using Xunit; - -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ - public static class ConnectionSchemaTest - { - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public static void GetTablesFromSchema() - { - VerifySchemaTable(SqlClientMetaDataCollectionNames.Tables, new string[] { "TABLE_CATALOG", "TABLE_SCHEMA", "TABLE_NAME", "TABLE_TYPE" }); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public static void GetProceduresFromSchema() - { - VerifySchemaTable(SqlClientMetaDataCollectionNames.Procedures, new string[] { "ROUTINE_SCHEMA", "ROUTINE_NAME", "ROUTINE_TYPE" }); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public static void GetProcedureParametersFromSchema() - { - VerifySchemaTable(SqlClientMetaDataCollectionNames.ProcedureParameters, new string[] { "PARAMETER_MODE", "PARAMETER_NAME" }); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public static void GetDatabasesFromSchema() - { - VerifySchemaTable(SqlClientMetaDataCollectionNames.Databases, new string[] { "database_name", "dbid", "create_date" }); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public static void GetForeignKeysFromSchema() - { - VerifySchemaTable(SqlClientMetaDataCollectionNames.ForeignKeys, new string[] { "CONSTRAINT_TYPE", "IS_DEFERRABLE", "INITIALLY_DEFERRED" }); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public static void GetIndexesFromSchema() - { - VerifySchemaTable(SqlClientMetaDataCollectionNames.Indexes, new string[] { "index_name", "constraint_name" }); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public static void GetIndexColumnsFromSchema() - { - VerifySchemaTable(SqlClientMetaDataCollectionNames.IndexColumns, new string[] { "index_name", "KeyType", "column_name" }); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public static void GetColumnsFromSchema() - { - VerifySchemaTable(SqlClientMetaDataCollectionNames.Columns, new string[] { "IS_NULLABLE", "COLUMN_DEFAULT" }); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public static void GetAllColumnsFromSchema() - { - VerifySchemaTable(SqlClientMetaDataCollectionNames.AllColumns, new string[] { "IS_NULLABLE", "COLUMN_DEFAULT", "IS_FILESTREAM", "IS_SPARSE", "IS_COLUMN_SET" }); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public static void GetColumnSetColumnsFromSchema() - { - VerifySchemaTable(SqlClientMetaDataCollectionNames.ColumnSetColumns, new string[] { "IS_NULLABLE", "COLUMN_DEFAULT", "IS_FILESTREAM", "IS_SPARSE", "IS_COLUMN_SET" }); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public static void GetUsersFromSchema() - { - VerifySchemaTable(SqlClientMetaDataCollectionNames.Users, new string[] { "uid", "user_name" }); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public static void GetViewsFromSchema() - { - VerifySchemaTable(SqlClientMetaDataCollectionNames.Views, new string[] { "TABLE_NAME", "CHECK_OPTION", "IS_UPDATABLE" }); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public static void GetViewColumnsFromSchema() - { - VerifySchemaTable(SqlClientMetaDataCollectionNames.ViewColumns, new string[] { "VIEW_CATALOG", "VIEW_SCHEMA", "VIEW_NAME" }); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public static void GetUserDefinedTypesFromSchema() - { - VerifySchemaTable(SqlClientMetaDataCollectionNames.UserDefinedTypes, new string[] { "assembly_name", "version_revision", "culture_info" }); - } - - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - public static void GetStructuredTypeMembersFromSchema() - { - VerifySchemaTable(SqlClientMetaDataCollectionNames.StructuredTypeMembers, new string[] { "TYPE_CATALOG", "TYPE_SCHEMA", "TYPE_NAME", "MEMBER_NAME", "ORDINAL_POSITION" }); - } - - private static void VerifySchemaTable(string schemaItemName, string[] testColumnNames) - { - SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) - { - InitialCatalog = "master" - }; - - using (SqlConnection connection = new SqlConnection(builder.ConnectionString)) - { - // Connect to the database then retrieve the schema information - connection.Open(); - DataTable table = connection.GetSchema(schemaItemName); - - // Get all table columns - HashSet columnNames = new HashSet(); - - foreach (DataColumn column in table.Columns) - { - columnNames.Add(column.ColumnName); - } - - Assert.All(testColumnNames, column => Assert.Contains(column, columnNames)); - } - } - } -} +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. + +//using System.Collections.Generic; +//using System.Data; +//using Xunit; + +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ +// public static class ConnectionSchemaTest +// { + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public static void GetTablesFromSchema() +// { +// VerifySchemaTable(SqlClientMetaDataCollectionNames.Tables, new string[] { "TABLE_CATALOG", "TABLE_SCHEMA", "TABLE_NAME", "TABLE_TYPE" }); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public static void GetProceduresFromSchema() +// { +// VerifySchemaTable(SqlClientMetaDataCollectionNames.Procedures, new string[] { "ROUTINE_SCHEMA", "ROUTINE_NAME", "ROUTINE_TYPE" }); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public static void GetProcedureParametersFromSchema() +// { +// VerifySchemaTable(SqlClientMetaDataCollectionNames.ProcedureParameters, new string[] { "PARAMETER_MODE", "PARAMETER_NAME" }); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public static void GetDatabasesFromSchema() +// { +// VerifySchemaTable(SqlClientMetaDataCollectionNames.Databases, new string[] { "database_name", "dbid", "create_date" }); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public static void GetForeignKeysFromSchema() +// { +// VerifySchemaTable(SqlClientMetaDataCollectionNames.ForeignKeys, new string[] { "CONSTRAINT_TYPE", "IS_DEFERRABLE", "INITIALLY_DEFERRED" }); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public static void GetIndexesFromSchema() +// { +// VerifySchemaTable(SqlClientMetaDataCollectionNames.Indexes, new string[] { "index_name", "constraint_name" }); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public static void GetIndexColumnsFromSchema() +// { +// VerifySchemaTable(SqlClientMetaDataCollectionNames.IndexColumns, new string[] { "index_name", "KeyType", "column_name" }); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public static void GetColumnsFromSchema() +// { +// VerifySchemaTable(SqlClientMetaDataCollectionNames.Columns, new string[] { "IS_NULLABLE", "COLUMN_DEFAULT" }); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public static void GetAllColumnsFromSchema() +// { +// VerifySchemaTable(SqlClientMetaDataCollectionNames.AllColumns, new string[] { "IS_NULLABLE", "COLUMN_DEFAULT", "IS_FILESTREAM", "IS_SPARSE", "IS_COLUMN_SET" }); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public static void GetColumnSetColumnsFromSchema() +// { +// VerifySchemaTable(SqlClientMetaDataCollectionNames.ColumnSetColumns, new string[] { "IS_NULLABLE", "COLUMN_DEFAULT", "IS_FILESTREAM", "IS_SPARSE", "IS_COLUMN_SET" }); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public static void GetUsersFromSchema() +// { +// VerifySchemaTable(SqlClientMetaDataCollectionNames.Users, new string[] { "uid", "user_name" }); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public static void GetViewsFromSchema() +// { +// VerifySchemaTable(SqlClientMetaDataCollectionNames.Views, new string[] { "TABLE_NAME", "CHECK_OPTION", "IS_UPDATABLE" }); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public static void GetViewColumnsFromSchema() +// { +// VerifySchemaTable(SqlClientMetaDataCollectionNames.ViewColumns, new string[] { "VIEW_CATALOG", "VIEW_SCHEMA", "VIEW_NAME" }); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public static void GetUserDefinedTypesFromSchema() +// { +// VerifySchemaTable(SqlClientMetaDataCollectionNames.UserDefinedTypes, new string[] { "assembly_name", "version_revision", "culture_info" }); +// } + +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] +// public static void GetStructuredTypeMembersFromSchema() +// { +// VerifySchemaTable(SqlClientMetaDataCollectionNames.StructuredTypeMembers, new string[] { "TYPE_CATALOG", "TYPE_SCHEMA", "TYPE_NAME", "MEMBER_NAME", "ORDINAL_POSITION" }); +// } + +// private static void VerifySchemaTable(string schemaItemName, string[] testColumnNames) +// { +// SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) +// { +// InitialCatalog = "master" +// }; + +// using (SqlConnection connection = new SqlConnection(builder.ConnectionString)) +// { +// // Connect to the database then retrieve the schema information +// connection.Open(); +// DataTable table = connection.GetSchema(schemaItemName); + +// // Get all table columns +// HashSet columnNames = new HashSet(); + +// foreach (DataColumn column in table.Columns) +// { +// columnNames.Add(column.ColumnName); +// } + +// Assert.All(testColumnNames, column => Assert.Contains(column, columnNames)); +// } +// } +// } +//} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataClassificationTest/DataClassificationTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataClassificationTest/DataClassificationTest.cs index 8119bd2586..41c205004b 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataClassificationTest/DataClassificationTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataClassificationTest/DataClassificationTest.cs @@ -1,274 +1,274 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. +//// Licensed to the .NET Foundation under one or more agreements. +//// The .NET Foundation licenses this file to you under the MIT license. +//// See the LICENSE file in the project root for more information. -using System; -using System.Collections.ObjectModel; -using System.Data; -using Microsoft.Data.SqlClient.DataClassification; -using Xunit; +//using System; +//using System.Collections.ObjectModel; +//using System.Data; +//using Microsoft.Data.SqlClient.DataClassification; +//using Xunit; -namespace Microsoft.Data.SqlClient.ManualTesting.Tests -{ - public static class DataClassificationTest - { - private static string s_tableName; +//namespace Microsoft.Data.SqlClient.ManualTesting.Tests +//{ +// public static class DataClassificationTest +// { +// private static string s_tableName; - // Synapse: Azure Synapse does not support RANK - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse), nameof(DataTestUtility.IsSupportedDataClassification))] - public static void TestDataClassificationResultSetRank() - { - s_tableName = DataTestUtility.GetUniqueNameForSqlServer("DC"); - using (SqlConnection sqlConnection = new SqlConnection(DataTestUtility.TCPConnectionString)) - using (SqlCommand sqlCommand = sqlConnection.CreateCommand()) - { - try - { - sqlConnection.Open(); - Assert.True(DataTestUtility.IsSupportedDataClassification()); - CreateTable(sqlCommand); - AddSensitivity(sqlCommand, rankEnabled: true); - InsertData(sqlCommand); - RunTestsForServer(sqlCommand, rankEnabled: true); - } - finally - { - DataTestUtility.DropTable(sqlConnection, s_tableName); - } - } - } +// // Synapse: Azure Synapse does not support RANK +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse), nameof(DataTestUtility.IsSupportedDataClassification))] +// public static void TestDataClassificationResultSetRank() +// { +// s_tableName = DataTestUtility.GetUniqueNameForSqlServer("DC"); +// using (SqlConnection sqlConnection = new SqlConnection(DataTestUtility.TCPConnectionString)) +// using (SqlCommand sqlCommand = sqlConnection.CreateCommand()) +// { +// try +// { +// sqlConnection.Open(); +// Assert.True(DataTestUtility.IsSupportedDataClassification()); +// CreateTable(sqlCommand); +// AddSensitivity(sqlCommand, rankEnabled: true); +// InsertData(sqlCommand); +// RunTestsForServer(sqlCommand, rankEnabled: true); +// } +// finally +// { +// DataTestUtility.DropTable(sqlConnection, s_tableName); +// } +// } +// } - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsSupportedDataClassification))] - public static void TestDataClassificationResultSet() - { - s_tableName = DataTestUtility.GetUniqueNameForSqlServer("DC"); - using (SqlConnection sqlConnection = new SqlConnection(DataTestUtility.TCPConnectionString)) - using (SqlCommand sqlCommand = sqlConnection.CreateCommand()) - { - try - { - sqlConnection.Open(); - Assert.True(DataTestUtility.IsSupportedDataClassification()); - CreateTable(sqlCommand); - AddSensitivity(sqlCommand); - InsertData(sqlCommand); - RunTestsForServer(sqlCommand); - } - finally - { - DataTestUtility.DropTable(sqlConnection, s_tableName); - } - } - } +// [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsSupportedDataClassification))] +// public static void TestDataClassificationResultSet() +// { +// s_tableName = DataTestUtility.GetUniqueNameForSqlServer("DC"); +// using (SqlConnection sqlConnection = new SqlConnection(DataTestUtility.TCPConnectionString)) +// using (SqlCommand sqlCommand = sqlConnection.CreateCommand()) +// { +// try +// { +// sqlConnection.Open(); +// Assert.True(DataTestUtility.IsSupportedDataClassification()); +// CreateTable(sqlCommand); +// AddSensitivity(sqlCommand); +// InsertData(sqlCommand); +// RunTestsForServer(sqlCommand); +// } +// finally +// { +// DataTestUtility.DropTable(sqlConnection, s_tableName); +// } +// } +// } - private static void RunTestsForServer(SqlCommand sqlCommand, bool rankEnabled = false) - { - sqlCommand.CommandText = "SELECT * FROM " + s_tableName; - using (SqlDataReader reader = sqlCommand.ExecuteReader()) - { - VerifySensitivityClassification(reader, rankEnabled); - } - } +// private static void RunTestsForServer(SqlCommand sqlCommand, bool rankEnabled = false) +// { +// sqlCommand.CommandText = "SELECT * FROM " + s_tableName; +// using (SqlDataReader reader = sqlCommand.ExecuteReader()) +// { +// VerifySensitivityClassification(reader, rankEnabled); +// } +// } - private static void VerifySensitivityClassification(SqlDataReader reader, bool rankEnabled = false) - { - if (null != reader.SensitivityClassification) - { - for (int columnPos = 0; columnPos < reader.SensitivityClassification.ColumnSensitivities.Count; - columnPos++) - { - foreach (SensitivityProperty sp in reader.SensitivityClassification.ColumnSensitivities[columnPos].SensitivityProperties) - { - ReadOnlyCollection infoTypes = reader.SensitivityClassification.InformationTypes; - Assert.Equal(3, infoTypes.Count); - for (int i = 0; i < infoTypes.Count; i++) - { - VerifyInfoType(infoTypes[i], i + 1); - } +// private static void VerifySensitivityClassification(SqlDataReader reader, bool rankEnabled = false) +// { +// if (null != reader.SensitivityClassification) +// { +// for (int columnPos = 0; columnPos < reader.SensitivityClassification.ColumnSensitivities.Count; +// columnPos++) +// { +// foreach (SensitivityProperty sp in reader.SensitivityClassification.ColumnSensitivities[columnPos].SensitivityProperties) +// { +// ReadOnlyCollection infoTypes = reader.SensitivityClassification.InformationTypes; +// Assert.Equal(3, infoTypes.Count); +// for (int i = 0; i < infoTypes.Count; i++) +// { +// VerifyInfoType(infoTypes[i], i + 1); +// } - ReadOnlyCollection