Skip to content

Commit 43c4e97

Browse files
authored
Enable .NET Analyzers for all managed projects. (#423)
* Enable .NET Analyzers for all managed projects. Use SDL Recommended ruleset at Error level. Report all code analysis warnings as errors. Fix existing violations.
1 parent f18a75c commit 43c4e97

File tree

10 files changed

+450
-17
lines changed

10 files changed

+450
-17
lines changed

build/CodeAnalysis/Sdl.Recommended.Error.ruleset

Lines changed: 364 additions & 0 deletions
Large diffs are not rendered by default.

build/Managed.props

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121

2222
<PropertyGroup>
2323
<DefineConstants Condition="'$(PublicRelease)' != 'True'">$(DefineConstants);ALLOWNOTSIGNED</DefineConstants>
24+
<EnableNetAnalyzers>true</EnableNetAnalyzers>
25+
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)CodeAnalysis\Sdl.Recommended.Error.ruleset</CodeAnalysisRuleSet>
26+
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
2427
</PropertyGroup>
2528

2629
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />

build/yaml/steps/codeanalysis/csharp.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ steps:
99
inputs:
1010
continueOnError: true
1111
rulesetName: Custom
12-
msBuildArchitecture: x64
12+
msBuildArchitecture: amd64
1313
customRuleset: DevDivRoslynRequired.ruleset
1414
msBuildCommandline: >-
1515
dotnet

