Skip to content

Commit 694a768

Browse files
authored
Fix incorrect analysis steps in the SARIF report (#249)
* #247 Fix incorrect analysis steps in the sarif report
1 parent 36aa0bd commit 694a768

File tree

2 files changed

+101
-49
lines changed

2 files changed

+101
-49
lines changed

utbot-framework/src/main/kotlin/org/utbot/sarif/SarifReport.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,10 +254,12 @@ class SarifReport(
254254
return null
255255

256256
// searching needed method call
257+
val publicMethodCallPattern = "$methodName("
258+
val privateMethodCallPattern = Regex("""$methodName.*\.invoke\(""") // using reflection
257259
val methodCallLineNumber = testsBodyLines
258260
.drop(testMethodStartsAt + 1) // for search after it
259261
.indexOfFirst { line ->
260-
line.contains("$methodName(")
262+
line.contains(publicMethodCallPattern) || line.contains(privateMethodCallPattern)
261263
}
262264
if (methodCallLineNumber == -1)
263265
return null

utbot-framework/src/test/kotlin/org/utbot/sarif/SarifReportTest.kt

Lines changed: 98 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class SarifReportTest {
1717
val actualReport = SarifReport(
1818
testCases = listOf(),
1919
generatedTestsCode = "",
20-
SourceFindingStrategyDefault("", "", "", "")
20+
sourceFindingEmpty
2121
).createReport()
2222

2323
assert(actualReport.isNotEmpty())
@@ -28,7 +28,7 @@ class SarifReportTest {
2828
val sarif = SarifReport(
2929
testCases = listOf(testCase),
3030
generatedTestsCode = "",
31-
SourceFindingStrategyDefault("", "", "", "")
31+
sourceFindingEmpty
3232
).createReport().toSarif()
3333

3434
assert(sarif.runs.first().results.isEmpty())
@@ -58,7 +58,7 @@ class SarifReportTest {
5858
val report = SarifReport(
5959
testCases = testCases,
6060
generatedTestsCode = "",
61-
SourceFindingStrategyDefault("", "", "", "")
61+
sourceFindingEmpty
6262
).createReport().toSarif()
6363

6464
assert(report.runs.first().results[0].message.text.contains("NullPointerException"))
@@ -74,23 +74,9 @@ class SarifReportTest {
7474
)
7575
Mockito.`when`(mockUtExecution.stateBefore.parameters).thenReturn(listOf())
7676
Mockito.`when`(mockUtExecution.path.lastOrNull()?.stmt?.javaSourceStartLineNumber).thenReturn(1337)
77-
Mockito.`when`(mockUtExecution.testMethodName).thenReturn("testMain")
77+
Mockito.`when`(mockUtExecution.testMethodName).thenReturn("testMain_ThrowArithmeticException")
7878

79-
val report = SarifReport(
80-
testCases = listOf(testCase),
81-
generatedTestsCode = """
82-
// comment for `startLine == 2` in related location
83-
public void testMain() throws Throwable {
84-
Main.main();
85-
}
86-
""".trimIndent(),
87-
SourceFindingStrategyDefault(
88-
sourceClassFqn = "Main",
89-
sourceFilePath = "src/Main.java",
90-
testsFilePath = "test/MainTest.java",
91-
projectRootPath = "."
92-
)
93-
).createReport().toSarif()
79+
val report = sarifReportMain.createReport().toSarif()
9480

9581
val result = report.runs.first().results.first()
9682
val location = result.locations.first().physicalLocation
@@ -99,7 +85,7 @@ class SarifReportTest {
9985
assert(location.artifactLocation.uri.contains("Main.java"))
10086
assert(location.region.startLine == 1337)
10187
assert(relatedLocation.artifactLocation.uri.contains("MainTest.java"))
102-
assert(relatedLocation.region.startLine == 2)
88+
assert(relatedLocation.region.startLine == 1)
10389
}
10490

10591
@Test
@@ -117,16 +103,7 @@ class SarifReportTest {
117103
)
118104
)
119105

120-
val report = SarifReport(
121-
testCases = listOf(testCase),
122-
generatedTestsCode = "",
123-
SourceFindingStrategyDefault(
124-
sourceClassFqn = "Main",
125-
sourceFilePath = "src/Main.java",
126-
testsFilePath = "test/MainTest.java",
127-
projectRootPath = "."
128-
)
129-
).createReport().toSarif()
106+
val report = sarifReportMain.createReport().toSarif()
130107

131108
val result = report.runs.first().results.first()
132109
assert(result.message.text.contains("227"))
@@ -135,39 +112,75 @@ class SarifReportTest {
135112
}
136113

137114
@Test
138-
fun testCorrectCodeFlow() {
115+
fun testCorrectCodeFlows() {
139116
mockUtMethodNames()
140117

141118
val uncheckedException = Mockito.mock(NullPointerException::class.java)
119+
val stackTraceElement = StackTraceElement("Main", "main", "Main.java", 17)
142120
Mockito.`when`(uncheckedException.stackTrace).thenReturn(
143-
Array(2) {
144-
StackTraceElement("Main", "main", "Main.java", 17)
145-
}
121+
Array(2) { stackTraceElement }
146122
)
147123

148124
Mockito.`when`(mockUtExecution.result).thenReturn(
149125
UtImplicitlyThrownException(uncheckedException, false)
150126
)
151127
Mockito.`when`(mockUtExecution.stateBefore.parameters).thenReturn(listOf())
152128

153-
val report = SarifReport(
154-
testCases = listOf(testCase),
155-
generatedTestsCode = "",
156-
SourceFindingStrategyDefault(
157-
sourceClassFqn = "Main",
158-
sourceFilePath = "src/Main.java",
159-
testsFilePath = "test/MainTest.java",
160-
projectRootPath = "."
161-
)
162-
).createReport().toSarif()
129+
val report = sarifReportMain.createReport().toSarif()
163130

164131
val result = report.runs.first().results.first().codeFlows.first().threadFlows.first().locations.map {
165132
it.location.physicalLocation
166133
}
167-
assert(result[0].artifactLocation.uri.contains("Main.java"))
168-
assert(result[0].region.startLine == 17)
169-
assert(result[1].artifactLocation.uri.contains("Main.java"))
170-
assert(result[1].region.startLine == 17)
134+
for (index in 0..1) {
135+
assert(result[index].artifactLocation.uri.contains("Main.java"))
136+
assert(result[index].region.startLine == 17)
137+
}
138+
}
139+
140+
@Test
141+
fun testCodeFlowsStartsWithMethodCall() {
142+
mockUtMethodNames()
143+
144+
val uncheckedException = Mockito.mock(NullPointerException::class.java)
145+
val stackTraceElement = StackTraceElement("Main", "main", "Main.java", 3)
146+
Mockito.`when`(uncheckedException.stackTrace).thenReturn(arrayOf(stackTraceElement))
147+
148+
Mockito.`when`(mockUtExecution.result).thenReturn(
149+
UtImplicitlyThrownException(uncheckedException, false)
150+
)
151+
Mockito.`when`(mockUtExecution.stateBefore.parameters).thenReturn(listOf())
152+
Mockito.`when`(mockUtExecution.testMethodName).thenReturn("testMain_ThrowArithmeticException")
153+
154+
val report = sarifReportMain.createReport().toSarif()
155+
156+
val codeFlowPhysicalLocations = report.runs[0].results[0].codeFlows[0].threadFlows[0].locations.map {
157+
it.location.physicalLocation
158+
}
159+
assert(codeFlowPhysicalLocations[0].artifactLocation.uri.contains("MainTest.java"))
160+
assert(codeFlowPhysicalLocations[0].region.startLine == 3)
161+
}
162+
163+
@Test
164+
fun testCodeFlowsStartsWithPrivateMethodCall() {
165+
mockUtMethodNames()
166+
167+
val uncheckedException = Mockito.mock(NullPointerException::class.java)
168+
val stackTraceElement = StackTraceElement("Main", "main", "Main.java", 3)
169+
Mockito.`when`(uncheckedException.stackTrace).thenReturn(arrayOf(stackTraceElement))
170+
171+
Mockito.`when`(mockUtExecution.result).thenReturn(
172+
UtImplicitlyThrownException(uncheckedException, false)
173+
)
174+
Mockito.`when`(mockUtExecution.stateBefore.parameters).thenReturn(listOf())
175+
Mockito.`when`(mockUtExecution.testMethodName).thenReturn("testMain_ThrowArithmeticException")
176+
177+
val report = sarifReportPrivateMain.createReport().toSarif()
178+
179+
val codeFlowPhysicalLocations = report.runs[0].results[0].codeFlows[0].threadFlows[0].locations.map {
180+
it.location.physicalLocation
181+
}
182+
assert(codeFlowPhysicalLocations[0].artifactLocation.uri.contains("MainTest.java"))
183+
assert(codeFlowPhysicalLocations[0].region.startLine == 4)
171184
}
172185

173186
// internal
@@ -184,4 +197,41 @@ class SarifReportTest {
184197
}
185198

186199
private fun String.toSarif(): Sarif = jacksonObjectMapper().readValue(this)
200+
201+
// constants
202+
203+
private val sourceFindingEmpty = SourceFindingStrategyDefault(
204+
sourceClassFqn = "",
205+
sourceFilePath = "",
206+
testsFilePath = "",
207+
projectRootPath = ""
208+
)
209+
210+
private val sourceFindingMain = SourceFindingStrategyDefault(
211+
sourceClassFqn = "Main",
212+
sourceFilePath = "src/Main.java",
213+
testsFilePath = "test/MainTest.java",
214+
projectRootPath = "."
215+
)
216+
217+
private val generatedTestsCodeMain = """
218+
public void testMain_ThrowArithmeticException() {
219+
Main main = new Main();
220+
main.main(0);
221+
}
222+
""".trimIndent()
223+
224+
private val generatedTestsCodePrivateMain = """
225+
public void testMain_ThrowArithmeticException() {
226+
Main main = new Main();
227+
// ...
228+
mainMethod.invoke(main, mainMethodArguments);
229+
}
230+
""".trimIndent()
231+
232+
private val sarifReportMain =
233+
SarifReport(listOf(testCase), generatedTestsCodeMain, sourceFindingMain)
234+
235+
private val sarifReportPrivateMain =
236+
SarifReport(listOf(testCase), generatedTestsCodePrivateMain, sourceFindingMain)
187237
}

0 commit comments

Comments
 (0)