Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion eng/InstallRuntimes.proj
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@

<Target Name="InstallTestRuntimes"
AfterTargets="Build"
DependsOnTargets="CleanupVersionManifest;InstallRuntimesWindows;InstallRuntimesUnix;InstallBuildSdk;OverrideLatestRuntime;WriteTestVersionManifest" />
DependsOnTargets="CleanupVersionManifest;InstallRuntimesWindows;InstallRuntimesUnix;InstallHostRuntimeX86;InstallBuildSdk;OverrideLatestRuntime;WriteTestVersionManifest" />

<!--
When cross-building (host arch != target arch), install a host-architecture SDK
Expand All @@ -85,6 +85,24 @@
IgnoreStandardErrorWarningFormat="true" />
</Target>

<!--
Stage the x86 host shared framework so the xUnit v3 / MTP test executable can start on the
Windows x86 test leg. Arcade's XUnitV3 RunTests target launches each test exe with
DOTNET_ROOT_X86=$(TestDotNetRoot)x86 (== $(ArtifactsDotnetTestDir)x86). A 32-bit apphost
reads DOTNET_ROOT_X86 before DOTNET_ROOT and does not fall back if it is set, so the x86
runtime must live in that subdirectory. The rest of the x86 install (SDK + all
RuntimeTestVersions) stays at the $(ArtifactsDotnetTestDir) root, where debuggees resolve it
via DotNetRoot. This replaces the global.json tools.runtimes.dotnet/x86 entry that used to
stage the same x86 shared framework into .dotnet.
-->

<Target Name="InstallHostRuntimeX86"
Condition="'$(TargetArch)' == 'x86' and $([MSBuild]::IsOsPlatform(Windows)) and !Exists('$(DotNetInstallRoot)x86\shared\Microsoft.NETCore.App\$(MicrosoftNETCoreApp100Version)')">

<Exec Command="$(PowershellWrapper) &quot;&amp; { &amp;$(DotnetInstallScriptCmd) -NoPath -SkipNonVersionedFiles -Architecture x86 -Runtime dotnet -Version $(MicrosoftNETCoreApp100Version) -InstallDir $(DotNetInstallRoot)x86 }&quot;"
IgnoreStandardErrorWarningFormat="true" />
</Target>

<!--
Installs the test runtimes on Windows
-->
Expand Down
53 changes: 49 additions & 4 deletions eng/build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,27 @@ if ($test) {
$env:SOS_TEST_INTERPRETER="true"
}

# Build the test filter argument if provided
# Use backslash-escaped quotes so they survive the additional quoting in tools.ps1
# Build the test filter argument if provided.
# Tests run as xUnit v3 / Microsoft.Testing.Platform executables, so use the MTP
# filter options (--filter-method / --filter-class) instead of the old xunit.console
# -method / -class flags.
# Use backslash-escaped quotes so they survive the additional quoting in tools.ps1.
#
# A filter is applied to EVERY project in the test traversal, so projects that don't
# contain a matching test legitimately run zero tests. MTP returns exit code 8 ("zero
# tests ran") in that case, which Arcade would otherwise treat as a failure. Append
# --ignore-exit-code 8 so those non-matching projects don't fail the run. The trade-off
# (a mistyped filter that matches nothing anywhere would pass silently) is covered by the
# "at least one test ran" guard after the test run below.
$testFilterActive = $false
$testFilterArg = ''
if ($methodfilter -ne '') {
$testFilterArg = "/p:TestRunnerAdditionalArguments=\`"-method $methodfilter\`""
$testFilterActive = $true
$testFilterArg = "/p:TestRunnerAdditionalArguments=\`"--filter-method $methodfilter --ignore-exit-code 8\`""
}
elseif ($classfilter -ne '') {
$testFilterArg = "/p:TestRunnerAdditionalArguments=\`"-class $classfilter\`""
$testFilterActive = $true
$testFilterArg = "/p:TestRunnerAdditionalArguments=\`"--filter-class $classfilter --ignore-exit-code 8\`""
}

# When the managed build was skipped (e.g. the test-only CI legs that download prebuilt
Expand All @@ -146,6 +159,17 @@ if ($test) {
}
}

# When a filter is active it is applied to every project in the traversal, so non-matching
# projects run zero tests. --ignore-exit-code 8 (added to $testFilterArg above) keeps those
# from failing the run; to still catch a filter that matches nothing ANYWHERE, count the
# tests that ran after the build. Clear this run's result XMLs first so the post-run count
# only reflects the current run (result file names embed the target framework, so stale
# files from a previous run would not otherwise be overwritten).
$resultsDir = Join-Path (Join-Path $artifactsdir "TestResults") $configuration
if ($testFilterActive -and (Test-Path $resultsDir)) {
Remove-Item (Join-Path $resultsDir "*.xml") -Force -ErrorAction SilentlyContinue
}

& "$engroot\common\build.ps1" `
-test `
-restore:$skipmanaged `
Expand All @@ -167,5 +191,26 @@ if ($test) {
if ($lastExitCode -ne 0) {
exit $lastExitCode
}

# Guard against a filter that silently matches nothing (see note above): sum the test
# counts from the xUnit result XMLs this run produced and fail if nothing ran.
if ($testFilterActive) {
$testsRan = 0
if (Test-Path $resultsDir) {
foreach ($xml in Get-ChildItem $resultsDir -Filter *.xml -File -ErrorAction SilentlyContinue) {
try {
[xml]$doc = Get-Content -LiteralPath $xml.FullName -Raw
foreach ($asm in @($doc.assemblies.assembly)) {
if ($asm -and $asm.total) { $testsRan += [int]$asm.total }
}
} catch { }
}
}
if ($testsRan -eq 0) {
Write-Host "ERROR: The test filter matched zero tests across all projects. Check the -methodfilter/-classfilter value." -ForegroundColor Red
exit 1
}
Write-Host "Test filter matched $testsRan test(s) across the run." -ForegroundColor Green
}
}
}
45 changes: 41 additions & 4 deletions eng/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,12 @@ handle_arguments() {
;;

methodfilter|-methodfilter)
__TestFilter="-method $2"
__TestFilter="--filter-method $2"
__ShiftArgs=1
;;

