]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8967 Fail fast when trying to analyse a module
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Wed, 18 Oct 2017 13:26:30 +0000 (15:26 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Fri, 20 Oct 2017 11:09:23 +0000 (13:09 +0200)
server/sonar-server/src/main/java/org/sonar/server/computation/queue/ReportSubmitter.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ValidateProjectStep.java
server/sonar-server/src/test/java/org/sonar/server/computation/queue/ReportSubmitterTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/ValidateProjectStepTest.java
tests/src/test/java/org/sonarqube/tests/analysis/ScannerTest.java

index e6f63e2ef8440f65ed58030189b3b00c7066aed4..a4cc5bbf1c5e4608b8514c85e95d287e787efff1 100644 (file)
  */
 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()),
index 62cf283c8ec87dddcdffa91875c8b403d55d1a57..27ef9e45b81d2c0107b7396e05bfd0d215ebb708 100644 (file)
@@ -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());
index 6c947ae6501339fbb64ae9baac2a7b4913f660ea..814c229af004937e967733ae4fc086dc640895e7 100644 (file)
@@ -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
@@ -99,24 +103,6 @@ public class ReportSubmitterTest {
     defaultOrganizationUuid = db.getDefaultOrganization().getUuid();
   }
 
-  @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
@@ -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) {
index 1c175d0d7d1f5476618971eb5553fc550f5f0c31..044a9ec740e6a40b3a8e037afde4e3c4dcf15246 100644 (file)
@@ -70,53 +70,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()
@@ -182,42 +135,6 @@ public class ValidateProjectStepTest {
     underTest.execute();
   }
 
-  @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()
index 4def0e576ab95c749d1d2248feeb4274a0f59a9f..4c48c3dfda4ea61d4dee61217d2df567f620854b 100644 (file)
@@ -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
    */