From dc75d0691dfad6fceecc2a5457726dde09ae06b2 Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Wed, 27 May 2026 12:42:17 -0500 Subject: [PATCH 01/20] Let's just enable azure stuff and see what breaks. --- .../pr/jobs/test-sqlclientmanual-job.yml | 16 +++++--- eng/pipelines/pr/stages/test-stages.yml | 39 ++++++++++--------- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml b/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml index ff81d983a3..7554721e03 100644 --- a/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml +++ b/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml @@ -71,6 +71,11 @@ parameters: - name: fileStreamDirectory type: string + # Whether the server that tests will be executed against is local to the job agent. If `true` + # server configuration steps will be executed prior to running the tests. + - name: isLocalServer + type: boolean + # Name of the local DB application name for localdb tests, this value will be stored in the # config.json - name: localDbAppName @@ -103,11 +108,12 @@ jobs: runtimeVersion: ${{ parameters.platformDotnet }} # Configure the local SQL Server instance - - template: /eng/pipelines/pr/steps/configure-sqlserver-step.yml@self - parameters: - fileStreamDirectory: ${{ parameters.fileStreamDirectory }} - operatingSystem: ${{ parameters.platformOperatingSystem }} - saPassword: $(saPassword) + - ${{ if(parameters.isLocalServer) }}: + - template: /eng/pipelines/pr/steps/configure-sqlserver-step.yml@self + parameters: + fileStreamDirectory: ${{ parameters.fileStreamDirectory }} + operatingSystem: ${{ parameters.platformOperatingSystem }} + saPassword: $(saPassword) # Assign the generated SA password to the $Password field. This will allow $(Password) to be # be replaced in connection strings with whatever set in the secrets stage. diff --git a/eng/pipelines/pr/stages/test-stages.yml b/eng/pipelines/pr/stages/test-stages.yml index f2ffbc09cf..c1a64b36ed 100644 --- a/eng/pipelines/pr/stages/test-stages.yml +++ b/eng/pipelines/pr/stages/test-stages.yml @@ -162,25 +162,26 @@ stages: localDbAppName: ${{ parameters.manualTestLocalDbAppName }} localDbSharedInstanceName: ${{ parameters.manualTestLocalDbSharedInstanceName }} - # @TODO: -# # TestSqlClientManual - Azure -# - template: /eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml@self -# parameters: -# buildConfiguration: ${{ parameters.buildConfiguration }} -# buildSuffix: ${{ parameters.buildSuffix }} -# platformDisplayName: ${{ platform.displayName }} -# platformDotnet: ${{ platform.dotnet }} -# platformImage: ${{ platform.image }} -# poolName: ${{ parameters.poolName }} -# -# azureKeyVaultTenantId: ${{ parameters.manualTestAzureKeyVaultTenantId }} -# azureKeyVaultUrl: ${{ parameters.manualTestAzureKeyVaultUrl }} -# connectionStringNp: ${{ parameters.manualTestConnectionStringNpAzure }} -# connectionStringTcp: ${{ parameters.manualTestConnectionStringTcpAzure }} -# fileStreamDirectory: ${{ parameters.manualTestFileStreamDirectory }} -# localDbAppName: ${{ parameters.manualTestLocalDbAppName }} -# localDbSharedInstanceName: ${{ parameters.manualTestLocalDbSharedInstanceName }} -# saPassword: $(manualTestSaPassword) + # TestSqlClientManual - Azure + - template: /eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml@self + parameters: + buildConfiguration: ${{ parameters.buildConfiguration }} + buildSuffix: ${{ parameters.buildSuffix }} + stageNameSecrets: ${{ parameters.stageNamesecrets }} + + platformDisplayName: ${{ platform.displayName }} + platformDotnet: ${{ platform.dotnet }} + platformImage: ${{ platform.image }} + platformOperatingSystem: ${{ platform.operatingSystem }} + poolName: ${{ parameters.poolName }} + + azureKeyVaultTenantId: ${{ parameters.manualTestAzureKeyVaultTenantId }} + azureKeyVaultUrl: ${{ parameters.manualTestAzureKeyVaultUrl }} + connectionStringNp: ${{ parameters.manualTestConnectionStringNpAzure }} + connectionStringTcp: ${{ parameters.manualTestConnectionStringTcpAzure }} + fileStreamDirectory: ${{ parameters.manualTestFileStreamDirectory }} + localDbAppName: ${{ parameters.manualTestLocalDbAppName }} + localDbSharedInstanceName: ${{ parameters.manualTestLocalDbSharedInstanceName }} # TestSqlClientUnit - template: /eng/pipelines/pr/jobs/test-buildproj-job.yml@self From 15714a614d0b254ab488149704ec97a8f673f461 Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Wed, 27 May 2026 13:10:43 -0500 Subject: [PATCH 02/20] config :hammer: --- eng/pipelines/pr/stages/test-stages.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/eng/pipelines/pr/stages/test-stages.yml b/eng/pipelines/pr/stages/test-stages.yml index c1a64b36ed..28607764e4 100644 --- a/eng/pipelines/pr/stages/test-stages.yml +++ b/eng/pipelines/pr/stages/test-stages.yml @@ -159,6 +159,7 @@ stages: connectionStringNp: ${{ parameters.manualTestConnectionStringNpLocalhost }} connectionStringTcp: ${{ parameters.manualTestConnectionStringTcpLocalhost }} fileStreamDirectory: ${{ parameters.manualTestFileStreamDirectory }} + isLocalServer: true localDbAppName: ${{ parameters.manualTestLocalDbAppName }} localDbSharedInstanceName: ${{ parameters.manualTestLocalDbSharedInstanceName }} @@ -180,6 +181,7 @@ stages: connectionStringNp: ${{ parameters.manualTestConnectionStringNpAzure }} connectionStringTcp: ${{ parameters.manualTestConnectionStringTcpAzure }} fileStreamDirectory: ${{ parameters.manualTestFileStreamDirectory }} + isLocalServer: false localDbAppName: ${{ parameters.manualTestLocalDbAppName }} localDbSharedInstanceName: ${{ parameters.manualTestLocalDbSharedInstanceName }} From 66278ae6d9d4ab48593ba0907398cf28152163bb Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Wed, 27 May 2026 13:11:51 -0500 Subject: [PATCH 03/20] this syntax is garbage --- eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml b/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml index 7554721e03..3dc21a3514 100644 --- a/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml +++ b/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml @@ -108,7 +108,7 @@ jobs: runtimeVersion: ${{ parameters.platformDotnet }} # Configure the local SQL Server instance - - ${{ if(parameters.isLocalServer) }}: + - ${{ if eq(parameters.isLocalServer, true) }}: - template: /eng/pipelines/pr/steps/configure-sqlserver-step.yml@self parameters: fileStreamDirectory: ${{ parameters.fileStreamDirectory }} From 1e98826dc1f1cb620f7a57d875d9eefc866bd116 Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Wed, 27 May 2026 13:20:15 -0500 Subject: [PATCH 04/20] Job names. --- eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml | 9 +++++++-- eng/pipelines/pr/stages/test-stages.yml | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml b/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml index 3dc21a3514..ec5f4f0ea1 100644 --- a/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml +++ b/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml @@ -59,6 +59,11 @@ parameters: - name: azureKeyVaultUrl type: string + # Display name for the config being used for this execution of the manual jobs. This will be used + # for the job name, so it may only contain alphanumeric and '_' characters. + - name: configDisplayName + type: string + # Connection string using named pipes that will be set in the config.json file. - name: connectionStringNp type: string @@ -87,8 +92,8 @@ parameters: type: string jobs: - - job: "test_${{ parameters.platformDisplayName }}_sqlclient_manual" - displayName: "sqlclient_manual_${{ parameters.platformDisplayName }}" + - job: "test_${{ parameters.platformDisplayName }}_${{ parameters.configDisplayName }}_sqlclient_manual" + displayName: "sqlclient_manual_${{ parameters.configDisplayName}}_${{ parameters.platformDisplayName }}" pool: name: ${{ parameters.poolName }} diff --git a/eng/pipelines/pr/stages/test-stages.yml b/eng/pipelines/pr/stages/test-stages.yml index 28607764e4..58fe1aaa65 100644 --- a/eng/pipelines/pr/stages/test-stages.yml +++ b/eng/pipelines/pr/stages/test-stages.yml @@ -156,6 +156,7 @@ stages: azureKeyVaultTenantId: ${{ parameters.manualTestAzureKeyVaultTenantId }} azureKeyVaultUrl: ${{ parameters.manualTestAzureKeyVaultUrl }} + configDisplayName: "localhost" connectionStringNp: ${{ parameters.manualTestConnectionStringNpLocalhost }} connectionStringTcp: ${{ parameters.manualTestConnectionStringTcpLocalhost }} fileStreamDirectory: ${{ parameters.manualTestFileStreamDirectory }} @@ -178,6 +179,7 @@ stages: azureKeyVaultTenantId: ${{ parameters.manualTestAzureKeyVaultTenantId }} azureKeyVaultUrl: ${{ parameters.manualTestAzureKeyVaultUrl }} + configDisplayName: "azure" connectionStringNp: ${{ parameters.manualTestConnectionStringNpAzure }} connectionStringTcp: ${{ parameters.manualTestConnectionStringTcpAzure }} fileStreamDirectory: ${{ parameters.manualTestFileStreamDirectory }} From 7d53a405cadbf6aa8dfb885bca8ab274cee4e81b Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Fri, 29 May 2026 15:10:05 -0500 Subject: [PATCH 05/20] :robot: Run AE in release mode separately, exlude AE from azure test runs. --- .../pr/jobs/test-sqlclientmanual-job.yml | 9 ++++-- eng/pipelines/pr/stages/test-stages.yml | 28 ++++++++++++++++++- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml b/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml index ec5f4f0ea1..6764b41ec5 100644 --- a/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml +++ b/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml @@ -91,9 +91,13 @@ parameters: - name: localDbSharedInstanceName type: string + # Manual test set to execute. + - name: testSet + type: string + jobs: - - job: "test_${{ parameters.platformDisplayName }}_${{ parameters.configDisplayName }}_sqlclient_manual" - displayName: "sqlclient_manual_${{ parameters.configDisplayName}}_${{ parameters.platformDisplayName }}" + - job: "test_${{ parameters.platformDisplayName }}_${{ parameters.configDisplayName }}_${{ parameters.testSet }}_sqlclient_manual" + displayName: "sqlclient_manual_${{ parameters.configDisplayName}}_${{ parameters.testSet }}_${{ parameters.platformDisplayName }}" pool: name: ${{ parameters.poolName }} @@ -168,4 +172,5 @@ jobs: packageShortName: "SqlClient" testFramework: ${{ parameters.platformDotnet }} testProject: "Manual" + testSet: ${{ parameters.testSet }} diff --git a/eng/pipelines/pr/stages/test-stages.yml b/eng/pipelines/pr/stages/test-stages.yml index 58fe1aaa65..9a2a862c9f 100644 --- a/eng/pipelines/pr/stages/test-stages.yml +++ b/eng/pipelines/pr/stages/test-stages.yml @@ -163,13 +163,14 @@ stages: isLocalServer: true localDbAppName: ${{ parameters.manualTestLocalDbAppName }} localDbSharedInstanceName: ${{ parameters.manualTestLocalDbSharedInstanceName }} + testSet: "123" # TestSqlClientManual - Azure - template: /eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml@self parameters: buildConfiguration: ${{ parameters.buildConfiguration }} buildSuffix: ${{ parameters.buildSuffix }} - stageNameSecrets: ${{ parameters.stageNamesecrets }} + stageNameSecrets: ${{ parameters.stageNameSecrets }} platformDisplayName: ${{ platform.displayName }} platformDotnet: ${{ platform.dotnet }} @@ -186,6 +187,31 @@ stages: isLocalServer: false localDbAppName: ${{ parameters.manualTestLocalDbAppName }} localDbSharedInstanceName: ${{ parameters.manualTestLocalDbSharedInstanceName }} + testSet: "123" + + # TestSqlClientManual - Localhost Always Encrypted + - template: /eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml@self + parameters: + buildConfiguration: "Release" # AE tests are not stable enough to run in DEBUG mode (as of 5/29/26) + buildSuffix: ${{ parameters.buildSuffix }} + stageNameSecrets: ${{ parameters.stageNameSecrets }} + + platformDisplayName: ${{ platform.displayName }} + platformDotnet: ${{ platform.dotnet }} + platformImage: ${{ platform.image }} + platformOperatingSystem: ${{ platform.operatingSystem }} + poolName: ${{ parameters.poolName }} + + azureKeyVaultTenantId: ${{ parameters.manualTestAzureKeyVaultTenantId }} + azureKeyVaultUrl: ${{ parameters.manualTestAzureKeyVaultUrl }} + configDisplayName: "localhost_ae" + connectionStringNp: ${{ parameters.manualTestConnectionStringNpLocalhost }} + connectionStringTcp: ${{ parameters.manualTestConnectionStringTcpLocalhost }} + fileStreamDirectory: ${{ parameters.manualTestFileStreamDirectory }} + isLocalServer: true + localDbAppName: ${{ parameters.manualTestLocalDbAppName }} + localDbSharedInstanceName: ${{ parameters.manualTestLocalDbSharedInstanceName }} + testSet: "AE" # TestSqlClientUnit - template: /eng/pipelines/pr/jobs/test-buildproj-job.yml@self From b5e74a56d0613f536cee5e9b683259f54e4cf9f9 Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Fri, 29 May 2026 15:14:23 -0500 Subject: [PATCH 06/20] Decompose the single step test-buildproj-job.yml file --- eng/pipelines/pr/jobs/test-buildproj-job.yml | 20 ++++--- .../pr/jobs/test-sqlclientmanual-job.yml | 22 ++++--- .../pr/steps/test-buildproj-step.yml | 59 ------------------- 3 files changed, 25 insertions(+), 76 deletions(-) delete mode 100644 eng/pipelines/pr/steps/test-buildproj-step.yml diff --git a/eng/pipelines/pr/jobs/test-buildproj-job.yml b/eng/pipelines/pr/jobs/test-buildproj-job.yml index 0b051bf50e..ec9cab4a4f 100644 --- a/eng/pipelines/pr/jobs/test-buildproj-job.yml +++ b/eng/pipelines/pr/jobs/test-buildproj-job.yml @@ -79,11 +79,15 @@ jobs: runtimeVersion: ${{ parameters.platformDotnet }} # Execute the test target - - template: /eng/pipelines/pr/steps/test-buildproj-step.yml - parameters: - buildConfiguration: ${{ parameters.buildConfiguration }} - buildSuffix: ${{ parameters.buildSuffix }} - - packageShortName: ${{ parameters.packageShortName }} - testFramework: ${{ parameters.platformDotnet }} - testProject: ${{ parameters.testProject }} + - task: DotNetCoreCLI@2 + displayName: 'build.proj - Test${{ parameters.packageShortName }}${{ parameters.testProject }}' + inputs: + command: build + projects: build.proj + verbosity: detailed + arguments: >- + -t:Test${{ parameters.packageShortName }}${{ parameters.testProject }} + -p:Configuration=${{ parameters.buildConfiguration }} + -p:BuildNumber='$(Build.BuildNumber)' + -p:BuildSuffix='${{ parameters.buildSuffix }}' + -p:TestFramework=${{ parameters.testFramework }} diff --git a/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml b/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml index 6764b41ec5..d60ab71348 100644 --- a/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml +++ b/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml @@ -164,13 +164,17 @@ jobs: displayName: 'Generate manual test config' # Execute TestSqlClientManual target from build.proj - - template: /eng/pipelines/pr/steps/test-buildproj-step.yml - parameters: - buildConfiguration: ${{ parameters.buildConfiguration }} - buildSuffix: ${{ parameters.buildSuffix }} - - packageShortName: "SqlClient" - testFramework: ${{ parameters.platformDotnet }} - testProject: "Manual" - testSet: ${{ parameters.testSet }} + - task: DotNetCoreCLI@2 + displayName: 'build.proj: Test${{ parameters.packageShortName }}${{ parameters.testProject }} ${{ parameters.testSet }}' + inputs: + command: build + projects: build.proj + verbosity: detailed + arguments: >- + -t:Test${{ parameters.packageShortName }}${{ parameters.testProject }} + -p:Configuration=${{ parameters.buildConfiguration }} + -p:BuildNumber='$(Build.BuildNumber)' + -p:BuildSuffix='${{ parameters.buildSuffix }}' + -p:TestFramework=${{ parameters.testFramework }} + -p:TestSet=${{ parameters.testSet }} diff --git a/eng/pipelines/pr/steps/test-buildproj-step.yml b/eng/pipelines/pr/steps/test-buildproj-step.yml deleted file mode 100644 index 5309e7ef96..0000000000 --- a/eng/pipelines/pr/steps/test-buildproj-step.yml +++ /dev/null @@ -1,59 +0,0 @@ -################################################################################# -# Licensed to the .NET Foundation under one or more agreements. # -# The .NET Foundation licenses this file to you under the MIT license. # -# See the LICENSE file in the project root for more information. # -################################################################################# - -parameters: - # General Parameters ======================================================= - - # Configuration to use to build the project. - - name: buildConfiguration - type: string - values: - - Debug - - Release - - # Suffix to apply to the generated packages such that the package will be considered a prerelease - # version. The resulting package version will look like: `1.2.3-suffix888.1` where 1.2.3 is the - # default version specified in Versions.props, suffix is this parameter, and 888.1 is the build - # number for the currently executing build. - - name: buildSuffix - type: string - - # Test Parameters ======================================================== - - # Package/project to test. - - name: packageShortName - type: string - values: - - Azure - - AkvProvider - - Abstractions - - Logging - - SqlClient - - SqlServer - - - name: testFramework - type: string - - # If the project to test has multiple projects supported by build.proj, use this optional - # parameter to specify the project to execute. This will be appended to Test{PackageShortName} to - # generate the target to execute. See build.proj for supported targets. - - name: testProject - type: string - default: '' - -steps: - - task: DotNetCoreCLI@2 - displayName: 'build.proj - Test${{ parameters.packageShortName }}${{ parameters.testProject }}' - inputs: - command: build - projects: build.proj - verbosity: detailed - arguments: >- - -t:Test${{ parameters.packageShortName }}${{ parameters.testProject }} - -p:Configuration=${{ parameters.buildConfiguration }} - -p:BuildNumber='$(Build.BuildNumber)' - -p:BuildSuffix='${{ parameters.buildSuffix }}' - -p:TestFramework=${{ parameters.testFramework }} From 392ceec1d85e6ad3a3aca1b6c68e65c7260001bd Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Fri, 29 May 2026 15:15:46 -0500 Subject: [PATCH 07/20] platformDotnet --- eng/pipelines/pr/jobs/test-buildproj-job.yml | 2 +- eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/pipelines/pr/jobs/test-buildproj-job.yml b/eng/pipelines/pr/jobs/test-buildproj-job.yml index ec9cab4a4f..b160e7931c 100644 --- a/eng/pipelines/pr/jobs/test-buildproj-job.yml +++ b/eng/pipelines/pr/jobs/test-buildproj-job.yml @@ -90,4 +90,4 @@ jobs: -p:Configuration=${{ parameters.buildConfiguration }} -p:BuildNumber='$(Build.BuildNumber)' -p:BuildSuffix='${{ parameters.buildSuffix }}' - -p:TestFramework=${{ parameters.testFramework }} + -p:TestFramework=${{ parameters.platformDotNet }} diff --git a/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml b/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml index d60ab71348..6a7e035347 100644 --- a/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml +++ b/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml @@ -175,6 +175,6 @@ jobs: -p:Configuration=${{ parameters.buildConfiguration }} -p:BuildNumber='$(Build.BuildNumber)' -p:BuildSuffix='${{ parameters.buildSuffix }}' - -p:TestFramework=${{ parameters.testFramework }} + -p:TestFramework=${{ parameters.platformDotnet }} -p:TestSet=${{ parameters.testSet }} From 472ec0cb89abe78e99feaa02a3f01fdc9abc3df3 Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Fri, 29 May 2026 15:16:47 -0500 Subject: [PATCH 08/20] Manual test name --- eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml b/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml index 6a7e035347..02127caba6 100644 --- a/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml +++ b/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml @@ -165,13 +165,13 @@ jobs: # Execute TestSqlClientManual target from build.proj - task: DotNetCoreCLI@2 - displayName: 'build.proj: Test${{ parameters.packageShortName }}${{ parameters.testProject }} ${{ parameters.testSet }}' + displayName: 'build.proj: TestSqlClientManual ${{ parameters.testSet }}' inputs: command: build projects: build.proj verbosity: detailed arguments: >- - -t:Test${{ parameters.packageShortName }}${{ parameters.testProject }} + -t:TestSqlClientManual -p:Configuration=${{ parameters.buildConfiguration }} -p:BuildNumber='$(Build.BuildNumber)' -p:BuildSuffix='${{ parameters.buildSuffix }}' From bff1f6bd6ab5e7fd3d70318ba5a8f04e8da842b2 Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Wed, 3 Jun 2026 15:55:20 -0500 Subject: [PATCH 09/20] Disable sqlbulkcopy that fails on azure # Conflicts: # src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/SqlBulkCopyTest.cs --- .../BulkCopy/CopyAllFromReaderConnectionCloseOnEventAsync.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/BulkCopy/CopyAllFromReaderConnectionCloseOnEventAsync.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/BulkCopy/CopyAllFromReaderConnectionCloseOnEventAsync.cs index 89b354c3b2..1a3fa72734 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/BulkCopy/CopyAllFromReaderConnectionCloseOnEventAsync.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/BulkCopy/CopyAllFromReaderConnectionCloseOnEventAsync.cs @@ -12,7 +12,7 @@ namespace Microsoft.Data.SqlClient.ManualTests.BulkCopy { public class CopyAllFromReaderConnectionClosedOnEventAsync { - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] + [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureServer))] public void Test() { string srcConstr = DataTestUtility.TCPConnectionString; From 1076211022b47a0473a113619892e8079f8b6aa6 Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Wed, 3 Jun 2026 14:17:30 -0500 Subject: [PATCH 10/20] Feedback from previous PR --- eng/pipelines/pr/jobs/test-buildproj-job.yml | 15 ++++-- .../pr/jobs/test-sqlclientmanual-job.yml | 13 ++++-- eng/pipelines/pr/stages/pack-stage.yml | 7 ++- .../pr/steps/build-buildproj-step.yml | 46 ------------------- eng/pipelines/pr/steps/install-dotnet.yml | 27 ----------- .../pr/steps/pack-buildproj-step.yml | 2 +- 6 files changed, 25 insertions(+), 85 deletions(-) delete mode 100644 eng/pipelines/pr/steps/build-buildproj-step.yml delete mode 100644 eng/pipelines/pr/steps/install-dotnet.yml diff --git a/eng/pipelines/pr/jobs/test-buildproj-job.yml b/eng/pipelines/pr/jobs/test-buildproj-job.yml index b160e7931c..bc931397bb 100644 --- a/eng/pipelines/pr/jobs/test-buildproj-job.yml +++ b/eng/pipelines/pr/jobs/test-buildproj-job.yml @@ -73,14 +73,19 @@ jobs: - imageOverride -equals ${{ parameters.platformImage }} steps: - # Install the version of the dotnet runtime we will use to execute the test target. - - template: /eng/pipelines/pr/steps/install-dotnet.yml@self + # Install dotnet and the runtime that will run the tests (if it is not netframework) + - template: /eng/pipelines/common/steps/install-dotnet.yml@self parameters: - runtimeVersion: ${{ parameters.platformDotnet }} + ${{ if not(contains(parameters.platformDotnet, 'net4')) }}: + runtimes: + - "${{ replace(parameters.platformDotnet, 'net', '') }}.x" + + # Restore dotnet tools + - template: /eng/pipelines/common/steps/restore-dotnet-tools.yml@self # Execute the test target - task: DotNetCoreCLI@2 - displayName: 'build.proj - Test${{ parameters.packageShortName }}${{ parameters.testProject }}' + displayName: 'Test: ${{ parameters.packageShortName }}${{ parameters.testProject }}' inputs: command: build projects: build.proj @@ -90,4 +95,4 @@ jobs: -p:Configuration=${{ parameters.buildConfiguration }} -p:BuildNumber='$(Build.BuildNumber)' -p:BuildSuffix='${{ parameters.buildSuffix }}' - -p:TestFramework=${{ parameters.platformDotNet }} + -p:TestFramework=${{ parameters.platformDotnet }} diff --git a/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml b/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml index 02127caba6..62e026ca3c 100644 --- a/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml +++ b/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml @@ -111,10 +111,15 @@ jobs: value: $[stageDependencies.${{ parameters.stageNameSecrets }}.secrets_job.outputs['SaPassword.Value']] steps: - # Install the version of the dotnet runtime we will use to execute the test target. - - template: /eng/pipelines/pr/steps/install-dotnet.yml@self + # Install dotnet and the runtime that will run the tests (if it is not netframework) + - template: /eng/pipelines/common/steps/install-dotnet.yml@self parameters: - runtimeVersion: ${{ parameters.platformDotnet }} + ${{ if not(contains(parameters.platformDotnet, 'net4')) }}: + runtimes: + - "${{ replace(parameters.platformDotnet, 'net', '') }}.x" + + # Restore dotnet tools + - template: /eng/pipelines/common/steps/restore-dotnet-tools.yml@self # Configure the local SQL Server instance - ${{ if eq(parameters.isLocalServer, true) }}: @@ -165,7 +170,7 @@ jobs: # Execute TestSqlClientManual target from build.proj - task: DotNetCoreCLI@2 - displayName: 'build.proj: TestSqlClientManual ${{ parameters.testSet }}' + displayName: 'Test: SqlClientManual ${{ parameters.testSet }}' inputs: command: build projects: build.proj diff --git a/eng/pipelines/pr/stages/pack-stage.yml b/eng/pipelines/pr/stages/pack-stage.yml index c0a135e246..5473027731 100644 --- a/eng/pipelines/pr/stages/pack-stage.yml +++ b/eng/pipelines/pr/stages/pack-stage.yml @@ -50,8 +50,11 @@ stages: vmImage: 'ubuntu-latest' steps: - # Install dotnet SDK and restore tools - - template: /eng/pipelines/pr/steps/install-dotnet.yml@self + # Install dotnet + - template: /eng/pipelines/common/steps/install-dotnet.yml@self + + # Restore dotnet tools + - template: /eng/pipelines/common/steps/restore-dotnet-tools.yml@self # ################################################################ # Build/Pack Microsoft.Data.SqlClient diff --git a/eng/pipelines/pr/steps/build-buildproj-step.yml b/eng/pipelines/pr/steps/build-buildproj-step.yml deleted file mode 100644 index 3e81edfbf4..0000000000 --- a/eng/pipelines/pr/steps/build-buildproj-step.yml +++ /dev/null @@ -1,46 +0,0 @@ -################################################################################# -# Licensed to the .NET Foundation under one or more agreements. # -# The .NET Foundation licenses this file to you under the MIT license. # -# See the LICENSE file in the project root for more information. # -################################################################################# - -# This collection of steps to build a project via the build.proj. This will execute the "Build*" -# target in build.proj, where * is the packageShortName provided in the parameters. -# -# Note: This differs from the onebranch build-buildproj-step.yml in that it does *not* strong-name -# sign the assemblies, it only builds in project reference mode, and as such it does not allow -# version parameters or dependencies to be provided. - -parameters: - - name: buildConfiguration - type: string - values: - - Debug - - Release - - - name: buildSuffix - type: string - - - name: packageShortName - type: string - values: - - Azure - - AkvProvider - - Abstractions - - Logging - - SqlClient - - SqlServer - -steps: - - task: DotNetCoreCLI@2 - displayName: 'build.proj - Build${{ parameters.packageShortName }}' - inputs: - command: build - projects: build.proj - arguments: >- - -t:Build${{ parameters.packageShortName }} - -p:Configuration=${{ parameters.buildConfiguration }} - -p:BuildNumber='$(Build.BuildNumber)' - -p:BuildSuffix='${{ parameters.buildSuffix }}' - - diff --git a/eng/pipelines/pr/steps/install-dotnet.yml b/eng/pipelines/pr/steps/install-dotnet.yml deleted file mode 100644 index fe1c8f7878..0000000000 --- a/eng/pipelines/pr/steps/install-dotnet.yml +++ /dev/null @@ -1,27 +0,0 @@ -################################################################################# -# Licensed to the .NET Foundation under one or more agreements. # -# The .NET Foundation licenses this file to you under the MIT license. # -# See the LICENSE file in the project root for more information. # -################################################################################# - -# This is a step to wrap the install-dotnet step for use in the PR pipeline. It will always install -# the SDK version specified in the global.json file, and if the runtime version specified does not -# begin with "net4" (ie, indicating netfx runtime is being used), the version will be passed in as -# part of the runtime parameters. -# -# This version chains into the common install-dotnet step to enable the pr pipeline to call a -# single step template and get the desired behavior without complexity. - -parameters: - - name: runtimeVersion - type: string - default: '' - -steps: - - template: /eng/pipelines/common/steps/install-dotnet.yml@self - parameters: - ${{ if and( not(eq(parameters.runtimeVersion, '' )), not(contains(parameters.runtimeVersion, 'net4')) ) }}: - runtimes: - - "${{ replace(parameters.runtimeVersion, 'net', '') }}.x" - - - template: /eng/pipelines/common/steps/restore-dotnet-tools.yml@self diff --git a/eng/pipelines/pr/steps/pack-buildproj-step.yml b/eng/pipelines/pr/steps/pack-buildproj-step.yml index 6b2980cbb4..f947bafb0e 100644 --- a/eng/pipelines/pr/steps/pack-buildproj-step.yml +++ b/eng/pipelines/pr/steps/pack-buildproj-step.yml @@ -46,7 +46,7 @@ parameters: steps: - task: DotNetCoreCLI@2 - displayName: 'build.proj - Build${{ parameters.packageShortName }}' + displayName: 'Pack: ${{ parameters.packageShortName }}' condition: ${{ parameters.condition }} inputs: command: build From 0ea0f80f5d7097b12f891ec68742104a6369d824 Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Thu, 4 Jun 2026 13:41:33 -0500 Subject: [PATCH 11/20] Flaky tests in azure. --- .../ManualTests/SQL/ParameterTest/SqlVariantParameterTests.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/SqlVariantParameterTests.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/SqlVariantParameterTests.cs index 5f47576baa..0bb4b8e7e9 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/SqlVariantParameterTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/SqlVariantParameterTests.cs @@ -31,7 +31,7 @@ public SqlVariantParameterTests() // which uses CultureInfo.CurrentCulture.LCID. On Linux, this LCID is 127 // (InvariantCulture), which is not a valid SQL Server collation and causes // "invalid TDS collation" errors in the TVP code path. - // SqlClient doesn't support invariant mode: + // SqlClient doesn't support invariant mode: // https://github.com/dotnet/SqlClient/issues/3742 _previousCulture = Thread.CurrentThread.CurrentCulture; Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); @@ -258,6 +258,7 @@ public void SqlType_BulkCopyFromDataRow_RoundTripsCorrectly(object paramValue, s /// /// Round trip sql_variant value using TVP with a SqlMetaData/SqlDataRecord source. /// + [Trait("Category", "flaky")] // Doesn't work well on Azure. [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] [MemberData(nameof(SqlTypeTestData), DisableDiscoveryEnumeration = true)] public void SqlType_TvpFromSqlMetaData_RoundTripsCorrectly(object paramValue, string expectedTypeName, string expectedBaseTypeName) @@ -304,6 +305,7 @@ public void SqlType_TvpFromSqlMetaData_RoundTripsCorrectly(object paramValue, st /// /// Round trip sql_variant value using TVP with a SqlDataReader source. /// + [Trait("Category", "flaky")] // Doesn't work well on Azure. [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] [MemberData(nameof(SqlTypeTestData), DisableDiscoveryEnumeration = true)] public void SqlType_TvpFromSqlDataReader_RoundTripsCorrectly(object paramValue, string expectedTypeName, string expectedBaseTypeName) From a4060e87a1ba949fbd12fbfebd429a94d9cb353c Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Thu, 4 Jun 2026 17:40:42 -0500 Subject: [PATCH 12/20] Another flaky test. --- .../BulkCopy/CopyAllFromReaderConnectionCloseOnEventAsync.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/BulkCopy/CopyAllFromReaderConnectionCloseOnEventAsync.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/BulkCopy/CopyAllFromReaderConnectionCloseOnEventAsync.cs index 1a3fa72734..8cbdc84d2f 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/BulkCopy/CopyAllFromReaderConnectionCloseOnEventAsync.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/BulkCopy/CopyAllFromReaderConnectionCloseOnEventAsync.cs @@ -12,6 +12,7 @@ namespace Microsoft.Data.SqlClient.ManualTests.BulkCopy { public class CopyAllFromReaderConnectionClosedOnEventAsync { + [Trait("Category", "flaky")] // Hangs and crashes on occasion [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureServer))] public void Test() { From 0f77f11052a2e382aba0eb5afe1415150ff1af95 Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Fri, 5 Jun 2026 14:17:06 -0500 Subject: [PATCH 13/20] :robot: Pipe dotnet verbosity through pipeline --- eng/pipelines/pr/jobs/test-buildproj-job.yml | 13 ++++++++- .../pr/jobs/test-sqlclientmanual-job.yml | 15 +++++++++- eng/pipelines/pr/pr-pipeline.yml | 16 +++++++++++ eng/pipelines/pr/stages/test-stages.yml | 28 ++++++++++++++++--- 4 files changed, 66 insertions(+), 6 deletions(-) diff --git a/eng/pipelines/pr/jobs/test-buildproj-job.yml b/eng/pipelines/pr/jobs/test-buildproj-job.yml index bc931397bb..ec2d292ec8 100644 --- a/eng/pipelines/pr/jobs/test-buildproj-job.yml +++ b/eng/pipelines/pr/jobs/test-buildproj-job.yml @@ -18,6 +18,17 @@ parameters: - name: buildSuffix type: string + # Dotnet CLI verbosity level. + - name: dotnetVerbosity + type: string + default: normal + values: + - quiet + - minimal + - normal + - detailed + - diagnostic + # Platform Parameters ==================================================== # Display name of the platform. This will be formatted into the job's official name as well as @@ -89,7 +100,7 @@ jobs: inputs: command: build projects: build.proj - verbosity: detailed + verbosity: ${{ parameters.dotnetVerbosity }} arguments: >- -t:Test${{ parameters.packageShortName }}${{ parameters.testProject }} -p:Configuration=${{ parameters.buildConfiguration }} diff --git a/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml b/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml index 62e026ca3c..e62049a251 100644 --- a/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml +++ b/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml @@ -5,6 +5,8 @@ ################################################################################# parameters: + # General Parameters ===================================================== + # Configuration with which to build the packages and execute the tests. - name: buildConfiguration type: string @@ -16,6 +18,17 @@ parameters: - name: buildSuffix type: string + # Dotnet CLI verbosity level. + - name: dotnetVerbosity + type: string + default: normal + values: + - quiet + - minimal + - normal + - detailed + - diagnostic + # Name of the stage that generated the SA password - name: stageNameSecrets type: string @@ -174,7 +187,7 @@ jobs: inputs: command: build projects: build.proj - verbosity: detailed + verbosity: ${{ parameters.dotnetVerbosity }} arguments: >- -t:TestSqlClientManual -p:Configuration=${{ parameters.buildConfiguration }} diff --git a/eng/pipelines/pr/pr-pipeline.yml b/eng/pipelines/pr/pr-pipeline.yml index 9774ebdbfa..a81fbbfc0c 100644 --- a/eng/pipelines/pr/pr-pipeline.yml +++ b/eng/pipelines/pr/pr-pipeline.yml @@ -6,6 +6,21 @@ name: $(DayOfYear)$(Rev:rr) +parameters: + # General Parameters ===================================================== + + # Dotnet CLI verbosity level. + - name: dotnetVerbosity + displayName: dotnet CLI Verbosity + type: string + default: normal + values: + - quiet + - minimal + - normal + - detailed + - diagnostic + variables: - template: /eng/pipelines/common/variables/common-variables.yml@self - template: /eng/pipelines/pr/variables/pr-variables.yml@self @@ -28,6 +43,7 @@ stages: parameters: buildConfiguration: Debug buildSuffix: pr + dotnetVerbosity: ${{ parameters.dotnetVerbosity }} poolName: $(PoolNameDefault) stageNamePack: ${{ variables.stageNamePack }} stageNameSecrets: ${{ variables.stageNameSecrets }} diff --git a/eng/pipelines/pr/stages/test-stages.yml b/eng/pipelines/pr/stages/test-stages.yml index 9a2a862c9f..c2e196fe31 100644 --- a/eng/pipelines/pr/stages/test-stages.yml +++ b/eng/pipelines/pr/stages/test-stages.yml @@ -9,6 +9,8 @@ # confidence and expedience of validation. parameters: + # General Parameters ===================================================== + # Configuration with which to build the packages and execute the tests. - name: buildConfiguration type: string @@ -20,6 +22,21 @@ parameters: - name: buildSuffix type: string + # Dotnet CLI verbosity level. + - name: dotnetVerbosity + type: string + default: normal + values: + - quiet + - minimal + - normal + - detailed + - diagnostic + + # Name of the pool to use for jobs that require customized VM images. + - name: poolName + type: string + # Name of the build/pack stage that this stage will depend on. - name: stageNamePack type: string @@ -28,10 +45,6 @@ parameters: - name: stageNameSecrets type: string - # Name of the pool to use for jobs that require customized VM images. - - name: poolName - type: string - # Manual Test Configuration Parameters ================================== # Azure Key Vault tenant ID that will be set in the config.json file for sqlclient manual tests. @@ -106,6 +119,7 @@ stages: parameters: buildConfiguration: ${{ parameters.buildConfiguration }} buildSuffix: ${{ parameters.buildSuffix }} + dotnetVerbosity: ${{ parameters.dotnetVerbosity }} platformDisplayName: ${{ platform.displayName }} platformDotnet: ${{ platform.dotnet }} platformImage: ${{ platform.image }} @@ -119,6 +133,7 @@ stages: parameters: buildConfiguration: ${{ parameters.buildConfiguration }} buildSuffix: ${{ parameters.buildSuffix }} + dotnetVerbosity: ${{ parameters.dotnetVerbosity }} platformDisplayName: ${{ platform.displayName }} platformDotnet: ${{ platform.dotnet }} platformImage: ${{ platform.image }} @@ -132,6 +147,7 @@ stages: parameters: buildConfiguration: ${{ parameters.buildConfiguration }} buildSuffix: ${{ parameters.buildSuffix }} + dotnetVerbosity: ${{ parameters.dotnetVerbosity }} platformDisplayName: ${{ platform.displayName }} platformDotnet: ${{ platform.dotnet }} platformImage: ${{ platform.image }} @@ -146,6 +162,7 @@ stages: parameters: buildConfiguration: ${{ parameters.buildConfiguration }} buildSuffix: ${{ parameters.buildSuffix }} + dotnetVerbosity: ${{ parameters.dotnetVerbosity }} stageNameSecrets: ${{ parameters.stageNameSecrets }} platformDisplayName: ${{ platform.displayName }} @@ -170,6 +187,7 @@ stages: parameters: buildConfiguration: ${{ parameters.buildConfiguration }} buildSuffix: ${{ parameters.buildSuffix }} + dotnetVerbosity: ${{ parameters.dotnetVerbosity }} stageNameSecrets: ${{ parameters.stageNameSecrets }} platformDisplayName: ${{ platform.displayName }} @@ -194,6 +212,7 @@ stages: parameters: buildConfiguration: "Release" # AE tests are not stable enough to run in DEBUG mode (as of 5/29/26) buildSuffix: ${{ parameters.buildSuffix }} + dotnetVerbosity: ${{ parameters.dotnetVerbosity }} stageNameSecrets: ${{ parameters.stageNameSecrets }} platformDisplayName: ${{ platform.displayName }} @@ -218,6 +237,7 @@ stages: parameters: buildConfiguration: ${{ parameters.buildConfiguration }} buildSuffix: ${{ parameters.buildSuffix }} + dotnetVerbosity: ${{ parameters.dotnetVerbosity }} platformDisplayName: ${{ platform.displayName }} platformDotnet: ${{ platform.dotnet }} platformImage: ${{ platform.image }} From 1f9f601aff88a14b38c61e0a00aa173f91020892 Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Mon, 8 Jun 2026 18:31:35 -0500 Subject: [PATCH 14/20] jsonc changes --- .../pr/jobs/test-sqlclientmanual-job.yml | 20 +++++++++---------- eng/pipelines/pr/stages/test-stages.yml | 18 ++++++++--------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml b/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml index e62049a251..683f4d3ef7 100644 --- a/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml +++ b/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml @@ -64,11 +64,11 @@ parameters: # Test Configuration Parameters ========================================== - # Azure Key Vault tenant ID that will be set in the config.json file. + # Azure Key Vault tenant ID that will be set in the config.jsonc file. - name: azureKeyVaultTenantId type: string - # Azure Key Vault URL that will be set in the config.json file. + # Azure Key Vault URL that will be set in the config.jsonc file. - name: azureKeyVaultUrl type: string @@ -77,15 +77,15 @@ parameters: - name: configDisplayName type: string - # Connection string using named pipes that will be set in the config.json file. + # Connection string using named pipes that will be set in the config.jsonc file. - name: connectionStringNp type: string - # Connection string using TCP that will be set in the config.json file. + # Connection string using TCP that will be set in the config.jsonc file. - name: connectionStringTcp type: string - # Path to use for file stream tests, this value will be stored in the config.json file. + # Path to use for file stream tests, this value will be stored in the config.jsonc file. - name: fileStreamDirectory type: string @@ -95,12 +95,12 @@ parameters: type: boolean # Name of the local DB application name for localdb tests, this value will be stored in the - # config.json + # config.jsonc - name: localDbAppName type: string # Name of the local DB shared instance name for localdb tests, this value will be stored in the - # config.json + # config.jsonc - name: localDbSharedInstanceName type: string @@ -149,12 +149,12 @@ jobs: Write-Host "##vso[task.setvariable variable=Password;isSecret=true]$password" displayName: Set Connection String Password - # Write configuration information to the config.json file. + # Write configuration information to the config.jsonc file. - pwsh: | # Read existing default configuration from file - $defaultConfigPath = "$(REPO_ROOT)/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/config.default.json" + $defaultConfigPath = "$(REPO_ROOT)/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/config.default.jsonc" $configDirectory = "$(Agent.TempDirectory)/mds-config" - $configPath = Join-Path $configDirectory "config.json" + $configPath = Join-Path $configDirectory "config.jsonc" $config = Get-Content -Raw $defaultConfigPath | ConvertFrom-Json # Update the config values diff --git a/eng/pipelines/pr/stages/test-stages.yml b/eng/pipelines/pr/stages/test-stages.yml index c2e196fe31..25f182f248 100644 --- a/eng/pipelines/pr/stages/test-stages.yml +++ b/eng/pipelines/pr/stages/test-stages.yml @@ -47,46 +47,46 @@ parameters: # Manual Test Configuration Parameters ================================== - # Azure Key Vault tenant ID that will be set in the config.json file for sqlclient manual tests. + # Azure Key Vault tenant ID that will be set in the config.jsonc file for sqlclient manual tests. - name: manualTestAzureKeyVaultTenantId type: string - # Azure Key Vault URL that will be set in the config.json file for sqlclient manual tests. + # Azure Key Vault URL that will be set in the config.jsonc file for sqlclient manual tests. - name: manualTestAzureKeyVaultUrl type: string - # Connection string to Azure SQL using named pipes that will be set in the config.json file for + # Connection string to Azure SQL using named pipes that will be set in the config.jsonc file for # sqlclient manual tests against Azure SQL. - name: manualTestConnectionStringNpAzure type: string - # Connection string to localhost using named pipes that will be set in the config.json file for + # Connection string to localhost using named pipes that will be set in the config.jsonc file for # sqlclient manual tests against a local box product. - name: manualTestConnectionStringNpLocalhost type: string - # Connection string to Azure SQL using TCP that will be set in the config.json file for sqlclient + # Connection string to Azure SQL using TCP that will be set in the config.jsonc file for sqlclient # manual tests against Azure SQL. - name: manualTestConnectionStringTcpAzure type: string - # Connection string to localhost using TCP that will be set in the config.json file for sqlclient + # Connection string to localhost using TCP that will be set in the config.jsonc file for sqlclient # manual tests against a local box product. - name: manualTestConnectionStringTcpLocalhost type: string - # Path to use for file stream tests, this value will be stored in the config.json for sqlclient + # Path to use for file stream tests, this value will be stored in the config.jsonc for sqlclient # manual tests. - name: manualTestFileStreamDirectory type: string # Name of the local DB application name for localdb tests, this value will be stored in the - # config.json for sqlclient manual tests. + # config.jsonc for sqlclient manual tests. - name: manualTestLocalDbAppName type: string # Name of the local DB shared instance name for localdb tests, this value will be stored in the - # config.json for sqlclient manual tests. + # config.jsonc for sqlclient manual tests. - name: manualTestLocalDbSharedInstanceName type: string From dc824607960884fca615ec1189e6c7521da4991c Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Tue, 9 Jun 2026 10:40:32 -0500 Subject: [PATCH 15/20] One more flaky test --- .../SQL/MARSSessionPoolingTest/MarsSessionPoolingTest.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/MARSSessionPoolingTest/MarsSessionPoolingTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/MARSSessionPoolingTest/MarsSessionPoolingTest.cs index e84c9fabb6..0954dd4db7 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/MARSSessionPoolingTest/MarsSessionPoolingTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/MARSSessionPoolingTest/MarsSessionPoolingTest.cs @@ -228,6 +228,7 @@ public void ExecuteReader_GarbageCollectReader(CommandType commandType) } } + [Trait("Category", "flaky")] [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsNotAzureSynapse), nameof(DataTestUtility.IsNotManagedInstance))] [InlineData(CommandType.Text)] [InlineData(CommandType.StoredProcedure)] From 0b208c895dea65c31dd40820acd80b2f4d432af7 Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Tue, 9 Jun 2026 11:11:33 -0500 Subject: [PATCH 16/20] One more more flaky test --- .../tests/ManualTests/AlwaysEncrypted/ApiShould.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs index feefe77adb..878af6fb83 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs @@ -1999,6 +1999,7 @@ public void TestBeginAndEndExecuteReaderWithAsyncCallback(string connection, Com } } + [Trait("Category", "flaky")] [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsTargetReadyForAeWithKeyStore))] [ClassData(typeof(AEConnectionStringProviderWithExecutionMethod))] public void TestSqlCommandCancel(string connection, string value) From af1d71ce7e6b587fd222e3573a835f27d063f6d6 Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Wed, 10 Jun 2026 11:34:33 -0500 Subject: [PATCH 17/20] Unflaky tests so I can hopefully get a reason why they failed. --- .../tests/ManualTests/AlwaysEncrypted/ApiShould.cs | 2 +- .../SQL/MARSSessionPoolingTest/MarsSessionPoolingTest.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs index 878af6fb83..4426799d69 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs @@ -1999,7 +1999,7 @@ public void TestBeginAndEndExecuteReaderWithAsyncCallback(string connection, Com } } - [Trait("Category", "flaky")] + // [Trait("Category", "flaky")] [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsTargetReadyForAeWithKeyStore))] [ClassData(typeof(AEConnectionStringProviderWithExecutionMethod))] public void TestSqlCommandCancel(string connection, string value) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/MARSSessionPoolingTest/MarsSessionPoolingTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/MARSSessionPoolingTest/MarsSessionPoolingTest.cs index 0954dd4db7..5805cb308e 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/MARSSessionPoolingTest/MarsSessionPoolingTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/MARSSessionPoolingTest/MarsSessionPoolingTest.cs @@ -228,7 +228,7 @@ public void ExecuteReader_GarbageCollectReader(CommandType commandType) } } - [Trait("Category", "flaky")] + // [Trait("Category", "flaky")] [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsNotAzureSynapse), nameof(DataTestUtility.IsNotManagedInstance))] [InlineData(CommandType.Text)] [InlineData(CommandType.StoredProcedure)] From 321d9375d03c91a8c8a63163f90a1b367434d917 Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Wed, 10 Jun 2026 12:38:46 -0500 Subject: [PATCH 18/20] Wire in managed identity client ID to hopefully enable AKV tests. --- eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml | 6 ++++++ eng/pipelines/pr/pr-pipeline.yml | 1 + eng/pipelines/pr/stages/test-stages.yml | 8 ++++++++ eng/pipelines/pr/variables/pr-variables.yml | 1 + 4 files changed, 16 insertions(+) diff --git a/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml b/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml index 683f4d3ef7..9ca2c7c555 100644 --- a/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml +++ b/eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml @@ -108,6 +108,11 @@ parameters: - name: testSet type: string + # Name of the user managed identity client ID. This value will be stored in config.jsonc for use + # in AKV tests and substituted in for Azure connection string user IDs. + - name: userManagedIdentityClientId + type: string + jobs: - job: "test_${{ parameters.platformDisplayName }}_${{ parameters.configDisplayName }}_${{ parameters.testSet }}_sqlclient_manual" displayName: "sqlclient_manual_${{ parameters.configDisplayName}}_${{ parameters.testSet }}_${{ parameters.platformDisplayName }}" @@ -166,6 +171,7 @@ jobs: $config.LocalDbSharedInstanceName = "${{ parameters.localDbSharedInstanceName }}" $config.ManagedIdentitySupported = $true $config.SupportsIntegratedSecurity = $false + $config.UserManagedIdentityClientId = "${{ parameters.userManagedIdentityClientId }}" if ("${{ parameters.platformOperatingSystem }}" -eq "Windows") { $config.FileStreamDirectory = "${{ parameters.fileStreamDirectory }}" diff --git a/eng/pipelines/pr/pr-pipeline.yml b/eng/pipelines/pr/pr-pipeline.yml index a81fbbfc0c..daf393e502 100644 --- a/eng/pipelines/pr/pr-pipeline.yml +++ b/eng/pipelines/pr/pr-pipeline.yml @@ -88,6 +88,7 @@ stages: manualTestFileStreamDirectory: "$(Pipeline.Workspace)/filestream" manualTestLocalDbAppName: $(LocalDbAppName) manualTestLocalDbSharedInstanceName: $(LocalDbSharedInstanceName) + manualTestUserManagedIdentityClientId: $(UserManagedIdentityClientId) # Stage 3: Collect code coverage # @TODO: diff --git a/eng/pipelines/pr/stages/test-stages.yml b/eng/pipelines/pr/stages/test-stages.yml index 25f182f248..3a1e2c2011 100644 --- a/eng/pipelines/pr/stages/test-stages.yml +++ b/eng/pipelines/pr/stages/test-stages.yml @@ -90,6 +90,11 @@ parameters: - name: manualTestLocalDbSharedInstanceName type: string + # Name of the managed identity client ID, this value will be stored in the config.jsonc for + # sqlclient manual tests. + - name: manualTestUserManagedIdentityClientId + type: string + # This is an array of objects with the following fields: # - displayName - Friendly name to use when displaying the stage name and job names. This # must only contain alphanumeric characters and '_'. It will be used for both @@ -181,6 +186,7 @@ stages: localDbAppName: ${{ parameters.manualTestLocalDbAppName }} localDbSharedInstanceName: ${{ parameters.manualTestLocalDbSharedInstanceName }} testSet: "123" + userManagedIdentityClientId: ${{ parameters.manualTestUserManagedIdentityClientId }} # TestSqlClientManual - Azure - template: /eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml@self @@ -206,6 +212,7 @@ stages: localDbAppName: ${{ parameters.manualTestLocalDbAppName }} localDbSharedInstanceName: ${{ parameters.manualTestLocalDbSharedInstanceName }} testSet: "123" + userManagedIdentityClientId: ${{ parameters.manualTestUserManagedIdentityClientId }} # TestSqlClientManual - Localhost Always Encrypted - template: /eng/pipelines/pr/jobs/test-sqlclientmanual-job.yml@self @@ -231,6 +238,7 @@ stages: localDbAppName: ${{ parameters.manualTestLocalDbAppName }} localDbSharedInstanceName: ${{ parameters.manualTestLocalDbSharedInstanceName }} testSet: "AE" + userManagedIdentityClientId: ${{ parameters.manualTestUserManagedIdentityClientId }} # TestSqlClientUnit - template: /eng/pipelines/pr/jobs/test-buildproj-job.yml@self diff --git a/eng/pipelines/pr/variables/pr-variables.yml b/eng/pipelines/pr/variables/pr-variables.yml index 4a28253dc7..a9da73850e 100644 --- a/eng/pipelines/pr/variables/pr-variables.yml +++ b/eng/pipelines/pr/variables/pr-variables.yml @@ -20,6 +20,7 @@ variables: # LocalDbAppName # LocalDbSharedInstanceName # PoolNameDefault + # UserManagedIdentityClientId - group: sqlclient-testconfig-v1 # General Variables ====================================================== From 7611899c7b1ee04d45c00ad4e4ddeae2a86853b8 Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Wed, 10 Jun 2026 14:41:14 -0500 Subject: [PATCH 19/20] Use TCP connection strings on HGSVBS AKV tests --- .../ManualTests/AlwaysEncrypted/AKVTests.cs | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVTests.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVTests.cs index 53232b1431..6c2db5dd6e 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVTests.cs @@ -30,7 +30,13 @@ public AKVTest(SQLSetupStrategyAzureKeyVault fixture) [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE), nameof(DataTestUtility.IsAKVSetupAvailable))] public void TestEncryptDecryptWithAKV() { - SqlConnectionStringBuilder builder = new(DataTestUtility.TCPConnectionStringHGSVBS) + // Select connection string - If an enclave connection string exists, use that, but for + // non-enclave test runs, use the standard TCP connection string. + string baseConnectionString = string.IsNullOrWhiteSpace(DataTestUtility.TCPConnectionStringHGSVBS) + ? DataTestUtility.TCPConnectionString + : DataTestUtility.TCPConnectionStringHGSVBS; + + SqlConnectionStringBuilder builder = new(baseConnectionString) { ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Enabled, AttestationProtocol = SqlConnectionAttestationProtocol.NotSpecified, @@ -71,7 +77,13 @@ It aims to confirm that three consecutive connections will consistently fail wit [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE), nameof(DataTestUtility.IsAKVSetupAvailable))] public void ForcedColumnDecryptErrorTestShouldFail() { - SqlConnectionStringBuilder builder = new(DataTestUtility.TCPConnectionStringHGSVBS) + // Select connection string - If an enclave connection string exists, use that, but for + // non-enclave test runs, use the standard TCP connection string. + string baseConnectionString = string.IsNullOrWhiteSpace(DataTestUtility.TCPConnectionStringHGSVBS) + ? DataTestUtility.TCPConnectionString + : DataTestUtility.TCPConnectionStringHGSVBS; + + SqlConnectionStringBuilder builder = new(baseConnectionString) { ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Enabled, AttestationProtocol = SqlConnectionAttestationProtocol.NotSpecified, @@ -148,7 +160,13 @@ public void TestRoundTripWithAKVAndCertStoreProvider() [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE), nameof(DataTestUtility.IsAKVSetupAvailable))] public void TestLocalCekCacheIsScopedToProvider() { - SqlConnectionStringBuilder builder = new(DataTestUtility.TCPConnectionStringHGSVBS) + // Select connection string - If an enclave connection string exists, use that, but for + // non-enclave test runs, use the standard TCP connection string. + string baseConnectionString = string.IsNullOrWhiteSpace(DataTestUtility.TCPConnectionStringHGSVBS) + ? DataTestUtility.TCPConnectionString + : DataTestUtility.TCPConnectionStringHGSVBS; + + SqlConnectionStringBuilder builder = new(baseConnectionString) { ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Enabled, AttestationProtocol = SqlConnectionAttestationProtocol.NotSpecified, From 631d50c1f33c5c81f5626c11479d1290fdb29f1d Mon Sep 17 00:00:00 2001 From: Ben Russell Date: Wed, 10 Jun 2026 14:53:11 -0500 Subject: [PATCH 20/20] Add traces for newly flaky tests --- .../ManualTests/AlwaysEncrypted/ApiShould.cs | 13 ++++++++++++- .../MarsSessionPoolingTest.cs | 15 ++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs index 4426799d69..6f564250ce 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs @@ -1999,7 +1999,8 @@ public void TestBeginAndEndExecuteReaderWithAsyncCallback(string connection, Com } } - // [Trait("Category", "flaky")] + [Trait("Category", "flaky")] // System.AggregateException : One or more errors occurred. (Assert.ThrowsAny() Failure: No exception was thrown + // Expected: typeof(System.Exception)) [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsTargetReadyForAeWithKeyStore))] [ClassData(typeof(AEConnectionStringProviderWithExecutionMethod))] public void TestSqlCommandCancel(string connection, string value) @@ -2185,6 +2186,16 @@ public void TestSqlCommandCancel(string connection, string value) tasks[1].Start(); // Wait for the threads to finish. + // Flaky Stack Trace -------------------------------------- + // Assert.ThrowsAny() Failure: No exception was thrown + // Expected: typeof(System.Exception) + // Stack Trace: + // at System.Threading.Tasks.Task.WaitAllCore(ReadOnlySpan`1 tasks, Int32 millisecondsTimeout, CancellationToken cancellationToken) + // at System.Threading.Tasks.Task.WaitAll(Task[] tasks) + // at Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.ApiShould.TestSqlCommandCancel(String connection, String value) in D:\a\_work\1\s\src\Microsoft.Data.SqlClient\tests\ManualTests\AlwaysEncrypted\ApiShould.cs:line 2187 + // at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor) + // at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr) + Task.WaitAll(tasks); CommandHelper.s_sleepAfterReadDescribeEncryptionParameterResults?.SetValue(null, false); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/MARSSessionPoolingTest/MarsSessionPoolingTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/MARSSessionPoolingTest/MarsSessionPoolingTest.cs index 5805cb308e..9f666fc45f 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/MARSSessionPoolingTest/MarsSessionPoolingTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/MARSSessionPoolingTest/MarsSessionPoolingTest.cs @@ -228,7 +228,9 @@ public void ExecuteReader_GarbageCollectReader(CommandType commandType) } } - // [Trait("Category", "flaky")] + [Trait("Category", "flaky")] // Assert.Equal() Failure: Values differ + // Expected: 5 + // Actual: 4 [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsNotAzureSynapse), nameof(DataTestUtility.IsNotManagedInstance))] [InlineData(CommandType.Text)] [InlineData(CommandType.StoredProcedure)] @@ -255,6 +257,17 @@ public void ExecuteReader_DisposeCommand(CommandType commandType) // Disposing of the command does *not* close the reader, meaning the MARS session // is left in an incomplete state. As such, with each command that's executed, a // new session is opened. + + // Flaky stack trace ------------------ + // Assert.Equal() Failure: Values differ + // Expected: 5 + // Actual: 4 + // Stack Trace: + // at Microsoft.Data.SqlClient.ManualTesting.Tests.MarsSessionPoolingTest.AssertSessionsAndRequests(SqlConnection connection, Int32 openMarsSessions, Int32 openRequests) in D:\a\_work\1\s\src\Microsoft.Data.SqlClient\tests\ManualTests\SQL\MARSSessionPoolingTest\MarsSessionPoolingTest.cs:line 368 + // at Microsoft.Data.SqlClient.ManualTesting.Tests.MarsSessionPoolingTest.ExecuteReader_DisposeCommand(CommandType commandType) in D:\a\_work\1\s\src\Microsoft.Data.SqlClient\tests\ManualTests\SQL\MARSSessionPoolingTest\MarsSessionPoolingTest.cs:line 256 + // at InvokeStub_MarsSessionPoolingTest.ExecuteReader_DisposeCommand(Object, Span`1) + // at System.Reflection.MethodBaseInvoker.InvokeWithOneArg(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) + AssertSessionsAndRequests(connection, openMarsSessions: i + 1, openRequests: i + 1); } }