Skip to content

Commit 6d92a25

Browse files
authored
Tests | Widen SqlVector test criteria, roundtrip additional values in tests (dotnet#3794)
* Roundtrip additional values in SqlVector tests * Cache results of capability checks These are IsDataClassificationSupported and IsVectorSupported. In the process, removed the attempted caching for IsTDS8Supported. This caching didn't work properly, and never should have - the ctor for CertificateTest changed the certificate for the SQL Server instance, so the cached data could have been out of date.
1 parent baae80c commit 6d92a25

4 files changed

Lines changed: 78 additions & 67 deletions

File tree

src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs

Lines changed: 49 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,14 @@ public static class DataTestUtility
8888

8989
// SQL server Version
9090
private static string s_sQLServerVersion = string.Empty;
91-
private static bool s_isTDS8Supported;
9291

9392
//SQL Server EngineEdition
9493
private static string s_sqlServerEngineEdition;
9594

95+
// SQL Server capabilities
96+
private static bool? s_isDataClassificationSupported;
97+
private static bool? s_isVectorSupported;
98+
9699
// Azure Synapse EngineEditionId == 6
97100
// More could be read at https://learn.microsoft.com/en-us/sql/t-sql/functions/serverproperty-transact-sql?view=sql-server-ver16#propertyname
98101
public static bool IsAzureSynapse
@@ -130,17 +133,28 @@ public static string SQLServerVersion
130133
}
131134

132135
// Is TDS8 supported
133-
public static bool IsTDS8Supported
134-
{
135-
get
136-
{
137-
if (!string.IsNullOrEmpty(TCPConnectionString))
138-
{
139-
s_isTDS8Supported = GetSQLServerStatusOnTDS8(TCPConnectionString);
140-
}
141-
return s_isTDS8Supported;
142-
}
143-
}
136+
public static bool IsTDS8Supported =>
137+
IsTCPConnStringSetup() &&
138+
GetSQLServerStatusOnTDS8(TCPConnectionString);
139+
140+
/// <summary>
141+
/// Checks if object SYS.SENSITIVITY_CLASSIFICATIONS exists in SQL Server
142+
/// </summary>
143+
/// <returns>True, if target SQL Server supports Data Classification</returns>
144+
public static bool IsDataClassificationSupported =>
145+
s_isDataClassificationSupported ??= IsTCPConnStringSetup() &&
146+
IsObjectPresent("SYS.SENSITIVITY_CLASSIFICATIONS");
147+
148+
/// <summary>
149+
/// Determines whether the SQL Server supports the 'vector' data type.
150+
/// </summary>
151+
/// <remarks>This method attempts to connect to the SQL Server and check for the existence of the
152+
/// 'vector' data type. If a connection cannot be established or an error occurs during the query, the method
153+
/// returns <see langword="false"/>.</remarks>
154+
/// <returns><see langword="true"/> if the 'vector' data type is supported; otherwise, <see langword="false"/>.</returns>
155+
public static bool IsSqlVectorSupported =>
156+
s_isVectorSupported ??= IsTCPConnStringSetup() &&
157+
IsTypePresent("vector");
144158

