Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
1bbfc9c
Add a basic xunit runner generator that generates a top-level-stateme…
jkoritzinsky Oct 22, 2021
6523a11
Fix some bugs in the generator. Convert the Interop/PInvoke/Vector2_3…
jkoritzinsky Oct 22, 2021
6143a48
Implement support for [Fact] methods that are instance methods on IDi…
jkoritzinsky Oct 22, 2021
9b9ae95
Import enum sources from XUnitExtensions and hook up support for some…
jkoritzinsky Oct 25, 2021
54e93eb
Add one more newline
jkoritzinsky Oct 25, 2021
14ca067
Add preliminary support for building an IL test runner using the sour…
jkoritzinsky Oct 25, 2021
149ffe2
Rename to make the logic clearer.
jkoritzinsky Oct 25, 2021
23b7975
Update src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs
jkoritzinsky Oct 25, 2021
623cc48
Add support for extern-alias with references (to handle conflicting n…
jkoritzinsky Oct 26, 2021
a20864e
Apply suggestions from code review
jkoritzinsky Nov 2, 2021
4a7ebe9
Merge branch 'main' of github.com:dotnet/runtime into xunit-runner-ge…
jkoritzinsky Nov 2, 2021
f5009c8
Update src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs
jkoritzinsky Nov 2, 2021
59960aa
Add the XUnit wrapper generator to the list of ambient project depend…
trylek Nov 2, 2021
191ac42
Fix nullability bug in XUnitWrapperGenerator
trylek Nov 2, 2021
a2bdb78
Merge branch 'main' of github.com:dotnet/runtime into xunit-runner-ge…
jkoritzinsky Nov 3, 2021
e597fec
Merge branch 'main' of github.com:dotnet/runtime into xunit-runner-ge…
jkoritzinsky Nov 8, 2021
e783f9e
Write out the exception that caused the test to fail to the console.
jkoritzinsky Nov 8, 2021
c978193
Convert the Castable test to use the generator
jkoritzinsky Nov 8, 2021
270144b
Support running the xunit wrapper generator in "standalone" mode for …
jkoritzinsky Nov 8, 2021
4c73d6f
Add first draft of result reporting infrastructure.
jkoritzinsky Nov 8, 2021
e81deda
Fix IL .assembly directive to be the assembly name that can be resolv…
jkoritzinsky Nov 9, 2021
4f9dcbb
Add test reporting for "merged test runner" assemblies.
jkoritzinsky Nov 10, 2021
d5961f6
Add Microsoft.DotNet.XUnitExtensions to the targetting pack.
jkoritzinsky Nov 10, 2021
4d412d0
Add support for the rest of ActiveIssueAttribute
jkoritzinsky Nov 10, 2021
377b8a0
Add support for more attributes and clean up code.
jkoritzinsky Nov 10, 2021
835f56d
Add support for SkipOnCoreClrAttribute.
jkoritzinsky Nov 10, 2021
c84c5d1
Merge branch 'main' of github.com:dotnet/runtime into xunit-runner-ge…
jkoritzinsky Nov 10, 2021
b7fb243
Support running tests with the [Fact] attribute that return 100 for s…
jkoritzinsky Nov 10, 2021
d49c1f4
Fix failures and update comment
jkoritzinsky Nov 10, 2021
1b19bed
Update src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs
jkoritzinsky Nov 11, 2021
040877c
Fix handling of SkipOnCoreClrAttribute and SkipOnMonoAttribute with R…
jkoritzinsky Nov 11, 2021
d736995
Add support for running tests marked with <RequiresProcessIsolation>t…
jkoritzinsky Nov 12, 2021
a77d13c
Merge branch 'main' into xunit-runner-generator
jkoritzinsky Nov 12, 2021
04650fd
Add support for substring-based test filtering and add infrastructure…
jkoritzinsky Nov 15, 2021
8ef73bd
Integrate work from #61224 with some modifications based on offline d…
jkoritzinsky Nov 15, 2021
5881fa1
Fix Castable.csproj and fix SkipOnMono/SkipOnCoreCLR attribute support.
jkoritzinsky Nov 15, 2021
eccf29a
Work around tests that hit compiler limits. Move tests that used Xuni…
jkoritzinsky Nov 16, 2021
ccd08a2
Rewrite how superpmicollect sets up its testing to make it more frien…
jkoritzinsky Nov 16, 2021
db68ce4
Add back the _BuildSpmiTestProjectScripts target since I'm not sure w…
jkoritzinsky Nov 17, 2021
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
Prev Previous commit
Next Next commit
Add support for running tests marked with <RequiresProcessIsolation>t…
…rue</RequiresProcessIsolation> in a separate process using the cmd/sh build scripts.
  • Loading branch information
jkoritzinsky committed Nov 12, 2021
commit d736995844131d874784d1741052f10b442807f3
4 changes: 4 additions & 0 deletions src/tests/Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
<Compile Include="HostPolicyMock.cs" />
<Compile Include="XPlatformUtils.cs" />
<Compile Include="CoreClrConfigurationDetection.cs" />
<Compile Include="OutOfProcessTest.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Coreclr.TestWrapper\CoreclrTestWrapperLib.cs" Link="CoreclrTestWrapperLib.cs" />
</ItemGroup>

<ItemGroup>
Expand Down
132 changes: 132 additions & 0 deletions src/tests/Common/CoreCLRTestLibrary/OutOfProcessTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using CoreclrTestLib;
using Xunit;

namespace TestLibrary
{
public static class OutOfProcessTest
{
internal static bool runningInWindows;
internal static string reportBase;
internal static string testBinaryBase;
internal static string helixUploadRoot;

static OutOfProcessTest()
{
reportBase = Directory.GetCurrentDirectory();
testBinaryBase = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
helixUploadRoot = Environment.GetEnvironmentVariable("HELIX_WORKITEM_UPLOAD_ROOT");
if (!String.IsNullOrEmpty(helixUploadRoot))
{
reportBase = Path.Combine(Path.GetFullPath(helixUploadRoot), "Reports");
}

if (String.IsNullOrEmpty(reportBase))
{
reportBase = Path.Combine(testBinaryBase, "Reports");
}
else
{
reportBase = Path.GetFullPath(reportBase);
}
}

public static void RunOutOfProcessTest(string basePath, string assemblyPath)
{
int ret = -100;
string outputFile = System.IO.Path.GetFullPath(reportBase + assemblyPath + "output.txt");
string errorFile = System.IO.Path.GetFullPath(reportBase + assemblyPath + "error.txt");
string outputDir = System.IO.Path.GetDirectoryName(outputFile)!;
string testExecutable = null;
Exception infraEx = null;

try
{
CoreclrTestWrapperLib wrapper = new CoreclrTestWrapperLib();

if (OperatingSystem.IsWindows())
{
testExecutable = Path.Combine(basePath, Path.ChangeExtension(assemblyPath, ".cmd"));
}
else
{
testExecutable = Path.Combine(basePath, Path.ChangeExtension(assemblyPath.Replace("\\", "/"), ".sh"));
}

System.IO.Directory.CreateDirectory(reportBase + Path.GetDirectoryName(assemblyPath));

ret = wrapper.RunTest(testExecutable, outputFile, errorFile, Assembly.GetEntryAssembly()!.FullName!, testBinaryBase, outputDir);
}
catch (Exception ex)
{
infraEx = ex;
}

if (infraEx != null)
{
Assert.True(false, "Test Infrastructure Failure: " + infraEx.ToString());
}
else
{
List<string> testOutput = new List<string>();

try
{
testOutput.AddRange(System.IO.File.ReadAllLines(errorFile));
}
catch (Exception ex)
{
testOutput.Add("Unable to read error file: " + errorFile);
testOutput.Add(ex.ToString());
}

testOutput.Add(string.Empty);
testOutput.Add("Return code: " + ret);
testOutput.Add("Raw output file: " + outputFile);
testOutput.Add("Raw output:");

try
{
testOutput.AddRange(System.IO.File.ReadAllLines(outputFile));
}
catch (Exception ex)
{
testOutput.Add("Unable to read output file: " + outputFile);
testOutput.Add(ex.ToString());
}

testOutput.Add("To run the test:");
testOutput.Add("Set up CORE_ROOT and run.");
testOutput.Add("> " + testExecutable);

var unicodeControlCharsRegex = new Regex("%5C%5Cp{C}+");

// Remove all characters that have no visual or spatial representation.
for (int i = 0; i < testOutput.Count; i++)
{
string line = testOutput[i];
line = unicodeControlCharsRegex.Replace(line, string.Empty);
testOutput[i] = line;
}

foreach (string line in testOutput)
{
Console.WriteLine(line);
}

Assert.True(ret == CoreclrTestWrapperLib.EXIT_SUCCESS_CODE, string.Join(Environment.NewLine, testOutput));
}
}
}
}
7 changes: 3 additions & 4 deletions src/tests/Common/Coreclr.TestWrapper/CoreclrTestWrapperLib.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
//
#nullable disable

using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -196,7 +197,7 @@ public class CoreclrTestWrapperLib
{
public const int EXIT_SUCCESS_CODE = 0;
public const string TIMEOUT_ENVIRONMENT_VAR = "__TestTimeout";

// Default timeout set to 10 minutes
public const int DEFAULT_TIMEOUT_MS = 1000 * 60 * 10;

Expand Down Expand Up @@ -289,7 +290,7 @@ public int RunTest(string executable, string outputFile, string errorFile, strin
Debug.Assert(outputFile != errorFile);

int exitCode = -100;

// If a timeout was given to us by an environment variable, use it instead of the default
// timeout.
string environmentVar = Environment.GetEnvironmentVariable(TIMEOUT_ENVIRONMENT_VAR);
Expand Down Expand Up @@ -387,7 +388,5 @@ public int RunTest(string executable, string outputFile, string errorFile, strin

return exitCode;
}


}
}
31 changes: 26 additions & 5 deletions src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Text;
using Microsoft.CodeAnalysis;

Expand Down Expand Up @@ -160,7 +161,7 @@ private static string GetPlatformConditionFromTestPlatform(Xunit.TestPlatforms p
}
if (platform.HasFlag(Xunit.TestPlatforms.tvOS))
{
platformCheckConditions.Add("global::System.OperatingSystem.IsTVOS()");
platformCheckConditions.Add("global::System.OperatingSystem.IsTvOS()");
}
if (platform.HasFlag(Xunit.TestPlatforms.MacCatalyst))
{
Expand Down Expand Up @@ -228,14 +229,34 @@ public override bool Equals(object obj)
}
}

