Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
9 changes: 9 additions & 0 deletions src/tests/Common/XUnitWrapperGenerator/Descriptors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,13 @@ public static class Descriptors
"XUnitWrapperGenerator",
DiagnosticSeverity.Warning,
isEnabledByDefault: true);

public static readonly DiagnosticDescriptor XUWG1002 =
new DiagnosticDescriptor(
"XUW1002",
"Tests should not unconditionally return 100",
"Tests should not unconditionally return 100. Convert to a void return.",
"XUnitWrapperGenerator",
DiagnosticSeverity.Warning,
isEnabledByDefault: true);
}
53 changes: 53 additions & 0 deletions src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,53 @@ public void Initialize(IncrementalGeneratorInitializationContext context)

var allTests = testsInSource.Collect().Combine(testsInReferencedAssemblies.Collect()).Combine(outOfProcessTests.Collect()).SelectMany((tests, ct) => tests.Left.Left.AddRange(tests.Left.Right).AddRange(tests.Right));

context.RegisterImplementationSourceOutput(
methodsInSource
.Combine(context.AnalyzerConfigOptionsProvider)
.Where(data =>
{
var (_, configOptions) = data;
return configOptions.GlobalOptions.InMergedTestDirectory();
}),
static (context, data) =>
{
var (method, _) = data;

// Only check test methods
bool found = false;
foreach (var attr in method.GetAttributesOnSelfAndContainingSymbols())
{
switch (attr.AttributeClass?.ToDisplayString())
{
case "Xunit.ConditionalFactAttribute":
case "Xunit.FactAttribute":
case "Xunit.ConditionalTheoryAttribute":
case "Xunit.TheoryAttribute":
found = true;
break;
}
}
if (!found) return;

// Find methods where all returns are the literal 100 (and there is at least one return)
if (method.DeclaringSyntaxReferences.IsEmpty) return;

found = false;
foreach (SyntaxReference node in method.DeclaringSyntaxReferences.Where(n => n != null))
{
foreach (ReturnStatementSyntax rs in node.GetSyntax(context.CancellationToken).DescendantNodes().OfType<ReturnStatementSyntax>())
{
if (rs.Expression == null) continue;
found = true;
if (rs.Expression is LiteralExpressionSyntax les && les.Token.Value is int i && i == 100) continue;
return;
}
}

if (!found) return;
Comment on lines +153 to +164
Copy link
Member

Choose a reason for hiding this comment

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

For a future PR, I think it's worthwhile moving these checks into a separate analyzer instead of doing them as part of the source generator. If we do them in an analyzer, we can get better performance at build time and we could use better tools (like the IOperation APIs) to validate these sorts of scenarios.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I like this idea but mainly did it this way because I'm unfamiliar with all of this and couldn't easily figure out how to set anything up (primarily copying and pasting in this file). So I'll either need a template for doing so or more time to turn the docs/bing chat into something real.

context.ReportDiagnostic(Diagnostic.Create(Descriptors.XUWG1002, method.Locations[0]));
});

