From baba1b4f4c262633b3f88d5d97e836fecdaadc0e Mon Sep 17 00:00:00 2001 From: Mark Plesko Date: Mon, 24 Jul 2023 18:52:16 -0700 Subject: [PATCH 01/20] First attempt at first rules --- .../XUnitWrapperGenerator/RoslynUtils.cs | 36 +++++++++++ .../XUnitWrapperGenerator.cs | 60 ++++++++++++++++--- src/tests/Directory.Build.targets | 2 +- 3 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 src/tests/Common/XUnitWrapperGenerator/RoslynUtils.cs diff --git a/src/tests/Common/XUnitWrapperGenerator/RoslynUtils.cs b/src/tests/Common/XUnitWrapperGenerator/RoslynUtils.cs new file mode 100644 index 0000000000000..4ba11ea443561 --- /dev/null +++ b/src/tests/Common/XUnitWrapperGenerator/RoslynUtils.cs @@ -0,0 +1,36 @@ +// 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 helper 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. + /// + 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 cb2ae27260a07..8e63f4116c2b6 100644 --- a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs +++ b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs @@ -5,6 +5,7 @@ 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 @@ 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 void Initialize(IncrementalGeneratorInitializationContext context) 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,13 +131,39 @@ public void Initialize(IncrementalGeneratorInitializationContext context) .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; + + foreach (IMethodSymbol entryPoint in compData.PossibleEntryPoints) + { + context.ReportDiagnostic(Diagnostic.Create( + new DiagnosticDescriptor( + "XUW1001", + "No explicit entry point", + "Projects in merged tests group should not contain entry points", + "XUnitWrapperGenerator", + DiagnosticSeverity.Error, + isEnabledByDefault: true), + entryPoint.Locations[0])); + } + + if (methods.IsEmpty && (compData.OutputKind != OutputKind.DynamicallyLinkedLibrary)) + { + context.ReportDiagnostic(Diagnostic.Create( + new DiagnosticDescriptor( + "XUW1002", + "Merged tests group projects should contain tests", + "Merged test group project does not contain any tests", + "XUnitWrapperGenerator", + DiagnosticSeverity.Warning, + isEnabledByDefault: true), + null)); + } - if (methods.Length == 0 && !alwaysWriteEntryPoint) + bool alwaysWriteEntryPoint = compData.OutputKind == OutputKind.ConsoleApplication && (compData.EntryPoint is null); + if (methods.IsEmpty && !alwaysWriteEntryPoint) { // 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. @@ -127,6 +172,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) bool isMergedTestRunnerAssembly = configOptions.GlobalOptions.IsMergedTestRunnerAssembly(); configOptions.GlobalOptions.TryGetValue("build_property.TargetOS", out string? targetOS); + string assemblyName = compData.AssemblyName; if (isMergedTestRunnerAssembly) { diff --git a/src/tests/Directory.Build.targets b/src/tests/Directory.Build.targets index fe922918c11ec..ff5d871ae3cd1 100644 --- a/src/tests/Directory.Build.targets +++ b/src/tests/Directory.Build.targets @@ -487,7 +487,7 @@ - + true From 0caf13df4a84a08712feec0208c0984ae25351bc Mon Sep 17 00:00:00 2001 From: Mark Plesko Date: Tue, 25 Jul 2023 16:39:04 -0700 Subject: [PATCH 02/20] Fix CLRTestExecutionArguments in CLRTest.Execute.Batch.targets, improve whitespace --- src/tests/Common/CLRTest.Execute.Batch.targets | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/tests/Common/CLRTest.Execute.Batch.targets b/src/tests/Common/CLRTest.Execute.Batch.targets index eeea1e3dea12c..90ba71856b72e 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 From 453e637d6f8dc17c7e1d6bf822b256423a2be00a Mon Sep 17 00:00:00 2001 From: Mark Plesko Date: Tue, 25 Jul 2023 16:39:43 -0700 Subject: [PATCH 03/20] XUWG: Display exceptions in stdout, factor a bit --- src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs | 10 +++------- .../XUnitWrapperGenerator/XUnitWrapperGenerator.cs | 4 ++-- src/tests/Common/XUnitWrapperLibrary/TestSummary.cs | 12 ++++++++++++ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs b/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs index 8b844be280cb8..4b0648ae5855d 100644 --- a/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs +++ b/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs @@ -415,22 +415,18 @@ public CodeBuilder WrapTestExecutionWithReporting(CodeBuilder testExecutionExpre 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/XUnitWrapperGenerator.cs b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs index 8e63f4116c2b6..c2e345acc7c56 100644 --- a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs +++ b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs @@ -358,7 +358,7 @@ private static string GenerateXHarnessTestRunner(ImmutableArray testI 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());"); @@ -481,7 +481,7 @@ private static string GenerateStandaloneSimpleTestRunner(ImmutableArray"); } + public void ReportStartingTest(string name, TextWriter outTw) + { + outTw.WriteLine("{0:HH:mm:ss.fff} Running test: {1}", System.DateTime.Now, name); + } + public void ReportPassedTest(string name, string containingTypeName, string methodName, TimeSpan duration, string output, + TextWriter outTw, StreamWriter tempLogSw, StreamWriter statsCsvSw) { @@ -133,8 +139,10 @@ public void ReportPassedTest(string name, 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 +153,7 @@ public void ReportFailedTest(string name, TimeSpan duration, Exception ex, string output, + TextWriter outTw, StreamWriter tempLogSw, StreamWriter statsCsvSw) { @@ -153,8 +162,11 @@ public void ReportFailedTest(string name, 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(); } From 8c7bc2776c3b84b070e9e722facebf0bf5f3fdd4 Mon Sep 17 00:00:00 2001 From: Mark Plesko Date: Tue, 25 Jul 2023 16:44:32 -0700 Subject: [PATCH 04/20] JIT/opt/Devirtualization/box2: Use Task.Run to de-async Main and then convert to [Fact] --- src/tests/JIT/opt/Devirtualization/box2.cs | 7 +++++-- src/tests/JIT/opt/Devirtualization/box2.csproj | 4 ---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/tests/JIT/opt/Devirtualization/box2.cs b/src/tests/JIT/opt/Devirtualization/box2.cs index 8837ee566c128..6505a0660e0fa 100644 --- a/src/tests/JIT/opt/Devirtualization/box2.cs +++ b/src/tests/JIT/opt/Devirtualization/box2.cs @@ -7,7 +7,7 @@ class Program { - static async Task Main() + static async Task TestTask() { for (int i = 0; i < 10; i++) { @@ -17,7 +17,10 @@ static async Task Main() // extra context argument. await new ValueTask(Task.Delay(1).ContinueWith(_ => default(string))).ConfigureAwait(false); } + } - return 100; + public static void TestEntryPoint() + { + Task.Run(TestTask); } } diff --git a/src/tests/JIT/opt/Devirtualization/box2.csproj b/src/tests/JIT/opt/Devirtualization/box2.csproj index 8d5913d6526a8..e86759e8715ea 100644 --- a/src/tests/JIT/opt/Devirtualization/box2.csproj +++ b/src/tests/JIT/opt/Devirtualization/box2.csproj @@ -1,8 +1,4 @@ - - - true - None True From e0f95281673919e9cb254eed91dd5f89866c30eb Mon Sep 17 00:00:00 2001 From: Mark Plesko Date: Tue, 25 Jul 2023 16:45:39 -0700 Subject: [PATCH 05/20] hfa_nested_f64_interop_cpp.csproj: No RequiresProcessIsolation on library --- .../JIT/jit64/hfa/main/dll/hfa_nested_f64_interop_cpp.csproj | 2 -- 1 file changed, 2 deletions(-) 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 d82380d9f192b..c470c81db6a69 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 From b2cbac0dad9fe5437a2f17ee4047af163be85784 Mon Sep 17 00:00:00 2001 From: Mark Plesko Date: Tue, 25 Jul 2023 16:48:16 -0700 Subject: [PATCH 06/20] Runtime_82535: Use Fact, remove tabs --- .../JitBlue/Runtime_82535/Runtime_82535.cs | 202 +++++++++--------- .../Runtime_82535/Runtime_82535.csproj | 3 +- 2 files changed, 101 insertions(+), 104 deletions(-) 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 110ea1d0d802b..88710befb89ff 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 23a7bac808073..1e568f64be7a2 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 From 11d7bd2e7423633226c7ab56a0d01c666fd97bd0 Mon Sep 17 00:00:00 2001 From: Mark Plesko Date: Tue, 25 Jul 2023 16:48:56 -0700 Subject: [PATCH 07/20] JIT/Methodical/delegate: Use Fact, leave exception for harness --- .../JIT/Methodical/delegate/GSDelegate.cs | 38 +++++++++---------- .../JIT/Methodical/delegate/GSDelegate.csproj | 6 +-- .../Methodical/delegate/VirtualDelegate.cs | 15 +++----- .../delegate/VirtualDelegate.csproj | 4 -- 4 files changed, 24 insertions(+), 39 deletions(-) diff --git a/src/tests/JIT/Methodical/delegate/GSDelegate.cs b/src/tests/JIT/Methodical/delegate/GSDelegate.cs index cbf80ad8848ac..ee68adb0fec01 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 96112c69f3c37..b47c3e8e8d9f5 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 5a28c6841ad14..f912580913d29 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 c8f15c2cc00c1..cddd1e53bad80 100644 --- a/src/tests/JIT/Methodical/delegate/VirtualDelegate.csproj +++ b/src/tests/JIT/Methodical/delegate/VirtualDelegate.csproj @@ -1,8 +1,4 @@ - - Exe - true - PdbOnly True From 305808cb54899ea1fddcf67f95b6b6619173e7a1 Mon Sep 17 00:00:00 2001 From: Mark Plesko Date: Tue, 25 Jul 2023 16:49:53 -0700 Subject: [PATCH 08/20] b08046cs: Remove Environment.ExitCode, improve logic --- .../V1.2-M01/b08046cs/SyncGCHole.cs | 46 +++++++++++-------- .../V1.2-M01/b08046cs/b08046cs.csproj | 2 - 2 files changed, 26 insertions(+), 22 deletions(-) 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 2e6d5ab49cf27..75ab9235f4944 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 @@ public 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 void runtest() { 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 0b13f790c43b0..a77f49fa23fd4 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 From c79f25e1e623122b2ca1b14b3114a406c1f2eb89 Mon Sep 17 00:00:00 2001 From: Mark Plesko Date: Tue, 25 Jul 2023 17:12:18 -0700 Subject: [PATCH 09/20] Runtime_75832: Use Assert.Throws --- .../JitBlue/Runtime_75832/Runtime_75832.cs | 25 +++---------------- 1 file changed, 3 insertions(+), 22 deletions(-) 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 edfcc9f177f3c..1e7dd41e87946 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 @@ 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; From 0d5f37f78fe2e0cbc29573c0c952b5e6dc04fcf0 Mon Sep 17 00:00:00 2001 From: Mark Plesko Date: Tue, 25 Jul 2023 18:07:24 -0700 Subject: [PATCH 10/20] Factor XUWG --- .../XUnitWrapperGenerator.cs | 102 ++++++++++-------- 1 file changed, 58 insertions(+), 44 deletions(-) diff --git a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs index c2e345acc7c56..6e834929014b2 100644 --- a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs +++ b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs @@ -136,31 +136,8 @@ public void Initialize(IncrementalGeneratorInitializationContext context) { var (((methods, configOptions), aliasMap), compData) = data; - foreach (IMethodSymbol entryPoint in compData.PossibleEntryPoints) - { - context.ReportDiagnostic(Diagnostic.Create( - new DiagnosticDescriptor( - "XUW1001", - "No explicit entry point", - "Projects in merged tests group should not contain entry points", - "XUnitWrapperGenerator", - DiagnosticSeverity.Error, - isEnabledByDefault: true), - entryPoint.Locations[0])); - } - - if (methods.IsEmpty && (compData.OutputKind != OutputKind.DynamicallyLinkedLibrary)) - { - context.ReportDiagnostic(Diagnostic.Create( - new DiagnosticDescriptor( - "XUW1002", - "Merged tests group projects should contain tests", - "Merged test group project does not contain any tests", - "XUnitWrapperGenerator", - DiagnosticSeverity.Warning, - isEnabledByDefault: true), - null)); - } + CheckNoEntryPoint(context, compData); + CheckTestsExist(context, methods, compData); bool alwaysWriteEntryPoint = compData.OutputKind == OutputKind.ConsoleApplication && (compData.EntryPoint is null); if (methods.IsEmpty && !alwaysWriteEntryPoint) @@ -170,28 +147,65 @@ public void Initialize(IncrementalGeneratorInitializationContext context) return; } - 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)); - } + 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 CheckTestsExist(SourceProductionContext context, ImmutableArray methods, CompData compData) + { + if (methods.IsEmpty && (compData.OutputKind != OutputKind.DynamicallyLinkedLibrary)) + { + context.ReportDiagnostic(Diagnostic.Create( + new DiagnosticDescriptor( + "XUW1002", + "Merged tests group projects should contain tests", + "Merged test group project does not contain any tests", + "XUnitWrapperGenerator", + DiagnosticSeverity.Warning, + isEnabledByDefault: true), + null)); + } + } + + private static void CheckNoEntryPoint(SourceProductionContext context, CompData compData) + { + foreach (IMethodSymbol entryPoint in compData.PossibleEntryPoints) + { + context.ReportDiagnostic(Diagnostic.Create( + new DiagnosticDescriptor( + "XUW1001", + "No explicit entry point", + "Projects in merged tests group should not contain entry points", + "XUnitWrapperGenerator", + DiagnosticSeverity.Error, + isEnabledByDefault: true), + entryPoint.Locations[0])); + } + } + private static void AppendAliasMap(CodeBuilder builder, ImmutableDictionary aliasMap) { bool didOutput = false; From fa6db9c53e36ca59b6ac9201a407c4733822abe2 Mon Sep 17 00:00:00 2001 From: Mark Plesko Date: Wed, 26 Jul 2023 12:11:04 -0700 Subject: [PATCH 11/20] typos --- src/tests/Common/XUnitWrapperGenerator/RoslynUtils.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/tests/Common/XUnitWrapperGenerator/RoslynUtils.cs b/src/tests/Common/XUnitWrapperGenerator/RoslynUtils.cs index 4ba11ea443561..d87e2a9fea079 100644 --- a/src/tests/Common/XUnitWrapperGenerator/RoslynUtils.cs +++ b/src/tests/Common/XUnitWrapperGenerator/RoslynUtils.cs @@ -19,13 +19,14 @@ internal class RoslynUtils /// whether the current target is an executable. /// /// - /// Replacement for CSharpCompilation.GetEntryPoint() which only works for executables - /// Replacement for its helper that are internal. + /// 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. + /// 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 From 4df2ebf5cebbae6f09745a92d269422b885436f2 Mon Sep 17 00:00:00 2001 From: Mark Plesko Date: Wed, 26 Jul 2023 12:19:16 -0700 Subject: [PATCH 12/20] Make XUW1001 a warning --- src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs index 6e834929014b2..5394c5e2654a2 100644 --- a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs +++ b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs @@ -200,7 +200,7 @@ private static void CheckNoEntryPoint(SourceProductionContext context, CompData "No explicit entry point", "Projects in merged tests group should not contain entry points", "XUnitWrapperGenerator", - DiagnosticSeverity.Error, + DiagnosticSeverity.Warning, isEnabledByDefault: true), entryPoint.Locations[0])); } From 40753c89d254655be6ac8c85b7b4744de12786fe Mon Sep 17 00:00:00 2001 From: Mark Plesko Date: Wed, 26 Jul 2023 12:30:56 -0700 Subject: [PATCH 13/20] Fix box2.cs --- src/tests/JIT/opt/Devirtualization/box2.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/tests/JIT/opt/Devirtualization/box2.cs b/src/tests/JIT/opt/Devirtualization/box2.cs index 6505a0660e0fa..8bd94b1334979 100644 --- a/src/tests/JIT/opt/Devirtualization/box2.cs +++ b/src/tests/JIT/opt/Devirtualization/box2.cs @@ -4,6 +4,7 @@ using System; using System.Threading; using System.Threading.Tasks; +using Xunit; class Program { @@ -19,8 +20,6 @@ static async Task TestTask() } } - public static void TestEntryPoint() - { - Task.Run(TestTask); - } + [Fact] + public static void TestEntryPoint() => Task.Run(TestTask).Wait(); } From 3dd47f2657a349fc5a0f94953cae55f85c736d10 Mon Sep 17 00:00:00 2001 From: Mark Plesko Date: Thu, 27 Jul 2023 00:16:52 -0700 Subject: [PATCH 14/20] Reinstate RefXUWG disjuncts in D.B.t --- src/tests/Directory.Build.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/Directory.Build.targets b/src/tests/Directory.Build.targets index ff5d871ae3cd1..4f87ebf879c0a 100644 --- a/src/tests/Directory.Build.targets +++ b/src/tests/Directory.Build.targets @@ -487,7 +487,7 @@ - + true From 41a8dcc1de1aa1793ef4e1d423f518a109e716c8 Mon Sep 17 00:00:00 2001 From: Mark Plesko Date: Thu, 27 Jul 2023 00:30:45 -0700 Subject: [PATCH 15/20] Add flush for consistency --- src/tests/Common/XUnitWrapperLibrary/TestSummary.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tests/Common/XUnitWrapperLibrary/TestSummary.cs b/src/tests/Common/XUnitWrapperLibrary/TestSummary.cs index 8cab373d02d4d..adf4e1a0578ca 100644 --- a/src/tests/Common/XUnitWrapperLibrary/TestSummary.cs +++ b/src/tests/Common/XUnitWrapperLibrary/TestSummary.cs @@ -123,6 +123,7 @@ public void WriteFooterToTempLog(StreamWriter tempLogSw) 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, From 31e281fcd7978bc06777f1c5411ddd227de93f9b Mon Sep 17 00:00:00 2001 From: Mark Plesko Date: Thu, 27 Jul 2023 01:09:49 -0700 Subject: [PATCH 16/20] Limit new checks to merged test groups --- src/tests/Common/XUnitWrapperGenerator/OptionsHelper.cs | 3 +++ .../Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs | 8 ++++++-- .../XUnitWrapperGenerator/XUnitWrapperGenerator.props | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/tests/Common/XUnitWrapperGenerator/OptionsHelper.cs b/src/tests/Common/XUnitWrapperGenerator/OptionsHelper.cs index fa92071c917e8..9b9dd10b23569 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 @@ private static bool GetBoolOption(this AnalyzerConfigOptions options, string key ? 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/XUnitWrapperGenerator.cs b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs index 5394c5e2654a2..1de83cebfe016 100644 --- a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs +++ b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs @@ -136,8 +136,12 @@ public void Initialize(IncrementalGeneratorInitializationContext context) { var (((methods, configOptions), aliasMap), compData) = data; - CheckNoEntryPoint(context, compData); - CheckTestsExist(context, methods, compData); + bool inMergedTestDirectory = configOptions.GlobalOptions.InMergedTestDirectory(); + if (inMergedTestDirectory) + { + CheckNoEntryPoint(context, compData); + CheckTestsExist(context, methods, compData); + } bool alwaysWriteEntryPoint = compData.OutputKind == OutputKind.ConsoleApplication && (compData.EntryPoint is null); if (methods.IsEmpty && !alwaysWriteEntryPoint) diff --git a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.props b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.props index 651a40c62aba4..067c31f8d6b4d 100644 --- a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.props +++ b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.props @@ -6,6 +6,7 @@ + From b9eeedbb92156ea8c420259c875f39624d324b67 Mon Sep 17 00:00:00 2001 From: Mark Plesko Date: Thu, 27 Jul 2023 02:30:36 -0700 Subject: [PATCH 17/20] box2 - make class public --- src/tests/JIT/opt/Devirtualization/box2.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/JIT/opt/Devirtualization/box2.cs b/src/tests/JIT/opt/Devirtualization/box2.cs index 8bd94b1334979..91f9568386ce1 100644 --- a/src/tests/JIT/opt/Devirtualization/box2.cs +++ b/src/tests/JIT/opt/Devirtualization/box2.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; using Xunit; -class Program +public class Program { static async Task TestTask() { From 2b0269fc074435c683df312395a7199650fd80bc Mon Sep 17 00:00:00 2001 From: Mark Plesko Date: Thu, 27 Jul 2023 02:33:01 -0700 Subject: [PATCH 18/20] Remove check that any tests exist --- .../XUnitWrapperGenerator.cs | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs index 1de83cebfe016..e36a1f184bb3f 100644 --- a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs +++ b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs @@ -140,7 +140,6 @@ public void Initialize(IncrementalGeneratorInitializationContext context) if (inMergedTestDirectory) { CheckNoEntryPoint(context, compData); - CheckTestsExist(context, methods, compData); } bool alwaysWriteEntryPoint = compData.OutputKind == OutputKind.ConsoleApplication && (compData.EntryPoint is null); @@ -178,22 +177,6 @@ private static void AddRunnerSource(SourceProductionContext context, ImmutableAr } } - private static void CheckTestsExist(SourceProductionContext context, ImmutableArray methods, CompData compData) - { - if (methods.IsEmpty && (compData.OutputKind != OutputKind.DynamicallyLinkedLibrary)) - { - context.ReportDiagnostic(Diagnostic.Create( - new DiagnosticDescriptor( - "XUW1002", - "Merged tests group projects should contain tests", - "Merged test group project does not contain any tests", - "XUnitWrapperGenerator", - DiagnosticSeverity.Warning, - isEnabledByDefault: true), - null)); - } - } - private static void CheckNoEntryPoint(SourceProductionContext context, CompData compData) { foreach (IMethodSymbol entryPoint in compData.PossibleEntryPoints) From 985534ee93af719a074804e09a863685ffeff561 Mon Sep 17 00:00:00 2001 From: Mark Plesko Date: Thu, 27 Jul 2023 10:58:29 -0700 Subject: [PATCH 19/20] Revert "Reenable a test which doesn't seem to fail any more. (#85576)" Also fix test path and update issue link This reverts commit d75e8114d636d9d23ab0bf30b463662c274cb64f. --- src/tests/issues.targets | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 2533601ac77c1..dd511525fe500 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 + From 79691743737fc44fc56f498d7acd2f3287d394b3 Mon Sep 17 00:00:00 2001 From: Mark Plesko Date: Thu, 27 Jul 2023 16:46:55 -0700 Subject: [PATCH 20/20] static for Descriptor; only write entrypoints for apps --- .../XUnitWrapperGenerator/Descriptors.cs | 21 +++++++++++++++++++ .../XUnitWrapperGenerator.cs | 17 +++++++-------- 2 files changed, 28 insertions(+), 10 deletions(-) create mode 100644 src/tests/Common/XUnitWrapperGenerator/Descriptors.cs diff --git a/src/tests/Common/XUnitWrapperGenerator/Descriptors.cs b/src/tests/Common/XUnitWrapperGenerator/Descriptors.cs new file mode 100644 index 0000000000000..41105a8117f83 --- /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/XUnitWrapperGenerator.cs b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs index e36a1f184bb3f..ce0d9d9de1499 100644 --- a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs +++ b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs @@ -142,7 +142,12 @@ public void Initialize(IncrementalGeneratorInitializationContext context) CheckNoEntryPoint(context, compData); } - bool alwaysWriteEntryPoint = compData.OutputKind == OutputKind.ConsoleApplication && (compData.EntryPoint is null); + if (compData.OutputKind != OutputKind.ConsoleApplication) + { + return; + } + + bool alwaysWriteEntryPoint = (compData.EntryPoint is null); if (methods.IsEmpty && !alwaysWriteEntryPoint) { // If we have no test methods, assume that this project is not migrated to the new system yet @@ -181,15 +186,7 @@ private static void CheckNoEntryPoint(SourceProductionContext context, CompData { foreach (IMethodSymbol entryPoint in compData.PossibleEntryPoints) { - context.ReportDiagnostic(Diagnostic.Create( - new DiagnosticDescriptor( - "XUW1001", - "No explicit entry point", - "Projects in merged tests group should not contain entry points", - "XUnitWrapperGenerator", - DiagnosticSeverity.Warning, - isEnabledByDefault: true), - entryPoint.Locations[0])); + context.ReportDiagnostic(Diagnostic.Create(Descriptors.XUWG1001, entryPoint.Locations[0])); } }