From: Julien HENRY Date: Wed, 7 May 2014 09:37:06 +0000 (+0200) Subject: SONAR-5189 Reintroduce a memory cache for measure in decorators X-Git-Tag: 4.4-RC1~1176 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=12077a645e769be0d4387f30a1e5f5c1966dc08e;p=sonarqube.git SONAR-5189 Reintroduce a memory cache for measure in decorators --- diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/TendencyDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/TendencyDecorator.java index 1e20c12f994..81e06451e24 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/TendencyDecorator.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/TendencyDecorator.java @@ -38,7 +38,6 @@ import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; import org.sonar.api.resources.Scopes; import org.sonar.batch.components.PeriodsDefinition; -import org.sonar.batch.index.DefaultIndex; import org.sonar.core.DryRunIncompatible; import java.util.List; @@ -53,11 +52,9 @@ public class TendencyDecorator implements Decorator { private TimeMachineQuery query; private TendencyAnalyser analyser; private List metrics; - private final DefaultIndex index; - public TendencyDecorator(TimeMachine timeMachine, MetricFinder metricFinder, DefaultIndex index) { + public TendencyDecorator(TimeMachine timeMachine, MetricFinder metricFinder) { this.timeMachine = timeMachine; - this.index = index; this.analyser = new TendencyAnalyser(); this.metrics = Lists.newLinkedList(); for (Metric metric : metricFinder.findAll()) { @@ -67,11 +64,10 @@ public class TendencyDecorator implements Decorator { } } - TendencyDecorator(TimeMachine timeMachine, TimeMachineQuery query, TendencyAnalyser analyser, DefaultIndex index) { + TendencyDecorator(TimeMachine timeMachine, TimeMachineQuery query, TendencyAnalyser analyser) { this.timeMachine = timeMachine; this.query = query; this.analyser = analyser; - this.index = index; } @DependsUpon @@ -118,7 +114,7 @@ public class TendencyDecorator implements Decorator { values.add(measure.getValue()); measure.setTendency(analyser.analyseLevel(valuesPerMetric.get(metric))); - index.updateMeasure(resource, measure); + context.saveMeasure(measure); } } } diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/VariationDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/VariationDecorator.java index be6d1a8f35e..46f8f9d93e8 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/VariationDecorator.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/VariationDecorator.java @@ -40,7 +40,6 @@ import org.sonar.api.technicaldebt.batch.Characteristic; import org.sonar.batch.components.PastMeasuresLoader; import org.sonar.batch.components.PastSnapshot; import org.sonar.batch.components.TimeMachineConfiguration; -import org.sonar.batch.index.DefaultIndex; import java.util.Collection; import java.util.List; @@ -53,19 +52,16 @@ public class VariationDecorator implements Decorator { private MetricFinder metricFinder; private PastMeasuresLoader pastMeasuresLoader; private RuleFinder ruleFinder; - private final DefaultIndex sonarIndex; - public VariationDecorator(PastMeasuresLoader pastMeasuresLoader, MetricFinder metricFinder, TimeMachineConfiguration timeMachineConfiguration, RuleFinder ruleFinder, - DefaultIndex index) { - this(pastMeasuresLoader, metricFinder, timeMachineConfiguration.getProjectPastSnapshots(), ruleFinder, index); + public VariationDecorator(PastMeasuresLoader pastMeasuresLoader, MetricFinder metricFinder, TimeMachineConfiguration timeMachineConfiguration, RuleFinder ruleFinder) { + this(pastMeasuresLoader, metricFinder, timeMachineConfiguration.getProjectPastSnapshots(), ruleFinder); } - VariationDecorator(PastMeasuresLoader pastMeasuresLoader, MetricFinder metricFinder, List projectPastSnapshots, RuleFinder ruleFinder, DefaultIndex index) { + VariationDecorator(PastMeasuresLoader pastMeasuresLoader, MetricFinder metricFinder, List projectPastSnapshots, RuleFinder ruleFinder) { this.pastMeasuresLoader = pastMeasuresLoader; this.projectPastSnapshots = projectPastSnapshots; this.metricFinder = metricFinder; this.ruleFinder = ruleFinder; - this.sonarIndex = index; } public boolean shouldExecuteOnProject(Project project) { @@ -116,7 +112,7 @@ public class VariationDecorator implements Decorator { Object[] pastMeasure = pastMeasuresByKey.get(new MeasureKey(metricId, characteristicId, personId, ruleId)); if (updateVariation(measure, pastMeasure, index)) { - sonarIndex.updateMeasure(resource, measure); + context.saveMeasure(measure); } } } diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/TendencyDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/TendencyDecoratorTest.java index a60dfbb5e9e..8713c66537b 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/TendencyDecoratorTest.java +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/TendencyDecoratorTest.java @@ -28,7 +28,6 @@ import org.sonar.api.measures.Measure; import org.sonar.api.measures.MetricFinder; import org.sonar.api.resources.Directory; import org.sonar.api.resources.Project; -import org.sonar.batch.index.DefaultIndex; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -54,7 +53,7 @@ public class TendencyDecoratorTest { MetricFinder metricFinder = mock(MetricFinder.class); when(metricFinder.findAll()).thenReturn(Arrays.asList(CoreMetrics.LINES, CoreMetrics.COVERAGE, CoreMetrics.COVERAGE_LINE_HITS_DATA, CoreMetrics.PROFILE)); - TendencyDecorator decorator = new TendencyDecorator(null, metricFinder, mock(DefaultIndex.class)); + TendencyDecorator decorator = new TendencyDecorator(null, metricFinder); TimeMachineQuery query = decorator.initQuery(project); assertThat(query.getMetrics().size(), is(2)); @@ -81,7 +80,7 @@ public class TendencyDecoratorTest { when(context.getMeasure(CoreMetrics.LINES)).thenReturn(new Measure(CoreMetrics.LINES, 1400.0)); when(context.getMeasure(CoreMetrics.COVERAGE)).thenReturn(new Measure(CoreMetrics.LINES, 90.0)); - TendencyDecorator decorator = new TendencyDecorator(timeMachine, query, analyser, mock(DefaultIndex.class)); + TendencyDecorator decorator = new TendencyDecorator(timeMachine, query, analyser); decorator.decorate(new Directory("org/foo"), context); verify(analyser).analyseLevel(Arrays.asList(1200.0, 1300.0, 1150.0, 1400.0)); @@ -100,7 +99,7 @@ public class TendencyDecoratorTest { )); DecoratorContext context = mock(DecoratorContext.class); - TendencyDecorator decorator = new TendencyDecorator(timeMachine, query, analyser, mock(DefaultIndex.class)); + TendencyDecorator decorator = new TendencyDecorator(timeMachine, query, analyser); decorator.decorate(new Directory("org/foo"), context); verify(analyser, never()).analyseLevel(anyList()); diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/VariationDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/VariationDecoratorTest.java index 971d6d9f99f..c7c1876bf6c 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/VariationDecoratorTest.java +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/VariationDecoratorTest.java @@ -36,14 +36,12 @@ import org.sonar.api.rules.RuleFinder; import org.sonar.batch.components.PastMeasuresLoader; import org.sonar.batch.components.PastSnapshot; import org.sonar.batch.components.TimeMachineConfiguration; -import org.sonar.batch.index.DefaultIndex; import org.sonar.jpa.test.AbstractDbUnitTestCase; import java.util.Arrays; import java.util.Date; import static org.fest.assertions.Assertions.assertThat; -import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -63,8 +61,7 @@ public class VariationDecoratorTest extends AbstractDbUnitTestCase { @Test public void shouldComputeVariations() { TimeMachineConfiguration timeMachineConfiguration = mock(TimeMachineConfiguration.class); - VariationDecorator decorator = new VariationDecorator(mock(PastMeasuresLoader.class), mock(MetricFinder.class), timeMachineConfiguration, mock(RuleFinder.class), - mock(DefaultIndex.class)); + VariationDecorator decorator = new VariationDecorator(mock(PastMeasuresLoader.class), mock(MetricFinder.class), timeMachineConfiguration, mock(RuleFinder.class)); assertThat(decorator.shouldComputeVariation(new Project("foo"))).isTrue(); assertThat(decorator.shouldComputeVariation(new File("foo/bar.c"))).isFalse(); @@ -93,13 +90,11 @@ public class VariationDecoratorTest extends AbstractDbUnitTestCase { Measure currentCoverage = newMeasure(COVERAGE, 80.0); when(context.getMeasures(Matchers.anyObject())).thenReturn(Arrays.asList(currentNcloc, currentCoverage)); - DefaultIndex index = mock(DefaultIndex.class); - VariationDecorator decorator = new VariationDecorator(pastMeasuresLoader, mock(MetricFinder.class), Arrays.asList(pastSnapshot1, pastSnapshot3), mock(RuleFinder.class), - index); + VariationDecorator decorator = new VariationDecorator(pastMeasuresLoader, mock(MetricFinder.class), Arrays.asList(pastSnapshot1, pastSnapshot3), mock(RuleFinder.class)); decorator.decorate(dir, context); // context updated for each variation : 2 times for ncloc and 1 time for coverage - verify(index, times(3)).updateMeasure(eq(dir), Matchers.anyObject()); + verify(context, times(3)).saveMeasure(Matchers.anyObject()); assertThat(currentNcloc.getVariation1()).isEqualTo(20.0); assertThat(currentNcloc.getVariation2()).isNull(); @@ -140,13 +135,11 @@ public class VariationDecoratorTest extends AbstractDbUnitTestCase { Measure violationsRule2 = RuleMeasure.createForRule(VIOLATIONS, rule2, 70.0); when(context.getMeasures(Matchers.anyObject())).thenReturn(Arrays.asList(violations, violationsRule1, violationsRule2)); - DefaultIndex index = mock(DefaultIndex.class); - VariationDecorator decorator = new VariationDecorator(pastMeasuresLoader, mock(MetricFinder.class), Arrays.asList(pastSnapshot1), ruleFinder, - index); + VariationDecorator decorator = new VariationDecorator(pastMeasuresLoader, mock(MetricFinder.class), Arrays.asList(pastSnapshot1), ruleFinder); decorator.decorate(dir, context); // context updated for each variation - verify(index, times(3)).updateMeasure(eq(dir), Matchers.anyObject()); + verify(context, times(3)).saveMeasure(Matchers.anyObject()); assertThat(violations.getVariation1()).isEqualTo(20.0); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java b/sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java index d33647ee5f3..d31b204e938 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java +++ b/sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java @@ -19,26 +19,31 @@ */ package org.sonar.batch; -import org.sonar.core.measure.MeasurementFilters; - -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.Set; - +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ListMultimap; import com.google.common.collect.Lists; import org.sonar.api.batch.DecoratorContext; import org.sonar.api.batch.Event; import org.sonar.api.batch.SonarIndex; import org.sonar.api.design.Dependency; +import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Measure; import org.sonar.api.measures.MeasuresFilter; import org.sonar.api.measures.MeasuresFilters; import org.sonar.api.measures.Metric; +import org.sonar.api.measures.MetricFinder; import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; import org.sonar.api.rules.Violation; +import org.sonar.api.utils.SonarException; import org.sonar.api.violations.ViolationQuery; +import org.sonar.batch.scan.measure.MeasureCache; +import org.sonar.core.measure.MeasurementFilters; + +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Set; public class DefaultDecoratorContext implements DecoratorContext { @@ -50,19 +55,35 @@ public class DefaultDecoratorContext implements DecoratorContext { private List childrenContexts; + private ListMultimap measuresByMetric = ArrayListMultimap.create(); + private MeasureCache measureCache; + private MetricFinder metricFinder; + public DefaultDecoratorContext(Resource resource, - SonarIndex index, - List childrenContexts, - MeasurementFilters measurementFilters) { + SonarIndex index, + List childrenContexts, + MeasurementFilters measurementFilters, MeasureCache measureCache, MetricFinder metricFinder) { this.index = index; this.resource = resource; this.childrenContexts = childrenContexts; this.measurementFilters = measurementFilters; + this.measureCache = measureCache; + this.metricFinder = metricFinder; + } + + public void init() { + Iterable unfiltered = measureCache.byResource(resource); + for (Measure measure : unfiltered) { + measuresByMetric.put(measure.getMetricKey(), measure); + } } - public DefaultDecoratorContext setReadOnly(boolean b) { - readOnly = b; + public DefaultDecoratorContext end() { + readOnly = true; childrenContexts = null; + for (Measure measure : measuresByMetric.values()) { + measureCache.put(resource, measure); + } return this; } @@ -82,11 +103,18 @@ public class DefaultDecoratorContext implements DecoratorContext { } public M getMeasures(MeasuresFilter filter) { - return index.getMeasures(resource, filter); + Collection unfiltered; + if (filter instanceof MeasuresFilters.MetricFilter) { + // optimization + unfiltered = measuresByMetric.get(((MeasuresFilters.MetricFilter) filter).filterOnMetricKey()); + } else { + unfiltered = measuresByMetric.values(); + } + return filter.filter(unfiltered); } public Measure getMeasure(Metric metric) { - return index.getMeasure(resource, metric); + return getMeasures(MeasuresFilters.metric(metric)); } public Collection getChildrenMeasures(MeasuresFilter filter) { @@ -114,8 +142,31 @@ public class DefaultDecoratorContext implements DecoratorContext { public DecoratorContext saveMeasure(Measure measure) { checkReadOnly(SAVE_MEASURE_METHOD); - if(measurementFilters.accept(resource, measure)) { - index.addMeasure(resource, measure); + Metric metric = metricFinder.findByKey(measure.getMetricKey()); + if (metric == null) { + throw new SonarException("Unknown metric: " + measure.getMetricKey()); + } + measure.setMetric(metric); + if (measurementFilters.accept(resource, measure)) { + List metricMeasures = measuresByMetric.get(measure.getMetricKey()); + + boolean add = true; + if (metricMeasures != null) { + int index = metricMeasures.indexOf(measure); + if (index > -1) { + if (metricMeasures.get(index) == measure) { + add = false; + } else if (measure.getMetric().equals(CoreMetrics.TESTS)) { + // Hack for SONAR-5212 + measuresByMetric.remove(measure.getMetric().getKey(), metricMeasures.get(index)); + } else { + throw new SonarException("Can not add twice the same measure on " + resource + ": " + measure); + } + } + } + if (add) { + measuresByMetric.put(measure.getMetricKey(), measure); + } } return this; } diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java index ad5516879f1..44db4e53f73 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java @@ -31,8 +31,20 @@ import org.sonar.api.batch.SonarIndex; import org.sonar.api.batch.bootstrap.ProjectDefinition; import org.sonar.api.database.model.Snapshot; import org.sonar.api.design.Dependency; -import org.sonar.api.measures.*; -import org.sonar.api.resources.*; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.MeasuresFilter; +import org.sonar.api.measures.MeasuresFilters; +import org.sonar.api.measures.Metric; +import org.sonar.api.measures.MetricFinder; +import org.sonar.api.resources.Directory; +import org.sonar.api.resources.File; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.ProjectLink; +import org.sonar.api.resources.Qualifiers; +import org.sonar.api.resources.Resource; +import org.sonar.api.resources.ResourceUtils; +import org.sonar.api.resources.Scopes; import org.sonar.api.rules.Rule; import org.sonar.api.rules.Violation; import org.sonar.api.scan.filesystem.PathResolver; @@ -41,7 +53,6 @@ import org.sonar.api.violations.ViolationQuery; import org.sonar.batch.ProjectTree; import org.sonar.batch.issue.DeprecatedViolations; import org.sonar.batch.issue.ModuleIssues; -import org.sonar.batch.qualitygate.QualityGateVerifier; import org.sonar.batch.scan.measure.MeasureCache; import org.sonar.core.component.ComponentKeys; import org.sonar.core.component.ScanGraph; @@ -49,7 +60,15 @@ import org.sonar.core.component.ScanGraph; import javax.annotation.CheckForNull; import javax.annotation.Nullable; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; public class DefaultIndex extends SonarIndex { @@ -202,17 +221,6 @@ public class DefaultIndex extends SonarIndex { return measure; } - /** - * Used by some core features like TendencyDecorator, {@link QualityGateVerifier}, VariationDecorator - * that need to update some existing measures - */ - public void updateMeasure(Resource resource, Measure measure) { - if (!measureCache.contains(resource, measure)) { - throw new SonarException("Can't update measure on " + resource + ": " + measure); - } - measureCache.put(resource, measure); - } - // // // diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/DecoratorsExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/phases/DecoratorsExecutor.java index dc4d0b35049..c6aa4ac8a79 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/phases/DecoratorsExecutor.java +++ b/sonar-batch/src/main/java/org/sonar/batch/phases/DecoratorsExecutor.java @@ -19,14 +19,13 @@ */ package org.sonar.batch.phases; -import org.sonar.core.measure.MeasurementFilters; - import com.google.common.collect.Lists; import org.sonar.api.BatchComponent; import org.sonar.api.batch.BatchExtensionDictionnary; import org.sonar.api.batch.Decorator; import org.sonar.api.batch.DecoratorContext; import org.sonar.api.batch.SonarIndex; +import org.sonar.api.measures.MetricFinder; import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; import org.sonar.api.utils.MessageException; @@ -34,6 +33,8 @@ import org.sonar.api.utils.SonarException; import org.sonar.batch.DecoratorsSelector; import org.sonar.batch.DefaultDecoratorContext; import org.sonar.batch.events.EventBus; +import org.sonar.batch.scan.measure.MeasureCache; +import org.sonar.core.measure.MeasurementFilters; import java.util.Collection; import java.util.List; @@ -45,9 +46,13 @@ public class DecoratorsExecutor implements BatchComponent { private EventBus eventBus; private Project project; private MeasurementFilters measurementFilters; + private MeasureCache measureCache; + private MetricFinder metricFinder; public DecoratorsExecutor(BatchExtensionDictionnary batchExtDictionnary, - Project project, SonarIndex index, EventBus eventBus, MeasurementFilters measurementFilters) { + Project project, SonarIndex index, EventBus eventBus, MeasurementFilters measurementFilters, MeasureCache measureCache, MetricFinder metricFinder) { + this.measureCache = measureCache; + this.metricFinder = metricFinder; this.decoratorsSelector = new DecoratorsSelector(batchExtDictionnary); this.index = index; this.eventBus = eventBus; @@ -58,7 +63,7 @@ public class DecoratorsExecutor implements BatchComponent { public void execute() { Collection decorators = decoratorsSelector.select(project); eventBus.fireEvent(new DecoratorsPhaseEvent(Lists.newArrayList(decorators), true)); - decorateResource(project, decorators, true); + ((DefaultDecoratorContext) decorateResource(project, decorators, true)).end(); eventBus.fireEvent(new DecoratorsPhaseEvent(Lists.newArrayList(decorators), false)); } @@ -67,10 +72,11 @@ public class DecoratorsExecutor implements BatchComponent { for (Resource child : index.getChildren(resource)) { boolean isModule = child instanceof Project; DefaultDecoratorContext childContext = (DefaultDecoratorContext) decorateResource(child, decorators, !isModule); - childrenContexts.add(childContext.setReadOnly(true)); + childrenContexts.add(childContext.end()); } - DefaultDecoratorContext context = new DefaultDecoratorContext(resource, index, childrenContexts, measurementFilters); + DefaultDecoratorContext context = new DefaultDecoratorContext(resource, index, childrenContexts, measurementFilters, measureCache, metricFinder); + context.init(); if (executeDecorators) { for (Decorator decorator : decorators) { executeDecorator(decorator, context, resource); diff --git a/sonar-batch/src/main/java/org/sonar/batch/qualitygate/QualityGateVerifier.java b/sonar-batch/src/main/java/org/sonar/batch/qualitygate/QualityGateVerifier.java index ac18daadf95..872381d6f5f 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/qualitygate/QualityGateVerifier.java +++ b/sonar-batch/src/main/java/org/sonar/batch/qualitygate/QualityGateVerifier.java @@ -38,7 +38,6 @@ import org.sonar.api.resources.Resource; import org.sonar.api.resources.ResourceUtils; import org.sonar.api.utils.Duration; import org.sonar.api.utils.Durations; -import org.sonar.batch.index.DefaultIndex; import org.sonar.core.qualitygate.db.QualityGateConditionDto; import org.sonar.core.timemachine.Periods; @@ -64,15 +63,13 @@ public class QualityGateVerifier implements Decorator { private Periods periods; private I18n i18n; private Durations durations; - private final DefaultIndex index; - public QualityGateVerifier(QualityGate qualityGate, Snapshot snapshot, Periods periods, I18n i18n, Durations durations, DefaultIndex index) { + public QualityGateVerifier(QualityGate qualityGate, Snapshot snapshot, Periods periods, I18n i18n, Durations durations) { this.qualityGate = qualityGate; this.snapshot = snapshot; this.periods = periods; this.i18n = i18n; this.durations = durations; - this.index = index; } @DependedUpon @@ -123,7 +120,7 @@ public class QualityGateVerifier implements Decorator { labels.add(text); } - index.updateMeasure(resource, measure); + context.saveMeasure(measure); if (Metric.Level.WARN == level && globalLevel != Metric.Level.ERROR) { globalLevel = Metric.Level.WARN; diff --git a/sonar-batch/src/test/java/org/sonar/batch/phases/DecoratorsExecutorTest.java b/sonar-batch/src/test/java/org/sonar/batch/phases/DecoratorsExecutorTest.java index 3534236e503..12d35f08b4d 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/phases/DecoratorsExecutorTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/phases/DecoratorsExecutorTest.java @@ -24,12 +24,14 @@ import org.sonar.api.batch.BatchExtensionDictionnary; import org.sonar.api.batch.Decorator; import org.sonar.api.batch.DecoratorContext; import org.sonar.api.batch.SonarIndex; +import org.sonar.api.measures.MetricFinder; import org.sonar.api.resources.File; import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; import org.sonar.api.utils.SonarException; import org.sonar.batch.DefaultDecoratorContext; import org.sonar.batch.events.EventBus; +import org.sonar.batch.scan.measure.MeasureCache; import org.sonar.core.measure.MeasurementFilters; import static org.fest.assertions.Assertions.assertThat; @@ -64,7 +66,7 @@ public class DecoratorsExecutorTest { doThrow(new SonarException()).when(decorator).decorate(any(Resource.class), any(DecoratorContext.class)); DecoratorsExecutor executor = new DecoratorsExecutor(mock(BatchExtensionDictionnary.class), new Project("key"), mock(SonarIndex.class), - mock(EventBus.class), mock(MeasurementFilters.class)); + mock(EventBus.class), mock(MeasurementFilters.class), mock(MeasureCache.class), mock(MetricFinder.class)); try { executor.executeDecorator(decorator, mock(DefaultDecoratorContext.class), File.create("src/org/foo/Bar.java", "org/foo/Bar.java", null, false)); fail("Exception has not been thrown"); diff --git a/sonar-batch/src/test/java/org/sonar/batch/qualitygate/QualityGateVerifierTest.java b/sonar-batch/src/test/java/org/sonar/batch/qualitygate/QualityGateVerifierTest.java index 28339d61c9c..9dd6a731f12 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/qualitygate/QualityGateVerifierTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/qualitygate/QualityGateVerifierTest.java @@ -39,7 +39,6 @@ import org.sonar.api.resources.Resource; import org.sonar.api.test.IsMeasure; import org.sonar.api.utils.Duration; import org.sonar.api.utils.Durations; -import org.sonar.batch.index.DefaultIndex; import org.sonar.core.qualitygate.db.QualityGateConditionDto; import org.sonar.core.timemachine.Periods; @@ -70,7 +69,6 @@ public class QualityGateVerifierTest { Periods periods; I18n i18n; Durations durations; - private DefaultIndex index; @Before public void before() { @@ -91,8 +89,7 @@ public class QualityGateVerifierTest { snapshot = mock(Snapshot.class); qualityGate = mock(QualityGate.class); when(qualityGate.isEnabled()).thenReturn(true); - index = mock(DefaultIndex.class); - verifier = new QualityGateVerifier(qualityGate, snapshot, periods, i18n, durations, index); + verifier = new QualityGateVerifier(qualityGate, snapshot, periods, i18n, durations); project = new Project("foo"); } @@ -133,8 +130,8 @@ public class QualityGateVerifierTest { verifier.decorate(project, context); - verify(index).updateMeasure(eq(project), argThat(hasLevel(measureClasses, Metric.Level.OK))); - verify(index).updateMeasure(eq(project), argThat(hasLevel(measureCoverage, Metric.Level.OK))); + verify(context).saveMeasure(argThat(hasLevel(measureClasses, Metric.Level.OK))); + verify(context).saveMeasure(argThat(hasLevel(measureCoverage, Metric.Level.OK))); verify(context).saveMeasure(argThat(new IsMeasure(CoreMetrics.ALERT_STATUS, Metric.Level.OK.toString()))); verify(context).saveMeasure(argThat(new IsMeasure(CoreMetrics.QUALITY_GATE_DETAILS, "{\"level\":\"OK\"," + "\"conditions\":" @@ -169,8 +166,8 @@ public class QualityGateVerifierTest { verify(context).saveMeasure(argThat(matchesMetric(CoreMetrics.ALERT_STATUS, Metric.Level.WARN, null))); - verify(index).updateMeasure(eq(project), argThat(hasLevel(measureClasses, Metric.Level.OK))); - verify(index).updateMeasure(eq(project), argThat(hasLevel(measureCoverage, Metric.Level.WARN))); + verify(context).saveMeasure(argThat(hasLevel(measureClasses, Metric.Level.OK))); + verify(context).saveMeasure(argThat(hasLevel(measureCoverage, Metric.Level.WARN))); } @@ -187,8 +184,8 @@ public class QualityGateVerifierTest { verify(context).saveMeasure(argThat(matchesMetric(CoreMetrics.ALERT_STATUS, Metric.Level.ERROR, null))); - verify(index).updateMeasure(eq(project), argThat(hasLevel(measureClasses, Metric.Level.WARN))); - verify(index).updateMeasure(eq(project), argThat(hasLevel(measureCoverage, Metric.Level.ERROR))); + verify(context).saveMeasure(argThat(hasLevel(measureClasses, Metric.Level.WARN))); + verify(context).saveMeasure(argThat(hasLevel(measureCoverage, Metric.Level.ERROR))); } @Test @@ -258,9 +255,9 @@ public class QualityGateVerifierTest { verify(context).saveMeasure(argThat(matchesMetric(CoreMetrics.ALERT_STATUS, Metric.Level.OK, null))); - verify(index).updateMeasure(eq(project), argThat(hasLevel(measureClasses, Metric.Level.OK))); - verify(index).updateMeasure(eq(project), argThat(hasLevel(measureCoverage, Metric.Level.OK))); - verify(index).updateMeasure(eq(project), argThat(hasLevel(measureComplexity, Metric.Level.OK))); + verify(context).saveMeasure(argThat(hasLevel(measureClasses, Metric.Level.OK))); + verify(context).saveMeasure(argThat(hasLevel(measureCoverage, Metric.Level.OK))); + verify(context).saveMeasure(argThat(hasLevel(measureComplexity, Metric.Level.OK))); } @Test @@ -286,9 +283,9 @@ public class QualityGateVerifierTest { verify(context).saveMeasure(argThat(matchesMetric(CoreMetrics.ALERT_STATUS, Metric.Level.WARN, null))); - verify(index).updateMeasure(eq(project), argThat(hasLevel(measureClasses, Metric.Level.WARN))); - verify(index).updateMeasure(eq(project), argThat(hasLevel(measureCoverage, Metric.Level.WARN))); - verify(index).updateMeasure(eq(project), argThat(hasLevel(measureComplexity, Metric.Level.WARN))); + verify(context).saveMeasure(argThat(hasLevel(measureClasses, Metric.Level.WARN))); + verify(context).saveMeasure(argThat(hasLevel(measureCoverage, Metric.Level.WARN))); + verify(context).saveMeasure(argThat(hasLevel(measureComplexity, Metric.Level.WARN))); } @Test @@ -302,7 +299,7 @@ public class QualityGateVerifierTest { verifier.decorate(project, context); verify(context).saveMeasure(argThat(matchesMetric(CoreMetrics.ALERT_STATUS, Metric.Level.OK, null))); - verify(index).updateMeasure(eq(project), argThat(hasLevel(measureClasses, Metric.Level.OK))); + verify(context).saveMeasure(argThat(hasLevel(measureClasses, Metric.Level.OK))); } @Test @@ -320,7 +317,7 @@ public class QualityGateVerifierTest { verifier.decorate(project, context); verify(context).saveMeasure(argThat(matchesMetric(CoreMetrics.ALERT_STATUS, Metric.Level.OK, null))); - verify(index).updateMeasure(eq(project), argThat(hasLevel(measureRatingMetric, Metric.Level.OK))); + verify(context).saveMeasure(argThat(hasLevel(measureRatingMetric, Metric.Level.OK))); } @Test @@ -335,7 +332,7 @@ public class QualityGateVerifierTest { verifier.decorate(project, context); verify(context).saveMeasure(argThat(matchesMetric(CoreMetrics.ALERT_STATUS, Metric.Level.WARN, null))); - verify(index).updateMeasure(eq(project), argThat(hasLevel(measureClasses, Metric.Level.WARN))); + verify(context).saveMeasure(argThat(hasLevel(measureClasses, Metric.Level.WARN))); } @Test(expected = NotImplementedException.class) @@ -408,7 +405,7 @@ public class QualityGateVerifierTest { verifier.decorate(project, context); // First call to saveMeasure is for the update of debt - verify(index).updateMeasure(eq(project), argThat(matchesMetric(metric, Level.ERROR, "The Debt > 1h"))); + verify(context).saveMeasure(argThat(matchesMetric(metric, Level.ERROR, "The Debt > 1h"))); verify(context).saveMeasure(argThat(matchesMetric(CoreMetrics.ALERT_STATUS, Metric.Level.ERROR, "The Debt > 1h"))); verify(context).saveMeasure(argThat(new IsMeasure(CoreMetrics.QUALITY_GATE_DETAILS, "{\"level\":\"ERROR\"," + "\"conditions\":" diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/DecoratorContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/DecoratorContext.java index 3cf8b4dee89..5d13d0ac7da 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/DecoratorContext.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/DecoratorContext.java @@ -76,14 +76,14 @@ public interface DecoratorContext { Collection getChildrenMeasures(Metric metric); /** - * Add a measure on the current resource. It can not be executed from children contexts. + * Add a new measure on the current resource. It can not be executed from children contexts. * * @return the same context */ DecoratorContext saveMeasure(Measure measure); /** - * Add a measure on the current resource. It can not be executed from children contexts. + * Add a new measure on the current resource. It can not be executed from children contexts. * * @return the current object */