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 @@
+