Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/linker.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorMateo Torres-Ruiz <mateoatr@users.noreply.github.com>2020-12-09 05:23:56 +0300
committerGitHub <noreply@github.com>2020-12-09 05:23:56 +0300
commita86658f4602e616d71e5d6db23a30940534132e2 (patch)
treea6f958d0ffeac9bae729e3845ca18375a78d021f /test
parentd0602c4767acf5dcd46700381ce39bd2775de6d7 (diff)
Port single-file analyzer (#1665)
* Add single-file analyzer * Add tests * Use str constant * Update Resources * Update tests * PR feedback * Remove mysterious filename from comments * Add helper method for single-file diagnostic verification * Refactor MSBuild properties * Add test with PublishSingleFile not set
Diffstat (limited to 'test')
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/AvoidAssemblyLocationInSingleFileTests.cs144
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/LinkerTestCases.cs4
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs (renamed from test/ILLink.RoslynAnalyzer.Tests/AnalyzerTests.cs)21
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs9
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpAnalyzerVerifier`1.cs4
5 files changed, 168 insertions, 14 deletions
diff --git a/test/ILLink.RoslynAnalyzer.Tests/AvoidAssemblyLocationInSingleFileTests.cs b/test/ILLink.RoslynAnalyzer.Tests/AvoidAssemblyLocationInSingleFileTests.cs
new file mode 100644
index 000000000..0ea712f97
--- /dev/null
+++ b/test/ILLink.RoslynAnalyzer.Tests/AvoidAssemblyLocationInSingleFileTests.cs
@@ -0,0 +1,144 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis.Testing;
+using Xunit;
+using VerifyCS = ILLink.RoslynAnalyzer.Tests.CSharpAnalyzerVerifier<
+ ILLink.RoslynAnalyzer.AvoidAssemblyLocationInSingleFile>;
+
+namespace ILLink.RoslynAnalyzer.Tests
+{
+ public class AvoidAssemblyLocationInSingleFileTests
+ {
+ static Task VerifySingleFileAnalyzer (string source, params DiagnosticResult[] expected)
+ {
+ return VerifyCS.VerifyAnalyzerAsync (source,
+ TestCaseUtils.UseMSBuildProperties (MSBuildPropertyOptionNames.PublishSingleFile),
+ expected);
+ }
+
+ [Fact]
+ public Task GetExecutingAssemblyLocation ()
+ {
+ const string src = @"
+using System.Reflection;
+class C
+{
+ public string M() => Assembly.GetExecutingAssembly().Location;
+}";
+
+ return VerifySingleFileAnalyzer (src,
+ // (5,26): warning IL3000: 'System.Reflection.Assembly.Location' always returns an empty string for assemblies embedded in a single-file app. If the path to the app directory is needed, consider calling 'System.AppContext.BaseDirectory'.
+ VerifyCS.Diagnostic (AvoidAssemblyLocationInSingleFile.IL3000).WithSpan (5, 26, 5, 66).WithArguments ("System.Reflection.Assembly.Location"));
+ }
+
+ [Fact]
+ public Task AssemblyProperties ()
+ {
+ var src = @"
+using System.Reflection;
+class C
+{
+ public void M()
+ {
+ var a = Assembly.GetExecutingAssembly();
+ _ = a.Location;
+ // below methods are marked as obsolete in 5.0
+ // _ = a.CodeBase;
+ // _ = a.EscapedCodeBase;
+ }
+}";
+ return VerifySingleFileAnalyzer (src,
+ // (8,13): warning IL3000: 'System.Reflection.Assembly.Location' always returns an empty string for assemblies embedded in a single-file app. If the path to the app directory is needed, consider calling 'System.AppContext.BaseDirectory'.
+ VerifyCS.Diagnostic (AvoidAssemblyLocationInSingleFile.IL3000).WithSpan (8, 13, 8, 23).WithArguments ("System.Reflection.Assembly.Location")
+ );
+ }
+
+ [Fact]
+ public Task AssemblyMethods ()
+ {
+ var src = @"
+using System.Reflection;
+class C
+{
+ public void M()
+ {
+ var a = Assembly.GetExecutingAssembly();
+ _ = a.GetFile(""/some/file/path"");
+ _ = a.GetFiles();
+ }
+}";
+ return VerifySingleFileAnalyzer (src,
+ // (8,13): warning IL3001: Assemblies embedded in a single-file app cannot have additional files in the manifest.
+ VerifyCS.Diagnostic (AvoidAssemblyLocationInSingleFile.IL3001).WithSpan (8, 13, 8, 41).WithArguments ("System.Reflection.Assembly.GetFile(string)"),
+ // (9,13): warning IL3001: Assemblies embedded in a single-file app cannot have additional files in the manifest.
+ VerifyCS.Diagnostic (AvoidAssemblyLocationInSingleFile.IL3001).WithSpan (9, 13, 9, 25).WithArguments ("System.Reflection.Assembly.GetFiles()")
+ );
+ }
+
+ [Fact]
+ public Task AssemblyNameAttributes ()
+ {
+ var src = @"
+using System.Reflection;
+class C
+{
+ public void M()
+ {
+ var a = Assembly.GetExecutingAssembly().GetName();
+ _ = a.CodeBase;
+ _ = a.EscapedCodeBase;
+ }
+}";
+ return VerifySingleFileAnalyzer (src,
+ // (8,13): warning IL3000: 'System.Reflection.AssemblyName.CodeBase' always returns an empty string for assemblies embedded in a single-file app. If the path to the app directory is needed, consider calling 'System.AppContext.BaseDirectory'.
+ VerifyCS.Diagnostic (AvoidAssemblyLocationInSingleFile.IL3000).WithSpan (8, 13, 8, 23).WithArguments ("System.Reflection.AssemblyName.CodeBase"),
+ // (9,13): warning IL3000: 'System.Reflection.AssemblyName.EscapedCodeBase' always returns an empty string for assemblies embedded in a single-file app. If the path to the app directory is needed, consider calling 'System.AppContext.BaseDirectory'.
+ VerifyCS.Diagnostic (AvoidAssemblyLocationInSingleFile.IL3000).WithSpan (9, 13, 9, 30).WithArguments ("System.Reflection.AssemblyName.EscapedCodeBase")
+ );
+ }
+
+ [Fact]
+ public Task FalsePositive ()
+ {
+ // This is an OK use of Location and GetFile since these assemblies were loaded from
+ // a file, but the analyzer is conservative
+ var src = @"
+using System.Reflection;
+class C
+{
+ public void M()
+ {
+ var a = Assembly.LoadFrom(""/some/path/not/in/bundle"");
+ _ = a.Location;
+ _ = a.GetFiles();
+ }
+}";
+ return VerifySingleFileAnalyzer (src,
+ // (8,13): warning IL3000: 'System.Reflection.Assembly.Location' always returns an empty string for assemblies embedded in a single-file app. If the path to the app directory is needed, consider calling 'System.AppContext.BaseDirectory'.
+ VerifyCS.Diagnostic (AvoidAssemblyLocationInSingleFile.IL3000).WithSpan (8, 13, 8, 23).WithArguments ("System.Reflection.Assembly.Location"),
+ // (9,13): warning IL3001: Assemblies embedded in a single-file app cannot have additional files in the manifest.
+ VerifyCS.Diagnostic (AvoidAssemblyLocationInSingleFile.IL3001).WithSpan (9, 13, 9, 25).WithArguments ("System.Reflection.Assembly.GetFiles()")
+ );
+ }
+
+ [Fact]
+ public Task PublishSingleFileIsNotSet ()
+ {
+ var src = @"
+using System.Reflection;
+class C
+{
+ public void M()
+ {
+ var a = Assembly.GetExecutingAssembly().Location;
+ }
+}";
+ // If 'PublishSingleFile' is not set to true, no diagnostics should be produced by the analyzer. This will
+ // effectively verify that the number of produced diagnostics matches the number of expected ones (zero).
+ return VerifyCS.VerifyAnalyzerAsync (src);
+ }
+ }
+}
diff --git a/test/ILLink.RoslynAnalyzer.Tests/LinkerTestCases.cs b/test/ILLink.RoslynAnalyzer.Tests/LinkerTestCases.cs
index e63d2c02f..f205fb25e 100644
--- a/test/ILLink.RoslynAnalyzer.Tests/LinkerTestCases.cs
+++ b/test/ILLink.RoslynAnalyzer.Tests/LinkerTestCases.cs
@@ -3,8 +3,6 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
-using System.Collections.Immutable;
-using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Xunit;
@@ -24,7 +22,7 @@ namespace ILLink.RoslynAnalyzer.Tests
case "MethodWithDuplicateRequiresAttribute":
return;
}
- RunTest (m, attrs);
+ RunTest (m, attrs, UseMSBuildProperties (MSBuildPropertyOptionNames.PublishTrimmed));
}
}
}
diff --git a/test/ILLink.RoslynAnalyzer.Tests/AnalyzerTests.cs b/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs
index fc1ee182d..81899e890 100644
--- a/test/ILLink.RoslynAnalyzer.Tests/AnalyzerTests.cs
+++ b/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs
@@ -3,14 +3,22 @@
// See the LICENSE file in the project root for more information.
using System.Threading.Tasks;
+using Microsoft.CodeAnalysis.Testing;
using Xunit;
using VerifyCS = ILLink.RoslynAnalyzer.Tests.CSharpAnalyzerVerifier<
ILLink.RoslynAnalyzer.RequiresUnreferencedCodeAnalyzer>;
namespace ILLink.RoslynAnalyzer.Tests
{
- public class AnalyzerTests
+ public class RequiresUnreferencedCodeAnalyzerTests
{
+ static Task VerifyRequiresUnreferencedCodeAnalyzer (string source, params DiagnosticResult[] expected)
+ {
+ return VerifyCS.VerifyAnalyzerAsync (source,
+ TestCaseUtils.UseMSBuildProperties (MSBuildPropertyOptionNames.PublishTrimmed),
+ expected);
+ }
+
[Fact]
public Task SimpleDiagnostic ()
{
@@ -23,10 +31,9 @@ class C
int M1() => 0;
int M2() => M1();
}";
- return VerifyCS.VerifyAnalyzerAsync (TestRequiresWithMessageOnlyOnMethod,
+ return VerifyRequiresUnreferencedCodeAnalyzer (TestRequiresWithMessageOnlyOnMethod,
// (8,17): warning IL2026: Calling 'System.Int32 C::M1()' which has `RequiresUnreferencedCodeAttribute` can break functionality when trimming application code. message.
- VerifyCS.Diagnostic ().WithSpan (8, 17, 8, 21).WithArguments ("C.M1()", "message", "")
- );
+ VerifyCS.Diagnostic ().WithSpan (8, 17, 8, 21).WithArguments ("C.M1()", "message", ""));
}
[Fact]
@@ -46,7 +53,7 @@ class C
{
}
}";
- return VerifyCS.VerifyAnalyzerAsync (MessageAndUrlOnMethod,
+ return VerifyRequiresUnreferencedCodeAnalyzer (MessageAndUrlOnMethod,
// (8,3): warning IL2026: Calling 'C.RequiresWithMessageAndUrl()' which has `RequiresUnreferencedCodeAttribute` can break functionality when trimming application code. Message for --RequiresWithMessageAndUrl--.
VerifyCS.Diagnostic ().WithSpan (8, 3, 8, 31).WithArguments ("C.RequiresWithMessageAndUrl()", "Message for --RequiresWithMessageAndUrl--", "https://helpurl")
);
@@ -70,7 +77,7 @@ class C
get { return 42; }
}
}";
- return VerifyCS.VerifyAnalyzerAsync (PropertyRequires,
+ return VerifyRequiresUnreferencedCodeAnalyzer (PropertyRequires,
// (8,7): warning IL2026: Calling 'C.PropertyRequires.get' which has `RequiresUnreferencedCodeAttribute` can break functionality when trimming application code. Message for --getter PropertyRequires--.
VerifyCS.Diagnostic ().WithSpan (8, 7, 8, 23).WithArguments ("C.PropertyRequires.get", "Message for --getter PropertyRequires--", "")
);
@@ -94,7 +101,7 @@ class C
set { }
}
}";
- return VerifyCS.VerifyAnalyzerAsync (PropertyRequires,
+ return VerifyRequiresUnreferencedCodeAnalyzer (PropertyRequires,
// (8,3): warning IL2026: Calling 'C.PropertyRequires.set' which has `RequiresUnreferencedCodeAttribute` can break functionality when trimming application code. Message for --setter PropertyRequires--.
VerifyCS.Diagnostic ().WithSpan (8, 3, 8, 19).WithArguments ("C.PropertyRequires.set", "Message for --setter PropertyRequires--", "")
);
diff --git a/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs b/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs
index 003823c02..c62c2d762 100644
--- a/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs
+++ b/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs
@@ -53,9 +53,9 @@ namespace ILLink.RoslynAnalyzer.Tests
}
}
- internal static void RunTest (MethodDeclarationSyntax m, List<AttributeSyntax> attrs)
+ internal static void RunTest (MethodDeclarationSyntax m, List<AttributeSyntax> attrs, params (string, string)[] MSBuildProperties)
{
- var comp = CSharpAnalyzerVerifier<RequiresUnreferencedCodeAnalyzer>.CreateCompilation (m.SyntaxTree).Result;
+ var comp = CSharpAnalyzerVerifier<RequiresUnreferencedCodeAnalyzer>.CreateCompilation (m.SyntaxTree, MSBuildProperties).Result;
var diags = comp.GetAnalyzerDiagnosticsAsync ().Result;
var filtered = diags.Where (d => d.Location.SourceSpan.IntersectsWith (m.Span))
@@ -181,6 +181,11 @@ In diagnostics:
}
}
+ internal static (string, string)[] UseMSBuildProperties (params string[] MSBuildProperties)
+ {
+ return MSBuildProperties.Select (msbp => ($"build_property.{msbp}", "true")).ToArray ();
+ }
+
internal static void GetDirectoryPaths (out string rootSourceDirectory, out string testAssemblyPath, [CallerFilePath] string thisFile = null)
{
diff --git a/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpAnalyzerVerifier`1.cs b/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpAnalyzerVerifier`1.cs
index 91b28b1aa..4d96f37d8 100644
--- a/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpAnalyzerVerifier`1.cs
+++ b/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpAnalyzerVerifier`1.cs
@@ -71,9 +71,9 @@ namespace ILLink.RoslynAnalyzer.Tests
}
/// <inheritdoc cref="AnalyzerVerifier{TAnalyzer, TTest, TVerifier}.VerifyAnalyzerAsync(string, DiagnosticResult[])"/>
- public static async Task VerifyAnalyzerAsync (string src, params DiagnosticResult[] expected)
+ public static async Task VerifyAnalyzerAsync (string src, (string, string)[]? analyzerOptions = null, params DiagnosticResult[] expected)
{
- var diags = await (await CreateCompilation (src)).GetAllDiagnosticsAsync ();
+ var diags = await (await CreateCompilation (src, analyzerOptions)).GetAllDiagnosticsAsync ();
var analyzers = ImmutableArray.Create<DiagnosticAnalyzer> (new TAnalyzer ());
VerifyDiagnosticResults (diags, analyzers, expected, DefaultVerifier);