Skip to content

Commit

Permalink
Merge pull request #20 from JetBrains/baseline-include-absent
Browse files Browse the repository at this point in the history
Support baseline-include-absent flag in baseline cli
  • Loading branch information
hybloid authored Apr 18, 2024
2 parents 1422f0b + 413ffca commit 5455852
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 100 deletions.
1 change: 1 addition & 0 deletions baseline-cli/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ plugins {
dependencies {
implementation(projects.sarif)
implementation(libs.gson)
implementation(libs.clikt)
}

application {
Expand Down
25 changes: 12 additions & 13 deletions baseline-cli/src/main/kotlin/BaselineCli.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,13 @@ import java.nio.file.Path
import java.nio.file.Paths

object BaselineCli {
fun process(map: Map<String, String>, cliPrinter: (String) -> Unit, errPrinter: (String) -> Unit): Int {
val sarifPath = map["sarifReport"]!!
val baselinePath = map["baselineReport"]
val failThreshold = map["failThreshold"]?.toIntOrNull()
if (!Files.exists(Paths.get(sarifPath))) {
fun process(options: BaselineOptions, cliPrinter: (String) -> Unit, errPrinter: (String) -> Unit): Int {
if (!Files.exists(Paths.get(options.sarifPath))) {
errPrinter("Please provide a valid SARIF report path")
return ERROR_EXIT
}
val sarifReport = try {
SarifUtil.readReport(Paths.get(sarifPath))
SarifUtil.readReport(Paths.get(options.sarifPath))
} catch (e: Exception) {
errPrinter("Error reading SARIF report: ${e.message}")
return ERROR_EXIT
Expand All @@ -30,18 +27,19 @@ object BaselineCli {
RuleUtil.findRuleDescriptor(sarifReport, id)?.shortDescription?.text ?: id
}
val printer = CommandLineResultsPrinter(simpleMemoize(resolveInspectionName), cliPrinter)
return if (baselinePath != null) {
return if (options.baselinePath != null) {
compareBaselineThreshold(
sarifReport,
Paths.get(sarifPath),
Paths.get(baselinePath),
failThreshold,
Paths.get(options.sarifPath),
Paths.get(options.baselinePath),
options.failThreshold,
options.includeAbsent,
printer,
cliPrinter,
errPrinter
)
} else {
compareThreshold(sarifReport, Paths.get(sarifPath), failThreshold, printer, cliPrinter, errPrinter)
compareThreshold(sarifReport, Paths.get(options.sarifPath), options.failThreshold, printer, cliPrinter, errPrinter)
}
}

Expand Down Expand Up @@ -91,6 +89,7 @@ object BaselineCli {
sarifPath: Path,
baselinePath: Path,
failThreshold: Int?,
includeAbsent: Boolean,
printer: CommandLineResultsPrinter,
cliPrinter: (String) -> Unit,
errPrinter: (String) -> Unit
Expand All @@ -106,8 +105,8 @@ object BaselineCli {
errPrinter("Error reading baseline report: ${e.message}")
return ERROR_EXIT
}
val baselineCalculation = BaselineCalculation.compare(sarifReport, baseline, BaselineCalculation.Options())
printer.printResultsWithBaselineState(sarifReport.runs.first().results, false)
val baselineCalculation = BaselineCalculation.compare(sarifReport, baseline, BaselineCalculation.Options(includeAbsent))
printer.printResultsWithBaselineState(sarifReport.runs.first().results, includeAbsent)
val invocation = processResultCount(baselineCalculation.newResults, failThreshold, cliPrinter, errPrinter)
sarifReport.runs.first().invocations = listOf(invocation)
SarifUtil.writeReport(sarifPath, sarifReport)
Expand Down
44 changes: 22 additions & 22 deletions baseline-cli/src/main/kotlin/Main.kt
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
import BaselineCli.process
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.options.flag
import com.github.ajalt.clikt.parameters.options.option
import com.github.ajalt.clikt.parameters.options.required
import com.github.ajalt.clikt.parameters.types.int
import kotlin.system.exitProcess

const val THRESHOLD_EXIT = 255
const val ERROR_EXIT = 1

fun main(args: Array<String>) {
val map = mutableMapOf<String, String>()

var i = 0
while (i < args.size) {
when (args[i]) {
"-r" -> map["sarifReport"] = args.getOrNull(i + 1) ?: printUsageAndExit()
"-b" -> map["baselineReport"] = args.getOrNull(i + 1) ?: printUsageAndExit()
"-f" -> map["failThreshold"] = args.getOrNull(i + 1) ?: printUsageAndExit()
}
i += 2
}

if (!map.contains("sarifReport")) {
printUsageAndExit()
class BaselineCommand : CliktCommand() {
private val sarifReport: String by option("-r", help = "Sarif report path").required()
private val baselineReport: String? by option("-b", help = "Baseline report path")
private val baselineIncludeAbsent: Boolean by option("-i", help = "Baseline include absent status").flag()
private val failThreshold: Int? by option("-f", help = "Fail threshold").int()
override fun run() {
val ret = process(
BaselineOptions(sarifReport, baselineReport, failThreshold, baselineIncludeAbsent),
{ println(it) },
{ System.err.println(it) })
exitProcess(ret)
}

val ret = process(map, { println(it) }, { System.err.println(it) })
exitProcess(ret)
}

fun printUsageAndExit(): Nothing {
println("Usage: -r <sarif_report> [-b <baseline_report>] [-f <fail_threshold>]")
exitProcess(1)
}
data class BaselineOptions(val sarifPath: String,
val baselinePath: String? = null,
val failThreshold: Int? = null,
val includeAbsent: Boolean = false)

fun main(args: Array<String>) = BaselineCommand().main(args)
105 changes: 40 additions & 65 deletions baseline-cli/src/test/kotlin/BaselineCliTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,18 @@ import kotlin.io.path.Path

class BaselineCliTest {

private val sarif = run {
val tmp = Files.createTempFile(null, ".sarif")
Files.copy(Path("src/test/resources/report.equal.sarif.json"), tmp, StandardCopyOption.REPLACE_EXISTING)
tmp.toFile().also(File::deleteOnExit).absolutePath
}
private val sarif = copySarifFromResources("report.equal.sarif.json")
private val emptySarif = copySarifFromResources("empty.sarif.json")
private val corruptedSarif = Path("src/test/resources/corrupted.sarif.json").toString()

private val stdout = StringBuilder()
private val stderr = StringBuilder()

@Test
fun `test when sarifReport does not exist in the provided path`() {
// Arrange
val map = mutableMapOf<String, String>().apply {
this["sarifReport"] = "nonExistentPath.sarif"
}

// Act
val exitCode = assertDoesNotThrow {
BaselineCli.process(map, stdout::append, stderr::append)
BaselineCli.process(BaselineOptions("nonExistentPath.sarif"), stdout::append, stderr::append)
}

// Assert
Expand All @@ -36,14 +29,9 @@ class BaselineCliTest {

@Test
fun `test when there is an error reading sarifReport`() {
// Arrange
val map = mutableMapOf<String, String>().apply {
this["sarifReport"] = Path("src/test/resources/corrupted.sarif.json").toString()
}

// Act
val exitCode = assertDoesNotThrow {
BaselineCli.process(map, stdout::append, stderr::append)
BaselineCli.process(BaselineOptions(corruptedSarif), stdout::append, stderr::append)
}

// Assert
Expand All @@ -53,15 +41,9 @@ class BaselineCliTest {

@Test
fun `test when baselineReport path is provided and file does not exist`() {
// Arrange
val map = mutableMapOf<String, String>().apply {
this["sarifReport"] = sarif
this["baselineReport"] = "nonExistentBaselineReport.sarif"
}

// Act
val exitCode = assertDoesNotThrow {
BaselineCli.process(map, stdout::append, stderr::append)
BaselineCli.process(BaselineOptions(sarif, "nonExistentBaselineReport.sarif"), stdout::append, stderr::append)
}

// Assert
Expand All @@ -71,15 +53,9 @@ class BaselineCliTest {

@Test
fun `test when there is a error reading baselineReport`() {
// Arrange
val map = mutableMapOf<String, String>().apply {
this["sarifReport"] = sarif
this["baselineReport"] = Path("src/test/resources/corrupted.sarif.json").toString()
}

// Act
val exitCode = assertDoesNotThrow {
BaselineCli.process(map, stdout::append, stderr::append)
BaselineCli.process(BaselineOptions(sarif, corruptedSarif), stdout::append, stderr::append)
}

// Assert
Expand All @@ -89,14 +65,9 @@ class BaselineCliTest {

@Test
fun `test when failThreshold is not present and results count is less than the failThreshold default value`() {
// Arrange
val map = mutableMapOf<String, String>().apply {
this["sarifReport"] = sarif
}

// Act
val exitCode = assertDoesNotThrow {
BaselineCli.process(map, stdout::append, stderr::append)
BaselineCli.process(BaselineOptions(sarif), stdout::append, stderr::append)
}

// Assert
Expand All @@ -106,15 +77,9 @@ class BaselineCliTest {

@Test
fun `test when failThreshold is provided and results count in sarifReport is more than failThreshold`() {
// Arrange
val map = mutableMapOf<String, String>().apply {
this["sarifReport"] = sarif
this["failThreshold"] = "0"
}

// Act
val exitCode = assertDoesNotThrow {
BaselineCli.process(map, stdout::append, stderr::append)
BaselineCli.process(BaselineOptions(sarif, failThreshold = 0), stdout::append, stderr::append)
}

// Assert
Expand All @@ -124,16 +89,9 @@ class BaselineCliTest {

@Test
fun `test when failThreshold is provided and newResults count in baselineCalculation is more than failThreshold`() {
// Arrange
val map = mutableMapOf<String, String>().apply {
this["sarifReport"] = sarif
this["baselineReport"] = Path("src/test/resources/empty.sarif.json").toString()
this["failThreshold"] = "1"
}

// Act
val exitCode = assertDoesNotThrow {
BaselineCli.process(map, stdout::append, stderr::append)
BaselineCli.process(BaselineOptions(sarif, emptySarif, failThreshold = 1), stdout::append, stderr::append)
}

// Assert
Expand All @@ -143,15 +101,9 @@ class BaselineCliTest {

@Test
fun `test when failThreshold is not provided or is less than newResults count in baselineCalculation`() {
// Arrange
val map = mutableMapOf<String, String>().apply {
this["sarifReport"] = sarif
this["baselineReport"] = Path("src/test/resources/empty.sarif.json").toString()
}

// Act
val exitCode = assertDoesNotThrow {
BaselineCli.process(map, stdout::append, stderr::append)
BaselineCli.process(BaselineOptions(sarif, emptySarif), stdout::append, stderr::append)
}

// Assert
Expand All @@ -161,17 +113,40 @@ class BaselineCliTest {

@Test
fun `test when rule description is available`() {
// Arrange
val map = mutableMapOf<String, String>().apply {
this["sarifReport"] = Path("src/test/resources/report.with-description.sarif.json").toString()
}

// Act
assertDoesNotThrow { BaselineCli.process(map, stdout::append, stderr::append) }
assertDoesNotThrow { BaselineCli.process(BaselineOptions(Path("src/test/resources/report.with-description.sarif.json").toString()), stdout::append, stderr::append) }

// Assert
assertTrue(stdout.contains("Result of method call ignored")) // the unresolved ID
assertFalse(stdout.contains("ResultOfMethodCallIgnored")) // the unresolved ID
}

@Test
fun `test include absent true`() {
// Act
assertDoesNotThrow { BaselineCli.process(BaselineOptions(emptySarif, sarif, includeAbsent = true), stdout::append, stderr::append) }

// Assert
assertTrue(stdout.contains("ABSENT: 2"))
val content = File(emptySarif).readText(charset("UTF-8"))
assertTrue(content.contains("absent"))
}

@Test
fun `test include absent false`() {
// Act
assertDoesNotThrow { BaselineCli.process(BaselineOptions(emptySarif, sarif, includeAbsent = false), stdout::append, stderr::append) }

// Assert
assertFalse(stdout.contains("ABSENT: 2"))
val content = File(emptySarif).readText(charset("UTF-8"))
assertFalse(content.contains("absent"))
}


private fun copySarifFromResources(name: String) = run {
val tmp = Files.createTempFile(null, ".sarif")
Files.copy(Path("src/test/resources/$name"), tmp, StandardCopyOption.REPLACE_EXISTING)
tmp.toFile().also(File::deleteOnExit).absolutePath
}
}
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
dokka = "1.9.10"
shadow = "8.1.1"
gson = "2.8.9"
clikt = "4.3.0"

[plugins]
shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" }
Expand All @@ -11,3 +12,4 @@ dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }
[libraries]
gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
dokkaBase = { module = "org.jetbrains.dokka:dokka-base", version.ref = "dokka" }
clikt = { module = "com.github.ajalt.clikt:clikt", version.ref = "clikt" }
2 changes: 2 additions & 0 deletions qodana.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ exclude:
- name: All
paths:
- sarif/src/test/resources/
dependencyIgnores:
- name: "colormath-jvm"

0 comments on commit 5455852

Please sign in to comment.