class NoTestReporting : ITestReporterWrapper
sealed class OutOfProcessTest : ITestInfo
{
public OutOfProcessTest(string displayName, string relativeAssemblyPath)
{
Method = displayName;
TestNameExpression = $"@\"{displayName}\"";
ExecutionStatement = $@"TestLibrary.OutOfProcessTest.RunOutOfProcessTest(typeof(Program).Assembly.Location, @""{relativeAssemblyPath}"");";
}

public string TestNameExpression { get; }

public string Method { get; }

public string ContainingType => "OutOfProcessTest";

private string ExecutionStatement { get; }

public string GenerateTestExecution(ITestReporterWrapper testReporterWrapper) => testReporterWrapper.WrapTestExecutionWithReporting(ExecutionStatement, this);
}

sealed class NoTestReporting : ITestReporterWrapper
{
public string WrapTestExecutionWithReporting(string testExecution, ITestInfo test) => testExecution;

public string GenerateSkippedTestReporting(ITestInfo skippedTest) => string.Empty;
}

class WrapperLibraryTestSummaryReporting : ITestReporterWrapper
sealed class WrapperLibraryTestSummaryReporting : ITestReporterWrapper
{
private string _summaryLocalIdentifier;

Expand All @@ -252,10 +273,10 @@ public string WrapTestExecutionWithReporting(string testExecutionExpression, ITe
builder.AppendLine($"TimeSpan testStart = stopwatch.Elapsed;");
builder.AppendLine("try {");
builder.AppendLine(testExecutionExpression);
builder.AppendLine($"{_summaryLocalIdentifier}.ReportPassedTest({test.TestNameExpression}, \"{test.ContainingType}\", \"{test.Method}\", stopwatch.Elapsed - testStart);");
builder.AppendLine($"{_summaryLocalIdentifier}.ReportPassedTest({test.TestNameExpression}, \"{test.ContainingType}\", @\"{test.Method}\", stopwatch.Elapsed - testStart);");
builder.AppendLine("}");
builder.AppendLine("catch (System.Exception ex) {");
builder.AppendLine($"{_summaryLocalIdentifier}.ReportFailedTest({test.TestNameExpression}, \"{test.ContainingType}\", \"{test.Method}\", stopwatch.Elapsed - testStart, ex);");
builder.AppendLine($"{_summaryLocalIdentifier}.ReportFailedTest({test.TestNameExpression}, \"{test.ContainingType}\", @\"{test.Method}\", stopwatch.Elapsed - testStart, ex);");
builder.AppendLine("}");

builder.AppendLine("}");
Expand Down
17 changes: 13 additions & 4 deletions src/tests/Common/XUnitWrapperGenerator/OptionsHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ namespace XUnitWrapperGenerator;

public static class OptionsHelper
{
public const string ReferenceSystemPrivateCoreLibOption = "build_property.ReferenceSystemPrivateCoreLib";
public const string IsMergedTestRunnerAssemblyOption = "build_property.IsMergedTestRunnerAssembly";
public const string PriorityOption = "build_property.Priority";
public const string RuntimeFlavorOption = "build_property.RuntimeFlavor";
private const string ReferenceSystemPrivateCoreLibOption = "build_property.ReferenceSystemPrivateCoreLib";
private const string IsMergedTestRunnerAssemblyOption = "build_property.IsMergedTestRunnerAssembly";
private const string PriorityOption = "build_property.Priority";
private const string RuntimeFlavorOption = "build_property.RuntimeFlavor";
private const string IsOutOfProcessTestAssemblyOption = "build_metadata.AdditionalFiles.IsOutOfProcessTestAssembly";
private const string TestAssemblyRelativePathOption = "build_metadata.AdditionalFiles.TestAssemblyRelativePath";
private const string TestDisplayNameOption = "build_metadata.AdditionalFiles.TestDisplayName";

private static bool GetBoolOption(this AnalyzerConfigOptions options, string key)
{
Expand All @@ -32,4 +35,10 @@ private static bool GetBoolOption(this AnalyzerConfigOptions options, string key
internal static int? Priority(this AnalyzerConfigOptions options) => options.GetIntOption(PriorityOption);

internal static string RuntimeFlavor(this AnalyzerConfigOptions options) => options.TryGetValue(RuntimeFlavorOption, out string? flavor) ? flavor : "CoreCLR";

internal static bool IsOutOfProcessTestAssembly(this AnalyzerConfigOptions options) => options.GetBoolOption(IsOutOfProcessTestAssemblyOption);

internal static string? TestAssemblyRelativePath(this AnalyzerConfigOptions options) => options.TryGetValue(TestAssemblyRelativePathOption, out string? flavor) ? flavor : null;

internal static string? TestDisplayName(this AnalyzerConfigOptions options) => options.TryGetValue(TestDisplayNameOption, out string? flavor) ? flavor : null;
}
31 changes: 29 additions & 2 deletions src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,24 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
return visitor.Visit(data.Right.GetAssemblyOrModuleSymbol(data.Left))!;
});

var assemblyName = context.CompilationProvider.Select((comp, ct) => comp.Assembly.MetadataName);
var outOfProcessTests = context.AdditionalTextsProvider.Combine(context.AnalyzerConfigOptionsProvider).SelectMany((data, ct) =>
{
var (file, options) = data;

AnalyzerConfigOptions fileOptions = options.GetOptions(file);

if (fileOptions.IsOutOfProcessTestAssembly())
{
string? assemblyPath = fileOptions.TestAssemblyRelativePath();
string? testDisplayName = fileOptions.TestDisplayName();
if (assemblyPath is not null && testDisplayName is not null)
{
return ImmutableArray.Create<ITestInfo>(new OutOfProcessTest(testDisplayName, assemblyPath));
}
}

return ImmutableArray<ITestInfo>.Empty;
});

var allMethods = methodsInSource.Collect().Combine(methodsInReferencedAssemblies.Collect()).SelectMany((methods, ct) => methods.Left.AddRange(methods.Right));

Expand All @@ -48,12 +65,16 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
return aliasMap.ToImmutable();
}).WithComparer(new ImmutableDictionaryValueComparer<string, string>(EqualityComparer<string>.Default));

