From: Fabrice Bellingard Date: Thu, 5 Jul 2012 16:00:16 +0000 (+0200) Subject: SONAR-3543 Fail analysis if a project has no files X-Git-Tag: 3.2~221 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=8dc62acc9f20e1400af64f8073fd4cb77d78cc14;p=sonarqube.git SONAR-3543 Fail analysis if a project has no files => The Sonar analysis must fail when a project has been analysed but the measure 'files' is 0. --- diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/FilesDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/FilesDecorator.java index 2b6fc1a9a04..7f3b1097cdd 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/FilesDecorator.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/FilesDecorator.java @@ -28,6 +28,8 @@ import org.sonar.api.measures.MeasureUtils; import org.sonar.api.measures.Metric; import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; +import org.sonar.api.resources.ResourceUtils; +import org.sonar.api.utils.SonarException; import java.util.Collection; @@ -45,8 +47,10 @@ public final class FilesDecorator implements Decorator { return CoreMetrics.FILES; } + @SuppressWarnings("rawtypes") public void decorate(Resource resource, DecoratorContext context) { if (MeasureUtils.hasValue(context.getMeasure(CoreMetrics.FILES))) { + checkRootProjectHasFiles(resource, context.getMeasure(CoreMetrics.FILES).getValue()); return; } @@ -56,9 +60,17 @@ public final class FilesDecorator implements Decorator { } else { Collection childrenMeasures = context.getChildrenMeasures(CoreMetrics.FILES); Double sum = MeasureUtils.sum(false, childrenMeasures); + checkRootProjectHasFiles(resource, sum); if (sum != null) { context.saveMeasure(CoreMetrics.FILES, sum); } } } + + @SuppressWarnings("rawtypes") + private void checkRootProjectHasFiles(Resource resource, Double sum) { + if (ResourceUtils.isRootProject(resource) && (sum == null || sum.doubleValue() == 0)) { + throw new SonarException("Project \"" + resource.getName() + "\" does not contain any file. Please check your project configuration."); + } + } } diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/FilesDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/FilesDecoratorTest.java new file mode 100644 index 00000000000..c6bfd2bde3f --- /dev/null +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/FilesDecoratorTest.java @@ -0,0 +1,146 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.core.sensors; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Qualifiers; +import org.sonar.api.resources.Resource; +import org.sonar.api.utils.SonarException; + +import java.util.Arrays; + +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Matchers.anyDouble; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class FilesDecoratorTest { + + private FilesDecorator decorator; + + @Mock + private DecoratorContext context; + + @Mock + private Resource resource; + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + decorator = new FilesDecorator(); + } + + @Test + public void generatesMetrics() { + assertThat(decorator.generateDirectoriesMetric()).isEqualTo(CoreMetrics.FILES); + } + + @Test + public void shouldExecute() { + assertThat(decorator.shouldExecuteOnProject(mock(Project.class))).isEqualTo(true); + } + + @Test + public void shouldNotSaveIfMeasureAlreadyExists() { + when(context.getMeasure(CoreMetrics.FILES)).thenReturn(new Measure(CoreMetrics.FILES, 1.0)); + + decorator.decorate(resource, context); + + verify(context, never()).saveMeasure(eq(CoreMetrics.FILES), anyDouble()); + } + + @Test + public void shouldSaveOneForFile() { + when(resource.getQualifier()).thenReturn(Qualifiers.FILE); + + decorator.decorate(resource, context); + + verify(context, times(1)).saveMeasure(eq(CoreMetrics.FILES), eq(1d)); + } + + @Test + public void shouldSaveOneForClass() { + when(resource.getQualifier()).thenReturn(Qualifiers.CLASS); + + decorator.decorate(resource, context); + + verify(context, times(1)).saveMeasure(eq(CoreMetrics.FILES), eq(1d)); + } + + @Test + public void shouldSumChildren() { + when(context.getChildrenMeasures(CoreMetrics.FILES)).thenReturn(Arrays.asList(new Measure(CoreMetrics.FILES, 2.0), new Measure(CoreMetrics.FILES, 3.0))); + + decorator.decorate(resource, context); + + verify(context).saveMeasure(eq(CoreMetrics.FILES), eq(5.0)); + } + + @Test + public void shouldFailOnRootProjectIfNoFile() { + when(resource.getQualifier()).thenReturn(Qualifiers.PROJECT); + when(resource.getName()).thenReturn("Foo"); + when(context.getChildrenMeasures(CoreMetrics.FILES)).thenReturn(Arrays.asList(new Measure(CoreMetrics.FILES, 0.0))); + + thrown.expect(SonarException.class); + thrown.expectMessage("Project \"Foo\" does not contain any file. Please check your project configuration."); + + decorator.decorate(resource, context); + } + + @Test + public void shouldFailOnRootProjectIfNoFileMeasure() { + when(resource.getQualifier()).thenReturn(Qualifiers.PROJECT); + when(resource.getName()).thenReturn("Foo"); + + thrown.expect(SonarException.class); + thrown.expectMessage("Project \"Foo\" does not contain any file. Please check your project configuration."); + + decorator.decorate(resource, context); + } + + @Test + public void shouldNotFailOnModuleIfNoFile() { + when(resource.getQualifier()).thenReturn(Qualifiers.MODULE); + when(context.getChildrenMeasures(CoreMetrics.FILES)).thenReturn(Arrays.asList(new Measure(CoreMetrics.FILES, 0.0))); + + decorator.decorate(resource, context); + + verify(context).saveMeasure(eq(CoreMetrics.FILES), eq(0.0)); + } + +}