From ee6e1465ef46dec5b5123ed687d58ea57403f505 Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Wed, 3 Sep 2025 07:58:26 -0300
Subject: [PATCH 01/11] User Story 38467: Backport mac server name fix
- Backported part of #3494 and #3591:
- Added configurable test jobs timeout, defaulting to 90 minutes.
- Reduced generated database names to 96 chars to try to fix macOS test failures.
---
.../jobs/run-tests-package-reference-job.yml | 10 ++++++++++
.../dotnet-sqlclient-signing-pipeline.yml | 7 +++++++
.../ManualTests/DataCommon/DataTestUtility.cs | 17 ++++++++++++++---
3 files changed, 31 insertions(+), 3 deletions(-)
diff --git a/eng/pipelines/common/templates/jobs/run-tests-package-reference-job.yml b/eng/pipelines/common/templates/jobs/run-tests-package-reference-job.yml
index a9fcd12720..9973e362e7 100644
--- a/eng/pipelines/common/templates/jobs/run-tests-package-reference-job.yml
+++ b/eng/pipelines/common/templates/jobs/run-tests-package-reference-job.yml
@@ -17,11 +17,21 @@ parameters:
type: string
default: empty
+ # The timeout, in minutes, for this job.
+ - name: timeout
+ type: string
+ default: 90
+
jobs:
- job: run_tests_package_reference
displayName: 'Run tests with package reference'
${{ if ne(parameters.dependsOn, 'empty')}}:
dependsOn: '${{parameters.dependsOn }}'
+
+ # Some of our tests take longer than the default 60 minutes to run on some
+ # OSes and configurations.
+ timeoutInMinutes: ${{ parameters.timeout }}
+
pool:
type: windows # read more about custom job pool types at https://aka.ms/obpipelines/yaml/jobs
isCustom: true
diff --git a/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml b/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml
index 299a4085fa..b422fa7836 100644
--- a/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml
+++ b/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml
@@ -65,6 +65,12 @@ parameters: # parameters are shown up in ADO UI in a build queue time
- NonOfficial
- Official
+# The timeout, in minutes, for each test job.
+- name: testsTimeout
+ displayName: 'Tests timeout (in minutes)'
+ type: string
+ default: 90
+
variables:
- template: /eng/pipelines/libraries/variables.yml@self
- name: packageFolderName
@@ -172,6 +178,7 @@ extends:
- template: eng/pipelines/common/templates/jobs/run-tests-package-reference-job.yml@self
parameters:
packageFolderName: $(packageFolderName)
+ timeout: ${{ parameters.testsTimeout }}
downloadPackageStep:
download: current
artifact: $(packageFolderName)
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs
index 1375cbea2f..7b080e5128 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs
@@ -442,7 +442,7 @@ public static string GetUniqueName(string prefix, bool withBracket = true)
///
/// Add the prefix to the generate string.
/// Database name must be pass with brackets by default.
- /// Unique name by considering the Sql Server naming rules.
+ /// Unique name by considering the Sql Server naming rules, never longer than 96 characters.
public static string GetUniqueNameForSqlServer(string prefix, bool withBracket = true)
{
string extendedPrefix = string.Format(
@@ -452,10 +452,21 @@ public static string GetUniqueNameForSqlServer(string prefix, bool withBracket =
Environment.MachineName,
DateTime.Now.ToString("yyyy_MM_dd", CultureInfo.InvariantCulture));
string name = GetUniqueName(extendedPrefix, withBracket);
- if (name.Length > 128)
+
+ // Truncate to no more than 96 characters.
+ const int maxLen = 96;
+ if (name.Length > maxLen)
{
- throw new ArgumentOutOfRangeException("the name is too long - SQL Server names are limited to 128");
+ if (withBracket)
+ {
+ name = name.Substring(0, maxLen - 1) + ']';
+ }
+ else
+ {
+ name = name.Substring(0, maxLen);
+ }
}
+
return name;
}
From 0213b163ee04bc27be8156c7e6cea1e3d80af518 Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Fri, 5 Sep 2025 09:30:46 -0300
Subject: [PATCH 02/11] User Story 38481: Fix unique db object name issues
- Fixed the unique name generators to:
- Keep max lengths to 30 and 96 characters respectively.
- Ensure uniqueness at the start of the names.
- Added link to database identifier syntax.
---
.../ManualTests/AlwaysEncrypted/ApiShould.cs | 10 +-
.../AlwaysEncrypted/CspProviderExt.cs | 49 ----
.../ManualTests/DataCommon/DataTestUtility.cs | 209 ++++++++++++++----
.../ProviderAgnostic/ReaderTest/ReaderTest.cs | 6 +-
.../SQL/AdapterTest/AdapterTest.cs | 10 +-
.../SQL/ConnectivityTests/ConnectivityTest.cs | 14 +-
.../DataClassificationTest.cs | 6 +-
.../SQL/DataReaderTest/DataReaderTest.cs | 8 +-
.../SQL/DataStreamTest/DataStreamTest.cs | 10 +-
.../SQL/ParameterTest/DateTimeVariantTest.cs | 52 ++---
.../SQL/ParameterTest/ParametersTest.cs | 141 +++++++++++-
.../ParameterTest/SqlAdapterUpdateBatch.cs | 2 +-
.../SQL/ParameterTest/SqlVariantParam.cs | 4 +-
.../RetryLogic/SqlCommandReliabilityTest.cs | 4 +-
.../SqlConnectionReliabilityTest.cs | 2 +-
.../AdjustPrecScaleForBulkCopy.cs | 2 +-
.../AzureDistributedTransaction.cs | 2 +-
.../CopyWidenNullInexactNumerics.cs | 4 +-
.../DataConversionErrorMessageTest.cs | 2 +-
.../SQL/SqlCommand/SqlCommandCompletedTest.cs | 2 +-
.../SQL/SqlCommand/SqlCommandSetTest.cs | 4 +-
.../SqlFileStreamTest/SqlFileStreamTest.cs | 4 +-
.../SQL/UdtTest/SqlServerTypesTest.cs | 2 +-
.../SQL/UdtTest/UdtBulkCopyTest.cs | 6 +-
.../tests/ManualTests/SQL/UdtTest/UdtTest2.cs | 16 +-
.../SQL/Utf8SupportTest/Utf8SupportTest.cs | 2 +-
26 files changed, 376 insertions(+), 197 deletions(-)
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs
index 8e7458f02e..b987bdbc99 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs
@@ -148,8 +148,8 @@ public void SqlParameterProperties(string connection)
const string firstColumnName = @"firstColumn";
const string secondColumnName = @"secondColumn";
const string thirdColumnName = @"thirdColumn";
- string inputProcedureName = DataTestUtility.GetUniqueName("InputProc").ToString();
- string outputProcedureName = DataTestUtility.GetUniqueName("OutputProc").ToString();
+ string inputProcedureName = DataTestUtility.GetShortName("InputProc").ToString();
+ string outputProcedureName = DataTestUtility.GetShortName("OutputProc").ToString();
const int charColumnSize = 100;
const int decimalColumnPrecision = 10;
const int decimalColumnScale = 4;
@@ -694,7 +694,7 @@ public void TestExecuteReader(string connection)
[ClassData(typeof(AEConnectionStringProvider))]
public async void TestExecuteReaderAsyncWithLargeQuery(string connectionString)
{
- string randomName = DataTestUtility.GetUniqueName(Guid.NewGuid().ToString().Replace("-", ""), false);
+ string randomName = DataTestUtility.GetShortName(Guid.NewGuid().ToString().Replace("-", ""), false);
if (randomName.Length > 50)
{
randomName = randomName.Substring(0, 50);
@@ -878,8 +878,8 @@ public void TestEnclaveStoredProceduresWithAndWithoutParameters(string connectio
using SqlCommand sqlCommand = new("", sqlConnection, transaction: null,
columnEncryptionSetting: SqlCommandColumnEncryptionSetting.Enabled);
- string procWithoutParams = DataTestUtility.GetUniqueName("EnclaveWithoutParams", withBracket: false);
- string procWithParam = DataTestUtility.GetUniqueName("EnclaveWithParams", withBracket: false);
+ string procWithoutParams = DataTestUtility.GetShortName("EnclaveWithoutParams", withBracket: false);
+ string procWithParam = DataTestUtility.GetShortName("EnclaveWithParams", withBracket: false);
try
{
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CspProviderExt.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CspProviderExt.cs
index 49071def2e..e26c67382e 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CspProviderExt.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CspProviderExt.cs
@@ -157,55 +157,6 @@ public void TestRoundTripWithCSPAndCertStoreProvider()
}
}
- [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.
///
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs
index 7b080e5128..2723853f27 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs
@@ -88,7 +88,7 @@ public static bool TcpConnectionStringDoesNotUseAadAuth
{
get
{
- SqlConnectionStringBuilder builder = new (TCPConnectionString);
+ SqlConnectionStringBuilder builder = new(TCPConnectionString);
return builder.Authentication == SqlAuthenticationMethod.SqlPassword || builder.Authentication == SqlAuthenticationMethod.NotSpecified;
}
}
@@ -415,59 +415,176 @@ public static bool DoesHostAddressContainBothIPv4AndIPv6()
}
}
+ // Generate a new GUID and return the characters from its 1st and 4th
+ // parts, as shown here:
+ //
+ // 7ff01cb8-88c7-11f0-b433-00155d7e531e
+ // ^^^^^^^^ ^^^^
+ //
+ // These 12 characters are concatenated together without any
+ // separators. These 2 parts typically comprise a timestamp and clock
+ // sequence, most likely to be unique for tests that generate names in
+ // quick succession.
+ private static string GetGuidParts()
+ {
+ var guid = Guid.NewGuid().ToString();
+ // GOTCHA: The slice operator is inclusive of the start index and
+ // exclusive of the end index!
+ return guid.Substring(0, 8) + guid.Substring(19, 4);
+ }
+
///
- /// Generate a unique name to use in Sql Server;
- /// some providers does not support names (Oracle supports up to 30).
+ /// Generate a short unique database object name, whose maximum length
+ /// is 30 characters, with the format:
+ ///
+ /// _
+ ///
+ /// The Prefix will be truncated to satisfy the overall maximum length.
+ ///
+ /// The GUID parts will be the characters from the 1st and 4th blocks
+ /// from a traditional string representation, as shown here:
+ ///
+ /// 7ff01cb8-88c7-11f0-b433-00155d7e531e
+ /// ^^^^^^^^ ^^^^
+ ///
+ /// These 2 parts typically comprise a timestamp and clock sequence,
+ /// most likely to be unique for tests that generate names in quick
+ /// succession. The 12 characters are concatenated together without any
+ /// separators.
///
- /// The name length will be no more then (16 + prefix.Length + escapeLeft.Length + escapeRight.Length).
- /// Name without brackets.
- /// Unique name by considering the Sql Server naming rules.
- public static string GetUniqueName(string prefix, bool withBracket = true)
- {
- string escapeLeft = withBracket ? "[" : string.Empty;
- string escapeRight = withBracket ? "]" : string.Empty;
- string uniqueName = string.Format("{0}{1}_{2}_{3}{4}",
- escapeLeft,
- prefix,
- DateTime.Now.Ticks.ToString("X", CultureInfo.InvariantCulture), // up to 8 characters
- Guid.NewGuid().ToString().Substring(0, 6), // take the first 6 characters only
- escapeRight);
- return uniqueName;
+ ///
+ ///
+ /// The prefix to use when generating the unique name, truncated to at
+ /// most 18 characters when withBracket is false, and 16 characters when
+ /// withBracket is true.
+ ///
+ /// This should not contain any characters that cannot be used in
+ /// database object names. See:
+ ///
+ /// https://learn.microsoft.com/en-us/sql/relational-databases/databases/database-identifiers?view=sql-server-ver17#rules-for-regular-identifiers
+ ///
+ ///
+ ///
+ /// When true, the entire generated name will be enclosed in square
+ /// brackets, for example:
+ ///
+ /// [MyPrefix_7ff01cb811f0]
+ ///
+ ///
+ ///
+ /// A unique database object name, no more than 30 characters long.
+ ///
+ public static string GetShortName(string prefix, bool withBracket = true)
+ {
+ StringBuilder name = new(30);
+
+ if (withBracket)
+ {
+ name.Append('[');
+ }
+
+ int maxPrefixLength = withBracket ? 16 : 18;
+ if (prefix.Length > maxPrefixLength)
+ {
+ prefix = prefix.Substring(0, maxPrefixLength);
+ }
+
+ name.Append(prefix);
+ name.Append('_');
+ name.Append(GetGuidParts());
+
+ if (withBracket)
+ {
+ name.Append(']');
+ }
+
+ return name.ToString();
}
///
- /// Uses environment values `UserName` and `MachineName` in addition to the specified `prefix` and current date
- /// to generate a unique name to use in Sql Server;
- /// SQL Server supports long names (up to 128 characters), add extra info for troubleshooting.
+ /// Generate a long unique database object name, whose maximum length is
+ /// 96 characters, with the format:
+ ///
+ /// ___
+ ///
+ /// The Prefix will be truncated to satisfy the overall maximum length.
+ ///
+ /// The GUID Parts will be the characters from the 1st and 4th blocks
+ /// from a traditional string representation, as shown here:
+ ///
+ /// 7ff01cb8-88c7-11f0-b433-00155d7e531e
+ /// ^^^^^^^^ ^^^^
+ ///
+ /// These 2 parts typically comprise a timestamp and clock sequence,
+ /// most likely to be unique for tests that generate names in quick
+ /// succession. The 12 characters are concatenated together without any
+ /// separators.
+ ///
+ /// The UserName and MachineName are obtained from the Environment,
+ /// and will be truncated to satisfy the maximum overall length.
///
- /// Add the prefix to the generate string.
- /// Database name must be pass with brackets by default.
- /// Unique name by considering the Sql Server naming rules, never longer than 96 characters.
- public static string GetUniqueNameForSqlServer(string prefix, bool withBracket = true)
- {
- string extendedPrefix = string.Format(
- "{0}_{1}_{2}@{3}",
- prefix,
- Environment.UserName,
- Environment.MachineName,
- DateTime.Now.ToString("yyyy_MM_dd", CultureInfo.InvariantCulture));
- string name = GetUniqueName(extendedPrefix, withBracket);
-
- // Truncate to no more than 96 characters.
- const int maxLen = 96;
- if (name.Length > maxLen)
- {
- if (withBracket)
- {
- name = name.Substring(0, maxLen - 1) + ']';
- }
- else
- {
- name = name.Substring(0, maxLen);
- }
+ ///
+ ///
+ /// The prefix to use when generating the unique name, truncated to at
+ /// most 32 characters.
+ ///
+ /// This should not contain any characters that cannot be used in
+ /// database object names. See:
+ ///
+ /// https://learn.microsoft.com/en-us/sql/relational-databases/databases/database-identifiers?view=sql-server-ver17#rules-for-regular-identifiers
+ ///
+ ///
+ ///
+ /// When true, the entire generated name will be enclosed in square
+ /// brackets, for example:
+ ///
+ /// [MyPrefix_7ff01cb811f0_test_user_ci_agent_machine_name]
+ ///
+ ///
+ ///
+ /// A unique database object name, no more than 96 characters long.
+ ///
+ public static string GetLongName(string prefix, bool withBracket = true)
+ {
+ StringBuilder name = new(96);
+
+ if (withBracket)
+ {
+ name.Append('[');
+ }
+
+ if (prefix.Length > 32)
+ {
+ prefix = prefix.Substring(0, 32);
+ }
+
+ name.Append(prefix);
+ name.Append('_');
+ name.Append(GetGuidParts());
+ name.Append('_');
+
+ var suffix =
+ Environment.UserName + '_' +
+ Environment.MachineName;
+
+ int maxSuffixLength = 96 - name.Length;
+ if (withBracket)
+ {
+ --maxSuffixLength;
+ }
+ if (suffix.Length > maxSuffixLength)
+ {
+ suffix = suffix.Substring(0, maxSuffixLength);
+ }
+
+ name.Append(suffix);
+
+ if (withBracket)
+ {
+ name.Append(']');
}
- return name;
+ return name.ToString();
}
public static bool IsSupportingDistributedTransactions()
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..5728a8b1ac 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/ProviderAgnostic/ReaderTest/ReaderTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/ProviderAgnostic/ReaderTest/ReaderTest.cs
@@ -19,7 +19,7 @@ public static void TestMain()
{
string connectionString = DataTestUtility.TCPConnectionString;
- string tempTable = DataTestUtility.GetUniqueNameForSqlServer("table");
+ string tempTable = DataTestUtility.GetLongName("table");
DbProviderFactory provider = SqlClientFactory.Instance;
try
@@ -275,7 +275,7 @@ public static void TestMain()
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))]
public static void SqlDataReader_SqlBuffer_GetFieldValue()
{
- string tableName = DataTestUtility.GetUniqueNameForSqlServer("SqlBuffer_GetFieldValue");
+ string tableName = DataTestUtility.GetLongName("SqlBuffer_GetFieldValue");
DateTimeOffset dtoffset = DateTimeOffset.Now;
DateTime dt = DateTime.Now;
//Exclude the millisecond because of rounding at some points by SQL Server.
@@ -374,7 +374,7 @@ public static void SqlDataReader_SqlBuffer_GetFieldValue()
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))]
public static async Task SqlDataReader_SqlBuffer_GetFieldValue_Async()
{
- string tableName = DataTestUtility.GetUniqueNameForSqlServer("SqlBuffer_GetFieldValue_Async");
+ string tableName = DataTestUtility.GetLongName("SqlBuffer_GetFieldValue_Async");
DateTimeOffset dtoffset = DateTimeOffset.Now;
DateTime dt = DateTime.Now;
//Exclude the millisecond because of rounding at some points by SQL Server.
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 9d43567cf1..371550e105 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AdapterTest/AdapterTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AdapterTest/AdapterTest.cs
@@ -54,7 +54,7 @@ public class AdapterTest
public AdapterTest()
{
// create random name for temp tables
- _tempTable = DataTestUtility.GetUniqueName("AdapterTest");
+ _tempTable = DataTestUtility.GetShortName("AdapterTest");
_tempTable = _tempTable.Replace('-', '_');
_randomGuid = Guid.NewGuid().ToString();
@@ -487,7 +487,7 @@ public void ParameterTest_AllTypes()
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))]
public void ParameterTest_InOut()
{
- string procName = DataTestUtility.GetUniqueName("P");
+ string procName = DataTestUtility.GetShortName("P");
// input, output
string spCreateInOut =
"CREATE PROCEDURE " + procName + " @in int, @inout int OUTPUT, @out nvarchar(8) OUTPUT " +
@@ -768,13 +768,13 @@ public void BulkUpdateTest()
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))]
public void UpdateRefreshTest()
{
- string identTableName = DataTestUtility.GetUniqueName("ID_");
+ string identTableName = DataTestUtility.GetShortName("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 spName = DataTestUtility.GetShortName("sp_insert", withBracket: false);
string spCreateInsert =
$"CREATE PROCEDURE {spName}" +
"(@FirstName nvarchar(50), @LastName nvarchar(50), @id int OUTPUT) " +
@@ -1087,7 +1087,7 @@ public void AutoGenUpdateTest()
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))]
public void AutoGenErrorTest()
{
- string identTableName = DataTestUtility.GetUniqueName("ID_");
+ string identTableName = DataTestUtility.GetShortName("ID_");
string createIdentTable =
$"CREATE TABLE {identTableName} (id int IDENTITY," +
"LastName nvarchar(50) NULL," +
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 7675643382..dfdbf5229f 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/ConnectivityTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/ConnectivityTest.cs
@@ -368,9 +368,10 @@ public static void ConnectionOpenDisableRetry()
{
SqlConnectionStringBuilder connectionStringBuilder = new(DataTestUtility.TCPConnectionString)
{
- InitialCatalog = "DoesNotExist0982532435423",
+ InitialCatalog = DataTestUtility.GetLongName("DoesNotExist", false),
Pooling = false,
- ConnectTimeout=15
+ ConnectTimeout = 15,
+ ConnectRetryCount = 3
};
using SqlConnection sqlConnection = new(connectionStringBuilder.ConnectionString);
Stopwatch timer = new();
@@ -397,15 +398,6 @@ private static bool CanCreateAliases()
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)
{
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..24786999e7 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataClassificationTest/DataClassificationTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataClassificationTest/DataClassificationTest.cs
@@ -18,7 +18,7 @@ public static class DataClassificationTest
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse), nameof(DataTestUtility.IsSupportedDataClassification))]
public static void TestDataClassificationResultSetRank()
{
- s_tableName = DataTestUtility.GetUniqueNameForSqlServer("DC");
+ s_tableName = DataTestUtility.GetLongName("DC");
using (SqlConnection sqlConnection = new SqlConnection(DataTestUtility.TCPConnectionString))
using (SqlCommand sqlCommand = sqlConnection.CreateCommand())
{
@@ -41,7 +41,7 @@ public static void TestDataClassificationResultSetRank()
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsSupportedDataClassification))]
public static void TestDataClassificationResultSet()
{
- s_tableName = DataTestUtility.GetUniqueNameForSqlServer("DC");
+ s_tableName = DataTestUtility.GetLongName("DC");
using (SqlConnection sqlConnection = new SqlConnection(DataTestUtility.TCPConnectionString))
using (SqlCommand sqlCommand = sqlConnection.CreateCommand())
{
@@ -232,7 +232,7 @@ public static void TestDataClassificationBulkCopy()
data.Rows.Add(Guid.NewGuid(), "Company 2", "sample2@contoso.com", 1);
data.Rows.Add(Guid.NewGuid(), "Company 3", "sample3@contoso.com", 1);
- var tableName = DataTestUtility.GetUniqueNameForSqlServer("DC");
+ var tableName = DataTestUtility.GetLongName("DC");
using (var connection = new SqlConnection(DataTestUtility.TCPConnectionString))
{
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataReaderTest/DataReaderTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataReaderTest/DataReaderTest.cs
index b8731ea672..0aaaaf890d 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataReaderTest/DataReaderTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataReaderTest/DataReaderTest.cs
@@ -123,9 +123,7 @@ public static void CheckSparseColumnBit()
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureServer), nameof(DataTestUtility.IsNotAzureSynapse))]
public static void CollatedDataReaderTest()
{
- var databaseName = DataTestUtility.GetUniqueName("DB");
- // Remove square brackets
- var dbName = databaseName.Substring(1, databaseName.Length - 2);
+ string dbName = DataTestUtility.GetShortName("CollationTest", false);
SqlConnectionStringBuilder builder = new(DataTestUtility.TCPConnectionString)
{
@@ -140,7 +138,7 @@ public static void CollatedDataReaderTest()
con.Open();
// Create collated database
- cmd.CommandText = $"CREATE DATABASE {databaseName} COLLATE KAZAKH_90_CI_AI";
+ cmd.CommandText = $"CREATE DATABASE {dbName} COLLATE KAZAKH_90_CI_AI";
cmd.ExecuteNonQuery();
//Create connection without pooling in order to delete database later.
@@ -165,7 +163,7 @@ public static void CollatedDataReaderTest()
}
finally
{
- cmd.CommandText = $"DROP DATABASE {databaseName}";
+ cmd.CommandText = $"DROP DATABASE {dbName}";
cmd.ExecuteNonQuery();
}
}
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataStreamTest/DataStreamTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataStreamTest/DataStreamTest.cs
index 30a1505442..e622121cbb 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataStreamTest/DataStreamTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataStreamTest/DataStreamTest.cs
@@ -50,7 +50,7 @@ public static async Task AsyncMultiPacketStreamRead()
byte[] inputData = null;
byte[] outputData = null;
- string tableName = DataTestUtility.GetUniqueNameForSqlServer("data");
+ string tableName = DataTestUtility.GetLongName("data");
using (SqlConnection connection = new(connectionString))
{
@@ -546,7 +546,7 @@ private static void RowBuffer(string connectionString)
private static void TimestampRead(string connectionString)
{
- string tempTable = DataTestUtility.GetUniqueNameForSqlServer("##Temp");
+ string tempTable = DataTestUtility.GetLongName("##Temp");
tempTable = tempTable.Replace('-', '_');
using (SqlConnection conn = new SqlConnection(connectionString))
@@ -1041,7 +1041,7 @@ private static void SequentialAccess(string connectionString)
private static void NumericRead(string connectionString)
{
- string tempTable = DataTestUtility.GetUniqueNameForSqlServer("##Temp");
+ string tempTable = DataTestUtility.GetLongName("##Temp");
tempTable = tempTable.Replace('-', '_');
using (SqlConnection conn = new SqlConnection(connectionString))
@@ -1872,8 +1872,8 @@ private static void StreamingBlobDataTypes(string connectionString)
private static void VariantCollationsTest(string connectionString)
{
- string dbName = DataTestUtility.GetUniqueName("JPN");
- string tableName = DataTestUtility.GetUniqueName("T");
+ string dbName = DataTestUtility.GetShortName("JPN");
+ string tableName = DataTestUtility.GetShortName("T");
using (SqlConnection connection = new SqlConnection(connectionString))
{
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/DateTimeVariantTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/DateTimeVariantTest.cs
index 31c232e3d0..20768e9329 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/DateTimeVariantTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/DateTimeVariantTest.cs
@@ -75,7 +75,7 @@ private static void TestSimpleParameter_Type(object paramValue, string expectedT
{
string tag = "TestSimpleParameter_Type";
DisplayHeader(tag, paramValue, expectedBaseTypeName);
- string procName = DataTestUtility.GetUniqueNameForSqlServer("paramProc1");
+ string procName = DataTestUtility.GetLongName("paramProc1");
try
{
using SqlConnection conn = new(s_connStr);
@@ -115,7 +115,7 @@ private static void TestSimpleParameter_Variant(object paramValue, string expect
{
string tag = "TestSimpleParameter_Variant";
DisplayHeader(tag, paramValue, expectedBaseTypeName);
- string procName = DataTestUtility.GetUniqueNameForSqlServer("paramProc2");
+ string procName = DataTestUtility.GetLongName("paramProc2");
try
{
using SqlConnection conn = new(s_connStr);
@@ -153,7 +153,7 @@ private static void TestSqlDataRecordParameterToTVP_Type(object paramValue, stri
{
string tag = "TestSqlDataRecordParameterToTVP_Type";
DisplayHeader(tag, paramValue, expectedBaseTypeName);
- string tvpTypeName = DataTestUtility.GetUniqueNameForSqlServer("tvpType");
+ string tvpTypeName = DataTestUtility.GetLongName("tvpType");
try
{
using SqlConnection conn = new(s_connStr);
@@ -200,7 +200,7 @@ private static void TestSqlDataRecordParameterToTVP_Variant(object paramValue, s
{
string tag = "TestSqlDataRecordParameterToTVP_Variant";
DisplayHeader(tag, paramValue, expectedBaseTypeName);
- string tvpTypeName = DataTestUtility.GetUniqueNameForSqlServer("tvpVariant");
+ string tvpTypeName = DataTestUtility.GetLongName("tvpVariant");
try
{
using SqlConnection conn = new(s_connStr);
@@ -245,7 +245,7 @@ private static void TestSqlDataReaderParameterToTVP_Type(object paramValue, stri
{
string tag = "TestSqlDataReaderParameterToTVP_Type";
DisplayHeader(tag, paramValue, expectedBaseTypeName);
- string tvpTypeName = DataTestUtility.GetUniqueNameForSqlServer("tvpType");
+ string tvpTypeName = DataTestUtility.GetLongName("tvpType");
try
{
using SqlConnection conn = new(s_connStr);
@@ -295,7 +295,7 @@ private static void TestSqlDataReaderParameterToTVP_Variant(object paramValue, s
{
string tag = "TestSqlDataReaderParameterToTVP_Variant";
DisplayHeader(tag, paramValue, expectedBaseTypeName);
- string tvpTypeName = DataTestUtility.GetUniqueNameForSqlServer("tvpVariant");
+ string tvpTypeName = DataTestUtility.GetLongName("tvpVariant");
try
{
using SqlConnection conn = new(s_connStr);
@@ -347,10 +347,10 @@ private static void TestSqlDataReader_TVP_Type(object paramValue, string expecte
{
string tag = "TestSqlDataReader_TVP_Type";
DisplayHeader(tag, paramValue, expectedBaseTypeName);
- string tvpTypeName = DataTestUtility.GetUniqueNameForSqlServer("tvpType");
- string InputTableName = DataTestUtility.GetUniqueNameForSqlServer("InputTable");
- string OutputTableName = DataTestUtility.GetUniqueNameForSqlServer("OutputTable");
- string ProcName = DataTestUtility.GetUniqueNameForSqlServer("spTVPProc");
+ string tvpTypeName = DataTestUtility.GetLongName("tvpType");
+ string InputTableName = DataTestUtility.GetLongName("InputTable");
+ string OutputTableName = DataTestUtility.GetLongName("OutputTable");
+ string ProcName = DataTestUtility.GetLongName("spTVPProc");
try
{
using SqlConnection conn = new(s_connStr);
@@ -428,10 +428,10 @@ private static void TestSqlDataReader_TVP_Variant(object paramValue, string expe
{
string tag = "TestSqlDataReader_TVP_Variant";
DisplayHeader(tag, paramValue, expectedBaseTypeName);
- string tvpTypeName = DataTestUtility.GetUniqueNameForSqlServer("tvpVariant_DRdrTVPVar");
- string InputTableName = DataTestUtility.GetUniqueNameForSqlServer("InputTable");
- string OutputTableName = DataTestUtility.GetUniqueNameForSqlServer("OutputTable");
- string ProcName = DataTestUtility.GetUniqueNameForSqlServer("spTVPProc_DRdrTVPVar");
+ string tvpTypeName = DataTestUtility.GetLongName("tvpVariant_DRdrTVPVar");
+ string InputTableName = DataTestUtility.GetLongName("InputTable");
+ string OutputTableName = DataTestUtility.GetLongName("OutputTable");
+ string ProcName = DataTestUtility.GetLongName("spTVPProc_DRdrTVPVar");
try
{
using SqlConnection conn = new(s_connStr);
@@ -512,8 +512,8 @@ private static void TestSimpleDataReader_Type(object paramValue, string expected
{
string tag = "TestSimpleDataReader_Type";
DisplayHeader(tag, paramValue, expectedBaseTypeName);
- string inputTable = DataTestUtility.GetUniqueNameForSqlServer("inputTable");
- string procName = DataTestUtility.GetUniqueNameForSqlServer("paramProc3");
+ string inputTable = DataTestUtility.GetLongName("inputTable");
+ string procName = DataTestUtility.GetLongName("paramProc3");
try
{
using SqlConnection conn = new(s_connStr);
@@ -568,8 +568,8 @@ private static void TestSimpleDataReader_Variant(object paramValue, string expec
{
string tag = "TestSimpleDataReader_Variant";
DisplayHeader(tag, paramValue, expectedBaseTypeName);
- string inputTable = DataTestUtility.GetUniqueNameForSqlServer("inputTable");
- string procName = DataTestUtility.GetUniqueNameForSqlServer("paramProc4");
+ string inputTable = DataTestUtility.GetLongName("inputTable");
+ string procName = DataTestUtility.GetLongName("paramProc4");
try
{
using SqlConnection conn = new(s_connStr);
@@ -624,8 +624,8 @@ private static void SqlBulkCopySqlDataReader_Type(object paramValue, string expe
{
string tag = "SqlBulkCopySqlDataReader_Type";
DisplayHeader(tag, paramValue, expectedBaseTypeName);
- string bulkCopySrcTableName = DataTestUtility.GetUniqueNameForSqlServer("bulkSrcTable");
- string bulkCopyTableName = DataTestUtility.GetUniqueNameForSqlServer("bulkDestTable");
+ string bulkCopySrcTableName = DataTestUtility.GetLongName("bulkSrcTable");
+ string bulkCopyTableName = DataTestUtility.GetLongName("bulkDestTable");
try
{
using SqlConnection conn = new(s_connStr);
@@ -698,8 +698,8 @@ private static void SqlBulkCopySqlDataReader_Variant(object paramValue, string e
{
string tag = "SqlBulkCopySqlDataReader_Variant";
DisplayHeader(tag, paramValue, expectedBaseTypeName);
- string bulkCopySrcTableName = DataTestUtility.GetUniqueNameForSqlServer("bulkSrcTable");
- string bulkCopyTableName = DataTestUtility.GetUniqueNameForSqlServer("bulkDestTable");
+ string bulkCopySrcTableName = DataTestUtility.GetLongName("bulkSrcTable");
+ string bulkCopyTableName = DataTestUtility.GetLongName("bulkDestTable");
try
{
using SqlConnection conn = new(s_connStr);
@@ -776,7 +776,7 @@ private static void SqlBulkCopyDataTable_Type(object paramValue, string expected
{
string tag = "SqlBulkCopyDataTable_Type";
DisplayHeader(tag, paramValue, expectedBaseTypeName);
- string bulkCopyTableName = DataTestUtility.GetUniqueNameForSqlServer("bulkDestType");
+ string bulkCopyTableName = DataTestUtility.GetLongName("bulkDestType");
try
{
using SqlConnection conn = new(s_connStr);
@@ -836,7 +836,7 @@ private static void SqlBulkCopyDataTable_Variant(object paramValue, string expec
{
string tag = "SqlBulkCopyDataTable_Variant";
DisplayHeader(tag, paramValue, expectedBaseTypeName);
- string bulkCopyTableName = DataTestUtility.GetUniqueNameForSqlServer("bulkDestVariant");
+ string bulkCopyTableName = DataTestUtility.GetLongName("bulkDestVariant");
try
{
using SqlConnection conn = new(s_connStr);
@@ -886,7 +886,7 @@ private static void SqlBulkCopyDataRow_Type(object paramValue, string expectedTy
{
string tag = "SqlBulkCopyDataRow_Type";
DisplayHeader(tag, paramValue, expectedBaseTypeName);
- string bulkCopyTableName = DataTestUtility.GetUniqueNameForSqlServer("bulkDestType");
+ string bulkCopyTableName = DataTestUtility.GetLongName("bulkDestType");
try
{
using SqlConnection conn = new(s_connStr);
@@ -941,7 +941,7 @@ private static void SqlBulkCopyDataRow_Variant(object paramValue, string expecte
{
string tag = "SqlBulkCopyDataRow_Variant";
DisplayHeader(tag, paramValue, expectedBaseTypeName);
- string bulkCopyTableName = DataTestUtility.GetUniqueNameForSqlServer("bulkDestVariant");
+ string bulkCopyTableName = DataTestUtility.GetLongName("bulkDestVariant");
try
{
using SqlConnection conn = new(s_connStr);
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs
index 93f31bf9f1..7182ce768c 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs
@@ -8,6 +8,7 @@
using System.Data;
using System.Data.SqlTypes;
using System.Threading;
+using Microsoft.Data.SqlClient.Server;
using Xunit;
namespace Microsoft.Data.SqlClient.ManualTesting.Tests
@@ -111,7 +112,7 @@ public static void CodeCoverageSqlClient()
public static void Test_Copy_SqlParameter()
{
using var conn = new SqlConnection(s_connString);
- string cTableName = DataTestUtility.GetUniqueNameForSqlServer("#tmp");
+ string cTableName = DataTestUtility.GetLongName("#tmp");
try
{
// Create tmp table
@@ -253,9 +254,9 @@ public static void TestParametersWithDatatablesTVPInsert()
};
using SqlConnection connection = new(builder.ConnectionString);
- string tableName = DataTestUtility.GetUniqueNameForSqlServer("Table");
- string procName = DataTestUtility.GetUniqueNameForSqlServer("Proc");
- string typeName = DataTestUtility.GetUniqueName("Type");
+ string tableName = DataTestUtility.GetLongName("Table");
+ string procName = DataTestUtility.GetLongName("Proc");
+ string typeName = DataTestUtility.GetShortName("Type");
try
{
connection.Open();
@@ -306,6 +307,126 @@ public static void TestParametersWithDatatablesTVPInsert()
}
}
+#if !NETFRAMEWORK
+
+ [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))]
+ public static void TestDateOnlyTVPDataTable_CommandSP()
+ {
+ string tableTypeName = "[dbo]." + DataTestUtility.GetLongName("UDTTTestDateOnlyTVP");
+ string spName = DataTestUtility.GetLongName("spTestDateOnlyTVP");
+ SqlConnection connection = new(s_connString);
+ try
+ {
+ connection.Open();
+ using (SqlCommand cmd = connection.CreateCommand())
+ {
+ cmd.CommandType = CommandType.Text;
+ cmd.CommandText = $"CREATE TYPE {tableTypeName} AS TABLE ([DateColumn] date NULL, [TimeColumn] time NULL)";
+ cmd.ExecuteNonQuery();
+ cmd.CommandText = $"CREATE PROCEDURE {spName} (@dates {tableTypeName} READONLY) AS SELECT COUNT(*) FROM @dates";
+ cmd.ExecuteNonQuery();
+ }
+ using (SqlCommand cmd = connection.CreateCommand())
+ {
+ cmd.CommandText = spName;
+ cmd.CommandType = CommandType.StoredProcedure;
+
+ DataTable dtTest = new();
+ dtTest.Columns.Add(new DataColumn("DateColumn", typeof(DateOnly)));
+ dtTest.Columns.Add(new DataColumn("TimeColumn", typeof(TimeOnly)));
+ var dataRow = dtTest.NewRow();
+ dataRow["DateColumn"] = new DateOnly(2023, 11, 15);
+ dataRow["TimeColumn"] = new TimeOnly(12, 30, 45);
+ dtTest.Rows.Add(dataRow);
+
+ cmd.Parameters.Add(new SqlParameter
+ {
+ ParameterName = "@dates",
+ SqlDbType = SqlDbType.Structured,
+ TypeName = tableTypeName,
+ Value = dtTest,
+ });
+
+ cmd.ExecuteNonQuery();
+ }
+ }
+ finally
+ {
+ DataTestUtility.DropStoredProcedure(connection, spName);
+ DataTestUtility.DropUserDefinedType(connection, tableTypeName);
+ }
+ }
+
+ [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))]
+ public static void TestDateOnlyTVPSqlDataRecord_CommandSP()
+ {
+ string tableTypeName = "[dbo]." + DataTestUtility.GetLongName("UDTTTestDateOnlySqlDataRecordTVP");
+ string spName = DataTestUtility.GetLongName("spTestDateOnlySqlDataRecordTVP");
+ SqlConnection connection = new(s_connString);
+ try
+ {
+ connection.Open();
+ using (SqlCommand cmd = connection.CreateCommand())
+ {
+ cmd.CommandType = CommandType.Text;
+ cmd.CommandText = $"CREATE TYPE {tableTypeName} AS TABLE ([DateColumn] date NULL, [TimeColumn] time NULL)";
+ cmd.ExecuteNonQuery();
+ cmd.CommandText = $"CREATE PROCEDURE {spName} (@dates {tableTypeName} READONLY) AS SELECT COUNT(*) FROM @dates";
+ cmd.ExecuteNonQuery();
+ }
+ using (SqlCommand cmd = connection.CreateCommand())
+ {
+ cmd.CommandText = spName;
+ cmd.CommandType = CommandType.StoredProcedure;
+
+ SqlMetaData[] metadata = new SqlMetaData[]
+ {
+ new SqlMetaData("DateColumn", SqlDbType.Date),
+ new SqlMetaData("TimeColumn", SqlDbType.Time)
+ };
+
+ SqlDataRecord record1 = new SqlDataRecord(metadata);
+ record1.SetValues(new DateOnly(2023, 11, 15), new TimeOnly(12, 30, 45));
+
+ SqlDataRecord record2 = new SqlDataRecord(metadata);
+ record2.SetValues(new DateOnly(2025, 11, 15), new TimeOnly(13, 31, 46));
+
+ IList featureInserts = new List
+ {
+ record1,
+ record2,
+ };
+
+ cmd.Parameters.Add(new SqlParameter
+ {
+ ParameterName = "@dates",
+ SqlDbType = SqlDbType.Structured,
+ TypeName = tableTypeName,
+ Value = featureInserts,
+ });
+
+ using var reader = cmd.ExecuteReader();
+
+ Assert.True(reader.HasRows);
+
+ int count = 0;
+ while (reader.Read())
+ {
+ Assert.NotNull(reader[0]);
+ count++;
+ }
+
+ Assert.Equal(1, count);
+ }
+ }
+ finally
+ {
+ DataTestUtility.DropStoredProcedure(connection, spName);
+ DataTestUtility.DropUserDefinedType(connection, tableTypeName);
+ }
+ }
+#endif
+
#region Scaled Decimal Parameter & TVP Test
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))]
[InlineData("CAST(1.0 as decimal(38, 37))", "1.0000000000000000000000000000")]
@@ -360,7 +481,7 @@ public static void SqlDecimalConvertToDecimal_TestOutOfRange(string sqlDecimalVa
[ClassData(typeof(ConnectionStringsProvider))]
public static void TestScaledDecimalParameter_CommandInsert(string connectionString, bool truncateScaledDecimal)
{
- string tableName = DataTestUtility.GetUniqueNameForSqlServer("TestDecimalParameterCMD");
+ string tableName = DataTestUtility.GetLongName("TestDecimalParameterCMD");
using SqlConnection connection = InitialDatabaseTable(connectionString, tableName);
try
{
@@ -392,7 +513,7 @@ public static void TestScaledDecimalParameter_CommandInsert(string connectionStr
[ClassData(typeof(ConnectionStringsProvider))]
public static void TestScaledDecimalParameter_BulkCopy(string connectionString, bool truncateScaledDecimal)
{
- string tableName = DataTestUtility.GetUniqueNameForSqlServer("TestDecimalParameterBC");
+ string tableName = DataTestUtility.GetLongName("TestDecimalParameterBC");
using SqlConnection connection = InitialDatabaseTable(connectionString, tableName);
try
{
@@ -426,9 +547,9 @@ public static void TestScaledDecimalParameter_BulkCopy(string connectionString,
[ClassData(typeof(ConnectionStringsProvider))]
public static void TestScaledDecimalTVP_CommandSP(string connectionString, bool truncateScaledDecimal)
{
- string tableName = DataTestUtility.GetUniqueNameForSqlServer("TestDecimalParameterBC");
- string tableTypeName = DataTestUtility.GetUniqueNameForSqlServer("UDTTTestDecimalParameterBC");
- string spName = DataTestUtility.GetUniqueNameForSqlServer("spTestDecimalParameterBC");
+ string tableName = DataTestUtility.GetLongName("TestDecimalParameterBC");
+ string tableTypeName = DataTestUtility.GetLongName("UDTTTestDecimalParameterBC");
+ string spName = DataTestUtility.GetLongName("spTestDecimalParameterBC");
using SqlConnection connection = InitialDatabaseUDTT(connectionString, tableName, tableTypeName, spName);
try
{
@@ -713,7 +834,7 @@ private static void EnableOptimizedParameterBinding_ReturnSucceeds()
{
int firstInput = 12;
- string sprocName = DataTestUtility.GetUniqueName("P");
+ string sprocName = DataTestUtility.GetShortName("P");
// input, output
string createSprocQuery =
"CREATE PROCEDURE " + sprocName + " @in int " +
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/SqlAdapterUpdateBatch.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/SqlAdapterUpdateBatch.cs
index 7f383e8201..aa59bc319c 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/SqlAdapterUpdateBatch.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/SqlAdapterUpdateBatch.cs
@@ -15,7 +15,7 @@ public class SqlAdapterUpdateBatch
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))]
public void SqlAdapterTest()
{
- string tableName = DataTestUtility.GetUniqueNameForSqlServer("Adapter");
+ string tableName = DataTestUtility.GetLongName("Adapter");
string tableNameNoBrackets = tableName.Substring(1, tableName.Length - 2);
try
{
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/SqlVariantParam.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/SqlVariantParam.cs
index 2d11274191..e1592825b1 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/SqlVariantParam.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/SqlVariantParam.cs
@@ -108,7 +108,7 @@ private static void SendVariantParam(object paramValue, string expectedTypeName,
///
private static void SendVariantBulkCopy(object paramValue, string expectedTypeName, string expectedBaseTypeName)
{
- string bulkCopyTableName = DataTestUtility.GetUniqueNameForSqlServer("bulkDest");
+ string bulkCopyTableName = DataTestUtility.GetLongName("bulkDest");
// Fetch reader using type.
using SqlDataReader dr = GetReaderForVariant(paramValue, false);
@@ -194,7 +194,7 @@ private static void SendVariantBulkCopy(object paramValue, string expectedTypeNa
///
private static void SendVariantTvp(object paramValue, string expectedTypeName, string expectedBaseTypeName)
{
- string tvpTypeName = DataTestUtility.GetUniqueNameForSqlServer("tvpVariant");
+ string tvpTypeName = DataTestUtility.GetLongName("tvpVariant");
using SqlConnection connTvp = new(s_connStr);
connTvp.Open();
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlCommandReliabilityTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlCommandReliabilityTest.cs
index 9e3ed81af4..dc467e3775 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlCommandReliabilityTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlCommandReliabilityTest.cs
@@ -240,7 +240,7 @@ public void RetryExecuteUnauthorizedSqlStatementDML(string cnnString, SqlRetryLo
public void DropDatabaseWithActiveConnection(string cnnString, SqlRetryLogicBaseProvider provider)
{
int currentRetries = 0;
- string database = DataTestUtility.GetUniqueNameForSqlServer($"RetryLogic_{provider.RetryLogic.RetryIntervalEnumerator.GetType().Name}", false);
+ string database = DataTestUtility.GetLongName($"RetryLogic_{provider.RetryLogic.RetryIntervalEnumerator.GetType().Name}", false);
var builder = new SqlConnectionStringBuilder(cnnString)
{
InitialCatalog = database,
@@ -302,7 +302,7 @@ public void DropDatabaseWithActiveConnection(string cnnString, SqlRetryLogicBase
public void UpdateALockedTable(string cnnString, SqlRetryLogicBaseProvider provider)
{
int currentRetries = 0;
- string tableName = DataTestUtility.GetUniqueNameForSqlServer("Region");
+ string tableName = DataTestUtility.GetLongName("Region");
string fieldName = "RegionDescription";
using (var cnn1 = new SqlConnection(cnnString))
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConnectionReliabilityTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConnectionReliabilityTest.cs
index c78c060677..d6f1e39f77 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConnectionReliabilityTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConnectionReliabilityTest.cs
@@ -58,7 +58,7 @@ public void ConnectionCancelRetryOpenInvalidCatalog(string cnnString, SqlRetryLo
public void CreateDatabaseWhileTryingToConnect(string cnnString, SqlRetryLogicBaseProvider provider)
{
int currentRetries = 0;
- string database = DataTestUtility.GetUniqueNameForSqlServer($"RetryLogic_{provider.RetryLogic.RetryIntervalEnumerator.GetType().Name}", false);
+ string database = DataTestUtility.GetLongName($"RetryLogic_{provider.RetryLogic.RetryIntervalEnumerator.GetType().Name}", false);
var builder = new SqlConnectionStringBuilder(cnnString)
{
InitialCatalog = database,
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/AdjustPrecScaleForBulkCopy.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/AdjustPrecScaleForBulkCopy.cs
index 72bab47869..a845710d50 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/AdjustPrecScaleForBulkCopy.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/AdjustPrecScaleForBulkCopy.cs
@@ -41,7 +41,7 @@ public static void RunTest()
private static SqlDecimal BulkCopySqlDecimalToTable(SqlDecimal decimalValue, int sourcePrecision, int sourceScale, int targetPrecision, int targetScale)
{
- string tableName = DataTestUtility.GetUniqueNameForSqlServer("Table");
+ string tableName = DataTestUtility.GetLongName("Table");
string connectionString = DataTestUtility.TCPConnectionString;
SqlDecimal resultValue;
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/AzureDistributedTransaction.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/AzureDistributedTransaction.cs
index 823bc50a9d..2a853d7ed4 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/AzureDistributedTransaction.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/AzureDistributedTransaction.cs
@@ -11,7 +11,7 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests
public class AzureDistributedTransaction
{
private static readonly string s_connectionString = DataTestUtility.TCPConnectionString;
- private static readonly string s_tableName = DataTestUtility.GetUniqueNameForSqlServer("Azure");
+ private static readonly string s_tableName = DataTestUtility.GetLongName("Azure");
private static readonly string s_createTableCmd = $"CREATE TABLE {s_tableName} (NAME NVARCHAR(40), AGE INT)";
private static readonly string s_sqlBulkCopyCmd = "SELECT * FROM(VALUES ('Fuller', 33), ('Davon', 49)) AS q (FirstName, Age)";
private static readonly int s_commandTimeout = 30;
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/CopyWidenNullInexactNumerics.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/CopyWidenNullInexactNumerics.cs
index 5ccda71fb9..f961521233 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/CopyWidenNullInexactNumerics.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/CopyWidenNullInexactNumerics.cs
@@ -12,8 +12,8 @@ public class CopyWidenNullInexactNumerics
{
public static void Test(string sourceDatabaseConnectionString, string destinationDatabaseConnectionString)
{
- string sourceTableName = DataTestUtility.GetUniqueNameForSqlServer("BCP_SRC");
- string destTableName = DataTestUtility.GetUniqueNameForSqlServer("BCP_DST");
+ string sourceTableName = DataTestUtility.GetLongName("BCP_SRC");
+ string destTableName = DataTestUtility.GetLongName("BCP_DST");
// this test copies float and real inexact numeric types into decimal targets using bulk copy to check that the widening of the type succeeds.
using (var sourceConnection = new SqlConnection(sourceDatabaseConnectionString))
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/DataConversionErrorMessageTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/DataConversionErrorMessageTest.cs
index 4c3d594ad1..4a722dd409 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/DataConversionErrorMessageTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/DataConversionErrorMessageTest.cs
@@ -28,7 +28,7 @@ public InitialDatabase()
srcConstr = DataTestUtility.TCPConnectionString;
Connection = new SqlConnection(srcConstr);
- TableName = DataTestUtility.GetUniqueNameForSqlServer("SqlBulkCopyTest_CopyStringToIntTest_");
+ TableName = DataTestUtility.GetLongName("SqlBulkCopyTest_CopyStringToIntTest_");
InitialTable(Connection, TableName);
}
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandCompletedTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandCompletedTest.cs
index 8e38bee7c0..21ff771ac0 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandCompletedTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandCompletedTest.cs
@@ -11,7 +11,7 @@ public static class SqlCommandCompletedTest
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))]
public static void VerifyStatmentCompletedCalled()
{
- string tableName = DataTestUtility.GetUniqueNameForSqlServer("stmt");
+ string tableName = DataTestUtility.GetLongName("stmt");
using (var conn = new SqlConnection(s_connStr))
using (var cmd = conn.CreateCommand())
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandSetTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandSetTest.cs
index 26b11055c2..7f28a4a09a 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandSetTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandSetTest.cs
@@ -15,8 +15,8 @@ public class SqlCommandSetTest
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))]
public void TestByteArrayParameters()
{
- string tableName = DataTestUtility.GetUniqueNameForSqlServer("CMD");
- string procName = DataTestUtility.GetUniqueNameForSqlServer("CMD");
+ string tableName = DataTestUtility.GetLongName("CMD");
+ string procName = DataTestUtility.GetLongName("CMD");
byte[] bArray = new byte[] { 1, 2, 3 };
using (var connection = new SqlConnection(DataTestUtility.TCPConnectionString))
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlFileStreamTest/SqlFileStreamTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlFileStreamTest/SqlFileStreamTest.cs
index 09c369e11e..3bea30c6b8 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlFileStreamTest/SqlFileStreamTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlFileStreamTest/SqlFileStreamTest.cs
@@ -221,7 +221,7 @@ private static string SetupFileStreamDB()
fileStreamDir += "\\";
}
- string dbName = DataTestUtility.GetUniqueName("FS", false);
+ string dbName = DataTestUtility.GetShortName("FS", false);
string createDBQuery = @$"CREATE DATABASE [{dbName}]
ON PRIMARY
(NAME = PhotoLibrary_data,
@@ -266,7 +266,7 @@ private static void DropFileStreamDb(string connString)
private static string SetupTable(string connString)
{
// Generate random table name
- string tempTable = DataTestUtility.GetUniqueNameForSqlServer("fs");
+ string tempTable = DataTestUtility.GetLongName("fs");
// Create table
string createTable = $"CREATE TABLE {tempTable} (EmployeeId INT NOT NULL PRIMARY KEY, Photo VARBINARY(MAX) FILESTREAM NULL, RowGuid UNIQUEIDENTIFIER NOT NULL ROWGUIDCOL UNIQUE DEFAULT NEWID() ) ";
ExecuteNonQueryCommand(createTable, connString);
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/SqlServerTypesTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/SqlServerTypesTest.cs
index 0e64b091b6..8f697af02e 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/SqlServerTypesTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/SqlServerTypesTest.cs
@@ -434,7 +434,7 @@ private static string GetUdtName(Type udtClrType)
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))]
public static void TestSqlServerTypesInsertAndRead()
{
- string tableName = DataTestUtility.GetUniqueNameForSqlServer("Type");
+ string tableName = DataTestUtility.GetLongName("Type");
string allTypesSQL = @$"
if not exists (select * from sysobjects where name='{tableName}' and xtype='U')
Begin
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UdtBulkCopyTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UdtBulkCopyTest.cs
index 90ceed4952..5f17036b4f 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UdtBulkCopyTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UdtBulkCopyTest.cs
@@ -18,9 +18,9 @@ public void RunCopyTest()
_connStr = (new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { InitialCatalog = DataTestUtility.UdtTestDbName }).ConnectionString;
SqlConnection conn = new SqlConnection(_connStr);
- string cities = DataTestUtility.GetUniqueNameForSqlServer("UdtBulkCopy_cities");
- string customers = DataTestUtility.GetUniqueNameForSqlServer("UdtBulkCopy_customers");
- string circles = DataTestUtility.GetUniqueNameForSqlServer("UdtBulkCopy_circles");
+ string cities = DataTestUtility.GetLongName("UdtBulkCopy_cities");
+ string customers = DataTestUtility.GetLongName("UdtBulkCopy_customers");
+ string circles = DataTestUtility.GetLongName("UdtBulkCopy_circles");
conn.Open();
try
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UdtTest2.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UdtTest2.cs
index 1f07242ee3..ef38e43dda 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UdtTest2.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UdtTest2.cs
@@ -84,8 +84,8 @@ public void UDTParams_Binary()
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsUdtTestDatabasePresent), nameof(DataTestUtility.AreConnStringsSetup))]
public void UDTParams_Invalid2()
{
- string spInsertCustomer = DataTestUtility.GetUniqueNameForSqlServer("spUdtTest2_InsertCustomer");
- string tableName = DataTestUtility.GetUniqueNameForSqlServer("UdtTest2");
+ string spInsertCustomer = DataTestUtility.GetLongName("spUdtTest2_InsertCustomer");
+ string tableName = DataTestUtility.GetLongName("UdtTest2");
using (SqlConnection conn = new SqlConnection(_connStr))
using (SqlCommand cmd = conn.CreateCommand())
@@ -143,8 +143,8 @@ public void UDTParams_Invalid()
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsUdtTestDatabasePresent), nameof(DataTestUtility.AreConnStringsSetup))]
public void UDTParams_TypedNull()
{
- string spInsertCustomer = DataTestUtility.GetUniqueNameForSqlServer("spUdtTest2_InsertCustomer");
- string tableName = DataTestUtility.GetUniqueNameForSqlServer("UdtTest2_Customer");
+ string spInsertCustomer = DataTestUtility.GetLongName("spUdtTest2_InsertCustomer");
+ string tableName = DataTestUtility.GetLongName("UdtTest2_Customer");
using (SqlConnection conn = new SqlConnection(_connStr))
using (SqlCommand cmd = conn.CreateCommand())
@@ -188,8 +188,8 @@ public void UDTParams_TypedNull()
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsUdtTestDatabasePresent), nameof(DataTestUtility.AreConnStringsSetup))]
public void UDTParams_NullInput()
{
- string spInsertCustomer = DataTestUtility.GetUniqueNameForSqlServer("spUdtTest2_InsertCustomer");
- string tableName = DataTestUtility.GetUniqueNameForSqlServer("UdtTest2_Customer");
+ string spInsertCustomer = DataTestUtility.GetLongName("spUdtTest2_InsertCustomer");
+ string tableName = DataTestUtility.GetLongName("UdtTest2_Customer");
using (SqlConnection conn = new SqlConnection(_connStr))
using (SqlCommand cmd = conn.CreateCommand())
@@ -232,8 +232,8 @@ public void UDTParams_NullInput()
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsUdtTestDatabasePresent), nameof(DataTestUtility.AreConnStringsSetup))]
public void UDTParams_InputOutput()
{
- string spInsertCity = DataTestUtility.GetUniqueNameForSqlServer("spUdtTest2_InsertCity");
- string tableName = DataTestUtility.GetUniqueNameForSqlServer("UdtTest2");
+ string spInsertCity = DataTestUtility.GetLongName("spUdtTest2_InsertCity");
+ string tableName = DataTestUtility.GetLongName("UdtTest2");
using (SqlConnection conn = new SqlConnection(_connStr))
{
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/Utf8SupportTest/Utf8SupportTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/Utf8SupportTest/Utf8SupportTest.cs
index effecb35b3..41f81b12e3 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/Utf8SupportTest/Utf8SupportTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/Utf8SupportTest/Utf8SupportTest.cs
@@ -37,7 +37,7 @@ public static void CheckSupportUtf8ConnectionProperty()
public static void UTF8databaseTest()
{
const string letters = @"!\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u007f€\u0081‚ƒ„…†‡ˆ‰Š‹Œ\u008dŽ\u008f\u0090‘’“”•–—˜™š›œ\u009džŸ ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ";
- string dbName = DataTestUtility.GetUniqueNameForSqlServer("UTF8databaseTest", false);
+ string dbName = DataTestUtility.GetLongName("UTF8databaseTest", false);
string tblName = "Table1";
SqlConnectionStringBuilder builder = new(DataTestUtility.TCPConnectionString);
From a236dac188dbc0db7ac3fa93254a3d305733fde2 Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Mon, 8 Sep 2025 12:09:23 -0300
Subject: [PATCH 03/11] User Story 38481: Fix unique db object name issues
- Removed DateOnly tests that aren't supported on 5.1.
---
.../SQL/ParameterTest/ParametersTest.cs | 120 ------------------
1 file changed, 120 deletions(-)
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs
index 7182ce768c..cd2c52083c 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs
@@ -307,126 +307,6 @@ public static void TestParametersWithDatatablesTVPInsert()
}
}
-#if !NETFRAMEWORK
-
- [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))]
- public static void TestDateOnlyTVPDataTable_CommandSP()
- {
- string tableTypeName = "[dbo]." + DataTestUtility.GetLongName("UDTTTestDateOnlyTVP");
- string spName = DataTestUtility.GetLongName("spTestDateOnlyTVP");
- SqlConnection connection = new(s_connString);
- try
- {
- connection.Open();
- using (SqlCommand cmd = connection.CreateCommand())
- {
- cmd.CommandType = CommandType.Text;
- cmd.CommandText = $"CREATE TYPE {tableTypeName} AS TABLE ([DateColumn] date NULL, [TimeColumn] time NULL)";
- cmd.ExecuteNonQuery();
- cmd.CommandText = $"CREATE PROCEDURE {spName} (@dates {tableTypeName} READONLY) AS SELECT COUNT(*) FROM @dates";
- cmd.ExecuteNonQuery();
- }
- using (SqlCommand cmd = connection.CreateCommand())
- {
- cmd.CommandText = spName;
- cmd.CommandType = CommandType.StoredProcedure;
-
- DataTable dtTest = new();
- dtTest.Columns.Add(new DataColumn("DateColumn", typeof(DateOnly)));
- dtTest.Columns.Add(new DataColumn("TimeColumn", typeof(TimeOnly)));
- var dataRow = dtTest.NewRow();
- dataRow["DateColumn"] = new DateOnly(2023, 11, 15);
- dataRow["TimeColumn"] = new TimeOnly(12, 30, 45);
- dtTest.Rows.Add(dataRow);
-
- cmd.Parameters.Add(new SqlParameter
- {
- ParameterName = "@dates",
- SqlDbType = SqlDbType.Structured,
- TypeName = tableTypeName,
- Value = dtTest,
- });
-
- cmd.ExecuteNonQuery();
- }
- }
- finally
- {
- DataTestUtility.DropStoredProcedure(connection, spName);
- DataTestUtility.DropUserDefinedType(connection, tableTypeName);
- }
- }
-
- [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))]
- public static void TestDateOnlyTVPSqlDataRecord_CommandSP()
- {
- string tableTypeName = "[dbo]." + DataTestUtility.GetLongName("UDTTTestDateOnlySqlDataRecordTVP");
- string spName = DataTestUtility.GetLongName("spTestDateOnlySqlDataRecordTVP");
- SqlConnection connection = new(s_connString);
- try
- {
- connection.Open();
- using (SqlCommand cmd = connection.CreateCommand())
- {
- cmd.CommandType = CommandType.Text;
- cmd.CommandText = $"CREATE TYPE {tableTypeName} AS TABLE ([DateColumn] date NULL, [TimeColumn] time NULL)";
- cmd.ExecuteNonQuery();
- cmd.CommandText = $"CREATE PROCEDURE {spName} (@dates {tableTypeName} READONLY) AS SELECT COUNT(*) FROM @dates";
- cmd.ExecuteNonQuery();
- }
- using (SqlCommand cmd = connection.CreateCommand())
- {
- cmd.CommandText = spName;
- cmd.CommandType = CommandType.StoredProcedure;
-
- SqlMetaData[] metadata = new SqlMetaData[]
- {
- new SqlMetaData("DateColumn", SqlDbType.Date),
- new SqlMetaData("TimeColumn", SqlDbType.Time)
- };
-
- SqlDataRecord record1 = new SqlDataRecord(metadata);
- record1.SetValues(new DateOnly(2023, 11, 15), new TimeOnly(12, 30, 45));
-
- SqlDataRecord record2 = new SqlDataRecord(metadata);
- record2.SetValues(new DateOnly(2025, 11, 15), new TimeOnly(13, 31, 46));
-
- IList featureInserts = new List
- {
- record1,
- record2,
- };
-
- cmd.Parameters.Add(new SqlParameter
- {
- ParameterName = "@dates",
- SqlDbType = SqlDbType.Structured,
- TypeName = tableTypeName,
- Value = featureInserts,
- });
-
- using var reader = cmd.ExecuteReader();
-
- Assert.True(reader.HasRows);
-
- int count = 0;
- while (reader.Read())
- {
- Assert.NotNull(reader[0]);
- count++;
- }
-
- Assert.Equal(1, count);
- }
- }
- finally
- {
- DataTestUtility.DropStoredProcedure(connection, spName);
- DataTestUtility.DropUserDefinedType(connection, tableTypeName);
- }
- }
-#endif
-
#region Scaled Decimal Parameter & TVP Test
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))]
[InlineData("CAST(1.0 as decimal(38, 37))", "1.0000000000000000000000000000")]
From cca23e5e834bcdc1a582e31b862c771e53759daf Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Thu, 7 Aug 2025 15:18:15 -0300
Subject: [PATCH 04/11] Add CodeQL suppression for DefaultAzureCredential use
in Production (#3542) - Adjusted CodeQL suppression to meet the strict
requirements of where it may appear relative to the flagged code. - Adding
catch for macOS socket error to log and ignore.
---
.../Data/SqlClient/SNI/SNITcpHandle.cs | 27 ++++++++++++++++---
.../ActiveDirectoryAuthenticationProvider.cs | 23 +++++++++++++++-
2 files changed, 46 insertions(+), 4 deletions(-)
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs
index b8e38978b9..9537eaf1c6 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs
@@ -851,9 +851,30 @@ public override uint Receive(out SNIPacket packet, int timeoutInMilliseconds)
}
finally
{
- // Reset the socket timeout to Timeout.Infinite after the receive operation is done
- // to avoid blocking the thread in case of a timeout error.
- _socket.ReceiveTimeout = Timeout.Infinite;
+ const int resetTimeout = Timeout.Infinite;
+
+ try
+ {
+ // Reset the socket timeout to Timeout.Infinite after
+ // the receive operation is done to avoid blocking the
+ // thread in case of a timeout error.
+ _socket.ReceiveTimeout = resetTimeout;
+
+ }
+ catch (SocketException ex)
+ {
+ // We sometimes see setting the ReceiveTimeout fail
+ // on macOS. There's isn't much we can do about it
+ // though, so just log and move on.
+ SqlClientEventSource.Log.TrySNITraceEvent(
+ nameof(SNITCPHandle),
+ EventType.ERR,
+ "Connection Id {0}, Failed to reset socket " +
+ "receive timeout to {1}: {2}",
+ _connectionId,
+ resetTimeout,
+ ex.Message);
+ }
}
}
}
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs
index 73fce50774..d69cbe06ab 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs
@@ -587,7 +587,28 @@ private static TokenCredentialData CreateTokenCredentialInstance(TokenCredential
defaultAzureCredentialOptions.WorkloadIdentityClientId = tokenCredentialKey._clientId;
}
- return new TokenCredentialData(new DefaultAzureCredential(defaultAzureCredentialOptions), GetHash(secret));
+ // SqlClient is a library and provides support to acquire access
+ // token using 'DefaultAzureCredential' on user demand when they
+ // specify 'Authentication = Active Directory Default' in
+ // connection string.
+ //
+ // Default Azure Credential is instantiated by the calling
+ // application when using "Active Directory Default"
+ // authentication code to connect to Azure SQL instance.
+ // SqlClient is a library, doesn't instantiate the credential
+ // without running application instructions.
+ //
+ // Note that CodeQL suppression support can only detect
+ // suppression comments that appear immediately above the
+ // flagged statement, or appended to the end of the statement.
+ // Multi-line justifications are not supported.
+ //
+ // https://eng.ms/docs/cloud-ai-platform/devdiv/one-engineering-system-1es/1es-docs/codeql/codeql-semmle#guidance-on-suppressions
+ //
+ // CodeQL [SM05137] See above for justification.
+ DefaultAzureCredential cred = new(defaultAzureCredentialOptions);
+
+ return new TokenCredentialData(cred, GetHash(secret));
}
TokenCredentialOptions tokenCredentialOptions = new() { AuthorityHost = new Uri(tokenCredentialKey._authority) };
From 7dfa969c382a5161384a877df45b39f4d8d6553a Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Tue, 9 Sep 2025 10:43:31 -0300
Subject: [PATCH 05/11] - Added back some blocks that were removed by
cherry-picks. - Added console diagnostics to see when Enclave tables are
dropped.
---
.../AlwaysEncrypted/CspProviderExt.cs | 49 +++++++++++++++++++
.../TestFixtures/Setup/Table.cs | 3 ++
.../SQL/ConnectivityTests/ConnectivityTest.cs | 9 ++++
.../SQL/ParameterTest/ParametersTest.cs | 1 -
4 files changed, 61 insertions(+), 1 deletion(-)
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CspProviderExt.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CspProviderExt.cs
index e26c67382e..49071def2e 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CspProviderExt.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CspProviderExt.cs
@@ -157,6 +157,55 @@ public void TestRoundTripWithCSPAndCertStoreProvider()
}
}
+ [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.
///
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/Table.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/Table.cs
index b18e5a0ae8..e19ff59f80 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/Table.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/Table.cs
@@ -19,6 +19,9 @@ public override void Drop(SqlConnection sqlConnection)
command.CommandText = sql;
command.ExecuteNonQuery();
}
+
+ // TODO: Remove.
+ System.Console.WriteLine($"Dropped table {Name} from {sqlConnection.ConnectionString}");
}
public static void DeleteData(string tableName, SqlConnection sqlConnection)
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 dfdbf5229f..57d6725ce5 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/ConnectivityTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/ConnectivityTest.cs
@@ -398,6 +398,15 @@ private static bool CanCreateAliases()
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)
{
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs
index cd2c52083c..6136f0bfc1 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs
@@ -8,7 +8,6 @@
using System.Data;
using System.Data.SqlTypes;
using System.Threading;
-using Microsoft.Data.SqlClient.Server;
using Xunit;
namespace Microsoft.Data.SqlClient.ManualTesting.Tests
From 58eca557f2e7a72438d0dfaebbec71db68b14953 Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Tue, 9 Sep 2025 11:35:46 -0300
Subject: [PATCH 06/11] - Fixed typo in code that only gets compiled when
building on Windows (eek!)
---
.../tests/ManualTests/AlwaysEncrypted/CspProviderExt.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CspProviderExt.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CspProviderExt.cs
index 49071def2e..93ff7e52ec 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CspProviderExt.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CspProviderExt.cs
@@ -162,7 +162,7 @@ public void TestRoundTripWithCSPAndCertStoreProvider()
public void TestEncryptDecryptWithCSP(string connectionString)
{
string providerName = @"Microsoft Enhanced RSA and AES Cryptographic Provider";
- string keyIdentifier = DataTestUtility.GetUniqueNameForSqlServer("CSP");
+ string keyIdentifier = DataTestUtility.GetLongName("CSP");
try
{
From 8f49502f5588b1d3bbf5b9b23329e3f5cd0fdca6 Mon Sep 17 00:00:00 2001
From: Benjamin Russell
Date: Thu, 5 Jun 2025 17:02:41 -0500
Subject: [PATCH 07/11] Tests | Remove hardcoded credentials from ManualTests
(#3204)
* Initial removal of CertificateUtility.CreateCertificate
One test implied that DataTestUtility.AKVUrl would point to an RSA key which aligned with the certificate's private key. Switching this to dynamically generate the key in places.
* Hotfix for Azure Key Vault tests
* Removed hardcoded references to Azure Key Vault key
* Removed hardcoded references to CertificateUtilityWin
These were mostly related to generating CSP keys.
* Code review changes
* Reorder properties and constructors
* Move AEConnectionStringProviderWithCspParameters to its own file
* Tweak to the AKV token acquisition
* Code review
Redundant bracket, alphabetised the ManualTesting csproj
* Update src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs
Let's try @edwardneal's idea
Co-authored-by: Edward Neal <55035479+edwardneal@users.noreply.github.com>
* Update src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs
Co-authored-by: Edward Neal <55035479+edwardneal@users.noreply.github.com>
* Fixes as per @edwardneal's suggestions
* Fix as per @edwardneal's suggestion
* Fix missing `new`
Co-authored-by: Edward Neal <55035479+edwardneal@users.noreply.github.com>
* Update src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategyAzureKeyVault.cs
Co-authored-by: Edward Neal <55035479+edwardneal@users.noreply.github.com>
* Update src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategyAzureKeyVault.cs
Co-authored-by: Edward Neal <55035479+edwardneal@users.noreply.github.com>
* Address comment that we don't need a CspParameters object as part of the test arguments
* Move test arguments into property (the class was only used in a single location)
* Cleanup test code
* Tweak default provider discovery code to handle edge cases a bit better
* Address comment regarding readonly member variables
Apply long line chomping
* Addressing the last of the comments.
---------
Co-authored-by: Edward Neal <55035479+edwardneal@users.noreply.github.com>
---
.../ManualTests/AlwaysEncrypted/AKVTests.cs | 10 +-
.../AlwaysEncrypted/AKVUnitTests.cs | 77 +++--
.../AlwaysEncrypted/ConversionTests.cs | 29 +-
.../AlwaysEncrypted/CspProviderExt.cs | 246 +++++---------
.../EnclaveAzureDatabaseTests.cs | 6 +-
.../AlwaysEncrypted/ExceptionTestAKVStore.cs | 62 ++--
.../TestFixtures/AzureKeyVaultKeyFixture.cs | 19 ++
.../TestFixtures/SQLSetupStrategy.cs | 51 +--
.../SQLSetupStrategyAzureKeyVault.cs | 65 +++-
.../SQLSetupStrategyCertStoreProvider.cs | 7 +-
.../TestFixtures/SQLSetupStrategyCspExt.cs | 50 ---
.../SQLSetupStrategyCspProvider.cs | 77 +++++
.../TestFixtures/Setup/CertificateUtility.cs | 89 -----
.../Setup/CertificateUtilityWin.cs | 264 ---------------
.../TestTrustedMasterKeyPaths.cs | 27 +-
.../ManualTests/DataCommon/DataTestUtility.cs | 7 +-
.../SqlClientCustomTokenCredential.cs | 9 +-
....Data.SqlClient.ManualTesting.Tests.csproj | 4 +-
.../Fixtures/AzureKeyVaultKeyFixtureBase.cs | 63 ++++
.../Fixtures/CertificateFixtureBase.cs | 308 ++++++++++++++++++
.../ColumnMasterKeyCertificateFixture.cs | 29 ++
.../Fixtures/CspCertificateFixture.cs | 47 +++
...rosoft.Data.SqlClient.TestUtilities.csproj | 2 +
23 files changed, 834 insertions(+), 714 deletions(-)
create mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/AzureKeyVaultKeyFixture.cs
delete mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategyCspExt.cs
create mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategyCspProvider.cs
delete mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CertificateUtilityWin.cs
create mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/AzureKeyVaultKeyFixtureBase.cs
create mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/CertificateFixtureBase.cs
create mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/ColumnMasterKeyCertificateFixture.cs
create mode 100644 src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Fixtures/CspCertificateFixture.cs
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVTests.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVTests.cs
index 3f2b7a83fa..ab4f38f882 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVTests.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVTests.cs
@@ -62,15 +62,15 @@ public void TestEncryptDecryptWithAKV()
[PlatformSpecific(TestPlatforms.Windows)]
public void TestRoundTripWithAKVAndCertStoreProvider()
{
- using SQLSetupStrategyCertStoreProvider certStoreFixture = new ();
+ SqlColumnEncryptionCertificateStoreProvider certStoreProvider = new SqlColumnEncryptionCertificateStoreProvider();
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);
+ byte[] encryptedColumnEncryptionKeyUsingAKV = _fixture.AkvStoreProvider.EncryptColumnEncryptionKey(_fixture.AkvKeyUrl, @"RSA_OAEP", plainTextColumnEncryptionKey);
+ byte[] columnEncryptionKeyReturnedAKV2Cert = certStoreProvider.DecryptColumnEncryptionKey(_fixture.ColumnMasterKeyPath, @"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);
+ byte[] encryptedColumnEncryptionKeyUsingCert = certStoreProvider.EncryptColumnEncryptionKey(_fixture.ColumnMasterKeyPath, @"RSA_OAEP", plainTextColumnEncryptionKey);
+ byte[] columnEncryptionKeyReturnedCert2AKV = _fixture.AkvStoreProvider.DecryptColumnEncryptionKey(_fixture.AkvKeyUrl, @"RSA_OAEP", encryptedColumnEncryptionKeyUsingCert);
Assert.True(plainTextColumnEncryptionKey.SequenceEqual(columnEncryptionKeyReturnedCert2AKV), @"Roundtrip failed");
}
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs
index 893c50799b..ed7061cf65 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs
@@ -14,13 +14,20 @@
namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted
{
- public static class AKVUnitTests
+ public class AKVUnitTests : IClassFixture
{
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 readonly AzureKeyVaultKeyFixture _fixture;
+
+ public AKVUnitTests(AzureKeyVaultKeyFixture fixture)
+ {
+ _fixture = fixture;
+ }
+
private static void ValidateAKVTraces(List eventData, Guid threadActivityId)
{
Assert.NotNull(eventData);
@@ -64,36 +71,36 @@ private static void ValidateAKVTraces(List eventData, Gui
}
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))]
- public static void LegacyAuthenticationCallbackTest()
+ public 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);
+ byte[] encryptedCek = akvProvider.EncryptColumnEncryptionKey(_fixture.GeneratedKeyUri, EncryptionAlgorithm, s_columnEncryptionKey);
+ byte[] decryptedCek = akvProvider.DecryptColumnEncryptionKey(_fixture.GeneratedKeyUri, EncryptionAlgorithm, encryptedCek);
Assert.Equal(s_columnEncryptionKey, decryptedCek);
ValidateAKVTraces(AKVListener.EventData, activityId);
}
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))]
- public static void TokenCredentialTest()
+ public void TokenCredentialTest()
{
Guid activityId = Trace.CorrelationManager.ActivityId = Guid.NewGuid();
using DataTestUtility.AKVEventListener AKVListener = new();
SqlColumnEncryptionAzureKeyVaultProvider akvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(DataTestUtility.GetTokenCredential());
- byte[] encryptedCek = akvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, s_columnEncryptionKey);
- byte[] decryptedCek = akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, encryptedCek);
+ byte[] encryptedCek = akvProvider.EncryptColumnEncryptionKey(_fixture.GeneratedKeyUri, EncryptionAlgorithm, s_columnEncryptionKey);
+ byte[] decryptedCek = akvProvider.DecryptColumnEncryptionKey(_fixture.GeneratedKeyUri, EncryptionAlgorithm, encryptedCek);
Assert.Equal(s_columnEncryptionKey, decryptedCek);
ValidateAKVTraces(AKVListener.EventData, activityId);
}
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))]
- public static void TokenCredentialRotationTest()
+ public void TokenCredentialRotationTest()
{
Guid activityId = Trace.CorrelationManager.ActivityId = Guid.NewGuid();
using DataTestUtility.AKVEventListener AKVListener = new();
@@ -103,19 +110,19 @@ public static void TokenCredentialRotationTest()
SqlColumnEncryptionAzureKeyVaultProvider newAkvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(DataTestUtility.GetTokenCredential());
- byte[] encryptedCekWithNewProvider = newAkvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, s_columnEncryptionKey);
- byte[] decryptedCekWithOldProvider = oldAkvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, encryptedCekWithNewProvider);
+ byte[] encryptedCekWithNewProvider = newAkvProvider.EncryptColumnEncryptionKey(_fixture.GeneratedKeyUri, EncryptionAlgorithm, s_columnEncryptionKey);
+ byte[] decryptedCekWithOldProvider = oldAkvProvider.DecryptColumnEncryptionKey(_fixture.GeneratedKeyUri, EncryptionAlgorithm, encryptedCekWithNewProvider);
Assert.Equal(s_columnEncryptionKey, decryptedCekWithOldProvider);
- byte[] encryptedCekWithOldProvider = oldAkvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, s_columnEncryptionKey);
- byte[] decryptedCekWithNewProvider = newAkvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, encryptedCekWithOldProvider);
+ byte[] encryptedCekWithOldProvider = oldAkvProvider.EncryptColumnEncryptionKey(_fixture.GeneratedKeyUri, EncryptionAlgorithm, s_columnEncryptionKey);
+ byte[] decryptedCekWithNewProvider = newAkvProvider.DecryptColumnEncryptionKey(_fixture.GeneratedKeyUri, EncryptionAlgorithm, encryptedCekWithOldProvider);
Assert.Equal(s_columnEncryptionKey, decryptedCekWithNewProvider);
ValidateAKVTraces(AKVListener.EventData, activityId);
}
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))]
- public static void ReturnSpecifiedVersionOfKeyWhenItIsNotTheMostRecentVersion()
+ public void ReturnSpecifiedVersionOfKeyWhenItIsNotTheMostRecentVersion()
{
Uri keyPathUri = new Uri(DataTestUtility.AKVOriginalUrl);
Uri vaultUri = new Uri(keyPathUri.GetLeftPart(UriPartial.Authority));
@@ -161,7 +168,7 @@ public static void ThrowWhenUrlHasLessThanThreeSegments()
}
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))]
- public static void DecryptedCekIsCachedDuringDecryption()
+ public void DecryptedCekIsCachedDuringDecryption()
{
Guid activityId = Trace.CorrelationManager.ActivityId = Guid.NewGuid();
using DataTestUtility.AKVEventListener AKVListener = new();
@@ -170,23 +177,23 @@ public static void DecryptedCekIsCachedDuringDecryption()
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[] encryptedKey1 = akvProvider.EncryptColumnEncryptionKey(_fixture.GeneratedKeyUri, "RSA_OAEP", plaintextKey1);
+ byte[] encryptedKey2 = akvProvider.EncryptColumnEncryptionKey(_fixture.GeneratedKeyUri, "RSA_OAEP", plaintextKey2);
+ byte[] encryptedKey3 = akvProvider.EncryptColumnEncryptionKey(_fixture.GeneratedKeyUri, "RSA_OAEP", plaintextKey3);
- byte[] decryptedKey1 = akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", encryptedKey1);
+ byte[] decryptedKey1 = akvProvider.DecryptColumnEncryptionKey(_fixture.GeneratedKeyUri, "RSA_OAEP", encryptedKey1);
Assert.Equal(1, GetCacheCount(cekCacheName, akvProvider));
Assert.Equal(plaintextKey1, decryptedKey1);
- decryptedKey1 = akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", encryptedKey1);
+ decryptedKey1 = akvProvider.DecryptColumnEncryptionKey(_fixture.GeneratedKeyUri, "RSA_OAEP", encryptedKey1);
Assert.Equal(1, GetCacheCount(cekCacheName, akvProvider));
Assert.Equal(plaintextKey1, decryptedKey1);
- byte[] decryptedKey2 = akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", encryptedKey2);
+ byte[] decryptedKey2 = akvProvider.DecryptColumnEncryptionKey(_fixture.GeneratedKeyUri, "RSA_OAEP", encryptedKey2);
Assert.Equal(2, GetCacheCount(cekCacheName, akvProvider));
Assert.Equal(plaintextKey2, decryptedKey2);
- byte[] decryptedKey3 = akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", encryptedKey3);
+ byte[] decryptedKey3 = akvProvider.DecryptColumnEncryptionKey(_fixture.GeneratedKeyUri, "RSA_OAEP", encryptedKey3);
Assert.Equal(3, GetCacheCount(cekCacheName, akvProvider));
Assert.Equal(plaintextKey3, decryptedKey3);
@@ -194,33 +201,33 @@ public static void DecryptedCekIsCachedDuringDecryption()
}
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))]
- public static void SignatureVerificationResultIsCachedDuringVerification()
+ public 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);
+ byte[] signature = akvProvider.SignColumnMasterKeyMetadata(_fixture.GeneratedKeyUri, true);
+ byte[] signature2 = akvProvider.SignColumnMasterKeyMetadata(_fixture.GeneratedKeyUri, true);
+ byte[] signatureWithoutEnclave = akvProvider.SignColumnMasterKeyMetadata(_fixture.GeneratedKeyUri, false);
- Assert.True(akvProvider.VerifyColumnMasterKeyMetadata(DataTestUtility.AKVUrl, true, signature));
+ Assert.True(akvProvider.VerifyColumnMasterKeyMetadata(_fixture.GeneratedKeyUri, true, signature));
Assert.Equal(1, GetCacheCount(signatureVerificationResultCacheName, akvProvider));
- Assert.True(akvProvider.VerifyColumnMasterKeyMetadata(DataTestUtility.AKVUrl, true, signature));
+ Assert.True(akvProvider.VerifyColumnMasterKeyMetadata(_fixture.GeneratedKeyUri, true, signature));
Assert.Equal(1, GetCacheCount(signatureVerificationResultCacheName, akvProvider));
- Assert.True(akvProvider.VerifyColumnMasterKeyMetadata(DataTestUtility.AKVUrl, true, signature2));
+ Assert.True(akvProvider.VerifyColumnMasterKeyMetadata(_fixture.GeneratedKeyUri, true, signature2));
Assert.Equal(1, GetCacheCount(signatureVerificationResultCacheName, akvProvider));
- Assert.True(akvProvider.VerifyColumnMasterKeyMetadata(DataTestUtility.AKVUrl, false, signatureWithoutEnclave));
+ Assert.True(akvProvider.VerifyColumnMasterKeyMetadata(_fixture.GeneratedKeyUri, false, signatureWithoutEnclave));
Assert.Equal(2, GetCacheCount(signatureVerificationResultCacheName, akvProvider));
ValidateAKVTraces(AKVListener.EventData, activityId);
}
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))]
- public static void CekCacheEntryIsEvictedAfterTtlExpires()
+ public void CekCacheEntryIsEvictedAfterTtlExpires()
{
Guid activityId = Trace.CorrelationManager.ActivityId = Guid.NewGuid();
using DataTestUtility.AKVEventListener AKVListener = new();
@@ -228,9 +235,9 @@ public static void CekCacheEntryIsEvictedAfterTtlExpires()
SqlColumnEncryptionAzureKeyVaultProvider akvProvider = new(new SqlClientCustomTokenCredential());
akvProvider.ColumnEncryptionKeyCacheTtl = TimeSpan.FromSeconds(5);
byte[] plaintextKey = { 1, 2, 3 };
- byte[] encryptedKey = akvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", plaintextKey);
+ byte[] encryptedKey = akvProvider.EncryptColumnEncryptionKey(_fixture.GeneratedKeyUri, "RSA_OAEP", plaintextKey);
- akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", encryptedKey);
+ akvProvider.DecryptColumnEncryptionKey(_fixture.GeneratedKeyUri, "RSA_OAEP", encryptedKey);
Assert.True(CekCacheContainsKey(encryptedKey, akvProvider));
Assert.Equal(1, GetCacheCount(cekCacheName, akvProvider));
@@ -242,7 +249,7 @@ public static void CekCacheEntryIsEvictedAfterTtlExpires()
}
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))]
- public static void CekCacheShouldBeDisabledWhenCustomProviderIsRegisteredGlobally()
+ public void CekCacheShouldBeDisabledWhenCustomProviderIsRegisteredGlobally()
{
if (SQLSetupStrategyAzureKeyVault.IsAKVProviderRegistered)
{
@@ -255,9 +262,9 @@ public static void CekCacheShouldBeDisabledWhenCustomProviderIsRegisteredGloball
SqlColumnEncryptionAzureKeyVaultProvider akvProviderInGlobalCache =
globalProviders["AZURE_KEY_VAULT"] as SqlColumnEncryptionAzureKeyVaultProvider;
byte[] plaintextKey = { 1, 2, 3 };
- byte[] encryptedKey = akvProviderInGlobalCache.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", plaintextKey);
+ byte[] encryptedKey = akvProviderInGlobalCache.EncryptColumnEncryptionKey(_fixture.GeneratedKeyUri, "RSA_OAEP", plaintextKey);
- akvProviderInGlobalCache.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, "RSA_OAEP", encryptedKey);
+ akvProviderInGlobalCache.DecryptColumnEncryptionKey(_fixture.GeneratedKeyUri, "RSA_OAEP", encryptedKey);
Assert.Equal(0, GetCacheCount(cekCacheName, akvProviderInGlobalCache));
}
}
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ConversionTests.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ConversionTests.cs
index 04c661902d..a7be11add4 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ConversionTests.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ConversionTests.cs
@@ -14,11 +14,12 @@
using System.Security.Cryptography.X509Certificates;
using Xunit;
using Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup;
+using Microsoft.Data.SqlClient.TestUtilities.Fixtures;
namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted
{
[PlatformSpecific(TestPlatforms.Windows)]
- public sealed class ConversionTests : IDisposable
+ public sealed class ConversionTests : IDisposable, IClassFixture
{
private const string IdentityColumnName = "IdentityColumn";
@@ -29,8 +30,6 @@ public sealed class ConversionTests : IDisposable
private const decimal SmallMoneyMinValue = -214748.3648M;
private const int MaxLength = 10000;
private int NumberOfRows = DataTestUtility.EnclaveEnabled ? 10 : 100;
- private static X509Certificate2 certificate;
- private ColumnMasterKey columnMasterKey;
private ColumnEncryptionKey columnEncryptionKey;
private SqlColumnEncryptionCertificateStoreProvider certStoreProvider = new SqlColumnEncryptionCertificateStoreProvider();
private List _databaseObjects = new List();
@@ -54,18 +53,20 @@ public ColumnMetaData(SqlDbType columnType, int columnSize, int precision, int s
public bool UseMax { get; set; }
}
- public ConversionTests()
+ public ConversionTests(ColumnMasterKeyCertificateFixture fixture)
{
- if (certificate == null)
- {
- certificate = CertificateUtility.CreateCertificate();
- }
- columnMasterKey = new CspColumnMasterKey(DatabaseHelper.GenerateUniqueName("CMK"), certificate.Thumbprint, certStoreProvider, DataTestUtility.EnclaveEnabled);
- _databaseObjects.Add(columnMasterKey);
-
- columnEncryptionKey = new ColumnEncryptionKey(DatabaseHelper.GenerateUniqueName("CEK"),
- columnMasterKey,
- certStoreProvider);
+ X509Certificate2 certificate = fixture.ColumnMasterKeyCertificate;
+ ColumnMasterKey columnMasterKey1 = new CspColumnMasterKey(
+ DatabaseHelper.GenerateUniqueName("CMK"),
+ certificate.Thumbprint,
+ certStoreProvider,
+ DataTestUtility.EnclaveEnabled);
+ _databaseObjects.Add(columnMasterKey1);
+
+ columnEncryptionKey = new ColumnEncryptionKey(
+ DatabaseHelper.GenerateUniqueName("CEK"),
+ columnMasterKey1,
+ certStoreProvider);
_databaseObjects.Add(columnEncryptionKey);
foreach (string connectionStr in DataTestUtility.AEConnStringsSetup)
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CspProviderExt.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CspProviderExt.cs
index 93ff7e52ec..f3e9bcd7fa 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CspProviderExt.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CspProviderExt.cs
@@ -2,14 +2,16 @@
// 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.IO;
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.Security.Cryptography;
+using Microsoft.Data.SqlClient.TestUtilities.Fixtures;
+using Microsoft.Win32;
+
+#if NET
using System.Runtime.Versioning;
#endif
@@ -25,185 +27,97 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted
[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()
+ public void TestRoundTripWithCspAndCertStoreProvider()
{
- const string providerName = "Microsoft Enhanced RSA and AES Cryptographic Provider";
- string providerType = "24";
+ using CspCertificateFixture cspCertificateFixture = new CspCertificateFixture();
- 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);
+ X509Certificate2 cert = cspCertificateFixture.CspCertificate;
+ string cspPath = cspCertificateFixture.CspKeyPath;
+ string certificatePath = cspCertificateFixture.CspCertificatePath;
- SqlColumnEncryptionCertificateStoreProvider certProvider = new SqlColumnEncryptionCertificateStoreProvider();
- SqlColumnEncryptionCspProvider cspProvider = new SqlColumnEncryptionCspProvider();
- byte[] columnEncryptionKey = DatabaseHelper.GenerateRandomBytes(32);
+ 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[] 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);
- }
+ byte[] encryptedColumnEncryptionKeyUsingCSP = cspProvider.EncryptColumnEncryptionKey(cspPath, @"RSA_OAEP", columnEncryptionKey);
+ byte[] columnEncryptionKeyReturnedCSP2Cert = certProvider.DecryptColumnEncryptionKey(certificatePath, @"RSA_OAEP", encryptedColumnEncryptionKeyUsingCSP);
+ Assert.True(columnEncryptionKey.SequenceEqual(columnEncryptionKeyReturnedCSP2Cert));
}
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))]
- [ClassData(typeof(AEConnectionStringProvider))]
- public void TestEncryptDecryptWithCSP(string connectionString)
+ [MemberData(nameof(TestEncryptDecryptWithCsp_Data))]
+ public void TestEncryptDecryptWithCsp(string connectionString, string providerName, int providerType)
{
- string providerName = @"Microsoft Enhanced RSA and AES Cryptographic Provider";
- string keyIdentifier = DataTestUtility.GetLongName("CSP");
+ string keyIdentifier = DataTestUtility.GetUniqueNameForSqlServer("CSP");
+ CspParameters namedCspParameters = new CspParameters(providerType, providerName, keyIdentifier);
+ using SQLSetupStrategyCspProvider sqlSetupStrategyCsp = new SQLSetupStrategyCspProvider(namedCspParameters);
+
+ using SqlConnection sqlConn = new(connectionString);
+ sqlConn.Open();
+
+ // Test INPUT parameter on an encrypted parameter
+ string commandText = @$"SELECT CustomerId, FirstName, LastName " +
+ @$"FROM [{sqlSetupStrategyCsp.ApiTestTable.Name}] " +
+ @$"WHERE FirstName = @firstName";
+ using SqlCommand sqlCommand = new(commandText, sqlConn, null, SqlCommandColumnEncryptionSetting.Enabled);
+
+ SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft");
+ customerFirstParam.Direction = System.Data.ParameterDirection.Input;
+
+ using SqlDataReader sqlDataReader = sqlCommand.ExecuteReader();
+ ValidateResultSet(sqlDataReader);
+ }
- try
+ public static IEnumerable