145159
static DataTestUtility()
146160
{
@@ -369,7 +383,7 @@ public static string GetSqlServerProperty(SqlConnection connection, ServerProper
369383

370384
#nullable disable
371385

372-
public static bool GetSQLServerStatusOnTDS8(string connectionString)
386+
private static bool GetSQLServerStatusOnTDS8(string connectionString)
373387
{
374388
bool isTDS8Supported = false;
375389
SqlConnectionStringBuilder builder = new(connectionString)
@@ -411,6 +425,28 @@ public static bool IsDatabasePresent(string name)
411425
return present;
412426
}
413427

428+
public static bool IsObjectPresent(string objectName)
429+
{
430+
using SqlConnection connection = new(TCPConnectionString);
431+
using SqlCommand command = new("SELECT OBJECT_ID(@name)", connection);
432+
433+
connection.Open();
434+
command.Parameters.AddWithValue("@name", objectName);
435+
436+
return command.ExecuteScalar() is not DBNull;
437+
}
438+
439+
public static bool IsTypePresent(string typeName)
440+
{
441+
using SqlConnection connection = new(TCPConnectionString);
442+
using SqlCommand command = new("SELECT COUNT(1) FROM SYS.TYPES WHERE [name] = @name", connection);
443+
444+
connection.Open();
445+
command.Parameters.AddWithValue("@name", typeName);
446+
447+
return (int)command.ExecuteScalar() > 0;
448+
}
449+
414450
public static bool IsAdmin
415451
{
416452
get
@@ -422,32 +458,6 @@ public static bool IsAdmin
422458
}
423459
}
424460

425-
/// <summary>
426-
/// Checks if object SYS.SENSITIVITY_CLASSIFICATIONS exists in SQL Server
427-
/// </summary>
428-
/// <returns>True, if target SQL Server supports Data Classification</returns>
429-
public static bool IsSupportedDataClassification()
430-
{
431-
try
432-
{
433-
using (var connection = new SqlConnection(TCPConnectionString))
434-
using (var command = new SqlCommand("SELECT * FROM SYS.SENSITIVITY_CLASSIFICATIONS", connection))
435-
{
436-
connection.Open();
437-
command.ExecuteNonQuery();
438-
}
439-
}
440-
catch (SqlException e)
441-
{
442-
// Check for Error 208: Invalid Object Name
443-
if (e.Errors != null && e.Errors[0].Number == 208)
444-
{
445-
return false;
446-
}
447-
}
448-
return true;
449-
}
450-
451461
public static bool IsDNSCachingSetup() => !string.IsNullOrEmpty(DNSCachingConnString);
452462

453463
// Synapse: Always Encrypted is not supported with Azure Synapse.

src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataClassificationTest/DataClassificationTest.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public static class DataClassificationTest
1515
private static string s_tableName;
1616

1717
// Synapse: Azure Synapse does not support RANK
18-
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse), nameof(DataTestUtility.IsSupportedDataClassification))]
18+
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse), nameof(DataTestUtility.IsDataClassificationSupported))]
1919
public static void TestDataClassificationResultSetRank()
2020
{
2121
s_tableName = DataTestUtility.GetLongName("DC");
@@ -25,7 +25,7 @@ public static void TestDataClassificationResultSetRank()
2525
try
2626
{
2727
sqlConnection.Open();
28-
Assert.True(DataTestUtility.IsSupportedDataClassification());
28+
Assert.True(DataTestUtility.IsDataClassificationSupported);
2929
CreateTable(sqlCommand);
3030
AddSensitivity(sqlCommand, rankEnabled: true);
3131
InsertData(sqlCommand);
@@ -38,7 +38,7 @@ public static void TestDataClassificationResultSetRank()
3838
}
3939
}
4040

