Skip to content

Commit

Permalink
feat: Import coverage reports correctly when the tested file doesn't …
Browse files Browse the repository at this point in the history
…start with the executed code (#156)

This fixes the following limitations documented in the utPLSQL docs:
- Each database (source-code) object is stored in an individual file. Package/type specification is kept separate from its body.
- Each file contains representation of database object "as is". No extra commands (like set echo off ALTER SESSION SET PLSQL_CCFLAGS = 'debug:TRUE';) or blank lines are present before CREATE TYPE,CREATE TYPE etc.

With this changes, it's possible to import the coverage correctly even in these situations
  • Loading branch information
felipebz committed May 23, 2024
1 parent b75eecf commit c7e952d
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ data class MappedObject(
val objectType: AstNodeType,
val fileType: PlSqlFile.Type,
val path: Path,
val inputFile: InputFile
val inputFile: InputFile,
val firstLine: Int = -1,
val lastLine: Int = -1
) {
val isMain: Boolean
get() = fileType === PlSqlFile.Type.MAIN
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ class ObjectLocator {
val plSqlFile = it.plSqlFile as SonarQubePlSqlFile? ?: return@map null
val identifier = it.identifier ?: return@map null
val type = it.type ?: return@map null
MappedObject(identifier, type, plSqlFile.type(), plSqlFile.path(), plSqlFile.inputFile)
val firstLine = it.tree?.tokenLine ?: return@map null
val lastLine = it.tree?.lastTokenOrNull?.endLine ?: return@map null
MappedObject(identifier, type, plSqlFile.type(), plSqlFile.path(), plSqlFile.inputFile, firstLine, lastLine)
}.filterNotNull()

fun setScope(scope: Scope) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ class CoverageResultImporter(private val objectLocator: ObjectLocator,
var inputFile = context.fileSystem()
.inputFile(context.fileSystem().predicates().hasPath(filePath))

var lineOffset = 0

if (inputFile == null) {
val objectType = when (filePath.substringBeforeLast(' ')) {
"package body" -> PlSqlGrammar.CREATE_PACKAGE_BODY
Expand All @@ -53,16 +55,19 @@ class CoverageResultImporter(private val objectLocator: ObjectLocator,
}
val objectName = filePath.substringAfterLast('.')

val mappedFile = objectLocator.findMainObject(objectName, objectType)

inputFile = mappedFile?.inputFile
val mappedObject = objectLocator.findMainObject(objectName, objectType)
if (mappedObject != null) {
inputFile = mappedObject.inputFile
lineOffset = mappedObject.firstLine - 1
}
}

if (inputFile != null) {
val newCoverage = context.newCoverage().onFile(inputFile)

file.linesToCover?.forEach { line ->
newCoverage.lineHits(line.lineNumber, if (line.covered) 1 else 0)
val lineNumber = line.lineNumber + lineOffset
newCoverage.lineHits(lineNumber, if (line.covered) 1 else 0)

val branchesToCover = line.branchesToCover
val coveredBranches = line.coveredBranches ?: 0
Expand All @@ -72,7 +77,7 @@ class CoverageResultImporter(private val objectLocator: ObjectLocator,
"${line.lineNumber} for file \"$filePath\""
}

newCoverage.conditions(line.lineNumber, branchesToCover, coveredBranches)
newCoverage.conditions(lineNumber, branchesToCover, coveredBranches)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,17 +145,25 @@ class UtPlSqlSensorTest {
context.fileSystem().add(mainFile)

whenever(objectLocator.findMainObject(any(), any())).thenReturn(
MappedObject("", PlSqlGrammar.CREATE_FUNCTION, PlSqlFile.Type.MAIN, mainFile.path(), mainFile)
MappedObject(
identifier = "",
objectType = PlSqlGrammar.CREATE_FUNCTION,
fileType = PlSqlFile.Type.MAIN,
path = mainFile.path(),
inputFile = mainFile,
firstLine = 3,
lastLine = 10
)
)

context.settings().setProperty(UtPlSqlSensor.COVERAGE_REPORT_PATH_KEY, "coverage-report-without-paths.xml")
sensor.execute(context)

val key = mainFile.key()
assertThat(context.lineHits(key, 2)).isOne()
assertThat(context.lineHits(key, 4)).isOne()
assertThat(context.lineHits(key, 5)).isOne()
assertThat(context.lineHits(key, 6)).isOne()
assertThat(context.lineHits(key, 7)).isOne()
assertThat(context.lineHits(key, 9)).isOne()
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* comment before the code
so the lines in the coverage report don't match the file */
create or replace function betwnstr(a_string varchar2, a_start_pos integer, a_end_pos integer) return varchar2 is
l_start_pos pls_integer := a_start_pos;
begin
Expand Down

0 comments on commit c7e952d

Please sign in to comment.