src/Tests/RemoteUnitTestExecutor.Host/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
namespace RemoteUnitTestExecutor.Host
77
{
8-
public class Program
8+
public static class Program
99
{
1010
public static void Main(string[] args)
1111
{

src/Tests/RemoteUnitTestExecutor/AssertExtensions.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,35 @@
44
namespace RemoteUnitTestExecutor
55
{
66
using Microsoft.VisualStudio.TestTools.UnitTesting;
7+
using System;
78
using System.Collections.Generic;
89

910
public static class AssertExtensions
1011
{
1112
public static void ClearInvokedMethods(IList<MethodInvocationInfo> invokedMethods)
1213
{
14+
if (null == invokedMethods)
15+
{
16+
throw new ArgumentNullException(nameof(invokedMethods));
17+
}
18+
1319
// Clear the methods
1420
invokedMethods.Clear();
1521
Assert.AreEqual(0, invokedMethods.Count, "Invoked methods are not cleared.");
1622
}
1723

1824
public static void InvokedMethodsAreEqual(IList<MethodInvocationInfo> actual, string[] expectedMethodNames)
1925
{
26+
if (null == actual)
27+
{
28+
throw new ArgumentNullException(nameof(actual));
29+
}
30+
31+
if (null == expectedMethodNames)
32+
{
33+
throw new ArgumentNullException(nameof(expectedMethodNames));
34+
}
35+
2036
Assert.AreEqual(expectedMethodNames.Length, actual.Count, "Actual and expected invoked methods count mismatch.");
2137

2238
for (int i = 0; i < expectedMethodNames.Length; ++i)

src/Tests/RemoteUnitTestExecutor/MethodInvocationInfo.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,21 @@
44
namespace RemoteUnitTestExecutor
55
{
66
using System;
7+
using System.Collections.Generic;
78

89
[Serializable]
910
public class MethodInvocationInfo
1011
{
12+
[NonSerialized]
13+
private List<object> _arguments = new List<object>();
14+
1115
public string MethodName { get; set; }
1216

13-
[NonSerialized] public object[] Arguments;
17+
public IEnumerable<object> Arguments => _arguments;
18+
19+
public void AddArgument(object value)
20+
{
21+
_arguments.Add(value);
22+
}
1423
}
1524
}

src/Tests/RemoteUnitTestExecutor/Program.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,15 @@ namespace RemoteUnitTestExecutor
55
{
66
using System;
77

8-
public class Program
8+
public static class Program
99
{
1010
public static void Main(string[] args)
1111
{
12+
if (null == args)
13+
{
14+
throw new ArgumentNullException(nameof(args));
15+
}
16+
1217
if (args.Length < 2 || string.IsNullOrWhiteSpace(args[1]))
1318
{
1419
throw new ArgumentException("Wrong number of arguments provided - expecting at least 2 arguments:\r\n arg[0] - test name; \r\n arg[1] - test results file name");

src/Tests/RemoteUnitTestExecutor/TestEngineBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public ITestResult ExecuteTest(
2020
{
2121
if (true == string.IsNullOrWhiteSpace(testName))
2222
{
23-
throw new ArgumentNullException("testName");
23+
throw new ArgumentNullException(nameof(testName));
2424
}
2525

2626
string testOutputFileName = "testOutput_" + Guid.NewGuid() + ".xml";

src/Tests/RemoteUnitTestExecutor/TestResult.cs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ namespace RemoteUnitTestExecutor
55
{
66
using System;
77
using System.Collections.Generic;
8+
using System.Diagnostics.CodeAnalysis;
89
using System.IO;
910
using System.Linq;
11+
using System.Runtime.Serialization;
1012
using System.Runtime.Serialization.Formatters.Binary;
1113

1214
/// <summary>
@@ -20,7 +22,7 @@ public TestResult()
2022
InvokedMethods = new List<MethodInvocationInfo>();
2123
}
2224

23-
public IList<MethodInvocationInfo> InvokedMethods { get; set; }
25+
public IList<MethodInvocationInfo> InvokedMethods { get; }
2426

2527
public bool Succeeded { get; set; }
2628

@@ -36,16 +38,28 @@ public void Serialize(string filename)
3638
}
3739
}
3840

41+
/// CA2300 is set to Info level, which will not cause a build break. However, RoslynAnalyzer and PostAnalysis
42+
/// pipeline tasks will fail on any level reported above None. Recommendation is to disable CA2300 and enable
43+
/// CA2301 and CA2302 as mitigations. However, these are part of the SDL ruleset and we should not modify its
44+
/// behavior. Thus, mitigate CA2301 and CA2302 and then suppress CA2300.
45+
[SuppressMessage("Security", "CA2300", Justification = "Mitigated with fixes for CA2301 and CA2302")]
3946
public static ITestResult CreateFromFile(string testOutputFileName)
4047
{
4148
using (FileStream deserializationStream = File.OpenRead(testOutputFileName))
4249
{
43-
return (ITestResult) new BinaryFormatter().Deserialize(deserializationStream);
50+
BinaryFormatter formatter = new BinaryFormatter();
51+
formatter.Binder = new TestResultSerializationBinder();
52+
return (ITestResult)formatter.Deserialize(deserializationStream);
4453
}
4554
}
4655

4756
public void AddProfilerTraces(IEnumerable<string> tracesIterator)
4857
{
58+
if (null == tracesIterator)
59+
{
60+
throw new ArgumentNullException(nameof(tracesIterator));
61+
}
62+
4963
foreach (var trace in tracesIterator)
5064
{
5165
this.ProfilerTraces.Add(trace);
@@ -71,5 +85,27 @@ public string InvokedMethodsSequence
7185
return string.Empty;
7286
}
7387
}
88+
89+
private class TestResultSerializationBinder : SerializationBinder
90+
{
91+
private static IEnumerable<string> s_supportedTypes = new List<string>()
92+
{
93+
typeof(List<MethodInvocationInfo>).FullName,
94+
typeof(List<string>).FullName,
95+
typeof(MethodInvocationInfo).FullName,
96+
typeof(TestResult).FullName
97+
};
98+
99+
public override Type BindToType(string assemblyName, string typeName)
100+
{
101+
if (s_supportedTypes.Contains(typeName, StringComparer.Ordinal))
102+
{
103+
// Tells serializer to use type from deserialized data.
104+
return null;
105+
}
106+
107+
throw new NotSupportedException("Attempted to deserialize unexpected type: " + typeName);
108+
}
109+
}
74110
}
75111
}

tests/ApplicationInsightsCompatibility/Intercept.Shared.Tests/InterceptDecorateTests.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,22 +71,22 @@ private object OnBegin(object thisObj)
7171

7272
public object OnEnd(object context, object retValue, object thisObj)
7373
{
74-
TestResult.InvokedMethods.Add(new MethodInvocationInfo
75-
{
76-
MethodName = "OnEnd",
77-
Arguments = new[] { context, retValue, thisObj }
78-
});
74+
MethodInvocationInfo info = new MethodInvocationInfo { MethodName = "OnEnd" };
75+
info.AddArgument(context);
76+
info.AddArgument(retValue);
77+
info.AddArgument(thisObj);
78+
TestResult.InvokedMethods.Add(info);
7979

8080
return retValue;
8181
}
8282

8383
public void OnException(object context, Exception exc, object thisObj)
8484
{
85-
TestResult.InvokedMethods.Add(new MethodInvocationInfo
86-
{
87-
MethodName = "OnException",
88-
Arguments = new[] { context, exc, thisObj }
89-
});
85+
MethodInvocationInfo info = new MethodInvocationInfo { MethodName = "OnException" };
86+
info.AddArgument(context);
87+
info.AddArgument(exc);
88+
info.AddArgument(thisObj);
89+
TestResult.InvokedMethods.Add(info);
9090
}
9191
}
9292

0 commit comments

Comments
 (0)