41-
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsSupportedDataClassification))]
41+
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsDataClassificationSupported))]
4242
public static void TestDataClassificationResultSet()
4343
{
4444
s_tableName = DataTestUtility.GetLongName("DC");
@@ -48,7 +48,7 @@ public static void TestDataClassificationResultSet()
4848
try
4949
{
5050
sqlConnection.Open();
51-
Assert.True(DataTestUtility.IsSupportedDataClassification());
51+
Assert.True(DataTestUtility.IsDataClassificationSupported);
5252
CreateTable(sqlCommand);
5353
AddSensitivity(sqlCommand);
5454
InsertData(sqlCommand);
@@ -219,7 +219,7 @@ private static void InsertData(SqlCommand sqlCommand)
219219
sqlCommand.ExecuteNonQuery();
220220
}
221221

222-
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsSupportedDataClassification))]
222+
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsDataClassificationSupported))]
223223
public static void TestDataClassificationBulkCopy()
224224
{
225225
var data = new DataTable("Company");

src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/VectorTest/NativeVectorFloat32Tests.cs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests.SQL.VectorTest
1717
public static class VectorFloat32TestData
1818
{
1919
public const int VectorHeaderSize = 8;
20-
public static float[] testData = new float[] { 1.1f, 2.2f, 3.3f };
20+
public static float[] testData = new float[] { 1.1f, 2.2f, 3.3f, 1.01f, float.MinValue, -0.0f };
2121
public static int vectorColumnLength = testData.Length;
2222
// Incorrect size for SqlParameter.Size
2323
public static int IncorrectParamSize = 3234;
@@ -59,16 +59,17 @@ public sealed class NativeVectorFloat32Tests : IDisposable
5959
private static readonly string s_connectionString = ManualTesting.Tests.DataTestUtility.TCPConnectionString;
6060
private static readonly string s_tableName = DataTestUtility.GetShortName("VectorTestTable");
6161
private static readonly string s_bulkCopySrcTableName = DataTestUtility.GetShortName("VectorBulkCopyTestTable");
62-
private static readonly string s_bulkCopySrcTableDef = $@"(Id INT PRIMARY KEY IDENTITY, VectorData vector(3) NULL)";
63-
private static readonly string s_tableDefinition = $@"(Id INT PRIMARY KEY IDENTITY, VectorData vector(3) NULL)";
62+
private static readonly int s_vectorDimensions = VectorFloat32TestData.vectorColumnLength;
63+
private static readonly string s_bulkCopySrcTableDef = $@"(Id INT PRIMARY KEY IDENTITY, VectorData vector({s_vectorDimensions}) NULL)";
64+
private static readonly string s_tableDefinition = $@"(Id INT PRIMARY KEY IDENTITY, VectorData vector({s_vectorDimensions}) NULL)";
6465
private static readonly string s_selectCmdString = $"SELECT VectorData FROM {s_tableName} ORDER BY Id DESC";
6566
private static readonly string s_insertCmdString = $"INSERT INTO {s_tableName} (VectorData) VALUES (@VectorData)";
6667
private static readonly string s_vectorParamName = $"@VectorData";
6768
private static readonly string s_outputVectorParamName = $"@OutputVectorData";
6869
private static readonly string s_storedProcName = DataTestUtility.GetShortName("VectorsAsVarcharSp");
6970
private static readonly string s_storedProcBody = $@"
70-
{s_vectorParamName} vector(3), -- Input: Serialized float[] as JSON string
71-
{s_outputVectorParamName} vector(3) OUTPUT -- Output: Echoed back from latest inserted row
71+
{s_vectorParamName} vector({s_vectorDimensions}), -- Input: Serialized float[] as JSON string
72+
{s_outputVectorParamName} vector({s_vectorDimensions}) OUTPUT -- Output: Echoed back from latest inserted row
7273
AS
7374
BEGIN
7475
SET NOCOUNT ON;
@@ -147,7 +148,7 @@ private void ValidateInsertedData(SqlConnection connection, float[] expectedData
147148
}
148149
}
149150

150-
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsAzureServer), nameof(DataTestUtility.IsNotManagedInstance))]
151+
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsSqlVectorSupported))]
151152
[MemberData(nameof(VectorFloat32TestData.GetVectorFloat32TestData), MemberType = typeof(VectorFloat32TestData), DisableDiscoveryEnumeration = true)]
152153
public void TestSqlVectorFloat32ParameterInsertionAndReads(
153154
int pattern,
@@ -213,7 +214,7 @@ private async Task ValidateInsertedDataAsync(SqlConnection connection, float[] e
213214
}
214215
}
215216

