diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 0c326b36d..274fab56d 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -42,4 +42,4 @@ jobs: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4 + uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 diff --git a/Directory.Packages.props b/Directory.Packages.props index 27e2a2706..3dcb3eb7a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -4,6 +4,7 @@ true true + 2.0.2 2.5.198 2.0.208 4.14.0 @@ -48,16 +49,13 @@ - - - - - - + + + + - - + diff --git a/azure-pipelines/Merge-CodeCoverage.ps1 b/azure-pipelines/Merge-CodeCoverage.ps1 index 32438237e..c552d25f2 100644 --- a/azure-pipelines/Merge-CodeCoverage.ps1 +++ b/azure-pipelines/Merge-CodeCoverage.ps1 @@ -28,6 +28,7 @@ try { if ($reports) { $reports |% { $_.FullName } |% { # In addition to replacing {reporoot}, we also normalize on one kind of slash so that the report aggregates data for a file whether data was collected on Windows or not. + Write-Verbose "Processing $_" $xml = [xml](Get-Content -LiteralPath $_) $xml.coverage.packages.package.classes.class |? { $_.filename} |% { $_.filename = $_.filename.Replace('{reporoot}', $RepoRoot).Replace([IO.Path]::AltDirectorySeparatorChar, [IO.Path]::DirectorySeparatorChar) diff --git a/azure-pipelines/dotnet.yml b/azure-pipelines/dotnet.yml index aa02c9044..385aa746d 100644 --- a/azure-pipelines/dotnet.yml +++ b/azure-pipelines/dotnet.yml @@ -20,25 +20,17 @@ steps: displayName: 🧪 dotnet test condition: and(succeeded(), ${{ parameters.RunTests }}) -- task: DotNetCoreCLI@2 +- powershell: tools/dotnet-test-cloud.ps1 -Configuration $(BuildConfiguration) -Agent $(Agent.JobName) -PublishResults -netfxOnly -logIsolationName EventSource-throw displayName: 🧪 dotnet test -f net472 (+EventSource throw) - inputs: - command: test - arguments: --no-build -c $(BuildConfiguration) -f net472 --filter "TestCategory!=FailsInCloudTest$(FailsOnMonoFilter)" -v n /p:CollectCoverage=true /bl:"$(Build.ArtifactStagingDirectory)/build_logs/test_net472_etw.binlog" --diag "$(Build.ArtifactStagingDirectory)/test_logs/net472_etw.txt" - testRunTitle: streamjsonrpc.tests-etw (net472, $(Agent.JobName)) env: StreamJsonRpc_TestWithEventSource: 1 # allow exceptions from EventSource to propagate - condition: and(succeeded(), ne(variables['OptProf'], 'true'), eq(variables['Agent.OS'], 'Windows_NT')) + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) -- task: DotNetCoreCLI@2 +- powershell: tools/dotnet-test-cloud.ps1 -Configuration $(BuildConfiguration) -Agent $(Agent.JobName) -PublishResults -netfxOnly -logIsolationName EventSource-production displayName: 🧪 dotnet test -f net472 (+EventSource production) - inputs: - command: test - arguments: --no-build -c $(BuildConfiguration) -f net472 --filter "TestCategory!=FailsInCloudTest$(FailsOnMonoFilter)" -v n /p:CollectCoverage=true /bl:"$(Build.ArtifactStagingDirectory)/build_logs/test_net472_etw.binlog" --diag "$(Build.ArtifactStagingDirectory)/test_logs/net472_etw.txt" - testRunTitle: streamjsonrpc.tests-etw (net472, $(Agent.JobName)) env: StreamJsonRpc_TestWithEventSource: 2 # swallow exceptions from EventSource, as is done in production - condition: and(succeeded(), ne(variables['OptProf'], 'true'), eq(variables['Agent.OS'], 'Windows_NT')) + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) - powershell: tools/variables/_define.ps1 failOnStderr: true diff --git a/global.json b/global.json index abcdce367..1fd52854d 100644 --- a/global.json +++ b/global.json @@ -1,9 +1,12 @@ { "sdk": { - "version": "10.0.100", + "version": "10.0.101", "rollForward": "patch", "allowPrerelease": false }, + "test": { + "runner": "Microsoft.Testing.Platform" + }, "msbuild-sdks": { "Microsoft.Build.NoTargets": "3.7.134", "Microsoft.Build.Traversal": "4.1.82" diff --git a/test/Benchmarks/Benchmarks.csproj b/test/Benchmarks/Benchmarks.csproj index 55c67166f..24ddedb74 100644 --- a/test/Benchmarks/Benchmarks.csproj +++ b/test/Benchmarks/Benchmarks.csproj @@ -3,6 +3,7 @@ Exe net8.0;net472 + false true diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 395359dd4..466be54e4 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -5,6 +5,7 @@ false true + true diff --git a/test/Directory.Build.targets b/test/Directory.Build.targets index 9f32cd061..3758bb8c9 100644 --- a/test/Directory.Build.targets +++ b/test/Directory.Build.targets @@ -1,5 +1,11 @@ + + + + + + diff --git a/test/Directory.Packages.props b/test/Directory.Packages.props new file mode 100644 index 000000000..069d7839b --- /dev/null +++ b/test/Directory.Packages.props @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/test/NativeAOTCompatibility.Test/NativeAOTCompatibility.Test.csproj b/test/NativeAOTCompatibility.Test/NativeAOTCompatibility.Test.csproj index 0f60cc881..95227fe45 100644 --- a/test/NativeAOTCompatibility.Test/NativeAOTCompatibility.Test.csproj +++ b/test/NativeAOTCompatibility.Test/NativeAOTCompatibility.Test.csproj @@ -6,6 +6,7 @@ false true true + false diff --git a/test/StreamJsonRpc.Analyzer.Tests/StreamJsonRpc.Analyzer.Tests.csproj b/test/StreamJsonRpc.Analyzer.Tests/StreamJsonRpc.Analyzer.Tests.csproj index 87bda8648..97d614d9e 100644 --- a/test/StreamJsonRpc.Analyzer.Tests/StreamJsonRpc.Analyzer.Tests.csproj +++ b/test/StreamJsonRpc.Analyzer.Tests/StreamJsonRpc.Analyzer.Tests.csproj @@ -4,7 +4,6 @@ net8.0 $(TargetFrameworks);net472 Exe - true @@ -16,9 +15,7 @@ - - - + diff --git a/test/StreamJsonRpc.Tests.ExternalAssembly/StreamJsonRpc.Tests.ExternalAssembly.csproj b/test/StreamJsonRpc.Tests.ExternalAssembly/StreamJsonRpc.Tests.ExternalAssembly.csproj index 4adecc5ed..0cda39713 100644 --- a/test/StreamJsonRpc.Tests.ExternalAssembly/StreamJsonRpc.Tests.ExternalAssembly.csproj +++ b/test/StreamJsonRpc.Tests.ExternalAssembly/StreamJsonRpc.Tests.ExternalAssembly.csproj @@ -3,6 +3,7 @@ netstandard2.0 true + false diff --git a/test/StreamJsonRpc.Tests.NoInterceptors/StreamJsonRpc.Tests.NoInterceptors.csproj b/test/StreamJsonRpc.Tests.NoInterceptors/StreamJsonRpc.Tests.NoInterceptors.csproj index 46bcf0e26..469cf0eb6 100644 --- a/test/StreamJsonRpc.Tests.NoInterceptors/StreamJsonRpc.Tests.NoInterceptors.csproj +++ b/test/StreamJsonRpc.Tests.NoInterceptors/StreamJsonRpc.Tests.NoInterceptors.csproj @@ -31,7 +31,6 @@ - @@ -39,9 +38,8 @@ - - + diff --git a/test/StreamJsonRpc.Tests/StreamJsonRpc.Tests.csproj b/test/StreamJsonRpc.Tests/StreamJsonRpc.Tests.csproj index 85ad9aa77..aa1d3ec34 100644 --- a/test/StreamJsonRpc.Tests/StreamJsonRpc.Tests.csproj +++ b/test/StreamJsonRpc.Tests/StreamJsonRpc.Tests.csproj @@ -73,7 +73,6 @@ - @@ -81,9 +80,8 @@ - - + diff --git a/test/UnreachableAssembly/UnreachableAssembly.csproj b/test/UnreachableAssembly/UnreachableAssembly.csproj index 089efa6ca..aab1fffc7 100644 --- a/test/UnreachableAssembly/UnreachableAssembly.csproj +++ b/test/UnreachableAssembly/UnreachableAssembly.csproj @@ -3,6 +3,7 @@ net8.0 $(TargetFrameworks);net472 + false diff --git a/tools/artifacts/coverageResults.ps1 b/tools/artifacts/coverageResults.ps1 index 8c68216ed..1aadbb747 100644 --- a/tools/artifacts/coverageResults.ps1 +++ b/tools/artifacts/coverageResults.ps1 @@ -1,25 +1,26 @@ -$RepoRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..") +$RepoRoot = Resolve-Path "$PSScriptRoot\..\.." -$coverageFiles = @(Get-ChildItem "$RepoRoot/test/*.cobertura.xml" -Recurse | Where {$_.FullName -notlike "*/In/*" -and $_.FullName -notlike "*\In\*" }) +$coverageFilesUnderRoot = @(Get-ChildItem "$RepoRoot/*.cobertura.xml" -Recurse | Where-Object {$_.FullName -notlike "*/In/*" -and $_.FullName -notlike "*\In\*" }) + +# Under MTP, coverage files are written directly to the artifacts output directory, +# so we need to look there too. +$ArtifactStagingFolder = & "$PSScriptRoot/../Get-ArtifactsStagingDirectory.ps1" +$directTestLogs = Join-Path $ArtifactStagingFolder test_logs +$coverageFilesUnderArtifacts = if (Test-Path $directTestLogs) { @(Get-ChildItem "$directTestLogs/*.cobertura.xml" -Recurse) } else { @() } # Prepare code coverage reports for merging on another machine -$repoRoot = $env:SYSTEM_DEFAULTWORKINGDIRECTORY -if (!$repoRoot) { $repoRoot = $env:GITHUB_WORKSPACE } -if ($repoRoot) { - Write-Host "Substituting $repoRoot with `"{reporoot}`"" - $coverageFiles |% { - $content = Get-Content -LiteralPath $_ |% { $_ -Replace [regex]::Escape($repoRoot), "{reporoot}" } - Set-Content -LiteralPath $_ -Value $content -Encoding UTF8 - } -} else { - Write-Warning "coverageResults: Cloud build not detected. Machine-neutral token replacement skipped." +Write-Host "Substituting $repoRoot with `"{reporoot}`"" +@($coverageFilesUnderRoot + $coverageFilesUnderArtifacts) |? { $_ }|% { + $content = Get-Content -LiteralPath $_ |% { $_ -Replace [regex]::Escape($repoRoot), "{reporoot}" } + Set-Content -LiteralPath $_ -Value $content -Encoding UTF8 } if (!((Test-Path $RepoRoot\bin) -and (Test-Path $RepoRoot\obj))) { return } @{ + $directTestLogs = $coverageFilesUnderArtifacts; $RepoRoot = ( - $coverageFiles + + $coverageFilesUnderRoot + (Get-ChildItem "$RepoRoot\obj\*.cs" -Recurse) ); } diff --git a/tools/artifacts/testResults.ps1 b/tools/artifacts/testResults.ps1 index 5310fb52a..a841967e8 100644 --- a/tools/artifacts/testResults.ps1 +++ b/tools/artifacts/testResults.ps1 @@ -4,7 +4,8 @@ Param( $result = @{} -$testRoot = Resolve-Path "$PSScriptRoot\..\..\test" +$RepoRoot = Resolve-Path "$PSScriptRoot\..\.." +$testRoot = Join-Path $RepoRoot test $result[$testRoot] = (Get-ChildItem "$testRoot\TestResults" -Recurse -Directory | Get-ChildItem -Recurse -File) $artifactStaging = & "$PSScriptRoot/../Get-ArtifactsStagingDirectory.ps1" diff --git a/tools/dotnet-test-cloud.ps1 b/tools/dotnet-test-cloud.ps1 index 529d5e921..df3265748 100644 --- a/tools/dotnet-test-cloud.ps1 +++ b/tools/dotnet-test-cloud.ps1 @@ -20,12 +20,14 @@ Param( [string]$Agent='Local', [switch]$PublishResults, [switch]$x86, - [string]$dotnet32 + [string]$dotnet32, + [switch]$netfxOnly, + [string]$logIsolationName ) $RepoRoot = (Resolve-Path "$PSScriptRoot/..").Path $ArtifactStagingFolder = & "$PSScriptRoot/Get-ArtifactsStagingDirectory.ps1" -$FailsOnMonoFilter = & "$PSScriptRoot/variables/FailsOnMonoFilter.ps1" +$OnCI = ($env:CI -or $env:TF_BUILD) $dotnet = 'dotnet' if ($x86) { @@ -45,26 +47,70 @@ if ($x86) { } } -$testBinLog = Join-Path $ArtifactStagingFolder (Join-Path build_logs test.binlog) -$testDiagLog = Join-Path $ArtifactStagingFolder (Join-Path test_logs diag.log) +$binlogName = if ($logIsolationName) { "test_$logIsolationName.binlog" } else { "test.binlog" } +$testBinLog = Join-Path $ArtifactStagingFolder (Join-Path build_logs $binlogName) -& $dotnet test $RepoRoot ` - --no-build ` - -c $Configuration ` - --filter "TestCategory!=FailsInCloudTest$FailsOnMonoFilter" ` - --collect "Code Coverage;Format=cobertura" ` - --settings "$PSScriptRoot/test.runsettings" ` - --blame-hang-timeout 60s ` - --blame-crash ` - -bl:"$testBinLog" ` - --diag "$testDiagLog;TraceLevel=info" ` - --logger trx ` +$testLogs = Join-Path $ArtifactStagingFolder test_logs +if ($logIsolationName) { + $testLogs = Join-Path $testLogs $logIsolationName +} + +$globalJson = Get-Content $PSScriptRoot/../global.json | ConvertFrom-Json +$isMTP = $globalJson.test.runner -eq 'Microsoft.Testing.Platform' +$extraArgs = @() + +if ($netfxOnly) { + $extraArgs += '--framework','net472' +} + +if ($isMTP) { + if ($OnCI) { $extraArgs += '--no-progress' } + & $dotnet test --solution $RepoRoot ` + --no-build ` + -c $Configuration ` + -bl:"$testBinLog" ` + --filter-not-trait 'TestCategory=FailsInCloudTest' ` + --coverage ` + --coverage-output-format cobertura ` + --coverage-settings "$PSScriptRoot/test.runsettings" ` + --hangdump ` + --hangdump-timeout 60s ` + --crashdump ` + --diagnostic ` + --diagnostic-output-directory $testLogs ` + --diagnostic-verbosity Information ` + --results-directory $testLogs ` + --report-trx ` + @extraArgs + + $trxFiles = Get-ChildItem -Recurse -Path $testLogs\*.trx +} else { + $testDiagLog = Join-Path $ArtifactStagingFolder (Join-Path test_logs diag.log) + & $dotnet test $RepoRoot ` + --no-build ` + -c $Configuration ` + --filter "TestCategory!=FailsInCloudTest" ` + --collect "Code Coverage;Format=cobertura" ` + --settings "$PSScriptRoot/test.runsettings" ` + --blame-hang-timeout 60s ` + --blame-crash ` + -bl:"$testBinLog" ` + --diag "$testDiagLog;TraceLevel=info" ` + --logger trx ` + @extraArgs + + $trxFiles = Get-ChildItem -Recurse -Path $RepoRoot\test\*.trx +} $unknownCounter = 0 -Get-ChildItem -Recurse -Path $RepoRoot\test\*.trx |% { - Copy-Item $_ -Destination $ArtifactStagingFolder/test_logs/ +$trxFiles |% { + New-Item $testLogs -ItemType Directory -Force | Out-Null + if (!($_.FullName.StartsWith($testLogs))) { + Copy-Item $_ -Destination $testLogs + } if ($PublishResults) { + $runTitleIsolationSuffix = if ($logIsolationName) { ", $logIsolationName" } else { "" } $x = [xml](Get-Content -LiteralPath $_) $runTitle = $null if ($x.TestRun.TestDefinitions -and $x.TestRun.TestDefinitions.GetElementsByTagName('UnitTest')) { @@ -73,13 +119,13 @@ Get-ChildItem -Recurse -Path $RepoRoot\test\*.trx |% { if ($matches.rid) { $runTitle = "$($matches.lib) ($($matches.tfm), $($matches.rid), $Agent)" } else { - $runTitle = "$($matches.lib) ($($matches.tfm)$x86RunTitleSuffix, $Agent)" + $runTitle = "$($matches.lib) ($($matches.tfm)$x86RunTitleSuffix$runTitleIsolationSuffix, $Agent)" } } } if (!$runTitle) { $unknownCounter += 1; - $runTitle = "unknown$unknownCounter ($Agent$x86RunTitleSuffix)"; + $runTitle = "unknown$unknownCounter ($Agent$x86RunTitleSuffix$runTitleIsolationSuffix)"; } Write-Host "##vso[results.publish type=VSTest;runTitle=$runTitle;publishRunAttachments=true;resultFiles=$_;failTaskOnFailedTests=true;testRunSystem=VSTS - PTR;]"