classfilter|-classfilter)
__TestFilter="-class $2"
__TestFilter="--filter-class $2"
__ShiftArgs=1
;;

Expand Down Expand Up @@ -347,10 +347,19 @@ if [[ "$__Test" == 1 ]]; then
export SOS_TEST_INTERPRETER="true"
fi

# Build the test filter argument if provided
# Build the test filter argument if provided.
#
# A filter is applied to EVERY project in the test traversal, so projects that don't
# contain a matching test legitimately run zero tests. MTP returns exit code 8 ("zero
# tests ran") in that case, which Arcade would otherwise treat as a failure. Append
# --ignore-exit-code 8 so those non-matching projects don't fail the run. The trade-off
# (a mistyped filter that matches nothing anywhere would pass silently) is covered by the
# "at least one test ran" guard after the test run below.
__TestFilterArg=
__TestFilterActive=0
if [[ -n "$__TestFilter" ]]; then
__TestFilterArg="/p:TestRunnerAdditionalArguments=\"$__TestFilter\""
__TestFilterActive=1
__TestFilterArg="/p:TestRunnerAdditionalArguments=\"$__TestFilter --ignore-exit-code 8\""
fi

# When the managed build was skipped (e.g. the test-only CI legs that download prebuilt
Expand All @@ -377,6 +386,17 @@ if [[ "$__Test" == 1 ]]; then
fi
fi

