Skip to content

Commit c0d7fdf

Browse files
committed
feat(model): guard against duplicate scan results / file lists per provenance
Prep work for upcoming PR oss-review-toolkit#10502. * `ScannerRun.init` - Add a `require` check that no two `ScanResult`s share the same provenance. - Add a similar check that no two `FileList`s share the same provenance. The offending provenance is rendered via `toYaml()` to aid debugging. * `ScannerRunTest` - Introduce two unit tests that assert an `IllegalArgumentException` is thrown when duplicates are present for scan results or file lists, respectively. These runtime checks make improper scan runs surface early and provide clear error messages, which will simplify the upcoming deduplication work. Signed-off-by: Jonatan Männchen <jonatan@maennchen.ch>
1 parent a15d3fb commit c0d7fdf

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed

model/src/main/kotlin/ScannerRun.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,13 @@ data class ScannerRun(
135135
}
136136
}
137137

138+
scanResults.toList().getDuplicates { it.provenance }.keys.let { duplicateProvenances ->
139+
require(duplicateProvenances.isEmpty()) {
140+
"Found multiple scan results for the same provenance:\n" +
141+
duplicateProvenances.first().toYaml()
142+
}
143+
}
144+
138145
provenances.getDuplicates { it.id }.keys.let { idsForDuplicateProvenanceResolutionResults ->
139146
require(idsForDuplicateProvenanceResolutionResults.isEmpty()) {
140147
"Found multiple provenance resolution results for the following ids: " +
@@ -173,6 +180,13 @@ data class ScannerRun(
173180
}
174181
}
175182
}
183+
184+
files.toList().getDuplicates { it.provenance }.keys.let { duplicateProvenances ->
185+
require(duplicateProvenances.isEmpty()) {
186+
"Found multiple file lists for the same provenance:\n" +
187+
duplicateProvenances.first().toYaml()
188+
}
189+
}
176190
}
177191

178192
private val provenancesById: Map<Identifier, ProvenanceResolutionResult> by lazy {

model/src/test/kotlin/ScannerRunTest.kt

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,101 @@
1919

2020
package org.ossreviewtoolkit.model
2121

22+
import io.kotest.assertions.throwables.shouldThrow
2223
import io.kotest.core.spec.style.WordSpec
2324
import io.kotest.matchers.collections.containExactlyInAnyOrder
2425
import io.kotest.matchers.maps.containExactly
2526
import io.kotest.matchers.nulls.shouldNotBeNull
2627
import io.kotest.matchers.should
28+
import io.kotest.matchers.string.shouldContain
2729

2830
import org.ossreviewtoolkit.model.FileList.Entry
2931
import org.ossreviewtoolkit.model.utils.alignRevisions
3032
import org.ossreviewtoolkit.model.utils.clearVcsPath
3133

3234
class ScannerRunTest : WordSpec({
35+
"init" should {
36+
"error on duplicate provenance scan results" {
37+
val provenance = RepositoryProvenance(
38+
VcsInfo(type = VcsType.GIT, url = "https://github.com/example.git", revision = "revision"),
39+
"revision"
40+
)
41+
42+
val ex = shouldThrow<IllegalArgumentException> {
43+
ScannerRun.EMPTY.copy(
44+
provenances = setOf(
45+
ProvenanceResolutionResult(
46+
id = Identifier("maven::example:1.0"),
47+
packageProvenance = provenance
48+
)
49+
),
50+
scanResults = setOf(
51+
ScanResult(
52+
provenance = provenance,
53+
scanner = ScannerDetails.EMPTY,
54+
summary = ScanSummary.EMPTY.copy(
55+
licenseFindings = setOf(
56+
LicenseFinding("MIT", TextLocation("file1.txt", 1, 1))
57+
)
58+
)
59+
),
60+
ScanResult(
61+
provenance = provenance,
62+
scanner = ScannerDetails.EMPTY,
63+
summary = ScanSummary.EMPTY.copy(
64+
licenseFindings = setOf(
65+
LicenseFinding("MIT", TextLocation("file2.txt", 1, 1))
66+
)
67+
)
68+
)
69+
)
70+
)
71+
}
72+
73+
ex.message shouldContain "Found multiple scan results for the same provenance"
74+
}
75+
76+
"error on duplicate provenance file lists" {
77+
val provenance = RepositoryProvenance(
78+
VcsInfo(type = VcsType.GIT, url = "https://github.com/example.git", revision = "revision"),
79+
"revision"
80+
)
81+
82+
val ex = shouldThrow<IllegalArgumentException> {
83+
ScannerRun.EMPTY.copy(
84+
provenances = setOf(
85+
ProvenanceResolutionResult(
86+
id = Identifier("maven::example:1.0"),
87+
packageProvenance = provenance
88+
)
89+
),
90+
files = setOf(
91+
FileList(
92+
provenance = provenance,
93+
files = setOf(
94+
Entry(
95+
path = "vcs/path/file1.txt",
96+
sha1 = "1111111111111111111111111111111111111111"
97+
)
98+
)
99+
),
100+
FileList(
101+
provenance = provenance,
102+
files = setOf(
103+
Entry(
104+
path = "some/dir/file2.txt",
105+
sha1 = "2222222222222222222222222222222222222222"
106+
)
107+
)
108+
)
109+
)
110+
)
111+
}
112+
113+
ex.message shouldContain "Found multiple file lists for the same provenance"
114+
}
115+
}
116+
33117
"getFileList()" should {
34118
"filter by VCS path and merge sub-repository lists as expected" {
35119
val id = Identifier("a:b:c:1.0.0")

0 commit comments

Comments
 (0)