Skip to content

Commit

Permalink
refactor: LPVSScanossDetectService refactoring and unit test fix (#524)
Browse files Browse the repository at this point in the history
* fix: correct the path to read the real file in the unit tests.

* test: Add an unit test to check the exception

* refactor: Refactor checkLicenses by extract method

* chore: Add javadoc comments and small fix for Gson

Signed-off-by: Taewan Kim <[email protected]>

---------

Signed-off-by: Taewan Kim <[email protected]>
  • Loading branch information
tiokim authored Jun 3, 2024
1 parent 03b112d commit bbb8dfb
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -146,108 +146,29 @@ public void runScan(LPVSQueue webhookConfig, String path) throws Exception {
public List<LPVSFile> checkLicenses(LPVSQueue webhookConfig) {
List<LPVSFile> 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<String, ArrayList<Object>> map =
gson.fromJson(
reader, new TypeToken<Map<String, ArrayList<Object>>>() {}.getType());

// parse map entries
long ind = 0L;
new Gson()
.fromJson(
reader,
new TypeToken<Map<String, ArrayList<Object>>>() {}.getType());
if (null == map) {
log.error("Error parsing Json File");
return detectedFiles;
}

// parse map entries
long ind = 0L;
for (Map.Entry<String, ArrayList<Object>> 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<LPVSLicense> 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<LPVSLicense> licenses = buildLicenseSet(object);
file.setLicenses(new HashSet<>(licenses));
if (!file.getLicenses().isEmpty()) detectedFiles.add(file);
}
Expand All @@ -261,6 +182,121 @@ public List<LPVSFile> 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<LPVSLicense> buildLicenseSet(ScanossJsonStructure object) {
if (object.licenses == null) {
return new HashSet<>();
}

Set<LPVSLicense> 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<String, ArrayList<Object>> 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.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.*;
Expand All @@ -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.*;
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down

0 comments on commit bbb8dfb

Please sign in to comment.