From ca1aef4461d8c46f24118c3e6561d411c53af0ee Mon Sep 17 00:00:00 2001 From: Martin Nonnenmacher Date: Thu, 11 Jul 2024 19:11:44 +0200 Subject: [PATCH] refactor(model)!: Inline `AdvisorRecord` with `AdvisorRun` The `AdvisorRecord` was only a holder for the map of advisor results per package. Inline it with `AdvisorRun` to reduce nesting in the data structures, similar to how `ScanRecord` was inlined with `ScannerRun` in 9d9a449. Signed-off-by: Martin Nonnenmacher --- advisor/src/main/kotlin/Advisor.kt | 5 +- advisor/src/test/kotlin/AdvisorTest.kt | 4 +- .../funTest/assets/semver4j-ort-result.yml | 31 ++-- evaluator/src/main/kotlin/PackageRule.kt | 4 +- evaluator/src/test/kotlin/TestData.kt | 47 +++--- model/src/main/kotlin/AdvisorRecord.kt | 143 ------------------ model/src/main/kotlin/AdvisorRun.kt | 116 +++++++++++++- model/src/main/kotlin/OrtResult.kt | 6 +- ...isorRecordTest.kt => AdvisorResultTest.kt} | 67 ++++---- .../advisor/src/main/kotlin/AdvisorCommand.kt | 4 +- .../funTest/assets/reporter-test-input.yml | 69 +++++---- .../src/main/kotlin/EvaluatedModelMapper.kt | 2 +- .../kotlin/FreemarkerTemplateProcessor.kt | 14 +- .../funTest/assets/reporter-test-input.yml | 69 +++++---- .../funTest/assets/reporter-test-input.yml | 69 +++++---- reporter/src/testFixtures/kotlin/TestData.kt | 15 +- utils/test/src/main/kotlin/Utils.kt | 3 +- 17 files changed, 311 insertions(+), 357 deletions(-) delete mode 100644 model/src/main/kotlin/AdvisorRecord.kt rename model/src/test/kotlin/{AdvisorRecordTest.kt => AdvisorResultTest.kt} (85%) diff --git a/advisor/src/main/kotlin/Advisor.kt b/advisor/src/main/kotlin/Advisor.kt index bf5c01cc05b5e..c65d993c51778 100644 --- a/advisor/src/main/kotlin/Advisor.kt +++ b/advisor/src/main/kotlin/Advisor.kt @@ -27,7 +27,6 @@ import kotlinx.coroutines.withContext import org.apache.logging.log4j.kotlin.logger -import org.ossreviewtoolkit.model.AdvisorRecord import org.ossreviewtoolkit.model.AdvisorResult import org.ossreviewtoolkit.model.AdvisorRun import org.ossreviewtoolkit.model.Identifier @@ -106,10 +105,8 @@ class Advisor( } } - val advisorRecord = AdvisorRecord(results) - val endTime = Instant.now() - AdvisorRun(startTime, endTime, Environment(), config, advisorRecord) + AdvisorRun(startTime, endTime, Environment(), config, results) } } diff --git a/advisor/src/test/kotlin/AdvisorTest.kt b/advisor/src/test/kotlin/AdvisorTest.kt index 50b2e389fcfb5..a121c844eec3f 100644 --- a/advisor/src/test/kotlin/AdvisorTest.kt +++ b/advisor/src/test/kotlin/AdvisorTest.kt @@ -63,7 +63,7 @@ class AdvisorTest : WordSpec({ val result = advisor.advise(originResult) result.advisor shouldNotBeNull { - results.advisorResults should beEmpty() + results should beEmpty() } coVerify(exactly = 0) { @@ -104,7 +104,7 @@ class AdvisorTest : WordSpec({ val result = advisor.advise(originResult) result.advisor shouldNotBeNull { - results.advisorResults shouldBe expectedResults + results shouldBe expectedResults } } } diff --git a/cli/src/funTest/assets/semver4j-ort-result.yml b/cli/src/funTest/assets/semver4j-ort-result.yml index 7f06ecc1c2915..db8eb45400aef 100644 --- a/cli/src/funTest/assets/semver4j-ort-result.yml +++ b/cli/src/funTest/assets/semver4j-ort-result.yml @@ -381,22 +381,21 @@ advisor: secrets: username: "user" results: - advisor_results: - Maven:junit:junit:4.12: - - advisor: - name: "NexusIQ" - capabilities: - - "VULNERABILITIES" - summary: - start_time: "2021-04-29T14:54:17.322191Z" - end_time: "2021-04-29T14:54:18.966672Z" - vulnerabilities: - - id: "CVE-2020-15250" - references: - - url: "http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-15250" - scoring_system: "CVSS2" - severity: "5.5" - severity_rating: "MEDIUM" + Maven:junit:junit:4.12: + - advisor: + name: "NexusIQ" + capabilities: + - "VULNERABILITIES" + summary: + start_time: "2021-04-29T14:54:17.322191Z" + end_time: "2021-04-29T14:54:18.966672Z" + vulnerabilities: + - id: "CVE-2020-15250" + references: + - url: "http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-15250" + scoring_system: "CVSS2" + severity: "5.5" + severity_rating: "MEDIUM" evaluator: null resolved_configuration: package_curations: diff --git a/evaluator/src/main/kotlin/PackageRule.kt b/evaluator/src/main/kotlin/PackageRule.kt index c9ab3e86c499e..a488d66133cf0 100644 --- a/evaluator/src/main/kotlin/PackageRule.kt +++ b/evaluator/src/main/kotlin/PackageRule.kt @@ -76,7 +76,7 @@ open class PackageRule( override fun matches(): Boolean { val run = ruleSet.ortResult.advisor ?: return false - return run.results.getVulnerabilities(pkg.metadata.id).isNotEmpty() + return run.getVulnerabilities(pkg.metadata.id).isNotEmpty() } } } @@ -92,7 +92,7 @@ open class PackageRule( override fun matches(): Boolean { val run = ruleSet.ortResult.advisor ?: return false - return run.results.getVulnerabilities(pkg.metadata.id).asSequence() + return run.getVulnerabilities(pkg.metadata.id).asSequence() .filter { vulnerability -> !ruleSet.resolutionProvider.isResolved(vulnerability) } .flatMap { it.references } .filter { reference -> reference.scoringSystem == scoringSystem } diff --git a/evaluator/src/test/kotlin/TestData.kt b/evaluator/src/test/kotlin/TestData.kt index 45d72b0c61b56..16b2f5e12cbe1 100644 --- a/evaluator/src/test/kotlin/TestData.kt +++ b/evaluator/src/test/kotlin/TestData.kt @@ -24,7 +24,6 @@ import java.time.Instant import org.ossreviewtoolkit.model.AdvisorCapability import org.ossreviewtoolkit.model.AdvisorDetails -import org.ossreviewtoolkit.model.AdvisorRecord import org.ossreviewtoolkit.model.AdvisorResult import org.ossreviewtoolkit.model.AdvisorRun import org.ossreviewtoolkit.model.AdvisorSummary @@ -221,31 +220,29 @@ val ortResult = OrtResult( endTime = Instant.EPOCH, environment = Environment(), config = AdvisorConfiguration(), - results = AdvisorRecord( - advisorResults = mapOf( - packageWithVulnerabilities.id to listOf( - AdvisorResult( - advisor = AdvisorDetails("Advisor", enumSetOf(AdvisorCapability.VULNERABILITIES)), - summary = AdvisorSummary(startTime = Instant.EPOCH, endTime = Instant.EPOCH), - vulnerabilities = listOf( - Vulnerability( - id = "CVE-2021-critical", - references = listOf( - VulnerabilityReference( - url = URI("https://oss-review-toolkit.org"), - scoringSystem = "CVSS3", - severity = "9.0" - ) + results = mapOf( + packageWithVulnerabilities.id to listOf( + AdvisorResult( + advisor = AdvisorDetails("Advisor", enumSetOf(AdvisorCapability.VULNERABILITIES)), + summary = AdvisorSummary(startTime = Instant.EPOCH, endTime = Instant.EPOCH), + vulnerabilities = listOf( + Vulnerability( + id = "CVE-2021-critical", + references = listOf( + VulnerabilityReference( + url = URI("https://oss-review-toolkit.org"), + scoringSystem = "CVSS3", + severity = "9.0" ) - ), - Vulnerability( - id = "CVE-2021-trivial", - references = listOf( - VulnerabilityReference( - url = URI("https://oss-review-toolkit.org"), - scoringSystem = "CVSS3", - severity = "2.0" - ) + ) + ), + Vulnerability( + id = "CVE-2021-trivial", + references = listOf( + VulnerabilityReference( + url = URI("https://oss-review-toolkit.org"), + scoringSystem = "CVSS3", + severity = "2.0" ) ) ) diff --git a/model/src/main/kotlin/AdvisorRecord.kt b/model/src/main/kotlin/AdvisorRecord.kt deleted file mode 100644 index 6adbe522fa899..0000000000000 --- a/model/src/main/kotlin/AdvisorRecord.kt +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2020 The ORT Project Authors (see ) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * License-Filename: LICENSE - */ - -package org.ossreviewtoolkit.model - -import com.fasterxml.jackson.annotation.JsonIgnore -import com.fasterxml.jackson.annotation.JsonPropertyOrder - -import org.ossreviewtoolkit.model.vulnerabilities.Vulnerability - -/** - * Type alias for a function that allows filtering of [AdvisorResult]s. - */ -typealias AdvisorResultFilter = (AdvisorResult) -> Boolean - -/** - * A record of a single run of the advisor tool, containing the input and the [Vulnerability] for every checked package. - */ -data class AdvisorRecord( - /** - * The [AdvisorResult]s for all [Package]s. - */ - @JsonPropertyOrder(alphabetic = true) - val advisorResults: Map> -) { - companion object { - /** - * A filter for [AdvisorResult]s that matches only results that contain vulnerabilities. - */ - val RESULTS_WITH_VULNERABILITIES: AdvisorResultFilter = { it.vulnerabilities.isNotEmpty() } - - /** - * A filter for [AdvisorResult]s that matches only results that contain defects. - */ - val RESULTS_WITH_DEFECTS: AdvisorResultFilter = { it.defects.isNotEmpty() } - - /** - * Return a filter for [AdvisorResult]s that contain issues. Match only results with an issue whose severity - * is greater or equal than [minSeverity]. Often, issues are only relevant for certain types of advisors. For - * instance, when processing vulnerability information, it is not of interest if an advisor for defects had - * encountered problems. Therefore, support an optional filter for a [capability] of the advisor that produced - * a result. - */ - fun resultsWithIssues( - minSeverity: Severity = Severity.HINT, - capability: AdvisorCapability? = null - ): AdvisorResultFilter = - { result -> - (capability == null || capability in result.advisor.capabilities) && result.summary.issues.any { - it.severity >= minSeverity - } - } - } - - @JsonIgnore - fun getIssues(): Map> = - buildMap> { - advisorResults.forEach { (id, results) -> - results.forEach { result -> - if (result.summary.issues.isNotEmpty()) { - getOrPut(id) { mutableSetOf() } += result.summary.issues - } - } - } - } - - /** - * Return a map of all [Package]s and the associated [Vulnerabilities][Vulnerability]. - */ - @JsonIgnore - fun getVulnerabilities(): Map> = - advisorResults.mapValues { (_, results) -> - results.flatMap { it.vulnerabilities }.mergeVulnerabilities() - } - - /** - * Return a list with all [Vulnerability] objects that have been found for the given [package][pkgId]. Results - * from different advisors are merged if necessary. - */ - fun getVulnerabilities(pkgId: Identifier): List = - getFindings(pkgId) { it.vulnerabilities }.mergeVulnerabilities() - - /** - * Return a list with all [Defect] objects that have been found for the given [package][pkgId]. If there are - * results from different advisors, a union list is constructed. No merging is done, as it is expected that the - * results from different advisors cannot be combined. - */ - fun getDefects(pkgId: Identifier): List = getFindings(pkgId) { it.defects } - - /** - * Apply the given [filter] to the results stored in this record and return a map with the results that pass the - * filter. When processing advisor results, often specific criteria are relevant, e.g. whether security - * vulnerabilities were found or certain issues were detected. Using this function, it is easy to filter out only - * those results matching such criteria. - */ - fun filterResults(filter: AdvisorResultFilter): Map> = - advisorResults.mapNotNull { (id, results) -> - results.filter(filter).takeIf { it.isNotEmpty() }?.let { id to it } - }.toMap() - - /** - * Helper function to obtain the findings of type [T] for the given [package][pkgId] using a [selector] function - * to extract the desired field. - */ - private fun getFindings(pkgId: Identifier, selector: (AdvisorResult) -> List): List = - advisorResults[pkgId].orEmpty().flatMap(selector) -} - -/** - * Merge this collection of [Vulnerability] objects by combining vulnerabilities with the same ID and merging their - * references. Other [Vulnerability] properties are taken from the first object which has any such property set. - */ -private fun Collection.mergeVulnerabilities(): List { - val vulnerabilitiesById = groupBy { it.id } - return vulnerabilitiesById.map { it.value.mergeReferences() } -} - -/** - * Merge this (non-empty) collection of [Vulnerability] objects (which are expected to have the same ID) to a single - * [Vulnerability] that contains all the references from the original vulnerabilities (with duplicates removed). Other - * [Vulnerability] properties are taken from the first object which has any such property set. - */ -private fun Collection.mergeReferences(): Vulnerability { - val references = flatMapTo(mutableSetOf()) { it.references } - val entry = find { it.summary != null || it.description != null } ?: first() - return entry.copy(references = references.toList()) -} diff --git a/model/src/main/kotlin/AdvisorRun.kt b/model/src/main/kotlin/AdvisorRun.kt index 5126f91996776..32d68571ec21d 100644 --- a/model/src/main/kotlin/AdvisorRun.kt +++ b/model/src/main/kotlin/AdvisorRun.kt @@ -19,11 +19,20 @@ package org.ossreviewtoolkit.model +import com.fasterxml.jackson.annotation.JsonIgnore +import com.fasterxml.jackson.annotation.JsonPropertyOrder + import java.time.Instant import org.ossreviewtoolkit.model.config.AdvisorConfiguration +import org.ossreviewtoolkit.model.vulnerabilities.Vulnerability import org.ossreviewtoolkit.utils.ort.Environment +/** + * Type alias for a function that allows filtering of [AdvisorResult]s. + */ +typealias AdvisorResultFilter = (AdvisorResult) -> Boolean + /** * The summary of a single run of the advisor. */ @@ -49,9 +58,10 @@ data class AdvisorRun( val config: AdvisorConfiguration, /** - * The result of this run. + * The [AdvisorResult]s for all [Package]s. */ - val results: AdvisorRecord + @JsonPropertyOrder(alphabetic = true) + val results: Map> ) { companion object { val EMPTY = AdvisorRun( @@ -59,7 +69,107 @@ data class AdvisorRun( endTime = Instant.EPOCH, environment = Environment(), config = AdvisorConfiguration(), - results = AdvisorRecord(emptyMap()) + results = emptyMap() ) + + /** + * A filter for [AdvisorResult]s that matches only results that contain vulnerabilities. + */ + val RESULTS_WITH_VULNERABILITIES: AdvisorResultFilter = { it.vulnerabilities.isNotEmpty() } + + /** + * A filter for [AdvisorResult]s that matches only results that contain defects. + */ + val RESULTS_WITH_DEFECTS: AdvisorResultFilter = { it.defects.isNotEmpty() } + + /** + * Return a filter for [AdvisorResult]s that contain issues. Match only results with an issue whose severity + * is greater or equal than [minSeverity]. Often, issues are only relevant for certain types of advisors. For + * instance, when processing vulnerability information, it is not of interest if an advisor for defects had + * encountered problems. Therefore, support an optional filter for a [capability] of the advisor that produced + * a result. + */ + fun resultsWithIssues( + minSeverity: Severity = Severity.HINT, + capability: AdvisorCapability? = null + ): AdvisorResultFilter = + { result -> + (capability == null || capability in result.advisor.capabilities) && result.summary.issues.any { + it.severity >= minSeverity + } + } } + + @JsonIgnore + fun getIssues(): Map> = + buildMap> { + results.forEach { (id, results) -> + results.forEach { result -> + if (result.summary.issues.isNotEmpty()) { + getOrPut(id) { mutableSetOf() } += result.summary.issues + } + } + } + } + + /** + * Return a map of all [Package]s and the associated [Vulnerabilities][Vulnerability]. + */ + @JsonIgnore + fun getVulnerabilities(): Map> = + results.mapValues { (_, results) -> + results.flatMap { it.vulnerabilities }.mergeVulnerabilities() + } + + /** + * Return a list with all [Vulnerability] objects that have been found for the given [package][pkgId]. Results + * from different advisors are merged if necessary. + */ + fun getVulnerabilities(pkgId: Identifier): List = + getFindings(pkgId) { it.vulnerabilities }.mergeVulnerabilities() + + /** + * Return a list with all [Defect] objects that have been found for the given [package][pkgId]. If there are + * results from different advisors, a union list is constructed. No merging is done, as it is expected that the + * results from different advisors cannot be combined. + */ + fun getDefects(pkgId: Identifier): List = getFindings(pkgId) { it.defects } + + /** + * Apply the given [filter] to the results stored in this record and return a map with the results that pass the + * filter. When processing advisor results, often specific criteria are relevant, e.g. whether security + * vulnerabilities were found or certain issues were detected. Using this function, it is easy to filter out only + * those results matching such criteria. + */ + fun filterResults(filter: AdvisorResultFilter): Map> = + results.mapNotNull { (id, results) -> + results.filter(filter).takeIf { it.isNotEmpty() }?.let { id to it } + }.toMap() + + /** + * Helper function to obtain the findings of type [T] for the given [package][pkgId] using a [selector] function + * to extract the desired field. + */ + private fun getFindings(pkgId: Identifier, selector: (AdvisorResult) -> List): List = + results[pkgId].orEmpty().flatMap(selector) +} + +/** + * Merge this collection of [Vulnerability] objects by combining vulnerabilities with the same ID and merging their + * references. Other [Vulnerability] properties are taken from the first object which has any such property set. + */ +private fun Collection.mergeVulnerabilities(): List { + val vulnerabilitiesById = groupBy { it.id } + return vulnerabilitiesById.map { it.value.mergeReferences() } +} + +/** + * Merge this (non-empty) collection of [Vulnerability] objects (which are expected to have the same ID) to a single + * [Vulnerability] that contains all the references from the original vulnerabilities (with duplicates removed). Other + * [Vulnerability] properties are taken from the first object which has any such property set. + */ +private fun Collection.mergeReferences(): Vulnerability { + val references = flatMapTo(mutableSetOf()) { it.references } + val entry = find { it.summary != null || it.description != null } ?: first() + return entry.copy(references = references.toList()) } diff --git a/model/src/main/kotlin/OrtResult.kt b/model/src/main/kotlin/OrtResult.kt index 1a8e400b416ce..c61599c63b7a9 100644 --- a/model/src/main/kotlin/OrtResult.kt +++ b/model/src/main/kotlin/OrtResult.kt @@ -110,7 +110,7 @@ data class OrtResult( val dependencyNavigator: DependencyNavigator by lazy { CompatibilityDependencyNavigator.create(this) } private val advisorResultsById: Map> by lazy { - advisor?.results?.advisorResults.orEmpty() + advisor?.results.orEmpty() } /** @@ -317,7 +317,7 @@ data class OrtResult( omitResolved: Boolean = false, minSeverity: Severity = Severity.entries.min() ): Map> = - advisor?.results?.getIssues().orEmpty().filterIssues(omitExcluded, omitResolved, minSeverity) + advisor?.getIssues().orEmpty().filterIssues(omitExcluded, omitResolved, minSeverity) private fun Map>.filterIssues( omitExcluded: Boolean = false, @@ -560,7 +560,7 @@ data class OrtResult( omitResolved: Boolean = false, omitExcluded: Boolean = false ): Map> { - val allVulnerabilities = advisor?.results?.getVulnerabilities().orEmpty() + val allVulnerabilities = advisor?.getVulnerabilities().orEmpty() .filterKeys { !omitExcluded || !isExcluded(it) } return if (omitResolved) { diff --git a/model/src/test/kotlin/AdvisorRecordTest.kt b/model/src/test/kotlin/AdvisorResultTest.kt similarity index 85% rename from model/src/test/kotlin/AdvisorRecordTest.kt rename to model/src/test/kotlin/AdvisorResultTest.kt index 34d7736168f61..d2a99928bea84 100644 --- a/model/src/test/kotlin/AdvisorRecordTest.kt +++ b/model/src/test/kotlin/AdvisorResultTest.kt @@ -33,14 +33,14 @@ import org.ossreviewtoolkit.model.vulnerabilities.Vulnerability import org.ossreviewtoolkit.model.vulnerabilities.VulnerabilityReference import org.ossreviewtoolkit.utils.common.enumSetOf -class AdvisorRecordTest : WordSpec({ +class AdvisorResultTest : WordSpec({ "collectIssues" should { "return a map which does not contain entries for IDs without any issues" { - val record = advisorRecordOf( + val run = advisorRunOf( langId to listOf(createResult()) ) - val issues = record.getIssues() + val issues = run.getIssues() issues.keys shouldNotContain langId } @@ -49,12 +49,12 @@ class AdvisorRecordTest : WordSpec({ val issue1 = Issue(source = "Advisor", message = "Failure1") val issue2 = Issue(source = "Advisor", message = "Failure2") val issue3 = Issue(source = "Advisor", message = "Warning", severity = Severity.WARNING) - val record = advisorRecordOf( + val run = advisorRunOf( langId to listOf(createResult(issues = listOf(issue3))), queryId to listOf(createResult(issues = listOf(issue1, issue2))) ) - val issues = record.getIssues() + val issues = run.getIssues() issues.keys should containExactlyInAnyOrder(langId, queryId) issues[langId] should containExactly(issue3) @@ -64,34 +64,34 @@ class AdvisorRecordTest : WordSpec({ "getVulnerabilities" should { "return an empty list for an unknown package" { - val record = advisorRecordOf() + val run = advisorRunOf() - record.getVulnerabilities(langId) should beEmpty() + run.getVulnerabilities(langId) should beEmpty() } "return the vulnerabilities of a specific package" { val vul1 = createVulnerability("CVE-2021-1") val vul2 = createVulnerability("CVE-2021-2") - val record = advisorRecordOf( + val run = advisorRunOf( queryId to listOf(createResult(vulnerabilities = listOf(vul1, vul2))) ) - record.getVulnerabilities(queryId) should containExactly(vul1, vul2) + run.getVulnerabilities(queryId) should containExactly(vul1, vul2) } "combine the vulnerabilities of a specific package from multiple advisor results" { val vul1 = createVulnerability("CVE-2021-1") val vul2 = createVulnerability("CVE-2021-2") - val record = advisorRecordOf( + val run = advisorRunOf( queryId to listOf( createResult(advisorIndex = 1, vulnerabilities = listOf(vul1)), createResult(advisorIndex = 2, vulnerabilities = listOf(vul2)) ) ) - record.getVulnerabilities(queryId) should containExactly(vul1, vul2) + run.getVulnerabilities(queryId) should containExactly(vul1, vul2) } "merge the references of vulnerabilities" { @@ -101,14 +101,14 @@ class AdvisorRecordTest : WordSpec({ val vul3 = createVulnerability("CVE-2021-2") val mergedVulnerability = Vulnerability(id = vul1.id, references = vul1.references + vul2.references) - val record = advisorRecordOf( + val run = advisorRunOf( queryId to listOf( createResult(advisorIndex = 1, vulnerabilities = listOf(vul1)), createResult(advisorIndex = 2, vulnerabilities = listOf(vul2, vul3)) ) ) - record.getVulnerabilities(queryId) should containExactly(mergedVulnerability, vul3) + run.getVulnerabilities(queryId) should containExactly(mergedVulnerability, vul3) } "remove duplicate references when merging vulnerabilities" { @@ -122,22 +122,22 @@ class AdvisorRecordTest : WordSpec({ references = vul1.references + vul2.references + vul4.references ) - val record = advisorRecordOf( + val run = advisorRunOf( queryId to listOf( createResult(advisorIndex = 1, vulnerabilities = listOf(vul1)), createResult(advisorIndex = 2, vulnerabilities = listOf(vul2, vul3, vul4)) ) ) - record.getVulnerabilities(queryId) should containExactly(mergedVulnerability) + run.getVulnerabilities(queryId) should containExactly(mergedVulnerability) } } "getDefects" should { "return an empty list for an unknown package" { - val record = advisorRecordOf() + val run = advisorRunOf() - record.getDefects(langId) should beEmpty() + run.getDefects(langId) should beEmpty() } "return the combined defects detected for a specific package" { @@ -147,14 +147,14 @@ class AdvisorRecordTest : WordSpec({ val defect4 = createDefect("d4") val defect5 = createDefect("d5") - val record = advisorRecordOf( + val run = advisorRunOf( queryId to listOf( createResult(advisorIndex = 1, defects = listOf(defect1, defect2)), createResult(advisorIndex = 2, defects = listOf(defect3, defect4, defect5)) ) ) - record.getDefects(queryId) should containExactlyInAnyOrder(defect1, defect2, defect3, defect4, defect5) + run.getDefects(queryId) should containExactlyInAnyOrder(defect1, defect2, defect3, defect4, defect5) } } @@ -166,12 +166,12 @@ class AdvisorRecordTest : WordSpec({ defects = listOf(createDefect("bug1")) ) - val record = advisorRecordOf( + val run = advisorRunOf( queryId to listOf(createResult(advisorIndex = 1), createResult(advisorIndex = 2)), langId to listOf(matchingResult, createResult(advisorIndex = 2)) ) - val filteredResults = record.filterResults { it == matchingResult } + val filteredResults = run.filterResults { it == matchingResult } filteredResults.keys should containExactly(langId) filteredResults.getValue(langId) should containExactly(matchingResult) @@ -183,11 +183,11 @@ class AdvisorRecordTest : WordSpec({ val result3 = createResult(advisorIndex = 3) val result4 = createResult(advisorIndex = 4, vulnerabilities = listOf(createVulnerability("CVE-2"))) - val record = advisorRecordOf( + val run = advisorRunOf( queryId to listOf(result1, result2, result3, result4) ) - val filteredResults = record.filterResults(AdvisorRecord.RESULTS_WITH_VULNERABILITIES) + val filteredResults = run.filterResults(AdvisorRun.RESULTS_WITH_VULNERABILITIES) filteredResults.keys should containExactly(queryId) filteredResults.getValue(queryId) should containExactlyInAnyOrder(result1, result4) @@ -199,11 +199,11 @@ class AdvisorRecordTest : WordSpec({ val result3 = createResult(advisorIndex = 3) val result4 = createResult(advisorIndex = 4, vulnerabilities = listOf(createVulnerability("CVE-2"))) - val record = advisorRecordOf( + val run = advisorRunOf( queryId to listOf(result1, result2, result3, result4) ) - val filteredResults = record.filterResults(AdvisorRecord.RESULTS_WITH_DEFECTS) + val filteredResults = run.filterResults(AdvisorRun.RESULTS_WITH_DEFECTS) filteredResults.keys should containExactly(queryId) filteredResults.getValue(queryId) should containExactly(result2) @@ -216,12 +216,12 @@ class AdvisorRecordTest : WordSpec({ ) val result2 = createResult(advisorIndex = 2) - val record = advisorRecordOf( + val run = advisorRunOf( queryId to listOf(result1), langId to listOf(result2) ) - val filteredResults = record.filterResults(AdvisorRecord.resultsWithIssues()) + val filteredResults = run.filterResults(AdvisorRun.resultsWithIssues()) filteredResults.keys should containExactly(queryId) filteredResults.getValue(queryId) should containExactly(result1) @@ -238,12 +238,12 @@ class AdvisorRecordTest : WordSpec({ capability = AdvisorCapability.DEFECTS ) - val record = advisorRecordOf( + val run = advisorRunOf( queryId to listOf(result1), langId to listOf(result2) ) - val filteredResults = record.filterResults(AdvisorRecord.resultsWithIssues(minSeverity = Severity.ERROR)) + val filteredResults = run.filterResults(AdvisorRun.resultsWithIssues(minSeverity = Severity.ERROR)) filteredResults.keys should containExactly(queryId) filteredResults.getValue(queryId) should containExactly(result1) @@ -260,12 +260,12 @@ class AdvisorRecordTest : WordSpec({ capability = AdvisorCapability.DEFECTS ) - val record = advisorRecordOf( + val run = advisorRunOf( queryId to listOf(result1), langId to listOf(result2) ) - val filteredResults = record.filterResults( - AdvisorRecord.resultsWithIssues( + val filteredResults = run.filterResults( + AdvisorRun.resultsWithIssues( minSeverity = Severity.WARNING, capability = AdvisorCapability.VULNERABILITIES ) @@ -333,4 +333,5 @@ private fun createResult( return AdvisorResult(details, summary, defects, vulnerabilities) } -private fun advisorRecordOf(vararg results: Pair>) = AdvisorRecord(results.toMap()) +private fun advisorRunOf(vararg results: Pair>) = + AdvisorRun.EMPTY.copy(results = results.toMap()) diff --git a/plugins/commands/advisor/src/main/kotlin/AdvisorCommand.kt b/plugins/commands/advisor/src/main/kotlin/AdvisorCommand.kt index b2d24e1344b1c..717377621ba65 100644 --- a/plugins/commands/advisor/src/main/kotlin/AdvisorCommand.kt +++ b/plugins/commands/advisor/src/main/kotlin/AdvisorCommand.kt @@ -141,7 +141,7 @@ class AdvisorCommand : OrtCommand( val duration = with(advisorRun) { Duration.between(startTime, endTime).toKotlinDuration() } echo("The advice took $duration.") - with(advisorRun.results.getVulnerabilities()) { + with(advisorRun.getVulnerabilities()) { val includedPackages = ortResultOutput.getPackages(omitExcluded = true).map { it.metadata.id } val totalPackageCount = includedPackages.size val vulnerablePackageCount = count { (id, vulnerabilities) -> @@ -157,7 +157,7 @@ class AdvisorCommand : OrtCommand( } val resolutionProvider = DefaultResolutionProvider.create(ortResultOutput, resolutionsFile) - val issues = advisorRun.results.getIssues().flatMap { it.value } + val issues = advisorRun.getIssues().flatMap { it.value } SeverityStatsPrinter(terminal, resolutionProvider).stats(issues) .print().conclude(ortConfig.severeIssueThreshold, ORT_FAILURE_STATUS_CODE) } diff --git a/plugins/reporters/evaluated-model/src/funTest/assets/reporter-test-input.yml b/plugins/reporters/evaluated-model/src/funTest/assets/reporter-test-input.yml index 0c9d1923ccd06..8f5861bfb0370 100644 --- a/plugins/reporters/evaluated-model/src/funTest/assets/reporter-test-input.yml +++ b/plugins/reporters/evaluated-model/src/funTest/assets/reporter-test-input.yml @@ -778,41 +778,40 @@ advisor: options: server_url: "http://localhost:8000" results: - advisor_results: - Maven:org.apache.commons:commons-text:1.1: - - advisor: - name: "VulnerableCode" - capabilities: - - "VULNERABILITIES" - summary: - start_time: "1970-01-01T00:00:00Z" - end_time: "1970-01-01T00:00:00Z" - issues: - - timestamp: "1970-01-01T00:00:00Z" - source: "VulnerableCode" - message: "Example advisor error, resolved." - severity: "ERROR" - - timestamp: "1970-01-01T00:00:00Z" - source: "VulnerableCode" - message: "Example advisor error." - severity: "ERROR" - - timestamp: "1970-01-01T00:00:00Z" - source: "VulnerableCode" - message: "Example advisor warning." - severity: "WARNING" - - timestamp: "1970-01-01T00:00:00Z" - source: "VulnerableCode" - message: "Example advisor hint." - severity: "HINT" - vulnerabilities: - - id: "VULCOID-VULNERABILITY_ID" - summary: "summary text" - description: "description text" - references: - - url: "https://registry.vulnerability-url/" - scoring_system: "SCORING_SYSTEM_NAME" - severity: "ERROR" - severity_rating: "UNKNOWN" + Maven:org.apache.commons:commons-text:1.1: + - advisor: + name: "VulnerableCode" + capabilities: + - "VULNERABILITIES" + summary: + start_time: "1970-01-01T00:00:00Z" + end_time: "1970-01-01T00:00:00Z" + issues: + - timestamp: "1970-01-01T00:00:00Z" + source: "VulnerableCode" + message: "Example advisor error, resolved." + severity: "ERROR" + - timestamp: "1970-01-01T00:00:00Z" + source: "VulnerableCode" + message: "Example advisor error." + severity: "ERROR" + - timestamp: "1970-01-01T00:00:00Z" + source: "VulnerableCode" + message: "Example advisor warning." + severity: "WARNING" + - timestamp: "1970-01-01T00:00:00Z" + source: "VulnerableCode" + message: "Example advisor hint." + severity: "HINT" + vulnerabilities: + - id: "VULCOID-VULNERABILITY_ID" + summary: "summary text" + description: "description text" + references: + - url: "https://registry.vulnerability-url/" + scoring_system: "SCORING_SYSTEM_NAME" + severity: "ERROR" + severity_rating: "UNKNOWN" evaluator: start_time: "1970-01-01T01:09:00Z" end_time: "1970-01-01T01:11:00Z" diff --git a/plugins/reporters/evaluated-model/src/main/kotlin/EvaluatedModelMapper.kt b/plugins/reporters/evaluated-model/src/main/kotlin/EvaluatedModelMapper.kt index e0f4843811e8b..2e9b685a56720 100644 --- a/plugins/reporters/evaluated-model/src/main/kotlin/EvaluatedModelMapper.kt +++ b/plugins/reporters/evaluated-model/src/main/kotlin/EvaluatedModelMapper.kt @@ -115,7 +115,7 @@ internal class EvaluatedModelMapper(private val input: ReporterInput) { addRuleViolation(ruleViolation) } - input.ortResult.advisor?.results?.advisorResults?.forEach { (id, results) -> + input.ortResult.advisor?.results?.forEach { (id, results) -> val pkg = packages.getValue(id) results.forEach { result -> diff --git a/plugins/reporters/freemarker/src/main/kotlin/FreemarkerTemplateProcessor.kt b/plugins/reporters/freemarker/src/main/kotlin/FreemarkerTemplateProcessor.kt index 62d74cfe445e3..1dae94aee1436 100644 --- a/plugins/reporters/freemarker/src/main/kotlin/FreemarkerTemplateProcessor.kt +++ b/plugins/reporters/freemarker/src/main/kotlin/FreemarkerTemplateProcessor.kt @@ -30,9 +30,9 @@ import java.io.File import org.apache.logging.log4j.kotlin.logger import org.ossreviewtoolkit.model.AdvisorCapability -import org.ossreviewtoolkit.model.AdvisorRecord import org.ossreviewtoolkit.model.AdvisorResult import org.ossreviewtoolkit.model.AdvisorResultFilter +import org.ossreviewtoolkit.model.AdvisorRun import org.ossreviewtoolkit.model.Identifier import org.ossreviewtoolkit.model.Issue import org.ossreviewtoolkit.model.OrtResult @@ -352,8 +352,8 @@ class FreemarkerTemplateProcessor( * therefore, it should contain a corresponding warning. */ fun hasAdvisorIssues(capability: AdvisorCapability, severity: Severity): Boolean = - input.ortResult.advisor?.results?.filterResults( - AdvisorRecord.resultsWithIssues( + input.ortResult.advisor?.filterResults( + AdvisorRun.resultsWithIssues( capability = capability, minSeverity = severity ) @@ -369,7 +369,7 @@ class FreemarkerTemplateProcessor( severity: Severity ): Map> = input.filteredAdvisorResults( - AdvisorRecord.resultsWithIssues( + AdvisorRun.resultsWithIssues( capability = capability, minSeverity = severity ) @@ -379,13 +379,13 @@ class FreemarkerTemplateProcessor( * Return the subset of the available advisor results that contain vulnerabilities. */ fun advisorResultsWithVulnerabilities(): Map> = - input.filteredAdvisorResults(AdvisorRecord.RESULTS_WITH_VULNERABILITIES) + input.filteredAdvisorResults(AdvisorRun.RESULTS_WITH_VULNERABILITIES) /** * Return the subset of the available advisor results that contain defects. */ fun advisorResultsWithDefects(): Map> = - input.filteredAdvisorResults(AdvisorRecord.RESULTS_WITH_DEFECTS) + input.filteredAdvisorResults(AdvisorRun.RESULTS_WITH_DEFECTS) /** * Return the package from the current [OrtResult] with the given [id] or the empty package if the ID cannot be @@ -453,4 +453,4 @@ private fun List.merge(): ResolvedLicense { * results are available. */ private fun ReporterInput.filteredAdvisorResults(filter: AdvisorResultFilter): Map> = - ortResult.advisor?.results?.filterResults(filter).orEmpty() + ortResult.advisor?.filterResults(filter).orEmpty() diff --git a/plugins/reporters/opossum/src/funTest/assets/reporter-test-input.yml b/plugins/reporters/opossum/src/funTest/assets/reporter-test-input.yml index 0c9d1923ccd06..8f5861bfb0370 100644 --- a/plugins/reporters/opossum/src/funTest/assets/reporter-test-input.yml +++ b/plugins/reporters/opossum/src/funTest/assets/reporter-test-input.yml @@ -778,41 +778,40 @@ advisor: options: server_url: "http://localhost:8000" results: - advisor_results: - Maven:org.apache.commons:commons-text:1.1: - - advisor: - name: "VulnerableCode" - capabilities: - - "VULNERABILITIES" - summary: - start_time: "1970-01-01T00:00:00Z" - end_time: "1970-01-01T00:00:00Z" - issues: - - timestamp: "1970-01-01T00:00:00Z" - source: "VulnerableCode" - message: "Example advisor error, resolved." - severity: "ERROR" - - timestamp: "1970-01-01T00:00:00Z" - source: "VulnerableCode" - message: "Example advisor error." - severity: "ERROR" - - timestamp: "1970-01-01T00:00:00Z" - source: "VulnerableCode" - message: "Example advisor warning." - severity: "WARNING" - - timestamp: "1970-01-01T00:00:00Z" - source: "VulnerableCode" - message: "Example advisor hint." - severity: "HINT" - vulnerabilities: - - id: "VULCOID-VULNERABILITY_ID" - summary: "summary text" - description: "description text" - references: - - url: "https://registry.vulnerability-url/" - scoring_system: "SCORING_SYSTEM_NAME" - severity: "ERROR" - severity_rating: "UNKNOWN" + Maven:org.apache.commons:commons-text:1.1: + - advisor: + name: "VulnerableCode" + capabilities: + - "VULNERABILITIES" + summary: + start_time: "1970-01-01T00:00:00Z" + end_time: "1970-01-01T00:00:00Z" + issues: + - timestamp: "1970-01-01T00:00:00Z" + source: "VulnerableCode" + message: "Example advisor error, resolved." + severity: "ERROR" + - timestamp: "1970-01-01T00:00:00Z" + source: "VulnerableCode" + message: "Example advisor error." + severity: "ERROR" + - timestamp: "1970-01-01T00:00:00Z" + source: "VulnerableCode" + message: "Example advisor warning." + severity: "WARNING" + - timestamp: "1970-01-01T00:00:00Z" + source: "VulnerableCode" + message: "Example advisor hint." + severity: "HINT" + vulnerabilities: + - id: "VULCOID-VULNERABILITY_ID" + summary: "summary text" + description: "description text" + references: + - url: "https://registry.vulnerability-url/" + scoring_system: "SCORING_SYSTEM_NAME" + severity: "ERROR" + severity_rating: "UNKNOWN" evaluator: start_time: "1970-01-01T01:09:00Z" end_time: "1970-01-01T01:11:00Z" diff --git a/plugins/reporters/static-html/src/funTest/assets/reporter-test-input.yml b/plugins/reporters/static-html/src/funTest/assets/reporter-test-input.yml index 0c9d1923ccd06..8f5861bfb0370 100644 --- a/plugins/reporters/static-html/src/funTest/assets/reporter-test-input.yml +++ b/plugins/reporters/static-html/src/funTest/assets/reporter-test-input.yml @@ -778,41 +778,40 @@ advisor: options: server_url: "http://localhost:8000" results: - advisor_results: - Maven:org.apache.commons:commons-text:1.1: - - advisor: - name: "VulnerableCode" - capabilities: - - "VULNERABILITIES" - summary: - start_time: "1970-01-01T00:00:00Z" - end_time: "1970-01-01T00:00:00Z" - issues: - - timestamp: "1970-01-01T00:00:00Z" - source: "VulnerableCode" - message: "Example advisor error, resolved." - severity: "ERROR" - - timestamp: "1970-01-01T00:00:00Z" - source: "VulnerableCode" - message: "Example advisor error." - severity: "ERROR" - - timestamp: "1970-01-01T00:00:00Z" - source: "VulnerableCode" - message: "Example advisor warning." - severity: "WARNING" - - timestamp: "1970-01-01T00:00:00Z" - source: "VulnerableCode" - message: "Example advisor hint." - severity: "HINT" - vulnerabilities: - - id: "VULCOID-VULNERABILITY_ID" - summary: "summary text" - description: "description text" - references: - - url: "https://registry.vulnerability-url/" - scoring_system: "SCORING_SYSTEM_NAME" - severity: "ERROR" - severity_rating: "UNKNOWN" + Maven:org.apache.commons:commons-text:1.1: + - advisor: + name: "VulnerableCode" + capabilities: + - "VULNERABILITIES" + summary: + start_time: "1970-01-01T00:00:00Z" + end_time: "1970-01-01T00:00:00Z" + issues: + - timestamp: "1970-01-01T00:00:00Z" + source: "VulnerableCode" + message: "Example advisor error, resolved." + severity: "ERROR" + - timestamp: "1970-01-01T00:00:00Z" + source: "VulnerableCode" + message: "Example advisor error." + severity: "ERROR" + - timestamp: "1970-01-01T00:00:00Z" + source: "VulnerableCode" + message: "Example advisor warning." + severity: "WARNING" + - timestamp: "1970-01-01T00:00:00Z" + source: "VulnerableCode" + message: "Example advisor hint." + severity: "HINT" + vulnerabilities: + - id: "VULCOID-VULNERABILITY_ID" + summary: "summary text" + description: "description text" + references: + - url: "https://registry.vulnerability-url/" + scoring_system: "SCORING_SYSTEM_NAME" + severity: "ERROR" + severity_rating: "UNKNOWN" evaluator: start_time: "1970-01-01T01:09:00Z" end_time: "1970-01-01T01:11:00Z" diff --git a/reporter/src/testFixtures/kotlin/TestData.kt b/reporter/src/testFixtures/kotlin/TestData.kt index 52fea88318446..dfc61b6667b62 100644 --- a/reporter/src/testFixtures/kotlin/TestData.kt +++ b/reporter/src/testFixtures/kotlin/TestData.kt @@ -24,7 +24,6 @@ import java.time.Instant import org.ossreviewtoolkit.model.AdvisorCapability import org.ossreviewtoolkit.model.AdvisorDetails -import org.ossreviewtoolkit.model.AdvisorRecord import org.ossreviewtoolkit.model.AdvisorResult import org.ossreviewtoolkit.model.AdvisorRun import org.ossreviewtoolkit.model.AdvisorSummary @@ -417,14 +416,12 @@ val ADVISOR_WITH_VULNERABILITIES = AdvisorRun( endTime = Instant.now(), environment = Environment(), config = AdvisorConfiguration(), - results = AdvisorRecord( - mapOf( - Identifier("NPM:@ort:declared-license:1.0") to listOf( - AdvisorResult( - advisor = AdvisorDetails("VulnerableCode", enumSetOf(AdvisorCapability.VULNERABILITIES)), - summary = AdvisorSummary(Instant.now(), Instant.now()), - vulnerabilities = listOf(VULNERABILITY) - ) + results = mapOf( + Identifier("NPM:@ort:declared-license:1.0") to listOf( + AdvisorResult( + advisor = AdvisorDetails("VulnerableCode", enumSetOf(AdvisorCapability.VULNERABILITIES)), + summary = AdvisorSummary(Instant.now(), Instant.now()), + vulnerabilities = listOf(VULNERABILITY) ) ) ) diff --git a/utils/test/src/main/kotlin/Utils.kt b/utils/test/src/main/kotlin/Utils.kt index 23dc774625232..b458ee18f30a0 100644 --- a/utils/test/src/main/kotlin/Utils.kt +++ b/utils/test/src/main/kotlin/Utils.kt @@ -25,7 +25,6 @@ import java.io.File import java.time.Instant import org.ossreviewtoolkit.downloader.VersionControlSystem -import org.ossreviewtoolkit.model.AdvisorRecord import org.ossreviewtoolkit.model.AdvisorResult import org.ossreviewtoolkit.model.AdvisorRun import org.ossreviewtoolkit.model.ArtifactProvenance @@ -66,7 +65,7 @@ fun advisorRunOf(vararg results: Pair>): Advisor endTime = Instant.now(), environment = Environment(), config = AdvisorConfiguration(), - results = AdvisorRecord(results.toMap()) + results = results.toMap() ) /**