From 2bfeec1414ccb5468f51367eaa65b5ed6399a934 Mon Sep 17 00:00:00 2001 From: Nicolas Nobelis Date: Wed, 22 May 2024 13:40:12 +0200 Subject: [PATCH] fix(fossid-webapp): Count snippets when enforcing the snippet limit The current logic is wrong: the snippet limit is applied to ORT snippet findings. However, a snippet finding refers to a single source code location and contains generally multiple snippets. Hence, those snippets must be counted when applying the limit. Please note that the new logic still garantees that all the snippets of a snippet finding are returned, for unity. This is a fixup for 9223e90e. Signed-off-by: Nicolas Nobelis --- .../src/main/kotlin/FossIdScanResults.kt | 8 ++- .../test/kotlin/FossIdSnippetChoiceTest.kt | 55 +++++++++++++++++-- 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/plugins/scanners/fossid/src/main/kotlin/FossIdScanResults.kt b/plugins/scanners/fossid/src/main/kotlin/FossIdScanResults.kt index 5902a84d7d056..7e568a4f32ab1 100644 --- a/plugins/scanners/fossid/src/main/kotlin/FossIdScanResults.kt +++ b/plugins/scanners/fossid/src/main/kotlin/FossIdScanResults.kt @@ -191,8 +191,12 @@ internal suspend fun mapSnippetFindings( snippetLicenseFindings ) - runningSnippetCount += mappedSnippets.size - results += mappedSnippets + val snippetFindingIterator = mappedSnippets.iterator() + while (runningSnippetCount < snippetsLimit && snippetFindingIterator.hasNext()) { + val snippetFinding = snippetFindingIterator.next() + runningSnippetCount += snippetFinding.snippets.size + results += snippetFinding + } } if (runningSnippetCount >= snippetsLimit) { diff --git a/plugins/scanners/fossid/src/test/kotlin/FossIdSnippetChoiceTest.kt b/plugins/scanners/fossid/src/test/kotlin/FossIdSnippetChoiceTest.kt index 82aa8545e2342..973cdecacd389 100644 --- a/plugins/scanners/fossid/src/test/kotlin/FossIdSnippetChoiceTest.kt +++ b/plugins/scanners/fossid/src/test/kotlin/FossIdSnippetChoiceTest.kt @@ -721,7 +721,7 @@ class FossIdSnippetChoiceTest : WordSpec({ } } - "respect the snippet limit when listing snippets" { + "respect the snippet limit when listing snippets (single snippet per finding)" { val projectCode = projectCode(PROJECT) val scanCode = scanCode(PROJECT, null) val config = createConfig(deltaScans = false, fetchSnippetMatchedLines = true, snippetsLimit = 2) @@ -766,6 +766,51 @@ class FossIdSnippetChoiceTest : WordSpec({ } } + "respect the snippet limit when listing snippets (multiple snippets per finding)" { + val projectCode = projectCode(PROJECT) + val scanCode = scanCode(PROJECT, null) + val config = createConfig(deltaScans = false, fetchSnippetMatchedLines = true, snippetsLimit = 2) + val vcsInfo = createVcsInfo() + val scan = createScan(vcsInfo.url, "${vcsInfo.revision}_other", scanCode) + val pkgId = createIdentifier(index = 42) + + FossIdRestService.create(config.serverUrl) + .expectProjectRequest(projectCode) + .expectListScans(projectCode, listOf(scan)) + .expectCheckScanStatus(scanCode, ScanStatus.FINISHED) + .expectCreateScan(projectCode, scanCode, vcsInfo, "") + .expectDownload(scanCode) + .mockFiles( + scanCode, + pendingFiles = listOf(FILE_1, FILE_2), + snippets = listOf( + createSnippet(0, FILE_1, PURL_1), + createSnippet(1, FILE_1, PURL_2) + ), + matchedLines = mapOf( + 0 to MatchedLines.create((10..20).toList(), (10..20).toList()), + 1 to MatchedLines.create((10..20).toList(), (20..30).toList()) + ) + ) + + val fossId = createFossId(config) + + val summary = fossId.scan(createPackage(pkgId, vcsInfo)).summary + + summary.snippetFindings shouldHaveSize 1 + summary.snippetFindings.forEach { + it.sourceLocation.path shouldBe FILE_1 + } + + summary.snippetFindings.flatMap { it.snippets } shouldHaveSize 2 + + summary.issues.forAtLeastOne { + it.message shouldBe "The snippets limit of 2 has been reached. To see the possible remaining " + + "snippets, please perform a snippet choice for the snippets presents in the snippet report an " + + "rerun the scan." + } + } + "list all the snippets of a file even if if goes over the snippets limit" { val projectCode = projectCode(PROJECT) val scanCode = scanCode(PROJECT, null) @@ -844,12 +889,12 @@ class FossIdSnippetChoiceTest : WordSpec({ val summary = fossId.scan(createPackage(pkgId, vcsInfo), snippetChoices = snippetChoices).summary - summary.snippetFindings shouldHaveSize 3 - summary.snippetFindings.first().apply { + summary.snippetFindings shouldHaveSize 2 + summary.snippetFindings.first().apply { // one snippet is remaining for file 1 sourceLocation.path shouldBe FILE_1 } - summary.snippetFindings.drop(1).forEach { - it.sourceLocation.path shouldBe FILE_2 + summary.snippetFindings.last().apply { // one snippet for file 2, then the limit is reached + sourceLocation.path shouldBe FILE_2 } summary.issues.forAtLeastOne {