From 6f27090e059de06b50516a6485576943876d6914 Mon Sep 17 00:00:00 2001 From: Mark Plesko Date: Fri, 28 Jul 2023 11:39:19 -0700 Subject: [PATCH] Add some checks for merged test groups (#89521) - CLRTest.Execute.Batch.targets - Fix CLRTestExecutionArguments (allows passing a filter argument to .cmd - Fix indenting in generated script - XUnitWrapperGenerator - Move some generated code into (shared) ITestInfo.cs - Also display exception on stdout on failure - Add check that projects in merged test groups don't contain entry points - Can be a sign of code that is expected to run but won't be - Or can be a [Fact]/etc-less entry point in a ReqProcIso project but would then need to be fixed if ReqProcIso were removed - Directory.Build.targets - Run XUnitWrapperGenerator on test projects in merged groups - Can't simply replace the conditional because we have XUnit-style tests outside of merged groups - Update tests to conform to above checks plus a bit of opportunistic cleanup --- src/tests/Common/CLRTest.Execute.Batch.targets | 16 +- .../Common/XUnitWrapperGenerator/Descriptors.cs | 21 +++ .../Common/XUnitWrapperGenerator/ITestInfo.cs | 10 +- .../Common/XUnitWrapperGenerator/OptionsHelper.cs | 3 + .../Common/XUnitWrapperGenerator/RoslynUtils.cs | 37 ++++ .../XUnitWrapperGenerator/XUnitWrapperGenerator.cs | 96 +++++++--- .../XUnitWrapperGenerator.props | 1 + .../Common/XUnitWrapperLibrary/TestSummary.cs | 13 ++ src/tests/Directory.Build.targets | 2 +- src/tests/JIT/Methodical/delegate/GSDelegate.cs | 38 ++-- .../JIT/Methodical/delegate/GSDelegate.csproj | 6 +- .../JIT/Methodical/delegate/VirtualDelegate.cs | 15 +- .../JIT/Methodical/delegate/VirtualDelegate.csproj | 4 - .../CLR-x86-JIT/V1.2-M01/b08046cs/SyncGCHole.cs | 46 +++-- .../CLR-x86-JIT/V1.2-M01/b08046cs/b08046cs.csproj | 2 - .../JitBlue/Runtime_75832/Runtime_75832.cs | 25 +-- .../JitBlue/Runtime_82535/Runtime_82535.cs | 202 ++++++++++----------- .../JitBlue/Runtime_82535/Runtime_82535.csproj | 3 +- .../hfa/main/dll/hfa_nested_f64_interop_cpp.csproj | 2 - src/tests/JIT/opt/Devirtualization/box2.cs | 10 +- src/tests/JIT/opt/Devirtualization/box2.csproj | 4 - src/tests/issues.targets | 3 + 22 files changed, 321 insertions(+), 238 deletions(-) create mode 100644 src/tests/Common/XUnitWrapperGenerator/Descriptors.cs create mode 100644 src/tests/Common/XUnitWrapperGenerator/RoslynUtils.cs diff --git a/src/tests/Common/CLRTest.Execute.Batch.targets b/src/tests/Common/CLRTest.Execute.Batch.targets index eeea1e3..90ba718 100644 --- a/src/tests/Common/CLRTest.Execute.Batch.targets +++ b/src/tests/Common/CLRTest.Execute.Batch.targets @@ -164,8 +164,8 @@ IF NOT "%CLRTestExitCode%"=="%CLRTestExpectedExitCode%" ( :TakeLock md %lockFolder% IF NOT "!ERRORLEVEL!"=="0" ( -timeout /t 10 /nobreak -goto :TakeLock + timeout /t 10 /nobreak + goto :TakeLock ) Exit /b 2 @@ -403,15 +403,17 @@ IF /I [%1] == [-%(Identity)] set cond=1 IF /I [%1] == [/%(Identity)] set cond=1 IF %cond% EQU 1 ( %(Command) -shift -IF /I [%(HasParam)] == [true] shift -goto NextArg + shift + IF /I [%(HasParam)] == [true] shift + goto NextArg )',' ') +:ExtraArgs if NOT "%1" == "" ( -set CLRTestExecutionArguments=%* -goto :ArgsDone + set CLRTestExecutionArguments=%CLRTestExecutionArguments% %1 + shift + goto :ExtraArgs ) goto ArgsDone diff --git a/src/tests/Common/XUnitWrapperGenerator/Descriptors.cs b/src/tests/Common/XUnitWrapperGenerator/Descriptors.cs new file mode 100644 index 0000000..41105a8 --- /dev/null +++ b/src/tests/Common/XUnitWrapperGenerator/Descriptors.cs @@ -0,0 +1,21 @@ +// 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.Text; +using Microsoft.CodeAnalysis; + +namespace XUnitWrapperGenerator; + +public static class Descriptors +{ + public static readonly DiagnosticDescriptor XUWG1001 = + new DiagnosticDescriptor( + "XUW1001", + "Projects in merged tests group should not have entry points", + "Projects in merged tests group should not have entry points. Convert to Facts or Theories.", + "XUnitWrapperGenerator", + DiagnosticSeverity.Warning, + isEnabledByDefault: true); +} diff --git a/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs b/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs index 8b844be..4b0648a 100644 --- a/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs +++ b/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs @@ -415,22 +415,18 @@ public sealed class WrapperLibraryTestSummaryReporting : ITestReporterWrapper 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($"{_summaryLocalIdentifier}.ReportStartingTest({test.TestNameExpression}, System.Console.Out);"); 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});"); + + $" stopwatch.Elapsed - testStart, {_outputRecorderIdentifier}.GetTestOutput(), System.Console.Out, tempLogSw, statsCsvSw);"); } 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});"); + + $" stopwatch.Elapsed - testStart, ex, {_outputRecorderIdentifier}.GetTestOutput(), System.Console.Out, tempLogSw, statsCsvSw);"); } } builder.AppendLine("else"); diff --git a/src/tests/Common/XUnitWrapperGenerator/OptionsHelper.cs b/src/tests/Common/XUnitWrapperGenerator/OptionsHelper.cs index fa92071..9b9dd10 100644 --- a/src/tests/Common/XUnitWrapperGenerator/OptionsHelper.cs +++ b/src/tests/Common/XUnitWrapperGenerator/OptionsHelper.cs @@ -6,6 +6,7 @@ namespace XUnitWrapperGenerator; public static class OptionsHelper { + private const string InMergedTestDirectoryOption = "build_property.InMergedTestDirectory"; private const string IsMergedTestRunnerAssemblyOption = "build_property.IsMergedTestRunnerAssembly"; private const string PriorityOption = "build_property.Priority"; private const string RuntimeFlavorOption = "build_property.RuntimeFlavor"; @@ -29,6 +30,8 @@ public static class OptionsHelper ? result : 0; } + internal static bool InMergedTestDirectory(this AnalyzerConfigOptions options) => options.GetBoolOption(InMergedTestDirectoryOption); + internal static bool IsMergedTestRunnerAssembly(this AnalyzerConfigOptions options) => options.GetBoolOption(IsMergedTestRunnerAssemblyOption); internal static int? Priority(this AnalyzerConfigOptions options) => options.GetIntOption(PriorityOption); diff --git a/src/tests/Common/XUnitWrapperGenerator/RoslynUtils.cs b/src/tests/Common/XUnitWrapperGenerator/RoslynUtils.cs new file mode 100644 index 0000000..d87e2a9 --- /dev/null +++ b/src/tests/Common/XUnitWrapperGenerator/RoslynUtils.cs @@ -0,0 +1,37 @@ +// 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.Linq; +using System.Text; +using System.Threading; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace XUnitWrapperGenerator +{ + internal class RoslynUtils + { + /// + /// Returns the Main method that would serve as the entry point of the assembly, ignoring + /// whether the current target is an executable. + /// + /// + /// Replacement for CSharpCompilation.GetEntryPoint() which only works for executables. + /// Replacement for its helpers that are internal. + /// + /// Intended for the analyzer that is trying to find Main methods that won't be called in + /// merged test groups. Ignores details such as SynthesizedSimpleProgramEntryPointSymbol. + /// Ignores top-level statements as (1) in exes, they will generate an error for conflicting + /// with the auto-generated main, and (2) in libs, they will generate an error for existing + /// at all. + /// + internal static IEnumerable GetPossibleEntryPoints(Compilation comp, CancellationToken cancellationToken) + => comp + .GetSymbolsWithName(WellKnownMemberNames.EntryPointMethodName, SymbolFilter.Member) + .OfType() + .Where(m => m.IsStatic && !m.IsAbstract && !m.IsVirtual); + } +} diff --git a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs index cb2ae27..ce0d9d9 100644 --- a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs +++ b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Text; @@ -15,6 +16,22 @@ using Microsoft.CodeAnalysis.Diagnostics; namespace XUnitWrapperGenerator; +internal struct CompData +{ + internal CompData(string assemblyName, IMethodSymbol? entryPoint, IEnumerable possibleEntryPoints, OutputKind outputKind) + { + AssemblyName = assemblyName; + EntryPoint = entryPoint; + PossibleEntryPoints = possibleEntryPoints; + OutputKind = outputKind; + } + + public string AssemblyName { get; private set; } + public IMethodSymbol? EntryPoint { get; private set; } + public IEnumerable PossibleEntryPoints { get; private set; } + public OutputKind OutputKind { get; private set; } +} + [Generator] public sealed class XUnitWrapperGenerator : IIncrementalGenerator { @@ -58,9 +75,11 @@ public sealed class XUnitWrapperGenerator : IIncrementalGenerator return aliasMap.ToImmutable(); }).WithComparer(new ImmutableDictionaryValueComparer(EqualityComparer.Default)); - var assemblyName = context.CompilationProvider.Select((comp, ct) => comp.Assembly.MetadataName); - - var alwaysWriteEntryPoint = context.CompilationProvider.Select((comp, ct) => comp.Options.OutputKind == OutputKind.ConsoleApplication && comp.GetEntryPoint(ct) is null); + var compData = context.CompilationProvider.Select((comp, ct) => new CompData( + assemblyName: comp.Assembly.MetadataName, + entryPoint: comp.GetEntryPoint(ct), + possibleEntryPoints: RoslynUtils.GetPossibleEntryPoints(comp, ct), + outputKind: comp.Options.OutputKind)); var testsInSource = methodsInSource @@ -112,40 +131,65 @@ public sealed class XUnitWrapperGenerator : IIncrementalGenerator .Collect() .Combine(context.AnalyzerConfigOptionsProvider) .Combine(aliasMap) - .Combine(assemblyName) - .Combine(alwaysWriteEntryPoint), + .Combine(compData), static (context, data) => { - var ((((methods, configOptions), aliasMap), assemblyName), alwaysWriteEntryPoint) = data; + var (((methods, configOptions), aliasMap), compData) = data; - if (methods.Length == 0 && !alwaysWriteEntryPoint) + bool inMergedTestDirectory = configOptions.GlobalOptions.InMergedTestDirectory(); + if (inMergedTestDirectory) { - // If we have no test methods, assume that this project is not migrated to the new system yet - // and that we shouldn't generate a no-op Main method. - return; + CheckNoEntryPoint(context, compData); } - bool isMergedTestRunnerAssembly = configOptions.GlobalOptions.IsMergedTestRunnerAssembly(); - configOptions.GlobalOptions.TryGetValue("build_property.TargetOS", out string? targetOS); - - if (isMergedTestRunnerAssembly) + if (compData.OutputKind != OutputKind.ConsoleApplication) { - if (targetOS?.ToLowerInvariant() is "ios" or "iossimulator" or "tvos" or "tvossimulator" or "maccatalyst" or "android" or "browser") - { - context.AddSource("XHarnessRunner.g.cs", GenerateXHarnessTestRunner(methods, aliasMap, assemblyName)); - } - else - { - context.AddSource("FullRunner.g.cs", GenerateFullTestRunner(methods, aliasMap, assemblyName)); - } + return; } - else + + bool alwaysWriteEntryPoint = (compData.EntryPoint is null); + if (methods.IsEmpty && !alwaysWriteEntryPoint) { - context.AddSource("SimpleRunner.g.cs", GenerateStandaloneSimpleTestRunner(methods, aliasMap)); + // If we have no test methods, assume that this project is not migrated to the new system yet + // and that we shouldn't generate a no-op Main method. + return; } + + AddRunnerSource(context, methods, configOptions, aliasMap, compData); }); } + private static void AddRunnerSource(SourceProductionContext context, ImmutableArray methods, AnalyzerConfigOptionsProvider configOptions, ImmutableDictionary aliasMap, CompData compData) + { + bool isMergedTestRunnerAssembly = configOptions.GlobalOptions.IsMergedTestRunnerAssembly(); + configOptions.GlobalOptions.TryGetValue("build_property.TargetOS", out string? targetOS); + string assemblyName = compData.AssemblyName; + + if (isMergedTestRunnerAssembly) + { + if (targetOS?.ToLowerInvariant() is "ios" or "iossimulator" or "tvos" or "tvossimulator" or "maccatalyst" or "android" or "browser") + { + context.AddSource("XHarnessRunner.g.cs", GenerateXHarnessTestRunner(methods, aliasMap, assemblyName)); + } + else + { + context.AddSource("FullRunner.g.cs", GenerateFullTestRunner(methods, aliasMap, assemblyName)); + } + } + else + { + context.AddSource("SimpleRunner.g.cs", GenerateStandaloneSimpleTestRunner(methods, aliasMap)); + } + } + + private static void CheckNoEntryPoint(SourceProductionContext context, CompData compData) + { + foreach (IMethodSymbol entryPoint in compData.PossibleEntryPoints) + { + context.ReportDiagnostic(Diagnostic.Create(Descriptors.XUWG1001, entryPoint.Locations[0])); + } + } + private static void AppendAliasMap(CodeBuilder builder, ImmutableDictionary aliasMap) { bool didOutput = false; @@ -312,7 +356,7 @@ public sealed class XUnitWrapperGenerator : IIncrementalGenerator builder.AppendLine("System.Collections.Generic.HashSet testExclusionList = XUnitWrapperLibrary.TestFilter.LoadTestExclusionList();"); builder.AppendLine($@"return await XHarnessRunnerLibrary.RunnerEntryPoint.RunTests(RunTests, ""{assemblyName}"", args.Length != 0 ? args[0] : null, testExclusionList);"); } - builder.AppendLine("catch(System.Exception ex)"); + builder.AppendLine("catch (System.Exception ex)"); using (builder.NewBracesScope()) { builder.AppendLine("System.Console.WriteLine(ex.ToString());"); @@ -435,7 +479,7 @@ public sealed class XUnitWrapperGenerator : IIncrementalGenerator builder.Append(testInfo.GenerateTestExecution(reporter)); } } - builder.AppendLine("catch(System.Exception ex)"); + builder.AppendLine("catch (System.Exception ex)"); using (builder.NewBracesScope()) { builder.AppendLine("System.Console.WriteLine(ex.ToString());"); diff --git a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.props b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.props index 651a40c..067c31f 100644 --- a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.props +++ b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.props @@ -6,6 +6,7 @@ + diff --git a/src/tests/Common/XUnitWrapperLibrary/TestSummary.cs b/src/tests/Common/XUnitWrapperLibrary/TestSummary.cs index 96636cc..adf4e1a 100644 --- a/src/tests/Common/XUnitWrapperLibrary/TestSummary.cs +++ b/src/tests/Common/XUnitWrapperLibrary/TestSummary.cs @@ -120,11 +120,18 @@ public class TestSummary tempLogSw.WriteLine(""); } + public void ReportStartingTest(string name, TextWriter outTw) + { + outTw.WriteLine("{0:HH:mm:ss.fff} Running test: {1}", System.DateTime.Now, name); + outTw.Flush(); + } + public void ReportPassedTest(string name, string containingTypeName, string methodName, TimeSpan duration, string output, + TextWriter outTw, StreamWriter tempLogSw, StreamWriter statsCsvSw) { @@ -133,8 +140,10 @@ public class TestSummary var result = new TestResult(name, containingTypeName, methodName, duration, null, null, output); _testResults.Add(result); + outTw.WriteLine($"{0:HH:mm:ss.fff} Passed test: {1}", System.DateTime.Now, name); statsCsvSw.WriteLine($"{TotalTests},{PassedTests},{FailedTests},{SkippedTests}"); tempLogSw.WriteLine(result.ToXmlString()); + outTw.Flush(); statsCsvSw.Flush(); tempLogSw.Flush(); } @@ -145,6 +154,7 @@ public class TestSummary TimeSpan duration, Exception ex, string output, + TextWriter outTw, StreamWriter tempLogSw, StreamWriter statsCsvSw) { @@ -153,8 +163,11 @@ public class TestSummary var result = new TestResult(name, containingTypeName, methodName, duration, ex, null, output); _testResults.Add(result); + outTw.WriteLine(ex); + outTw.WriteLine("{0:HH:mm:ss.fff} Failed test: {1}", System.DateTime.Now, name); statsCsvSw.WriteLine($"{TotalTests},{PassedTests},{FailedTests},{SkippedTests}"); tempLogSw.WriteLine(result.ToXmlString()); + outTw.Flush(); statsCsvSw.Flush(); tempLogSw.Flush(); } diff --git a/src/tests/Directory.Build.targets b/src/tests/Directory.Build.targets index c8b7799..7c0dbf9 100644 --- a/src/tests/Directory.Build.targets +++ b/src/tests/Directory.Build.targets @@ -510,7 +510,7 @@ - + true diff --git a/src/tests/JIT/Methodical/delegate/GSDelegate.cs b/src/tests/JIT/Methodical/delegate/GSDelegate.cs index cbf80ad..ee68adb 100644 --- a/src/tests/JIT/Methodical/delegate/GSDelegate.cs +++ b/src/tests/JIT/Methodical/delegate/GSDelegate.cs @@ -3,7 +3,7 @@ using System; using System.Reflection; - +using Xunit; public interface IGetContents { (string, int, T) GetContents(); @@ -23,30 +23,26 @@ public class Program { public delegate (string, int, T) MyDelegate(IGetContents arg); - public static int Main(string[] args) + [Fact] + public static int TestEntryPoint() { int retVal = 100; - try { - MyStruct myStruct = new MyStruct(); - myStruct.s = "test1"; - myStruct.a = 42; - myStruct.t = "test2"; - - MethodInfo mi = typeof(IGetContents).GetMethod("GetContents"); - MyDelegate func = (MyDelegate)mi.CreateDelegate(typeof(MyDelegate)); - - (string c1, int c2, string c3) = func(myStruct); - if (c1 != "test1") - retVal = 1; - if (c2 != 42) - retVal = 2; - if (c3 != "test2") - retVal = 3; - } catch (Exception e) { - Console.WriteLine(e); + MyStruct myStruct = new MyStruct(); + myStruct.s = "test1"; + myStruct.a = 42; + myStruct.t = "test2"; + + MethodInfo mi = typeof(IGetContents).GetMethod("GetContents"); + MyDelegate func = (MyDelegate)mi.CreateDelegate(typeof(MyDelegate)); + + (string c1, int c2, string c3) = func(myStruct); + if (c1 != "test1") retVal = 1; - } + if (c2 != 42) + retVal = 2; + if (c3 != "test2") + retVal = 3; return retVal; } diff --git a/src/tests/JIT/Methodical/delegate/GSDelegate.csproj b/src/tests/JIT/Methodical/delegate/GSDelegate.csproj index 96112c6..b47c3e8 100644 --- a/src/tests/JIT/Methodical/delegate/GSDelegate.csproj +++ b/src/tests/JIT/Methodical/delegate/GSDelegate.csproj @@ -1,13 +1,9 @@ - Exe - true - - PdbOnly True - + diff --git a/src/tests/JIT/Methodical/delegate/VirtualDelegate.cs b/src/tests/JIT/Methodical/delegate/VirtualDelegate.cs index 5a28c68..f912580 100644 --- a/src/tests/JIT/Methodical/delegate/VirtualDelegate.cs +++ b/src/tests/JIT/Methodical/delegate/VirtualDelegate.cs @@ -1,22 +1,19 @@ // 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.Runtime.InteropServices; +using Xunit; public class VirtualDelegate { - public static int Main () { + [Fact] + public static int TestEntryPoint() { int retVal = 100; - try { - var del = (Func)Delegate.CreateDelegate (typeof (Func), null, typeof (object).GetMethod ("ToString")); - if (del ("FOO") != "FOO") - retVal = 1; - } catch(Exception e) { - Console.WriteLine(e); + + var del = (Func)Delegate.CreateDelegate(typeof(Func), null, typeof(object).GetMethod ("ToString")); + if (del("FOO") != "FOO") retVal = 1; - } return retVal; diff --git a/src/tests/JIT/Methodical/delegate/VirtualDelegate.csproj b/src/tests/JIT/Methodical/delegate/VirtualDelegate.csproj index c8f15c2..cddd1e5 100644 --- a/src/tests/JIT/Methodical/delegate/VirtualDelegate.csproj +++ b/src/tests/JIT/Methodical/delegate/VirtualDelegate.csproj @@ -1,9 +1,5 @@ - Exe - true - - PdbOnly True diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M01/b08046cs/SyncGCHole.cs b/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M01/b08046cs/SyncGCHole.cs index 2e6d5ab..75ab923 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M01/b08046cs/SyncGCHole.cs +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M01/b08046cs/SyncGCHole.cs @@ -2,12 +2,18 @@ // src\tests\JIT\Regression\CLR-x86-JIT\V1.2-M01\b08046\SyncGCHole.il // // Changes: -// - Remove the [Fact] from Main because it eventually leads to -// "CS7022 The entry point of the program is global code; ignoring 'Main()' entry point." -// [Fact] will be added again as part of the test merging work. -// - Remove the Environment.Exit call at the end of Main. Exit doesn't wait +// - Rename Main to TestEntryPoint (standard change for merged test groups). +// - Remove the Environment.Exit call at the end of Main. Exit doesn't wait // for foreground threads to complete, so the test becomes a race that is // typically lost. +// - Write a local static instead of Environment.ExitCode for compatibility +// with merged test groups. +// - Don't allow a successful thread to overwrite the exit value of a failing +// one. Retain the writes for successes (to 'Ignored') to keep the shape of +// the code as similar to the original as possible. It is unclear what +// aspect of the code caused the original problem. +// - Don't bother catching the exception in the outer method as the test +// infrastructure will handle it. using System; using System.Runtime.CompilerServices; @@ -29,26 +35,26 @@ class ExternalClass public class ExternalException : Exception { - public static void Main() + public static int ExitCode { get; set; } + public static int Ignored { get; set; } + + [Fact] + public static int TestEntryPoint() { + ExitCode = 100; + ExternalException v1 = new ExternalException(); for (int v2 = 0; v2 < 10; v2++) { Thread v0 = new Thread(new ThreadStart(v1.runtest)); - - try - { - v0.Start(); - } - catch (Exception) - { - Console.WriteLine("Exception was caught in main"); - } + v0.Start(); } + + return ExitCode; } - public void runtest() + private void runtest() { int v0 = 0; @@ -86,22 +92,22 @@ public class ExternalException : Exception { lock(this) { - Console.WriteLine("TryCatch Test Passed"); - Environment.ExitCode = 100; + Console.WriteLine("TryCatch Thread Passed"); + ExternalException.Ignored = 100; } } else { lock(this) { - Console.WriteLine("TryCatch Test Failed"); + Console.WriteLine("TryCatch Thread Failed"); Console.WriteLine(0); - Environment.ExitCode = 1; + ExternalException.ExitCode = 1; } } } - public void recurse(int counter) + private void recurse(int counter) { char[] v0 = new char[100]; diff --git a/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M01/b08046cs/b08046cs.csproj b/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M01/b08046cs/b08046cs.csproj index 0b13f79..a77f49f 100644 --- a/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M01/b08046cs/b08046cs.csproj +++ b/src/tests/JIT/Regression/CLR-x86-JIT/V1.2-M01/b08046cs/b08046cs.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_75832/Runtime_75832.cs b/src/tests/JIT/Regression/JitBlue/Runtime_75832/Runtime_75832.cs index edfcc9f..1e7dd41 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_75832/Runtime_75832.cs +++ b/src/tests/JIT/Regression/JitBlue/Runtime_75832/Runtime_75832.cs @@ -8,30 +8,11 @@ using Xunit; public class Runtime_75832 { [Fact] - public static int TestEntryPoint() - { - try - { - Test(0); - Console.WriteLine("FAIL: No exception thrown"); - } - catch (DivideByZeroException) - { - return 100; - } - catch (Exception ex) - { - Console.WriteLine("FAIL: Caught {0}", ex.GetType().Name); - } - - return 101; - } + public static void TestEntryPoint() + => Assert.Throws(() => Test(0)); [MethodImpl(MethodImplOptions.NoInlining)] - private static void Test(int i) - { - GetAction()(100 / i); - } + private static void Test(int i) => GetAction()(100 / i); [MethodImpl(MethodImplOptions.NoInlining)] private static Action GetAction() => null; diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_82535/Runtime_82535.cs b/src/tests/JIT/Regression/JitBlue/Runtime_82535/Runtime_82535.cs index 110ea1d..88710be 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_82535/Runtime_82535.cs +++ b/src/tests/JIT/Regression/JitBlue/Runtime_82535/Runtime_82535.cs @@ -2,130 +2,128 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Runtime.CompilerServices; +using Xunit; public class Program { - public Program() - { - } - - static int Main(string[] args) - { + [Fact] + public static int TestEntryPoint() + { Foo currentFoo; - Bacon defaultBacon = new Bacon(-180, 180, true, false, 300f, 0.1f, 0.1f, "Foo", false); - currentFoo = new Foo(); + Bacon defaultBacon = new Bacon(-180, 180, true, false, 300f, 0.1f, 0.1f, "Foo", false); + currentFoo = new Foo(); try { currentFoo.GetBar().m_Bacon = defaultBacon; } catch (NullReferenceException) { return 100; } return 101; - } + } } public class Foo { - private Bar m_Bar; - public Bar GetBar() - { - return m_Bar; - } + private Bar m_Bar; + public Bar GetBar() + { + return m_Bar; + } } public class Bar { - public Bacon m_Bacon = new Bacon(-180, 180, true, false, 300f, 0.1f, 0.1f, "Foo", false); + public Bacon m_Bacon = new Bacon(-180, 180, true, false, 300f, 0.1f, 0.1f, "Foo", false); } public struct Bacon { - public float Value; - public enum FooEnum - { - One, - Two - }; - - public FooEnum m_FooEnum; - public float m_f1; - public float m_f2; - public float m_f3; - public string m_s1; - public float m_f8; - public bool m_bool1; - public float m_f4; - public float m_f5; - public bool m_bool2; - public FooBar m_FooBar; - - float m_f6; - float m_f7; - int m_i1; - - public bool bool3 { get; set; } - - public bool bool4 { get; set; } - - public interface IFooInterface - { - float GetFooValue(int foo); - } - - IFooInterface m_FooProvider; - int m_i2; - - public Bacon( - float minValue, float maxValue, bool wrap, bool rangeLocked, - float maxSpeed, float accelTime, float decelTime, - string name, bool invert) - { - m_f4 = minValue; - m_f5 = maxValue; - m_bool2 = wrap; - bool3 = rangeLocked; - - bool4 = false; - m_FooBar = new FooBar(false, 1, 2); - - m_FooEnum = FooEnum.One; - m_f1 = maxSpeed; - m_f2 = accelTime; - m_f3 = decelTime; - Value = (minValue + maxValue) / 2; - m_s1 = name; - m_f8 = 0; - m_bool1 = invert; - - m_f6 = 0f; - m_FooProvider = null; - m_i2 = 0; - m_f7 = 0; - m_i1 = 0; - } - - public struct FooBar - { - public bool m_FooBar_bool1; - public float m_FooBar_f1; - public float m_FooBar_f2; - - float m_FooBar_f3; - float m_FooBar_f4; - float m_FooBar_f5; - int m_FooBar_i1; - int m_FooBar_i2; - - public FooBar(bool b1, float f1, float f2) - { - m_FooBar_bool1 = b1; - m_FooBar_f1 = f1; - m_FooBar_f2 = f2; - m_FooBar_f4 = 0; - m_FooBar_f5 = 0; - m_FooBar_i1 = m_FooBar_i2 = -1; - m_FooBar_f3 = 0; - } - } + public float Value; + public enum FooEnum + { + One, + Two + }; + + public FooEnum m_FooEnum; + public float m_f1; + public float m_f2; + public float m_f3; + public string m_s1; + public float m_f8; + public bool m_bool1; + public float m_f4; + public float m_f5; + public bool m_bool2; + public FooBar m_FooBar; + + float m_f6; + float m_f7; + int m_i1; + + public bool bool3 { get; set; } + + public bool bool4 { get; set; } + + public interface IFooInterface + { + float GetFooValue(int foo); + } + + IFooInterface m_FooProvider; + int m_i2; + + public Bacon( + float minValue, float maxValue, bool wrap, bool rangeLocked, + float maxSpeed, float accelTime, float decelTime, + string name, bool invert) + { + m_f4 = minValue; + m_f5 = maxValue; + m_bool2 = wrap; + bool3 = rangeLocked; + + bool4 = false; + m_FooBar = new FooBar(false, 1, 2); + + m_FooEnum = FooEnum.One; + m_f1 = maxSpeed; + m_f2 = accelTime; + m_f3 = decelTime; + Value = (minValue + maxValue) / 2; + m_s1 = name; + m_f8 = 0; + m_bool1 = invert; + + m_f6 = 0f; + m_FooProvider = null; + m_i2 = 0; + m_f7 = 0; + m_i1 = 0; + } + + public struct FooBar + { + public bool m_FooBar_bool1; + public float m_FooBar_f1; + public float m_FooBar_f2; + + float m_FooBar_f3; + float m_FooBar_f4; + float m_FooBar_f5; + int m_FooBar_i1; + int m_FooBar_i2; + + public FooBar(bool b1, float f1, float f2) + { + m_FooBar_bool1 = b1; + m_FooBar_f1 = f1; + m_FooBar_f2 = f2; + m_FooBar_f4 = 0; + m_FooBar_f5 = 0; + m_FooBar_i1 = m_FooBar_i2 = -1; + m_FooBar_f3 = 0; + } + } } diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_82535/Runtime_82535.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_82535/Runtime_82535.csproj index 23a7bac..1e568f6 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_82535/Runtime_82535.csproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_82535/Runtime_82535.csproj @@ -1,6 +1,5 @@ - + - Library True diff --git a/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f64_interop_cpp.csproj b/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f64_interop_cpp.csproj index d82380d..c470c81 100644 --- a/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f64_interop_cpp.csproj +++ b/src/tests/JIT/jit64/hfa/main/dll/hfa_nested_f64_interop_cpp.csproj @@ -1,7 +1,5 @@ - - true Library BuildOnly false diff --git a/src/tests/JIT/opt/Devirtualization/box2.cs b/src/tests/JIT/opt/Devirtualization/box2.cs index 8837ee5..91f9568 100644 --- a/src/tests/JIT/opt/Devirtualization/box2.cs +++ b/src/tests/JIT/opt/Devirtualization/box2.cs @@ -4,10 +4,11 @@ using System; using System.Threading; using System.Threading.Tasks; +using Xunit; -class Program +public class Program { - static async Task Main() + static async Task TestTask() { for (int i = 0; i < 10; i++) { @@ -17,7 +18,8 @@ class Program // extra context argument. await new ValueTask(Task.Delay(1).ContinueWith(_ => default(string))).ConfigureAwait(false); } - - return 100; } + + [Fact] + public static void TestEntryPoint() => Task.Run(TestTask).Wait(); } diff --git a/src/tests/JIT/opt/Devirtualization/box2.csproj b/src/tests/JIT/opt/Devirtualization/box2.csproj index 8d5913d..e86759e 100644 --- a/src/tests/JIT/opt/Devirtualization/box2.csproj +++ b/src/tests/JIT/opt/Devirtualization/box2.csproj @@ -1,9 +1,5 @@ - - true - - None True diff --git a/src/tests/issues.targets b/src/tests/issues.targets index b1d9c5a..35c1a1c 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -69,6 +69,9 @@ https://github.com/dotnet/runtime/issues/78899 + + https://github.com/dotnet/runtime/issues/89585 + -- 2.7.4