diff --git a/src/tests/Common/XUnitWrapperGenerator/CodeBuilder.cs b/src/tests/Common/XUnitWrapperGenerator/CodeBuilder.cs new file mode 100644 index 0000000000000..1477f544de348 --- /dev/null +++ b/src/tests/Common/XUnitWrapperGenerator/CodeBuilder.cs @@ -0,0 +1,228 @@ +// 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.Text; +using static System.FormattableString; + +namespace XUnitWrapperGenerator; + +/// +/// A helper class for generating indented code. Indentation is automatically added to lines. +/// Trailing whitespace is removed from lines. +/// +[DebuggerDisplay("Code = {_code}")] +public class CodeBuilder { + private readonly Stack _indentLevels; + private string _currentIndentString; + private readonly int _indentSize; + private readonly StringBuilder _code; + private const int DefaultAdditionalIndent = 1; + + private sealed class IndentationContext : IDisposable { + private CodeBuilder Builder { get; } + private bool _disposed; + private string? EndLine { get; } + + /// + /// Constructor. + /// + /// The associated with this object. + /// The number of indentation levels to add. + /// Line to add after disposing the indentation context + public IndentationContext(CodeBuilder builder, uint additionalIndent = DefaultAdditionalIndent, string? endLine = null) { + Builder = builder; + _disposed = false; + EndLine = endLine; + Builder.PushIndent(additionalIndent); + } + + /// + /// Performs cleanup actions at the end of the lifetime. + /// This involves decreasing the level of indentation on + /// the object that was used to + /// construct this . + /// + public void Dispose() { + if (_disposed) return; + Builder.PopIndent(); + if (EndLine != null) Builder.AppendLine(EndLine); + _disposed = true; + } + } + + /// + /// Constructor. + /// + /// The number of spaces each level of indentation adds. + public CodeBuilder(uint indentSize = 4) { + _indentLevels = new Stack(); + _indentSize = Convert.ToInt32(indentSize); + _currentIndentString = ""; + _code = new StringBuilder(); + _indentLevels.Push(0); + } + + public bool IsEmpty => _code.Length == 0; + + public static CodeBuilder Create(string initialCode) { + var code = new CodeBuilder(); + code.Append(initialCode); + return code; + } + + public static CodeBuilder CreateNewLine(string initialCode) { + var code = new CodeBuilder(); + code.Append(initialCode); + code.AppendLine(); + return code; + } + + /// + /// Push a new indent level. + /// + /// The amount of indentation to add. + public void PushIndent(uint additionalIndent = DefaultAdditionalIndent) { + int existingIndent = _indentLevels.Peek(); + var newIndent = (int) (existingIndent + additionalIndent); + _indentLevels.Push(newIndent); + _currentIndentString = new string(' ', newIndent * _indentSize); + } + + /// + /// Pop an indent level (and restore the indent level to before the last call to ). + /// + public void PopIndent() { + _indentLevels.Pop(); + _currentIndentString = new string(' ', _indentLevels.Peek() * _indentSize); + } + + private bool AtStartOfLine() { + if (_code.Length == 0) { + return true; + } + + return _code[_code.Length - 1] == '\n'; + } + + private void Append(string code, bool allowLeadingWhiteSpace) { + if (string.IsNullOrEmpty(code)) return; + + string[] lines = code.Split('\n'); + + // Do entire check first to avoid a partial write in the case of failure + if (!allowLeadingWhiteSpace) { + for (int i = 0; i < lines.Length; ++i) { + if ((i > 0 || AtStartOfLine()) + && (lines[i].Length > 0) && char.IsWhiteSpace(lines[i][0])) { + throw new ArgumentException(Invariant($@"Whitespace (0x{(int)lines[i][0]:x2}) at start of line {i} in input '{code}'")); + } + } + } + + for (int i = 0; i < lines.Length; ++i) { + if (i != 0) AppendLine(); + + string line = lines[i]; + if (AtStartOfLine() && !string.IsNullOrWhiteSpace(line)) _code.Append(_currentIndentString); + _code.Append(line); + } + } + + /// + /// Append the given code. The currently active indentation level is applied at newlines. + /// + /// Thrown when a line already contains leading whitespace + /// The code to append. + public void Append(string code) => Append(code, allowLeadingWhiteSpace: false); + + /// + /// Append the given, already-indented code. The currently active indentation level is also applied at newlines. + /// + /// The code to append. + public void AppendIndented(string code) => Append(code, allowLeadingWhiteSpace: true); + + /// + /// Append the given, already-indented code. The currently active indentation level is also applied at newlines. + /// + /// The code to append. + public void Append(CodeBuilder code) => AppendIndented(code.GetCode()); + + /// + /// Append the given code followed by a line terminator. The currently active indentation level is applied at newlines. + /// + /// The line to append. + public void AppendLine(string codeLine) { + Append(codeLine); + AppendLine(); + } + + /// Append a blank line. + public void AppendLine() { + int lastToKeep; + for (lastToKeep = _code.Length - 1; lastToKeep >= 0; --lastToKeep) { + if (_code[lastToKeep] == '\n' || !char.IsWhiteSpace(_code[lastToKeep])) { + break; + } + } + _code.Length = lastToKeep + 1; + _code.AppendLine(); + } + + /// + /// Appends a block of code using the current indentation. + /// + /// The code block. + public void AppendBlock(string block) { + if (block == null) throw new ArgumentNullException(nameof(block)); + + using (var reader = new StringReader(block)) { + string line = reader.ReadLine(); + if (line == null) return; + + AppendIndented(line); + while ((line = reader.ReadLine()) != null) { + AppendLine(); + AppendIndented(line); + } + } + } + + /// + /// Creates a new . + /// + /// + /// String to add before the braces and indentation context. If non-empty, then a new line will be + /// appended after it. + /// + /// Number of indentation levels to add. + /// A new . + public IDisposable NewScope(string? introduction = null, uint additionalIndent = DefaultAdditionalIndent) { + if (!string.IsNullOrEmpty(introduction)) { + this.AppendLine(introduction!); + } + return new IndentationContext(this, additionalIndent); + } + + /// + /// Creates a new with an introduction and + /// surrounded by braces. + /// + /// String to add before the braces and indentation context. + /// Number of indentation levels to add. + /// A new . + public IDisposable NewBracesScope(string? introduction = null, uint additionalIndent = DefaultAdditionalIndent) { + if (!string.IsNullOrEmpty(introduction)) { + this.Append(introduction!); + } + this.AppendLine(string.IsNullOrEmpty(introduction) ? "{" : " {"); + return new IndentationContext(this, additionalIndent: additionalIndent, endLine: "}"); + } + + /// Returns the built-up code. + /// The built-up code. + public string GetCode() => _code.ToString(); +} diff --git a/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs b/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs index 81e07deb6041e..afbfeb30a566b 100644 --- a/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs +++ b/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs @@ -17,12 +17,12 @@ interface ITestInfo string Method { get; } string ContainingType { get; } - string GenerateTestExecution(ITestReporterWrapper testReporterWrapper); + CodeBuilder GenerateTestExecution(ITestReporterWrapper testReporterWrapper); } interface ITestReporterWrapper { - string WrapTestExecutionWithReporting(string testExecution, ITestInfo test); + CodeBuilder WrapTestExecutionWithReporting(CodeBuilder testExecution, ITestInfo test); string GenerateSkippedTestReporting(ITestInfo skippedTest); } @@ -52,9 +52,9 @@ public BasicTestMethod(IMethodSymbol method, string externAlias, ImmutableArray< public string ContainingType { get; } private string ExecutionStatement { get; } - public string GenerateTestExecution(ITestReporterWrapper testReporterWrapper) + public CodeBuilder GenerateTestExecution(ITestReporterWrapper testReporterWrapper) { - return testReporterWrapper.WrapTestExecutionWithReporting(ExecutionStatement, this); + return testReporterWrapper.WrapTestExecutionWithReporting(CodeBuilder.CreateNewLine(ExecutionStatement), this); } public override bool Equals(object obj) @@ -84,9 +84,9 @@ public LegacyStandaloneEntryPointTestMethod(IMethodSymbol method, string externA public string ContainingType { get; } private string ExecutionStatement { get; } - public string GenerateTestExecution(ITestReporterWrapper testReporterWrapper) + public CodeBuilder GenerateTestExecution(ITestReporterWrapper testReporterWrapper) { - return testReporterWrapper.WrapTestExecutionWithReporting(ExecutionStatement, this); + return testReporterWrapper.WrapTestExecutionWithReporting(CodeBuilder.CreateNewLine(ExecutionStatement), this); } public override bool Equals(object obj) @@ -124,9 +124,20 @@ public ConditionalTest(ITestInfo innerTest, Xunit.TestPlatforms platform) public string Method { get; } public string ContainingType { get; } - public string GenerateTestExecution(ITestReporterWrapper testReporterWrapper) + public CodeBuilder GenerateTestExecution(ITestReporterWrapper testReporterWrapper) { - return $"if ({_condition}) {{ {_innerTest.GenerateTestExecution(testReporterWrapper)} }} else {{ {testReporterWrapper.GenerateSkippedTestReporting(_innerTest)} }}"; + CodeBuilder builder = new(); + builder.AppendLine($"if ({_condition})"); + using (builder.NewBracesScope()) + { + builder.Append(_innerTest.GenerateTestExecution(testReporterWrapper)); + } + builder.AppendLine($"else"); + using (builder.NewBracesScope()) + { + builder.AppendLine(testReporterWrapper.GenerateSkippedTestReporting(_innerTest)); + } + return builder; } public override bool Equals(object obj) @@ -222,14 +233,16 @@ public MemberDataTest(ISymbol referencedMember, ITestInfo innerTest, string exte public string Method { get; } public string ContainingType { get; } - public string GenerateTestExecution(ITestReporterWrapper testReporterWrapper) + public CodeBuilder GenerateTestExecution(ITestReporterWrapper testReporterWrapper) { - return $@" -foreach (object[] {_loopVarIdentifier} in {_memberInvocation}) -{{ - {_innerTest.GenerateTestExecution(testReporterWrapper)} -}} -"; + CodeBuilder builder = new(); + builder.AppendLine(); + builder.AppendLine($@"foreach (object[] {_loopVarIdentifier} in {_memberInvocation})"); + using (builder.NewBracesScope()) + { + builder.Append(_innerTest.GenerateTestExecution(testReporterWrapper)); + } + return builder; } public override bool Equals(object obj) @@ -249,31 +262,35 @@ public OutOfProcessTest(string displayName, string relativeAssemblyPath) Method = displayName; DisplayNameForFiltering = displayName; TestNameExpression = $"@\"{displayName}\""; - ExecutionStatement = $@" -if (TestLibrary.OutOfProcessTest.OutOfProcessTestsSupported) -{{ -TestLibrary.OutOfProcessTest.RunOutOfProcessTest(typeof(Program).Assembly.Location, @""{relativeAssemblyPath}""); -}} -"; + RelativeAssemblyPath = relativeAssemblyPath; + ExecutionStatement = new CodeBuilder(); + ExecutionStatement.AppendLine(); + ExecutionStatement.AppendLine("if (TestLibrary.OutOfProcessTest.OutOfProcessTestsSupported)"); + using (ExecutionStatement.NewBracesScope()) + { + ExecutionStatement.AppendLine($@"TestLibrary.OutOfProcessTest.RunOutOfProcessTest(typeof(Program).Assembly.Location, @""{relativeAssemblyPath}"");"); + } } public string TestNameExpression { get; } public string DisplayNameForFiltering { get; } + private string RelativeAssemblyPath { get; } + public string Method { get; } public string ContainingType => "OutOfProcessTest"; - private string ExecutionStatement { get; } + private CodeBuilder ExecutionStatement { get; } - public string GenerateTestExecution(ITestReporterWrapper testReporterWrapper) => testReporterWrapper.WrapTestExecutionWithReporting(ExecutionStatement, this); + public CodeBuilder GenerateTestExecution(ITestReporterWrapper testReporterWrapper) => testReporterWrapper.WrapTestExecutionWithReporting(ExecutionStatement, this); public override bool Equals(object obj) { return obj is OutOfProcessTest other && DisplayNameForFiltering == other.DisplayNameForFiltering - && ExecutionStatement == other.ExecutionStatement; + && RelativeAssemblyPath == other.RelativeAssemblyPath; } } @@ -295,10 +312,10 @@ public TestWithCustomDisplayName(ITestInfo inner, string displayName) public string ContainingType => _inner.ContainingType; - public string GenerateTestExecution(ITestReporterWrapper testReporterWrapper) + public CodeBuilder GenerateTestExecution(ITestReporterWrapper testReporterWrapper) { ITestReporterWrapper dummyInnerWrapper = new NoTestReporting(); - string innerExecution = _inner.GenerateTestExecution(dummyInnerWrapper); + CodeBuilder innerExecution = _inner.GenerateTestExecution(dummyInnerWrapper); return testReporterWrapper.WrapTestExecutionWithReporting(innerExecution, this); } @@ -312,7 +329,7 @@ public override bool Equals(object obj) sealed class NoTestReporting : ITestReporterWrapper { - public string WrapTestExecutionWithReporting(string testExecution, ITestInfo test) => testExecution; + public CodeBuilder WrapTestExecutionWithReporting(CodeBuilder testExecution, ITestInfo test) => testExecution; public string GenerateSkippedTestReporting(ITestInfo skippedTest) => string.Empty; } @@ -330,38 +347,41 @@ public WrapperLibraryTestSummaryReporting(string summaryLocalIdentifier, string _outputRecorderIdentifier = outputRecorderIdentifier; } - public string WrapTestExecutionWithReporting(string testExecutionExpression, ITestInfo test) + public CodeBuilder WrapTestExecutionWithReporting(CodeBuilder testExecutionExpression, ITestInfo test) { - StringBuilder builder = new(); + CodeBuilder builder = new(); builder.AppendLine($"if ({_filterLocalIdentifier} is null || {_filterLocalIdentifier}.ShouldRunTest(@\"{test.ContainingType}.{test.Method}\"," + $" {test.TestNameExpression}))"); - builder.AppendLine("{"); - - builder.AppendLine($"System.TimeSpan testStart = stopwatch.Elapsed;"); - builder.AppendLine("try {"); - builder.AppendLine($"System.Console.WriteLine(\"{{0:HH:mm:ss.fff}} Running test: {{1}}\", System.DateTime.Now, {test.TestNameExpression});"); - builder.AppendLine($"{_outputRecorderIdentifier}.ResetTestOutput();"); - builder.AppendLine(testExecutionExpression); - - builder.AppendLine($"{_summaryLocalIdentifier}.ReportPassedTest({test.TestNameExpression}, \"{test.ContainingType}\", @\"{test.Method}\"," - + $" stopwatch.Elapsed - testStart, {_outputRecorderIdentifier}.GetTestOutput(), tempLogSw, statsCsvSw);"); - - builder.AppendLine($"System.Console.WriteLine(\"{{0:HH:mm:ss.fff}} Passed test: {{1}}\", System.DateTime.Now, {test.TestNameExpression});"); - builder.AppendLine("}"); - builder.AppendLine("catch (System.Exception ex) {"); - - builder.AppendLine($"{_summaryLocalIdentifier}.ReportFailedTest({test.TestNameExpression}, \"{test.ContainingType}\", @\"{test.Method}\"," - + $" stopwatch.Elapsed - testStart, ex, {_outputRecorderIdentifier}.GetTestOutput(), tempLogSw, statsCsvSw);"); - - builder.AppendLine($"System.Console.WriteLine(\"{{0:HH:mm:ss.fff}} Failed test: {{1}}\", System.DateTime.Now, {test.TestNameExpression});"); - builder.AppendLine("}"); - - builder.AppendLine("}"); + using (builder.NewBracesScope()) + { + builder.AppendLine($"System.TimeSpan testStart = stopwatch.Elapsed;"); + builder.AppendLine("try"); + using (builder.NewBracesScope()) + { + builder.AppendLine($"System.Console.WriteLine(\"{{0:HH:mm:ss.fff}} Running test: {{1}}\", System.DateTime.Now, {test.TestNameExpression});"); + builder.AppendLine($"{_outputRecorderIdentifier}.ResetTestOutput();"); + builder.Append(testExecutionExpression); + + builder.AppendLine($"{_summaryLocalIdentifier}.ReportPassedTest({test.TestNameExpression}, \"{test.ContainingType}\", @\"{test.Method}\"," + + $" stopwatch.Elapsed - testStart, {_outputRecorderIdentifier}.GetTestOutput(), tempLogSw, statsCsvSw);"); + + builder.AppendLine($"System.Console.WriteLine(\"{{0:HH:mm:ss.fff}} Passed test: {{1}}\", System.DateTime.Now, {test.TestNameExpression});"); + } + builder.AppendLine("catch (System.Exception ex)"); + using (builder.NewBracesScope()) + { + builder.AppendLine($"{_summaryLocalIdentifier}.ReportFailedTest({test.TestNameExpression}, \"{test.ContainingType}\", @\"{test.Method}\"," + + $" stopwatch.Elapsed - testStart, ex, {_outputRecorderIdentifier}.GetTestOutput(), tempLogSw, statsCsvSw);"); + + builder.AppendLine($"System.Console.WriteLine(\"{{0:HH:mm:ss.fff}} Failed test: {{1}}\", System.DateTime.Now, {test.TestNameExpression});"); + } + } builder.AppendLine("else"); - builder.AppendLine("{"); - builder.AppendLine(GenerateSkippedTestReporting(test)); - builder.AppendLine("}"); - return builder.ToString(); + using (builder.NewBracesScope()) + { + builder.AppendLine(GenerateSkippedTestReporting(test)); + } + return builder; } public string GenerateSkippedTestReporting(ITestInfo skippedTest) diff --git a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs index ae1d12d57b0f8..3f4e8ae532829 100644 --- a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs +++ b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs @@ -147,19 +147,40 @@ public void Initialize(IncrementalGeneratorInitializationContext context) }); } + private static void AppendAliasMap(CodeBuilder builder, ImmutableDictionary aliasMap) + { + bool didOutput = false; + foreach (string alias in aliasMap.Values.Where(alias => alias != "global").OrderBy(a => a)) + { + builder.AppendLine($"extern alias {alias};"); + didOutput = true; + } + if (didOutput) + { + builder.AppendLine(); + } + } + private static string GenerateFullTestRunner(ImmutableArray testInfos, ImmutableDictionary aliasMap, string assemblyName) { // For simplicity, we'll use top-level statements for the generated Main method. - StringBuilder builder = new(); - builder.AppendLine(string.Join("\n", aliasMap.Values.Where(alias => alias != "global").Select(alias => $"extern alias {alias};"))); + CodeBuilder builder = new(); + AppendAliasMap(builder, aliasMap); + builder.AppendLine("System.Collections.Generic.HashSet testExclusionList = XUnitWrapperLibrary.TestFilter.LoadTestExclusionList();"); + builder.AppendLine(); - builder.Append("\n"); // Make the FullRunner.g.cs file a bit more readable. builder.AppendLine($@"if (System.IO.File.Exists(""{assemblyName}.tempLog.xml""))"); - builder.AppendLine($@"System.IO.File.Delete(""{assemblyName}.tempLog.xml"");"); + using (builder.NewBracesScope()) + { + builder.AppendLine($@"System.IO.File.Delete(""{assemblyName}.tempLog.xml"");"); + } builder.AppendLine($@"if (System.IO.File.Exists(""{assemblyName}.testStats.csv""))"); - builder.AppendLine($@"System.IO.File.Delete(""{assemblyName}.testStats.csv"");"); - builder.Append("\n"); + using (builder.NewBracesScope()) + { + builder.AppendLine($@"System.IO.File.Delete(""{assemblyName}.testStats.csv"");"); + } + builder.AppendLine(); builder.AppendLine("XUnitWrapperLibrary.TestFilter filter = new (args, testExclusionList);"); // builder.AppendLine("XUnitWrapperLibrary.TestSummary summary = new(TestCount.Count);"); @@ -167,154 +188,220 @@ private static string GenerateFullTestRunner(ImmutableArray testInfos builder.AppendLine("System.Diagnostics.Stopwatch stopwatch = System.Diagnostics.Stopwatch.StartNew();"); builder.AppendLine("XUnitWrapperLibrary.TestOutputRecorder outputRecorder = new(System.Console.Out);"); builder.AppendLine("System.Console.SetOut(outputRecorder);"); + builder.AppendLine(); - builder.Append("\n"); builder.AppendLine($@"using (System.IO.StreamWriter tempLogSw = System.IO.File.AppendText(""{assemblyName}.tempLog.xml""))"); - builder.AppendLine($@"using (System.IO.StreamWriter statsCsvSw = System.IO.File.AppendText(""{assemblyName}.testStats.csv"")){{"); - builder.AppendLine("statsCsvSw.WriteLine($\"{TestCount.Count},0,0,0\");"); + builder.AppendLine($@"using (System.IO.StreamWriter statsCsvSw = System.IO.File.AppendText(""{assemblyName}.testStats.csv""))"); - ITestReporterWrapper reporter = new WrapperLibraryTestSummaryReporting("summary", "filter", "outputRecorder"); - - StringBuilder testExecutorBuilder = new(); - int testsLeftInCurrentTestExecutor = 0; - int currentTestExecutor = 0; + CodeBuilder testExecutorBuilder = new(); int totalTestsEmitted = 0; - if (testInfos.Length > 0) + using (builder.NewBracesScope()) { - // Break tests into groups of 50 so that we don't create an unreasonably large main method - // Excessively large methods are known to take a long time to compile, and use excessive stack - // leading to test failures. - foreach (ITestInfo test in testInfos) + builder.AppendLine("statsCsvSw.WriteLine($\"{TestCount.Count},0,0,0\");"); + + ITestReporterWrapper reporter = + new WrapperLibraryTestSummaryReporting("summary", "filter", "outputRecorder"); + + int testsLeftInCurrentTestExecutor = 0; + int currentTestExecutor = 0; + + if (testInfos.Length > 0) { - if (testsLeftInCurrentTestExecutor == 0) + // Break tests into groups of 50 so that we don't create an unreasonably large main method + // Excessively large methods are known to take a long time to compile, and use excessive stack + // leading to test failures. + foreach (ITestInfo test in testInfos) { - if (currentTestExecutor != 0) + if (testsLeftInCurrentTestExecutor == 0) + { + if (currentTestExecutor != 0) + { + testExecutorBuilder.PopIndent(); + testExecutorBuilder.AppendLine("}"); + testExecutorBuilder.AppendLine(); + } + + currentTestExecutor++; + testExecutorBuilder.AppendLine($"void TestExecutor{currentTestExecutor}(System.IO.StreamWriter tempLogSw, System.IO.StreamWriter statsCsvSw)"); + testExecutorBuilder.AppendLine("{"); + testExecutorBuilder.PushIndent(); + + builder.AppendLine($"TestExecutor{currentTestExecutor}(tempLogSw, statsCsvSw);"); + testsLeftInCurrentTestExecutor = 50; // Break test executors into groups of 50, which empirically seems to work well + } + else { - testExecutorBuilder.AppendLine("}"); + testExecutorBuilder.AppendLine(); } - currentTestExecutor++; - testExecutorBuilder.AppendLine($"void TestExecutor{currentTestExecutor}(System.IO.StreamWriter tempLogSw, System.IO.StreamWriter statsCsvSw) {{"); - builder.AppendLine($"TestExecutor{currentTestExecutor}(tempLogSw, statsCsvSw);"); - testsLeftInCurrentTestExecutor = 50; // Break test executors into groups of 50, which empirically seems to work well + testExecutorBuilder.Append(test.GenerateTestExecution(reporter)); + totalTestsEmitted++; + testsLeftInCurrentTestExecutor--; } - testExecutorBuilder.AppendLine(test.GenerateTestExecution(reporter)); - totalTestsEmitted++; - testsLeftInCurrentTestExecutor--; + testExecutorBuilder.PopIndent(); + testExecutorBuilder.AppendLine("}"); + testExecutorBuilder.AppendLine(); } - - testExecutorBuilder.AppendLine("}"); } - - // Closing the 'using' statements that stream the temporary files. - builder.AppendLine("}\n"); + builder.AppendLine(); builder.AppendLine($@"string testResults = summary.GetTestResultOutput(""{assemblyName}"");"); builder.AppendLine($@"string workitemUploadRoot = System.Environment.GetEnvironmentVariable(""HELIX_WORKITEM_UPLOAD_ROOT"");"); - builder.AppendLine($@"if (workitemUploadRoot != null) System.IO.File.WriteAllText(System.IO.Path.Combine(workitemUploadRoot, ""{assemblyName}.testResults.xml.txt""), testResults);"); + builder.AppendLine($@"if (workitemUploadRoot != null)"); + using (builder.NewBracesScope()) + { + builder.AppendLine($@"System.IO.File.WriteAllText(System.IO.Path.Combine(workitemUploadRoot, ""{assemblyName}.testResults.xml.txt""), testResults);"); + } + builder.AppendLine(); + builder.AppendLine($@"System.IO.File.WriteAllText(""{assemblyName}.testResults.xml"", testResults);"); builder.AppendLine("return 100;"); + builder.AppendLine(); builder.Append(testExecutorBuilder); builder.AppendLine("public static class TestCount { public const int Count = " + totalTestsEmitted.ToString() + "; }"); - return builder.ToString(); + return builder.GetCode(); } private static string GenerateXHarnessTestRunner(ImmutableArray testInfos, ImmutableDictionary aliasMap, string assemblyName) { // For simplicity, we'll use top-level statements for the generated Main method. - StringBuilder builder = new(); - builder.AppendLine(string.Join("\n", aliasMap.Values.Where(alias => alias != "global").Select(alias => $"extern alias {alias};"))); + CodeBuilder builder = new(); + AppendAliasMap(builder, aliasMap); + builder.AppendLine("System.Collections.Generic.HashSet testExclusionList = XUnitWrapperLibrary.TestFilter.LoadTestExclusionList();"); + builder.AppendLine(); - builder.AppendLine("try {"); - builder.AppendLine($@"return await XHarnessRunnerLibrary.RunnerEntryPoint.RunTests(RunTests, ""{assemblyName}"", args.Length != 0 ? args[0] : null, testExclusionList);"); - builder.AppendLine("} catch(System.Exception ex) { System.Console.WriteLine(ex.ToString()); return 101; }"); + builder.AppendLine("try"); + using (builder.NewBracesScope()) + { + builder.AppendLine($@"return await XHarnessRunnerLibrary.RunnerEntryPoint.RunTests(RunTests, ""{assemblyName}"", args.Length != 0 ? args[0] : null, testExclusionList);"); + } + builder.AppendLine("catch(System.Exception ex)"); + using (builder.NewBracesScope()) + { + builder.AppendLine("System.Console.WriteLine(ex.ToString());"); + builder.AppendLine("return 101;"); + } + builder.AppendLine(); builder.AppendLine("static XUnitWrapperLibrary.TestSummary RunTests(XUnitWrapperLibrary.TestFilter filter)"); - builder.AppendLine("{"); - builder.AppendLine("XUnitWrapperLibrary.TestSummary summary = new();"); - builder.AppendLine("System.Diagnostics.Stopwatch stopwatch = new();"); - builder.AppendLine("XUnitWrapperLibrary.TestOutputRecorder outputRecorder = new(System.Console.Out);"); - builder.AppendLine("System.Console.SetOut(outputRecorder);"); - - builder.Append("\n"); - builder.AppendLine($@"if (System.IO.File.Exists(""{assemblyName}.tempLog.xml""))"); - builder.AppendLine($@"System.IO.File.Delete(""{assemblyName}.tempLog.xml"");"); - builder.AppendLine($@"if (System.IO.File.Exists(""{assemblyName}.testStats.csv""))"); - builder.AppendLine($@"System.IO.File.Delete(""{assemblyName}.testStats.csv"");"); - builder.Append("\n"); + using (builder.NewBracesScope()) + { + builder.AppendLine("XUnitWrapperLibrary.TestSummary summary = new();"); + builder.AppendLine("System.Diagnostics.Stopwatch stopwatch = new();"); + builder.AppendLine("XUnitWrapperLibrary.TestOutputRecorder outputRecorder = new(System.Console.Out);"); + builder.AppendLine("System.Console.SetOut(outputRecorder);"); + builder.AppendLine(); - ITestReporterWrapper reporter = new WrapperLibraryTestSummaryReporting("summary", "filter", "outputRecorder"); + builder.AppendLine($@"if (System.IO.File.Exists(""{assemblyName}.tempLog.xml""))"); + using (builder.NewBracesScope()) + { + builder.AppendLine($@"System.IO.File.Delete(""{assemblyName}.tempLog.xml"");"); + } + builder.AppendLine($@"if (System.IO.File.Exists(""{assemblyName}.testStats.csv""))"); + using (builder.NewBracesScope()) + { + builder.AppendLine($@"System.IO.File.Delete(""{assemblyName}.testStats.csv"");"); + } + builder.AppendLine(); - StringBuilder testExecutorBuilder = new(); - int testsLeftInCurrentTestExecutor = 0; - int currentTestExecutor = 0; + ITestReporterWrapper reporter = new WrapperLibraryTestSummaryReporting("summary", "filter", "outputRecorder"); - // Open the stream writer for the temp log. - builder.AppendLine($@"using (System.IO.StreamWriter tempLogSw = System.IO.File.AppendText(""{assemblyName}.templog.xml""))"); - builder.AppendLine($@"using (System.IO.StreamWriter statsCsvSw = System.IO.File.AppendText(""{assemblyName}.testStats.csv"")){{"); - builder.AppendLine($"statsCsvSw.WriteLine(\"{testInfos.Length},0,0,0\");"); + CodeBuilder testExecutorBuilder = new(); + int testsLeftInCurrentTestExecutor = 0; + int currentTestExecutor = 0; - if (testInfos.Length > 0) - { - // Break tests into groups of 50 so that we don't create an unreasonably large main method - // Excessively large methods are known to take a long time to compile, and use excessive stack - // leading to test failures. - foreach (ITestInfo test in testInfos) + // Open the stream writer for the temp log. + builder.AppendLine($@"using (System.IO.StreamWriter tempLogSw = System.IO.File.AppendText(""{assemblyName}.templog.xml""))"); + builder.AppendLine($@"using (System.IO.StreamWriter statsCsvSw = System.IO.File.AppendText(""{assemblyName}.testStats.csv""))"); + using (builder.NewBracesScope()) { - if (testsLeftInCurrentTestExecutor == 0) + builder.AppendLine($"statsCsvSw.WriteLine(\"{testInfos.Length},0,0,0\");"); + + if (testInfos.Length > 0) { - if (currentTestExecutor != 0) - testExecutorBuilder.AppendLine("}"); - - currentTestExecutor++; - testExecutorBuilder.AppendLine($"static void TestExecutor{currentTestExecutor}(" - + "XUnitWrapperLibrary.TestSummary summary, " - + "XUnitWrapperLibrary.TestFilter filter, " - + "XUnitWrapperLibrary.TestOutputRecorder outputRecorder, " - + "System.Diagnostics.Stopwatch stopwatch, " - + "System.IO.StreamWriter tempLogSw, " - + "System.IO.StreamWriter statsCsvSw){"); - - builder.AppendLine($"TestExecutor{currentTestExecutor}(summary, filter, outputRecorder, stopwatch, tempLogSw, statsCsvSw);"); - testsLeftInCurrentTestExecutor = 50; // Break test executors into groups of 50, which empirically seems to work well - } + // Break tests into groups of 50 so that we don't create an unreasonably large main method + // Excessively large methods are known to take a long time to compile, and use excessive stack + // leading to test failures. + foreach (ITestInfo test in testInfos) + { + if (testsLeftInCurrentTestExecutor == 0) + { + if (currentTestExecutor != 0) + { + testExecutorBuilder.PopIndent(); + testExecutorBuilder.AppendLine("}"); + testExecutorBuilder.AppendLine(); + } + + currentTestExecutor++; + testExecutorBuilder.AppendLine($"static void TestExecutor{currentTestExecutor}(" + + "XUnitWrapperLibrary.TestSummary summary, " + + "XUnitWrapperLibrary.TestFilter filter, " + + "XUnitWrapperLibrary.TestOutputRecorder outputRecorder, " + + "System.Diagnostics.Stopwatch stopwatch, " + + "System.IO.StreamWriter tempLogSw, " + + "System.IO.StreamWriter statsCsvSw)"); + testExecutorBuilder.AppendLine("{"); + testExecutorBuilder.PushIndent(); + + builder.AppendLine($"TestExecutor{currentTestExecutor}(summary, filter, outputRecorder, stopwatch, tempLogSw, statsCsvSw);"); + testsLeftInCurrentTestExecutor = 50; // Break test executors into groups of 50, which empirically seems to work well + } + else + { + testExecutorBuilder.AppendLine(); + } - testExecutorBuilder.AppendLine(test.GenerateTestExecution(reporter)); - testsLeftInCurrentTestExecutor--; + testExecutorBuilder.Append(test.GenerateTestExecution(reporter)); + testsLeftInCurrentTestExecutor--; + } + + testExecutorBuilder.PopIndent(); + testExecutorBuilder.AppendLine("}"); + testExecutorBuilder.AppendLine(); + } } + builder.AppendLine("return summary;"); - testExecutorBuilder.AppendLine("}"); - builder.AppendLine("}"); + builder.Append(testExecutorBuilder); } - builder.AppendLine("return summary;"); - builder.AppendLine("}"); - - builder.Append(testExecutorBuilder); - - return builder.ToString(); + return builder.GetCode(); } private static string GenerateStandaloneSimpleTestRunner(ImmutableArray testInfos, ImmutableDictionary aliasMap, string consoleType) { - // For simplicity, we'll use top-level statements for the generated Main method. ITestReporterWrapper reporter = new NoTestReporting(); - StringBuilder builder = new(); - builder.AppendLine(string.Join("\n", aliasMap.Values.Where(alias => alias != "global").Select(alias => $"extern alias {alias};"))); - builder.AppendLine("namespace __GeneratedMainWrapper;"); - builder.AppendLine("class __GeneratedMainWrapper {"); - builder.AppendLine("public static int Main() {"); - builder.AppendLine("try {"); - builder.AppendLine(string.Join("\n", testInfos.Select(m => m.GenerateTestExecution(reporter)))); - builder.AppendLine("} catch(System.Exception ex) { System.Console.WriteLine(ex.ToString()); return 101; }"); - builder.AppendLine("return 100;"); - builder.AppendLine("}"); - builder.AppendLine("}"); - return builder.ToString(); + CodeBuilder builder = new(); + AppendAliasMap(builder, aliasMap); + builder.AppendLine("class __GeneratedMainWrapper"); + using (builder.NewBracesScope()) + { + builder.AppendLine("public static int Main()"); + using (builder.NewBracesScope()) + { + builder.AppendLine("try"); + using (builder.NewBracesScope()) + { + foreach (ITestInfo testInfo in testInfos) + { + builder.Append(testInfo.GenerateTestExecution(reporter)); + } + } + builder.AppendLine("catch(System.Exception ex)"); + using (builder.NewBracesScope()) + { + builder.AppendLine("System.Console.WriteLine(ex.ToString());"); + builder.AppendLine("return 101;"); + } + builder.AppendLine("return 100;"); + } + } + return builder.GetCode(); } private class ExternallyReferencedTestMethodsVisitor : SymbolVisitor> diff --git a/src/tests/Directory.Build.targets b/src/tests/Directory.Build.targets index e26e9f6388215..81b4fc841a8c8 100644 --- a/src/tests/Directory.Build.targets +++ b/src/tests/Directory.Build.targets @@ -13,9 +13,11 @@ true Exe + BuildAndRun BuildOnly 0 + $(NoWarn);CS2008 diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Aes/Aes_r.csproj b/src/tests/JIT/HardwareIntrinsics/Arm/Aes/Aes.Arm_r.csproj similarity index 100% rename from src/tests/JIT/HardwareIntrinsics/Arm/Aes/Aes_r.csproj rename to src/tests/JIT/HardwareIntrinsics/Arm/Aes/Aes.Arm_r.csproj diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Aes/Aes_ro.csproj b/src/tests/JIT/HardwareIntrinsics/Arm/Aes/Aes.Arm_ro.csproj similarity index 100% rename from src/tests/JIT/HardwareIntrinsics/Arm/Aes/Aes_ro.csproj rename to src/tests/JIT/HardwareIntrinsics/Arm/Aes/Aes.Arm_ro.csproj diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Crc32/Crc32_r.csproj b/src/tests/JIT/HardwareIntrinsics/Arm/Crc32/Crc32.Arm_r.csproj similarity index 100% rename from src/tests/JIT/HardwareIntrinsics/Arm/Crc32/Crc32_r.csproj rename to src/tests/JIT/HardwareIntrinsics/Arm/Crc32/Crc32.Arm_r.csproj diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Crc32/Crc32_ro.csproj b/src/tests/JIT/HardwareIntrinsics/Arm/Crc32/Crc32.Arm_ro.csproj similarity index 100% rename from src/tests/JIT/HardwareIntrinsics/Arm/Crc32/Crc32_ro.csproj rename to src/tests/JIT/HardwareIntrinsics/Arm/Crc32/Crc32.Arm_ro.csproj diff --git a/src/tests/JIT/HardwareIntrinsics/HardwareIntrinsics_r.csproj b/src/tests/JIT/HardwareIntrinsics/HardwareIntrinsics_r.csproj index d81af3a381450..696c3d04a6dd1 100644 --- a/src/tests/JIT/HardwareIntrinsics/HardwareIntrinsics_r.csproj +++ b/src/tests/JIT/HardwareIntrinsics/HardwareIntrinsics_r.csproj @@ -1,6 +1,5 @@ - true 20 true true @@ -26,6 +25,7 @@ - + + diff --git a/src/tests/JIT/HardwareIntrinsics/HardwareIntrinsics_ro.csproj b/src/tests/JIT/HardwareIntrinsics/HardwareIntrinsics_ro.csproj index cec6dbb86c481..e9fd5bcfd4999 100644 --- a/src/tests/JIT/HardwareIntrinsics/HardwareIntrinsics_ro.csproj +++ b/src/tests/JIT/HardwareIntrinsics/HardwareIntrinsics_ro.csproj @@ -1,6 +1,5 @@ - true 20 true true @@ -26,7 +25,7 @@ - - + + diff --git a/src/tests/JIT/HardwareIntrinsics/X86/AvxVnni_Vector128/MultiplyWideningAndAdd_r.csproj b/src/tests/JIT/HardwareIntrinsics/X86/AvxVnni_Vector128/MultiplyWideningAndAdd_Vector128_r.csproj similarity index 100% rename from src/tests/JIT/HardwareIntrinsics/X86/AvxVnni_Vector128/MultiplyWideningAndAdd_r.csproj rename to src/tests/JIT/HardwareIntrinsics/X86/AvxVnni_Vector128/MultiplyWideningAndAdd_Vector128_r.csproj diff --git a/src/tests/JIT/HardwareIntrinsics/X86/AvxVnni_Vector128/MultiplyWideningAndAdd_ro.csproj b/src/tests/JIT/HardwareIntrinsics/X86/AvxVnni_Vector128/MultiplyWideningAndAdd_Vector128_ro.csproj similarity index 100% rename from src/tests/JIT/HardwareIntrinsics/X86/AvxVnni_Vector128/MultiplyWideningAndAdd_ro.csproj rename to src/tests/JIT/HardwareIntrinsics/X86/AvxVnni_Vector128/MultiplyWideningAndAdd_Vector128_ro.csproj diff --git a/src/tests/JIT/HardwareIntrinsics/X86/Sse42.X64/Crc32_r.csproj b/src/tests/JIT/HardwareIntrinsics/X86/Sse42.X64/Crc32.X64_r.csproj similarity index 100% rename from src/tests/JIT/HardwareIntrinsics/X86/Sse42.X64/Crc32_r.csproj rename to src/tests/JIT/HardwareIntrinsics/X86/Sse42.X64/Crc32.X64_r.csproj diff --git a/src/tests/JIT/HardwareIntrinsics/X86/Sse42.X64/Crc32_ro.csproj b/src/tests/JIT/HardwareIntrinsics/X86/Sse42.X64/Crc32.X64_ro.csproj similarity index 100% rename from src/tests/JIT/HardwareIntrinsics/X86/Sse42.X64/Crc32_ro.csproj rename to src/tests/JIT/HardwareIntrinsics/X86/Sse42.X64/Crc32.X64_ro.csproj diff --git a/src/tests/JIT/IL_Conformance/IL_Conformance.csproj b/src/tests/JIT/IL_Conformance/IL_Conformance.csproj index 5e641dbafb2cf..0f7b4f5ff8284 100644 --- a/src/tests/JIT/IL_Conformance/IL_Conformance.csproj +++ b/src/tests/JIT/IL_Conformance/IL_Conformance.csproj @@ -1,9 +1,7 @@ - - true - - + + \ No newline at end of file diff --git a/src/tests/JIT/Methodical/Methodical_d1.csproj b/src/tests/JIT/Methodical/Methodical_d1.csproj index 1b765ef609e58..0053845f32274 100644 --- a/src/tests/JIT/Methodical/Methodical_d1.csproj +++ b/src/tests/JIT/Methodical/Methodical_d1.csproj @@ -1,13 +1,11 @@ - - true - - + + diff --git a/src/tests/JIT/Methodical/Methodical_d2.csproj b/src/tests/JIT/Methodical/Methodical_d2.csproj index 0ec205658464f..4aca955892f50 100644 --- a/src/tests/JIT/Methodical/Methodical_d2.csproj +++ b/src/tests/JIT/Methodical/Methodical_d2.csproj @@ -1,7 +1,4 @@ - - true - @@ -9,6 +6,7 @@ - + + diff --git a/src/tests/JIT/Methodical/Methodical_do.csproj b/src/tests/JIT/Methodical/Methodical_do.csproj index 002f38b1e12da..96b0976b7ccf4 100644 --- a/src/tests/JIT/Methodical/Methodical_do.csproj +++ b/src/tests/JIT/Methodical/Methodical_do.csproj @@ -1,8 +1,7 @@ - - true - - + + + diff --git a/src/tests/JIT/Methodical/Methodical_others.csproj b/src/tests/JIT/Methodical/Methodical_others.csproj index 356c3d7587a73..4021ca8992282 100644 --- a/src/tests/JIT/Methodical/Methodical_others.csproj +++ b/src/tests/JIT/Methodical/Methodical_others.csproj @@ -1,12 +1,11 @@ - - true - - - - - - + + + + + + + diff --git a/src/tests/JIT/Methodical/Methodical_r1.csproj b/src/tests/JIT/Methodical/Methodical_r1.csproj index 532ce8b581839..1efc37e0cbb0d 100644 --- a/src/tests/JIT/Methodical/Methodical_r1.csproj +++ b/src/tests/JIT/Methodical/Methodical_r1.csproj @@ -1,13 +1,11 @@ - - true - - + + diff --git a/src/tests/JIT/Methodical/Methodical_r2.csproj b/src/tests/JIT/Methodical/Methodical_r2.csproj index 68f110ea6d64a..5e54baf3ed6d7 100644 --- a/src/tests/JIT/Methodical/Methodical_r2.csproj +++ b/src/tests/JIT/Methodical/Methodical_r2.csproj @@ -1,7 +1,4 @@ - - true - @@ -9,6 +6,7 @@ - + + diff --git a/src/tests/JIT/Methodical/Methodical_ro.csproj b/src/tests/JIT/Methodical/Methodical_ro.csproj index a75e209c30a3d..acf22626a849f 100644 --- a/src/tests/JIT/Methodical/Methodical_ro.csproj +++ b/src/tests/JIT/Methodical/Methodical_ro.csproj @@ -1,8 +1,7 @@ - - true - - + + + diff --git a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests0-99.csproj b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests0-99.csproj index 115b67e172e88..65bab37faa42f 100644 --- a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests0-99.csproj +++ b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests0-99.csproj @@ -1,11 +1,12 @@ 1 - true - - - + + + + + diff --git a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests100-199.csproj b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests100-199.csproj index 08f6a1a0c49cb..79c89194d7b2a 100644 --- a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests100-199.csproj +++ b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests100-199.csproj @@ -1,10 +1,11 @@  1 - true - - + + + + diff --git a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests1000-1099.csproj b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests1000-1099.csproj index bddda0d0c5b0f..da5a9726e4d05 100644 --- a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests1000-1099.csproj +++ b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests1000-1099.csproj @@ -1,10 +1,11 @@  1 - true - - + + + + diff --git a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests1100-1199.csproj b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests1100-1199.csproj index 365bcf7d49c1c..c523d3602f26a 100644 --- a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests1100-1199.csproj +++ b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests1100-1199.csproj @@ -1,10 +1,11 @@  1 - true - - + + + + diff --git a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests1200-1299.csproj b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests1200-1299.csproj index 2ad89135c72f0..83f8253f796a6 100644 --- a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests1200-1299.csproj +++ b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests1200-1299.csproj @@ -1,10 +1,11 @@  1 - true - - + + + + diff --git a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests1300-1399.csproj b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests1300-1399.csproj index 0f092654b623a..7ca5bfe0f8a02 100644 --- a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests1300-1399.csproj +++ b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests1300-1399.csproj @@ -1,10 +1,11 @@  1 - true - - + + + + diff --git a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests1400-1599.csproj b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests1400-1599.csproj index 74cb61ba6e05d..a1daf88b06bd9 100644 --- a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests1400-1599.csproj +++ b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests1400-1599.csproj @@ -1,11 +1,12 @@  1 - true - - - + + + + + diff --git a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests200-299.csproj b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests200-299.csproj index f1aeb00ddab3a..8a7a4d4d87679 100644 --- a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests200-299.csproj +++ b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests200-299.csproj @@ -1,10 +1,11 @@  1 - true - - + + + + diff --git a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests300-399.csproj b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests300-399.csproj index 74c158b597550..827c1df18e770 100644 --- a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests300-399.csproj +++ b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests300-399.csproj @@ -1,10 +1,11 @@ 1 - true - - + + + + diff --git a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests400-499.csproj b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests400-499.csproj index 6931acb1fa3c2..53c61d8e1196a 100644 --- a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests400-499.csproj +++ b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests400-499.csproj @@ -1,10 +1,11 @@  1 - true - - + + + + diff --git a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests500-599.csproj b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests500-599.csproj index b95348752dd44..b155247e7f38b 100644 --- a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests500-599.csproj +++ b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests500-599.csproj @@ -1,10 +1,11 @@  1 - true - - + + + + diff --git a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests600-699.csproj b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests600-699.csproj index 7efba2ca08d65..36e6d990c3b8c 100644 --- a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests600-699.csproj +++ b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests600-699.csproj @@ -1,10 +1,11 @@  1 - true - - + + + + diff --git a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests700-799.csproj b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests700-799.csproj index 2f82ed1c20e2f..3d0fe1cb38634 100644 --- a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests700-799.csproj +++ b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests700-799.csproj @@ -1,10 +1,11 @@  1 - true - - + + + + diff --git a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests800-899.csproj b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests800-899.csproj index 7ad7e17d7f7ac..c3f8528edcb4f 100644 --- a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests800-899.csproj +++ b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests800-899.csproj @@ -1,10 +1,11 @@  1 - true - - + + + + diff --git a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests900-999.csproj b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests900-999.csproj index 6e952ff28dd47..e049aba25c3a8 100644 --- a/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests900-999.csproj +++ b/src/tests/Loader/classloader/TypeGeneratorTests/TypeGeneratorTests900-999.csproj @@ -1,10 +1,11 @@  1 - true - - + + + + diff --git a/src/tests/MergedTestRunner.targets b/src/tests/MergedTestRunner.targets new file mode 100644 index 0000000000000..258b711537d2b --- /dev/null +++ b/src/tests/MergedTestRunner.targets @@ -0,0 +1,21 @@ + + + + + true + true + + + + + + + + + \ No newline at end of file diff --git a/src/tests/baseservices/threading/threading_group1.csproj b/src/tests/baseservices/threading/threading_group1.csproj index a099f2d9e87c5..15e01f3e3ae1c 100644 --- a/src/tests/baseservices/threading/threading_group1.csproj +++ b/src/tests/baseservices/threading/threading_group1.csproj @@ -1,7 +1,4 @@ - - true - @@ -10,7 +7,7 @@ - - + + \ No newline at end of file diff --git a/src/tests/baseservices/threading/threading_group2.csproj b/src/tests/baseservices/threading/threading_group2.csproj index bb5468800359d..bec4e631db702 100644 --- a/src/tests/baseservices/threading/threading_group2.csproj +++ b/src/tests/baseservices/threading/threading_group2.csproj @@ -1,7 +1,4 @@ - - true - @@ -11,7 +8,7 @@ - - + + \ No newline at end of file