diff --git a/src/main/java/com/lpvs/service/scan/scanner/LPVSScanossDetectService.java b/src/main/java/com/lpvs/service/scan/scanner/LPVSScanossDetectService.java index 53a563a4..2ca23994 100644 --- a/src/main/java/com/lpvs/service/scan/scanner/LPVSScanossDetectService.java +++ b/src/main/java/com/lpvs/service/scan/scanner/LPVSScanossDetectService.java @@ -146,108 +146,29 @@ public void runScan(LPVSQueue webhookConfig, String path) throws Exception { public List checkLicenses(LPVSQueue webhookConfig) { List detectedFiles = new ArrayList<>(); try { - Gson gson = new Gson(); - Reader reader; - if (webhookConfig.getHeadCommitSHA() == null - || webhookConfig.getHeadCommitSHA().equals("")) { - reader = - Files.newBufferedReader( - Paths.get( - System.getProperty("user.home") - + File.separator - + "Results" - + File.separator - + LPVSPayloadUtil.getRepositoryName(webhookConfig) - + File.separator - + LPVSPayloadUtil.getPullRequestId(webhookConfig) - + ".json")); - } else { - reader = - Files.newBufferedReader( - Paths.get( - System.getProperty("user.home") - + File.separator - + "Results" - + File.separator - + LPVSPayloadUtil.getRepositoryName(webhookConfig) - + File.separator - + webhookConfig.getHeadCommitSHA() - + ".json")); - } + Reader reader = getReader(webhookConfig); + // convert JSON file to map Map> map = - gson.fromJson( - reader, new TypeToken>>() {}.getType()); - - // parse map entries - long ind = 0L; + new Gson() + .fromJson( + reader, + new TypeToken>>() {}.getType()); if (null == map) { log.error("Error parsing Json File"); return detectedFiles; } + + // parse map entries + long ind = 0L; for (Map.Entry> entry : map.entrySet()) { LPVSFile file = new LPVSFile(); file.setId(ind++); file.setFilePath(entry.getKey().toString()); - String content = - entry.getValue() - .toString() - .replaceAll("=\\[", "\" : [") - .replaceAll("=", "\" : \"") - .replaceAll("\\}, \\{", "\"},{") - .replaceAll("\\}\\],", "\"}],") - .replaceAll("\\{", "{\"") - .replaceAll(", ", "\", \"") - .replaceAll("\\]\"", "]") - .replaceAll("}\",", "\"},") - .replaceAll(": \\[", ": [\"") - .replaceAll("],", "\"],") - .replaceAll("\"\\{\"", "{\"") - .replaceAll("\"}\"]", "\"}]") - .replaceAll("\\[\"\"\\]", "[]") - .replaceAll( - "incompatible_with\" : (\".*?\"), \"name", - "incompatible_with\" : \\[$1\\], \"name"); - content = content.substring(1, content.length() - 1); - if (content.endsWith("}")) { - content = content.substring(0, content.length() - 1) + "\"}"; - } - content = content.replaceAll("}\"}", "\"}}"); - ScanossJsonStructure object = gson.fromJson(content, ScanossJsonStructure.class); - if (object.id != null) file.setSnippetType(object.id); - if (object.matched != null) file.setSnippetMatch(object.matched); - if (object.lines != null) file.setMatchedLines(object.lines); - if (object.file != null) file.setComponentFilePath(object.file); - if (object.file_url != null) file.setComponentFileUrl(object.file_url); - if (object.component != null) file.setComponentName(object.component); - if (object.oss_lines != null) file.setComponentLines(object.oss_lines); - if (object.url != null) file.setComponentUrl(object.url); - if (object.version != null) file.setComponentVersion(object.version); - if (object.vendor != null) file.setComponentVendor(object.vendor); - - Set licenses = new HashSet<>(); - if (object.licenses != null) { - for (ScanossJsonStructure.ScanossLicense license : object.licenses) { - // Check detected licenses - LPVSLicense lic = - licenseService.getLicenseBySpdxIdAndName( - license.name, Optional.empty()); - lic.setChecklistUrl(license.checklist_url); - licenses.add(lic); - - // Check for the license conflicts if the property - // "license_conflict=scanner" - if (licenseService.licenseConflictsSource.equalsIgnoreCase("scanner")) { - if (license.incompatible_with != null) { - for (String incompatibleLicense : license.incompatible_with) { - licenseService.addLicenseConflict( - incompatibleLicense, license.name); - } - } - } - } - } + String content = buildContent(entry); + ScanossJsonStructure object = getScanossJsonStructure(content, file); + Set licenses = buildLicenseSet(object); file.setLicenses(new HashSet<>(licenses)); if (!file.getLicenses().isEmpty()) detectedFiles.add(file); } @@ -261,6 +182,121 @@ public List checkLicenses(LPVSQueue webhookConfig) { return detectedFiles; } + /** + * Builds a set of LPVSLicense objects detected by Scanoss in the given ScanossJsonStructure structure. + * + * @param object The ScanossJsonStructure containing information about the licenses detected by Scanoss. + * @return A set of LPVSLicense objects representing the detected licenses with additional metadata. + */ + private Set buildLicenseSet(ScanossJsonStructure object) { + if (object.licenses == null) { + return new HashSet<>(); + } + + Set licenses = new HashSet<>(); + for (ScanossJsonStructure.ScanossLicense license : object.licenses) { + // Check detected licenses + LPVSLicense lic = + licenseService.getLicenseBySpdxIdAndName(license.name, Optional.empty()); + lic.setChecklistUrl(license.checklist_url); + licenses.add(lic); + + // Check for the license conflicts if the property + // "license_conflict=scanner" + if (licenseService.licenseConflictsSource.equalsIgnoreCase("scanner")) { + if (license.incompatible_with != null) { + for (String incompatibleLicense : license.incompatible_with) { + licenseService.addLicenseConflict(incompatibleLicense, license.name); + } + } + } + } + return licenses; + } + + /** + * Parses the content returned by Scanoss and populates the given LPVSFile entity with the relevant information. + * + * @param content The string content returned by Scanoss. + * @param file The LPVSFile entity to be populated with the parsed information. + * @return The parsed ScanossJsonStructure object containing the extracted information. + */ + private ScanossJsonStructure getScanossJsonStructure(String content, LPVSFile file) { + ScanossJsonStructure object = new Gson().fromJson(content, ScanossJsonStructure.class); + if (object.id != null) file.setSnippetType(object.id); + if (object.matched != null) file.setSnippetMatch(object.matched); + if (object.lines != null) file.setMatchedLines(object.lines); + if (object.file != null) file.setComponentFilePath(object.file); + if (object.file_url != null) file.setComponentFileUrl(object.file_url); + if (object.component != null) file.setComponentName(object.component); + if (object.oss_lines != null) file.setComponentLines(object.oss_lines); + if (object.url != null) file.setComponentUrl(object.url); + if (object.version != null) file.setComponentVersion(object.version); + if (object.vendor != null) file.setComponentVendor(object.vendor); + return object; + } + + /** + * Creates a new BufferedReader object for reading the JSON file containing the scan results. + * + * @param webhookConfig The LPVSQueue representing the GitHub webhook configuration. + * @return A BufferedReader object for reading the JSON file. + * @throws IOException If an error occurs while creating the BufferedReader object. + */ + private static Reader getReader(LPVSQueue webhookConfig) throws IOException { + String fileName = null; + if (webhookConfig.getHeadCommitSHA() == null + || webhookConfig.getHeadCommitSHA().isBlank()) { + fileName = LPVSPayloadUtil.getPullRequestId(webhookConfig); + } else { + fileName = webhookConfig.getHeadCommitSHA(); + } + + return Files.newBufferedReader( + Paths.get( + System.getProperty("user.home") + + File.separator + + "Results" + + File.separator + + LPVSPayloadUtil.getRepositoryName(webhookConfig) + + File.separator + + fileName + + ".json")); + } + + /** + * Builds the content string for the given Map.Entry object. + * + * @param entry The Map.Entry object containing the information to be included in the content string. + * @return The constructed content string. + */ + private static String buildContent(Map.Entry> entry) { + String content = + entry.getValue() + .toString() + .replaceAll("=\\[", "\" : [") + .replaceAll("=", "\" : \"") + .replaceAll("\\}, \\{", "\"},{") + .replaceAll("\\}\\],", "\"}],") + .replaceAll("\\{", "{\"") + .replaceAll(", ", "\", \"") + .replaceAll("\\]\"", "]") + .replaceAll("}\",", "\"},") + .replaceAll(": \\[", ": [\"") + .replaceAll("],", "\"],") + .replaceAll("\"\\{\"", "{\"") + .replaceAll("\"}\"]", "\"}]") + .replaceAll("\\[\"\"\\]", "[]") + .replaceAll( + "incompatible_with\" : (\".*?\"), \"name", + "incompatible_with\" : \\[$1\\], \"name"); + content = content.substring(1, content.length() - 1); + if (content.endsWith("}")) { + content = content.substring(0, content.length() - 1) + "\"}"; + } + return content.replaceAll("}\"}", "\"}}"); + } + /** * Represents the JSON structure of Scanoss scan results. */ diff --git a/src/test/java/com/lpvs/service/scan/scanner/LPVSScanossDetectServiceTest.java b/src/test/java/com/lpvs/service/scan/scanner/LPVSScanossDetectServiceTest.java index 1e9a3728..1c291a74 100644 --- a/src/test/java/com/lpvs/service/scan/scanner/LPVSScanossDetectServiceTest.java +++ b/src/test/java/com/lpvs/service/scan/scanner/LPVSScanossDetectServiceTest.java @@ -15,10 +15,13 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.MockedConstruction; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.springframework.boot.test.system.CapturedOutput; +import org.springframework.boot.test.system.OutputCaptureExtension; import org.springframework.test.util.ReflectionTestUtils; import java.io.*; @@ -28,6 +31,8 @@ import java.nio.file.StandardCopyOption; import java.util.Objects; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.*; @@ -123,11 +128,20 @@ public void testWithNullHeadCommitSHA() { Mockito.when(webhookConfig.getHeadCommitSHA()).thenReturn(null); Mockito.when(webhookConfig.getRepositoryUrl()) .thenReturn("https://github.com/Samsung/LPVS"); - Mockito.when(LPVSPayloadUtil.getRepositoryName(webhookConfig)).thenReturn("A"); - Mockito.when(webhookConfig.getPullRequestUrl()).thenReturn("A/B"); + Mockito.when(LPVSPayloadUtil.getRepositoryName(webhookConfig)).thenReturn("C"); + Mockito.when(webhookConfig.getPullRequestUrl()).thenReturn("A_B"); ReflectionTestUtils.setField( licenseService, "licenseConflictsSource", licenseConflictsSource); - Assertions.assertNotNull(scanossDetectService.checkLicenses(webhookConfig)); + Mockito.when(licenseService.getLicenseBySpdxIdAndName(anyString(), any())) + .thenReturn( + new LPVSLicense() { + { + setLicenseName("MIT"); + setLicenseId(1L); + setSpdxId("MIT"); + } + }); + Assertions.assertEquals(scanossDetectService.checkLicenses(webhookConfig).size(), 3); } @Test @@ -137,11 +151,31 @@ public void testWithNullHeadCommitSHADB() { Mockito.when(webhookConfig.getHeadCommitSHA()).thenReturn(null); Mockito.when(webhookConfig.getRepositoryUrl()) .thenReturn("https://github.com/Samsung/LPVS"); - Mockito.when(webhookConfig.getPullRequestUrl()).thenReturn("A/B"); - Mockito.when(LPVSPayloadUtil.getRepositoryName(webhookConfig)).thenReturn("A"); + Mockito.when(webhookConfig.getPullRequestUrl()).thenReturn("A_B"); + Mockito.when(LPVSPayloadUtil.getRepositoryName(webhookConfig)).thenReturn("C"); ReflectionTestUtils.setField( licenseService, "licenseConflictsSource", licenseConflictsSource); - Assertions.assertNotNull(scanossDetectService.checkLicenses(webhookConfig)); + + Mockito.when(licenseService.getLicenseBySpdxIdAndName(anyString(), any())) + .thenReturn( + new LPVSLicense() { + { + setLicenseName("MIT"); + setLicenseId(1L); + setSpdxId("MIT"); + } + }); + Assertions.assertEquals(scanossDetectService.checkLicenses(webhookConfig).size(), 3); + } + + @Test + @ExtendWith(OutputCaptureExtension.class) + public void testCheckLicenseException(CapturedOutput capturedOutput) { + Mockito.when(lpvsQueue.getHeadCommitSHA()).thenReturn("AB"); + Mockito.when(lpvsQueue.getRepositoryUrl()).thenReturn("https://github.com/Samsung/LPVS"); + scanossDetectService.checkLicenses(lpvsQueue); + assertThat( + capturedOutput.toString(), containsString("Error while processing Webhook ID = ")); } @Test