@@ -186,6 +186,116 @@ class SarifReportTest {
186
186
assert (codeFlowPhysicalLocations[0 ].region.startColumn == 5 )
187
187
}
188
188
189
+ @Test
190
+ fun testMinimizationRemovesDuplicates () {
191
+ mockUtMethodNames()
192
+
193
+ val mockUtExecution = Mockito .mock(UtExecution ::class .java, Mockito .RETURNS_DEEP_STUBS )
194
+ Mockito .`when `(mockUtExecution.result).thenReturn(UtImplicitlyThrownException (NullPointerException (), false ))
195
+
196
+ val testCases = listOf (
197
+ UtTestCase (mockUtMethod, listOf (mockUtExecution)),
198
+ UtTestCase (mockUtMethod, listOf (mockUtExecution)) // duplicate
199
+ )
200
+
201
+ val report = SarifReport (
202
+ testCases = testCases,
203
+ generatedTestsCode = " " ,
204
+ sourceFindingMain
205
+ ).createReport().toSarif()
206
+
207
+ assert (report.runs.first().results.size == 1 ) // no duplicates
208
+ }
209
+
210
+ @Test
211
+ fun testMinimizationDoesNotRemoveResultsWithDifferentRuleId () {
212
+ mockUtMethodNames()
213
+
214
+ val mockUtExecution1 = Mockito .mock(UtExecution ::class .java, Mockito .RETURNS_DEEP_STUBS )
215
+ val mockUtExecution2 = Mockito .mock(UtExecution ::class .java, Mockito .RETURNS_DEEP_STUBS )
216
+
217
+ // different ruleId's
218
+ Mockito .`when `(mockUtExecution1.result).thenReturn(UtImplicitlyThrownException (NullPointerException (), false ))
219
+ Mockito .`when `(mockUtExecution2.result).thenReturn(UtImplicitlyThrownException (ArithmeticException (), false ))
220
+
221
+ val testCases = listOf (
222
+ UtTestCase (mockUtMethod, listOf (mockUtExecution1)),
223
+ UtTestCase (mockUtMethod, listOf (mockUtExecution2)) // not a duplicate
224
+ )
225
+
226
+ val report = SarifReport (
227
+ testCases = testCases,
228
+ generatedTestsCode = " " ,
229
+ sourceFindingMain
230
+ ).createReport().toSarif()
231
+
232
+ assert (report.runs.first().results.size == 2 ) // no results have been removed
233
+ }
234
+
235
+ @Test
236
+ fun testMinimizationDoesNotRemoveResultsWithDifferentLocations () {
237
+ mockUtMethodNames()
238
+
239
+ val mockUtExecution1 = Mockito .mock(UtExecution ::class .java, Mockito .RETURNS_DEEP_STUBS )
240
+ val mockUtExecution2 = Mockito .mock(UtExecution ::class .java, Mockito .RETURNS_DEEP_STUBS )
241
+
242
+ // the same ruleId's
243
+ Mockito .`when `(mockUtExecution1.result).thenReturn(UtImplicitlyThrownException (NullPointerException (), false ))
244
+ Mockito .`when `(mockUtExecution2.result).thenReturn(UtImplicitlyThrownException (NullPointerException (), false ))
245
+
246
+ // different locations
247
+ Mockito .`when `(mockUtExecution1.path.lastOrNull()?.stmt?.javaSourceStartLineNumber).thenReturn(11 )
248
+ Mockito .`when `(mockUtExecution2.path.lastOrNull()?.stmt?.javaSourceStartLineNumber).thenReturn(22 )
249
+
250
+ val testCases = listOf (
251
+ UtTestCase (mockUtMethod, listOf (mockUtExecution1)),
252
+ UtTestCase (mockUtMethod, listOf (mockUtExecution2)) // not a duplicate
253
+ )
254
+
255
+ val report = SarifReport (
256
+ testCases = testCases,
257
+ generatedTestsCode = " " ,
258
+ sourceFindingMain
259
+ ).createReport().toSarif()
260
+
261
+ assert (report.runs.first().results.size == 2 ) // no results have been removed
262
+ }
263
+
264
+ @Test
265
+ fun testMinimizationChoosesShortestCodeFlow () {
266
+ mockUtMethodNames()
267
+
268
+ val mockNPE1 = Mockito .mock(NullPointerException ::class .java)
269
+ val mockNPE2 = Mockito .mock(NullPointerException ::class .java)
270
+
271
+ val mockUtExecution1 = Mockito .mock(UtExecution ::class .java, Mockito .RETURNS_DEEP_STUBS )
272
+ val mockUtExecution2 = Mockito .mock(UtExecution ::class .java, Mockito .RETURNS_DEEP_STUBS )
273
+
274
+ // the same ruleId's
275
+ Mockito .`when `(mockUtExecution1.result).thenReturn(UtImplicitlyThrownException (mockNPE1, false ))
276
+ Mockito .`when `(mockUtExecution2.result).thenReturn(UtImplicitlyThrownException (mockNPE2, false ))
277
+
278
+ // but different stack traces
279
+ val stackTraceElement1 = StackTraceElement (" Main" , " main" , " Main.java" , 3 )
280
+ val stackTraceElement2 = StackTraceElement (" Main" , " main" , " Main.java" , 7 )
281
+ Mockito .`when `(mockNPE1.stackTrace).thenReturn(arrayOf(stackTraceElement1))
282
+ Mockito .`when `(mockNPE2.stackTrace).thenReturn(arrayOf(stackTraceElement1, stackTraceElement2))
283
+
284
+ val testCases = listOf (
285
+ UtTestCase (mockUtMethod, listOf (mockUtExecution1)),
286
+ UtTestCase (mockUtMethod, listOf (mockUtExecution2)) // duplicate with a longer stack trace
287
+ )
288
+
289
+ val report = SarifReport (
290
+ testCases = testCases,
291
+ generatedTestsCode = " " ,
292
+ sourceFindingMain
293
+ ).createReport().toSarif()
294
+
295
+ assert (report.runs.first().results.size == 1 ) // no duplicates
296
+ assert (report.runs.first().results.first().totalCodeFlowLocations() == 1 ) // with a shorter stack trace
297
+ }
298
+
189
299
// internal
190
300
191
301
private val mockUtMethod = Mockito .mock(UtMethod ::class .java, Mockito .RETURNS_DEEP_STUBS )
0 commit comments