diff --git a/pom.xml b/pom.xml index 970e4b97..5828e74c 100644 --- a/pom.xml +++ b/pom.xml @@ -136,6 +136,10 @@ h2 2.2.220 + + org.springframework.boot + spring-boot-starter-validation + diff --git a/src/main/java/com/lpvs/controller/GitHubWebhooksController.java b/src/main/java/com/lpvs/controller/GitHubController.java similarity index 67% rename from src/main/java/com/lpvs/controller/GitHubWebhooksController.java rename to src/main/java/com/lpvs/controller/GitHubController.java index 4c7af690..8ab53230 100644 --- a/src/main/java/com/lpvs/controller/GitHubWebhooksController.java +++ b/src/main/java/com/lpvs/controller/GitHubController.java @@ -7,6 +7,7 @@ package com.lpvs.controller; import com.lpvs.entity.LPVSQueue; +import com.lpvs.entity.enums.LPVSPullRequestAction; import com.lpvs.repository.LPVSQueueRepository; import com.lpvs.service.LPVSGitHubService; import com.lpvs.service.LPVSQueueService; @@ -15,17 +16,18 @@ import com.lpvs.entity.LPVSResponseWrapper; import lombok.extern.slf4j.Slf4j; +import javax.validation.Valid; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotEmpty; import org.apache.commons.codec.binary.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.util.StringUtils; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.util.HtmlUtils; + import java.util.Date; import java.util.Optional; import javax.annotation.PostConstruct; @@ -38,7 +40,7 @@ */ @RestController @Slf4j -public class GitHubWebhooksController { +public class GitHubController { /** * The GitHub secret used for validating webhook payloads. @@ -90,7 +92,7 @@ public void initializeGitHubSecret() { private static final String ALGORITHM = "HmacSHA256"; /** - * Constructor for GitHubWebhooksController. + * Constructor for GitHubController. * Initializes LPVSQueueService, LPVSGitHubService, LPVSQueueRepository, GitHub secret, and LPVSExitHandler. * * @param queueService LPVSQueueService for handling user-related business logic. @@ -99,7 +101,7 @@ public void initializeGitHubSecret() { * @param GITHUB_SECRET The GitHub secret used for validating webhook payloads. * @param exitHandler LPVSExitHandler for handling application exit scenarios. */ - public GitHubWebhooksController( + public GitHubController( LPVSQueueService queueService, LPVSGitHubService gitHubService, LPVSQueueRepository queueRepository, @@ -166,6 +168,68 @@ public ResponseEntity gitHubWebhooks( .body(new LPVSResponseWrapper(SUCCESS)); } + /** + * Handles a GitHub single scan request. + * + * This endpoint performs a single scan operation based on the GitHub organization, repository, + * and pull request number provided in the path variables. The method validates + * the input parameters and performs necessary security checks. + * + * @param gitHubOrg The GitHub organization name. Must not be empty and should be a valid string. + * @param gitHubRepo The GitHub repository name. Must not be empty and should be a valid string. + * @param prNumber The pull request number. Must be a positive integer greater than or equal to 1. + * @return ResponseEntity with LPVSResponseWrapper containing the result of the scan. + * If successful, returns HTTP 200 OK with the success message. + * If there are validation errors or security issues, returns HTTP 403 FORBIDDEN. + */ + @RequestMapping( + value = "/scan/{gitHubUrl}/{gitHubOrg}/{gitHubRepo}/{prNumber}", + method = RequestMethod.POST) + public ResponseEntity gitHubSingleScan( + @PathVariable("gitHubUrl") @NotEmpty @Valid String gitHubUrl, + @PathVariable("gitHubOrg") @NotEmpty @Valid String gitHubOrg, + @PathVariable("gitHubRepo") @NotEmpty @Valid String gitHubRepo, + @PathVariable("prNumber") @Min(1) @Valid Integer prNumber) + throws InterruptedException { + log.debug("New GitHub single scan request received"); + + if (GITHUB_SECRET.trim().isEmpty()) { + log.error("Received empty GITHUB_SECRET"); + return ResponseEntity.status(HttpStatus.FORBIDDEN) + .headers(LPVSWebhookUtil.generateSecurityHeaders()) + .body(new LPVSResponseWrapper(ERROR)); + } + + // Validate and sanitize user inputs to prevent XSS attacks + gitHubUrl = HtmlUtils.htmlEscape(gitHubUrl); + gitHubOrg = HtmlUtils.htmlEscape(gitHubOrg); + gitHubRepo = HtmlUtils.htmlEscape(gitHubRepo); + + String prUrl = "https://" + gitHubUrl + "/" + gitHubOrg + "/" + gitHubRepo + "/pull/" + prNumber; + LPVSQueue scanConfig = + gitHubService.getInternalQueueByPullRequest(HtmlUtils.htmlEscape(prUrl)); + if (scanConfig == null) { + log.error("Error with connection to GitHub."); + return ResponseEntity.status(HttpStatus.FORBIDDEN) + .headers(LPVSWebhookUtil.generateSecurityHeaders()) + .body(new LPVSResponseWrapper(ERROR)); + } + scanConfig.setAction(LPVSPullRequestAction.SINGLE_SCAN); + scanConfig.setAttempts(0); + scanConfig.setDate(new Date()); + scanConfig.setReviewSystemType("github"); + queueRepository.save(scanConfig); + log.debug("Pull request scanning is enabled"); + gitHubService.setPendingCheck(scanConfig); + log.debug("Set status to Pending done"); + queueService.addFirst(scanConfig); + log.debug("Put Scan config to the queue done"); + log.debug("Response sent"); + return ResponseEntity.ok() + .headers(LPVSWebhookUtil.generateSecurityHeaders()) + .body(new LPVSResponseWrapper(SUCCESS)); + } + /** * Verifies if the signature matches the calculated signature using the GitHub secret. * diff --git a/src/main/java/com/lpvs/controller/package-info.java b/src/main/java/com/lpvs/controller/package-info.java index 321d8a2e..214570b9 100644 --- a/src/main/java/com/lpvs/controller/package-info.java +++ b/src/main/java/com/lpvs/controller/package-info.java @@ -9,7 +9,7 @@ * This package contains the controller classes for handling various aspects of the License Pre-Validation Service (LPVS). * Controllers in this package manage interactions related to GitHub webhooks, user interfaces, and API endpoints. *

- * - {@link com.lpvs.controller.GitHubWebhooksController}: Manages GitHub webhook events, processes payloads, and interacts + * - {@link com.lpvs.controller.GitHubController}: Manages GitHub webhook events, processes payloads, and interacts * with LPVS services for queue handling and GitHub operations. *

* - {@link com.lpvs.controller.LPVSWebController}: Controls the web interface and API endpoints for LPVS, including user diff --git a/src/main/java/com/lpvs/entity/enums/LPVSPullRequestAction.java b/src/main/java/com/lpvs/entity/enums/LPVSPullRequestAction.java index 2ead8219..d73bbe43 100644 --- a/src/main/java/com/lpvs/entity/enums/LPVSPullRequestAction.java +++ b/src/main/java/com/lpvs/entity/enums/LPVSPullRequestAction.java @@ -35,7 +35,12 @@ public enum LPVSPullRequestAction { /** * Represents the action of triggering a rescan of a pull request. */ - RESCAN("rescan"); + RESCAN("rescan"), + + /** + * Represents the action of triggering a manual single scan of a pull request. + */ + SINGLE_SCAN("single-scan"); /** * The string representation of the pull request action. @@ -77,6 +82,8 @@ public static LPVSPullRequestAction convertFrom(String action) { return UPDATE; } else if (action.equals(RESCAN.getPullRequestAction())) { return RESCAN; + } else if (action.equals(SINGLE_SCAN.getPullRequestAction())) { + return SINGLE_SCAN; } else { return null; } diff --git a/src/main/java/com/lpvs/service/LPVSDetectService.java b/src/main/java/com/lpvs/service/LPVSDetectService.java index 98cf9bd6..3edc31cd 100644 --- a/src/main/java/com/lpvs/service/LPVSDetectService.java +++ b/src/main/java/com/lpvs/service/LPVSDetectService.java @@ -13,9 +13,6 @@ import com.lpvs.util.LPVSFileUtil; import lombok.extern.slf4j.Slf4j; -import org.kohsuke.github.GHPullRequest; -import org.kohsuke.github.GHRepository; -import org.kohsuke.github.GitHub; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.ExitCodeEvent; @@ -28,12 +25,10 @@ import javax.annotation.PostConstruct; -import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; /** @@ -63,6 +58,11 @@ public class LPVSDetectService { */ private LPVSLicenseService licenseService; + /** + * Service responsible for GitHub connection and operation. + */ + private LPVSGitHubService gitHubService; + /** * Event publisher for triggering application events. */ @@ -92,17 +92,20 @@ public class LPVSDetectService { * @param gitHubConnectionService Service for connecting to the GitHub API. * @param scanossDetectService Service for license detection using ScanOSS. * @param licenseService Service for license conflict analysis. + * @param gitHubService Service for GitHub connection and operation. */ @Autowired public LPVSDetectService( @Value("${scanner:scanoss}") String scannerType, LPVSGitHubConnectionService gitHubConnectionService, LPVSScanossDetectService scanossDetectService, - LPVSLicenseService licenseService) { + LPVSLicenseService licenseService, + LPVSGitHubService gitHubService) { this.scannerType = scannerType; this.gitHubConnectionService = gitHubConnectionService; this.scanossDetectService = scanossDetectService; this.licenseService = licenseService; + this.gitHubService = gitHubService; } /** @@ -122,12 +125,11 @@ public void runOneScan() { if (trigger != null && !HtmlUtils.htmlEscape(trigger).equals("")) { try { LPVSQueue webhookConfig = - this.getInternalQueueByPullRequest(HtmlUtils.htmlEscape(trigger)); + gitHubService.getInternalQueueByPullRequest(HtmlUtils.htmlEscape(trigger)); List scanResult = this.runScan( - webhookConfig, - LPVSDetectService.getPathByPullRequest(webhookConfig)); + webhookConfig, LPVSFileUtil.getPathByPullRequest(webhookConfig)); List> detectedConflicts = licenseService.findConflicts(webhookConfig, scanResult); @@ -162,73 +164,6 @@ public void runOneScan() { } } - /** - * Retrieves an LPVSQueue configuration based on the GitHub repository and pull request. - * - * @param repo The GitHub repository. - * @param pR The GitHub pull request. - * @return LPVSQueue configuration for the given GitHub repository and pull request. - */ - private static LPVSQueue getGitHubWebhookConfig(GHRepository repo, GHPullRequest pR) { - LPVSQueue webhookConfig = new LPVSQueue(); - webhookConfig.setPullRequestUrl( - pR.getHtmlUrl() != null ? pR.getHtmlUrl().toString() : null); - if (pR.getHead() != null - && pR.getHead().getRepository() != null - && pR.getHead().getRepository().getHtmlUrl() != null) { - webhookConfig.setPullRequestFilesUrl( - pR.getHead().getRepository().getHtmlUrl().toString()); - } else { - webhookConfig.setPullRequestFilesUrl(webhookConfig.getPullRequestUrl()); - } - webhookConfig.setPullRequestAPIUrl(pR.getUrl() != null ? pR.getUrl().toString() : null); - webhookConfig.setRepositoryUrl( - repo.getHtmlUrl() != null ? repo.getHtmlUrl().toString() : null); - webhookConfig.setUserId("Single scan run"); - webhookConfig.setHeadCommitSHA(pR.getHead() != null ? pR.getHead().getSha() : null); - return webhookConfig; - } - - /** - * Retrieves the LPVSQueue configuration for a given GitHub pull request URL. - * - * @param pullRequest The GitHub pull request URL. - * @return LPVSQueue configuration for the given pull request. - */ - public LPVSQueue getInternalQueueByPullRequest(String pullRequest) { - try { - if (pullRequest == null) return null; - String[] pullRequestSplit = pullRequest.split("/"); - if (pullRequestSplit.length < 5) return null; - String pullRequestRepo = - String.join( - "/", - Arrays.asList(pullRequestSplit) - .subList( - pullRequestSplit.length - 4, - pullRequestSplit.length - 2)); - int pullRequestNum = Integer.parseInt(pullRequestSplit[pullRequestSplit.length - 1]); - GitHub gitHub = gitHubConnectionService.connectToGitHubApi(); - GHRepository repo = gitHub.getRepository(pullRequestRepo); - GHPullRequest pR = repo.getPullRequest(pullRequestNum); - return LPVSDetectService.getGitHubWebhookConfig(repo, pR); - } catch (IOException e) { - log.error("Can't set up github client: " + e); - } - return null; - } - - /** - * Retrieves the local directory path for a given LPVSQueue configuration. - * - * @param webhookConfig LPVSQueue configuration. - * @return Local directory path for the given LPVSQueue. - */ - public static String getPathByPullRequest(LPVSQueue webhookConfig) { - if (webhookConfig == null) return null; - return LPVSFileUtil.getLocalDirectoryPath(webhookConfig); - } - /** * Runs a license scan based on the selected scanner type. * diff --git a/src/main/java/com/lpvs/service/LPVSGitHubService.java b/src/main/java/com/lpvs/service/LPVSGitHubService.java index 236d656a..7c2f9687 100644 --- a/src/main/java/com/lpvs/service/LPVSGitHubService.java +++ b/src/main/java/com/lpvs/service/LPVSGitHubService.java @@ -28,6 +28,7 @@ import org.springframework.stereotype.Service; import java.io.IOException; +import java.util.Arrays; import java.util.List; /** @@ -413,4 +414,35 @@ public String getRepositoryLicense(LPVSQueue webhookConfig) { } return "Proprietary"; } + + /** + * Retrieves the LPVSQueue configuration for a given GitHub pull request URL. + * + * @param pullRequest The GitHub pull request URL. + * @return LPVSQueue configuration for the given pull request. + */ + public LPVSQueue getInternalQueueByPullRequest(String pullRequest) { + try { + if (pullRequest == null) { + return null; + } + String[] pullRequestSplit = pullRequest.split("/"); + if (pullRequestSplit.length < 5) return null; + String pullRequestRepo = + String.join( + "/", + Arrays.asList(pullRequestSplit) + .subList( + pullRequestSplit.length - 4, + pullRequestSplit.length - 2)); + int pullRequestNum = Integer.parseInt(pullRequestSplit[pullRequestSplit.length - 1]); + GitHub gitHub = gitHubConnectionService.connectToGitHubApi(); + GHRepository repo = gitHub.getRepository(pullRequestRepo); + GHPullRequest pR = repo.getPullRequest(pullRequestNum); + return LPVSWebhookUtil.getGitHubWebhookConfig(repo, pR); + } catch (IOException e) { + log.error("Can't set up github client: " + e); + } + return null; + } } diff --git a/src/main/java/com/lpvs/service/LPVSQueueService.java b/src/main/java/com/lpvs/service/LPVSQueueService.java index 5847cfb8..beb0ebb6 100644 --- a/src/main/java/com/lpvs/service/LPVSQueueService.java +++ b/src/main/java/com/lpvs/service/LPVSQueueService.java @@ -214,8 +214,8 @@ public LPVSQueue getLatestScan(List webhookConfigList) { public void processWebHook(LPVSQueue webhookConfig) throws IOException { LPVSPullRequest pullRequest = new LPVSPullRequest(); try { - log.info("GitHub Webhook processing..."); - log.info(webhookConfig.toString()); + log.info("GitHub queue processing..."); + log.debug(webhookConfig.toString()); String filePath = gitHubService.getPullRequestFiles(webhookConfig); diff --git a/src/main/java/com/lpvs/util/LPVSFileUtil.java b/src/main/java/com/lpvs/util/LPVSFileUtil.java index 64db0ae1..7fe1643c 100644 --- a/src/main/java/com/lpvs/util/LPVSFileUtil.java +++ b/src/main/java/com/lpvs/util/LPVSFileUtil.java @@ -196,4 +196,15 @@ public static String getScanResultsDirectoryPath(LPVSQueue webhookConfig) { + "Results/" + LPVSWebhookUtil.getRepositoryName(webhookConfig); } + + /** + * Retrieves the local directory path for a given LPVSQueue configuration. + * + * @param webhookConfig LPVSQueue configuration. + * @return Local directory path for the given LPVSQueue. + */ + public static String getPathByPullRequest(LPVSQueue webhookConfig) { + if (webhookConfig == null) return null; + return getLocalDirectoryPath(webhookConfig); + } } diff --git a/src/main/java/com/lpvs/util/LPVSWebhookUtil.java b/src/main/java/com/lpvs/util/LPVSWebhookUtil.java index a63b74c5..0e049dcd 100644 --- a/src/main/java/com/lpvs/util/LPVSWebhookUtil.java +++ b/src/main/java/com/lpvs/util/LPVSWebhookUtil.java @@ -11,6 +11,8 @@ import com.lpvs.entity.LPVSQueue; import com.lpvs.entity.enums.LPVSPullRequestAction; import lombok.extern.slf4j.Slf4j; +import org.kohsuke.github.GHPullRequest; +import org.kohsuke.github.GHRepository; import org.springframework.http.HttpHeaders; import java.util.Arrays; @@ -231,4 +233,31 @@ public static HttpHeaders generateSecurityHeaders() { return headers; } + + /** + * Retrieves an LPVSQueue configuration based on the GitHub repository and pull request. + * + * @param repo The GitHub repository. + * @param pR The GitHub pull request. + * @return LPVSQueue configuration for the given GitHub repository and pull request. + */ + public static LPVSQueue getGitHubWebhookConfig(GHRepository repo, GHPullRequest pR) { + LPVSQueue webhookConfig = new LPVSQueue(); + webhookConfig.setPullRequestUrl( + pR.getHtmlUrl() != null ? pR.getHtmlUrl().toString() : null); + if (pR.getHead() != null + && pR.getHead().getRepository() != null + && pR.getHead().getRepository().getHtmlUrl() != null) { + webhookConfig.setPullRequestFilesUrl( + pR.getHead().getRepository().getHtmlUrl().toString()); + } else { + webhookConfig.setPullRequestFilesUrl(webhookConfig.getPullRequestUrl()); + } + webhookConfig.setPullRequestAPIUrl(pR.getUrl() != null ? pR.getUrl().toString() : null); + webhookConfig.setRepositoryUrl( + repo.getHtmlUrl() != null ? repo.getHtmlUrl().toString() : null); + webhookConfig.setUserId("Single scan run"); + webhookConfig.setHeadCommitSHA(pR.getHead() != null ? pR.getHead().getSha() : null); + return webhookConfig; + } } diff --git a/src/test/java/com/lpvs/controller/GitHubWebhooksControllerTest.java b/src/test/java/com/lpvs/controller/GitHubControllerTest.java similarity index 89% rename from src/test/java/com/lpvs/controller/GitHubWebhooksControllerTest.java rename to src/test/java/com/lpvs/controller/GitHubControllerTest.java index d8f8ed8d..1b4189a0 100644 --- a/src/test/java/com/lpvs/controller/GitHubWebhooksControllerTest.java +++ b/src/test/java/com/lpvs/controller/GitHubControllerTest.java @@ -23,7 +23,7 @@ import static org.mockito.Mockito.mock; @Slf4j -public class GitHubWebhooksControllerTest { +public class GitHubControllerTest { private static final String SIGNATURE = "X-Hub-Signature-256"; private static final String SUCCESS = "Success"; @@ -34,8 +34,8 @@ public class GitHubWebhooksControllerTest { LPVSQueueService mocked_instance_queueServ = mock(LPVSQueueService.class); LPVSGitHubService mocked_instance_ghServ = mock(LPVSGitHubService.class); LPVSQueueRepository mocked_queueRepo = mock(LPVSQueueRepository.class); - GitHubWebhooksController gitHubWebhooksController = - new GitHubWebhooksController( + GitHubController gitHubController = + new GitHubController( mocked_instance_queueServ, mocked_instance_ghServ, mocked_queueRepo, @@ -46,7 +46,7 @@ public class GitHubWebhooksControllerTest { public void noSignatureTest() { ResponseEntity actual; try { - actual = gitHubWebhooksController.gitHubWebhooks(null, null); + actual = gitHubController.gitHubWebhooks(null, null); } catch (Exception e) { actual = null; } @@ -59,7 +59,7 @@ public void noSignatureTest() { public void noPayloadTest() { ResponseEntity actual; try { - actual = gitHubWebhooksController.gitHubWebhooks(SIGNATURE, null); + actual = gitHubController.gitHubWebhooks(SIGNATURE, null); } catch (Exception e) { actual = null; } @@ -109,7 +109,7 @@ public void okTest() { + "}"; try { - actual = gitHubWebhooksController.gitHubWebhooks(SIGNATURE, json_to_test); + actual = gitHubController.gitHubWebhooks(SIGNATURE, json_to_test); } catch (Exception e) { log.error(e.getMessage()); actual = null; @@ -148,13 +148,13 @@ public void wrongSecretTest() { + "}" + "}"; try { - gitHubWebhooksController.initializeGitHubSecret(); - boolean secret = gitHubWebhooksController.wrongSecret(signature, json_to_test); + gitHubController.initializeGitHubSecret(); + boolean secret = gitHubController.wrongSecret(signature, json_to_test); assertEquals(secret, false); - secret = gitHubWebhooksController.wrongSecret(signature + " ", json_to_test); + secret = gitHubController.wrongSecret(signature + " ", json_to_test); assertEquals(secret, true); } catch (Exception e) { - log.error("GitHubWebhooksControllerTest::wrongSecretTest exception: " + e); + log.error("GitHubControllerTest::wrongSecretTest exception: " + e); fail(); } } diff --git a/src/test/java/com/lpvs/service/LPVSDetectServiceTest.java b/src/test/java/com/lpvs/service/LPVSDetectServiceTest.java index fcfe3b41..907e77ea 100644 --- a/src/test/java/com/lpvs/service/LPVSDetectServiceTest.java +++ b/src/test/java/com/lpvs/service/LPVSDetectServiceTest.java @@ -11,6 +11,7 @@ import com.lpvs.service.scanner.scanoss.LPVSScanossDetectService; import com.lpvs.util.LPVSCommentUtil; +import com.lpvs.util.LPVSFileUtil; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.BeforeEach; @@ -24,8 +25,6 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.boot.context.event.ApplicationReadyEvent; -import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationEventPublisher; import java.io.IOException; @@ -39,7 +38,6 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; @@ -51,25 +49,14 @@ public class LPVSDetectServiceTest { @Mock private ApplicationEventPublisher mockEventPublisher; - @Mock private LPVSGitHubConnectionService gitHubConnectionService; - - @Mock private GitHub gitHub; - - @Mock private GHRepository ghRepository; - - @Mock private GHPullRequest ghPullRequest; - @Mock private LPVSScanossDetectService scanossDetectService; - @Mock private ApplicationContext applicationContext; - - @Mock private ApplicationReadyEvent applicationReadyEvent; - @InjectMocks private LPVSDetectService lpvsDetectService; @Nested class TestInit { - final LPVSDetectService detectService = new LPVSDetectService("scanoss", null, null, null); + final LPVSDetectService detectService = + new LPVSDetectService("scanoss", null, null, null, null); @Test public void testInit() { @@ -90,6 +77,7 @@ class TestRunScan__Scanoss { LPVSGitHubConnectionService github_mock = mock(LPVSGitHubConnectionService.class); LPVSScanossDetectService scanoss_mock = mock(LPVSScanossDetectService.class); LPVSLicenseService licenseservice_mock = mock(LPVSLicenseService.class); + LPVSGitHubService githubservice_mock = mock(LPVSGitHubService.class); GitHub mockGitHub = mock(GitHub.class); GHCommitPointer mockCommitPointer = mock(GHCommitPointer.class); GHRepository mockRepository = mock(GHRepository.class); @@ -105,7 +93,11 @@ class TestRunScan__Scanoss { void setUp() throws IOException { detectService = new LPVSDetectService( - "scanoss", github_mock, scanoss_mock, licenseservice_mock); + "scanoss", + github_mock, + scanoss_mock, + licenseservice_mock, + githubservice_mock); webhookConfig = new LPVSQueue(); webhookConfig.setId(1L); @@ -127,7 +119,7 @@ void setUp() throws IOException { @Test void testRunOneScanWithNullTriger() throws NoSuchFieldException, IllegalAccessException { lpvsDetectService = - spy(new LPVSDetectService("scanoss", null, scanossDetectService, null)); + spy(new LPVSDetectService("scanoss", null, scanossDetectService, null, null)); setPrivateField(lpvsDetectService, "trigger", null); setPrivateField(lpvsDetectService, "eventPublisher", mockEventPublisher); @@ -143,7 +135,7 @@ void testRunOneScanWithNullTriger() throws NoSuchFieldException, IllegalAccessEx void testRunOneScan_Default() throws NoSuchFieldException, IllegalAccessException { lpvsDetectService = - spy(new LPVSDetectService("scanoss", null, scanossDetectService, null)); + spy(new LPVSDetectService("scanoss", null, scanossDetectService, null, null)); setPrivateField(lpvsDetectService, "trigger", "fake-trigger-value"); setPrivateField(lpvsDetectService, "eventPublisher", mockEventPublisher); @@ -162,7 +154,7 @@ void testRunOneScan_Branch2() List.of(conflict_1, conflict_1); lpvsDetectService = - spy(new LPVSDetectService("scanoss", null, scanossDetectService, null)); + spy(new LPVSDetectService("scanoss", null, scanossDetectService, null, null)); // Mock the necessary GitHub objects for LPVSQueue when(mockGitHub.getRepository(any())).thenReturn(mockRepository); @@ -204,7 +196,7 @@ void testRunOneScan_Branch3() doNothing().when(mockEventPublisher).publishEvent(any()); lpvsDetectService = - spy(new LPVSDetectService("scanoss", null, scanossDetectService, null)); + spy(new LPVSDetectService("scanoss", null, scanossDetectService, null, null)); setPrivateField(detectService, "trigger", "github/owner/repo/branch/123"); setPrivateField(detectService, "scannerType", "scanoss"); @@ -329,7 +321,6 @@ void testRunOneScan_TriggerNotNull_Branch3() throws Exception { when(mockPullRequest.getHead()).thenReturn(mockCommitPointer); when(licenseservice_mock.findConflicts(webhookConfig, null)).thenReturn(expected); when(mockCommitPointer.getRepository()).thenReturn(mockHeadRepository2); - when(mockHeadRepository2.getHtmlUrl()).thenReturn(null); // Set up expected values String expectedPullRequestUrl = "https://example.com/pull/1"; @@ -361,45 +352,12 @@ void testCommentBuilder_ConflictFilePresent() throws Exception { assertNotNull(commentHTML); } - @Test - void testGetInternalQueueByPullRequestWithNull() throws IOException { - LPVSQueue result = lpvsDetectService.getInternalQueueByPullRequest(null); - assertNull(result); - } - - @Test - void testGetInternalQueueByPullRequest() throws IOException { - String pullRequest = "github/owner/repo/branch/123"; - when(gitHubConnectionService.connectToGitHubApi()).thenReturn(gitHub); - when(gitHub.getRepository("owner/repo")).thenReturn(ghRepository); - when(ghRepository.getPullRequest(123)).thenReturn(ghPullRequest); - - LPVSQueue result = lpvsDetectService.getInternalQueueByPullRequest(pullRequest); - - assertNotNull(result); - assertEquals(result.getUserId(), "Single scan run"); - } - - @Test - void testGetInternalQueueByPullRequestError() throws IOException { - String pullRequest = "github/owner/repo/branch/123"; - - when(gitHubConnectionService.connectToGitHubApi()).thenThrow(IOException.class); - - try { - LPVSQueue result = lpvsDetectService.getInternalQueueByPullRequest(pullRequest); - assertNull(result, "Expected result to be null"); - } catch (Exception e) { - fail("Exception not expected to be thrown here"); - } - } - @Test public void testGetPathByPullRequest() { LPVSQueue mockWebhookConfig = mock(LPVSQueue.class); - String result = LPVSDetectService.getPathByPullRequest(mockWebhookConfig); + String result = LPVSFileUtil.getPathByPullRequest(mockWebhookConfig); assertNotNull(result); } @@ -434,6 +392,7 @@ class TestRunScan__ScanossException { LPVSGitHubConnectionService github_mock = mock(LPVSGitHubConnectionService.class); LPVSScanossDetectService scanoss_mock = mock(LPVSScanossDetectService.class); LPVSLicenseService licenseservice_mock = mock(LPVSLicenseService.class); + LPVSGitHubService githubservice_mock = mock(LPVSGitHubService.class); LPVSQueue webhookConfig; final String test_path = "test_path"; @@ -443,7 +402,11 @@ class TestRunScan__ScanossException { void setUp() { detectService = new LPVSDetectService( - "scanoss", github_mock, scanoss_mock, licenseservice_mock); + "scanoss", + github_mock, + scanoss_mock, + licenseservice_mock, + githubservice_mock); webhookConfig = new LPVSQueue(); webhookConfig.setId(1L); @@ -488,7 +451,7 @@ class TestRunScan__NotScanoss { @BeforeEach void setUp() { - detectService = new LPVSDetectService("not_scanoss", null, null, null); + detectService = new LPVSDetectService("not_scanoss", null, null, null, null); } @Test diff --git a/src/test/java/com/lpvs/service/LPVSGitHubServiceTest.java b/src/test/java/com/lpvs/service/LPVSGitHubServiceTest.java index 1f62098b..ddaa6694 100644 --- a/src/test/java/com/lpvs/service/LPVSGitHubServiceTest.java +++ b/src/test/java/com/lpvs/service/LPVSGitHubServiceTest.java @@ -24,11 +24,11 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.junitpioneer.jupiter.SetEnvironmentVariable; import org.kohsuke.github.*; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; +import org.mockito.*; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.test.util.ReflectionTestUtils; import java.io.IOException; @@ -48,6 +48,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; @Slf4j +@ExtendWith(MockitoExtension.class) public class LPVSGitHubServiceTest { /** @@ -60,6 +61,16 @@ public class LPVSGitHubServiceTest { */ private LPVSExitHandler exitHandler; + @Mock private GitHub gitHub; + + @Mock private GHRepository ghRepository; + + @Mock private GHPullRequest ghPullRequest; + + @Mock private LPVSGitHubConnectionService gitHubConnectionService; + + @InjectMocks private LPVSGitHubService gitHubService; + static class GHPullRequestOurMock extends GHPullRequest { private final URL mockedGetUrl; private final String mockedGetTitle; @@ -4316,25 +4327,10 @@ public void testCheckNotEmpty() String GH_LOGIN = ""; String GH_AUTH_TOKEN = "non-empty"; String GH_API_URL = ""; - LPVSPullRequestRepository mocked_pullRequestRepository = - mock(LPVSPullRequestRepository.class); - LPVSDetectedLicenseRepository mocked_lpvsDetectedLicenseRepository = - mock(LPVSDetectedLicenseRepository.class); - LPVSLicenseRepository mocked_lpvsLicenseRepository = mock(LPVSLicenseRepository.class); - LPVSLicenseConflictRepository mocked_lpvsLicenseConflictRepository = - mock(LPVSLicenseConflictRepository.class); LPVSExitHandler exitHandler = mock(LPVSExitHandler.class); LPVSGitHubConnectionService lpvsGitHubConnectionService = new LPVSGitHubConnectionService( GH_LOGIN, GH_AUTH_TOKEN, GH_API_URL, exitHandler); - - final LPVSGitHubService gh_service = - new LPVSGitHubService( - mocked_pullRequestRepository, - mocked_lpvsDetectedLicenseRepository, - mocked_lpvsLicenseRepository, - mocked_lpvsLicenseConflictRepository, - lpvsGitHubConnectionService); Method method = lpvsGitHubConnectionService.getClass().getDeclaredMethod("checks"); method.setAccessible(true); method.invoke(lpvsGitHubConnectionService); @@ -4342,4 +4338,42 @@ public void testCheckNotEmpty() verify(exitHandler, never()).exit(anyInt()); } } + + @Nested + class getInternalQueueByPullRequests { + + @Test + void testGetInternalQueueByPullRequestWithNull() { + LPVSQueue result = gitHubService.getInternalQueueByPullRequest(null); + assertNull(result); + } + + @Test + void testGetInternalQueueByPullRequest() throws IOException { + String pullRequest = "github/owner/repo/branch/123"; + + when(gitHubConnectionService.connectToGitHubApi()).thenReturn(gitHub); + when(gitHub.getRepository("owner/repo")).thenReturn(ghRepository); + when(ghRepository.getPullRequest(123)).thenReturn(ghPullRequest); + + LPVSQueue result = gitHubService.getInternalQueueByPullRequest(pullRequest); + + assertNotNull(result); + assertEquals(result.getUserId(), "Single scan run"); + } + + @Test + void testGetInternalQueueByPullRequestError() throws IOException { + String pullRequest = "github/owner/repo/branch/123"; + + when(gitHubConnectionService.connectToGitHubApi()).thenThrow(IOException.class); + + try { + LPVSQueue result = gitHubService.getInternalQueueByPullRequest(pullRequest); + assertNull(result, "Expected result to be null"); + } catch (Exception e) { + fail("Exception not expected to be thrown here"); + } + } + } }