diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2017-10-18 15:26:30 +0200 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@sonarsource.com> | 2017-10-20 13:09:23 +0200 |
commit | 48feb5a6bd658c638b0cdd03231d0799fde533c0 (patch) | |
tree | 43a1393b9cb137cee33a2c2a79b48245f956aef2 | |
parent | f3e111f489c0acc81239743ddcb5cef5b1717005 (diff) | |
download | sonarqube-48feb5a6bd658c638b0cdd03231d0799fde533c0.tar.gz sonarqube-48feb5a6bd658c638b0cdd03231d0799fde533c0.zip |
SONAR-8967 Fail fast when trying to analyse a module
5 files changed, 125 insertions, 163 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/ReportSubmitter.java b/server/sonar-server/src/main/java/org/sonar/server/computation/queue/ReportSubmitter.java index e6f63e2ef84..a4cc5bbf1c5 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/ReportSubmitter.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/queue/ReportSubmitter.java @@ -19,22 +19,17 @@ */ package org.sonar.server.computation.queue; -import static com.google.common.base.Preconditions.checkArgument; -import static java.lang.String.format; -import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION; -import static org.sonar.server.component.NewComponent.newComponentBuilder; -import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException; - +import com.google.common.base.Optional; import java.io.InputStream; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.stream.Collectors; - import javax.annotation.Nullable; - import org.apache.commons.lang.StringUtils; import org.sonar.api.resources.Qualifiers; +import org.sonar.api.resources.Scopes; import org.sonar.api.server.ServerSide; import org.sonar.ce.queue.CeQueue; import org.sonar.ce.queue.CeTask; @@ -50,11 +45,16 @@ import org.sonar.db.organization.OrganizationDto; import org.sonar.db.permission.OrganizationPermission; import org.sonar.server.component.ComponentUpdater; import org.sonar.server.component.NewComponent; +import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.permission.PermissionTemplateService; import org.sonar.server.user.UserSession; -import com.google.common.base.Optional; +import static com.google.common.base.Preconditions.checkArgument; +import static java.lang.String.format; +import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION; +import static org.sonar.server.component.NewComponent.newComponentBuilder; +import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException; @ServerSide public class ReportSubmitter { @@ -89,9 +89,10 @@ public class ReportSubmitter { try (DbSession dbSession = dbClient.openSession(false)) { OrganizationDto organizationDto = getOrganizationDtoOrFail(dbSession, organizationKey); String effectiveProjectKey = ComponentKeys.createKey(projectKey, projectBranch); - Optional<ComponentDto> opt = dbClient.componentDao().selectByKey(dbSession, effectiveProjectKey); - ensureOrganizationIsConsistent(opt, organizationDto); - ComponentDto project = opt.or(() -> createProject(dbSession, organizationDto, projectKey, projectBranch, projectName)); + Optional<ComponentDto> component = dbClient.componentDao().selectByKey(dbSession, effectiveProjectKey); + validateProject(dbSession, component, projectKey); + ensureOrganizationIsConsistent(component, organizationDto); + ComponentDto project = component.or(() -> createProject(dbSession, organizationDto, projectKey, projectBranch, projectName)); checkScanPermission(project); return submitReport(dbSession, reportInput, project, characteristics); } @@ -114,6 +115,28 @@ public class ReportSubmitter { .orElseThrow(() -> new NotFoundException(format("Organization with key '%s' does not exist", organizationKey))); } + private void validateProject(DbSession dbSession, Optional<ComponentDto> project, String rawProjectKey) { + List<String> errors = new ArrayList<>(); + if (!project.isPresent()) { + return; + } + + ComponentDto component = project.get(); + if (!Qualifiers.PROJECT.equals(component.qualifier()) || !Scopes.PROJECT.equals(component.scope())) { + errors.add(format("Component '%s' is not a project", rawProjectKey)); + } + if (!project.get().projectUuid().equals(project.get().uuid())) { + // Project key is already used as a module of another project + ComponentDto anotherBaseProject = dbClient.componentDao().selectOrFailByUuid(dbSession, project.get().projectUuid()); + errors.add(format("The project '%s' is already defined in SonarQube but as a module of project '%s'. " + + "If you really want to stop directly analysing project '%s', please first delete it from SonarQube and then relaunch the analysis of project '%s'.", + rawProjectKey, anotherBaseProject.getKey(), anotherBaseProject.getKey(), rawProjectKey)); + } + if (!errors.isEmpty()) { + throw BadRequestException.create(errors); + } + } + private static void ensureOrganizationIsConsistent(Optional<ComponentDto> project, OrganizationDto organizationDto) { if (project.isPresent()) { checkArgument(project.get().getOrganizationUuid().equals(organizationDto.getUuid()), diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ValidateProjectStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ValidateProjectStep.java index 62cf283c8ec..27ef9e45b81 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ValidateProjectStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ValidateProjectStep.java @@ -25,8 +25,6 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.resources.Scopes; import org.sonar.api.utils.MessageException; import org.sonar.core.component.ComponentKeys; import org.sonar.db.DbClient; @@ -51,8 +49,7 @@ import static org.sonar.api.utils.DateUtils.formatDateTime; /** * Validate project and modules. It will fail in the following cases : * <ol> - * <li>branch is not valid</li> - * <li>project or module key is not valid</li> + * <li>module key is not valid</li> * <li>module key already exists in another project (same module key cannot exists in different projects)</li> * <li>module key is already used as a project key</li> * <li>date of the analysis is before last analysis</li> @@ -115,34 +112,11 @@ public class ValidateProjectStep implements ComputationStep { public void visitProject(Component rawProject) { this.rawProject = rawProject; String rawProjectKey = rawProject.getKey(); - validateBatchKey(rawProject); Optional<ComponentDto> baseProject = loadBaseComponent(rawProjectKey); - validateRootIsProject(baseProject); - validateProjectKey(baseProject, rawProjectKey); validateAnalysisDate(baseProject); } - private void validateRootIsProject(Optional<ComponentDto> baseProject) { - if (baseProject.isPresent()) { - ComponentDto componentDto = baseProject.get(); - // the scope field is verified for excluding the project copies generated by portfolios - if (!Qualifiers.PROJECT.equals(componentDto.qualifier()) || !Scopes.PROJECT.equals(componentDto.scope())) { - validationMessages.add(format("Component (uuid=%s, key=%s) is not a project", rawProject.getUuid(), rawProject.getKey())); - } - } - } - - private void validateProjectKey(Optional<ComponentDto> baseProject, String rawProjectKey) { - if (baseProject.isPresent() && !baseProject.get().projectUuid().equals(baseProject.get().uuid())) { - // Project key is already used as a module of another project - ComponentDto anotherBaseProject = componentDao.selectOrFailByUuid(session, baseProject.get().projectUuid()); - validationMessages.add(format("The project \"%s\" is already defined in SonarQube but as a module of project \"%s\". " - + "If you really want to stop directly analysing project \"%s\", please first delete it from SonarQube and then relaunch the analysis of project \"%s\".", - rawProjectKey, anotherBaseProject.getDbKey(), anotherBaseProject.getDbKey(), rawProjectKey)); - } - } - private void validateAnalysisDate(Optional<ComponentDto> baseProject) { if (baseProject.isPresent()) { java.util.Optional<SnapshotDto> snapshotDto = dbClient.snapshotDao().selectLastAnalysisByRootComponentUuid(session, baseProject.get().uuid()); diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/queue/ReportSubmitterTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/queue/ReportSubmitterTest.java index 6c947ae6501..814c229af00 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/queue/ReportSubmitterTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/queue/ReportSubmitterTest.java @@ -48,14 +48,17 @@ import org.sonar.db.organization.OrganizationDto; import org.sonar.db.permission.OrganizationPermission; import org.sonar.server.component.ComponentUpdater; import org.sonar.server.component.NewComponent; +import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.favorite.FavoriteUpdater; import org.sonar.server.permission.PermissionTemplateService; import org.sonar.server.tester.UserSessionRule; +import static java.lang.String.format; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; +import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.argThat; @@ -65,6 +68,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION; +import static org.sonar.db.component.ComponentTesting.newModuleDto; import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; import static org.sonar.db.permission.OrganizationPermission.PROVISION_PROJECTS; import static org.sonar.db.permission.OrganizationPermission.SCAN; @@ -77,7 +81,7 @@ public class ReportSubmitterTest { private static final String TASK_UUID = "TASK_1"; @Rule - public ExpectedException thrown = ExpectedException.none(); + public ExpectedException expectedException = ExpectedException.none(); @Rule public UserSessionRule userSession = UserSessionRule.standalone(); @Rule @@ -100,24 +104,6 @@ public class ReportSubmitterTest { } @Test - public void submit_fails_with_NotFoundException_if_organization_with_specified_key_does_not_exist() { - thrown.expect(NotFoundException.class); - thrown.expectMessage("Organization with key 'fop' does not exist"); - - underTest.submit("fop", PROJECT_KEY, null, null, null /* method will fail before parameter is used */); - } - - @Test - public void submit_fails_with_organizationKey_does_not_match_organization_of_specified_component() { - userSession.logIn().setRoot(); - OrganizationDto organization = db.organizations().insert(); - ComponentDto project = db.components().insertPrivateProject(organization); - mockSuccessfulPrepareSubmitCall(); - - underTest.submit(organization.getKey(), project.getDbKey(), null, project.name(), IOUtils.toInputStream("{binary}")); - } - - @Test public void submit_inserts_characteristics() { userSession .addPermission(OrganizationPermission.SCAN, db.getDefaultOrganization().getUuid()) @@ -128,7 +114,7 @@ public class ReportSubmitterTest { when(componentUpdater.create(any(DbSession.class), any(NewComponent.class), eq(null))).thenReturn(project); when(permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(DbSession.class), eq(defaultOrganizationUuid), anyInt(), eq(PROJECT_KEY), eq(Qualifiers.PROJECT))) - .thenReturn(true); + .thenReturn(true); Map<String, String> taskCharacteristics = new HashMap<>(); taskCharacteristics.put("incremental", "true"); @@ -184,7 +170,7 @@ public class ReportSubmitterTest { when(componentUpdater.create(any(DbSession.class), any(NewComponent.class), eq(null))).thenReturn(createdProject); when( permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(DbSession.class), eq(organization.getUuid()), anyInt(), eq(PROJECT_KEY), eq(Qualifiers.PROJECT))) - .thenReturn(true); + .thenReturn(true); when(permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(any(DbSession.class), eq(organization.getUuid()), any(ComponentDto.class))).thenReturn(true); underTest.submit(organization.getKey(), PROJECT_KEY, null, PROJECT_NAME, IOUtils.toInputStream("{binary}")); @@ -215,7 +201,7 @@ public class ReportSubmitterTest { when(componentUpdater.create(any(DbSession.class), any(NewComponent.class), eq(null))).thenReturn(createdProject); when(permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(DbSession.class), eq(defaultOrganizationUuid), anyInt(), eq(PROJECT_KEY), eq(Qualifiers.PROJECT))) - .thenReturn(true); + .thenReturn(true); when(permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(any(DbSession.class), eq(defaultOrganizationUuid), any(ComponentDto.class))).thenReturn(false); underTest.submit(defaultOrganizationKey, PROJECT_KEY, null, PROJECT_NAME, IOUtils.toInputStream("{binary}")); @@ -234,7 +220,7 @@ public class ReportSubmitterTest { when(componentUpdater.create(any(DbSession.class), any(NewComponent.class), eq(null))).thenReturn(project); when(permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(DbSession.class), eq(defaultOrganizationUuid), anyInt(), eq(PROJECT_KEY), eq(Qualifiers.PROJECT))) - .thenReturn(true); + .thenReturn(true); underTest.submit(defaultOrganizationKey, PROJECT_KEY, null, PROJECT_NAME, IOUtils.toInputStream("{binary}")); @@ -266,38 +252,86 @@ public class ReportSubmitterTest { verify(queue).submit(any(CeTaskSubmit.class)); } + /** + * SONAR-8757 + */ @Test - public void fail_with_forbidden_exception_when_no_scan_permission() { - thrown.expect(ForbiddenException.class); + public void project_branch_must_not_benefit_from_the_scan_permission_on_main_project() { + ComponentDto mainProject = db.components().insertPrivateProject(); + userSession.addProjectPermission(GlobalPermissions.SCAN_EXECUTION, mainProject); - underTest.submit(defaultOrganizationKey, PROJECT_KEY, null, PROJECT_NAME, IOUtils.toInputStream("{binary}")); + // user does not have the "scan" permission on the branch, so it can't scan it + String branchName = "branchFoo"; + ComponentDto branchProject = db.components().insertPrivateProject(p -> p.setDbKey(mainProject.getDbKey() + ":" + branchName)); + + expectedException.expect(ForbiddenException.class); + underTest.submit(defaultOrganizationKey, mainProject.getDbKey(), branchName, PROJECT_NAME, IOUtils.toInputStream("{binary}")); } @Test - public void fail_with_forbidden_exception_on_new_project_when_only_project_scan_permission() { - userSession.addProjectPermission(SCAN_EXECUTION, ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization(), PROJECT_UUID)); + public void fail_with_NotFoundException_if_organization_with_specified_key_does_not_exist() { + expectedException.expect(NotFoundException.class); + expectedException.expectMessage("Organization with key 'fop' does not exist"); + + underTest.submit("fop", PROJECT_KEY, null, null, null /* method will fail before parameter is used */); + } + @Test + public void fail_with_organizationKey_does_not_match_organization_of_specified_component() { + userSession.logIn().setRoot(); + OrganizationDto organization = db.organizations().insert(); + ComponentDto project = db.components().insertPrivateProject(organization); mockSuccessfulPrepareSubmitCall(); - when(componentUpdater.create(any(DbSession.class), any(NewComponent.class), eq(null))).thenReturn(new ComponentDto().setUuid(PROJECT_UUID).setDbKey(PROJECT_KEY)); - thrown.expect(ForbiddenException.class); + underTest.submit(organization.getKey(), project.getDbKey(), null, project.name(), IOUtils.toInputStream("{binary}")); + } + + @Test + public void fail_if_component_is_not_a_project() { + ComponentDto component = db.components().insertPublicPortfolio(db.getDefaultOrganization()); + userSession.logIn().addProjectPermission(SCAN_EXECUTION, component); + mockSuccessfulPrepareSubmitCall(); + + expectedException.expect(BadRequestException.class); + expectedException.expectMessage(format("Component '%s' is not a project", component.getKey())); + + underTest.submit(defaultOrganizationKey, component.getDbKey(), null, component.name(), IOUtils.toInputStream("{binary}")); + } + + @Test + public void fail_if_project_key_already_exists_as_module() { + ComponentDto project = db.components().insertPrivateProject(db.getDefaultOrganization()); + ComponentDto module = db.components().insertComponent(newModuleDto(project)); + userSession.logIn().addProjectPermission(SCAN_EXECUTION, project); + mockSuccessfulPrepareSubmitCall(); + + try { + underTest.submit(defaultOrganizationKey, module.getDbKey(), null, module.name(), IOUtils.toInputStream("{binary}")); + fail(); + } catch (BadRequestException e) { + assertThat(e.errors()).contains( + format("The project '%s' is already defined in SonarQube but as a module of project '%s'. " + + "If you really want to stop directly analysing project '%s', please first delete it from SonarQube and then relaunch the analysis of project '%s'.", + module.getKey(), project.getKey(), project.getKey(), module.getKey())); + } + } + + @Test + public void fail_with_forbidden_exception_when_no_scan_permission() { + expectedException.expect(ForbiddenException.class); + underTest.submit(defaultOrganizationKey, PROJECT_KEY, null, PROJECT_NAME, IOUtils.toInputStream("{binary}")); } - /** - * SONAR-8757 - */ @Test - public void project_branch_must_not_benefit_from_the_scan_permission_on_main_project() { - ComponentDto mainProject = db.components().insertPrivateProject(); - userSession.addProjectPermission(GlobalPermissions.SCAN_EXECUTION, mainProject); + public void fail_with_forbidden_exception_on_new_project_when_only_project_scan_permission() { + userSession.addProjectPermission(SCAN_EXECUTION, ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization(), PROJECT_UUID)); - // user does not have the "scan" permission on the branch, so it can't scan it - String branchName = "branchFoo"; - ComponentDto branchProject = db.components().insertPrivateProject(p -> p.setDbKey(mainProject.getDbKey() + ":" + branchName)); + mockSuccessfulPrepareSubmitCall(); + when(componentUpdater.create(any(DbSession.class), any(NewComponent.class), eq(null))).thenReturn(new ComponentDto().setUuid(PROJECT_UUID).setDbKey(PROJECT_KEY)); - thrown.expect(ForbiddenException.class); - underTest.submit(defaultOrganizationKey, mainProject.getDbKey(), branchName, PROJECT_NAME, IOUtils.toInputStream("{binary}")); + expectedException.expect(ForbiddenException.class); + underTest.submit(defaultOrganizationKey, PROJECT_KEY, null, PROJECT_NAME, IOUtils.toInputStream("{binary}")); } private void verifyReportIsPersisted(String taskUuid) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/ValidateProjectStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/ValidateProjectStepTest.java index 1c175d0d7d1..044a9ec740e 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/ValidateProjectStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/ValidateProjectStepTest.java @@ -71,53 +71,6 @@ public class ValidateProjectStepTest { ValidateProjectStep underTest = new ValidateProjectStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder); @Test - public void fail_if_root_component_is_not_a_project_in_db() { - reportReader.putComponent(ScannerReport.Component.newBuilder() - .setRef(1) - .setType(ComponentType.PROJECT) - .setKey(PROJECT_KEY) - .build()); - treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").setKey(PROJECT_KEY).build()); - - ComponentDto project = ComponentTesting.newView(dbTester.organizations().insert(), "ABCD").setDbKey(PROJECT_KEY); - dbClient.componentDao().insert(dbTester.getSession(), project); - dbTester.getSession().commit(); - - thrown.expect(MessageException.class); - thrown.expectMessage("Validation of project failed:\n" + - " o Component (uuid=ABCD, key=PROJECT_KEY) is not a project"); - - underTest.execute(); - } - - @Test - public void fail_on_invalid_key() { - String invalidProjectKey = "Project\\Key"; - - reportReader.putComponent(ScannerReport.Component.newBuilder() - .setRef(1) - .setType(ComponentType.PROJECT) - .setKey(invalidProjectKey) - .addChildRef(2) - .build()); - reportReader.putComponent(ScannerReport.Component.newBuilder() - .setRef(2) - .setType(ComponentType.MODULE) - .setKey("Module$Key") - .build()); - treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").setKey(invalidProjectKey).addChildren( - ReportComponent.builder(Component.Type.MODULE, 2).setUuid("BCDE").setKey("Module$Key").build()) - .build()); - - thrown.expect(MessageException.class); - thrown.expectMessage("Validation of project failed:\n" + - " o \"Project\\Key\" is not a valid project or module key. Allowed characters are alphanumeric, '-', '_', '.' and ':', with at least one non-digit.\n" + - " o \"Module$Key\" is not a valid project or module key. Allowed characters are alphanumeric, '-', '_', '.' and ':', with at least one non-digit"); - - underTest.execute(); - } - - @Test public void fail_if_module_key_is_already_used_as_project_key() { reportReader.putComponent(ScannerReport.Component.newBuilder() .setRef(1) @@ -183,42 +136,6 @@ public class ValidateProjectStepTest { } @Test - public void fail_if_project_key_already_exists_as_module() { - String anotherProjectKey = "ANOTHER_PROJECT_KEY"; - - reportReader.putComponent(ScannerReport.Component.newBuilder() - .setRef(1) - .setType(ComponentType.PROJECT) - .setKey(PROJECT_KEY) - .addChildRef(2) - .build()); - reportReader.putComponent(ScannerReport.Component.newBuilder() - .setRef(2) - .setType(ComponentType.MODULE) - .setKey(MODULE_KEY) - .build()); - - ComponentDto anotherProject = ComponentTesting.newPrivateProjectDto(dbTester.organizations().insert()).setDbKey(anotherProjectKey); - dbClient.componentDao().insert(dbTester.getSession(), anotherProject); - ComponentDto module = ComponentTesting.newModuleDto("ABCD", anotherProject).setDbKey(PROJECT_KEY); - dbClient.componentDao().insert(dbTester.getSession(), module); - dbTester.getSession().commit(); - - treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").setKey(PROJECT_KEY).addChildren( - ReportComponent.builder(Component.Type.MODULE, 2).setUuid("BCDE").setKey(MODULE_KEY).build()) - .build()); - - thrown.expect(MessageException.class); - thrown.expectMessage("Validation of project failed:\n" + - " o Component (uuid=ABCD, key=PROJECT_KEY) is not a project\n" + - " o The project \"" + PROJECT_KEY + "\" is already defined in SonarQube but as a module of project \"" + anotherProjectKey + "\". " + - "If you really want to stop directly analysing project \"" + anotherProjectKey + "\", please first delete it from SonarQube and then relaunch the analysis of project \"" - + PROJECT_KEY + "\"."); - - underTest.execute(); - } - - @Test public void not_fail_if_analysis_date_is_after_last_analysis() { reportReader.putComponent(ScannerReport.Component.newBuilder() .setRef(1) diff --git a/tests/src/test/java/org/sonarqube/tests/analysis/ScannerTest.java b/tests/src/test/java/org/sonarqube/tests/analysis/ScannerTest.java index 4def0e576ab..4c48c3dfda4 100644 --- a/tests/src/test/java/org/sonarqube/tests/analysis/ScannerTest.java +++ b/tests/src/test/java/org/sonarqube/tests/analysis/ScannerTest.java @@ -333,6 +333,20 @@ public class ScannerTest { .contains("Allowed characters"); } + @Test + public void display_explicit_message_when_using_existing_module_key_as_project_key() { + String projectKey = "com.sonarsource.it.samples:multi-modules-sample"; + String moduleKey = "com.sonarsource.it.samples:multi-modules-sample:module_a"; + scan("shared/xoo-multi-modules-sample", "sonar.projectKey", projectKey); + + BuildResult buildResult = scanQuietly("shared/xoo-sample", "sonar.projectKey", moduleKey); + assertThat(buildResult.getLastStatus()).isEqualTo(1); + assertThat(buildResult.getLogs()) + .contains(String.format("Component '%s' is not a project", moduleKey)) + .contains(String.format("The project '%s' is already defined in SonarQube but as a module of project '%s'. If you really want to stop directly analysing project '%s', " + + "please first delete it from SonarQube and then relaunch the analysis of project '%s'", moduleKey, projectKey, projectKey, moduleKey)); + } + /** * SONAR-4547 */ |