SourceFiles="@(SharedFrameworkPublishFiles)"
DestinationFiles="@(SharedFrameworkPublishFiles->'$(TestsOutputDir)sharedFrameworkPublish/%(RecursiveDir)%(Filename)%(Extension)')" />
- <!-- Create file with a name that describes what a test dir is. Useful if path abbreviated. -->
+ <!-- Create files with a name that describes what a test dir is. Useful if path abbreviated. -->
<WriteLinesToFile
File="$(TestsOutputRootDir)$(TestsOutputName)-is-$(MSBuildProjectName).txt"
Overwrite="true"
Lines="$(MSBuildProjectName) intermediates are located in '$(TestsOutputName)'. Abbreviated to work around path limits on Windows."
Condition="'$(TestsOutputName)' != '$(MSBuildProjectName)'" />
+ <WriteLinesToFile
+ File="$(TestsOutputDir)$(MSBuildProjectName).txt"
+ Overwrite="true"
+ Lines="$(MSBuildProjectName) intermediates are located in '$(TestsOutputName)'. Abbreviated to work around path limits on Windows."
+ Condition="'$(TestsOutputName)' != '$(MSBuildProjectName)'" />
</Target>
- <Target Name="DetermineTestOutputDirectory">
- <GetTargetMachineInfo>
- <Output TaskParameter="RuntimeIdentifier" PropertyName="_HostRid" />
- </GetTargetMachineInfo>
-
- <PropertyGroup>
- <TestTargetRid Condition="'$(TestTargetRid)' == ''">$(_HostRid)</TestTargetRid>
- <TestsOutputName Condition="'$(TestsOutputName)' == ''">$(MSBuildProjectName)</TestsOutputName>
-
- <TestsOutputRootDir Condition="'$(TestsOutputRootDir)' == ''">$(ArtifactsDir)tests/$(ConfigurationGroup)/</TestsOutputRootDir>
- <TestsOutputDir Condition="'$(TestsOutputDir)' == ''">$(TestsOutputRootDir)$(TestsOutputName)/</TestsOutputDir>
- </PropertyGroup>
- </Target>
-
- <Target Name="SetupTextFixtureEnvironment"
- Condition="'$(SkipTests)' != 'true'"
+ <Target Name="SetupTestContextVariables"
DependsOnTargets="
GetProductVersions;
DetermineTestOutputDirectory"
- BeforeTargets="RunTests">
+ BeforeTargets="Build">
<PropertyGroup>
- <!-- The tests use the TEST_ARTIFACTS env variable to determine the artifacts folder and then later compare that path to its expected path.
- So, the TEST_ARTIFACTS variable has to have system specific path separators or the string compoarison will fail. -->
+ <!--
+ The tests use the TEST_ARTIFACTS variable to determine the artifacts folder and then later
+ compare that path to its expected path. So, the TEST_ARTIFACTS variable has to have system
+ specific path separators or the string compoarison will fail.
+ -->
<DirectorySeparatorChar>$([System.IO.Path]::DirectorySeparatorChar)</DirectorySeparatorChar>
<SystemPathTestsOutputDir>$([System.String]::Copy('$(TestsOutputDir)').Replace('/', '$(DirectorySeparatorChar)'))</SystemPathTestsOutputDir>
<SystemPathTestsOutputDir>$([System.String]::Copy('$(SystemPathTestsOutputDir)').Replace('\', '$(DirectorySeparatorChar)'))</SystemPathTestsOutputDir>
- </PropertyGroup>
-
- <!-- Set properties used inside tests as environment variables. -->
- <ItemGroup>
- <TestRunnerEnvironmentVariable Include="NUGET_PACKAGES=$(TestRestorePackagesPath)" />
- <TestRunnerEnvironmentVariable Include="TEST_ARTIFACTS=$(SystemPathTestsOutputDir)" />
- <TestRunnerEnvironmentVariable Include="TEST_TARGETRID=$(TestTargetRid)" />
- <TestRunnerEnvironmentVariable Include="BUILDRID=$(OutputRid)" />
- <TestRunnerEnvironmentVariable Include="BUILD_ARCHITECTURE=$(TargetArchitecture)" />
- <TestRunnerEnvironmentVariable Include="BUILD_CONFIGURATION=$(ConfigurationGroup)" />
- <TestRunnerEnvironmentVariable Include="MNA_VERSION=$(ProductVersion)" />
- <TestRunnerEnvironmentVariable Include="MNA_TFM=$(NETCoreAppFramework)" />
- <TestRunnerEnvironmentVariable Include="DOTNET_SDK_PATH=$(DotNetRoot)" />
- </ItemGroup>
- </Target>
-
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory).., Directory.Build.targets))\Directory.Build.targets" />
-
- <!--
- Rewrite Arcade RunTests target to add TestRunnerEnvironmentVariable support. In the future we
- should switch to a file to transfer this information, or derive the info from information on
- disk. Env vars are not likely to be supported in upstream Arcade.
-
- See https://github.com/dotnet/arcade/issues/3077.
- -->
- <!-- <OVERRIDE> https://github.com/dotnet/arcade/blob/dc538a29793fd56618d0fa3186e2388d47d00c19/src/Microsoft.DotNet.Arcade.Sdk/tools/XUnit/XUnit.targets#L25-L120 -->
- <!--
- Include '*' target to force running tests even if the input assemblies haven't changed and the outputs are present.
- This matches the common expectations that test command always runs all tests in scope.
- -->
- <Target Name="RunTests"
- Inputs="@(TestToRun);*"
- Outputs="%(TestToRun.ResultsStdOutPath);%(TestToRun.ResultsXmlPath);%(TestToRun.ResultsHtmlPath)">
-
- <PropertyGroup>
- <_TestEnvironment>%(TestToRun.EnvironmentDisplay)</_TestEnvironment>
- <_TestAssembly>%(TestToRun.Identity)</_TestAssembly>
- <_TestRuntime>%(TestToRun.TestRuntime)</_TestRuntime>
- <_TestRunnerAdditionalArguments>%(TestToRun.TestRunnerAdditionalArguments)</_TestRunnerAdditionalArguments>
-
- <!-- Always use net472 for desktop to enable displaying source location from Portable PDBs in stack traces -->
- <_TestRunnerTargetFramework>net472</_TestRunnerTargetFramework>
- <_TestRunnerTargetFramework Condition="'$(_TestRuntime)' == 'Core'">netcoreapp2.0</_TestRunnerTargetFramework>
- <_TestRunnerTargetFramework Condition="%(TestToRun.TargetFramework) == 'netcoreapp1.1' or %(TestToRun.TargetFramework) == 'netcoreapp1.0'">netcoreapp1.0</_TestRunnerTargetFramework>
- </PropertyGroup>
-
- <PropertyGroup Condition="'$(_TestRuntime)' == 'Core'">
- <_TargetFileNameNoExt>$([System.IO.Path]::GetFileNameWithoutExtension('$(_TestAssembly)'))</_TargetFileNameNoExt>
- <_TargetDir>$([System.IO.Path]::GetDirectoryName('$(_TestAssembly)'))\</_TargetDir>
- <_CoreRuntimeConfigPath>$(_TargetDir)$(_TargetFileNameNoExt).runtimeconfig.json</_CoreRuntimeConfigPath>
- <_CoreDepsPath>$(_TargetDir)$(_TargetFileNameNoExt).deps.json</_CoreDepsPath>
-
- <_TestRunner Condition="'%(TestToRun.Architecture)'=='x86' And Exists('$(DotNetRoot)x86\dotnet.exe')">$(DotNetRoot)x86\dotnet.exe</_TestRunner>
- <_TestRunner Condition="'$(_TestRunner)'==''">$(DotNetTool)</_TestRunner>
-
- <_TestRunnerArgs>exec --depsfile "$(_CoreDepsPath)" --runtimeconfig "$(_CoreRuntimeConfigPath)" $(TestRuntimeAdditionalArguments) "$(NuGetPackageRoot)xunit.runner.console/$(XUnitVersion)/tools/$(_TestRunnerTargetFramework)/xunit.console.dll" "$(_TestAssembly)" -noautoreporters -xml "%(TestToRun.ResultsXmlPath)" -html "%(TestToRun.ResultsHtmlPath)" $(_TestRunnerAdditionalArguments)</_TestRunnerArgs>
- </PropertyGroup>
-
- <PropertyGroup Condition="'$(_TestRuntime)' != 'Core'">
- <_XUnitConsoleExe>xunit.console.exe</_XUnitConsoleExe>
- <_XUnitConsoleExe Condition="'%(TestToRun.Architecture)' == 'x86'">xunit.console.x86.exe</_XUnitConsoleExe>
- <_XUnitConsoleExePath>$(NuGetPackageRoot)xunit.runner.console\$(XUnitVersion)\tools\$(_TestRunnerTargetFramework)\$(_XUnitConsoleExe)</_XUnitConsoleExePath>
-
- <_TestRunnerArgs>"$(_TestAssembly)" -noshadow -xml "%(TestToRun.ResultsXmlPath)" -html "%(TestToRun.ResultsHtmlPath)" $(_TestRunnerAdditionalArguments)</_TestRunnerArgs>
- <_TestRunnerArgs Condition="'$(_TestRuntime)' == 'Mono'">$(TestRuntimeAdditionalArguments) "$(_XUnitConsoleExePath)" $(_TestRunnerArgs)</_TestRunnerArgs>
- <_TestRunner Condition="'$(_TestRuntime)' == 'Mono'">$(MonoTool)</_TestRunner>
- <_TestRunner Condition="'$(_TestRuntime)' != 'Mono'">$(_XUnitConsoleExePath)</_TestRunner>
- </PropertyGroup>
-
- <PropertyGroup>
- <_TestRunnerCommand>"$(_TestRunner)" $(_TestRunnerArgs)</_TestRunnerCommand>
-
- <!--
- Redirect std output of the runner.
- Note that xUnit outputs failure info to both STDOUT (stack trace, message) and STDERR (failed test name)
- -->
- <_TestRunnerCommand Condition="'$(TestCaptureOutput)' != 'false'">$(_TestRunnerCommand) > "%(TestToRun.ResultsStdOutPath)" 2>&1</_TestRunnerCommand>
+ <!-- This is defined when building in Visual Studio, not DotNetRoot. -->
+ <DotNetRoot Condition="'$(DotNetRoot)' == ''">$(NetCoreRoot)</DotNetRoot>
</PropertyGroup>
+ <!--
+ Set up properties used inside tests. Write them to a text file so that they can be found
+ inside the VS Test Explorer context the same way as the XUnit runner will find them.
+ See https://github.com/dotnet/arcade/issues/3077.
+ -->
<ItemGroup>
- <_OutputFiles Include="%(TestToRun.ResultsXmlPath)" />
- <_OutputFiles Include="%(TestToRun.ResultsHtmlPath)" />
- <_OutputFiles Include="%(TestToRun.ResultsStdOutPath)" />
+ <TestContextVariable Include="NUGET_PACKAGES=$(TestRestorePackagesPath)" />
+ <TestContextVariable Include="TEST_ARTIFACTS=$(SystemPathTestsOutputDir)" />
+ <TestContextVariable Include="TEST_TARGETRID=$(TestTargetRid)" />
+ <TestContextVariable Include="BUILDRID=$(OutputRid)" />
+ <TestContextVariable Include="BUILD_ARCHITECTURE=$(TargetArchitecture)" />
+ <TestContextVariable Include="BUILD_CONFIGURATION=$(ConfigurationGroup)" />
+ <TestContextVariable Include="MNA_VERSION=$(ProductVersion)" />
+ <TestContextVariable Include="MNA_TFM=$(NETCoreAppFramework)" />
+ <TestContextVariable Include="DOTNET_SDK_PATH=$(DotNetRoot)" />
</ItemGroup>
- <MakeDir Directories="@(_OutputFiles->'%(RootDir)%(Directory)')"/>
- <Delete Files="@(_OutputFiles)" />
-
- <Message Text="Running tests: $(_TestAssembly) [$(_TestEnvironment)]" Importance="high"/>
- <!-- <CHANGE> Add env var parameter, taking TestRunnerEnvironmentVariable items. -->
- <Exec
- Command='$(_TestRunnerCommand)'
- EnvironmentVariables="@(TestRunnerEnvironmentVariable)"
- LogStandardErrorAsError="false"
- WorkingDirectory="$(_TargetDir)"
- IgnoreExitCode="true">
- <!-- </CHANGE> -->
- <Output TaskParameter="ExitCode" PropertyName="_TestErrorCode" />
- </Exec>
-
- <!--
- Add command line to the log.
- -->
- <WriteLinesToFile File="%(TestToRun.ResultsStdOutPath)"
- Overwrite="false"
- Lines=";=== COMMAND LINE ===;$(_TestRunnerCommand)"
- Condition="'$(TestCaptureOutput)' != 'false'" />
+ <WriteLinesToFile
+ File="$(OutDir)TestContextVariables.txt"
+ Overwrite="true"
+ Lines="@(TestContextVariable)" />
+ </Target>
- <!--
- Report test status.
- -->
- <Message Text="Tests succeeded: $(_TestAssembly) [$(_TestEnvironment)]" Condition="'$(_TestErrorCode)' == '0'" Importance="high" />
+ <Target Name="DetermineTestOutputDirectory">
+ <GetTargetMachineInfo>
+ <Output TaskParameter="RuntimeIdentifier" PropertyName="_HostRid" />
+ </GetTargetMachineInfo>
<PropertyGroup>
- <_ResultsFileToDisplay>%(TestToRun.ResultsHtmlPath)</_ResultsFileToDisplay>
- <_ResultsFileToDisplay Condition="!Exists('$(_ResultsFileToDisplay)')">%(TestToRun.ResultsStdOutPath)</_ResultsFileToDisplay>
- </PropertyGroup>
-
- <!--
- Ideally we would set ContinueOnError="ErrorAndContinue" so that when a test fails in multi-targeted test project
- we'll still run tests for all target frameworks. ErrorAndContinue doesn't work well on Linux though: https://github.com/Microsoft/msbuild/issues/3961.
- -->
- <Error Text="Tests failed: $(_ResultsFileToDisplay) [$(_TestEnvironment)]" Condition="'$(_TestErrorCode)' != '0'" File="XUnit" />
+ <TestTargetRid Condition="'$(TestTargetRid)' == ''">$(_HostRid)</TestTargetRid>
+ <TestsOutputName Condition="'$(TestsOutputName)' == ''">$(MSBuildProjectName)</TestsOutputName>
- <ItemGroup>
- <FileWrites Include="@(_OutputFiles)"/>
- </ItemGroup>
+ <TestsOutputRootDir Condition="'$(TestsOutputRootDir)' == ''">$(ArtifactsDir)tests/$(ConfigurationGroup)/</TestsOutputRootDir>
+ <TestsOutputDir Condition="'$(TestsOutputDir)' == ''">$(TestsOutputRootDir)$(TestsOutputName)/</TestsOutputDir>
+ </PropertyGroup>
</Target>
- <!-- </OVERRIDE> -->
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory).., Directory.Build.targets))\Directory.Build.targets" />
</Project>
using System;
using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Immutable;
using System.IO;
+using System.Linq;
namespace Microsoft.DotNet.CoreSetup.Test
{
public string BuildArchitecture { get; }
public string TargetRID { get; }
public string MicrosoftNETCoreAppVersion { get; }
+ public string Configuration { get; }
public string RepoRoot { get; }
+ public string BaseArtifactsFolder { get; }
+ public string BaseBinFolder { get; }
+ public string BaseObjFolder { get; }
public string Artifacts { get; }
public string HostArtifacts { get; }
public string BuiltDotnet { get; }
public string CorehostPackages { get; }
public string DotnetSDK { get; }
+ private string _testContextVariableFilePath { get; }
+ private ImmutableDictionary<string, string> _testContextVariables { get; }
+
public RepoDirectoriesProvider(
string repoRoot = null,
string artifacts = null,
{
RepoRoot = repoRoot ?? GetRepoRootDirectory();
- string baseArtifactsFolder = artifacts ?? Path.Combine(RepoRoot, "artifacts");
- string baseBinFolder = artifacts ?? Path.Combine(baseArtifactsFolder, "bin");
- string baseObjFolder = artifacts ?? Path.Combine(baseArtifactsFolder, "obj");
+ _testContextVariableFilePath = Path.Combine(
+ Directory.GetCurrentDirectory(),
+ "TestContextVariables.txt");
+
+ _testContextVariables = File.ReadAllLines(_testContextVariableFilePath)
+ .ToImmutableDictionary(
+ line => line.Substring(0, line.IndexOf('=')),
+ line => line.Substring(line.IndexOf('=') + 1),
+ StringComparer.OrdinalIgnoreCase);
+
+ BaseArtifactsFolder = artifacts ?? Path.Combine(RepoRoot, "artifacts");
+ BaseBinFolder = artifacts ?? Path.Combine(BaseArtifactsFolder, "bin");
+ BaseObjFolder = artifacts ?? Path.Combine(BaseArtifactsFolder, "obj");
- TargetRID = Environment.GetEnvironmentVariable("TEST_TARGETRID");
- BuildRID = Environment.GetEnvironmentVariable("BUILDRID");
- BuildArchitecture = Environment.GetEnvironmentVariable("BUILD_ARCHITECTURE");
- MicrosoftNETCoreAppVersion = microsoftNETCoreAppVersion ?? Environment.GetEnvironmentVariable("MNA_VERSION");
+ TargetRID = GetTestContextVariable("TEST_TARGETRID");
+ BuildRID = GetTestContextVariable("BUILDRID");
+ BuildArchitecture = GetTestContextVariable("BUILD_ARCHITECTURE");
+ MicrosoftNETCoreAppVersion = microsoftNETCoreAppVersion ?? GetTestContextVariable("MNA_VERSION");
- string configuration = Environment.GetEnvironmentVariable("BUILD_CONFIGURATION");
- string osPlatformConfig = $"{BuildRID}.{configuration}";
+ Configuration = GetTestContextVariable("BUILD_CONFIGURATION");
+ string osPlatformConfig = $"{BuildRID}.{Configuration}";
- DotnetSDK = dotnetSdk ?? Environment.GetEnvironmentVariable("DOTNET_SDK_PATH");
+ DotnetSDK = dotnetSdk ?? GetTestContextVariable("DOTNET_SDK_PATH");
if (!Directory.Exists(DotnetSDK))
{
throw new InvalidOperationException("ERROR: Test SDK folder not found.");
}
- Artifacts = Path.Combine(baseBinFolder, osPlatformConfig);
+ Artifacts = Path.Combine(BaseBinFolder, osPlatformConfig);
HostArtifacts = artifacts ?? Path.Combine(Artifacts, "corehost");
NugetPackages = nugetPackages ??
- Environment.GetEnvironmentVariable("NUGET_PACKAGES") ??
+ GetTestContextVariable("NUGET_PACKAGES") ??
Path.Combine(RepoRoot, ".packages");
CorehostPackages = corehostPackages ?? Path.Combine(Artifacts, "corehost");
- BuiltDotnet = builtDotnet ?? Path.Combine(baseObjFolder, osPlatformConfig, "sharedFrameworkPublish");
+ BuiltDotnet = builtDotnet ?? Path.Combine(BaseObjFolder, osPlatformConfig, "sharedFrameworkPublish");
+ }
+
+ public string GetTestContextVariable(string name)
+ {
+ return GetTestContextVariableOrNull(name) ?? throw new ArgumentException(
+ $"Unable to find variable '{name}' in " +
+ $"test context variable file '{_testContextVariableFilePath}'");
+ }
+
+ public string GetTestContextVariableOrNull(string name)
+ {
+ // Allow env var override, although normally the test context variables file is used.
+ // Don't accept NUGET_PACKAGES env override specifically: Arcade sets this and it leaks
+ // in during build.cmd/sh runs, replacing the test-specific dir.
+ if (!name.Equals("NUGET_PACKAGES", StringComparison.OrdinalIgnoreCase))
+ {
+ if (Environment.GetEnvironmentVariable(name) is string envValue)
+ {
+ return envValue;
+ }
+ }
+
+ if (_testContextVariables.TryGetValue(name, out string value))
+ {
+ return value;
+ }
+
+ return null;
}
private static string GetRepoRootDirectory()