From 3311c45eb73bbe30655e0090044671f2ff96e786 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Fri, 19 Jun 2026 12:44:57 -0300 Subject: [PATCH] Add Logging test project and wire it into the build and CI Add the Microsoft.Data.SqlClient.Internal.Logging test project with its SqlClientEventSource tests, the TestLogging build target and project path, the test-logging CI job, the solution entry, and the signed-IVT/test signing setup for the Logging project. Wire the Logging package stage for signed internal builds. --- build.proj | 36 ++- eng/pipelines/dotnet-sqlclient-ci-core.yml | 2 + .../jobs/pack-logging-package-ci-job.yml | 33 ++- .../jobs/test-logging-package-ci-job.yml | 218 ++++++++++++++++++ .../stages/build-logging-package-ci-stage.yml | 71 +++++- .../Logging/src/Logging.csproj | 14 +- .../Logging/test/Directory.Packages.props | 10 + .../Logging/test/Logging.Test.csproj | 57 +++++ .../Logging/test/SqlClientEventSourceTest.cs | 20 ++ src/Microsoft.Data.SqlClient.slnx | 1 + 10 files changed, 455 insertions(+), 7 deletions(-) create mode 100644 eng/pipelines/jobs/test-logging-package-ci-job.yml create mode 100644 src/Microsoft.Data.SqlClient.Internal/Logging/test/Directory.Packages.props create mode 100644 src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj create mode 100644 src/Microsoft.Data.SqlClient.Internal/Logging/test/SqlClientEventSourceTest.cs diff --git a/build.proj b/build.proj index a37b83d9fd..91c8729f23 100644 --- a/build.proj +++ b/build.proj @@ -394,7 +394,7 @@ environments. Please consider running project specific test targets or specific test sets within the project. --> - + @@ -1073,6 +1073,7 @@ $(RepoRoot)src/Microsoft.Data.SqlClient.Internal/Logging/src/ $(LoggingSrcRoot)Logging.csproj + $(RepoRoot)src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj $(RepoRoot)artifacts/Microsoft.Data.SqlClient.Internal.Logging/$(Configuration)/ @@ -1134,6 +1135,39 @@ SkipUnchangedFiles="true" /> + + + + LoggingTests-$(OS) + $(LogFilePrefix)-$(TestFramework) + + + "$(DotnetPath)dotnet" test "$(LoggingTestProjectPath)" + + + -p:Configuration=$(Configuration) + $(SigningKeyPathArgument) + $(TestSigningKeyPathArgument) + + + $(TestBlameArgument) + $(TestCodeCoverageArgument) + $(TestFiltersArgument) + $(TestFrameworkArgument) + --results-directory "$(TestResultsFolderPath)" + --logger:"trx;LogFilePrefix=$(LogFilePrefix)" + + + $(ReferenceTypeArgument) + + + $([System.Text.RegularExpressions.Regex]::Replace($(DotnetCommand), "\s+", " ")) + + + + + + diff --git a/eng/pipelines/dotnet-sqlclient-ci-core.yml b/eng/pipelines/dotnet-sqlclient-ci-core.yml index 5361407e0d..fc48aa0ea2 100644 --- a/eng/pipelines/dotnet-sqlclient-ci-core.yml +++ b/eng/pipelines/dotnet-sqlclient-ci-core.yml @@ -156,6 +156,8 @@ stages: buildConfiguration: ${{ parameters.buildConfiguration }} debug: ${{ parameters.debug }} dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} + referenceType: ${{ parameters.referenceType }} # Build the Abstractions package, and publish it to the pipeline artifacts # under the given artifact name. diff --git a/eng/pipelines/jobs/pack-logging-package-ci-job.yml b/eng/pipelines/jobs/pack-logging-package-ci-job.yml index f2a42699e0..5248bf0853 100644 --- a/eng/pipelines/jobs/pack-logging-package-ci-job.yml +++ b/eng/pipelines/jobs/pack-logging-package-ci-job.yml @@ -53,6 +53,19 @@ parameters: - detailed - diagnostic + # The C# project reference type to use when building and packing the packages. + - name: referenceType + type: string + default: Project + values: + - Package + - Project + + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + jobs: - job: pack_logging_package_job @@ -86,6 +99,20 @@ jobs: - name: Configuration value: '' + # Build properties passed to dotnet pack. + - name: baseBuildProperties + value: LoggingPackageVersion=${{ parameters.loggingPackageVersion }};LoggingAssemblyFileVersion=${{ parameters.loggingAssemblyFileVersion }} + + # NOTE: We use compile-time ${{ if }} branches rather than concatenating + # separate variables (e.g. "$(base);$(signing)") because when the + # optional variable is empty the semicolons remain, producing a trailing + # ";;" that MSBuild rejects with MSB1005. + - name: buildProperties + ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: + value: $(baseBuildProperties);SigningKeyPath=$(driverKeyFile.secureFilePath) + ${{ else }}: + value: $(baseBuildProperties) + steps: # Emit environment variables if debug is enabled. @@ -98,6 +125,10 @@ jobs: parameters: debug: ${{ parameters.debug }} + # Download the assembly signing key for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + # Create the NuGet packages. - task: DotNetCoreCLI@2 displayName: Create NuGet Package @@ -107,7 +138,7 @@ jobs: configurationToPack: ${{ parameters.buildConfiguration }} packDirectory: $(dotnetPackagesDir) verbosityToPack: ${{ parameters.dotnetVerbosity }} - buildProperties: LoggingPackageVersion=${{ parameters.loggingPackageVersion }};LoggingAssemblyFileVersion=${{ parameters.loggingAssemblyFileVersion }} + buildProperties: $(buildProperties) # Publish the NuGet packages as a named pipeline artifact. - task: PublishPipelineArtifact@1 diff --git a/eng/pipelines/jobs/test-logging-package-ci-job.yml b/eng/pipelines/jobs/test-logging-package-ci-job.yml new file mode 100644 index 0000000000..fde3e44c7e --- /dev/null +++ b/eng/pipelines/jobs/test-logging-package-ci-job.yml @@ -0,0 +1,218 @@ +################################################################################ +# Licensed to the .NET Foundation under one or more agreements. The .NET +# Foundation licenses this file to you under the MIT license. See the LICENSE +# file in the project root for more information. +################################################################################ + +# This job builds the Logging package and runs its tests for a set of .NET +# runtimes. +# +# This template defines a job named +# 'test_logging_package_job_' that can be depended on by +# downstream jobs. + +parameters: + + # The type of build to test (Release or Debug) + - name: buildConfiguration + type: string + values: + - Release + - Debug + + # True to emit debug information and steps. + - name: debug + type: boolean + default: false + + # The prefix to prepend to the job's display name: + # + # [] Test Logging Package + # + - name: displayNamePrefix + type: string + + # The verbosity level for the dotnet CLI commands. + - name: dotnetVerbosity + type: string + default: normal + values: + - quiet + - minimal + - normal + - detailed + - diagnostic + + # True when building on the internal ADO.Net project. When set, assemblies + # are signed with the driver key and tests are signed with the test key. + - name: isInternalBuild + type: boolean + default: false + + # The suffix to append to the job name. + - name: jobNameSuffix + type: string + + # The list of .NET Framework runtimes to test against. + - name: netFrameworkRuntimes + type: object + default: [] + + # The list of .NET runtimes to test against. + - name: netRuntimes + type: object + default: [] + + # The name of the Azure Pipelines pool to use. + - name: poolName + type: string + + # The pool VM image to use. + - name: vmImage + type: string + + # The C# project reference type to use when building. + - name: referenceType + type: string + default: Project + values: + - Package + - Project + +jobs: + + - job: test_logging_package_job_${{ parameters.jobNameSuffix }} + displayName: '[${{ parameters.displayNamePrefix }}] Test Logging Package' + pool: + name: ${{ parameters.poolName }} + + # Images provided by Azure Pipelines must be selected using 'vmImage'. + ${{ if eq(parameters.poolName, 'Azure Pipelines') }}: + vmImage: ${{ parameters.vmImage }} + # Images provided by 1ES must be selected using a demand. + ${{ else }}: + demands: + - imageOverride -equals ${{ parameters.vmImage }} + + variables: + + # The Logging test project file to use for all dotnet CLI commands. + # + # Building this project implicitly builds the Logging project. + - name: project + value: src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj + + # dotnet CLI arguments for build/test/pack commands + - name: dotnetBuildOpts + value: >- + -p:Configuration=${{ parameters.buildConfiguration }} + --verbosity ${{ parameters.dotnetVerbosity }} + + # Signing arguments — only set for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: + - name: signingArguments + value: >- + -p:SigningKeyPath=$(driverKeyFile.secureFilePath) + -p:TestSigningKeyPath=$(testKeyFile.secureFilePath) + - ${{ else }}: + - name: signingArguments + value: '' + + # Explicitly unset the $PLATFORM environment variable that is set by the + # 'ADO Build properties' Library in the ADO SqlClientDrivers public project. + # This is defined with a non-standard Platform of 'AnyCPU', and will fail + # the builds if left defined. + # + # Note that Azure Pipelines will inject this variable as PLATFORM into the + # environment of all tasks in this job. + # + # See: + # https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch + # + - name: Platform + value: '' + + # Do the same for $CONFIGURATION since we explicitly set it using our + # 'buildConfiguration' parameter, and we don't want the environment to + # override us. + - name: Configuration + value: '' + + steps: + + # Emit environment variables if debug is enabled. + - ${{ if eq(parameters.debug, true) }}: + - pwsh: 'Get-ChildItem Env: | Sort-Object Name' + displayName: '[Debug] Print Environment Variables' + + # Download the assembly signing keys for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + parameters: + isTest: true + + # Install the .NET SDK and Runtimes. + - template: /eng/pipelines/common/steps/install-dotnet.yml@self + parameters: + debug: ${{ parameters.debug }} + runtimes: [8.x, 9.x] + + # The Windows agent images include a suitable .NET Framework runtime, so + # we don't have to install one explicitly. + + # Build the project. + - task: DotNetCoreCLI@2 + displayName: Build Project + inputs: + command: build + projects: $(project) + arguments: $(dotnetBuildOpts) $(signingArguments) + + # Run the tests for each .NET runtime. + - ${{ each runtime in parameters.netRuntimes }}: + - task: DotNetCoreCLI@2 + displayName: Test [${{ runtime }}] + inputs: + command: test + projects: $(project) + arguments: >- + $(dotnetBuildOpts) + --no-build + -f ${{ runtime }} + --filter "category != failing & category != flaky & category != interactive" + + - task: DotNetCoreCLI@2 + displayName: Test Flaky [${{ runtime }}] + inputs: + command: test + projects: $(project) + arguments: >- + $(dotnetBuildOpts) + --no-build + -f ${{ runtime }} + --filter "category = flaky" + + # Run the tests for each .NET Framework runtime. + - ${{ each runtime in parameters.netFrameworkRuntimes }}: + - task: DotNetCoreCLI@2 + displayName: Test [${{ runtime }}] + inputs: + command: test + projects: $(project) + arguments: >- + $(dotnetBuildOpts) + --no-build + -f ${{ runtime }} + --filter "category != failing & category != flaky & category != interactive" + + - task: DotNetCoreCLI@2 + displayName: Test Flaky [${{ runtime }}] + inputs: + command: test + projects: $(project) + arguments: >- + $(dotnetBuildOpts) + --no-build + -f ${{ runtime }} + --filter "category = flaky" diff --git a/eng/pipelines/stages/build-logging-package-ci-stage.yml b/eng/pipelines/stages/build-logging-package-ci-stage.yml index 6b5f22feeb..4a0ee11a8f 100644 --- a/eng/pipelines/stages/build-logging-package-ci-stage.yml +++ b/eng/pipelines/stages/build-logging-package-ci-stage.yml @@ -67,6 +67,19 @@ parameters: - detailed - diagnostic + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + + # The C# project reference type to use when building and packing the packages. + - name: referenceType + type: string + default: Project + values: + - Package + - Project + stages: - stage: build_logging_package_stage @@ -79,11 +92,59 @@ stages: jobs: + # ------------------------------------------------------------------------ + # Build and test on Linux. + + - template: /eng/pipelines/jobs/test-logging-package-ci-job.yml@self + parameters: + buildConfiguration: ${{ parameters.buildConfiguration }} + debug: ${{ parameters.debug }} + displayNamePrefix: Linux + dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} + jobNameSuffix: linux + netFrameworkRuntimes: [] + netRuntimes: [net8.0, net9.0, net10.0] + poolName: Azure Pipelines + referenceType: ${{ parameters.referenceType }} + vmImage: ubuntu-latest + + # ------------------------------------------------------------------------ + # Build and test on Windows. + + - template: /eng/pipelines/jobs/test-logging-package-ci-job.yml@self + parameters: + buildConfiguration: ${{ parameters.buildConfiguration }} + debug: ${{ parameters.debug }} + displayNamePrefix: Win + dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} + jobNameSuffix: windows + netFrameworkRuntimes: [net462] + netRuntimes: [net8.0, net9.0, net10.0] + poolName: Azure Pipelines + referenceType: ${{ parameters.referenceType }} + vmImage: windows-latest + + # ------------------------------------------------------------------------ + # Build and test on macOS. + + - template: /eng/pipelines/jobs/test-logging-package-ci-job.yml@self + parameters: + buildConfiguration: ${{ parameters.buildConfiguration }} + debug: ${{ parameters.debug }} + displayNamePrefix: macOS + dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} + jobNameSuffix: macos + netFrameworkRuntimes: [] + netRuntimes: [net8.0, net9.0, net10.0] + poolName: Azure Pipelines + referenceType: ${{ parameters.referenceType }} + vmImage: macos-latest + + # ------------------------------------------------------------------------ # Create and publish the NuGet package. - # Note: No test jobs because the Logging project does not have a test - # project yet. When a test project is added, test jobs should be added - # here (mirroring the Abstractions stage pattern) and the pack job should - # depend on them. - template: /eng/pipelines/jobs/pack-logging-package-ci-job.yml@self parameters: @@ -93,3 +154,5 @@ stages: buildConfiguration: ${{ parameters.buildConfiguration }} debug: ${{ parameters.debug }} dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} + referenceType: ${{ parameters.referenceType }} diff --git a/src/Microsoft.Data.SqlClient.Internal/Logging/src/Logging.csproj b/src/Microsoft.Data.SqlClient.Internal/Logging/src/Logging.csproj index d1c3e0fc5c..bc7502d517 100644 --- a/src/Microsoft.Data.SqlClient.Internal/Logging/src/Logging.csproj +++ b/src/Microsoft.Data.SqlClient.Internal/Logging/src/Logging.csproj @@ -34,12 +34,24 @@ $(LoggingPackageVersion) - + + + + + + + + $(RepoRoot)artifacts/ diff --git a/src/Microsoft.Data.SqlClient.Internal/Logging/test/Directory.Packages.props b/src/Microsoft.Data.SqlClient.Internal/Logging/test/Directory.Packages.props new file mode 100644 index 0000000000..f3593ec1ba --- /dev/null +++ b/src/Microsoft.Data.SqlClient.Internal/Logging/test/Directory.Packages.props @@ -0,0 +1,10 @@ + + + + diff --git a/src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj b/src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj new file mode 100644 index 0000000000..be3ca85785 --- /dev/null +++ b/src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj @@ -0,0 +1,57 @@ + + + + Microsoft.Data.SqlClient.Internal.Logging.Test + net8.0;net9.0;net10.0 + + + $(TargetFrameworks);net462 + + false + true + + + + + + true + $(TestSigningKeyPath) + + + + + enable + enable + + + + + + + + + + + PreserveNewest + xunit.runner.json + + + + + + + + + + + + + + + + + + diff --git a/src/Microsoft.Data.SqlClient.Internal/Logging/test/SqlClientEventSourceTest.cs b/src/Microsoft.Data.SqlClient.Internal/Logging/test/SqlClientEventSourceTest.cs new file mode 100644 index 0000000000..d46896672f --- /dev/null +++ b/src/Microsoft.Data.SqlClient.Internal/Logging/test/SqlClientEventSourceTest.cs @@ -0,0 +1,20 @@ +// 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. + +namespace Microsoft.Data.SqlClient.Internal.Logging.Test; + +public class SqlClientEventSourceTest +{ + [Fact] + public void SqlClientEventSource_Log_IsNotNull() + { + Assert.NotNull(SqlClientEventSource.Log); + } + + [Fact] + public void SqlClientEventSource_Log_IsSingleton() + { + Assert.Same(SqlClientEventSource.Log, SqlClientEventSource.Log); + } +} diff --git a/src/Microsoft.Data.SqlClient.slnx b/src/Microsoft.Data.SqlClient.slnx index c0c12132e7..437b117268 100644 --- a/src/Microsoft.Data.SqlClient.slnx +++ b/src/Microsoft.Data.SqlClient.slnx @@ -149,6 +149,7 @@ +