diff options
author | Tlakaelel Axayakatl Ceja <tlakaelel.ceja@microsoft.com> | 2021-04-01 06:38:10 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-01 06:38:10 +0300 |
commit | f4147aa53a425420f725c9cb5dbd36552df99372 (patch) | |
tree | cdc2529bd7824a210ae95c150c6d888e8b7a1036 /test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs | |
parent | dd7d70118b7146125781c830bbff47a8cb953f39 (diff) |
Merge SingleFileAnalyzer into RequiresAssemblyFilesAnalyzer and add capability to suppress IL3000/IL3001 with RequiresAssemblyFilesAnalyzer (#1921)
Merge SingleFileAnalyzer into RequiresAssemblyFilesAnalyzer
Suppress warnings on dangerous patterns if RequiresAssemblyFilesAttribute is used on the parent call
Fix case in which we have a dangerous method inside a property
Add tests
Diffstat (limited to 'test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs')
-rw-r--r-- | test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs | 192 |
1 files changed, 185 insertions, 7 deletions
diff --git a/test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs b/test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs index 07f1aa2b6..5e62159da 100644 --- a/test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs +++ b/test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs @@ -35,7 +35,7 @@ class C }"; return VerifyRequiresAssemblyFilesAnalyzer (TestRequiresAssemblyFieldsOnEvent, // (12,17): warning IL3002: Using member 'C.E' which has 'RequiresAssemblyFilesAttribute' can break functionality when embedded in a single-file app. - VerifyCS.Diagnostic ().WithSpan (12, 17, 12, 18).WithArguments ("C.E", "", "")); + VerifyCS.Diagnostic (RequiresAssemblyFilesAnalyzer.IL3002).WithSpan (12, 17, 12, 18).WithArguments ("C.E", "", "")); } [Fact] @@ -58,7 +58,7 @@ class C }"; return VerifyRequiresAssemblyFilesAnalyzer (TestRequiresAssemblyFilesOnMethod, // (13,3): warning IL3002: Using member 'C.M1()' which has 'RequiresAssemblyFilesAttribute' can break functionality when embedded in a single-file app. - VerifyCS.Diagnostic ().WithSpan (13, 3, 13, 7).WithArguments ("C.M1()", "", "")); + VerifyCS.Diagnostic (RequiresAssemblyFilesAnalyzer.IL3002).WithSpan (13, 3, 13, 7).WithArguments ("C.M1()", "", "")); } [Fact] @@ -81,9 +81,43 @@ class C }"; return VerifyRequiresAssemblyFilesAnalyzer (TestRequiresAssemblyFilesOnProperty, // (11,3): warning IL3002: Using member 'C.P' which has 'RequiresAssemblyFilesAttribute' can break functionality when embedded in a single-file app. - VerifyCS.Diagnostic ().WithSpan (12, 3, 12, 4).WithArguments ("C.P", "", ""), + VerifyCS.Diagnostic (RequiresAssemblyFilesAnalyzer.IL3002).WithSpan (12, 3, 12, 4).WithArguments ("C.P", "", ""), // (13,12): warning IL3002: Using member 'C.P' which has 'RequiresAssemblyFilesAttribute' can break functionality when embedded in a single-file app. - VerifyCS.Diagnostic ().WithSpan (13, 35, 13, 36).WithArguments ("C.P", "", "")); + VerifyCS.Diagnostic (RequiresAssemblyFilesAnalyzer.IL3002).WithSpan (13, 35, 13, 36).WithArguments ("C.P", "", "")); + } + + [Fact] + public Task CallDangerousMethodInsideProperty () + { + var TestRequiresAssemblyFilesOnMethodInsideProperty = @" +using System.Diagnostics.CodeAnalysis; + +class C +{ + bool field; + + [RequiresAssemblyFiles] + bool P { + get { + return field; + } + set { + CallDangerousMethod (); + field = value; + } + } + + [RequiresAssemblyFiles] + void CallDangerousMethod () {} + + void M () + { + P = false; + } +}"; + return VerifyRequiresAssemblyFilesAnalyzer (TestRequiresAssemblyFilesOnMethodInsideProperty, + // (24,3): warning IL3002: Using member 'C.P' which has 'RequiresAssemblyFilesAttribute' can break functionality when embedded in a single-file app. + VerifyCS.Diagnostic (RequiresAssemblyFilesAnalyzer.IL3002).WithSpan (24, 3, 24, 4).WithArguments ("C.P", "", "")); } [Fact] @@ -106,7 +140,7 @@ class C }"; return VerifyRequiresAssemblyFilesAnalyzer (TestRequiresAssemblyFilesWithMessageAndUrl, // (13,3): warning IL3002: Using member 'C.M1()' which has 'RequiresAssemblyFilesAttribute' can break functionality when embedded in a single-file app. Message from attribute. https://helpurl - VerifyCS.Diagnostic ().WithSpan (13, 3, 13, 7).WithArguments ("C.M1()", " Message from attribute.", " https://helpurl")); + VerifyCS.Diagnostic (RequiresAssemblyFilesAnalyzer.IL3002).WithSpan (13, 3, 13, 7).WithArguments ("C.M1()", " Message from attribute.", " https://helpurl")); } [Fact] @@ -129,7 +163,7 @@ class C }"; return VerifyRequiresAssemblyFilesAnalyzer (TestRequiresAssemblyFilesWithMessageAndUrl, // (13,3): warning IL3002: Using member 'C.M1()' which has 'RequiresAssemblyFilesAttribute' can break functionality when embedded in a single-file app. https://helpurl - VerifyCS.Diagnostic ().WithSpan (13, 3, 13, 7).WithArguments ("C.M1()", "", " https://helpurl")); + VerifyCS.Diagnostic (RequiresAssemblyFilesAnalyzer.IL3002).WithSpan (13, 3, 13, 7).WithArguments ("C.M1()", "", " https://helpurl")); } [Fact] @@ -172,7 +206,151 @@ class C }"; return VerifyRequiresAssemblyFilesAnalyzer (TestNoDiagnosticIsProducedIfCallerIsAnnotated, // (8,3): warning IL3002: Using member 'C.M2()' which has 'RequiresAssemblyFilesAttribute' can break functionality when embedded in a single-file app. Warn from M2. - VerifyCS.Diagnostic ().WithSpan (8, 3, 8, 7).WithArguments ("C.M2()", " Warn from M2.", "")); + VerifyCS.Diagnostic (RequiresAssemblyFilesAnalyzer.IL3002).WithSpan (8, 3, 8, 7).WithArguments ("C.M2()", " Warn from M2.", "")); + } + + [Fact] + public Task GetExecutingAssemblyLocation () + { + const string src = @" +using System.Reflection; +class C +{ + public string M() => Assembly.GetExecutingAssembly().Location; +}"; + + return VerifyRequiresAssemblyFilesAnalyzer (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 (RequiresAssemblyFilesAnalyzer.IL3000).WithSpan (5, 26, 5, 66).WithArguments ("System.Reflection.Assembly.Location")); + } + + [Fact] + public Task GetAssemblyLocationViaAssemblyProperties () + { + 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 VerifyRequiresAssemblyFilesAnalyzer (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 (RequiresAssemblyFilesAnalyzer.IL3000).WithSpan (8, 13, 8, 23).WithArguments ("System.Reflection.Assembly.Location") + ); + } + + [Fact] + public Task CallKnownDangerousAssemblyMethods () + { + var src = @" +using System.Reflection; +class C +{ + public void M() + { + var a = Assembly.GetExecutingAssembly(); + _ = a.GetFile(""/some/file/path""); + _ = a.GetFiles(); + } +}"; + return VerifyRequiresAssemblyFilesAnalyzer (src, + // (8,13): warning IL3001: Assemblies embedded in a single-file app cannot have additional files in the manifest. + VerifyCS.Diagnostic (RequiresAssemblyFilesAnalyzer.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 (RequiresAssemblyFilesAnalyzer.IL3001).WithSpan (9, 13, 9, 25).WithArguments ("System.Reflection.Assembly.GetFiles()") + ); + } + + [Fact] + public Task CallKnownDangerousAssemblyNameAttributes () + { + var src = @" +using System.Reflection; +class C +{ + public void M() + { + var a = Assembly.GetExecutingAssembly().GetName(); + _ = a.CodeBase; + _ = a.EscapedCodeBase; + } +}"; + return VerifyRequiresAssemblyFilesAnalyzer (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 (RequiresAssemblyFilesAnalyzer.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 (RequiresAssemblyFilesAnalyzer.IL3000).WithSpan (9, 13, 9, 30).WithArguments ("System.Reflection.AssemblyName.EscapedCodeBase") + ); + } + + [Fact] + public Task GetAssemblyLocationFalsePositive () + { + // 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 VerifyRequiresAssemblyFilesAnalyzer (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 (RequiresAssemblyFilesAnalyzer.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 (RequiresAssemblyFilesAnalyzer.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); + } + + [Fact] + public Task SupressWarningsWithRequiresAssemblyFiles () + { + const string src = @" +using System.Reflection; +using System.Diagnostics.CodeAnalysis; +class C +{ + [RequiresAssemblyFiles] + public void M() + { + var a = Assembly.GetExecutingAssembly(); + _ = a.Location; + var b = Assembly.GetExecutingAssembly(); + _ = b.GetFile(""/some/file/path""); + _ = b.GetFiles(); + } +}"; + + return VerifyRequiresAssemblyFilesAnalyzer (src); } } } |