216-
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsAzureServer), nameof(DataTestUtility.IsNotManagedInstance))]
217+
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsSqlVectorSupported))]
217218
[MemberData(nameof(VectorFloat32TestData.GetVectorFloat32TestData), MemberType = typeof(VectorFloat32TestData), DisableDiscoveryEnumeration = true)]
218219
public async Task TestSqlVectorFloat32ParameterInsertionAndReadsAsync(
219220
int pattern,
@@ -247,7 +248,7 @@ public async Task TestSqlVectorFloat32ParameterInsertionAndReadsAsync(
247248
await ValidateInsertedDataAsync(conn, expectedValues, expectedLength);
248249
}
249250

250-
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsAzureServer), nameof(DataTestUtility.IsNotManagedInstance))]
251+
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsSqlVectorSupported))]
251252
[MemberData(nameof(VectorFloat32TestData.GetVectorFloat32TestData), MemberType = typeof(VectorFloat32TestData), DisableDiscoveryEnumeration = true)]
252253
public void TestStoredProcParamsForVectorFloat32(
253254
int pattern,
@@ -304,7 +305,7 @@ public void TestStoredProcParamsForVectorFloat32(
304305
Assert.Throws<InvalidOperationException>(() => command.ExecuteNonQuery());
305306
}
306307

307-
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsAzureServer), nameof(DataTestUtility.IsNotManagedInstance))]
308+
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsSqlVectorSupported))]
308309
[MemberData(nameof(VectorFloat32TestData.GetVectorFloat32TestData), MemberType = typeof(VectorFloat32TestData), DisableDiscoveryEnumeration = true)]
309310
public async Task TestStoredProcParamsForVectorFloat32Async(
310311
int pattern,
@@ -361,7 +362,7 @@ public async Task TestStoredProcParamsForVectorFloat32Async(
361362
await Assert.ThrowsAsync<InvalidOperationException>(async () => await command.ExecuteNonQueryAsync());
362363
}
363364

364-
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsAzureServer), nameof(DataTestUtility.IsNotManagedInstance))]
365+
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsSqlVectorSupported))]
365366
[InlineData(1)]
366367
[InlineData(2)]
367368
public void TestBulkCopyFromSqlTable(int bulkCopySourceMode)
@@ -460,7 +461,7 @@ public void TestBulkCopyFromSqlTable(int bulkCopySourceMode)
460461
Assert.Equal(VectorFloat32TestData.testData.Length, ((SqlVector<float>)verifyReader.GetSqlVector<float>(0)).Length);
461462
}
462463

463-
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsAzureServer), nameof(DataTestUtility.IsNotManagedInstance))]
464+
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsSqlVectorSupported))]
464465
[InlineData(1)]
465466
[InlineData(2)]
466467
public async Task TestBulkCopyFromSqlTableAsync(int bulkCopySourceMode)
@@ -560,7 +561,7 @@ public async Task TestBulkCopyFromSqlTableAsync(int bulkCopySourceMode)
560561
Assert.Equal(VectorFloat32TestData.testData.Length, vector.Length);
561562
}
562563

563-
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAzureServer), nameof(DataTestUtility.IsNotManagedInstance))]
564+
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsSqlVectorSupported))]
564565
public void TestInsertVectorsFloat32WithPrepare()
565566
{
566567
SqlConnection conn = new SqlConnection(s_connectionString);
@@ -571,15 +572,15 @@ public void TestInsertVectorsFloat32WithPrepare()
571572
command.Prepare();
572573
for (int i = 0; i < 10; i++)
573574
{
574-
vectorParam.Value = new SqlVector<float>(new float[] { i + 0.1f, i + 0.2f, i + 0.3f });
575+
vectorParam.Value = new SqlVector<float>(new float[] { i + 0.1f, i + 0.2f, i + 0.3f, i + 0.4f, i + 0.5f, i + 0.6f });
575576
command.ExecuteNonQuery();
576577
}
577578
SqlCommand validateCommand = new SqlCommand($"SELECT VectorData FROM {s_tableName}", conn);
578579
using SqlDataReader reader = validateCommand.ExecuteReader();
579580
int rowcnt = 0;
580581
while (reader.Read())
581582
{
582-
float[] expectedData = new float[] { rowcnt + 0.1f, rowcnt + 0.2f, rowcnt + 0.3f };
583+
float[] expectedData = new float[] { rowcnt + 0.1f, rowcnt + 0.2f, rowcnt + 0.3f, rowcnt + 0.4f, rowcnt + 0.5f, rowcnt + 0.6f };
583584
float[] dbData = reader.GetSqlVector<float>(0).Memory.ToArray();
584585
Assert.Equal(expectedData, dbData);
585586
rowcnt++;

0 commit comments

Comments
 (0)