Skip to content

Commit

Permalink
[Continuation] - Enable the fundamentals behind libraries tests compi…
Browse files Browse the repository at this point in the history
…led via Crossgen2 (dotnet#80946)

* Added the documentation regarding the new libraries test modes.

* Enable the fundamentals behind libraries tests compiled via crossgen2.

* Fixed a typo with SINGLE_FILE_TEST_RUNNER.

* Addressed review comments.

* Restored an accidentally deleted comment.

* Fixed wrong Crossgen2 path and added comment with link to an important tracking SDK bug.
  • Loading branch information
ivdiazsa authored Feb 20, 2023
1 parent 6d325e1 commit bf0608f
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 23 deletions.
61 changes: 52 additions & 9 deletions docs/workflow/testing/libraries/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,80 +5,88 @@
These example commands automate the test run and all pre-requisite build steps in a single command from a clean enlistment.

- Run all tests - Builds clr in release, libs+tests in debug:

```
build.cmd/sh -subset clr+libs+libs.tests -test -rc Release
```

- Run all tests - Builds Mono in release, libs+tests in debug:

```
build.cmd/sh -subset mono+libs+libs.tests -test -rc Release
```

- Run all tests - Build Mono and libs for x86 architecture in debug (choosing debug for runtime will run very slowly):

```
build.cmd/sh -subset mono+libs+libs.tests -test -arch x86
```

## Partial Build and Test Runs

Doing full build and test runs takes a long time and is very inefficient if you need to iterate on a change.
For greater control and efficiency individual parts of the build + testing workflow can be run in isolation.
See the [Building instructions](../../building/libraries/README.md) for more info on build options.
Doing full build and test runs takes a long time and is very inefficient if you need to iterate on a change. For greater control and efficiency individual parts of the build + testing workflow can be run in isolation. See the [Building instructions](../../building/libraries/README.md) for more info on build options.

### Test Run Pre-requisites
Before any tests can run we need a complete build to run them on. This requires building (1) a runtime, and
(2) all the libraries. Examples:

Before any tests can run we need a complete build to run them on. This requires building (1) a runtime, and (2) all the libraries. Examples:

- Build release clr + debug libraries

```
build.cmd/sh -subset clr+libs -rc Release
```

- Build release mono + debug libraries

```
build.cmd/sh -subset mono+libs -rc Release
```

Building the `libs` subset or any of individual library projects automatically copies product binaries into the testhost folder
in the bin directory. This is where the tests will load the binaries from during the run. However System.Private.CorLib is an
exception - the build does not automatically copy it to the testhost folder. If you [rebuild System.Private.CoreLib](https://github.com/dotnet/runtime/blob/main/docs/workflow/building/libraries/README.md#iterating-on-systemprivatecorelib-changes) you must also build the `libs.pretest` subset to ensure S.P.C is copied before running tests.
Building the `libs` subset or any of individual library projects automatically copies product binaries into the testhost folder in the bin directory. This is where the tests will load the binaries from during the run. However System.Private.CorLib is an exception - the build does not automatically copy it to the testhost folder. If you [rebuild System.Private.CoreLib](https://github.com/dotnet/runtime/blob/main/docs/workflow/building/libraries/README.md#iterating-on-systemprivatecorelib-changes) you must also build the `libs.pretest` subset to ensure S.P.C is copied before running tests.

### Running tests for all libraries

- Build and run all tests in release configuration.

```
build.cmd/sh -subset libs.tests -test -c Release
```

- Build the tests without running them

```
build.cmd/sh -subset libs.tests
```

- Run the tests without building them

```
build.cmd/sh -subset libs.tests -test -testnobuild
```

- The following example shows how to pass extra msbuild properties to ignore tests ignored in CI.

```
build.cmd/sh -subset libs.tests -test /p:WithoutCategories=IgnoreForCI
```

### Running tests for a single library

The easiest (and recommended) way to build and run the tests for a specific library, is to invoke the `Test` target on that library:

```cmd
cd src\libraries\System.Collections.Immutable\tests
dotnet build /t:Test
```

It is possible to pass parameters to the underlying xunit runner via the `XUnitOptions` parameter, e.g.:

```cmd
dotnet build /t:Test /p:XUnitOptions="-class Test.ClassUnderTests"
```

Which is very useful when you want to run tests as `x86` on a `x64` machine:

```cmd
dotnet build /t:Test /p:TargetArchitecture=x86
```
Expand All @@ -88,17 +96,52 @@ There may be multiple projects in some directories so you may need to specify th
### Running a single test on the command line

To quickly run or debug a single test from the command line, set the XunitMethodName property, e.g.:

```cmd
dotnet build /t:Test /p:XunitMethodName={FullyQualifiedNamespace}.{ClassName}.{MethodName}
```

### Running outer loop tests

To run all tests, including "outer loop" tests (which are typically slower and in some test suites less reliable, but which are more comprehensive):

```cmd
dotnet build /t:Test /p:Outerloop=true
```

### Running tests on a different target framework

Each test project can potentially have multiple target frameworks. There are some tests that might be OS-specific, or might be testing an API that is available only on some target frameworks, so the `TargetFrameworks` property specifies the valid target frameworks.
Each test project can potentially have multiple target frameworks. There are some tests that might be OS-specific, or might be testing an API that is available only on some target frameworks, so the `TargetFrameworks` property specifies the valid target frameworks.

### Running tests in custom compilation modes

There are several custom compilation modes for tests. These are enabled by setting a switch during the configuration. These switches are described in the following table:

| Mode | Description | Prerequisite Subsets |
| -------------- | --------------------------------------------------------- | -------------------- |
| TestSingleFile | Test using the single file compilation mode | libs+clr |
| TestNativeAot | Test by compiling using NativeAOT | libs+clr.aot |
| TestReadyToRun | Test compilation of the tests/libraries into R2R binaries | libs+clr |

To run a test in a specific mode, simply build the tests after building the prerequisite subsets, and specify the test mode in the command-line. For example, to use the _TestReadyToRun_ mode in Release configuration:

```bash
dotnet build -c Release -t:Test -p:TestReadyToRun=true
```

<!-- NOTE: It might be worth it to explain what each of these flags actually does. -->
It is important to highlight that these tests do not use the standard XUnit test runner. Instead, they run with the [SingleFileTestRunner](/src/libraries/Common/tests/SingleFileTestRunner/SingleFileTestRunner.cs). The set of available commands is listed here:

- `-xml`
- `-notrait`
- `-class`
- `-class-`
- `-noclass`
- `-method`
- `-method-`
- `-nomethod`
- `-namespace`
- `-namespace-`
- `-nonamespace`
- `-parallel`

1 change: 1 addition & 0 deletions eng/testing/tests.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<VSTestNoLogo>true</VSTestNoLogo>
<ILLinkDescriptorsPath>$(MSBuildThisFileDirectory)ILLinkDescriptors\</ILLinkDescriptorsPath>
<TestSingleFile Condition="'$(TestNativeAot)' == 'true'">true</TestSingleFile>
<TestSingleFile Condition="'$(TestReadyToRun)' == 'true'">true</TestSingleFile>
</PropertyGroup>

<PropertyGroup Condition="'$(TargetsMobile)' == 'true'">
Expand Down
44 changes: 32 additions & 12 deletions eng/testing/tests.singlefile.targets
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
<PropertyGroup>
<OutputType>Exe</OutputType>

<DefineConstants>$(DefineConstants);SINGLE_FILE_TEST_RUNNER</DefineConstants>

<BundleDir>$([MSBuild]::NormalizeDirectory('$(OutDir)', 'publish'))</BundleDir>
<RunScriptOutputPath>$([MSBuild]::NormalizePath('$(BundleDir)', '$(RunScriptOutputName)'))</RunScriptOutputPath>
<RuntimeIdentifier>$(OutputRid)</RuntimeIdentifier>
Expand All @@ -18,6 +16,11 @@
<SelfContained>true</SelfContained>
</PropertyGroup>

<PropertyGroup Condition="'$(TestReadyToRun)' == 'true'">
<PublishReadyToRun>true</PublishReadyToRun>
<PublishSingleFile>false</PublishSingleFile>
</PropertyGroup>

<PropertyGroup Condition="'$(TestNativeAot)' == 'true'">
<IlcToolsPath>$(CoreCLRILCompilerDir)</IlcToolsPath>
<IlcToolsPath Condition="'$(TargetArchitecture)' != '$(BuildArchitecture)'">$(CoreCLRCrossILCompilerDir)</IlcToolsPath>
Expand All @@ -35,6 +38,10 @@
<SelfContained>true</SelfContained>
</PropertyGroup>

<PropertyGroup Condition="'$(PublishSingleFile)' == 'true' or '$(TestNativeAot)' == 'true'">
<DefineConstants>$(DefineConstants);SINGLE_FILE_TEST_RUNNER</DefineConstants>
</PropertyGroup>

<Import Project="$(CoreCLRBuildIntegrationDir)Microsoft.DotNet.ILCompiler.SingleEntry.targets" Condition="'$(TestNativeAot)' == 'true'" />

<ItemGroup Condition="'$(TestNativeAot)' == 'true'">
Expand Down Expand Up @@ -93,16 +100,29 @@
<Target Name="LocateNativeCompiler"
Condition="'$(TestNativeAot)' == 'true' and '$(HostOS)' != 'windows'"
BeforeTargets="SetupOSSpecificProps">
<PropertyGroup>
<CppCompilerAndLinker Condition="'$(CppCompilerAndLinker)' == ''">clang</CppCompilerAndLinker>
</PropertyGroup>

<Exec Command="sh -c 'build_arch=&quot;$(TargetArchitecture)&quot; compiler=&quot;$(CppCompilerAndLinker)&quot; . &quot;$(RepositoryEngineeringDir)/common/native/init-compiler.sh&quot; &amp;&amp; echo $CC' 2>/dev/null"
EchoOff="true"
ConsoleToMsBuild="true"
StandardOutputImportance="Low">
<Output TaskParameter="ConsoleOutput" PropertyName="CppLinker" />
</Exec>
<PropertyGroup>
<CppCompilerAndLinker Condition="'$(CppCompilerAndLinker)' == ''">clang</CppCompilerAndLinker>
</PropertyGroup>

<Exec Command="sh -c 'build_arch=&quot;$(TargetArchitecture)&quot; compiler=&quot;$(CppCompilerAndLinker)&quot; . &quot;$(RepositoryEngineeringDir)/common/native/init-compiler.sh&quot; &amp;&amp; echo $CC' 2>/dev/null"
EchoOff="true"
ConsoleToMsBuild="true"
StandardOutputImportance="Low">
<Output TaskParameter="ConsoleOutput" PropertyName="CppLinker" />
</Exec>
</Target>

<Target Name="__ReplaceCrossgen2ExecutableWithFreshlyBuiltOne"
BeforeTargets="_PrepareForReadyToRunCompilation">
<PropertyGroup>
<Crossgen2ArtifactPath>$(CoreCLRCrossgen2Dir)crossgen2$(ExeSuffix)</Crossgen2ArtifactPath>
</PropertyGroup>

<ItemGroup>
<Crossgen2CurrentTool Include="@(Crossgen2Tool->'$(Crossgen2ArtifactPath)')" />
<Crossgen2Tool Remove="@(Crossgen2Tool)" />
<Crossgen2Tool Include="@(Crossgen2CurrentTool)" />
</ItemGroup>
</Target>

<Target Name="PublishTestAsSingleFile"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ public static int Main(string[] args)
var asm = typeof(SingleFileTestRunner).Assembly;
Console.WriteLine("Running assembly:" + asm.FullName);

// The current RemoteExecutor implementation is not compatible with the SingleFileTestRunner.
Environment.SetEnvironmentVariable("DOTNET_REMOTEEXECUTOR_SUPPORTED", "0");

var diagnosticSink = new ConsoleDiagnosticMessageSink();
var testsFinished = new TaskCompletionSource();
var testSink = new TestMessageSink();
Expand Down Expand Up @@ -68,16 +71,77 @@ public static int Main(string[] args)
{
if (args[i].Equals("-notrait", StringComparison.OrdinalIgnoreCase))
{
var traitKeyValue=args[i + 1].Split("=", StringSplitOptions.TrimEntries);
var traitKeyValue = args[i + 1].Split("=", StringSplitOptions.TrimEntries);

if (!noTraits.TryGetValue(traitKeyValue[0], out List<string> values))
{
noTraits.Add(traitKeyValue[0], values = new List<string>());
}

values.Add(traitKeyValue[1]);
i++;
}

if (args[i].Equals("-xml", StringComparison.OrdinalIgnoreCase))
{
xmlResultFileName=args[i + 1].Trim();
xmlResultFileName = args[i + 1].Trim();
i++;
}

if (args[i].Equals("-class", StringComparison.OrdinalIgnoreCase))
{
filters.IncludedClasses.Add(args[i + 1].Trim());
i++;
}

if (args[i].Equals("-noclass", StringComparison.OrdinalIgnoreCase) ||
args[i].Equals("-class-", StringComparison.OrdinalIgnoreCase))
{
filters.ExcludedClasses.Add(args[i + 1].Trim());
i++;
}

if (args[i].Equals("-method", StringComparison.OrdinalIgnoreCase))
{
filters.IncludedMethods.Add(args[i + 1].Trim());
i++;
}

if (args[i].Equals("-nomethod", StringComparison.OrdinalIgnoreCase) ||
args[i].Equals("-method-", StringComparison.OrdinalIgnoreCase))
{
filters.ExcludedMethods.Add(args[i + 1].Trim());
i++;
}

if (args[i].Equals("-namespace", StringComparison.OrdinalIgnoreCase))
{
filters.IncludedNamespaces.Add(args[i + 1].Trim());
i++;
}

if (args[i].Equals("-nonamespace", StringComparison.OrdinalIgnoreCase) ||
args[i].Equals("-namespace-", StringComparison.OrdinalIgnoreCase))
{
filters.ExcludedNamespaces.Add(args[i + 1].Trim());
i++;
}

if (args[i].Equals("-parallel", StringComparison.OrdinalIgnoreCase))
{
string parallelismArg = args[i + 1].Trim().ToLower();
var (parallelizeAssemblies, parallelizeTestCollections) = parallelismArg switch
{
"all" => (true, true),
"assemblies" => (true, false),
"collections" => (false, true),
"none" => (false, false),
_ => throw new ArgumentException($"Unknown parallelism option '{parallelismArg}'.")
};

assemblyConfig.ParallelizeAssembly = parallelizeAssemblies;
assemblyConfig.ParallelizeTestCollections = parallelizeTestCollections;
i++;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,8 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</ProjectReference>
<ProjectReference Include="..\System.Diagnostics.FileVersionInfo.TestAssembly\System.Diagnostics.FileVersionInfo.TestAssembly.csproj" Condition="'$(TargetOS)' == 'browser'" />
<!-- R2R testing does not tolerate the combination of a regular project reference and a content reference. -->
<!-- This is a bug in the SDK tracked here: https://github.com/dotnet/sdk/issues/30718 -->
<PublishReadyToRunExclude Include="System.Diagnostics.FileVersionInfo.TestAssembly.dll" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,8 @@
<OutputItemType>Content</OutputItemType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</ProjectReference>
<!-- R2R testing does not tolerate the combination of a regular project reference and a content reference. -->
<!-- This is a bug in the SDK tracked here: https://github.com/dotnet/sdk/issues/30718 -->
<PublishReadyToRunExclude Include="LongPath.dll" />
</ItemGroup>
</Project>

0 comments on commit bf0608f

Please sign in to comment.