2
2
using Xunit . Abstractions ;
3
3
using System . Text . Json ;
4
4
using CliWrap ;
5
+ using Xunit . Sdk ;
5
6
6
7
namespace Workleap . DotNet . CodingStandards . Tests . Helpers ;
7
8
@@ -46,14 +47,27 @@ public void AddFile(string relativePath, string content)
46
47
File . WriteAllText ( this . _directory . GetPath ( relativePath ) , content ) ;
47
48
}
48
49
49
- public void AddCsprojFile ( Dictionary < string , string > ? properties = null )
50
+ public void AddCsprojFile ( Dictionary < string , string > ? properties = null , Dictionary < string , string > ? packageReferences = null )
50
51
{
51
- var element = new XElement ( "PropertyGroup" ) ;
52
+ var propertyElement = new XElement ( "PropertyGroup" ) ;
52
53
if ( properties != null )
53
54
{
54
55
foreach ( var prop in properties )
55
56
{
56
- element . Add ( new XElement ( prop . Key ) , prop . Value ) ;
57
+ propertyElement . Add ( new XElement ( prop . Key ) , prop . Value ) ;
58
+ }
59
+ }
60
+
61
+ var referencesElement = new XElement ( "ItemGroup" ) ;
62
+ if ( packageReferences != null )
63
+ {
64
+ foreach ( var reference in packageReferences )
65
+ {
66
+ var packageReference = new XElement ( "PackageReference" ) ;
67
+ packageReference . SetAttributeValue ( "Include" , reference . Key ) ;
68
+ packageReference . SetAttributeValue ( "Version" , reference . Value ) ;
69
+
70
+ referencesElement . Add ( packageReference ) ;
57
71
}
58
72
}
59
73
@@ -66,11 +80,12 @@ public void AddCsprojFile(Dictionary<string, string>? properties = null)
66
80
<Nullable>enable</Nullable>
67
81
<ErrorLog>{ SarifFileName } ,version=2.1</ErrorLog>
68
82
</PropertyGroup>
69
- { element }
83
+ { propertyElement }
70
84
71
85
<ItemGroup>
72
86
<PackageReference Include="Workleap.DotNet.CodingStandards" Version="*" />
73
87
</ItemGroup>
88
+ { referencesElement }
74
89
</Project>
75
90
""" ;
76
91
@@ -92,9 +107,52 @@ public async Task<SarifFile> BuildAndGetOutput(string[]? buildArguments = null)
92
107
93
108
var bytes = await File . ReadAllBytesAsync ( this . _directory . GetPath ( SarifFileName ) ) ;
94
109
var sarif = JsonSerializer . Deserialize < SarifFile > ( bytes ) ?? throw new InvalidOperationException ( "The sarif file is invalid" ) ;
110
+
111
+ this . AppendAdditionalResult ( sarif ) ;
112
+
95
113
this . _testOutputHelper . WriteLine ( "Sarif result:\n " + string . Join ( "\n " , sarif . AllResults ( ) . Select ( r => r . ToString ( ) ) ) ) ;
96
114
return sarif ;
97
115
}
98
116
99
117
public void Dispose ( ) => this . _directory . Dispose ( ) ;
118
+
119
+ private void AppendAdditionalResult ( SarifFile sarifFile )
120
+ {
121
+ if ( this . _testOutputHelper is not TestOutputHelper testOutputHelper || sarifFile . Runs == null )
122
+ {
123
+ return ;
124
+ }
125
+
126
+ var outputLines = testOutputHelper . Output . Split ( Environment . NewLine ) ;
127
+ var customRunResults = new List < SarifFileRunResult > ( ) ;
128
+
129
+ // These rules (for nuget package vulnerability) are not parsed in the sarif file automatically
130
+ // See https://learn.microsoft.com/en-us/nuget/reference/errors-and-warnings/nu1901-nu1904
131
+ var scannedRules = new List < string > { "NU1901" , "NU1902" , "NU1903" , "NU1904" }
132
+ . ToDictionary ( x => x , x => $ "{ x } :") ;
133
+
134
+ foreach ( var outputLine in outputLines )
135
+ {
136
+ foreach ( var scannedRule in scannedRules )
137
+ {
138
+ var scannedRuleIndex = outputLine . IndexOf ( scannedRule . Value , StringComparison . OrdinalIgnoreCase ) ;
139
+ if ( scannedRuleIndex == - 1 )
140
+ {
141
+ continue ;
142
+ }
143
+
144
+ var previousColonIndex = outputLine . LastIndexOf ( ':' , scannedRuleIndex ) ;
145
+ var ruleLevel = outputLine . Substring ( previousColonIndex + 1 , scannedRuleIndex - previousColonIndex - 1 ) . Trim ( ) ;
146
+
147
+ var message = outputLine [ ( scannedRuleIndex + scannedRule . Value . Length + 1 ) ..] ;
148
+ customRunResults . Add ( new SarifFileRunResult { Level = ruleLevel , RuleId = scannedRule . Key , Message = new SarifFileRunResultMessage { Text = message } } ) ;
149
+ }
150
+ }
151
+
152
+ var distinctRules = customRunResults
153
+ . DistinctBy ( x => new { x . RuleId , x . Level } )
154
+ . ToArray ( ) ;
155
+
156
+ sarifFile . Runs = sarifFile . Runs . Append ( new SarifFileRun { Results = distinctRules } ) . ToArray ( ) ;
157
+ }
100
158
}
0 commit comments