diff options
author | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2015-07-21 17:24:15 +0200 |
---|---|---|
committer | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2015-07-23 11:06:03 +0200 |
commit | c5a1decadac5bcefe65fc1194c1694e2b6c73143 (patch) | |
tree | 7e555bd87562b19e1ec86ad30924748554755d36 /server | |
parent | a774449c9a95139486a69a5a02ece6206ea15c95 (diff) | |
download | sonarqube-c5a1decadac5bcefe65fc1194c1694e2b6c73143.tar.gz sonarqube-c5a1decadac5bcefe65fc1194c1694e2b6c73143.zip |
SONAR-6676 compute FILES and DIRECTORIES measures in CE
Diffstat (limited to 'server')
3 files changed, 235 insertions, 0 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java index c38bc358f96..fe213aaabe6 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java @@ -52,6 +52,7 @@ public class ComputationSteps { FeedPeriodsStep.class, // data computation + FileAndDirectoryMeasuresStep.class, NewCoverageMeasuresStep.class, CoverageMeasuresStep.class, CommentMeasuresStep.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/FileAndDirectoryMeasuresStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/FileAndDirectoryMeasuresStep.java new file mode 100644 index 00000000000..563bc3e5495 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/FileAndDirectoryMeasuresStep.java @@ -0,0 +1,123 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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 this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.computation.step; + +import org.sonar.api.measures.CoreMetrics; +import org.sonar.server.computation.component.Component; +import org.sonar.server.computation.component.PathAwareVisitor; +import org.sonar.server.computation.component.TreeRootHolder; +import org.sonar.server.computation.measure.MeasureRepository; +import org.sonar.server.computation.metric.Metric; +import org.sonar.server.computation.metric.MetricRepository; + +import static org.sonar.server.computation.component.Component.Type.FILE; +import static org.sonar.server.computation.component.ComponentVisitor.Order.POST_ORDER; +import static org.sonar.server.computation.measure.Measure.newMeasureBuilder; + +public class FileAndDirectoryMeasuresStep implements ComputationStep { + private static final CounterStackElementFactory COUNTER_STACK_ELEMENT_FACTORY = new CounterStackElementFactory(); + + private final TreeRootHolder treeRootHolder; + private final MetricRepository metricRepository; + private final MeasureRepository measureRepository; + + public FileAndDirectoryMeasuresStep(TreeRootHolder treeRootHolder, MetricRepository metricRepository, MeasureRepository measureRepository) { + this.treeRootHolder = treeRootHolder; + this.metricRepository = metricRepository; + this.measureRepository = measureRepository; + } + + @Override + public void execute() { + Metric fileMetric = metricRepository.getByKey(CoreMetrics.FILES_KEY); + Metric directoryMetric = metricRepository.getByKey(CoreMetrics.DIRECTORIES_KEY); + + new FileAndDirectoryMeasureVisitor(directoryMetric, fileMetric).visit(treeRootHolder.getRoot()); + } + + @Override + public String getDescription() { + return "File and Directory measures"; + } + + private class FileAndDirectoryMeasureVisitor extends PathAwareVisitor<Counter> { + private final Metric directoryMetric; + private final Metric fileMetric; + + public FileAndDirectoryMeasureVisitor(Metric directoryMetric, Metric fileMetric) { + super(FILE, POST_ORDER, COUNTER_STACK_ELEMENT_FACTORY); + this.directoryMetric = directoryMetric; + this.fileMetric = fileMetric; + } + + @Override + protected void visitProject(Component project, Path<Counter> path) { + measureRepository.add(project, directoryMetric, newMeasureBuilder().create(path.current().directories)); + measureRepository.add(project, fileMetric, newMeasureBuilder().create(path.current().files)); + } + + @Override + protected void visitModule(Component module, Path<Counter> path) { + measureRepository.add(module, directoryMetric, newMeasureBuilder().create(path.current().directories)); + measureRepository.add(module, fileMetric, newMeasureBuilder().create(path.current().files)); + + path.parent().directories += path.current().directories; + path.parent().files += path.current().files; + } + + @Override + protected void visitDirectory(Component directory, Path<Counter> path) { + measureRepository.add(directory, directoryMetric, newMeasureBuilder().create(1)); + measureRepository.add(directory, fileMetric, newMeasureBuilder().create(path.current().files)); + + path.parent().directories += 1; + path.parent().files += path.current().files; + } + + @Override + protected void visitFile(Component file, Path<Counter> path) { + if (file.getFileAttributes().isUnitTest()) { + return; + } + measureRepository.add(file, fileMetric, newMeasureBuilder().create(1)); + + path.parent().files += 1; + } + + } + + private static class Counter { + private int files = 0; + private int directories = 0; + + } + + private static class CounterStackElementFactory extends PathAwareVisitor.SimpleStackElementFactory<Counter> { + @Override + public Counter createForAny(Component component) { + return new Counter(); + } + + @Override + public Counter createForFile(Component file) { + return null; + } + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/FileAndDirectoryMeasuresStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/FileAndDirectoryMeasuresStepTest.java new file mode 100644 index 00000000000..3989a86268a --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/FileAndDirectoryMeasuresStepTest.java @@ -0,0 +1,111 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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 this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.computation.step; + +import org.junit.Rule; +import org.junit.Test; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.server.computation.batch.TreeRootHolderRule; +import org.sonar.server.computation.component.FileAttributes; +import org.sonar.server.computation.measure.MeasureRepositoryRule; +import org.sonar.server.computation.metric.MetricRepositoryRule; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.api.measures.CoreMetrics.DIRECTORIES_KEY; +import static org.sonar.api.measures.CoreMetrics.FILES_KEY; +import static org.sonar.server.computation.component.Component.Type.DIRECTORY; +import static org.sonar.server.computation.component.Component.Type.FILE; +import static org.sonar.server.computation.component.Component.Type.MODULE; +import static org.sonar.server.computation.component.Component.Type.PROJECT; +import static org.sonar.server.computation.component.DumbComponent.builder; +import static org.sonar.server.computation.measure.Measure.newMeasureBuilder; +import static org.sonar.server.computation.measure.MeasureRepoEntry.entryOf; +import static org.sonar.server.computation.measure.MeasureRepoEntry.toEntries; + +public class FileAndDirectoryMeasuresStepTest { + + private static final int ROOT_REF = 1; + private static final int MODULE_REF = 12; + private static final int SUB_MODULE_REF = 123; + private static final int DIRECTORY_1_REF = 1234; + private static final int DIRECTORY_2_REF = 1235; + private static final int FILE_1_REF = 12341; + private static final int FILE_2_REF = 12343; + private static final int FILE_3_REF = 12351; + private static final int UNIT_TEST_REF = 12352; + public static final String LANGUAGE_KEY_DOES_NOT_MATTER_HERE = null; + + @Rule + public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule(); + @Rule + public MetricRepositoryRule metricRepository = new MetricRepositoryRule() + .add(CoreMetrics.FILES) + .add(CoreMetrics.DIRECTORIES); + @Rule + public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository); + + private FileAndDirectoryMeasuresStep underTest = new FileAndDirectoryMeasuresStep(treeRootHolder, metricRepository, measureRepository); + + @Test + public void verify_FILE_and_DIRECTORY_computation_and_aggregation() { + treeRootHolder.setRoot( + builder(PROJECT, ROOT_REF) + .addChildren( + builder(MODULE, MODULE_REF) + .addChildren( + builder(MODULE, SUB_MODULE_REF) + .addChildren( + builder(DIRECTORY, DIRECTORY_1_REF) + .addChildren( + builder(FILE, FILE_1_REF).build(), + builder(FILE, FILE_2_REF).build()) + .build(), + builder(DIRECTORY, DIRECTORY_2_REF) + .addChildren( + builder(FILE, FILE_3_REF).build(), + builder(FILE, UNIT_TEST_REF).setFileAttributes(new FileAttributes(true, LANGUAGE_KEY_DOES_NOT_MATTER_HERE)).build()) + .build()) + .build()) + .build()) + .build()); + + underTest.execute(); + + verifyMeasuresOnFile(FILE_1_REF, 1); + verifyMeasuresOnFile(FILE_2_REF, 1); + verifyMeasuresOnFile(FILE_3_REF, 1); + assertThat(toEntries(measureRepository.getAddedRawMeasures(UNIT_TEST_REF))).isEmpty(); + verifyMeasuresOnOtherComponent(DIRECTORY_1_REF, 2, 1); + verifyMeasuresOnOtherComponent(DIRECTORY_2_REF, 1, 1); + verifyMeasuresOnOtherComponent(SUB_MODULE_REF, 3, 2); + verifyMeasuresOnOtherComponent(MODULE_REF, 3, 2); + verifyMeasuresOnOtherComponent(ROOT_REF, 3, 2); + } + + private void verifyMeasuresOnFile(int componentRef, int fileCount) { + assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))) + .containsOnly(entryOf(FILES_KEY, newMeasureBuilder().create(fileCount))); + } + + private void verifyMeasuresOnOtherComponent(int componentRef, int fileCount, int directoryCount) { + assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))) + .containsOnly(entryOf(FILES_KEY, newMeasureBuilder().create(fileCount)), entryOf(DIRECTORIES_KEY, newMeasureBuilder().create(directoryCount))); + } +} |