# When a filter is active it is applied to every project in the traversal, so non-matching
# projects run zero tests. --ignore-exit-code 8 (added to __TestFilterArg above) keeps those
# from failing the run; to still catch a filter that matches nothing ANYWHERE, count the
# tests that ran after the build. Clear this run's result XMLs first so the post-run count
# only reflects the current run (result file names embed the target framework, so stale
# files from a previous run would not otherwise be overwritten).
__ResultsDir="$__RootBinDir/TestResults/$__BuildType"
if [[ "$__TestFilterActive" == 1 && -d "$__ResultsDir" ]]; then
rm -f "$__ResultsDir"/*.xml
fi

# __CommonMSBuildArgs contains TargetOS property
"$__RepoRootDir/eng/common/build.sh" \
--test \
Expand All @@ -397,6 +417,23 @@ if [[ "$__Test" == 1 ]]; then
if [ $? != 0 ]; then
exit 1
fi

# Guard against a filter that silently matches nothing (see note above): sum the test
# counts from the xUnit result XMLs this run produced and fail if nothing ran.
if [[ "$__TestFilterActive" == 1 ]]; then
__TestsRan=0
if [[ -d "$__ResultsDir" ]]; then
__TestsRan=$(cat "$__ResultsDir"/*.xml 2>/dev/null | grep -oE '<assembly [^>]*total="[0-9]+"' | grep -oE 'total="[0-9]+"' | grep -oE '[0-9]+' | awk '{s+=$1} END {print s+0}')
fi
if [[ -z "$__TestsRan" ]]; then
__TestsRan=0
fi
if [[ "$__TestsRan" == 0 ]]; then
echo "ERROR: The test filter matched zero tests across all projects. Check the -methodfilter/-classfilter value."
exit 1
fi
echo "Test filter matched $__TestsRan test(s) across the run."
fi
fi
fi

Expand Down
10 changes: 4 additions & 6 deletions global.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@
"allowPrerelease": true,
"rollForward": "major"
},
"test": {
"runner": "Microsoft.Testing.Platform"
},
"tools": {
"dotnet": "10.0.110",
"runtimes": {
"dotnet/x86": [
"$(MicrosoftNETCoreApp100Version)"
]
}
"dotnet": "10.0.110"
},
"msbuild-sdks": {
"Microsoft.Build.NoTargets": "3.7.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using System.IO.Compression;
using System.Net.Http;
using System.Threading.Tasks;
using Xunit.Abstractions;
using Xunit;

namespace Microsoft.Diagnostics.TestHelpers
{
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.Diagnostics.TestHelpers/AssertX.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

using System;
using System.IO;
using Xunit.Abstractions;
using Xunit;

namespace Microsoft.Diagnostics.TestHelpers
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Xunit.Abstractions;
using Xunit;

namespace Microsoft.Diagnostics.TestHelpers
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,26 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using Xunit.Abstractions;
using Xunit;

namespace Microsoft.Diagnostics.TestHelpers
{
public class ConsoleTestOutputHelper : ITestOutputHelper
{
public string Output => string.Empty;

public void Write(string message)
{
Console.Write(message);
Console.Out.Flush();
}

public void Write(string format, params object[] args)
{
Console.Write(format, args);
Console.Out.Flush();
}

public void WriteLine(string message)
{
Console.WriteLine(message);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using System.IO;
using System.Threading.Tasks;
using System.Xml.Linq;
using Xunit.Abstractions;
using Xunit;

namespace Microsoft.Diagnostics.TestHelpers
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

using System;
using System.Threading.Tasks;
using Xunit.Abstractions;
using Xunit;

namespace Microsoft.Diagnostics.TestHelpers
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Xunit.Abstractions;
using Xunit;

namespace Microsoft.Diagnostics.TestHelpers
{
Expand Down
20 changes: 19 additions & 1 deletion src/Microsoft.Diagnostics.TestHelpers/FileTestOutputHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

using System;
using System.IO;
using Xunit.Abstractions;
using Xunit;

namespace Microsoft.Diagnostics.TestHelpers
{
Expand All @@ -24,6 +24,24 @@ public FileTestOutputHelper(string logFilePath, FileMode fileMode = FileMode.Cre
_lock = new object();
}

public string Output => string.Empty;

public void Write(string message)
{
lock (_lock)
{
_logWriter.Write(message);
}
}

public void Write(string format, params object[] args)
{
lock (_lock)
{
_logWriter.Write(format, args);
}
}

public void WriteLine(string message)
{
lock (_lock)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Xunit.Abstractions;
using Xunit;

namespace Microsoft.Diagnostics.TestHelpers
{
Expand All @@ -20,6 +20,18 @@ public IndentedTestOutputHelper(ITestOutputHelper innerOutput, string indentText
_indentText = indentText;
}

public string Output => _output.Output;

public void Write(string message)
{
_output.Write(_indentText + message);
}

public void Write(string format, params object[] args)
{
_output.Write(_indentText + format, args);
}

public void WriteLine(string message)
{
_output.WriteLine(_indentText + message);
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.Diagnostics.TestHelpers/LoggingListener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using System;
using System.Diagnostics;
using Microsoft.Diagnostics.DebugServices.Implementation;
using Xunit.Abstractions;
using Xunit;

namespace Microsoft.Diagnostics.TestHelpers
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@

<ItemGroup>
<PackageReference Include="Microsoft.DotNet.RemoteExecutor" Version="$(MicrosoftDotNetRemoteExecutorVersion)" />
<PackageReference Include="xunit" Version="$(XUnitVersion)" />
<PackageReference Include="xunit.abstractions" Version="$(XUnitAbstractionsVersion)" />
<PackageReference Include="xunit.v3.extensibility.core" Version="$(XUnitV3Version)" />
<PackageReference Include="xunit.v3.assert" Version="$(XUnitV3Version)" />
</ItemGroup>

<ItemGroup>
Expand Down
Loading