From e781c007414fe556ddb2c6cda86001aa6e35cca1 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Thu, 23 Jul 2015 17:01:17 +0200 Subject: [PATCH] SONAR-6729 Analysis should fail when no quality profile --- .../step/ComputeQProfileMeasureStep.java | 6 ++ .../step/ComputeQProfileMeasureStepTest.java | 84 +++++++++++-------- .../DefaultProjectRepositoriesLoader.java | 18 ++-- .../DefaultProjectRepositoriesLoaderTest.java | 35 +++++++- 4 files changed, 102 insertions(+), 41 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputeQProfileMeasureStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputeQProfileMeasureStep.java index 5f5dbcce21b..85b9f6d0173 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputeQProfileMeasureStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputeQProfileMeasureStep.java @@ -24,6 +24,7 @@ import com.google.common.base.Optional; import java.util.HashMap; import java.util.Map; import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.utils.MessageException; import org.sonar.server.computation.component.Component; import org.sonar.server.computation.component.PathAwareVisitor; import org.sonar.server.computation.component.TreeRootHolder; @@ -75,6 +76,11 @@ public class ComputeQProfileMeasureStep implements ComputationStep { @Override protected void visitProject(Component project, Path path) { addMeasure(project, path.current()); + Optional qProfileMeasure = measureRepository.getRawMeasure(project, qProfilesMetric); + if (!qProfileMeasure.isPresent() || QPMeasureData.fromJson(qProfileMeasure.get().getData()).getProfiles().isEmpty()) { + throw MessageException.of(String.format("No quality profiles has been found on project '%s', you probably don't have any language plugin suitable for this analysis.", + project.getKey())); + } } @Override diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputeQProfileMeasureStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputeQProfileMeasureStepTest.java index 3b174127a27..e6bbd85fb76 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputeQProfileMeasureStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputeQProfileMeasureStepTest.java @@ -26,7 +26,10 @@ import java.util.List; import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.utils.MessageException; import org.sonar.server.computation.batch.TreeRootHolderRule; +import org.sonar.server.computation.component.Component; import org.sonar.server.computation.component.DumbComponent; import org.sonar.server.computation.measure.Measure; import org.sonar.server.computation.measure.MeasureRepositoryRule; @@ -49,6 +52,23 @@ public class ComputeQProfileMeasureStepTest { private static final String LANGUAGE_KEY_1 = "language_key1"; private static final String LANGUAGE_KEY_2 = "language_key2"; + private static final String PROJECT_KEY = "PROJECT KEY"; + private static final int PROJECT_REF = 1; + private static final int MODULE_REF = 11; + private static final int SUB_MODULE_REF = 111; + + private static final Component MULTI_MODULE_PROJECT = DumbComponent.builder(PROJECT, PROJECT_REF).setKey(PROJECT_KEY) + .addChildren( + DumbComponent.builder(MODULE, MODULE_REF) + .addChildren( + DumbComponent.builder(MODULE, SUB_MODULE_REF).build() + ) + .build() + ).build(); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Rule public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule(); @@ -67,32 +87,23 @@ public class ComputeQProfileMeasureStepTest { @Test public void add_quality_profile_measure_on_project() throws Exception { - DumbComponent project = DumbComponent.builder(PROJECT, 1) - .addChildren( - DumbComponent.builder(MODULE, 11) - .addChildren( - DumbComponent.builder(MODULE, 111).build() - ) - .build() - ).build(); - - treeRootHolder.setRoot(project); + treeRootHolder.setRoot(MULTI_MODULE_PROJECT); QualityProfile qp = createQProfile(QP_NAME_1, LANGUAGE_KEY_1); - addMeasure(111, qp); + addMeasure(SUB_MODULE_REF, qp); underTest.execute(); - assertThat(measureRepository.getAddedRawMeasures(1).get(QUALITY_PROFILES_KEY)).extracting("data").containsOnly(toJson(qp)); + assertThat(measureRepository.getAddedRawMeasures(PROJECT_REF).get(QUALITY_PROFILES_KEY)).extracting("data").containsOnly(toJson(qp)); } @Test public void add_quality_profile_measure_from_multiple_modules() throws Exception { - DumbComponent project = DumbComponent.builder(PROJECT, 1) + DumbComponent project = DumbComponent.builder(PROJECT, PROJECT_REF) .addChildren( - DumbComponent.builder(MODULE, 11) + DumbComponent.builder(MODULE, MODULE_REF) .addChildren( - DumbComponent.builder(MODULE, 111).build() + DumbComponent.builder(MODULE, SUB_MODULE_REF).build() ) .build(), DumbComponent.builder(MODULE, 12).build() @@ -101,45 +112,52 @@ public class ComputeQProfileMeasureStepTest { treeRootHolder.setRoot(project); QualityProfile qp1 = createQProfile(QP_NAME_1, LANGUAGE_KEY_1); - addMeasure(111, qp1); + addMeasure(SUB_MODULE_REF, qp1); QualityProfile qp2 = createQProfile(QP_NAME_2, LANGUAGE_KEY_2); addMeasure(12, qp2); underTest.execute(); - assertThat(measureRepository.getAddedRawMeasures(1).get(QUALITY_PROFILES_KEY)).extracting("data").containsOnly(toJson(qp1, qp2)); + assertThat(measureRepository.getAddedRawMeasures(PROJECT_REF).get(QUALITY_PROFILES_KEY)).extracting("data").containsOnly(toJson(qp1, qp2)); } @Test - public void nothing_to_add_when_no_measure() throws Exception { - DumbComponent project = DumbComponent.builder(PROJECT, 1) - .addChildren( - DumbComponent.builder(MODULE, 11) - .addChildren( - DumbComponent.builder(MODULE, 111).build() - ) - .build() - ).build(); + public void nothing_to_add_when_measure_already_exists_on_project() throws Exception { + DumbComponent project = DumbComponent.builder(PROJECT, PROJECT_REF).build(); treeRootHolder.setRoot(project); + QualityProfile qp = createQProfile(QP_NAME_1, LANGUAGE_KEY_1); + addMeasure(PROJECT_REF, qp); + underTest.execute(); - assertThat(measureRepository.getAddedRawMeasures(1)).isEmpty(); + assertThat(measureRepository.getAddedRawMeasures(PROJECT_REF)).isEmpty(); } @Test - public void nothing_to_add_when_measure_already_exists_on_project() throws Exception { - DumbComponent project = DumbComponent.builder(PROJECT, 1).build(); + public void fail_with_message_exception_when_no_qprofile_computed_on_project() throws Exception { + thrown.expect(MessageException.class); + thrown.expectMessage("No quality profiles has been found on project 'PROJECT KEY'"); - treeRootHolder.setRoot(project); + treeRootHolder.setRoot(MULTI_MODULE_PROJECT); - QualityProfile qp = createQProfile(QP_NAME_1, LANGUAGE_KEY_1); - addMeasure(1, qp); + underTest.execute(); + + assertThat(measureRepository.getAddedRawMeasures(PROJECT_REF)).isEmpty(); + } + + @Test + public void fail_with_message_exception_when_qprofiles_computed_on_project_are_empty() throws Exception { + thrown.expect(MessageException.class); + thrown.expectMessage("No quality profiles has been found on project 'PROJECT KEY', you probably don't have any language plugin suitable for this analysis."); + + treeRootHolder.setRoot(MULTI_MODULE_PROJECT); + measureRepository.addRawMeasure(PROJECT_REF, QUALITY_PROFILES_KEY, newMeasureBuilder().create(toJson())); underTest.execute(); - assertThat(measureRepository.getAddedRawMeasures(1)).isEmpty(); + assertThat(measureRepository.getAddedRawMeasures(PROJECT_REF)).isEmpty(); } private static QualityProfile createQProfile(String qpName, String languageKey) { diff --git a/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java index dc39233376b..388faf11b6a 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java +++ b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java @@ -19,16 +19,16 @@ */ package org.sonar.batch.repository; -import org.sonar.batch.bootstrap.GlobalMode; - -import org.sonar.batch.util.BatchUtils; -import org.sonar.batch.bootstrap.WSLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.batch.bootstrap.ProjectReactor; +import org.sonar.api.utils.MessageException; import org.sonar.batch.bootstrap.AnalysisProperties; +import org.sonar.batch.bootstrap.GlobalMode; +import org.sonar.batch.bootstrap.WSLoader; import org.sonar.batch.protocol.input.ProjectRepositories; import org.sonar.batch.rule.ModuleQProfiles; +import org.sonar.batch.util.BatchUtils; public class DefaultProjectRepositoriesLoader implements ProjectRepositoriesLoader { @@ -54,7 +54,15 @@ public class DefaultProjectRepositoriesLoader implements ProjectRepositoriesLoad url += "&profile=" + BatchUtils.encodeForUrl(taskProperties.properties().get(ModuleQProfiles.SONAR_PROFILE_PROP)); } url += "&preview=" + globalMode.isPreview(); - return ProjectRepositories.fromJson(wsLoader.loadString(url)); + ProjectRepositories projectRepositories = ProjectRepositories.fromJson(wsLoader.loadString(url)); + validateProjectRepositories(projectRepositories, reactor.getRoot().getKey()); + return projectRepositories; + } + + private static void validateProjectRepositories(ProjectRepositories projectRepositories, String projectKey) { + if (projectRepositories.qProfiles().isEmpty()) { + throw MessageException.of("No quality profiles has been found this project, you probably don't have any language plugin suitable for this analysis."); + } } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoaderTest.java b/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoaderTest.java index 32e32e068cf..63a69e0c600 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoaderTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoaderTest.java @@ -19,16 +19,22 @@ */ package org.sonar.batch.repository; -import org.sonar.batch.bootstrap.GlobalMode; - -import org.sonar.batch.bootstrap.WSLoader; import com.google.common.collect.Maps; +import java.util.Date; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.sonar.api.batch.bootstrap.ProjectDefinition; import org.sonar.api.batch.bootstrap.ProjectReactor; +import org.sonar.api.utils.MessageException; import org.sonar.batch.bootstrap.AnalysisProperties; +import org.sonar.batch.bootstrap.GlobalMode; +import org.sonar.batch.bootstrap.WSLoader; +import org.sonar.batch.protocol.input.ProjectRepositories; +import org.sonar.batch.protocol.input.QProfile; import org.sonar.batch.rule.ModuleQProfiles; + import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -37,6 +43,9 @@ import static org.mockito.Mockito.when; public class DefaultProjectRepositoriesLoaderTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private DefaultProjectRepositoriesLoader loader; private WSLoader wsLoader; private GlobalMode globalMode; @@ -55,6 +64,7 @@ public class DefaultProjectRepositoriesLoaderTest { @Test public void passPreviewParameter() { + addQualityProfile(); reactor = new ProjectReactor(ProjectDefinition.create().setKey("foo")); when(globalMode.isPreview()).thenReturn(false); loader.load(reactor, taskProperties); @@ -67,6 +77,7 @@ public class DefaultProjectRepositoriesLoaderTest { @Test public void passAndEncodeProjectKeyParameter() { + addQualityProfile(); reactor = new ProjectReactor(ProjectDefinition.create().setKey("foo bàr")); loader.load(reactor, taskProperties); verify(wsLoader).loadString("/batch/project?key=foo+b%C3%A0r&preview=false"); @@ -74,10 +85,28 @@ public class DefaultProjectRepositoriesLoaderTest { @Test public void passAndEncodeProfileParameter() { + addQualityProfile(); reactor = new ProjectReactor(ProjectDefinition.create().setKey("foo")); taskProperties.properties().put(ModuleQProfiles.SONAR_PROFILE_PROP, "my-profile#2"); loader.load(reactor, taskProperties); verify(wsLoader).loadString("/batch/project?key=foo&profile=my-profile%232&preview=false"); } + @Test + public void fail_with_message_exception_when_no_quality_profile() throws Exception { + thrown.expect(MessageException.class); + thrown.expectMessage("No quality profiles has been found this project, you probably don't have any language plugin suitable for this analysis."); + + reactor = new ProjectReactor(ProjectDefinition.create().setKey("foo")); + when(wsLoader.loadString(anyString())).thenReturn(new ProjectRepositories().toJson()); + + loader.load(reactor, taskProperties); + } + + private void addQualityProfile(){ + ProjectRepositories projectRepositories = new ProjectRepositories(); + projectRepositories.addQProfile(new QProfile("key", "name", "language", new Date())); + when(wsLoader.loadString(anyString())).thenReturn(projectRepositories.toJson()); + } + } -- 2.39.5