context.RegisterImplementationSourceOutput(
allTests
.Combine(context.AnalyzerConfigOptionsProvider)
Expand Down Expand Up @@ -845,6 +892,12 @@ private static ImmutableArray<ITestInfo> CreateTestCases(IMethodSymbol method, L
case "Xunit.InlineDataAttribute":
{
var args = attr.ConstructorArguments[0].Values;
if (args == null)
{
// This can happen with something like InlineData(default(MyStruct)).
// csc will already report an error, but we should not crash.
continue;
}
if (method.Parameters.Length != args.Length)
{
// Emit diagnostic
Expand Down
15 changes: 2 additions & 13 deletions src/tests/JIT/CodeGenBringUpTests/Call1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,10 @@
using Xunit;
public class BringUpTest_Call1
{
const int Pass = 100;
const int Fail = -1;

[MethodImplAttribute(MethodImplOptions.NoInlining)]
internal static void M() { Console.WriteLine("Hello"); }
internal static void M() { Console.WriteLine("Hello"); }
[MethodImplAttribute(MethodImplOptions.NoInlining)]
internal static void Call1()
{
M();
}
[Fact]
public static int TestEntryPoint()
{
Call1();
return 100;
}
public static void Call1() => M();
}

Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ namespace Test
public static class App
{
[Fact]
public static int TestEntryPoint()
public static void TestEntryPoint()
{
new DerivedClass<int>(3);
new DerivedClass<int>(8);
return 100;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ namespace Test
public static class App
{
[Fact]
public static int TestEntryPoint()
public static void TestEntryPoint()
{
new DerivedClass<int>("NotNull");
new DerivedClass<int>(null);
return 100;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ namespace Test
public static class App
{
[Fact]
public static int TestEntryPoint()
public static void TestEntryPoint()
{
new DerivedClass<int>(7);
return 100;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ namespace Test
public static class App
{
[Fact]
public static int TestEntryPoint()
public static void TestEntryPoint()
{
new DerivedClass<int>(7);
return 100;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ namespace Test
public static class App
{
[Fact]
public static int TestEntryPoint()
public static void TestEntryPoint()
{
new DerivedClass<Reftype>();
new DerivedClass<Valuetype>();
return 100;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ namespace Test
public static class App
{
[Fact]
public static int TestEntryPoint()
public static void TestEntryPoint()
{
new DerivedClass<int>(3);
new DerivedClass<int>(8);
return 100;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ namespace Test
public static class App
{
[Fact]
public static int TestEntryPoint()
public static void TestEntryPoint()
{
new DerivedClass<int>("NotNull");
new DerivedClass<int>(null);
return 100;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ namespace Test
public static class App
{
[Fact]
public static int TestEntryPoint()
public static void TestEntryPoint()
{
new DerivedClass<int>(7);
return 100;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ namespace Test
public static class App
{
[Fact]
public static int TestEntryPoint()
public static void TestEntryPoint()
{
new DerivedClass<int>(7);
return 100;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ namespace Test
public static class App
{
[Fact]
public static int TestEntryPoint()
public static void TestEntryPoint()
{
new DerivedClass<Reftype>();
new DerivedClass<Valuetype>();
return 100;
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/tests/JIT/Directed/CheckedCtor/Test_CSharp_Base_1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ namespace Test
public static class App
{
[Fact]
public static int TestEntryPoint()
public static void TestEntryPoint()
{
new DerivedClass(3);
new DerivedClass(8);
return 100;
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/tests/JIT/Directed/CheckedCtor/Test_CSharp_Base_2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ namespace Test
public static class App
{
[Fact]
public static int TestEntryPoint()
public static void TestEntryPoint()
{
new DerivedClass("NotNull");
new DerivedClass(null);
return 100;
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/tests/JIT/Directed/CheckedCtor/Test_CSharp_Base_3.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ namespace Test
public static class App
{
[Fact]
public static int TestEntryPoint()
public static void TestEntryPoint()
{
new DerivedClass(7);
return 100;
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/tests/JIT/Directed/CheckedCtor/Test_CSharp_Base_4.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ namespace Test
public static class App
{
[Fact]
public static int TestEntryPoint()
public static void TestEntryPoint()
{
new DerivedClass(7);
return 100;
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/tests/JIT/Directed/CheckedCtor/Test_CSharp_Peer_1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ namespace Test
public static class App
{
[Fact]
public static int TestEntryPoint()
public static void TestEntryPoint()
{
new DerivedClass(3);
new DerivedClass(8);
return 100;
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/tests/JIT/Directed/CheckedCtor/Test_CSharp_Peer_2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ namespace Test
public static class App
{
[Fact]
public static int TestEntryPoint()
public static void TestEntryPoint()
{
new DerivedClass("NotNull");
new DerivedClass(null);
return 100;
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/tests/JIT/Directed/CheckedCtor/Test_CSharp_Peer_3.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ namespace Test
public static class App
{
[Fact]
public static int TestEntryPoint()
public static void TestEntryPoint()
{
new DerivedClass(7);
return 100;
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/tests/JIT/Directed/CheckedCtor/Test_CSharp_Peer_4.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ namespace Test
public static class App
{
[Fact]
public static int TestEntryPoint()
public static void TestEntryPoint()
{
new DerivedClass(7);
return 100;
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/tests/JIT/Directed/LoopAlignment/LoopsToProcess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,8 @@ internal void Method0()
}
}
[Fact]
public static int TestEntryPoint()
public static void TestEntryPoint()
{
new TestClass_Loops().Method0();
return 100;
}
}
16 changes: 6 additions & 10 deletions src/tests/JIT/Directed/StructABI/StructWithOverlappingFields.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ public FourByteStruct(int val)

public class Program
{
static void TestClass(int initVal)
[Theory]
[InlineData(2)]
public static void TestClass(int initVal)
{
FourByteClass fb = new FourByteClass(initVal);
fb.fval = 0;
Expand All @@ -93,7 +95,9 @@ static void TestClass(int initVal)
Debug.Assert(cse_val_2 == 52);
}

static void TestStruct(int initVal)
[Theory]
[InlineData(2)]
public static void TestStruct(int initVal)
{
FourByteStruct fb = new FourByteStruct(initVal);
fb.fval = 0;
Expand All @@ -118,13 +122,5 @@ static void TestStruct(int initVal)
Debug.Assert(cse_uval_2 == 7);
Debug.Assert(cse_val_2 == 52);
}

[Fact]
public static int TestEntryPoint()
{
TestClass(2);
TestStruct(2);
return 100;
}
}
}
3 changes: 1 addition & 2 deletions src/tests/JIT/Directed/StructABI/structreturn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1813,13 +1813,12 @@ public static void Test()
public class TestStructs
{
[Fact]
public static int TestEntryPoint()
public static void TestEntryPoint()
{
TestStructReturns.Test();
TestUnsafeCasts.Test();
TestMergeReturnBlocks.Test();
TestHFAandHVA.Test();
TestNon2PowerStructs.Test();
return 100;
}
}
Loading