diff options
author | Mateo Torres-Ruiz <mateoatr@users.noreply.github.com> | 2021-10-19 01:03:30 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-19 01:03:30 +0300 |
commit | 3418bcd1d864ce7f62d789c8961f9c2d750fb079 (patch) | |
tree | 611dbace8908c89ead7a59df7e8ad0a97501df8c /test | |
parent | ef00d382d9761e89938fbce31ca13fe3a5c0b839 (diff) |
Add COMAnalyzer (#2306)
* Add COM Analyzer
* Add IsComInterop
Run Interop tests
* PR feedback
* Rename variables in GetTestFilesByDirName
* Extend ProducedBy with enum values for each supported analyzer
* Lint
* PR feedback
* Return ProducedBy instead of list
Diffstat (limited to 'test')
5 files changed, 81 insertions, 10 deletions
diff --git a/test/ILLink.RoslynAnalyzer.Tests/LinkerTestCases.cs b/test/ILLink.RoslynAnalyzer.Tests/LinkerTestCases.cs index a52400284..37fca09bd 100644 --- a/test/ILLink.RoslynAnalyzer.Tests/LinkerTestCases.cs +++ b/test/ILLink.RoslynAnalyzer.Tests/LinkerTestCases.cs @@ -27,5 +27,12 @@ namespace ILLink.RoslynAnalyzer.Tests RunTest<RequiresUnreferencedCodeAnalyzer> (m, attrs, UseMSBuildProperties (MSBuildPropertyOptionNames.EnableTrimAnalyzer)); } + + [Theory] + [MemberData (nameof (TestCaseUtils.GetTestData), parameters: nameof (Interop))] + public void Interop (string testName, MethodDeclarationSyntax m, List<AttributeSyntax> attrs) + { + RunTest<COMAnalyzer> (m, attrs, UseMSBuildProperties (MSBuildPropertyOptionNames.EnableTrimAnalyzer)); + } } } diff --git a/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs b/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs index 7e5739cad..a1eaa9ecc 100644 --- a/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs +++ b/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs @@ -18,6 +18,8 @@ namespace ILLink.RoslynAnalyzer.Tests { public abstract class TestCaseUtils { + private static readonly string MonoLinkerTestsCases = "Mono.Linker.Tests.Cases"; + public static readonly ReferenceAssemblies Net6PreviewAssemblies = new ReferenceAssemblies ( "net6.0", @@ -86,12 +88,16 @@ namespace ILLink.RoslynAnalyzer.Tests var builder = ImmutableDictionary.CreateBuilder<string, List<string>> (); foreach (var file in GetTestFiles ()) { - var dirName = Path.GetFileName (Path.GetDirectoryName (file))!; - if (builder.TryGetValue (dirName, out var sources)) { + var directory = Path.GetDirectoryName (file); + while (Path.GetFileName (Path.GetDirectoryName (directory)) != MonoLinkerTestsCases) + directory = Path.GetDirectoryName (directory); + + var parentDirectory = Path.GetFileName (directory); + if (builder.TryGetValue (parentDirectory!, out var sources)) { sources.Add (file); } else { sources = new List<string> () { file }; - builder[dirName] = sources; + builder[parentDirectory!] = sources; } } diff --git a/test/ILLink.RoslynAnalyzer.Tests/TestChecker.cs b/test/ILLink.RoslynAnalyzer.Tests/TestChecker.cs index ecf91c376..68563e46e 100644 --- a/test/ILLink.RoslynAnalyzer.Tests/TestChecker.cs +++ b/test/ILLink.RoslynAnalyzer.Tests/TestChecker.cs @@ -11,6 +11,7 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Text; +using Mono.Linker.Tests.Cases.Expectations.Assertions; using Xunit; namespace ILLink.RoslynAnalyzer.Tests @@ -25,10 +26,15 @@ namespace ILLink.RoslynAnalyzer.Tests private readonly SyntaxNode MemberSyntax; + private readonly string TestingAnalyzerName; + public TestChecker (MemberDeclarationSyntax memberSyntax, (CompilationWithAnalyzers Compilation, SemanticModel SemanticModel) compilationResult) { Compilation = compilationResult.Compilation; SemanticModel = compilationResult.SemanticModel; + + // Currently, tests are only run using a single analyzer. + TestingAnalyzerName = Compilation.Analyzers.Single ().GetType ().Name; DiagnosticMessages = Compilation.GetAnalyzerDiagnosticsAsync ().Result .Where (d => { // Filter down to diagnostics which originate from this member. @@ -67,11 +73,11 @@ namespace ILLink.RoslynAnalyzer.Tests switch (attribute.Name.ToString ()) { case "ExpectedWarning": var args = TestCaseUtils.GetAttributeArguments (attribute); - if (args.TryGetValue ("ProducedBy", out var producedBy) && - producedBy is MemberAccessExpressionSyntax memberAccessExpression && - memberAccessExpression.Name is IdentifierNameSyntax identifierNameSyntax && - identifierNameSyntax.Identifier.ValueText == "Trimmer") - return false; + if (args.TryGetValue ("ProducedBy", out var producedBy)) { + // Skip if this warning is not expected to be produced by any of the analyzers that we are currently testing. + return GetProducedBy (producedBy).HasFlag (Enum.Parse<ProducedBy> (TestingAnalyzerName)); + } + return true; case "LogContains": case "UnrecognizedReflectionAccessPattern": @@ -79,6 +85,28 @@ namespace ILLink.RoslynAnalyzer.Tests default: return false; } + + static ProducedBy GetProducedBy (ExpressionSyntax expression) + { + var producedBy = (ProducedBy) 0x0; + switch (expression) { + case BinaryExpressionSyntax binaryExpressionSyntax: + Enum.TryParse<ProducedBy> ((binaryExpressionSyntax.Left as MemberAccessExpressionSyntax)!.Name.Identifier.ValueText, out var besProducedBy); + producedBy |= besProducedBy; + producedBy |= GetProducedBy (binaryExpressionSyntax.Right); + break; + + case MemberAccessExpressionSyntax memberAccessExpressionSyntax: + Enum.TryParse<ProducedBy> (memberAccessExpressionSyntax.Name.Identifier.ValueText, out var maeProducedBy); + producedBy |= maeProducedBy; + break; + + default: + break; + } + + return producedBy; + } } bool TryValidateExpectedDiagnostic (AttributeSyntax attribute, List<Diagnostic> diagnostics, [NotNullWhen (true)] out int? matchIndex, [NotNullWhen (false)] out string? missingDiagnosticMessage) diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ProducedBy.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ProducedBy.cs index b18578c3d..6b441975e 100644 --- a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ProducedBy.cs +++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ProducedBy.cs @@ -5,11 +5,19 @@ using System; namespace Mono.Linker.Tests.Cases.Expectations.Assertions { + /// <summary> + /// Used to specify which tool produces a warning. This can either be the trimmer, a specific analyzer, or both. + /// Currently we have all existing diagnostic analyzers listed in here so that we can leave out some expected warnings + /// when testing analyzers which do not produce them. + /// </summary> [Flags] public enum ProducedBy { Trimmer = 1, - Analyzer = 2, + RequiresAssemblyFileAnalyzer = 2, + RequiresUnreferencedCodeAnalyzer = 4, + COMAnalyzer = 8, + Analyzer = RequiresAssemblyFileAnalyzer | RequiresUnreferencedCodeAnalyzer | COMAnalyzer, TrimmerAndAnalyzer = Trimmer | Analyzer } }
\ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases/Interop/PInvoke/Warnings/ComPInvokeWarning.cs b/test/Mono.Linker.Tests.Cases/Interop/PInvoke/Warnings/ComPInvokeWarning.cs index 720ad738b..e82d8bc59 100644 --- a/test/Mono.Linker.Tests.Cases/Interop/PInvoke/Warnings/ComPInvokeWarning.cs +++ b/test/Mono.Linker.Tests.Cases/Interop/PInvoke/Warnings/ComPInvokeWarning.cs @@ -15,6 +15,7 @@ namespace Mono.Linker.Tests.Cases.Interop.PInvoke.Warnings [UnconditionalSuppressMessage ("trim", "IL2026")] static void Main () { + Call_SomeMethodReturningAutoLayoutClass (); Call_SomeMethodTakingInterface (); Call_SomeMethodTakingObject (); Call_SomeMethodTakingArray (); @@ -38,6 +39,7 @@ namespace Mono.Linker.Tests.Cases.Interop.PInvoke.Warnings { SomeMethodTakingInterface (null); } + [DllImport ("Foo")] static extern void SomeMethodTakingInterface (IFoo foo); @@ -46,6 +48,7 @@ namespace Mono.Linker.Tests.Cases.Interop.PInvoke.Warnings { SomeMethodTakingObject (null); } + [DllImport ("Foo")] static extern void SomeMethodTakingObject ([MarshalAs (UnmanagedType.IUnknown)] object obj); @@ -54,6 +57,7 @@ namespace Mono.Linker.Tests.Cases.Interop.PInvoke.Warnings { SomeMethodTakingArray (null); } + [DllImport ("Foo")] static extern void SomeMethodTakingArray (Array array); @@ -61,6 +65,7 @@ namespace Mono.Linker.Tests.Cases.Interop.PInvoke.Warnings { SomeMethodTakingStringBuilder (null); } + [DllImport ("Foo")] static extern void SomeMethodTakingStringBuilder (StringBuilder str); @@ -68,6 +73,7 @@ namespace Mono.Linker.Tests.Cases.Interop.PInvoke.Warnings { SomeMethodTakingCriticalHandle (null); } + [DllImport ("Foo")] static extern void SomeMethodTakingCriticalHandle (MyCriticalHandle handle); @@ -76,6 +82,7 @@ namespace Mono.Linker.Tests.Cases.Interop.PInvoke.Warnings { SomeMethodTakingSafeHandle (null); } + [DllImport ("Foo")] static extern void SomeMethodTakingSafeHandle (TestSafeHandle handle); @@ -83,6 +90,7 @@ namespace Mono.Linker.Tests.Cases.Interop.PInvoke.Warnings { SomeMethodTakingExplicitLayout (null); } + [DllImport ("Foo")] static extern void SomeMethodTakingExplicitLayout (ExplicitLayout _class); @@ -90,6 +98,7 @@ namespace Mono.Linker.Tests.Cases.Interop.PInvoke.Warnings { SomeMethodTakingSequentialLayout (null); } + [DllImport ("Foo")] static extern void SomeMethodTakingSequentialLayout (SequentialLayout _class); @@ -98,14 +107,24 @@ namespace Mono.Linker.Tests.Cases.Interop.PInvoke.Warnings { SomeMethodTakingAutoLayout (null); } + [DllImport ("Foo")] static extern void SomeMethodTakingAutoLayout (AutoLayout _class); + [ExpectedWarning ("IL2050")] + static void Call_SomeMethodReturningAutoLayoutClass () + { + SomeMethodReturningAutoLayout (); + } + + [DllImport ("Foo")] + static extern AutoLayout SomeMethodReturningAutoLayout (); static void Call_SomeMethodTakingString () { SomeMethodTakingString (null); } + [DllImport ("Foo")] static extern void SomeMethodTakingString (String str); @@ -114,6 +133,7 @@ namespace Mono.Linker.Tests.Cases.Interop.PInvoke.Warnings { GetInterface (); } + [DllImport ("Foo")] static extern IFoo GetInterface (); @@ -122,6 +142,7 @@ namespace Mono.Linker.Tests.Cases.Interop.PInvoke.Warnings { CanSuppressWarningOnParameter (null); } + [DllImport ("Foo")] static extern void CanSuppressWarningOnParameter ([MarshalAs (UnmanagedType.IUnknown)] object obj); @@ -130,6 +151,7 @@ namespace Mono.Linker.Tests.Cases.Interop.PInvoke.Warnings { CanSuppressWarningOnReturnType (); } + [DllImport ("Foo")] static extern IFoo CanSuppressWarningOnReturnType (); @@ -153,7 +175,7 @@ namespace Mono.Linker.Tests.Cases.Interop.PInvoke.Warnings static extern void CanSuppressPInvokeWithRequiresUnreferencedCode (IFoo foo); [ExpectedWarning ("IL2050")] - [ExpectedWarning ("IL2026")] + [ExpectedWarning ("IL2026", ProducedBy = ProducedBy.Trimmer | ProducedBy.RequiresUnreferencedCodeAnalyzer)] static void Call_PInvokeWithRequiresUnreferencedCode () { PInvokeWithRequiresUnreferencedCode (null); |