var assemblyName = context.CompilationProvider.Select((comp, ct) => comp.Assembly.MetadataName);

context.RegisterImplementationSourceOutput(
allMethods
.Combine(context.AnalyzerConfigOptionsProvider)
.Combine(aliasMap)
.SelectMany((data, ct) => ImmutableArray.CreateRange(GetTestMethodInfosForMethod(data.Left.Left, data.Left.Right, data.Right)))
.Collect()
.Combine(outOfProcessTests.Collect())
.Select((tests, ct) => tests.Left.AddRange(tests.Right))
.Combine(aliasMap)
.Combine(context.AnalyzerConfigOptionsProvider)
.Combine(assemblyName),
Expand Down Expand Up @@ -318,6 +339,7 @@ private static IEnumerable<ITestInfo> GetTestMethodInfosForMethod(IMethodSymbol
if (options.GlobalOptions.RuntimeFlavor() != "CoreCLR")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be a big problem to postpone the platform / runtime check to the actual runtime execution? We can do it in a future change but ideally we should be able to use the same managed build for Mono and CoreCLR (I don't believe we're doing that now, we have two different legs for that purpose but that's also cost that could be reduced).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only mechanism known today to detect runtime flavor at runtime easily is though reflection, which is very heavyweight for the src/tests test tree. I'm trying to keep the platform checks as cheap as possible so as to not make the "bring up" tests in the JIT significantly less useful, which is why I try to hard-code them at generation time when possible.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. I think it's OK to leave as is for now, I can look into it as part of the new-style Helix publishing; in particular I believe we're setting up about two dozens of environment variables that get set on the Helix execution machine and these include target architecture and OS so I guess we could use these for the runtime checks. We can also add an arbitrary number of additional environment variables as we need to express any of the execution characteristics.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be a big problem to postpone the platform / runtime check to the actual runtime execution? We can do it in a future change but ideally we should be able to use the same managed build for Mono and CoreCLR (I don't believe we're doing that now, we have two different legs for that purpose but that's also cost that could be reduced).

{
// If we're building tests not for CoreCLR, we can skip handling the specifics of the SkipOnCoreClrAttribute.
testInfos = ImmutableArray<ITestInfo>.Empty;
break;
}

Expand Down Expand Up @@ -508,7 +530,12 @@ private static ImmutableArray<ITestInfo> DecorateWithSkipOnPlatform(ImmutableArr
options.GlobalOptions.TryGetValue("build_property.TargetOS", out string? targetOS);
Xunit.TestPlatforms targetPlatform = GetPlatformForTargetOS(targetOS);

if (platformsToSkip.HasFlag(targetPlatform))
if (platformsToSkip == 0)
{
// In this case, we don't need to skip any platforms
return testInfos;
}
else if (platformsToSkip.HasFlag(targetPlatform))
{
// If the target platform is skipped, then we don't have any tests to emit.
return ImmutableArray<ITestInfo>.Empty;
Expand Down
11 changes: 11 additions & 0 deletions src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,16 @@
<!-- Properties that influence test harness generation -->
<CompilerVisibleProperty Include="ReferenceSystemPrivateCoreLib" />
<CompilerVisibleProperty Include="IsMergedTestRunnerAssembly" />
<CompilerVisibleItemMetadata Include="AdditionalFiles" MetadataName="IsOutOfProcessTestAssembly" />
<CompilerVisibleItemMetadata Include="AdditionalFiles" MetadataName="TestAssemblyRelativePath" />
<CompilerVisibleItemMetadata Include="AdditionalFiles" MetadataName="TestDisplayName" />
</ItemGroup>

<Target Name="AddOutOfProcessTestAssembliesToCompilation" AfterTargets="ResolveProjectReferences">
<ItemGroup>
<OutOfProcessTests IsOutOfProcessTestAssembly="true" TestAssemblyRelativePath="$([MSBuild]::MakeRelative('$(OutputPath)', '%(Identity)'))" TestDisplayName="$([MSBuild]::MakeRelative('$(TestBinDir)', '%(Identity)'))" />
<!-- Change the extension to .cmd to match the existing test names for out-of-proc test runs. -->
<AdditionalFiles Include="@(OutOfProcessTests)" TestDisplayName="$([System.IO.Path]::ChangeExtension('%(TestDisplayName)', '.cmd'))" />
</ItemGroup>
</Target>
</Project>
1 change: 1 addition & 0 deletions src/tests/Common/external/external.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
<PackageToInclude Include="Microsoft.CodeAnalysis.CSharp"/>
<PackageToInclude Include="Microsoft.CodeAnalysis.VisualBasic"/>
<PackageToInclude Include="CommandLineParser"/>
<PackageToInclude Include="Microsoft.DotNet.XUnitExtensions" />

<PackageReference Include="Microsoft.CodeAnalysis.Compilers" Version="1.1.1" />
<PackageReference Include="CommandLineParser" Version="2.1.1-beta" />
Expand Down
17 changes: 17 additions & 0 deletions src/tests/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,23 @@

</Target>

<Target Name="GetRequiresProcessIsolation" Returns="@(ProjectRequiringProcessIsolation)">
<ItemGroup Condition="'$(RequiresProcessIsolation)' == 'true'">
<ProjectRequiringProcessIsolation Include="$(MSBuildProjectFullPath)" />
</ItemGroup>
</Target>

<Target Name="DiscoverProcessIsolatedTestProjectReferences" BeforeTargets="AssignProjectConfiguration">
<MSBuild Projects="@(ProjectReference)" Targets="GetRequiresProcessIsolation" SkipNonexistentTargets="true">
<Output TaskParameter="TargetOutputs" ItemName="ReferencedProjectRequiringProcessIsolation" />
</MSBuild>

<ItemGroup>
<ProjectReference Remove="@(ReferencedProjectRequiringProcessIsolation)" />
<ProjectReference Include="@(ReferencedProjectRequiringProcessIsolation)" OutputItemType="OutOfProcessTests" BuildReference="true" ReferenceOutputAssembly="false" />
</ItemGroup>
</Target>

<Import Project="$(RepoRoot)eng/liveBuilds.targets" />
<Import Project="$(MSBuildProjectFullPath).targets" Condition="Exists('$(MSBuildProjectFullPath).targets')"/>

Expand Down