From: Simon Brandhof Date: Wed, 27 May 2015 07:38:17 +0000 (+0200) Subject: SONAR-6370 move batch extensions out of core plugin X-Git-Tag: 5.2-RC1~1805 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=57c01be1943a882a5a2fe0cc0fecab2fe75a861a;p=sonarqube.git SONAR-6370 move batch extensions out of core plugin Decorators temporarily moved to package org.sonar.batch.compute of sonar-batch. --- diff --git a/plugins/sonar-core-plugin/pom.xml b/plugins/sonar-core-plugin/pom.xml index 3df82a92539..58ead2cf637 100644 --- a/plugins/sonar-core-plugin/pom.xml +++ b/plugins/sonar-core-plugin/pom.xml @@ -33,12 +33,6 @@ jfreechart provided - - org.codehaus.sonar - sonar-batch - ${project.version} - provided - org.apache.maven maven-plugin-api diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java index 0b1883d954b..cd0b8687a3c 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java @@ -26,30 +26,7 @@ import org.sonar.api.Properties; import org.sonar.api.Property; import org.sonar.api.PropertyType; import org.sonar.api.SonarPlugin; -import org.sonar.plugins.core.issue.CountFalsePositivesDecorator; -import org.sonar.plugins.core.issue.CountUnresolvedIssuesDecorator; import org.sonar.plugins.core.notifications.alerts.NewAlerts; -import org.sonar.plugins.core.security.ApplyProjectRolesDecorator; -import org.sonar.plugins.core.sensors.BranchCoverageDecorator; -import org.sonar.plugins.core.sensors.CommentDensityDecorator; -import org.sonar.plugins.core.sensors.CoverageDecorator; -import org.sonar.plugins.core.sensors.DirectoriesDecorator; -import org.sonar.plugins.core.sensors.FilesDecorator; -import org.sonar.plugins.core.sensors.ItBranchCoverageDecorator; -import org.sonar.plugins.core.sensors.ItCoverageDecorator; -import org.sonar.plugins.core.sensors.ItLineCoverageDecorator; -import org.sonar.plugins.core.sensors.LineCoverageDecorator; -import org.sonar.plugins.core.sensors.ManualMeasureDecorator; -import org.sonar.plugins.core.sensors.OverallBranchCoverageDecorator; -import org.sonar.plugins.core.sensors.OverallCoverageDecorator; -import org.sonar.plugins.core.sensors.OverallLineCoverageDecorator; -import org.sonar.plugins.core.sensors.UnitTestDecorator; -import org.sonar.plugins.core.timemachine.NewCoverageAggregator; -import org.sonar.plugins.core.timemachine.NewCoverageFileAnalyzer; -import org.sonar.plugins.core.timemachine.NewItCoverageFileAnalyzer; -import org.sonar.plugins.core.timemachine.NewOverallCoverageFileAnalyzer; -import org.sonar.plugins.core.timemachine.TimeMachineConfigurationPersister; -import org.sonar.plugins.core.timemachine.VariationDecorator; @Properties({ @Property( @@ -219,35 +196,6 @@ public final class CorePlugin extends SonarPlugin { DefaultResourceTypes.class, UserManagedMetrics.class, - // issues - CountUnresolvedIssuesDecorator.class, - CountFalsePositivesDecorator.class, - - // batch - UnitTestDecorator.class, - LineCoverageDecorator.class, - CoverageDecorator.class, - BranchCoverageDecorator.class, - ItLineCoverageDecorator.class, - ItCoverageDecorator.class, - ItBranchCoverageDecorator.class, - OverallLineCoverageDecorator.class, - OverallCoverageDecorator.class, - OverallBranchCoverageDecorator.class, - ApplyProjectRolesDecorator.class, - CommentDensityDecorator.class, - DirectoriesDecorator.class, - FilesDecorator.class, - ManualMeasureDecorator.class, - - // time machine - VariationDecorator.class, - TimeMachineConfigurationPersister.class, - NewCoverageFileAnalyzer.class, - NewItCoverageFileAnalyzer.class, - NewOverallCoverageFileAnalyzer.class, - NewCoverageAggregator.class, - // Notify alerts on my favourite projects NewAlerts.class, NewAlerts.newMetadata()); diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/CountFalsePositivesDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/CountFalsePositivesDecorator.java deleted file mode 100644 index c962544de24..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/CountFalsePositivesDecorator.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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.plugins.core.issue; - -import org.sonar.api.batch.*; -import org.sonar.api.component.ResourcePerspectives; -import org.sonar.api.issue.Issuable; -import org.sonar.api.issue.Issue; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.MeasureUtils; -import org.sonar.api.measures.Metric; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Resource; - -/** - * Computes the number of false-positives - * - * @since 3.6 - */ -@DependsUpon(DecoratorBarriers.END_OF_VIOLATION_TRACKING) -public class CountFalsePositivesDecorator implements Decorator { - - private final ResourcePerspectives perspectives; - - public CountFalsePositivesDecorator(ResourcePerspectives perspectives) { - this.perspectives = perspectives; - } - - @Override - public boolean shouldExecuteOnProject(Project project) { - return true; - } - - @DependedUpon - public Metric generatesFalsePositiveMeasure() { - return CoreMetrics.FALSE_POSITIVE_ISSUES; - } - - @Override - public void decorate(Resource resource, DecoratorContext context) { - Issuable issuable = perspectives.as(Issuable.class, resource); - if (issuable != null) { - int falsePositives = 0; - for (Issue issue : issuable.resolvedIssues()) { - if (Issue.RESOLUTION_FALSE_POSITIVE.equals(issue.resolution())) { - falsePositives++; - } - } - saveMeasure(context, CoreMetrics.FALSE_POSITIVE_ISSUES, falsePositives); - } - } - - private void saveMeasure(DecoratorContext context, Metric metric, int value) { - context.saveMeasure(metric, (double) (value + sumChildren(context, metric))); - } - - private int sumChildren(DecoratorContext context, Metric metric) { - return MeasureUtils.sum(true, context.getChildrenMeasures(metric)).intValue(); - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/CountUnresolvedIssuesDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/CountUnresolvedIssuesDecorator.java deleted file mode 100644 index 1606b3aeaca..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/CountUnresolvedIssuesDecorator.java +++ /dev/null @@ -1,285 +0,0 @@ -/* - * 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.plugins.core.issue; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.*; -import org.apache.commons.lang.time.DateUtils; -import org.sonar.api.batch.*; -import org.sonar.api.component.ResourcePerspectives; -import org.sonar.api.issue.Issuable; -import org.sonar.api.issue.Issue; -import org.sonar.api.measures.*; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Resource; -import org.sonar.api.resources.ResourceUtils; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.rules.RulePriority; -import org.sonar.batch.components.Period; -import org.sonar.batch.components.TimeMachineConfiguration; - -import javax.annotation.Nullable; - -import java.util.*; - -/** - * Computes metrics related to number of issues. - * - * @since 3.6 - */ -@DependsUpon(DecoratorBarriers.ISSUES_TRACKED) -@RequiresDB -public class CountUnresolvedIssuesDecorator implements Decorator { - - private final ResourcePerspectives perspectives; - private final TimeMachineConfiguration timeMachineConfiguration; - - public CountUnresolvedIssuesDecorator(ResourcePerspectives perspectives, TimeMachineConfiguration timeMachineConfiguration) { - this.perspectives = perspectives; - this.timeMachineConfiguration = timeMachineConfiguration; - } - - @Override - public boolean shouldExecuteOnProject(Project project) { - return true; - } - - @DependedUpon - public List generatesIssuesMetrics() { - return ImmutableList.of( - CoreMetrics.VIOLATIONS, - CoreMetrics.BLOCKER_VIOLATIONS, - CoreMetrics.CRITICAL_VIOLATIONS, - CoreMetrics.MAJOR_VIOLATIONS, - CoreMetrics.MINOR_VIOLATIONS, - CoreMetrics.INFO_VIOLATIONS, - CoreMetrics.NEW_VIOLATIONS, - CoreMetrics.NEW_BLOCKER_VIOLATIONS, - CoreMetrics.NEW_CRITICAL_VIOLATIONS, - CoreMetrics.NEW_MAJOR_VIOLATIONS, - CoreMetrics.NEW_MINOR_VIOLATIONS, - CoreMetrics.NEW_INFO_VIOLATIONS, - CoreMetrics.OPEN_ISSUES, - CoreMetrics.REOPENED_ISSUES, - CoreMetrics.CONFIRMED_ISSUES - ); - } - - @Override - public void decorate(Resource resource, DecoratorContext context) { - Issuable issuable = perspectives.as(Issuable.class, resource); - if (issuable != null) { - Collection issues = issuable.issues(); - boolean shouldSaveNewMetrics = shouldSaveNewMetrics(context); - - Multiset severityBag = HashMultiset.create(); - Map> rulesPerSeverity = Maps.newHashMap(); - ListMultimap issuesPerSeverity = ArrayListMultimap.create(); - int countOpen = 0; - int countReopened = 0; - int countConfirmed = 0; - - for (Issue issue : issues) { - severityBag.add(RulePriority.valueOf(issue.severity())); - Multiset rulesBag = initRules(rulesPerSeverity, RulePriority.valueOf(issue.severity())); - rulesBag.add(issue.ruleKey()); - issuesPerSeverity.put(RulePriority.valueOf(issue.severity()), issue); - - if (Issue.STATUS_OPEN.equals(issue.status())) { - countOpen++; - } else if (Issue.STATUS_REOPENED.equals(issue.status())) { - countReopened++; - } else if (Issue.STATUS_CONFIRMED.equals(issue.status())) { - countConfirmed++; - } - } - - for (RulePriority ruleSeverity : RulePriority.values()) { - saveIssuesForSeverity(context, ruleSeverity, severityBag); - saveIssuesPerRules(context, ruleSeverity, rulesPerSeverity); - saveNewIssuesForSeverity(context, ruleSeverity, issuesPerSeverity, shouldSaveNewMetrics); - saveNewIssuesPerRule(context, ruleSeverity, issues, shouldSaveNewMetrics); - } - - saveTotalIssues(context, issues); - saveNewIssues(context, issues, shouldSaveNewMetrics); - - saveMeasure(context, CoreMetrics.OPEN_ISSUES, countOpen); - saveMeasure(context, CoreMetrics.REOPENED_ISSUES, countReopened); - saveMeasure(context, CoreMetrics.CONFIRMED_ISSUES, countConfirmed); - } - } - - private void saveTotalIssues(DecoratorContext context, Collection issues) { - if (context.getMeasure(CoreMetrics.VIOLATIONS) == null) { - Collection childrenIssues = context.getChildrenMeasures(CoreMetrics.VIOLATIONS); - Double sum = MeasureUtils.sum(true, childrenIssues); - context.saveMeasure(CoreMetrics.VIOLATIONS, sum + issues.size()); - } - } - - private void saveNewIssues(DecoratorContext context, Collection issues, boolean shouldSaveNewMetrics) { - if (shouldSaveNewMetrics) { - Measure measure = new Measure(CoreMetrics.NEW_VIOLATIONS); - saveNewIssues(context, measure, issues); - } - } - - private void saveIssuesForSeverity(DecoratorContext context, RulePriority ruleSeverity, Multiset severitiesBag) { - Metric metric = SeverityUtils.severityToIssueMetric(ruleSeverity); - if (context.getMeasure(metric) == null) { - Collection children = context.getChildrenMeasures(MeasuresFilters.metric(metric)); - int sum = MeasureUtils.sum(true, children).intValue() + severitiesBag.count(ruleSeverity); - context.saveMeasure(metric, (double) sum); - } - } - - private void saveNewIssuesForSeverity(DecoratorContext context, RulePriority severity, ListMultimap issuesPerSeverities, boolean shouldSaveNewMetrics) { - if (shouldSaveNewMetrics) { - Metric metric = SeverityUtils.severityToNewMetricIssue(severity); - Measure measure = new Measure(metric); - saveNewIssues(context, measure, issuesPerSeverities.get(severity)); - } - } - - private void saveIssuesPerRules(DecoratorContext context, RulePriority severity, Map> rulesPerSeverity) { - Metric metric = SeverityUtils.severityToIssueMetric(severity); - - Collection children = context.getChildrenMeasures(MeasuresFilters.rules(metric)); - for (Measure child : children) { - RuleMeasure childRuleMeasure = (RuleMeasure) child; - RuleKey ruleKey = childRuleMeasure.ruleKey(); - if (ruleKey != null && MeasureUtils.hasValue(childRuleMeasure)) { - Multiset rulesBag = initRules(rulesPerSeverity, severity); - rulesBag.add(ruleKey, childRuleMeasure.getIntValue()); - } - } - - Multiset rulesBag = rulesPerSeverity.get(severity); - if (rulesBag != null) { - for (Multiset.Entry entry : rulesBag.entrySet()) { - RuleMeasure measure = RuleMeasure.createForRule(metric, entry.getElement(), (double) entry.getCount()); - measure.setSeverity(severity); - context.saveMeasure(measure); - } - } - } - - private void saveNewIssuesPerRule(DecoratorContext context, RulePriority severity, Collection issues, boolean shouldSaveNewMetrics) { - if (shouldSaveNewMetrics) { - Metric metric = SeverityUtils.severityToNewMetricIssue(severity); - ListMultimap childMeasuresPerRuleKeys = ArrayListMultimap.create(); - ListMultimap issuesPerRuleKeys = ArrayListMultimap.create(); - Set ruleKeys = Sets.newHashSet(); - - Collection children = context.getChildrenMeasures(MeasuresFilters.rules(metric)); - for (Measure child : children) { - RuleMeasure childRuleMeasure = (RuleMeasure) child; - RuleKey ruleKey = childRuleMeasure.ruleKey(); - if (ruleKey != null) { - childMeasuresPerRuleKeys.put(ruleKey, childRuleMeasure); - ruleKeys.add(ruleKey); - } - } - - for (Issue issue : issues) { - if (RulePriority.valueOf(issue.severity()).equals(severity)) { - ruleKeys.add(issue.ruleKey()); - issuesPerRuleKeys.put(issue.ruleKey(), issue); - } - } - - for (RuleKey ruleKey : ruleKeys) { - RuleMeasure measure = RuleMeasure.createForRule(metric, ruleKey, null); - measure.setSeverity(severity); - for (Period period : timeMachineConfiguration.periods()) { - int variationIndex = period.getIndex(); - double sum = MeasureUtils.sumOnVariation(true, variationIndex, childMeasuresPerRuleKeys.get(ruleKey)) + countIssues(issuesPerRuleKeys.get(ruleKey), period); - measure.setVariation(variationIndex, sum); - } - context.saveMeasure(measure); - } - } - } - - private void saveNewIssues(DecoratorContext context, Measure measure, Collection issues) { - for (Period period : timeMachineConfiguration.periods()) { - int variationIndex = period.getIndex(); - Collection children = context.getChildrenMeasures(measure.getMetric()); - double sum = MeasureUtils.sumOnVariation(true, variationIndex, children) + countIssues(issues, period); - measure.setVariation(variationIndex, sum); - } - context.saveMeasure(measure); - } - - private void saveMeasure(DecoratorContext context, Metric metric, int value) { - context.saveMeasure(metric, (double) (value + sumChildren(context, metric))); - } - - private int sumChildren(DecoratorContext context, Metric metric) { - int sum = 0; - if (!ResourceUtils.isFile(context.getResource())) { - sum = MeasureUtils.sum(true, context.getChildrenMeasures(metric)).intValue(); - } - return sum; - } - - private Multiset initRules(Map> rulesPerSeverity, RulePriority severity) { - Multiset rulesBag = rulesPerSeverity.get(severity); - if (rulesBag == null) { - rulesBag = HashMultiset.create(); - rulesPerSeverity.put(severity, rulesBag); - } - return rulesBag; - } - - private int countIssues(Collection issues, Period period) { - // SONAR-3647 Use real snapshot date and not target date in order to stay consistent with other measure variations - Date datePlusOneSecond = period.getDate() != null ? DateUtils.addSeconds(period.getDate(), 1) : null; - return countIssuesAfterDate(issues, datePlusOneSecond); - } - - @VisibleForTesting - int countIssuesAfterDate(Collection issues, @Nullable Date date) { - if (issues == null) { - return 0; - } - int count = 0; - for (Issue issue : issues) { - if (isAfter(issue, date)) { - count++; - } - } - return count; - } - - private boolean isAfter(Issue issue, @Nullable Date date) { - return date == null || (issue.creationDate() != null && DateUtils.truncatedCompareTo(issue.creationDate(), date, Calendar.SECOND) > 0); - } - - private boolean shouldSaveNewMetrics(DecoratorContext context) { - return context.getMeasure(CoreMetrics.NEW_VIOLATIONS) == null; - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/SeverityUtils.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/SeverityUtils.java deleted file mode 100644 index e1a1d5ba19c..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/SeverityUtils.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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.plugins.core.issue; - -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Metric; -import org.sonar.api.rules.RulePriority; - -final class SeverityUtils { - private SeverityUtils() { - // only static methods - } - - static Metric severityToIssueMetric(RulePriority severity) { - Metric metric; - if (severity.equals(RulePriority.BLOCKER)) { - metric = CoreMetrics.BLOCKER_VIOLATIONS; - } else if (severity.equals(RulePriority.CRITICAL)) { - metric = CoreMetrics.CRITICAL_VIOLATIONS; - } else if (severity.equals(RulePriority.MAJOR)) { - metric = CoreMetrics.MAJOR_VIOLATIONS; - } else if (severity.equals(RulePriority.MINOR)) { - metric = CoreMetrics.MINOR_VIOLATIONS; - } else if (severity.equals(RulePriority.INFO)) { - metric = CoreMetrics.INFO_VIOLATIONS; - } else { - throw new IllegalArgumentException("Unsupported severity: " + severity); - } - return metric; - } - - static Metric severityToNewMetricIssue(RulePriority severity) { - Metric metric; - if (severity.equals(RulePriority.BLOCKER)) { - metric = CoreMetrics.NEW_BLOCKER_VIOLATIONS; - } else if (severity.equals(RulePriority.CRITICAL)) { - metric = CoreMetrics.NEW_CRITICAL_VIOLATIONS; - } else if (severity.equals(RulePriority.MAJOR)) { - metric = CoreMetrics.NEW_MAJOR_VIOLATIONS; - } else if (severity.equals(RulePriority.MINOR)) { - metric = CoreMetrics.NEW_MINOR_VIOLATIONS; - } else if (severity.equals(RulePriority.INFO)) { - metric = CoreMetrics.NEW_INFO_VIOLATIONS; - } else { - throw new IllegalArgumentException("Unsupported severity: " + severity); - } - return metric; - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/security/ApplyProjectRolesDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/security/ApplyProjectRolesDecorator.java deleted file mode 100644 index c93eb0e1228..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/security/ApplyProjectRolesDecorator.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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.plugins.core.security; - -import org.sonar.api.batch.RequiresDB; - -import com.google.common.collect.ImmutableSet; -import org.slf4j.LoggerFactory; -import org.sonar.api.batch.Decorator; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.resources.Resource; -import org.sonar.api.security.ResourcePermissions; - -import java.util.Set; - -@RequiresDB -public class ApplyProjectRolesDecorator implements Decorator { - - private static final Set QUALIFIERS = ImmutableSet.of(Qualifiers.PROJECT, Qualifiers.VIEW, Qualifiers.SUBVIEW); - private final ResourcePermissions resourcePermissions; - - public ApplyProjectRolesDecorator(ResourcePermissions resourcePermissions) { - this.resourcePermissions = resourcePermissions; - } - - @Override - public boolean shouldExecuteOnProject(Project project) { - return true; - } - - @Override - public void decorate(Resource resource, DecoratorContext context) { - if (shouldDecorateResource(resource)) { - LoggerFactory.getLogger(ApplyProjectRolesDecorator.class).info("Grant default permissions to {}", resource.getKey()); - resourcePermissions.grantDefaultRoles(resource); - } - } - - private boolean shouldDecorateResource(Resource resource) { - return resource.getId() != null && QUALIFIERS.contains(resource.getQualifier()) && !resourcePermissions.hasRoles(resource); - } - -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/AbstractCoverageDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/AbstractCoverageDecorator.java deleted file mode 100644 index 8b287506247..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/AbstractCoverageDecorator.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import org.sonar.api.batch.Decorator; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.DependedUpon; -import org.sonar.api.measures.Measure; -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 java.util.Arrays; -import java.util.Collection; - -public abstract class AbstractCoverageDecorator implements Decorator { - - @Override - public boolean shouldExecuteOnProject(Project project) { - return true; - } - - @DependedUpon - public Collection generatedMetrics() { - return Arrays.asList(getGeneratedMetric(), getGeneratedMetricForNewCode()); - } - - @Override - public void decorate(final Resource resource, final DecoratorContext context) { - if (shouldDecorate(resource)) { - computeMeasure(context); - computeMeasureForNewCode(context); - } - } - - protected boolean shouldDecorate(final Resource resource) { - return !ResourceUtils.isUnitTestFile(resource); - } - - private void computeMeasure(DecoratorContext context) { - if (context.getMeasure(getGeneratedMetric()) == null) { - Long elements = countElements(context); - if (elements != null && elements > 0L) { - Long coveredElements = countCoveredElements(context); - context.saveMeasure(getGeneratedMetric(), calculateCoverage(coveredElements, elements)); - } - } - } - - private void computeMeasureForNewCode(DecoratorContext context) { - if (context.getMeasure(getGeneratedMetricForNewCode()) == null) { - Measure measure = new Measure(getGeneratedMetricForNewCode()); - boolean hasValue = false; - /* TODO remove this magic number */ - for (int periodIndex = 1; periodIndex <= 5; periodIndex++) { - Long elements = countElementsForNewCode(context, periodIndex); - - if (elements != null && elements > 0L) { - long coveredElements = countCoveredElementsForNewCode(context, periodIndex); - measure.setVariation(periodIndex, calculateCoverage(coveredElements, elements)); - hasValue = true; - } - } - if (hasValue) { - context.saveMeasure(measure); - } - } - } - - private double calculateCoverage(final long coveredLines, final long lines) { - return (100.0 * coveredLines) / lines; - } - - protected abstract Metric getGeneratedMetric(); - - protected abstract Long countElements(DecoratorContext context); - - protected abstract long countCoveredElements(DecoratorContext context); - - protected abstract Metric getGeneratedMetricForNewCode(); - - protected abstract Long countElementsForNewCode(DecoratorContext context, int periodIndex); - - protected abstract long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex); -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/BranchCoverageDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/BranchCoverageDecorator.java deleted file mode 100644 index c154440ea39..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/BranchCoverageDecorator.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.DependsUpon; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.MeasureUtils; -import org.sonar.api.measures.Metric; -import org.sonar.batch.sensor.coverage.CoverageConstants; - -import java.util.Collection; - -public final class BranchCoverageDecorator extends AbstractCoverageDecorator { - - @DependsUpon - public Collection dependsUponMetrics() { - return CoverageConstants.BRANCH_COVERAGE_METRICS; - } - - @Override - protected Metric getGeneratedMetric() { - return CoreMetrics.BRANCH_COVERAGE; - } - - @Override - protected Long countElements(DecoratorContext context) { - return MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.CONDITIONS_TO_COVER), 0L); - } - - @Override - protected long countCoveredElements(DecoratorContext context) { - long uncoveredConditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.UNCOVERED_CONDITIONS), 0L); - long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.CONDITIONS_TO_COVER), 0L); - - return conditions - uncoveredConditions; - } - - @Override - protected Metric getGeneratedMetricForNewCode() { - return CoreMetrics.NEW_BRANCH_COVERAGE; - } - - @Override - protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) { - return MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_CONDITIONS_TO_COVER), periodIndex); - } - - @Override - protected long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex) { - long uncoveredConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_UNCOVERED_CONDITIONS), periodIndex, 0L); - long conditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_CONDITIONS_TO_COVER), periodIndex, 0L); - - return conditions - uncoveredConditions; - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CommentDensityDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CommentDensityDecorator.java deleted file mode 100644 index 76a54e7da55..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CommentDensityDecorator.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import org.sonar.api.batch.Decorator; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.DependedUpon; -import org.sonar.api.batch.DependsUpon; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -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 java.util.Arrays; -import java.util.List; - -public class CommentDensityDecorator implements Decorator { - - @DependsUpon - public List dependsUponMetrics() { - return Arrays.asList(CoreMetrics.NCLOC, CoreMetrics.COMMENT_LINES, CoreMetrics.PUBLIC_API, CoreMetrics.PUBLIC_UNDOCUMENTED_API); - } - - @DependedUpon - public List generatesMetrics() { - return Arrays.asList(CoreMetrics.COMMENT_LINES_DENSITY, CoreMetrics.PUBLIC_DOCUMENTED_API_DENSITY); - } - - @Override - public boolean shouldExecuteOnProject(Project project) { - return true; - } - - @Override - public void decorate(Resource resource, DecoratorContext context) { - saveCommentsDensity(context); - savePublicApiDensity(context); - } - - private void saveCommentsDensity(DecoratorContext context) { - if (context.getMeasure(CoreMetrics.COMMENT_LINES_DENSITY) != null) { - return; - } - - Measure ncloc = context.getMeasure(CoreMetrics.NCLOC); - Measure comments = context.getMeasure(CoreMetrics.COMMENT_LINES); - if (MeasureUtils.hasValue(ncloc) && MeasureUtils.hasValue(comments) && (comments.getValue() + ncloc.getValue()) > 0) { - double val = 100.0 * (comments.getValue() / (comments.getValue() + ncloc.getValue())); - context.saveMeasure(new Measure(CoreMetrics.COMMENT_LINES_DENSITY, val)); - } - } - - private void savePublicApiDensity(DecoratorContext context) { - if (context.getMeasure(CoreMetrics.PUBLIC_DOCUMENTED_API_DENSITY) != null) { - return; - } - - Measure publicApi = context.getMeasure(CoreMetrics.PUBLIC_API); - Measure publicUndocApi = context.getMeasure(CoreMetrics.PUBLIC_UNDOCUMENTED_API); - - if (MeasureUtils.hasValue(publicApi) && MeasureUtils.hasValue(publicUndocApi) && publicApi.getValue() > 0) { - double documentedAPI = publicApi.getValue() - publicUndocApi.getValue(); - Double value = 100.0 * (documentedAPI / publicApi.getValue()); - context.saveMeasure(new Measure(CoreMetrics.PUBLIC_DOCUMENTED_API_DENSITY, value)); - } - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CoverageDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CoverageDecorator.java deleted file mode 100644 index 0eb539f24b0..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CoverageDecorator.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.DependsUpon; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.MeasureUtils; -import org.sonar.api.measures.Metric; -import org.sonar.batch.sensor.coverage.CoverageConstants; - -import java.util.Collection; - -public final class CoverageDecorator extends AbstractCoverageDecorator { - - @DependsUpon - public Collection usedMetrics() { - return CoverageConstants.COVERAGE_METRICS; - } - - @Override - protected Metric getGeneratedMetric() { - return CoreMetrics.COVERAGE; - } - - @Override - protected Long countElements(DecoratorContext context) { - long linesToCover = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.LINES_TO_COVER), 0L); - long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.CONDITIONS_TO_COVER), 0L); - - return linesToCover + conditions; - } - - @Override - protected long countCoveredElements(DecoratorContext context) { - long uncoveredLines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.UNCOVERED_LINES), 0L); - long lines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.LINES_TO_COVER), 0L); - long uncoveredConditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.UNCOVERED_CONDITIONS), 0L); - long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.CONDITIONS_TO_COVER), 0L); - - return lines + conditions - uncoveredConditions - uncoveredLines; - } - - @Override - protected Metric getGeneratedMetricForNewCode() { - return CoreMetrics.NEW_COVERAGE; - } - - @Override - protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) { - Long newLinesToCover = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_LINES_TO_COVER), periodIndex); - if (newLinesToCover == null) { - return null; - } - - long newConditionsToCover = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_CONDITIONS_TO_COVER), periodIndex, 0L); - - return newLinesToCover + newConditionsToCover; - } - - @Override - protected long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex) { - long newLines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_LINES_TO_COVER), periodIndex, 0L); - long newUncoveredLines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_UNCOVERED_LINES), periodIndex, 0L); - long newUncoveredConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_UNCOVERED_CONDITIONS), periodIndex, 0L); - long newConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_CONDITIONS_TO_COVER), periodIndex, 0L); - - return newLines + newConditions - newUncoveredConditions - newUncoveredLines; - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/DirectoriesDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/DirectoriesDecorator.java deleted file mode 100644 index b8dddd4eb76..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/DirectoriesDecorator.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import org.sonar.api.batch.Decorator; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.DependedUpon; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -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 java.util.Collection; - -/** - * @since 2.2 - */ -public final class DirectoriesDecorator implements Decorator { - - @Override - public boolean shouldExecuteOnProject(Project project) { - return true; - } - - @DependedUpon - public Metric generateDirectoriesMetric() { - return CoreMetrics.DIRECTORIES; - } - - /** - * {@inheritDoc} - */ - @Override - public void decorate(Resource resource, DecoratorContext context) { - if (MeasureUtils.hasValue(context.getMeasure(CoreMetrics.DIRECTORIES))) { - return; - } - - if (Resource.QUALIFIER_DIRECTORY.equals(resource.getQualifier())) { - context.saveMeasure(CoreMetrics.DIRECTORIES, 1.0); - - } else if (ResourceUtils.isSet(resource)) { - Collection childrenMeasures = context.getChildrenMeasures(CoreMetrics.DIRECTORIES); - Double sum = MeasureUtils.sum(false, childrenMeasures); - if (sum != null) { - context.saveMeasure(CoreMetrics.DIRECTORIES, sum); - } - } - } -} 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 deleted file mode 100644 index 67f16205b6b..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/FilesDecorator.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import org.sonar.api.batch.Decorator; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.DependedUpon; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -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 java.util.Collection; - -/** - * @since 2.2 - */ -public final class FilesDecorator implements Decorator { - - @Override - public boolean shouldExecuteOnProject(Project project) { - return true; - } - - @DependedUpon - public Metric generateDirectoriesMetric() { - return CoreMetrics.FILES; - } - - @Override - public void decorate(Resource resource, DecoratorContext context) { - if (MeasureUtils.hasValue(context.getMeasure(CoreMetrics.FILES))) { - return; - } - - if (Resource.QUALIFIER_CLASS.equals(resource.getQualifier()) || Resource.QUALIFIER_FILE.equals(resource.getQualifier())) { - context.saveMeasure(CoreMetrics.FILES, 1.0); - - } else { - Collection childrenMeasures = context.getChildrenMeasures(CoreMetrics.FILES); - Double sum = MeasureUtils.sum(false, childrenMeasures); - if (sum != null) { - context.saveMeasure(CoreMetrics.FILES, sum); - } - } - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ItBranchCoverageDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ItBranchCoverageDecorator.java deleted file mode 100644 index eb515e363a5..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ItBranchCoverageDecorator.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import com.google.common.collect.ImmutableList; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.DependsUpon; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.MeasureUtils; -import org.sonar.api.measures.Metric; - -import java.util.List; - -public final class ItBranchCoverageDecorator extends AbstractCoverageDecorator { - - @DependsUpon - public List dependsUponMetrics() { - return ImmutableList.of(CoreMetrics.IT_UNCOVERED_CONDITIONS, CoreMetrics.IT_CONDITIONS_TO_COVER, - CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS, CoreMetrics.NEW_IT_CONDITIONS_TO_COVER); - } - - @Override - protected Metric getGeneratedMetric() { - return CoreMetrics.IT_BRANCH_COVERAGE; - } - - @Override - protected Long countElements(DecoratorContext context) { - return MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_CONDITIONS_TO_COVER), 0L); - } - - @Override - protected long countCoveredElements(DecoratorContext context) { - long uncoveredConditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_UNCOVERED_CONDITIONS), 0L); - long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_CONDITIONS_TO_COVER), 0L); - - return conditions - uncoveredConditions; - } - - @Override - protected Metric getGeneratedMetricForNewCode() { - return CoreMetrics.NEW_IT_BRANCH_COVERAGE; - } - - @Override - protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) { - return MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_CONDITIONS_TO_COVER), periodIndex); - } - - @Override - protected long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex) { - long uncoveredConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS), periodIndex, 0L); - long conditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_CONDITIONS_TO_COVER), periodIndex, 0L); - - return conditions - uncoveredConditions; - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ItCoverageDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ItCoverageDecorator.java deleted file mode 100644 index 9b2d990b48c..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ItCoverageDecorator.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import com.google.common.collect.ImmutableList; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.DependsUpon; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.MeasureUtils; -import org.sonar.api.measures.Metric; - -import java.util.Collection; - -public final class ItCoverageDecorator extends AbstractCoverageDecorator { - - @DependsUpon - public Collection usedMetrics() { - return ImmutableList.of(CoreMetrics.IT_LINES_TO_COVER, CoreMetrics.IT_UNCOVERED_LINES, CoreMetrics.NEW_IT_LINES_TO_COVER, - CoreMetrics.NEW_IT_UNCOVERED_LINES, CoreMetrics.IT_CONDITIONS_TO_COVER, CoreMetrics.IT_UNCOVERED_CONDITIONS, - CoreMetrics.NEW_IT_CONDITIONS_TO_COVER, CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS); - } - - @Override - protected Metric getGeneratedMetric() { - return CoreMetrics.IT_COVERAGE; - } - - @Override - protected Long countElements(DecoratorContext context) { - long lines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_LINES_TO_COVER), 0L); - long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_CONDITIONS_TO_COVER), 0L); - - return lines + conditions; - } - - @Override - protected long countCoveredElements(DecoratorContext context) { - long uncoveredLines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_UNCOVERED_LINES), 0L); - long lines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_LINES_TO_COVER), 0L); - long uncoveredConditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_UNCOVERED_CONDITIONS), 0L); - long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_CONDITIONS_TO_COVER), 0L); - - return lines + conditions - uncoveredConditions - uncoveredLines; - } - - @Override - protected Metric getGeneratedMetricForNewCode() { - return CoreMetrics.NEW_IT_COVERAGE; - } - - @Override - protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) { - Long newLinesToCover = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_LINES_TO_COVER), periodIndex); - if (newLinesToCover == null) { - return null; - } - - long newConditionsToCover = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_CONDITIONS_TO_COVER), periodIndex, 0L); - return newLinesToCover + newConditionsToCover; - } - - @Override - protected long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex) { - long newLines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_LINES_TO_COVER), periodIndex, 0L); - long newUncoveredLines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_UNCOVERED_LINES), periodIndex, 0L); - long newUncoveredConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS), periodIndex, 0L); - long newConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_CONDITIONS_TO_COVER), periodIndex, 0L); - - return newLines + newConditions - newUncoveredConditions - newUncoveredLines; - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ItLineCoverageDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ItLineCoverageDecorator.java deleted file mode 100644 index f829393180e..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ItLineCoverageDecorator.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import com.google.common.collect.ImmutableList; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.DependsUpon; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.MeasureUtils; -import org.sonar.api.measures.Metric; - -import java.util.List; - -public final class ItLineCoverageDecorator extends AbstractCoverageDecorator { - - @DependsUpon - public List dependsUponMetrics() { - return ImmutableList.of(CoreMetrics.IT_UNCOVERED_LINES, CoreMetrics.IT_LINES_TO_COVER, CoreMetrics.NEW_IT_UNCOVERED_LINES, - CoreMetrics.NEW_IT_LINES_TO_COVER); - } - - @Override - protected Metric getGeneratedMetric() { - return CoreMetrics.IT_LINE_COVERAGE; - } - - @Override - protected Long countElements(DecoratorContext context) { - return MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_LINES_TO_COVER), 0L); - } - - @Override - protected long countCoveredElements(DecoratorContext context) { - long uncoveredLines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_UNCOVERED_LINES), 0L); - long lines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_LINES_TO_COVER), 0L); - - return lines - uncoveredLines; - } - - @Override - protected Metric getGeneratedMetricForNewCode() { - return CoreMetrics.NEW_IT_LINE_COVERAGE; - } - - @Override - protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) { - return MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_LINES_TO_COVER), periodIndex); - } - - @Override - protected long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex) { - long uncoveredLines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_UNCOVERED_LINES), periodIndex, 0L); - long lines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_LINES_TO_COVER), periodIndex, 0L); - - return lines - uncoveredLines; - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/LineCoverageDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/LineCoverageDecorator.java deleted file mode 100644 index ebc29af0023..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/LineCoverageDecorator.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.DependsUpon; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.MeasureUtils; -import org.sonar.api.measures.Metric; -import org.sonar.batch.sensor.coverage.CoverageConstants; - -import java.util.Collection; - -public final class LineCoverageDecorator extends AbstractCoverageDecorator { - - @DependsUpon - public Collection dependsUponMetrics() { - return CoverageConstants.LINE_COVERAGE_METRICS; - } - - @Override - protected Metric getGeneratedMetric() { - return CoreMetrics.LINE_COVERAGE; - } - - @Override - protected Long countElements(DecoratorContext context) { - return MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.LINES_TO_COVER), 0L); - } - - @Override - protected long countCoveredElements(DecoratorContext context) { - long uncoveredLines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.UNCOVERED_LINES), 0L); - long lines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.LINES_TO_COVER), 0L); - - return lines - uncoveredLines; - } - - @Override - protected Metric getGeneratedMetricForNewCode() { - return CoreMetrics.NEW_LINE_COVERAGE; - } - - @Override - protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) { - return MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_LINES_TO_COVER), periodIndex); - } - - @Override - protected long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex) { - long uncoveredLines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_UNCOVERED_LINES), periodIndex, 0L); - long lines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_LINES_TO_COVER), periodIndex, 0L); - - return lines - uncoveredLines; - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ManualMeasureDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ManualMeasureDecorator.java deleted file mode 100644 index a62c1af9748..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ManualMeasureDecorator.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import org.sonar.api.batch.Decorator; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.Phase; -import org.sonar.api.batch.RequiresDB; -import org.sonar.api.database.DatabaseSession; -import org.sonar.api.measures.Measure; -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.jpa.entity.ManualMeasure; - -import java.util.List; - -import static com.google.common.base.Preconditions.checkState; - -@Phase(name = Phase.Name.PRE) -@RequiresDB -public class ManualMeasureDecorator implements Decorator { - - private DatabaseSession session; - private MetricFinder metricFinder; - - public ManualMeasureDecorator(DatabaseSession session, MetricFinder metricFinder) { - this.session = session; - this.metricFinder = metricFinder; - } - - @Override - public boolean shouldExecuteOnProject(Project project) { - return true; - } - - @Override - public void decorate(Resource resource, DecoratorContext context) { - if (resource.getId() != null) { - List manualMeasures = session.getResults(ManualMeasure.class, "resourceId", resource.getId()); - for (ManualMeasure manualMeasure : manualMeasures) { - context.saveMeasure(copy(manualMeasure)); - } - } - } - - private Measure copy(ManualMeasure manualMeasure) { - Metric metric = metricFinder.findById(manualMeasure.getMetricId()); - checkState(metric != null, "Unable to find manual metric with id: " + manualMeasure.getMetricId()); - - Measure measure = new Measure(metric); - measure.setValue(manualMeasure.getValue(), 5); - measure.setData(manualMeasure.getTextValue()); - measure.setDescription(manualMeasure.getDescription()); - return measure; - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/OverallBranchCoverageDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/OverallBranchCoverageDecorator.java deleted file mode 100644 index 2407269613a..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/OverallBranchCoverageDecorator.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import com.google.common.collect.ImmutableList; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.DependsUpon; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.MeasureUtils; -import org.sonar.api.measures.Metric; - -import java.util.List; - -public final class OverallBranchCoverageDecorator extends AbstractCoverageDecorator { - - @DependsUpon - public List dependsUponMetrics() { - return ImmutableList.of(CoreMetrics.OVERALL_UNCOVERED_CONDITIONS, CoreMetrics.OVERALL_CONDITIONS_TO_COVER, - CoreMetrics.NEW_OVERALL_UNCOVERED_CONDITIONS, CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER); - } - - @Override - protected Metric getGeneratedMetric() { - return CoreMetrics.OVERALL_BRANCH_COVERAGE; - } - - @Override - protected Long countElements(DecoratorContext context) { - return MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_CONDITIONS_TO_COVER), 0L); - } - - @Override - protected long countCoveredElements(DecoratorContext context) { - long uncoveredConditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_UNCOVERED_CONDITIONS), 0L); - long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_CONDITIONS_TO_COVER), 0L); - - return conditions - uncoveredConditions; - } - - @Override - protected Metric getGeneratedMetricForNewCode() { - return CoreMetrics.NEW_OVERALL_BRANCH_COVERAGE; - } - - @Override - protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) { - return MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER), periodIndex); - } - - @Override - protected long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex) { - long uncoveredConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_UNCOVERED_CONDITIONS), periodIndex, 0L); - long conditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER), periodIndex, 0L); - - return conditions - uncoveredConditions; - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/OverallCoverageDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/OverallCoverageDecorator.java deleted file mode 100644 index 49602e6c04a..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/OverallCoverageDecorator.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import com.google.common.collect.ImmutableList; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.DependsUpon; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.MeasureUtils; -import org.sonar.api.measures.Metric; - -import java.util.Collection; - -public final class OverallCoverageDecorator extends AbstractCoverageDecorator { - - @DependsUpon - public Collection usedMetrics() { - return ImmutableList.of(CoreMetrics.OVERALL_LINES_TO_COVER, CoreMetrics.OVERALL_UNCOVERED_LINES, CoreMetrics.NEW_OVERALL_LINES_TO_COVER, - CoreMetrics.NEW_OVERALL_UNCOVERED_LINES, CoreMetrics.OVERALL_CONDITIONS_TO_COVER, CoreMetrics.OVERALL_UNCOVERED_CONDITIONS, - CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER, CoreMetrics.NEW_OVERALL_UNCOVERED_CONDITIONS); - } - - @Override - protected Metric getGeneratedMetric() { - return CoreMetrics.OVERALL_COVERAGE; - } - - @Override - protected Long countElements(DecoratorContext context) { - long lines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_LINES_TO_COVER), 0L); - long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_CONDITIONS_TO_COVER), 0L); - - return lines + conditions; - } - - @Override - protected long countCoveredElements(DecoratorContext context) { - long uncoveredLines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_UNCOVERED_LINES), 0L); - long lines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_LINES_TO_COVER), 0L); - long uncoveredConditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_UNCOVERED_CONDITIONS), 0L); - long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_CONDITIONS_TO_COVER), 0L); - - return lines + conditions - uncoveredConditions - uncoveredLines; - } - - @Override - protected Metric getGeneratedMetricForNewCode() { - return CoreMetrics.NEW_OVERALL_COVERAGE; - } - - @Override - protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) { - Long newLinesToCover = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_LINES_TO_COVER), periodIndex); - if (newLinesToCover == null) { - return null; - } - - long newConditionsToCover = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER), periodIndex, 0L); - - return newLinesToCover + newConditionsToCover; - } - - @Override - protected long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex) { - long newLines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_LINES_TO_COVER), periodIndex, 0L); - long newUncoveredLines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_UNCOVERED_LINES), periodIndex, 0L); - long newUncoveredConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_UNCOVERED_CONDITIONS), periodIndex, 0L); - long newConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER), periodIndex, 0L); - - return newLines + newConditions - newUncoveredConditions - newUncoveredLines; - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/OverallLineCoverageDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/OverallLineCoverageDecorator.java deleted file mode 100644 index c6f53a2aaac..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/OverallLineCoverageDecorator.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import com.google.common.collect.ImmutableList; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.DependsUpon; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.MeasureUtils; -import org.sonar.api.measures.Metric; - -import java.util.List; - -public final class OverallLineCoverageDecorator extends AbstractCoverageDecorator { - - @DependsUpon - public List dependsUponMetrics() { - return ImmutableList.of(CoreMetrics.OVERALL_UNCOVERED_LINES, CoreMetrics.OVERALL_LINES_TO_COVER, CoreMetrics.NEW_OVERALL_UNCOVERED_LINES, - CoreMetrics.NEW_OVERALL_LINES_TO_COVER); - } - - @Override - protected Metric getGeneratedMetric() { - return CoreMetrics.OVERALL_LINE_COVERAGE; - } - - @Override - protected Long countElements(DecoratorContext context) { - return MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_LINES_TO_COVER), 0L); - } - - @Override - protected long countCoveredElements(DecoratorContext context) { - long uncoveredLines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_UNCOVERED_LINES), 0L); - long lines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_LINES_TO_COVER), 0L); - - return lines - uncoveredLines; - } - - @Override - protected Metric getGeneratedMetricForNewCode() { - return CoreMetrics.NEW_OVERALL_LINE_COVERAGE; - } - - @Override - protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) { - return MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_LINES_TO_COVER), periodIndex); - } - - @Override - protected long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex) { - long uncoveredLines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_UNCOVERED_LINES), periodIndex, 0L); - long lines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_LINES_TO_COVER), periodIndex, 0L); - - return lines - uncoveredLines; - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/UnitTestDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/UnitTestDecorator.java deleted file mode 100644 index 7e4680f20f9..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/UnitTestDecorator.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import org.sonar.api.batch.Decorator; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.DependedUpon; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -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 java.util.Arrays; -import java.util.Collection; -import java.util.List; - -public class UnitTestDecorator implements Decorator { - - @DependedUpon - public List generatesMetrics() { - return Arrays.asList(CoreMetrics.TEST_EXECUTION_TIME, CoreMetrics.TESTS, CoreMetrics.TEST_ERRORS, CoreMetrics.TEST_FAILURES, CoreMetrics.TEST_SUCCESS_DENSITY); - } - - @Override - public boolean shouldExecuteOnProject(Project project) { - return !Project.AnalysisType.STATIC.equals(project.getAnalysisType()); - } - - public boolean shouldDecorateResource(Resource resource) { - return ResourceUtils.isUnitTestFile(resource) || !ResourceUtils.isEntity(resource); - } - - @Override - public void decorate(Resource resource, DecoratorContext context) { - if (shouldDecorateResource(resource)) { - sumChildren(context, CoreMetrics.TEST_EXECUTION_TIME); - sumChildren(context, CoreMetrics.SKIPPED_TESTS); - Double tests = sumChildren(context, CoreMetrics.TESTS); - Double errors = sumChildren(context, CoreMetrics.TEST_ERRORS); - Double failures = sumChildren(context, CoreMetrics.TEST_FAILURES); - - if (isPositive(tests, true) && isPositive(errors, false) && isPositive(failures, false)) { - Double errorsAndFailuresRatio = (errors + failures) * 100.0 / tests; - context.saveMeasure(CoreMetrics.TEST_SUCCESS_DENSITY, 100.0 - errorsAndFailuresRatio); - } - } - } - - private boolean isPositive(Double d, boolean strict) { - return d != null && (strict ? d > 0.0 : d >= 0.0); - } - - private Double sumChildren(DecoratorContext jobContext, Metric metric) { - Collection childrenMeasures = jobContext.getChildrenMeasures(metric); - if (childrenMeasures != null && !childrenMeasures.isEmpty()) { - Double sum = 0.0; - boolean hasChildrenMeasures = false; - for (Measure measure : childrenMeasures) { - if (MeasureUtils.hasValue(measure)) { - sum += measure.getValue(); - hasChildrenMeasures = true; - } - } - if (hasChildrenMeasures) { - jobContext.saveMeasure(metric, sum); - return sum; - } - } - return null; - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/AbstractNewCoverageFileAnalyzer.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/AbstractNewCoverageFileAnalyzer.java deleted file mode 100644 index 35d8a3506e4..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/AbstractNewCoverageFileAnalyzer.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * 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.plugins.core.timemachine; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.commons.lang.ObjectUtils; -import org.sonar.api.batch.Decorator; -import org.sonar.api.batch.DecoratorBarriers; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.DependedUpon; -import org.sonar.api.batch.DependsUpon; -import org.sonar.api.batch.RequiresDB; -import org.sonar.api.measures.Measure; -import org.sonar.api.measures.Metric; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.resources.Resource; -import org.sonar.api.resources.Scopes; -import org.sonar.api.utils.KeyValueFormat; -import org.sonar.batch.components.Period; -import org.sonar.batch.components.TimeMachineConfiguration; -import org.sonar.batch.index.BatchComponentCache; -import org.sonar.batch.protocol.output.BatchReport; -import org.sonar.batch.protocol.output.BatchReport.Changesets.Changeset; -import org.sonar.batch.protocol.output.BatchReportReader; -import org.sonar.batch.report.ReportPublisher; - -import javax.annotation.Nullable; - -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.Map; - -/** - * @since 2.7 - */ -@RequiresDB -@DependedUpon(DecoratorBarriers.END_OF_TIME_MACHINE) -public abstract class AbstractNewCoverageFileAnalyzer implements Decorator { - - private final List structs; - private final ReportPublisher publishReportJob; - private final BatchComponentCache resourceCache; - - public AbstractNewCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration, ReportPublisher publishReportJob, BatchComponentCache resourceCache) { - this(Lists.newArrayList(), publishReportJob, resourceCache); - for (Period period : timeMachineConfiguration.periods()) { - structs.add(new PeriodStruct(period.getIndex(), period.getDate())); - } - } - - AbstractNewCoverageFileAnalyzer(List structs, ReportPublisher publishReportJob, BatchComponentCache resourceCache) { - this.resourceCache = resourceCache; - this.publishReportJob = publishReportJob; - this.structs = structs; - } - - public abstract Metric getCoverageLineHitsDataMetric(); - - public abstract Metric getConditionsByLineMetric(); - - public abstract Metric getCoveredConditionsByLineMetric(); - - public abstract Metric getNewLinesToCoverMetric(); - - public abstract Metric getNewUncoveredLinesMetric(); - - public abstract Metric getNewConditionsToCoverMetric(); - - public abstract Metric getNewUncoveredConditionsMetric(); - - @Override - public boolean shouldExecuteOnProject(Project project) { - return !structs.isEmpty(); - } - - private boolean shouldDecorate(Resource resource) { - return Scopes.isFile(resource) && !Qualifiers.UNIT_TEST_FILE.equals(resource.getQualifier()); - } - - @DependsUpon - public List dependsOnMetrics() { - - return Arrays.asList(getCoverageLineHitsDataMetric(), getConditionsByLineMetric(), getCoveredConditionsByLineMetric()); - } - - @DependedUpon - public List generatesNewCoverageMetrics() { - return Arrays.asList(getNewLinesToCoverMetric(), getNewUncoveredLinesMetric(), getNewConditionsToCoverMetric(), getNewUncoveredConditionsMetric()); - } - - @Override - public void decorate(Resource resource, DecoratorContext context) { - if (shouldDecorate(resource)) { - doDecorate(context); - } - } - - void doDecorate(DecoratorContext context) { - if (parse(context)) { - compute(context); - } - } - - private boolean parse(DecoratorContext context) { - BatchReportReader reader = new BatchReportReader(publishReportJob.getReportDir()); - BatchReport.Changesets componentScm = reader.readChangesets(resourceCache.get(context.getResource()).batchId()); - Measure hitsByLineMeasure = context.getMeasure(getCoverageLineHitsDataMetric()); - - if (componentScm != null && hitsByLineMeasure != null && hitsByLineMeasure.hasData()) { - Map hitsByLine = parseCountByLine(hitsByLineMeasure); - Map conditionsByLine = parseCountByLine(context.getMeasure(getConditionsByLineMetric())); - Map coveredConditionsByLine = parseCountByLine(context.getMeasure(getCoveredConditionsByLineMetric())); - - reset(); - - for (Map.Entry entry : hitsByLine.entrySet()) { - int lineId = entry.getKey(); - int hits = entry.getValue(); - int conditions = (Integer) ObjectUtils.defaultIfNull(conditionsByLine.get(lineId), 0); - int coveredConditions = (Integer) ObjectUtils.defaultIfNull(coveredConditionsByLine.get(lineId), 0); - Changeset changeset = componentScm.getChangeset(componentScm.getChangesetIndexByLine(lineId - 1)); - Date date = changeset.hasDate() ? new Date(changeset.getDate()) : null; - for (PeriodStruct struct : structs) { - struct.analyze(date, hits, conditions, coveredConditions); - } - } - - return true; - } - return false; - } - - private void reset() { - for (PeriodStruct struct : structs) { - struct.reset(); - } - } - - private void compute(DecoratorContext context) { - Measure newLines = new Measure(getNewLinesToCoverMetric()); - Measure newUncoveredLines = new Measure(getNewUncoveredLinesMetric()); - Measure newConditions = new Measure(getNewConditionsToCoverMetric()); - Measure newUncoveredConditions = new Measure(getNewUncoveredConditionsMetric()); - - for (PeriodStruct struct : structs) { - if (struct.hasNewCode()) { - newLines.setVariation(struct.index, (double) struct.getNewLines()); - newUncoveredLines.setVariation(struct.index, (double) (struct.getNewLines() - struct.getNewCoveredLines())); - newConditions.setVariation(struct.index, (double) struct.getNewConditions()); - newUncoveredConditions.setVariation(struct.index, (double) struct.getNewConditions() - struct.getNewCoveredConditions()); - } - } - - context.saveMeasure(newLines); - context.saveMeasure(newUncoveredLines); - context.saveMeasure(newConditions); - context.saveMeasure(newUncoveredConditions); - } - - private Map parseCountByLine(@Nullable Measure measure) { - if (measure != null && measure.hasData()) { - return KeyValueFormat.parseIntInt(measure.getData()); - } - return Maps.newHashMap(); - } - - public static final class PeriodStruct { - int index; - Date date; - Integer newLines; - Integer newCoveredLines; - Integer newConditions; - Integer newCoveredConditions; - - PeriodStruct(int index, @Nullable Date date) { - this.index = index; - this.date = date; - } - - void reset() { - newLines = null; - newCoveredLines = null; - newConditions = null; - newCoveredConditions = null; - } - - void analyze(@Nullable Date lineDate, int hits, int conditions, int coveredConditions) { - if (lineDate == null) { - // TODO warning - - } else if (date == null || lineDate.after(date)) { - // TODO test if string comparison is faster or not - addLine(hits > 0); - addConditions(conditions, coveredConditions); - } - } - - void addLine(boolean covered) { - if (newLines == null) { - newLines = 0; - } - newLines += 1; - if (covered) { - if (newCoveredLines == null) { - newCoveredLines = 0; - } - newCoveredLines += 1; - } - } - - void addConditions(int count, int countCovered) { - if (newConditions == null) { - newConditions = 0; - } - newConditions += count; - if (count > 0) { - if (newCoveredConditions == null) { - newCoveredConditions = 0; - } - newCoveredConditions += countCovered; - } - } - - boolean hasNewCode() { - return newLines != null; - } - - public int getNewLines() { - return newLines != null ? newLines : 0; - } - - public int getNewCoveredLines() { - return newCoveredLines != null ? newCoveredLines : 0; - } - - public int getNewConditions() { - return newConditions != null ? newConditions : 0; - } - - public int getNewCoveredConditions() { - return newCoveredConditions != null ? newCoveredConditions : 0; - } - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewCoverageAggregator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewCoverageAggregator.java deleted file mode 100644 index 70735e66566..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewCoverageAggregator.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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.plugins.core.timemachine; - -import org.apache.commons.lang.ArrayUtils; -import org.sonar.api.batch.Decorator; -import org.sonar.api.batch.DecoratorBarriers; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.DependedUpon; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -import org.sonar.api.measures.Metric; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.resources.Resource; -import org.sonar.api.resources.Scopes; - -import java.util.Arrays; -import java.util.List; - -@DependedUpon(DecoratorBarriers.END_OF_TIME_MACHINE) -public final class NewCoverageAggregator implements Decorator { - - @Override - public boolean shouldExecuteOnProject(Project project) { - return true; - } - - @DependedUpon - public List generatesNewCoverageMetrics() { - return Arrays.asList( - CoreMetrics.NEW_LINES_TO_COVER, CoreMetrics.NEW_UNCOVERED_LINES, CoreMetrics.NEW_CONDITIONS_TO_COVER, CoreMetrics.NEW_UNCOVERED_CONDITIONS, - CoreMetrics.NEW_IT_LINES_TO_COVER, CoreMetrics.NEW_IT_UNCOVERED_LINES, CoreMetrics.NEW_IT_CONDITIONS_TO_COVER, CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS, - CoreMetrics.NEW_OVERALL_LINES_TO_COVER, CoreMetrics.NEW_OVERALL_UNCOVERED_LINES, CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER, CoreMetrics.NEW_OVERALL_UNCOVERED_CONDITIONS); - } - - @Override - public void decorate(Resource resource, DecoratorContext context) { - if (shouldDecorate(resource)) { - int maxPeriods = Qualifiers.isView(resource, true) ? 3 : 5; - aggregate(context, CoreMetrics.NEW_LINES_TO_COVER, maxPeriods); - aggregate(context, CoreMetrics.NEW_UNCOVERED_LINES, maxPeriods); - aggregate(context, CoreMetrics.NEW_CONDITIONS_TO_COVER, maxPeriods); - aggregate(context, CoreMetrics.NEW_UNCOVERED_CONDITIONS, maxPeriods); - aggregate(context, CoreMetrics.NEW_IT_LINES_TO_COVER, maxPeriods); - aggregate(context, CoreMetrics.NEW_IT_UNCOVERED_LINES, maxPeriods); - aggregate(context, CoreMetrics.NEW_IT_CONDITIONS_TO_COVER, maxPeriods); - aggregate(context, CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS, maxPeriods); - aggregate(context, CoreMetrics.NEW_OVERALL_LINES_TO_COVER, maxPeriods); - aggregate(context, CoreMetrics.NEW_OVERALL_UNCOVERED_LINES, maxPeriods); - aggregate(context, CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER, maxPeriods); - aggregate(context, CoreMetrics.NEW_OVERALL_UNCOVERED_CONDITIONS, maxPeriods); - } - } - - void aggregate(DecoratorContext context, Metric metric, int maxPeriods) { - int[] variations = {0, 0, 0, 0, 0}; - boolean[] hasValues = {false, false, false, false, false}; - for (Measure child : context.getChildrenMeasures(metric)) { - for (int indexPeriod = 1; indexPeriod <= maxPeriods; indexPeriod++) { - Double variation = child.getVariation(indexPeriod); - if (variation != null) { - variations[indexPeriod - 1] = variations[indexPeriod - 1] + variation.intValue(); - hasValues[indexPeriod - 1] = true; - } - } - } - - if (ArrayUtils.contains(hasValues, true)) { - Measure measure = new Measure(metric); - for (int index = 0; index < 5; index++) { - if (hasValues[index]) { - measure.setVariation(index + 1, (double) variations[index]); - } - } - context.saveMeasure(measure); - } - } - - boolean shouldDecorate(Resource resource) { - return Scopes.isHigherThan(resource, Scopes.FILE); - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzer.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzer.java deleted file mode 100644 index 79f028966cd..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzer.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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.plugins.core.timemachine; - -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Metric; -import org.sonar.batch.components.TimeMachineConfiguration; -import org.sonar.batch.index.BatchComponentCache; -import org.sonar.batch.report.ReportPublisher; - -import java.util.List; - -public class NewCoverageFileAnalyzer extends AbstractNewCoverageFileAnalyzer { - - public NewCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration, ReportPublisher publishReportJob, BatchComponentCache resourceCache) { - super(timeMachineConfiguration, publishReportJob, resourceCache); - } - - NewCoverageFileAnalyzer(List structs, ReportPublisher publishReportJob, BatchComponentCache resourceCache) { - super(structs, publishReportJob, resourceCache); - } - - @Override - public Metric getCoverageLineHitsDataMetric() { - return CoreMetrics.COVERAGE_LINE_HITS_DATA; - } - - @Override - public Metric getConditionsByLineMetric() { - return CoreMetrics.CONDITIONS_BY_LINE; - } - - @Override - public Metric getCoveredConditionsByLineMetric() { - return CoreMetrics.COVERED_CONDITIONS_BY_LINE; - } - - @Override - public Metric getNewLinesToCoverMetric() { - return CoreMetrics.NEW_LINES_TO_COVER; - } - - @Override - public Metric getNewUncoveredLinesMetric() { - return CoreMetrics.NEW_UNCOVERED_LINES; - } - - @Override - public Metric getNewConditionsToCoverMetric() { - return CoreMetrics.NEW_CONDITIONS_TO_COVER; - } - - @Override - public Metric getNewUncoveredConditionsMetric() { - return CoreMetrics.NEW_UNCOVERED_CONDITIONS; - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewItCoverageFileAnalyzer.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewItCoverageFileAnalyzer.java deleted file mode 100644 index 2aacf34a9bd..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewItCoverageFileAnalyzer.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.plugins.core.timemachine; - -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Metric; -import org.sonar.batch.components.TimeMachineConfiguration; -import org.sonar.batch.index.BatchComponentCache; -import org.sonar.batch.report.ReportPublisher; - -public class NewItCoverageFileAnalyzer extends AbstractNewCoverageFileAnalyzer { - - public NewItCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration, ReportPublisher publishReportJob, BatchComponentCache resourceCache) { - super(timeMachineConfiguration, publishReportJob, resourceCache); - } - - @Override - public Metric getCoverageLineHitsDataMetric() { - return CoreMetrics.IT_COVERAGE_LINE_HITS_DATA; - } - - @Override - public Metric getConditionsByLineMetric() { - return CoreMetrics.IT_CONDITIONS_BY_LINE; - } - - @Override - public Metric getCoveredConditionsByLineMetric() { - return CoreMetrics.IT_COVERED_CONDITIONS_BY_LINE; - } - - @Override - public Metric getNewLinesToCoverMetric() { - return CoreMetrics.NEW_IT_LINES_TO_COVER; - } - - @Override - public Metric getNewUncoveredLinesMetric() { - return CoreMetrics.NEW_IT_UNCOVERED_LINES; - } - - @Override - public Metric getNewConditionsToCoverMetric() { - return CoreMetrics.NEW_IT_CONDITIONS_TO_COVER; - } - - @Override - public Metric getNewUncoveredConditionsMetric() { - return CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS; - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewOverallCoverageFileAnalyzer.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewOverallCoverageFileAnalyzer.java deleted file mode 100644 index f80da9470bb..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewOverallCoverageFileAnalyzer.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.plugins.core.timemachine; - -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Metric; -import org.sonar.batch.components.TimeMachineConfiguration; -import org.sonar.batch.index.BatchComponentCache; -import org.sonar.batch.report.ReportPublisher; - -public class NewOverallCoverageFileAnalyzer extends AbstractNewCoverageFileAnalyzer { - - public NewOverallCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration, ReportPublisher publishReportJob, BatchComponentCache resourceCache) { - super(timeMachineConfiguration, publishReportJob, resourceCache); - } - - @Override - public Metric getCoverageLineHitsDataMetric() { - return CoreMetrics.OVERALL_COVERAGE_LINE_HITS_DATA; - } - - @Override - public Metric getConditionsByLineMetric() { - return CoreMetrics.OVERALL_CONDITIONS_BY_LINE; - } - - @Override - public Metric getCoveredConditionsByLineMetric() { - return CoreMetrics.OVERALL_COVERED_CONDITIONS_BY_LINE; - } - - @Override - public Metric getNewLinesToCoverMetric() { - return CoreMetrics.NEW_OVERALL_LINES_TO_COVER; - } - - @Override - public Metric getNewUncoveredLinesMetric() { - return CoreMetrics.NEW_OVERALL_UNCOVERED_LINES; - } - - @Override - public Metric getNewConditionsToCoverMetric() { - return CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER; - } - - @Override - public Metric getNewUncoveredConditionsMetric() { - return CoreMetrics.NEW_OVERALL_UNCOVERED_CONDITIONS; - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/TimeMachineConfigurationPersister.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/TimeMachineConfigurationPersister.java deleted file mode 100644 index 7427654f1bc..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/TimeMachineConfigurationPersister.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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.plugins.core.timemachine; - -import org.sonar.api.batch.*; -import org.sonar.api.database.DatabaseSession; -import org.sonar.api.database.model.Snapshot; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Resource; -import org.sonar.api.resources.ResourceUtils; -import org.sonar.batch.components.PastSnapshot; -import org.sonar.batch.components.TimeMachineConfiguration; -import org.sonar.batch.index.BatchComponentCache; - -import java.util.List; - -import static org.sonar.api.utils.DateUtils.dateToLong; - -@DependedUpon(DecoratorBarriers.END_OF_TIME_MACHINE) -@RequiresDB -public final class TimeMachineConfigurationPersister implements Decorator { - - private final TimeMachineConfiguration timeMachineConfiguration; - private BatchComponentCache resourceCache; - private DatabaseSession session; - - public TimeMachineConfigurationPersister(TimeMachineConfiguration timeMachineConfiguration, BatchComponentCache resourceCache, DatabaseSession session) { - this.timeMachineConfiguration = timeMachineConfiguration; - this.resourceCache = resourceCache; - this.session = session; - } - - @Override - public void decorate(Resource resource, DecoratorContext context) { - if (ResourceUtils.isProject(resource)) { - persistConfiguration(resource); - } - } - - void persistConfiguration(Resource module) { - List pastSnapshots = timeMachineConfiguration.getProjectPastSnapshots(); - Snapshot projectSnapshot = resourceCache.get(module).snapshot(); - for (PastSnapshot pastSnapshot : pastSnapshots) { - Snapshot snapshot = session.reattach(Snapshot.class, projectSnapshot.getId()); - updatePeriodParams(snapshot, pastSnapshot); - updatePeriodParams(projectSnapshot, pastSnapshot); - session.save(snapshot); - } - session.commit(); - } - - @Override - public boolean shouldExecuteOnProject(Project project) { - return true; - } - - private void updatePeriodParams(Snapshot snapshot, PastSnapshot pastSnapshot) { - int periodIndex = pastSnapshot.getIndex(); - snapshot.setPeriodMode(periodIndex, pastSnapshot.getMode()); - snapshot.setPeriodModeParameter(periodIndex, pastSnapshot.getModeParameter()); - snapshot.setPeriodDateMs(periodIndex, dateToLong(pastSnapshot.getDate())); - } -} 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 deleted file mode 100644 index 36e525ecfb1..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/VariationDecorator.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * 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.plugins.core.timemachine; - -import com.google.common.collect.Maps; -import org.apache.commons.lang.StringUtils; -import org.sonar.api.batch.*; -import org.sonar.api.measures.*; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.resources.Resource; -import org.sonar.api.resources.Scopes; -import org.sonar.api.rules.Rule; -import org.sonar.api.rules.RuleFinder; -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 javax.annotation.Nullable; - -import java.util.Collection; -import java.util.List; -import java.util.Map; - -@DependedUpon(DecoratorBarriers.END_OF_TIME_MACHINE) -@RequiresDB -public class VariationDecorator implements Decorator { - - private List projectPastSnapshots; - private MetricFinder metricFinder; - private PastMeasuresLoader pastMeasuresLoader; - private RuleFinder ruleFinder; - - 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) { - this.pastMeasuresLoader = pastMeasuresLoader; - this.projectPastSnapshots = projectPastSnapshots; - this.metricFinder = metricFinder; - this.ruleFinder = ruleFinder; - } - - @Override - public boolean shouldExecuteOnProject(Project project) { - return true; - } - - @DependsUpon - public Collection dependsUponMetrics() { - return pastMeasuresLoader.getMetrics(); - } - - @Override - public void decorate(Resource resource, DecoratorContext context) { - for (PastSnapshot projectPastSnapshot : projectPastSnapshots) { - if (shouldComputeVariation(resource)) { - computeVariation(resource, context, projectPastSnapshot); - } - } - } - - boolean shouldComputeVariation(Resource resource) { - if (Scopes.FILE.equals(resource.getScope()) && !Qualifiers.UNIT_TEST_FILE.equals(resource.getQualifier())) { - return false; - } - - // measures on files are currently purged, so past measures are not available on files - return StringUtils.equals(Scopes.PROJECT, resource.getScope()) || StringUtils.equals(Scopes.DIRECTORY, resource.getScope()); - } - - private void computeVariation(Resource resource, DecoratorContext context, PastSnapshot pastSnapshot) { - List pastMeasures = pastMeasuresLoader.getPastMeasures(resource, pastSnapshot); - compareWithPastMeasures(context, pastSnapshot.getIndex(), pastMeasures); - } - - private void compareWithPastMeasures(DecoratorContext context, int index, List pastMeasures) { - Map pastMeasuresByKey = Maps.newHashMap(); - for (Object[] pastMeasure : pastMeasures) { - pastMeasuresByKey.put(new MeasureKey(pastMeasure), pastMeasure); - } - - // for each measure, search equivalent past measure - for (Measure measure : context.getMeasures(MeasuresFilters.all())) { - // compare with past measure - Integer metricId = measure.getMetric().getId(); - if (metricId == null) { - Metric metric = metricFinder.findByKey(measure.getMetric().getKey()); - if (metric == null) { - throw new IllegalStateException("Unknow metric with key: " + measure.getMetric().getKey()); - } - metricId = metric.getId(); - } - Characteristic characteristic = measure.getCharacteristic(); - Integer characteristicId = characteristic != null ? characteristic.id() : null; - Integer personId = measure.getPersonId(); - Integer ruleId = null; - if (measure instanceof RuleMeasure) { - Rule rule = ruleFinder.findByKey(((RuleMeasure) measure).ruleKey()); - if (rule != null) { - ruleId = rule.getId(); - } - } - - Object[] pastMeasure = pastMeasuresByKey.get(new MeasureKey(metricId, characteristicId, personId, ruleId)); - if (updateVariation(measure, pastMeasure, index)) { - context.saveMeasure(measure); - } - } - } - - boolean updateVariation(Measure measure, Object[] pastMeasure, int index) { - if (pastMeasure != null && PastMeasuresLoader.hasValue(pastMeasure) && measure.getValue() != null) { - double variation = measure.getValue() - PastMeasuresLoader.getValue(pastMeasure); - measure.setVariation(index, variation); - return true; - } - return false; - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } - - static final class MeasureKey { - int metricId; - Integer characteristicId; - Integer personId; - Integer ruleId; - - MeasureKey(Object[] pastFields) { - metricId = PastMeasuresLoader.getMetricId(pastFields); - characteristicId = PastMeasuresLoader.getCharacteristicId(pastFields); - personId = PastMeasuresLoader.getPersonId(pastFields); - ruleId = PastMeasuresLoader.getRuleId(pastFields); - } - - MeasureKey(int metricId, @Nullable Integer characteristicId, @Nullable Integer personId, @Nullable Integer ruleId) { - this.metricId = metricId; - this.characteristicId = characteristicId; - this.personId = personId; - this.ruleId = ruleId; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - MeasureKey that = (MeasureKey) o; - if (metricId != that.metricId) { - return false; - } - if (characteristicId != null ? !characteristicId.equals(that.characteristicId) : that.characteristicId != null) { - return false; - } - if (personId != null ? !personId.equals(that.personId) : that.personId != null) { - return false; - } - if (ruleId != null ? !ruleId.equals(that.ruleId) : that.ruleId != null) { - return false; - } - return true; - } - - @Override - public int hashCode() { - int result = metricId; - result = 31 * result + (characteristicId != null ? characteristicId.hashCode() : 0); - result = 31 * result + (personId != null ? personId.hashCode() : 0); - result = 31 * result + (ruleId != null ? ruleId.hashCode() : 0); - return result; - } - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/package-info.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/package-info.java deleted file mode 100644 index 8d487ae9500..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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. - */ -@ParametersAreNonnullByDefault -package org.sonar.plugins.core.timemachine; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/CorePluginTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/CorePluginTest.java index 0e312383c2c..f21fb3bbaca 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/CorePluginTest.java +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/CorePluginTest.java @@ -26,6 +26,6 @@ import static org.assertj.core.api.Assertions.assertThat; public class CorePluginTest { @Test public void should_define_extensions() { - assertThat(new CorePlugin().getExtensions().size()).isGreaterThan(10); + assertThat(new CorePlugin().getExtensions().size()).isGreaterThan(2); } } diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/CountFalsePositivesDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/CountFalsePositivesDecoratorTest.java deleted file mode 100644 index 28327ac5954..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/CountFalsePositivesDecoratorTest.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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.plugins.core.issue; - -import org.junit.Test; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.component.ResourcePerspectives; -import org.sonar.api.issue.Issuable; -import org.sonar.api.issue.Issue; -import org.sonar.api.issue.internal.DefaultIssue; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.resources.File; -import org.sonar.api.resources.Project; -import org.sonar.api.rule.RuleKey; -import org.sonar.java.api.JavaClass; - -import java.util.Arrays; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -public class CountFalsePositivesDecoratorTest { - - ResourcePerspectives perspectives = mock(ResourcePerspectives.class); - CountFalsePositivesDecorator decorator = new CountFalsePositivesDecorator(perspectives); - - @Test - public void should_count_false_positives() { - DefaultIssue falsePositive = new DefaultIssue().setRuleKey(RuleKey.parse("squid:AvoidCycles")) - .setResolution(Issue.RESOLUTION_FALSE_POSITIVE).setStatus(Issue.STATUS_RESOLVED); - DefaultIssue fixed = new DefaultIssue().setRuleKey(RuleKey.parse("squid:AvoidCycles")) - .setResolution(Issue.RESOLUTION_FIXED).setStatus(Issue.STATUS_RESOLVED); - - File file = File.create("foo.c"); - Issuable issuable = mock(Issuable.class); - when(perspectives.as(Issuable.class, file)).thenReturn(issuable); - when(issuable.resolvedIssues()).thenReturn(Arrays.asList(falsePositive, fixed)); - - DecoratorContext context = mock(DecoratorContext.class); - decorator.decorate(file, context); - - verify(context).saveMeasure(CoreMetrics.FALSE_POSITIVE_ISSUES, 1.0); - } - - @Test - public void should_declare_metadata() { - assertThat(decorator.shouldExecuteOnProject(new Project("foo"))).isTrue(); - assertThat(decorator.generatesFalsePositiveMeasure()).isEqualTo(CoreMetrics.FALSE_POSITIVE_ISSUES); - assertThat(decorator.toString()).isEqualTo("CountFalsePositivesDecorator"); - } - - @Test - public void should_ignore_classes_and_methods() { - JavaClass javaClass = JavaClass.create("Foo.java"); - when(perspectives.as(Issuable.class, javaClass)).thenReturn(null); - - DecoratorContext context = mock(DecoratorContext.class); - decorator.decorate(javaClass, context); - - verifyZeroInteractions(context); - } -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/CountUnresolvedIssuesDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/CountUnresolvedIssuesDecoratorTest.java deleted file mode 100644 index ebd2b99b553..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/CountUnresolvedIssuesDecoratorTest.java +++ /dev/null @@ -1,361 +0,0 @@ -/* - * 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.plugins.core.issue; - -import org.sonar.batch.components.Period; - -import org.sonar.batch.components.TimeMachineConfiguration; -import com.google.common.collect.Lists; -import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang.time.DateUtils; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentMatcher; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.component.ResourcePerspectives; -import org.sonar.api.issue.Issuable; -import org.sonar.api.issue.Issue; -import org.sonar.api.issue.internal.DefaultIssue; -import org.sonar.api.measures.*; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Resource; -import org.sonar.api.resources.Scopes; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.rule.Severity; -import org.sonar.api.rules.Rule; -import org.sonar.api.rules.RulePriority; -import org.sonar.api.test.IsRuleMeasure; - -import java.util.Calendar; -import java.util.Collections; -import java.util.Date; -import java.util.List; - -import static com.google.common.collect.Lists.newArrayList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.*; - -public class CountUnresolvedIssuesDecoratorTest { - - CountUnresolvedIssuesDecorator decorator; - TimeMachineConfiguration timeMachineConfiguration; - Issuable issuable; - DecoratorContext context; - Resource resource; - Project project; - Rule ruleA1; - Rule ruleA2; - Rule ruleB1; - Date rightNow; - Date tenDaysAgo; - Date afterTenDaysAgo; - Date fiveDaysAgo; - Date afterFiveDaysAgo; - Date sameSecond; - - @Before - public void before() { - ruleA1 = Rule.create().setRepositoryKey("ruleA1").setKey("ruleA1").setName("nameA1"); - ruleA2 = Rule.create().setRepositoryKey("ruleA2").setKey("ruleA2").setName("nameA2"); - ruleB1 = Rule.create().setRepositoryKey("ruleB1").setKey("ruleB1").setName("nameB1"); - - rightNow = new Date(); - tenDaysAgo = DateUtils.addDays(rightNow, -10); - afterTenDaysAgo = DateUtils.addDays(tenDaysAgo, 1); - fiveDaysAgo = DateUtils.addDays(rightNow, -5); - afterFiveDaysAgo = DateUtils.addDays(fiveDaysAgo, 1); - sameSecond = DateUtils.truncate(rightNow, Calendar.SECOND); - - timeMachineConfiguration = mock(TimeMachineConfiguration.class); - when(timeMachineConfiguration.periods()).thenReturn(newArrayList(new Period(1, afterFiveDaysAgo), new Period(2, afterTenDaysAgo))); - - project = mock(Project.class); - resource = mock(Resource.class); - context = mock(DecoratorContext.class); - when(context.getResource()).thenReturn(resource); - when(context.getProject()).thenReturn(project); - when(context.getMeasure(CoreMetrics.NEW_VIOLATIONS)).thenReturn(null); - - issuable = mock(Issuable.class); - ResourcePerspectives perspectives = mock(ResourcePerspectives.class); - when(perspectives.as(Issuable.class, resource)).thenReturn(issuable); - decorator = new CountUnresolvedIssuesDecorator(perspectives, timeMachineConfiguration); - } - - @Test - public void should_be_depended_upon_metric() { - assertThat(decorator.generatesIssuesMetrics()).hasSize(15); - } - - @Test - public void should_count_issues() { - when(resource.getScope()).thenReturn(Scopes.PROJECT); - when(issuable.issues()).thenReturn(createIssues()); - when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.emptyList()); - - decorator.decorate(resource, context); - - verify(context).saveMeasure(CoreMetrics.VIOLATIONS, 4.0); - } - - @Test - public void should_do_nothing_when_issuable_is_null() { - ResourcePerspectives perspectives = mock(ResourcePerspectives.class); - when(perspectives.as(Issuable.class, resource)).thenReturn(null); - CountUnresolvedIssuesDecorator decorator = new CountUnresolvedIssuesDecorator(perspectives, timeMachineConfiguration); - - decorator.decorate(resource, context); - - verifyZeroInteractions(context); - } - - /** - * See http://jira.codehaus.org/browse/SONAR-1729 - */ - @Test - public void should_not_count_issues_if_measure_already_exists() { - when(resource.getScope()).thenReturn(Scopes.PROJECT); - when(issuable.issues()).thenReturn(createIssues()); - when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.emptyList()); - when(context.getMeasure(CoreMetrics.VIOLATIONS)).thenReturn(new Measure(CoreMetrics.VIOLATIONS, 3000.0)); - when(context.getMeasure(CoreMetrics.MAJOR_VIOLATIONS)).thenReturn(new Measure(CoreMetrics.MAJOR_VIOLATIONS, 500.0)); - - decorator.decorate(resource, context); - - verify(context, never()).saveMeasure(eq(CoreMetrics.VIOLATIONS), anyDouble());// not changed - verify(context, never()).saveMeasure(eq(CoreMetrics.MAJOR_VIOLATIONS), anyDouble());// not changed - verify(context, times(1)).saveMeasure(eq(CoreMetrics.CRITICAL_VIOLATIONS), anyDouble());// did not exist - } - - @Test - public void should_save_zero_on_projects() { - when(resource.getScope()).thenReturn(Scopes.PROJECT); - when(issuable.issues()).thenReturn(Lists.newArrayList()); - when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.emptyList()); - - decorator.decorate(resource, context); - - verify(context).saveMeasure(CoreMetrics.VIOLATIONS, 0.0); - } - - @Test - public void should_save_zero_on_directories() { - when(resource.getScope()).thenReturn(Scopes.DIRECTORY); - when(issuable.issues()).thenReturn(Lists.newArrayList()); - when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.emptyList()); - - decorator.decorate(resource, context); - - verify(context).saveMeasure(CoreMetrics.VIOLATIONS, 0.0); - } - - @Test - public void should_count_issues_by_severity() { - when(resource.getScope()).thenReturn(Scopes.PROJECT); - when(issuable.issues()).thenReturn(createIssues()); - when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.emptyList()); - - decorator.decorate(resource, context); - - verify(context).saveMeasure(CoreMetrics.BLOCKER_VIOLATIONS, 0.0); - verify(context).saveMeasure(CoreMetrics.CRITICAL_VIOLATIONS, 2.0); - verify(context).saveMeasure(CoreMetrics.MAJOR_VIOLATIONS, 1.0); - verify(context).saveMeasure(CoreMetrics.MINOR_VIOLATIONS, 1.0); - verify(context).saveMeasure(CoreMetrics.INFO_VIOLATIONS, 0.0); - } - - @Test - public void should_count_issues_per_rule() { - List issues = newArrayList(); - issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name())); - issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name())); - issues.add(new DefaultIssue().setRuleKey(ruleA2.ruleKey()).setSeverity(RulePriority.MAJOR.name())); - when(issuable.issues()).thenReturn(issues); - - decorator.decorate(resource, context); - - verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.CRITICAL_VIOLATIONS, ruleA1, 2.0))); - verify(context, never()).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.MAJOR_VIOLATIONS, ruleA1, 0.0))); - verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.MAJOR_VIOLATIONS, ruleA2, 1.0))); - } - - @Test - public void same_rule_should_have_different_severities() { - List issues = newArrayList(); - issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name())); - issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name())); - issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.MINOR.name())); - when(issuable.issues()).thenReturn(issues); - - decorator.decorate(resource, context); - - verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.CRITICAL_VIOLATIONS, ruleA1, 2.0))); - verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.MINOR_VIOLATIONS, ruleA1, 1.0))); - } - - @Test - public void should_count_issues_after_date() { - List issues = createIssuesForNewMetrics(); - - assertThat(decorator.countIssuesAfterDate(null, fiveDaysAgo)).isEqualTo(0); - assertThat(decorator.countIssuesAfterDate(issues, fiveDaysAgo)).isEqualTo(1); // 1 rightNow - assertThat(decorator.countIssuesAfterDate(issues, tenDaysAgo)).isEqualTo(3); // 1 rightNow + 2 fiveDaysAgo - assertThat(decorator.countIssuesAfterDate(issues, sameSecond)).isEqualTo(0); // 0 - } - - @Test - public void should_clear_cache_after_execution() { - Issue issue1 = new DefaultIssue().setRuleKey(RuleKey.of(ruleA1.getRepositoryKey(), ruleA1.getKey())).setSeverity(RulePriority.CRITICAL.name()).setCreationDate(rightNow); - Issue issue2 = new DefaultIssue().setRuleKey(RuleKey.of(ruleA2.getRepositoryKey(), ruleA2.getKey())).setSeverity(RulePriority.CRITICAL.name()).setCreationDate(rightNow); - when(issuable.issues()).thenReturn(newArrayList(issue1)).thenReturn(newArrayList(issue2)); - - decorator.decorate(resource, context); - decorator.decorate(resource, context); - - verify(context, times(2)).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS, 1.0, 1.0))); - verify(context, never()).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS, 2.0, 2.0))); - } - - @Test - public void should_save_severity_new_issues() { - when(issuable.issues()).thenReturn(createIssuesForNewMetrics()); - - decorator.decorate(resource, context); - - // remember : period1 is 5daysAgo, period2 is 10daysAgo - verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_BLOCKER_VIOLATIONS, 0.0, 0.0))); - verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS, 1.0, 1.0))); - verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_MAJOR_VIOLATIONS, 0.0, 1.0))); - verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_MINOR_VIOLATIONS, 0.0, 1.0))); - verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_INFO_VIOLATIONS, 0.0, 0.0))); - } - - @Test - public void should_save_rule_new_issues() { - when(issuable.issues()).thenReturn(createIssuesForNewMetrics()); - - decorator.decorate(resource, context); - - // remember : period1 is 5daysAgo, period2 is 10daysAgo - verify(context).saveMeasure(argThat(new IsVariationRuleMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS, ruleA1, 1.0, 1.0))); - verify(context).saveMeasure(argThat(new IsVariationRuleMeasure(CoreMetrics.NEW_MAJOR_VIOLATIONS, ruleA2, 0.0, 1.0))); - verify(context).saveMeasure(argThat(new IsVariationRuleMeasure(CoreMetrics.NEW_MINOR_VIOLATIONS, ruleB1, 0.0, 1.0))); - } - - @Test - public void should_not_save_new_issues_if_measure_already_computed() { - when(context.getMeasure(CoreMetrics.NEW_VIOLATIONS)).thenReturn(new Measure()); - when(issuable.issues()).thenReturn(createIssuesForNewMetrics()); - - decorator.decorate(resource, context); - - verify(context, never()).saveMeasure(argThat(new IsMetricMeasure(CoreMetrics.NEW_BLOCKER_VIOLATIONS))); - verify(context, never()).saveMeasure(argThat(new IsMetricMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS))); - verify(context, never()).saveMeasure(argThat(new IsMetricMeasure(CoreMetrics.NEW_MAJOR_VIOLATIONS))); - verify(context, never()).saveMeasure(argThat(new IsMetricMeasure(CoreMetrics.NEW_MINOR_VIOLATIONS))); - verify(context, never()).saveMeasure(argThat(new IsMetricMeasure(CoreMetrics.NEW_INFO_VIOLATIONS))); - verify(context, never()).saveMeasure(argThat(new IsMetricMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS))); - } - - List createIssues() { - List issues = newArrayList(); - issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(Severity.CRITICAL).setStatus(Issue.STATUS_OPEN)); - issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(Severity.CRITICAL).setStatus(Issue.STATUS_REOPENED)); - issues.add(new DefaultIssue().setRuleKey(ruleA2.ruleKey()).setSeverity(Severity.MAJOR).setStatus(Issue.STATUS_REOPENED)); - issues.add(new DefaultIssue().setRuleKey(ruleB1.ruleKey()).setSeverity(Severity.MINOR).setStatus(Issue.STATUS_OPEN)); - return issues; - } - - List createIssuesForNewMetrics() { - List issues = newArrayList(); - issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name()).setCreationDate(rightNow).setStatus(Issue.STATUS_OPEN)); - issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name()).setCreationDate(tenDaysAgo).setStatus(Issue.STATUS_OPEN)); - issues.add(new DefaultIssue().setRuleKey(ruleA2.ruleKey()).setSeverity(RulePriority.MAJOR.name()).setCreationDate(fiveDaysAgo).setStatus(Issue.STATUS_REOPENED)); - issues.add(new DefaultIssue().setRuleKey(ruleA2.ruleKey()).setSeverity(RulePriority.MAJOR.name()).setCreationDate(tenDaysAgo).setStatus(Issue.STATUS_REOPENED)); - issues.add(new DefaultIssue().setRuleKey(ruleB1.ruleKey()).setSeverity(RulePriority.MINOR.name()).setCreationDate(fiveDaysAgo).setStatus(Issue.STATUS_OPEN)); - issues.add(new DefaultIssue().setRuleKey(ruleB1.ruleKey()).setSeverity(RulePriority.MINOR.name()).setCreationDate(tenDaysAgo).setStatus(Issue.STATUS_OPEN)); - return issues; - } - - class IsVariationRuleMeasure extends ArgumentMatcher { - Metric metric = null; - Rule rule = null; - Double var1 = null; - Double var2 = null; - - public IsVariationRuleMeasure(Metric metric, Rule rule, Double var1, Double var2) { - this.metric = metric; - this.rule = rule; - this.var1 = var1; - this.var2 = var2; - } - - public boolean matches(Object o) { - if (!(o instanceof RuleMeasure)) { - return false; - } - RuleMeasure m = (RuleMeasure) o; - return ObjectUtils.equals(metric, m.getMetric()) && - ObjectUtils.equals(rule.ruleKey(), m.ruleKey()) && - ObjectUtils.equals(var1, m.getVariation1()) && - ObjectUtils.equals(var2, m.getVariation2()); - } - } - - class IsVariationMeasure extends ArgumentMatcher { - Metric metric = null; - Double var1 = null; - Double var2 = null; - - public IsVariationMeasure(Metric metric, Double var1, Double var2) { - this.metric = metric; - this.var1 = var1; - this.var2 = var2; - } - - public boolean matches(Object o) { - if (!(o instanceof Measure)) { - return false; - } - Measure m = (Measure) o; - return ObjectUtils.equals(metric, m.getMetric()) && - ObjectUtils.equals(var1, m.getVariation1()) && - ObjectUtils.equals(var2, m.getVariation2()) && - !(m instanceof RuleMeasure); - } - } - - class IsMetricMeasure extends ArgumentMatcher { - Metric metric = null; - - public IsMetricMeasure(Metric metric) { - this.metric = metric; - } - - public boolean matches(Object o) { - if (!(o instanceof Measure)) { - return false; - } - Measure m = (Measure) o; - return ObjectUtils.equals(metric, m.getMetric()); - } - } -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/security/ApplyProjectRolesDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/security/ApplyProjectRolesDecoratorTest.java deleted file mode 100644 index dd551860aa7..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/security/ApplyProjectRolesDecoratorTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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.plugins.core.security; - -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.resources.Project; -import org.sonar.api.security.ResourcePermissions; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.*; - -public class ApplyProjectRolesDecoratorTest { - - private ResourcePermissions resourcePermissions; - private ApplyProjectRolesDecorator decorator; - - @Before - public void init() { - resourcePermissions = mock(ResourcePermissions.class); - decorator = new ApplyProjectRolesDecorator(resourcePermissions); - } - - @Test - public void alwaysExecute() { - assertThat(decorator.shouldExecuteOnProject(new Project("project"))).isTrue(); - } - - @Test - public void doNotGrantDefaultRolesWhenExistingPermissions() { - Project project = new Project("project"); - project.setId(10); - when(resourcePermissions.hasRoles(project)).thenReturn(true); - - decorator.decorate(project, null); - - verify(resourcePermissions, never()).grantDefaultRoles(project); - } - - @Test - public void doNotApplySecurityOnModules() { - Project project = new Project("project"); - Project module = new Project("module").setParent(project); - module.setId(10); - when(resourcePermissions.hasRoles(project)).thenReturn(false); - - decorator.decorate(module, null); - - verify(resourcePermissions, never()).grantDefaultRoles(module); - } - - @Test - public void grantDefaultRolesWhenNoPermissions() { - Project project = new Project("project"); - project.setId(10); - when(resourcePermissions.hasRoles(project)).thenReturn(false); - - decorator.decorate(project, null); - - verify(resourcePermissions).grantDefaultRoles(project); - } - -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/BranchCoverageDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/BranchCoverageDecoratorTest.java deleted file mode 100644 index 6c88fb9aceb..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/BranchCoverageDecoratorTest.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import org.junit.Before; -import org.junit.Test; -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.Scopes; - -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.verify; -import static org.mockito.Mockito.when; - -public class BranchCoverageDecoratorTest { - private final BranchCoverageDecorator decorator = new BranchCoverageDecorator(); - private final Project resource = mock(Project.class); - - @Before - public void setUp() { - when(resource.getScope()).thenReturn(Scopes.PROJECT); - when(resource.getQualifier()).thenReturn(Qualifiers.PROJECT); - } - - @Test - public void shouldSaveBranchCoverage() { - DecoratorContext context = mockContext(20, 15); - - decorator.decorate(resource, context); - - verify(context).saveMeasure(CoreMetrics.BRANCH_COVERAGE, 25.0); - } - - @Test - public void shouldNotSaveBranchCoverageIfMissingConditions() { - DecoratorContext context = mock(DecoratorContext.class); - - decorator.decorate(resource, context); - - verify(context, never()).saveMeasure(eq(CoreMetrics.BRANCH_COVERAGE), anyDouble()); - } - - private static DecoratorContext mockContext(int conditions, int uncoveredConditions) { - DecoratorContext context = mock(DecoratorContext.class); - when(context.getMeasure(CoreMetrics.CONDITIONS_TO_COVER)).thenReturn(new Measure(CoreMetrics.CONDITIONS_TO_COVER, (double) conditions)); - when(context.getMeasure(CoreMetrics.UNCOVERED_CONDITIONS)).thenReturn(new Measure(CoreMetrics.UNCOVERED_CONDITIONS, (double) uncoveredConditions)); - return context; - } -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/CommentDensityDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/CommentDensityDecoratorTest.java deleted file mode 100644 index eae51007721..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/CommentDensityDecoratorTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import org.junit.Test; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -import org.sonar.api.test.IsMeasure; - -import static org.mockito.Matchers.argThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class CommentDensityDecoratorTest { - - @Test - public void densityIsBalancedByNcloc() { - DecoratorContext context = mock(DecoratorContext.class); - when(context.getMeasure(CoreMetrics.NCLOC)).thenReturn(new Measure(CoreMetrics.NCLOC, 300.0)); - when(context.getMeasure(CoreMetrics.COMMENT_LINES)).thenReturn(new Measure(CoreMetrics.COMMENT_LINES, 200.0)); - CommentDensityDecorator decorator = new CommentDensityDecorator(); - decorator.decorate(null, context); - // 200 / (200 + 300) = 40% - verify(context).saveMeasure(argThat(new IsMeasure(CoreMetrics.COMMENT_LINES_DENSITY, 40.0))); - } - - @Test - public void noDensityIfUnknownComments() { - DecoratorContext context = mock(DecoratorContext.class); - when(context.getMeasure(CoreMetrics.NCLOC)).thenReturn(new Measure(CoreMetrics.NCLOC, 300.0)); - CommentDensityDecorator decorator = new CommentDensityDecorator(); - decorator.decorate(null, context); - verify(context, never()).saveMeasure(argThat(new IsMeasure(CoreMetrics.COMMENT_LINES_DENSITY))); - } - - @Test - public void noDensityIfZeroNcloc() { - DecoratorContext context = mock(DecoratorContext.class); - when(context.getMeasure(CoreMetrics.NCLOC)).thenReturn(new Measure(CoreMetrics.NCLOC, 0.0)); - when(context.getMeasure(CoreMetrics.COMMENT_LINES)).thenReturn(new Measure(CoreMetrics.COMMENT_LINES, 0.0)); - CommentDensityDecorator decorator = new CommentDensityDecorator(); - decorator.decorate(null, context); - verify(context, never()).saveMeasure(argThat(new IsMeasure(CoreMetrics.COMMENT_LINES_DENSITY))); - } - - @Test - public void zeroDensityWhenZeroComments() { - DecoratorContext context = mock(DecoratorContext.class); - when(context.getMeasure(CoreMetrics.NCLOC)).thenReturn(new Measure(CoreMetrics.NCLOC, 40.0)); - when(context.getMeasure(CoreMetrics.COMMENT_LINES)).thenReturn(new Measure(CoreMetrics.COMMENT_LINES, 0.0)); - CommentDensityDecorator decorator = new CommentDensityDecorator(); - decorator.decorate(null, context); - verify(context).saveMeasure(argThat(new IsMeasure(CoreMetrics.COMMENT_LINES_DENSITY, 0.0))); - } -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/CoverageDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/CoverageDecoratorTest.java deleted file mode 100644 index 0404cded7a1..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/CoverageDecoratorTest.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -import org.sonar.api.measures.Metric; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Scopes; - -import java.util.Collection; - -import static org.assertj.core.api.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.verify; -import static org.mockito.Mockito.when; - -public class CoverageDecoratorTest { - private CoverageDecorator decorator; - private final Project project = mock(Project.class); - - @Before - public void before() { - when(project.getScope()).thenReturn(Scopes.PROJECT); - decorator = new CoverageDecorator(); - } - - @Test - public void should_use_metrics() { - Collection metrics = decorator.usedMetrics(); - - assertThat(metrics).containsOnly(CoreMetrics.LINES_TO_COVER, CoreMetrics.UNCOVERED_LINES, CoreMetrics.NEW_LINES_TO_COVER, - CoreMetrics.NEW_UNCOVERED_LINES, CoreMetrics.CONDITIONS_TO_COVER, CoreMetrics.UNCOVERED_CONDITIONS, - CoreMetrics.NEW_CONDITIONS_TO_COVER, CoreMetrics.NEW_UNCOVERED_CONDITIONS); - } - - @Test - public void coverage() { - DecoratorContext context = mockContext(50, 40, 10, 8); - - decorator.decorate(project, context); - - // (50-40 covered lines + 10-8 covered conditions) / (50 lines + 10 conditions) - verify(context).saveMeasure(CoreMetrics.COVERAGE, 20.0); - } - - @Test - public void coverageCanBe0() { - DecoratorContext context = mockContext(50, 50, 5, 5); - - decorator.decorate(project, context); - - verify(context).saveMeasure(CoreMetrics.COVERAGE, 0.0); - } - - @Test - public void coverageCanBe100() { - DecoratorContext context = mockContext(50, 0, 5, 0); - - decorator.decorate(project, context); - - verify(context).saveMeasure(CoreMetrics.COVERAGE, 100.0); - } - - @Test - public void noCoverageIfNoElements() { - DecoratorContext context = mock(DecoratorContext.class); - - decorator.decorate(project, context); - - verify(context, never()).saveMeasure(eq(CoreMetrics.COVERAGE), anyDouble()); - } - - @Test - public void should_count_elements_for_new_code() { - Measure newLines = measureWithVariation(1, 100.0); - Measure newConditions = measureWithVariation(1, 1.0); - DecoratorContext context = mockNewContext(newLines, null, null, newConditions); - - long count = decorator.countElementsForNewCode(context, 1); - - assertThat(count).isEqualTo(101).isEqualTo(100 + 1); - } - - @Test - public void should_count_covered_elements_for_new_code() { - Measure newLines = measureWithVariation(1, 100.0); - Measure newUncoveredConditions = measureWithVariation(1, 10.0); - Measure newUncoveredLines = measureWithVariation(1, 5.0); - Measure newConditions = measureWithVariation(1, 1.0); - DecoratorContext context = mockNewContext(newLines, newUncoveredConditions, newUncoveredLines, newConditions); - - long count = decorator.countCoveredElementsForNewCode(context, 1); - - assertThat(count).isEqualTo(86).isEqualTo(100 + 1 - 10 - 5); - } - - private static DecoratorContext mockContext(int lines, int uncoveredLines, int conditions, int uncoveredConditions) { - DecoratorContext context = mock(DecoratorContext.class); - when(context.getMeasure(CoreMetrics.LINES_TO_COVER)).thenReturn(new Measure(CoreMetrics.LINES_TO_COVER, (double) lines)); - when(context.getMeasure(CoreMetrics.UNCOVERED_LINES)).thenReturn(new Measure(CoreMetrics.UNCOVERED_LINES, (double) uncoveredLines)); - when(context.getMeasure(CoreMetrics.CONDITIONS_TO_COVER)).thenReturn(new Measure(CoreMetrics.CONDITIONS_TO_COVER, (double) conditions)); - when(context.getMeasure(CoreMetrics.UNCOVERED_CONDITIONS)).thenReturn(new Measure(CoreMetrics.UNCOVERED_CONDITIONS, (double) uncoveredConditions)); - return context; - } - - private static DecoratorContext mockNewContext(Measure newLines, Measure newUncoveredConditions, Measure newUncoveredLines, Measure newConditions) { - DecoratorContext context = mock(DecoratorContext.class); - when(context.getMeasure(CoreMetrics.NEW_LINES_TO_COVER)).thenReturn(newLines); - when(context.getMeasure(CoreMetrics.NEW_UNCOVERED_LINES)).thenReturn(newUncoveredLines); - when(context.getMeasure(CoreMetrics.NEW_UNCOVERED_CONDITIONS)).thenReturn(newUncoveredConditions); - when(context.getMeasure(CoreMetrics.NEW_CONDITIONS_TO_COVER)).thenReturn(newConditions); - return context; - } - - private static Measure measureWithVariation(int period, double variation) { - Measure measure = mock(Measure.class); - when(measure.getVariation(period)).thenReturn(variation); - return measure; - } -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/DirectoriesDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/DirectoriesDecoratorTest.java deleted file mode 100644 index 01524877fb1..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/DirectoriesDecoratorTest.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import org.junit.Test; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -import org.sonar.api.resources.Directory; -import org.sonar.api.resources.File; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Resource; - -import java.util.Arrays; -import java.util.Collections; - -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.verify; -import static org.mockito.Mockito.when; - -public class DirectoriesDecoratorTest { - - @Test - public void doNotInsertZeroOnFiles() { - DirectoriesDecorator decorator = new DirectoriesDecorator(); - Resource file = File.create("foo.php"); - DecoratorContext context = mock(DecoratorContext.class); - - decorator.decorate(file, context); - - verify(context, never()).saveMeasure(eq(CoreMetrics.DIRECTORIES), anyDouble()); - } - - @Test - public void directoryCountsForOne() { - DirectoriesDecorator decorator = new DirectoriesDecorator(); - Resource directory = Directory.create("org/foo"); - DecoratorContext context = mock(DecoratorContext.class); - decorator.decorate(directory, context); - verify(context).saveMeasure(CoreMetrics.DIRECTORIES, 1.0); - } - - @Test - public void countProjectDirectories() { - DirectoriesDecorator decorator = new DirectoriesDecorator(); - Resource project = new Project("project"); - DecoratorContext context = mock(DecoratorContext.class); - - when(context.getChildrenMeasures(CoreMetrics.DIRECTORIES)).thenReturn(Arrays.asList( - new Measure(CoreMetrics.DIRECTORIES, 1.0), - new Measure(CoreMetrics.DIRECTORIES, 1.0), - new Measure(CoreMetrics.DIRECTORIES, 1.0) - )); - decorator.decorate(project, context); - verify(context).saveMeasure(CoreMetrics.DIRECTORIES, 3.0); - } - - @Test - public void noProjectValueWhenOnlyPackages() { - DirectoriesDecorator decorator = new DirectoriesDecorator(); - Resource project = new Project("project"); - DecoratorContext context = mock(DecoratorContext.class); - when(context.getChildrenMeasures(CoreMetrics.DIRECTORIES)).thenReturn(Collections.emptyList()); - when(context.getChildrenMeasures(CoreMetrics.PACKAGES)).thenReturn(Arrays.asList( - new Measure(CoreMetrics.PACKAGES, 1.0), - new Measure(CoreMetrics.PACKAGES, 1.0) - )); - decorator.decorate(project, context); - verify(context, never()).saveMeasure(eq(CoreMetrics.DIRECTORIES), anyDouble()); - } -} 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 deleted file mode 100644 index 76cb6ab8c82..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/FilesDecoratorTest.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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.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 java.util.Arrays; - -import static org.assertj.core.api.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)); - } - -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ItBranchCoverageDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ItBranchCoverageDecoratorTest.java deleted file mode 100644 index 14ba49d0432..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ItBranchCoverageDecoratorTest.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import org.junit.Before; -import org.junit.Test; -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.Scopes; - -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.verify; -import static org.mockito.Mockito.when; - -public class ItBranchCoverageDecoratorTest { - private final ItBranchCoverageDecorator decorator = new ItBranchCoverageDecorator(); - private final Project resource = mock(Project.class); - - @Before - public void setUp() { - when(resource.getScope()).thenReturn(Scopes.PROJECT); - when(resource.getQualifier()).thenReturn(Qualifiers.PROJECT); - } - - @Test - public void shouldSaveBranchCoverage() { - DecoratorContext context = mockContext(20, 15); - - decorator.decorate(resource, context); - - verify(context).saveMeasure(CoreMetrics.IT_BRANCH_COVERAGE, 25.0); - } - - @Test - public void shouldNotSaveBranchCoverageIfMissingConditions() { - DecoratorContext context = mock(DecoratorContext.class); - - decorator.decorate(resource, context); - - verify(context, never()).saveMeasure(eq(CoreMetrics.IT_BRANCH_COVERAGE), anyDouble()); - } - - private static DecoratorContext mockContext(int conditions, int uncoveredConditions) { - DecoratorContext context = mock(DecoratorContext.class); - when(context.getMeasure(CoreMetrics.IT_CONDITIONS_TO_COVER)).thenReturn(new Measure(CoreMetrics.IT_CONDITIONS_TO_COVER, (double) conditions)); - when(context.getMeasure(CoreMetrics.IT_UNCOVERED_CONDITIONS)).thenReturn(new Measure(CoreMetrics.IT_UNCOVERED_CONDITIONS, (double) uncoveredConditions)); - return context; - } -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ItCoverageDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ItCoverageDecoratorTest.java deleted file mode 100644 index 08a82034a43..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ItCoverageDecoratorTest.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -import org.sonar.api.measures.Metric; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Scopes; - -import java.util.Collection; - -import static org.assertj.core.api.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.verify; -import static org.mockito.Mockito.when; - -public class ItCoverageDecoratorTest { - private final ItCoverageDecorator decorator = new ItCoverageDecorator(); - private final Project project = mock(Project.class); - - @Before - public void before() { - when(project.getScope()).thenReturn(Scopes.PROJECT); - } - - @Test - public void should_use_metrics() { - Collection metrics = decorator.usedMetrics(); - - assertThat(metrics).containsOnly(CoreMetrics.IT_LINES_TO_COVER, CoreMetrics.IT_UNCOVERED_LINES, CoreMetrics.NEW_IT_LINES_TO_COVER, - CoreMetrics.NEW_IT_UNCOVERED_LINES, CoreMetrics.IT_CONDITIONS_TO_COVER, CoreMetrics.IT_UNCOVERED_CONDITIONS, - CoreMetrics.NEW_IT_CONDITIONS_TO_COVER, CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS); - } - - @Test - public void coverage() { - DecoratorContext context = mockContext(50, 40, 10, 8); - - decorator.decorate(project, context); - - // (50-40 covered lines + 10-8 covered conditions) / (50 lines + 10 conditions) - verify(context).saveMeasure(CoreMetrics.IT_COVERAGE, 20.0); - } - - @Test - public void coverageCanBe0() { - DecoratorContext context = mockContext(50, 50, 5, 5); - - decorator.decorate(project, context); - - verify(context).saveMeasure(CoreMetrics.IT_COVERAGE, 0.0); - } - - @Test - public void coverageCanBe100() { - DecoratorContext context = mockContext(50, 0, 5, 0); - - decorator.decorate(project, context); - - verify(context).saveMeasure(CoreMetrics.IT_COVERAGE, 100.0); - } - - @Test - public void noCoverageIfNoElements() { - DecoratorContext context = mock(DecoratorContext.class); - - decorator.decorate(project, context); - - verify(context, never()).saveMeasure(eq(CoreMetrics.IT_COVERAGE), anyDouble()); - } - - @Test - public void should_count_elements_for_new_code() { - Measure newLines = measureWithVariation(1, 100.0); - Measure newConditions = measureWithVariation(1, 1.0); - DecoratorContext context = mockNewContext(newLines, null, null, newConditions); - - long count = decorator.countElementsForNewCode(context, 1); - - assertThat(count).isEqualTo(101).isEqualTo(100 + 1); - } - - @Test - public void should_count_covered_elements_for_new_code() { - Measure newLines = measureWithVariation(1, 100.0); - Measure newUncoveredConditions = measureWithVariation(1, 10.0); - Measure newUncoveredLines = measureWithVariation(1, 5.0); - Measure newConditions = measureWithVariation(1, 1.0); - DecoratorContext context = mockNewContext(newLines, newUncoveredConditions, newUncoveredLines, newConditions); - - long count = decorator.countCoveredElementsForNewCode(context, 1); - - assertThat(count).isEqualTo(86).isEqualTo(100 + 1 - 10 - 5); - } - - private static DecoratorContext mockContext(int lines, int uncoveredLines, int conditions, int uncoveredConditions) { - DecoratorContext context = mock(DecoratorContext.class); - when(context.getMeasure(CoreMetrics.IT_LINES_TO_COVER)).thenReturn(new Measure(CoreMetrics.IT_LINES_TO_COVER, (double) lines)); - when(context.getMeasure(CoreMetrics.IT_UNCOVERED_LINES)).thenReturn(new Measure(CoreMetrics.IT_UNCOVERED_LINES, (double) uncoveredLines)); - when(context.getMeasure(CoreMetrics.IT_CONDITIONS_TO_COVER)).thenReturn(new Measure(CoreMetrics.IT_CONDITIONS_TO_COVER, (double) conditions)); - when(context.getMeasure(CoreMetrics.IT_UNCOVERED_CONDITIONS)).thenReturn(new Measure(CoreMetrics.IT_UNCOVERED_CONDITIONS, (double) uncoveredConditions)); - return context; - } - - private static DecoratorContext mockNewContext(Measure newLines, Measure newUncoveredConditions, Measure newUncoveredLines, Measure newConditions) { - DecoratorContext context = mock(DecoratorContext.class); - when(context.getMeasure(CoreMetrics.NEW_IT_LINES_TO_COVER)).thenReturn(newLines); - when(context.getMeasure(CoreMetrics.NEW_IT_UNCOVERED_LINES)).thenReturn(newUncoveredLines); - when(context.getMeasure(CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS)).thenReturn(newUncoveredConditions); - when(context.getMeasure(CoreMetrics.NEW_IT_CONDITIONS_TO_COVER)).thenReturn(newConditions); - return context; - } - - private static Measure measureWithVariation(int period, double variation) { - Measure measure = mock(Measure.class); - when(measure.getVariation(period)).thenReturn(variation); - return measure; - } -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ItLineCoverageDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ItLineCoverageDecoratorTest.java deleted file mode 100644 index 976b0442ac6..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ItLineCoverageDecoratorTest.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -import org.sonar.api.measures.Metric; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Scopes; - -import java.util.List; - -import static org.assertj.core.api.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.verify; -import static org.mockito.Mockito.when; - -public class ItLineCoverageDecoratorTest { - private final ItLineCoverageDecorator decorator = new ItLineCoverageDecorator(); - private final Project project = mock(Project.class); - - @Before - public void before() { - when(project.getScope()).thenReturn(Scopes.PROJECT); - } - - @Test - public void should_depend_on_coverage_metrics() { - List metrics = decorator.dependsUponMetrics(); - - assertThat(metrics).containsOnly(CoreMetrics.IT_UNCOVERED_LINES, CoreMetrics.IT_LINES_TO_COVER, CoreMetrics.NEW_IT_UNCOVERED_LINES, CoreMetrics.NEW_IT_LINES_TO_COVER); - } - - @Test - public void lineCoverage() { - DecoratorContext context = mockContext(50, 10); - - decorator.decorate(project, context); - - // 50-10 covered lines / 50 lines - verify(context).saveMeasure(CoreMetrics.IT_LINE_COVERAGE, 80.0); - } - - @Test - public void zeroCoveredLines() { - DecoratorContext context = mockContext(50, 50); - - decorator.decorate(project, context); - - verify(context).saveMeasure(CoreMetrics.IT_LINE_COVERAGE, 0.0); - } - - @Test - public void allCoveredLines() { - DecoratorContext context = mockContext(50, 00); - - decorator.decorate(project, context); - - verify(context).saveMeasure(CoreMetrics.IT_LINE_COVERAGE, 100.0); - } - - @Test - public void noLineCoverageIfNoLines() { - DecoratorContext context = mock(DecoratorContext.class); - - decorator.decorate(project, context); - - verify(context, never()).saveMeasure(eq(CoreMetrics.IT_LINE_COVERAGE), anyDouble()); - } - - private static DecoratorContext mockContext(int lines, int uncoveredLines) { - DecoratorContext context = mock(DecoratorContext.class); - when(context.getMeasure(CoreMetrics.IT_LINES_TO_COVER)).thenReturn(new Measure(CoreMetrics.IT_LINES_TO_COVER, (double) lines)); - when(context.getMeasure(CoreMetrics.IT_UNCOVERED_LINES)).thenReturn(new Measure(CoreMetrics.IT_UNCOVERED_LINES, (double) uncoveredLines)); - return context; - } -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/LineCoverageDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/LineCoverageDecoratorTest.java deleted file mode 100644 index 3381182889f..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/LineCoverageDecoratorTest.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import org.junit.Before; -import org.junit.Test; -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.Scopes; - -import static org.assertj.core.api.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.verify; -import static org.mockito.Mockito.when; - -public class LineCoverageDecoratorTest { - - private LineCoverageDecorator decorator; - private final Project project = mock(Project.class); - - @Before - public void before() { - when(project.getScope()).thenReturn(Scopes.PROJECT); - decorator = new LineCoverageDecorator(); - } - - @Test - public void should_depend_on_coverage_metrics() { - assertThat(decorator.dependsUponMetrics()).containsOnly(CoreMetrics.UNCOVERED_LINES, CoreMetrics.LINES_TO_COVER, CoreMetrics.NEW_UNCOVERED_LINES, - CoreMetrics.NEW_LINES_TO_COVER); - } - - @Test - public void lineCoverage() { - DecoratorContext context = mockContext(50, 10); - - decorator.decorate(project, context); - - // 50-10 covered lines / 50 lines - verify(context).saveMeasure(CoreMetrics.LINE_COVERAGE, 80.0); - } - - @Test - public void zeroCoveredLines() { - DecoratorContext context = mockContext(50, 50); - - decorator.decorate(project, context); - - verify(context).saveMeasure(CoreMetrics.LINE_COVERAGE, 0.0); - } - - @Test - public void allCoveredLines() { - DecoratorContext context = mockContext(50, 00); - - decorator.decorate(project, context); - - verify(context).saveMeasure(CoreMetrics.LINE_COVERAGE, 100.0); - } - - @Test - public void noLineCoverageIfNoLines() { - DecoratorContext context = mock(DecoratorContext.class); - - decorator.decorate(project, context); - - verify(context, never()).saveMeasure(eq(CoreMetrics.LINE_COVERAGE), anyDouble()); - } - - private static DecoratorContext mockContext(int lines, int uncoveredLines) { - DecoratorContext context = mock(DecoratorContext.class); - when(context.getMeasure(CoreMetrics.LINES_TO_COVER)).thenReturn(new Measure(CoreMetrics.LINES_TO_COVER, (double) lines)); - when(context.getMeasure(CoreMetrics.UNCOVERED_LINES)).thenReturn(new Measure(CoreMetrics.UNCOVERED_LINES, (double) uncoveredLines)); - return context; - } -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ManualMeasureDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ManualMeasureDecoratorTest.java deleted file mode 100644 index 02793e1160c..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ManualMeasureDecoratorTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import org.junit.Test; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.measures.Metric; -import org.sonar.api.resources.File; -import org.sonar.api.test.IsMeasure; -import org.sonar.core.metric.DefaultMetricFinder; -import org.sonar.jpa.test.AbstractDbUnitTestCase; - -import static org.mockito.Matchers.argThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -public class ManualMeasureDecoratorTest extends AbstractDbUnitTestCase { - - private Metric reviewNote = new Metric.Builder("review_note", "Note", Metric.ValueType.FLOAT).create().setId(2); - - @Test - public void testCopyManualMeasures() throws Exception { - setupData("testCopyManualMeasures"); - - File javaFile = File.create("Foo.java"); - javaFile.setId(40); - - ManualMeasureDecorator decorator = new ManualMeasureDecorator(getSession(), new DefaultMetricFinder(getSessionFactory())); - DecoratorContext context = mock(DecoratorContext.class); - decorator.decorate(javaFile, context); - - verify(context).saveMeasure(argThat(new IsMeasure(reviewNote, 6.0, "six"))); - } - -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/OverallBranchCoverageDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/OverallBranchCoverageDecoratorTest.java deleted file mode 100644 index 9f18f71df70..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/OverallBranchCoverageDecoratorTest.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import org.junit.Before; -import org.junit.Test; -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.Scopes; - -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.verify; -import static org.mockito.Mockito.when; - -public class OverallBranchCoverageDecoratorTest { - private final OverallBranchCoverageDecorator decorator = new OverallBranchCoverageDecorator(); - private final Project resource = mock(Project.class); - - @Before - public void setUp() { - when(resource.getScope()).thenReturn(Scopes.PROJECT); - when(resource.getQualifier()).thenReturn(Qualifiers.PROJECT); - } - - @Test - public void shouldSaveBranchCoverage() { - DecoratorContext context = mockContext(20, 15); - - decorator.decorate(resource, context); - - verify(context).saveMeasure(CoreMetrics.OVERALL_BRANCH_COVERAGE, 25.0); - } - - @Test - public void shouldNotSaveBranchCoverageIfMissingConditions() { - DecoratorContext context = mock(DecoratorContext.class); - - decorator.decorate(resource, context); - - verify(context, never()).saveMeasure(eq(CoreMetrics.OVERALL_BRANCH_COVERAGE), anyDouble()); - } - - private static DecoratorContext mockContext(int conditions, int uncoveredConditions) { - DecoratorContext context = mock(DecoratorContext.class); - when(context.getMeasure(CoreMetrics.OVERALL_CONDITIONS_TO_COVER)).thenReturn(new Measure(CoreMetrics.OVERALL_CONDITIONS_TO_COVER, (double) conditions)); - when(context.getMeasure(CoreMetrics.OVERALL_UNCOVERED_CONDITIONS)).thenReturn(new Measure(CoreMetrics.OVERALL_UNCOVERED_CONDITIONS, (double) uncoveredConditions)); - return context; - } -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/OverallCoverageDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/OverallCoverageDecoratorTest.java deleted file mode 100644 index 9aa79b1bbfb..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/OverallCoverageDecoratorTest.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -import org.sonar.api.measures.Metric; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Scopes; - -import java.util.Collection; - -import static org.assertj.core.api.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.verify; -import static org.mockito.Mockito.when; - -public class OverallCoverageDecoratorTest { - private final OverallCoverageDecorator decorator = new OverallCoverageDecorator(); - private final Project project = mock(Project.class); - - @Before - public void before() { - when(project.getScope()).thenReturn(Scopes.PROJECT); - } - - @Test - public void should_use_metrics() { - Collection metrics = decorator.usedMetrics(); - - assertThat(metrics).containsOnly(CoreMetrics.OVERALL_LINES_TO_COVER, CoreMetrics.OVERALL_UNCOVERED_LINES, CoreMetrics.NEW_OVERALL_LINES_TO_COVER, - CoreMetrics.NEW_OVERALL_UNCOVERED_LINES, CoreMetrics.OVERALL_CONDITIONS_TO_COVER, CoreMetrics.OVERALL_UNCOVERED_CONDITIONS, - CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER, CoreMetrics.NEW_OVERALL_UNCOVERED_CONDITIONS); - } - - @Test - public void coverage() { - DecoratorContext context = mockContext(50, 40, 10, 8); - - decorator.decorate(project, context); - - // (50-40 covered lines + 10-8 covered conditions) / (50 lines + 10 conditions) - verify(context).saveMeasure(CoreMetrics.OVERALL_COVERAGE, 20.0); - } - - @Test - public void coverageCanBe0() { - DecoratorContext context = mockContext(50, 50, 5, 5); - - decorator.decorate(project, context); - - verify(context).saveMeasure(CoreMetrics.OVERALL_COVERAGE, 0.0); - } - - @Test - public void coverageCanBe100() { - DecoratorContext context = mockContext(50, 0, 5, 0); - - decorator.decorate(project, context); - - verify(context).saveMeasure(CoreMetrics.OVERALL_COVERAGE, 100.0); - } - - @Test - public void noCoverageIfNoElements() { - DecoratorContext context = mock(DecoratorContext.class); - - decorator.decorate(project, context); - - verify(context, never()).saveMeasure(eq(CoreMetrics.OVERALL_COVERAGE), anyDouble()); - } - - @Test - public void should_count_elements_for_new_code() { - Measure newLines = measureWithVariation(1, 100.0); - Measure newConditions = measureWithVariation(1, 1.0); - DecoratorContext context = mockNewContext(newLines, null, null, newConditions); - - long count = decorator.countElementsForNewCode(context, 1); - - assertThat(count).isEqualTo(101).isEqualTo(100 + 1); - } - - @Test - public void should_count_covered_elements_for_new_code() { - Measure newLines = measureWithVariation(1, 100.0); - Measure newUncoveredConditions = measureWithVariation(1, 10.0); - Measure newUncoveredLines = measureWithVariation(1, 5.0); - Measure newConditions = measureWithVariation(1, 1.0); - DecoratorContext context = mockNewContext(newLines, newUncoveredConditions, newUncoveredLines, newConditions); - - long count = decorator.countCoveredElementsForNewCode(context, 1); - - assertThat(count).isEqualTo(86).isEqualTo(100 + 1 - 10 - 5); - } - - private static DecoratorContext mockContext(int lines, int uncoveredLines, int conditions, int uncoveredConditions) { - DecoratorContext context = mock(DecoratorContext.class); - when(context.getMeasure(CoreMetrics.OVERALL_LINES_TO_COVER)).thenReturn(new Measure(CoreMetrics.OVERALL_LINES_TO_COVER, (double) lines)); - when(context.getMeasure(CoreMetrics.OVERALL_UNCOVERED_LINES)).thenReturn(new Measure(CoreMetrics.OVERALL_UNCOVERED_LINES, (double) uncoveredLines)); - when(context.getMeasure(CoreMetrics.OVERALL_CONDITIONS_TO_COVER)).thenReturn(new Measure(CoreMetrics.OVERALL_CONDITIONS_TO_COVER, (double) conditions)); - when(context.getMeasure(CoreMetrics.OVERALL_UNCOVERED_CONDITIONS)).thenReturn(new Measure(CoreMetrics.OVERALL_UNCOVERED_CONDITIONS, (double) uncoveredConditions)); - return context; - } - - private static DecoratorContext mockNewContext(Measure newLines, Measure newUncoveredConditions, Measure newUncoveredLines, Measure newConditions) { - DecoratorContext context = mock(DecoratorContext.class); - when(context.getMeasure(CoreMetrics.NEW_OVERALL_LINES_TO_COVER)).thenReturn(newLines); - when(context.getMeasure(CoreMetrics.NEW_OVERALL_UNCOVERED_LINES)).thenReturn(newUncoveredLines); - when(context.getMeasure(CoreMetrics.NEW_OVERALL_UNCOVERED_CONDITIONS)).thenReturn(newUncoveredConditions); - when(context.getMeasure(CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER)).thenReturn(newConditions); - return context; - } - - private static Measure measureWithVariation(int period, double variation) { - Measure measure = mock(Measure.class); - when(measure.getVariation(period)).thenReturn(variation); - return measure; - } -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/OverallLineCoverageDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/OverallLineCoverageDecoratorTest.java deleted file mode 100644 index c19e51755dd..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/OverallLineCoverageDecoratorTest.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -import org.sonar.api.measures.Metric; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Scopes; - -import java.util.List; - -import static org.assertj.core.api.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.verify; -import static org.mockito.Mockito.when; - -public class OverallLineCoverageDecoratorTest { - private final OverallLineCoverageDecorator decorator = new OverallLineCoverageDecorator(); - private final Project project = mock(Project.class); - - @Before - public void before() { - when(project.getScope()).thenReturn(Scopes.PROJECT); - } - - @Test - public void should_depend_on_coverage_metrics() { - List metrics = decorator.dependsUponMetrics(); - - assertThat(metrics).containsOnly(CoreMetrics.OVERALL_UNCOVERED_LINES, CoreMetrics.OVERALL_LINES_TO_COVER, CoreMetrics.NEW_OVERALL_UNCOVERED_LINES, - CoreMetrics.NEW_OVERALL_LINES_TO_COVER); - } - - @Test - public void lineCoverage() { - DecoratorContext context = mockContext(50, 10); - - decorator.decorate(project, context); - - // 50-10 covered lines / 50 lines - verify(context).saveMeasure(CoreMetrics.OVERALL_LINE_COVERAGE, 80.0); - } - - @Test - public void zeroCoveredLines() { - DecoratorContext context = mockContext(50, 50); - - decorator.decorate(project, context); - - verify(context).saveMeasure(CoreMetrics.OVERALL_LINE_COVERAGE, 0.0); - } - - @Test - public void allCoveredLines() { - DecoratorContext context = mockContext(50, 00); - - decorator.decorate(project, context); - - verify(context).saveMeasure(CoreMetrics.OVERALL_LINE_COVERAGE, 100.0); - } - - @Test - public void noLineCoverageIfNoLines() { - DecoratorContext context = mock(DecoratorContext.class); - - decorator.decorate(project, context); - - verify(context, never()).saveMeasure(eq(CoreMetrics.OVERALL_LINE_COVERAGE), anyDouble()); - } - - private static DecoratorContext mockContext(int lines, int uncoveredLines) { - DecoratorContext context = mock(DecoratorContext.class); - when(context.getMeasure(CoreMetrics.OVERALL_LINES_TO_COVER)).thenReturn(new Measure(CoreMetrics.OVERALL_LINES_TO_COVER, (double) lines)); - when(context.getMeasure(CoreMetrics.OVERALL_UNCOVERED_LINES)).thenReturn(new Measure(CoreMetrics.OVERALL_UNCOVERED_LINES, (double) uncoveredLines)); - return context; - } -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/UnitTestDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/UnitTestDecoratorTest.java deleted file mode 100644 index 966b6475ca9..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/UnitTestDecoratorTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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.plugins.core.sensors; - -import org.hamcrest.Matchers; -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -import org.sonar.api.measures.Metric; -import org.sonar.api.resources.Project; - -import java.util.Arrays; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.doubleThat; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class UnitTestDecoratorTest { - - private UnitTestDecorator decorator; - private DecoratorContext context; - - @Before - public void setUp() { - decorator = new UnitTestDecorator(); - context = mock(DecoratorContext.class); - } - - @Test - public void generatesMetrics() { - assertThat(decorator.generatesMetrics()).hasSize(5); - } - - @Test - public void doNotDecorateStaticAnalysis() { - Project project = mock(Project.class); - when(project.getAnalysisType()).thenReturn(Project.AnalysisType.STATIC); - assertThat(decorator.shouldExecuteOnProject(project)).isFalse(); - - when(project.getAnalysisType()).thenReturn(Project.AnalysisType.DYNAMIC); - assertThat(decorator.shouldExecuteOnProject(project)).isTrue(); - } - - @Test - public void shouldSumChildren() { - Project project = mock(Project.class); - mockChildrenMeasures(CoreMetrics.TESTS, 3.0); - mockChildrenMeasures(CoreMetrics.TEST_ERRORS, 1.0); - mockChildrenMeasures(CoreMetrics.TEST_FAILURES, 1.0); - mockChildrenMeasures(CoreMetrics.SKIPPED_TESTS, 1.0); - mockChildrenMeasures(CoreMetrics.TEST_EXECUTION_TIME, 1.0); - - decorator.decorate(project, context); - - verify(context).saveMeasure(eq(CoreMetrics.TESTS), eq(6.0)); - verify(context).saveMeasure(eq(CoreMetrics.TEST_ERRORS), eq(2.0)); - verify(context).saveMeasure(eq(CoreMetrics.TEST_FAILURES), eq(2.0)); - verify(context).saveMeasure(eq(CoreMetrics.SKIPPED_TESTS), eq(2.0)); - verify(context).saveMeasure(eq(CoreMetrics.TEST_EXECUTION_TIME), eq(2.0)); - verify(context).saveMeasure(eq(CoreMetrics.TEST_SUCCESS_DENSITY), doubleThat(Matchers.closeTo(33.3, 0.1))); - } - - private void mockChildrenMeasures(Metric metric, double value) { - when(context.getChildrenMeasures(metric)).thenReturn(Arrays.asList(new Measure(metric, value), new Measure(metric, value))); - } -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/NewCoverageAggregatorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/NewCoverageAggregatorTest.java deleted file mode 100644 index c85e24dcc81..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/NewCoverageAggregatorTest.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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.plugins.core.timemachine; - -import org.junit.Test; -import org.mockito.ArgumentMatcher; -import org.mockito.Matchers; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; - -import java.util.Arrays; -import java.util.Collections; - -import static org.mockito.Matchers.argThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class NewCoverageAggregatorTest { - - @Test - public void shouldNotSaveDataWhenNoMeasures() { - NewCoverageAggregator aggregator = new NewCoverageAggregator(); - DecoratorContext context = mock(DecoratorContext.class); - when(context.getChildrenMeasures(CoreMetrics.NEW_LINES_TO_COVER)).thenReturn(Collections.emptyList()); - - aggregator.aggregate(context, CoreMetrics.NEW_LINES_TO_COVER, 3); - - verify(context, never()).saveMeasure(Matchers.anyObject()); - } - - @Test - public void shouldNotsetZeroWhenNoValueOnPeriod() { - NewCoverageAggregator aggregator = new NewCoverageAggregator(); - DecoratorContext context = mock(DecoratorContext.class); - when(context.getChildrenMeasures(CoreMetrics.NEW_LINES_TO_COVER)).thenReturn(Arrays.asList(newMeasure(null, 3.0, 2.0), newMeasure(null, 13.0, null))); - - aggregator.aggregate(context, CoreMetrics.NEW_LINES_TO_COVER, 3); - - verify(context).saveMeasure(argThat(new ArgumentMatcher() { - @Override - public boolean matches(Object o) { - Measure m = (Measure)o; - return m.getVariation1()==null; - } - })); - } - - @Test - public void shouldSumValues() { - NewCoverageAggregator aggregator = new NewCoverageAggregator(); - DecoratorContext context = mock(DecoratorContext.class); - when(context.getChildrenMeasures(CoreMetrics.NEW_LINES_TO_COVER)).thenReturn(Arrays.asList(newMeasure(null, 3.0, 2.0), newMeasure(null, 13.0, null))); - - aggregator.aggregate(context, CoreMetrics.NEW_LINES_TO_COVER, 3); - - verify(context).saveMeasure(argThat(new ArgumentMatcher() { - @Override - public boolean matches(Object o) { - Measure m = (Measure)o; - return m.getVariation2()==16.0 && m.getVariation3()==2.0; - } - })); - } - - private Measure newMeasure(Double variation1, Double variation2, Double variation3) { - return new Measure(CoreMetrics.NEW_LINES_TO_COVER) - .setVariation1(variation1) - .setVariation2(variation2) - .setVariation3(variation3); - } -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzerTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzerTest.java deleted file mode 100644 index adc6f087b44..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzerTest.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * 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.plugins.core.timemachine; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.ArgumentMatcher; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -import org.sonar.api.measures.Metric; -import org.sonar.api.resources.File; -import org.sonar.api.resources.Resource; -import org.sonar.api.utils.DateUtils; -import org.sonar.batch.index.BatchComponentCache; -import org.sonar.batch.protocol.output.BatchReport; -import org.sonar.batch.protocol.output.BatchReport.Changesets.Changeset; -import org.sonar.batch.protocol.output.BatchReportWriter; -import org.sonar.batch.report.ReportPublisher; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Date; -import java.util.List; - -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.argThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class NewCoverageFileAnalyzerTest { - - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - - private DecoratorContext context; - private NewCoverageFileAnalyzer decorator; - private BatchReportWriter writer; - - @Before - public void prepare() throws Exception { - context = mock(DecoratorContext.class); - Resource f = File.create("src/Foo.java").setEffectiveKey("foo:src/Foo.java"); - when(context.getResource()).thenReturn(f); - BatchComponentCache cache = new BatchComponentCache(); - cache.add(f, null); - List structs = Arrays.asList( - new AbstractNewCoverageFileAnalyzer.PeriodStruct(1, newDate("2009-12-25")), - new AbstractNewCoverageFileAnalyzer.PeriodStruct(3, newDate("2011-02-18"))); - ReportPublisher publishReportJob = mock(ReportPublisher.class); - java.io.File reportBaseDir = temp.newFolder(); - when(publishReportJob.getReportDir()).thenReturn(reportBaseDir); - writer = new BatchReportWriter(reportBaseDir); - decorator = new NewCoverageFileAnalyzer(structs, publishReportJob, cache); - - } - - @Test - public void shouldDoNothingIfNoScmData() { - when(context.getMeasure(CoreMetrics.COVERAGE_LINE_HITS_DATA)) - .thenReturn(new Measure(CoreMetrics.COVERAGE_LINE_HITS_DATA, "1=10")); - - decorator.doDecorate(context); - verify(context, never()).saveMeasure(any(Measure.class)); - } - - @Test - public void shouldDoNothingIfNoCoverageData() { - writer.writeComponentChangesets(BatchReport.Changesets.newBuilder() - .setComponentRef(1) - .addChangeset(Changeset.newBuilder() - .setDate(DateUtils.parseDateTime("2008-05-18T00:00:00+0000").getTime()) - .build()) - .addChangesetIndexByLine(0) - .build()); - - decorator.doDecorate(context); - - verify(context, never()).saveMeasure(any(Measure.class)); - } - - @Test - public void shouldGetNewLines() { - when(context.getMeasure(CoreMetrics.COVERAGE_LINE_HITS_DATA)).thenReturn( - new Measure(CoreMetrics.COVERAGE_LINE_HITS_DATA, "10=2;11=3")); - writer.writeComponentChangesets(BatchReport.Changesets.newBuilder() - .setComponentRef(1) - .addChangeset(Changeset.newBuilder() - .build()) - .addChangeset(Changeset.newBuilder() - .setDate(DateUtils.parseDateTime("2007-01-15T00:00:00+0000").getTime()) - .build()) - .addChangeset(Changeset.newBuilder() - .setDate(DateUtils.parseDateTime("2011-01-01T00:00:00+0000").getTime()) - .build()) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(1) - .addChangesetIndexByLine(2) - .build()); - - decorator.doDecorate(context); - - // line 11 has been updated after date1 (2009-12-25). This line is covered. - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_LINES_TO_COVER, 1, 1.0))); - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_LINES, 1, 0.0))); - - // no line have been updated after date3 (2011-02-18) - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_LINES_TO_COVER, 3, null))); - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_LINES, 3, null))); - - // no data on other periods - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_LINES_TO_COVER, 2, null))); - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_LINES_TO_COVER, 4, null))); - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_LINES_TO_COVER, 5, null))); - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_LINES, 2, null))); - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_LINES, 4, null))); - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_LINES, 5, null))); - } - - @Test - public void shouldGetNewConditions() { - when(context.getMeasure(CoreMetrics.COVERAGE_LINE_HITS_DATA)).thenReturn( - new Measure(CoreMetrics.COVERAGE_LINE_HITS_DATA, "10=2;11=3")); - when(context.getMeasure(CoreMetrics.CONDITIONS_BY_LINE)).thenReturn( - new Measure(CoreMetrics.CONDITIONS_BY_LINE, "11=4")); - when(context.getMeasure(CoreMetrics.COVERED_CONDITIONS_BY_LINE)).thenReturn( - new Measure(CoreMetrics.COVERED_CONDITIONS_BY_LINE, "11=1")); - writer.writeComponentChangesets(BatchReport.Changesets.newBuilder() - .setComponentRef(1) - .addChangeset(Changeset.newBuilder() - .build()) - .addChangeset(Changeset.newBuilder() - .setDate(DateUtils.parseDateTime("2007-01-15T00:00:00+0000").getTime()) - .build()) - .addChangeset(Changeset.newBuilder() - .setDate(DateUtils.parseDateTime("2011-01-01T00:00:00+0000").getTime()) - .build()) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(1) - .addChangesetIndexByLine(2) - .build()); - - decorator.doDecorate(context); - - // line 11 has been updated after date1 (2009-12-25). This line has 1 covered condition amongst 4 - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_CONDITIONS_TO_COVER, 1, 4.0))); - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_CONDITIONS, 1, 3.0))); - - // no line have been updated after date3 (2011-02-18) - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_CONDITIONS_TO_COVER, 3, null))); - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_CONDITIONS, 3, null))); - - // no data on other periods - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_CONDITIONS_TO_COVER, 2, null))); - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_CONDITIONS_TO_COVER, 4, null))); - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_CONDITIONS_TO_COVER, 5, null))); - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_CONDITIONS, 2, null))); - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_CONDITIONS, 4, null))); - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_CONDITIONS, 5, null))); - } - - @Test - public void shouldNotGetNewConditionsWhenNewLineHasNoConditions() { - when(context.getMeasure(CoreMetrics.COVERAGE_LINE_HITS_DATA)).thenReturn( - new Measure(CoreMetrics.COVERAGE_LINE_HITS_DATA, "10=2;11=3")); - when(context.getMeasure(CoreMetrics.CONDITIONS_BY_LINE)).thenReturn( - new Measure(CoreMetrics.CONDITIONS_BY_LINE, "10=1")); - when(context.getMeasure(CoreMetrics.COVERED_CONDITIONS_BY_LINE)).thenReturn( - new Measure(CoreMetrics.COVERED_CONDITIONS_BY_LINE, "10=1")); - writer.writeComponentChangesets(BatchReport.Changesets.newBuilder() - .setComponentRef(1) - .addChangeset(Changeset.newBuilder() - .build()) - .addChangeset(Changeset.newBuilder() - .setDate(DateUtils.parseDateTime("2007-01-15T00:00:00+0000").getTime()) - .build()) - .addChangeset(Changeset.newBuilder() - .setDate(DateUtils.parseDateTime("2011-01-01T00:00:00+0000").getTime()) - .build()) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(1) - .addChangesetIndexByLine(2) - .build()); - - decorator.doDecorate(context); - - // line 11 has been updated after date1 (2009-12-25) but it has no conditions - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_CONDITIONS_TO_COVER, 1, 0.0))); - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_CONDITIONS, 1, 0.0))); - } - - @Test - public void shouldLeaveNullValueWhenNothingHasChanged() { - - when(context.getMeasure(CoreMetrics.COVERAGE_LINE_HITS_DATA)).thenReturn( - new Measure(CoreMetrics.COVERAGE_LINE_HITS_DATA, "2=1;3=1")); - when(context.getMeasure(CoreMetrics.CONDITIONS_BY_LINE)).thenReturn( - new Measure(CoreMetrics.CONDITIONS_BY_LINE, "2=1")); - when(context.getMeasure(CoreMetrics.COVERED_CONDITIONS_BY_LINE)).thenReturn( - new Measure(CoreMetrics.COVERED_CONDITIONS_BY_LINE, "2=1")); - writer.writeComponentChangesets(BatchReport.Changesets.newBuilder() - .setComponentRef(1) - .addChangeset(Changeset.newBuilder() - .setDate(DateUtils.parseDateTime("2008-08-02T13:56:37+0200").getTime()) - .build()) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .addChangesetIndexByLine(0) - .build()); - - decorator.doDecorate(context); - - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_LINES_TO_COVER, 1, null))); - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_LINES, 1, null))); - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_CONDITIONS_TO_COVER, 1, null))); - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_CONDITIONS, 1, null))); - - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_LINES_TO_COVER, 3, null))); - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_LINES, 3, null))); - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_CONDITIONS_TO_COVER, 3, null))); - verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_CONDITIONS, 3, null))); - } - - static class VariationMatcher extends ArgumentMatcher { - Metric metric; - int index; - Double variation; - - VariationMatcher(Metric metric, int index, Double variation) { - this.metric = metric; - this.index = index; - this.variation = variation; - } - - @Override - public boolean matches(Object o) { - Measure m = (Measure) o; - if (m.getMetric().equals(metric)) { - if ((variation == null && m.getVariation(index) == null) || - (variation != null && variation.equals(m.getVariation(index)))) { - return true; - } - } - return false; - } - } - - private Date newDate(String s) throws ParseException { - return new SimpleDateFormat(DateUtils.DATE_FORMAT).parse(s); - } -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/TimeMachineConfigurationPersisterTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/TimeMachineConfigurationPersisterTest.java deleted file mode 100644 index ca8c36a51cd..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/TimeMachineConfigurationPersisterTest.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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.plugins.core.timemachine; - -import org.sonar.batch.components.TimeMachineConfiguration; - -import org.sonar.batch.components.PastSnapshot; -import org.junit.Test; -import org.sonar.api.database.model.Snapshot; -import org.sonar.api.resources.Project; -import org.sonar.api.utils.DateUtils; -import org.sonar.batch.index.BatchComponentCache; -import org.sonar.jpa.test.AbstractDbUnitTestCase; - -import java.util.Arrays; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class TimeMachineConfigurationPersisterTest extends AbstractDbUnitTestCase { - - @Test - public void shouldSaveConfigurationInSnapshotsTable() { - setupData("shared"); - - TimeMachineConfiguration timeMachineConfiguration = mock(TimeMachineConfiguration.class); - PastSnapshot vs1 = new PastSnapshot("days", DateUtils.parseDate("2009-01-25"), getSession().getSingleResult(Snapshot.class, "id", 100)) - .setModeParameter("30").setIndex(1); - PastSnapshot vs3 = new PastSnapshot("version", DateUtils.parseDate("2008-12-13"), getSession().getSingleResult(Snapshot.class, "id", 300)) - .setModeParameter("1.2.3").setIndex(3); - when(timeMachineConfiguration.getProjectPastSnapshots()).thenReturn(Arrays.asList(vs1, vs3)); - Snapshot projectSnapshot = getSession().getSingleResult(Snapshot.class, "id", 1000); - - BatchComponentCache resourceCache = new BatchComponentCache(); - Project project = new Project("foo"); - resourceCache.add(project, null).setSnapshot(projectSnapshot); - - TimeMachineConfigurationPersister persister = new TimeMachineConfigurationPersister(timeMachineConfiguration, resourceCache, getSession()); - - persister.persistConfiguration(project); - - checkTables("shouldSaveConfigurationInSnapshotsTable", "snapshots"); - } -} 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 deleted file mode 100644 index 223abadcbac..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/VariationDecoratorTest.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * 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.plugins.core.timemachine; - -import org.sonar.batch.components.TimeMachineConfiguration; - -import org.sonar.batch.components.PastSnapshot; -import org.sonar.batch.components.PastMeasuresLoader; -import org.junit.Test; -import org.mockito.Matchers; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.measures.Measure; -import org.sonar.api.measures.MeasuresFilter; -import org.sonar.api.measures.Metric; -import org.sonar.api.measures.MetricFinder; -import org.sonar.api.measures.RuleMeasure; -import org.sonar.api.resources.Directory; -import org.sonar.api.resources.File; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Resource; -import org.sonar.api.rules.Rule; -import org.sonar.api.rules.RuleFinder; -import org.sonar.jpa.test.AbstractDbUnitTestCase; - -import java.util.Arrays; -import java.util.Date; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class VariationDecoratorTest extends AbstractDbUnitTestCase { - - public static final int NCLOC_ID = 12; - public static final Metric NCLOC = new Metric("ncloc").setId(NCLOC_ID); - - public static final int COVERAGE_ID = 16; - public static final Metric COVERAGE = new Metric("coverage").setId(COVERAGE_ID); - - public static final int VIOLATIONS_ID = 17; - public static final Metric VIOLATIONS = new Metric("violations").setId(VIOLATIONS_ID); - - @Test - public void shouldComputeVariations() { - TimeMachineConfiguration timeMachineConfiguration = mock(TimeMachineConfiguration.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(File.create("foo/bar.c"))).isFalse(); - } - - @Test - public void shouldCompareAndSaveVariation() { - Resource dir = Directory.create("org/foo"); - - PastMeasuresLoader pastMeasuresLoader = mock(PastMeasuresLoader.class); - PastSnapshot pastSnapshot1 = new PastSnapshot("days", new Date()).setIndex(1); - PastSnapshot pastSnapshot3 = new PastSnapshot("days", new Date()).setIndex(3); - - // first past analysis - when(pastMeasuresLoader.getPastMeasures(dir, pastSnapshot1)).thenReturn(Arrays.asList( - new Object[] {NCLOC_ID, null, null, null, 180.0}, - new Object[] {COVERAGE_ID, null, null, null, 75.0})); - - // second past analysis - when(pastMeasuresLoader.getPastMeasures(dir, pastSnapshot3)).thenReturn(Arrays.asList( - new Object[] {NCLOC_ID, null, null, null, 240.0})); - - // current analysis - DecoratorContext context = mock(DecoratorContext.class); - Measure currentNcloc = newMeasure(NCLOC, 200.0); - Measure currentCoverage = newMeasure(COVERAGE, 80.0); - when(context.getMeasures(Matchers.anyObject())).thenReturn(Arrays.asList(currentNcloc, currentCoverage)); - - 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(context, times(3)).saveMeasure(Matchers.anyObject()); - - assertThat(currentNcloc.getVariation1()).isEqualTo(20.0); - assertThat(currentNcloc.getVariation2()).isNull(); - assertThat(currentNcloc.getVariation3()).isEqualTo(-40.0); - - assertThat(currentCoverage.getVariation1()).isEqualTo(5.0); - assertThat(currentCoverage.getVariation2()).isNull(); - assertThat(currentCoverage.getVariation3()).isNull(); - } - - @Test - public void shouldComputeVariationOfRuleMeasures() { - RuleFinder ruleFinder = mock(RuleFinder.class); - - Rule rule1 = Rule.create("repo", "rule1"); - rule1.setId(1); - Rule rule2 = Rule.create("repo", "rule2"); - rule2.setId(2); - - when(ruleFinder.findByKey(rule1.ruleKey())).thenReturn(rule1); - when(ruleFinder.findByKey(rule2.ruleKey())).thenReturn(rule2); - - Resource dir = Directory.create("org/foo"); - - PastMeasuresLoader pastMeasuresLoader = mock(PastMeasuresLoader.class); - PastSnapshot pastSnapshot1 = new PastSnapshot("days", new Date()).setIndex(1); - - // first past analysis - when(pastMeasuresLoader.getPastMeasures(dir, pastSnapshot1)).thenReturn(Arrays.asList( - new Object[] {VIOLATIONS_ID, null, null, null, 180.0},// total - new Object[] {VIOLATIONS_ID, null, null, rule1.getId(), 100.0},// rule 1 - new Object[] {VIOLATIONS_ID, null, null, rule2.getId(), 80.0})); // rule 2 - - // current analysis - DecoratorContext context = mock(DecoratorContext.class); - Measure violations = newMeasure(VIOLATIONS, 200.0); - Measure violationsRule1 = RuleMeasure.createForRule(VIOLATIONS, rule1, 130.0); - Measure violationsRule2 = RuleMeasure.createForRule(VIOLATIONS, rule2, 70.0); - when(context.getMeasures(Matchers.anyObject())).thenReturn(Arrays.asList(violations, violationsRule1, violationsRule2)); - - VariationDecorator decorator = new VariationDecorator(pastMeasuresLoader, mock(MetricFinder.class), Arrays.asList(pastSnapshot1), ruleFinder); - decorator.decorate(dir, context); - - // context updated for each variation - verify(context, times(3)).saveMeasure(Matchers.anyObject()); - - assertThat(violations.getVariation1()).isEqualTo(20.0); - } - - private Measure newMeasure(Metric metric, double value) { - return new Measure(metric, value); - } -} diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/sensors/ManualMeasureDecoratorTest/testCopyManualMeasures.xml b/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/sensors/ManualMeasureDecoratorTest/testCopyManualMeasures.xml deleted file mode 100644 index 0307f16e6e3..00000000000 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/sensors/ManualMeasureDecoratorTest/testCopyManualMeasures.xml +++ /dev/null @@ -1,11 +0,0 @@ - - \ No newline at end of file diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/sensors/ProjectLinksSensorTest/shouldDeleteMissingLinks.xml b/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/sensors/ProjectLinksSensorTest/shouldDeleteMissingLinks.xml deleted file mode 100644 index 836bb4630e9..00000000000 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/sensors/ProjectLinksSensorTest/shouldDeleteMissingLinks.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - 4.0.0 - org.codehaus.sonar - sonar - pom - 1.8-SNAPSHOT - - \ No newline at end of file diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/sensors/ProjectLinksSensorTest/shouldSaveLinks.xml b/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/sensors/ProjectLinksSensorTest/shouldSaveLinks.xml deleted file mode 100644 index a44ea429019..00000000000 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/sensors/ProjectLinksSensorTest/shouldSaveLinks.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - 4.0.0 - org.codehaus.sonar - sonar - pom - 1.8-SNAPSHOT - http://sonar.codehaus.org - - - SonarSource SA - http://www.sonarsource.com - - 2009 - - - jira - http://jira.codehaus.org/browse/SONAR - - - - - Sonar users mailing list - http://xircles.codehaus.org/projects/sonar/lists - http://xircles.codehaus.org/projects/sonar/lists - user@sonar.codehaus.org - http://www.nabble.com/Sonar-f30151.html - - - - - scm:svn:http://svn.codehaus.org/sonar/trunk - scm:svn:https://svn.codehaus.org/sonar/trunk - http://svn.sonar.codehaus.org - - - - bamboo - http://bamboo.ci.codehaus.org/browse/SONAR/ - - - - - GNU Lesser General Public License (LGPL), v.3 - http://www.gnu.org/licenses/lgpl.txt - repo - - - - \ No newline at end of file diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/TimeMachineConfigurationPersisterTest/shared.xml b/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/TimeMachineConfigurationPersisterTest/shared.xml deleted file mode 100644 index 70c8178d4e8..00000000000 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/TimeMachineConfigurationPersisterTest/shared.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/TimeMachineConfigurationPersisterTest/shouldSaveConfigurationInSnapshotsTable-result.xml b/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/TimeMachineConfigurationPersisterTest/shouldSaveConfigurationInSnapshotsTable-result.xml deleted file mode 100644 index 34fdf2d4d32..00000000000 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/TimeMachineConfigurationPersisterTest/shouldSaveConfigurationInSnapshotsTable-result.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/ViolationPersisterDecoratorTest/shared.xml b/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/ViolationPersisterDecoratorTest/shared.xml deleted file mode 100644 index 519ce8d5157..00000000000 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/ViolationPersisterDecoratorTest/shared.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/ViolationPersisterDecoratorTest/shouldCopyPermanentIdFromReferenceViolation-result.xml b/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/ViolationPersisterDecoratorTest/shouldCopyPermanentIdFromReferenceViolation-result.xml deleted file mode 100644 index 061041849aa..00000000000 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/ViolationPersisterDecoratorTest/shouldCopyPermanentIdFromReferenceViolation-result.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/ViolationPersisterDecoratorTest/shouldSaveViolations-result.xml b/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/ViolationPersisterDecoratorTest/shouldSaveViolations-result.xml deleted file mode 100644 index f1bbc0bda6f..00000000000 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/ViolationPersisterDecoratorTest/shouldSaveViolations-result.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/ViolationTrackingTest/example1-v1.txt b/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/ViolationTrackingTest/example1-v1.txt deleted file mode 100644 index 1920333ddb6..00000000000 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/ViolationTrackingTest/example1-v1.txt +++ /dev/null @@ -1,12 +0,0 @@ -package example1; - -public class Toto { - - public void doSomething() { - // doSomething - } - - public void doSomethingElse() { - // doSomethingElse - } -} diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/ViolationTrackingTest/example1-v2.txt b/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/ViolationTrackingTest/example1-v2.txt deleted file mode 100644 index 231532452b2..00000000000 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/ViolationTrackingTest/example1-v2.txt +++ /dev/null @@ -1,22 +0,0 @@ -package example1; - -public class Toto { - - public Toto(){} - - public void doSomethingNew() { - // doSomethingNew - } - - public void doSomethingElseNew() { - // doSomethingElseNew - } - - public void doSomething() { - // doSomething - } - - public void doSomethingElse() { - // doSomethingElse - } -} diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/ViolationTrackingTest/example2-v1.txt b/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/ViolationTrackingTest/example2-v1.txt deleted file mode 100644 index a920afe459b..00000000000 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/ViolationTrackingTest/example2-v1.txt +++ /dev/null @@ -1,7 +0,0 @@ -package example2; - -public class Toto { - void method1() { - System.out.println("toto"); - } -} diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/ViolationTrackingTest/example2-v2.txt b/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/ViolationTrackingTest/example2-v2.txt deleted file mode 100644 index c5c8250cf65..00000000000 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/timemachine/ViolationTrackingTest/example2-v2.txt +++ /dev/null @@ -1,16 +0,0 @@ -package example2; - -public class Toto { - - void method2() { - System.out.println("toto"); - } - - void method1() { - System.out.println("toto"); - } - - void method3() { - System.out.println("toto"); - } -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java index c584274eaf5..ba42319b7bd 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java @@ -23,6 +23,29 @@ import com.google.common.collect.Lists; import java.util.Collection; import java.util.List; import org.sonar.batch.components.TimeMachineConfiguration; +import org.sonar.batch.compute.ApplyProjectRolesDecorator; +import org.sonar.batch.compute.BranchCoverageDecorator; +import org.sonar.batch.compute.CommentDensityDecorator; +import org.sonar.batch.compute.CountFalsePositivesDecorator; +import org.sonar.batch.compute.CountUnresolvedIssuesDecorator; +import org.sonar.batch.compute.CoverageDecorator; +import org.sonar.batch.compute.DirectoriesDecorator; +import org.sonar.batch.compute.FilesDecorator; +import org.sonar.batch.compute.ItBranchCoverageDecorator; +import org.sonar.batch.compute.ItCoverageDecorator; +import org.sonar.batch.compute.ItLineCoverageDecorator; +import org.sonar.batch.compute.LineCoverageDecorator; +import org.sonar.batch.compute.ManualMeasureDecorator; +import org.sonar.batch.compute.NewCoverageAggregator; +import org.sonar.batch.compute.NewCoverageFileAnalyzer; +import org.sonar.batch.compute.NewItCoverageFileAnalyzer; +import org.sonar.batch.compute.NewOverallCoverageFileAnalyzer; +import org.sonar.batch.compute.OverallBranchCoverageDecorator; +import org.sonar.batch.compute.OverallCoverageDecorator; +import org.sonar.batch.compute.OverallLineCoverageDecorator; +import org.sonar.batch.compute.TimeMachineConfigurationPersister; +import org.sonar.batch.compute.UnitTestDecorator; +import org.sonar.batch.compute.VariationDecorator; import org.sonar.batch.cpd.CpdComponents; import org.sonar.batch.debt.DebtDecorator; import org.sonar.batch.debt.IssueChangelogDebtCalculator; @@ -103,8 +126,31 @@ public class BatchComponents { IssueHandlers.class, InitialOpenIssuesSensor.class, + // to be moved to compute engine QProfileEventsDecorator.class, - + CountUnresolvedIssuesDecorator.class, + CountFalsePositivesDecorator.class, + UnitTestDecorator.class, + LineCoverageDecorator.class, + CoverageDecorator.class, + BranchCoverageDecorator.class, + ItLineCoverageDecorator.class, + ItCoverageDecorator.class, + ItBranchCoverageDecorator.class, + OverallLineCoverageDecorator.class, + OverallCoverageDecorator.class, + OverallBranchCoverageDecorator.class, + ApplyProjectRolesDecorator.class, + CommentDensityDecorator.class, + DirectoriesDecorator.class, + FilesDecorator.class, + ManualMeasureDecorator.class, + VariationDecorator.class, + TimeMachineConfigurationPersister.class, + NewCoverageFileAnalyzer.class, + NewItCoverageFileAnalyzer.class, + NewOverallCoverageFileAnalyzer.class, + NewCoverageAggregator.class, TimeMachineConfiguration.class ); components.addAll(CorePropertyDefinitions.all()); diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/AbstractCoverageDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/compute/AbstractCoverageDecorator.java new file mode 100644 index 00000000000..4960f991ea2 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/AbstractCoverageDecorator.java @@ -0,0 +1,102 @@ +/* + * 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.batch.compute; + +import java.util.Arrays; +import java.util.Collection; +import org.sonar.api.batch.Decorator; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependedUpon; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.Metric; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Resource; +import org.sonar.api.resources.ResourceUtils; + +public abstract class AbstractCoverageDecorator implements Decorator { + + @Override + public boolean shouldExecuteOnProject(Project project) { + return true; + } + + @DependedUpon + public Collection generatedMetrics() { + return Arrays.asList(getGeneratedMetric(), getGeneratedMetricForNewCode()); + } + + @Override + public void decorate(final Resource resource, final DecoratorContext context) { + if (shouldDecorate(resource)) { + computeMeasure(context); + computeMeasureForNewCode(context); + } + } + + protected boolean shouldDecorate(final Resource resource) { + return !ResourceUtils.isUnitTestFile(resource); + } + + private void computeMeasure(DecoratorContext context) { + if (context.getMeasure(getGeneratedMetric()) == null) { + Long elements = countElements(context); + if (elements != null && elements > 0L) { + Long coveredElements = countCoveredElements(context); + context.saveMeasure(getGeneratedMetric(), calculateCoverage(coveredElements, elements)); + } + } + } + + private void computeMeasureForNewCode(DecoratorContext context) { + if (context.getMeasure(getGeneratedMetricForNewCode()) == null) { + Measure measure = new Measure(getGeneratedMetricForNewCode()); + boolean hasValue = false; + /* TODO remove this magic number */ + for (int periodIndex = 1; periodIndex <= 5; periodIndex++) { + Long elements = countElementsForNewCode(context, periodIndex); + + if (elements != null && elements > 0L) { + long coveredElements = countCoveredElementsForNewCode(context, periodIndex); + measure.setVariation(periodIndex, calculateCoverage(coveredElements, elements)); + hasValue = true; + } + } + if (hasValue) { + context.saveMeasure(measure); + } + } + } + + private double calculateCoverage(final long coveredLines, final long lines) { + return (100.0 * coveredLines) / lines; + } + + protected abstract Metric getGeneratedMetric(); + + protected abstract Long countElements(DecoratorContext context); + + protected abstract long countCoveredElements(DecoratorContext context); + + protected abstract Metric getGeneratedMetricForNewCode(); + + protected abstract Long countElementsForNewCode(DecoratorContext context, int periodIndex); + + protected abstract long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex); +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/AbstractNewCoverageFileAnalyzer.java b/sonar-batch/src/main/java/org/sonar/batch/compute/AbstractNewCoverageFileAnalyzer.java new file mode 100644 index 00000000000..446c0820244 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/AbstractNewCoverageFileAnalyzer.java @@ -0,0 +1,262 @@ +/* + * 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.batch.compute; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; +import org.apache.commons.lang.ObjectUtils; +import org.sonar.api.batch.Decorator; +import org.sonar.api.batch.DecoratorBarriers; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependedUpon; +import org.sonar.api.batch.DependsUpon; +import org.sonar.api.batch.RequiresDB; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.Metric; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Qualifiers; +import org.sonar.api.resources.Resource; +import org.sonar.api.resources.Scopes; +import org.sonar.api.utils.KeyValueFormat; +import org.sonar.batch.components.Period; +import org.sonar.batch.components.TimeMachineConfiguration; +import org.sonar.batch.index.BatchComponentCache; +import org.sonar.batch.protocol.output.BatchReport; +import org.sonar.batch.protocol.output.BatchReport.Changesets.Changeset; +import org.sonar.batch.protocol.output.BatchReportReader; +import org.sonar.batch.report.ReportPublisher; + +/** + * @since 2.7 + */ +@RequiresDB +@DependedUpon(DecoratorBarriers.END_OF_TIME_MACHINE) +public abstract class AbstractNewCoverageFileAnalyzer implements Decorator { + + private final List structs; + private final ReportPublisher publishReportJob; + private final BatchComponentCache resourceCache; + + public AbstractNewCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration, ReportPublisher publishReportJob, BatchComponentCache resourceCache) { + this(new ArrayList(), publishReportJob, resourceCache); + for (Period period : timeMachineConfiguration.periods()) { + structs.add(new PeriodStruct(period.getIndex(), period.getDate())); + } + } + + AbstractNewCoverageFileAnalyzer(List structs, ReportPublisher publishReportJob, BatchComponentCache resourceCache) { + this.resourceCache = resourceCache; + this.publishReportJob = publishReportJob; + this.structs = structs; + } + + public abstract Metric getCoverageLineHitsDataMetric(); + + public abstract Metric getConditionsByLineMetric(); + + public abstract Metric getCoveredConditionsByLineMetric(); + + public abstract Metric getNewLinesToCoverMetric(); + + public abstract Metric getNewUncoveredLinesMetric(); + + public abstract Metric getNewConditionsToCoverMetric(); + + public abstract Metric getNewUncoveredConditionsMetric(); + + @Override + public boolean shouldExecuteOnProject(Project project) { + return !structs.isEmpty(); + } + + private boolean shouldDecorate(Resource resource) { + return Scopes.isFile(resource) && !Qualifiers.UNIT_TEST_FILE.equals(resource.getQualifier()); + } + + @DependsUpon + public List dependsOnMetrics() { + + return Arrays.asList(getCoverageLineHitsDataMetric(), getConditionsByLineMetric(), getCoveredConditionsByLineMetric()); + } + + @DependedUpon + public List generatesNewCoverageMetrics() { + return Arrays.asList(getNewLinesToCoverMetric(), getNewUncoveredLinesMetric(), getNewConditionsToCoverMetric(), getNewUncoveredConditionsMetric()); + } + + @Override + public void decorate(Resource resource, DecoratorContext context) { + if (shouldDecorate(resource)) { + doDecorate(context); + } + } + + void doDecorate(DecoratorContext context) { + if (parse(context)) { + compute(context); + } + } + + private boolean parse(DecoratorContext context) { + BatchReportReader reader = new BatchReportReader(publishReportJob.getReportDir()); + BatchReport.Changesets componentScm = reader.readChangesets(resourceCache.get(context.getResource()).batchId()); + Measure hitsByLineMeasure = context.getMeasure(getCoverageLineHitsDataMetric()); + + if (componentScm != null && hitsByLineMeasure != null && hitsByLineMeasure.hasData()) { + Map hitsByLine = parseCountByLine(hitsByLineMeasure); + Map conditionsByLine = parseCountByLine(context.getMeasure(getConditionsByLineMetric())); + Map coveredConditionsByLine = parseCountByLine(context.getMeasure(getCoveredConditionsByLineMetric())); + + reset(); + + for (Map.Entry entry : hitsByLine.entrySet()) { + int lineId = entry.getKey(); + int hits = entry.getValue(); + int conditions = (Integer) ObjectUtils.defaultIfNull(conditionsByLine.get(lineId), 0); + int coveredConditions = (Integer) ObjectUtils.defaultIfNull(coveredConditionsByLine.get(lineId), 0); + Changeset changeset = componentScm.getChangeset(componentScm.getChangesetIndexByLine(lineId - 1)); + Date date = changeset.hasDate() ? new Date(changeset.getDate()) : null; + for (PeriodStruct struct : structs) { + struct.analyze(date, hits, conditions, coveredConditions); + } + } + + return true; + } + return false; + } + + private void reset() { + for (PeriodStruct struct : structs) { + struct.reset(); + } + } + + private void compute(DecoratorContext context) { + Measure newLines = new Measure(getNewLinesToCoverMetric()); + Measure newUncoveredLines = new Measure(getNewUncoveredLinesMetric()); + Measure newConditions = new Measure(getNewConditionsToCoverMetric()); + Measure newUncoveredConditions = new Measure(getNewUncoveredConditionsMetric()); + + for (PeriodStruct struct : structs) { + if (struct.hasNewCode()) { + newLines.setVariation(struct.index, (double) struct.getNewLines()); + newUncoveredLines.setVariation(struct.index, (double) (struct.getNewLines() - struct.getNewCoveredLines())); + newConditions.setVariation(struct.index, (double) struct.getNewConditions()); + newUncoveredConditions.setVariation(struct.index, (double) struct.getNewConditions() - struct.getNewCoveredConditions()); + } + } + + context.saveMeasure(newLines); + context.saveMeasure(newUncoveredLines); + context.saveMeasure(newConditions); + context.saveMeasure(newUncoveredConditions); + } + + private Map parseCountByLine(@Nullable Measure measure) { + if (measure != null && measure.hasData()) { + return KeyValueFormat.parseIntInt(measure.getData()); + } + return new HashMap<>(); + } + + public static final class PeriodStruct { + int index; + Date date; + Integer newLines; + Integer newCoveredLines; + Integer newConditions; + Integer newCoveredConditions; + + PeriodStruct(int index, @Nullable Date date) { + this.index = index; + this.date = date; + } + + void reset() { + newLines = null; + newCoveredLines = null; + newConditions = null; + newCoveredConditions = null; + } + + void analyze(@Nullable Date lineDate, int hits, int conditions, int coveredConditions) { + if (lineDate == null) { + // TODO warning + + } else if (date == null || lineDate.after(date)) { + // TODO test if string comparison is faster or not + addLine(hits > 0); + addConditions(conditions, coveredConditions); + } + } + + void addLine(boolean covered) { + if (newLines == null) { + newLines = 0; + } + newLines += 1; + if (covered) { + if (newCoveredLines == null) { + newCoveredLines = 0; + } + newCoveredLines += 1; + } + } + + void addConditions(int count, int countCovered) { + if (newConditions == null) { + newConditions = 0; + } + newConditions += count; + if (count > 0) { + if (newCoveredConditions == null) { + newCoveredConditions = 0; + } + newCoveredConditions += countCovered; + } + } + + boolean hasNewCode() { + return newLines != null; + } + + public int getNewLines() { + return newLines != null ? newLines : 0; + } + + public int getNewCoveredLines() { + return newCoveredLines != null ? newCoveredLines : 0; + } + + public int getNewConditions() { + return newConditions != null ? newConditions : 0; + } + + public int getNewCoveredConditions() { + return newCoveredConditions != null ? newCoveredConditions : 0; + } + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/ApplyProjectRolesDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/compute/ApplyProjectRolesDecorator.java new file mode 100644 index 00000000000..8861e1312f8 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/ApplyProjectRolesDecorator.java @@ -0,0 +1,60 @@ +/* + * 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.batch.compute; + +import com.google.common.collect.ImmutableSet; +import java.util.Set; +import org.slf4j.LoggerFactory; +import org.sonar.api.batch.Decorator; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.RequiresDB; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Qualifiers; +import org.sonar.api.resources.Resource; +import org.sonar.api.security.ResourcePermissions; + +@RequiresDB +public class ApplyProjectRolesDecorator implements Decorator { + + private static final Set QUALIFIERS = ImmutableSet.of(Qualifiers.PROJECT, Qualifiers.VIEW, Qualifiers.SUBVIEW); + private final ResourcePermissions resourcePermissions; + + public ApplyProjectRolesDecorator(ResourcePermissions resourcePermissions) { + this.resourcePermissions = resourcePermissions; + } + + @Override + public boolean shouldExecuteOnProject(Project project) { + return true; + } + + @Override + public void decorate(Resource resource, DecoratorContext context) { + if (shouldDecorateResource(resource)) { + LoggerFactory.getLogger(ApplyProjectRolesDecorator.class).info("Grant default permissions to {}", resource.getKey()); + resourcePermissions.grantDefaultRoles(resource); + } + } + + private boolean shouldDecorateResource(Resource resource) { + return resource.getId() != null && QUALIFIERS.contains(resource.getQualifier()) && !resourcePermissions.hasRoles(resource); + } + +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/BranchCoverageDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/compute/BranchCoverageDecorator.java new file mode 100644 index 00000000000..637ea6eea44 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/BranchCoverageDecorator.java @@ -0,0 +1,72 @@ +/* + * 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.batch.compute; + +import java.util.Collection; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependsUpon; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.MeasureUtils; +import org.sonar.api.measures.Metric; +import org.sonar.batch.sensor.coverage.CoverageConstants; + +public final class BranchCoverageDecorator extends AbstractCoverageDecorator { + + @DependsUpon + public Collection dependsUponMetrics() { + return CoverageConstants.BRANCH_COVERAGE_METRICS; + } + + @Override + protected Metric getGeneratedMetric() { + return CoreMetrics.BRANCH_COVERAGE; + } + + @Override + protected Long countElements(DecoratorContext context) { + return MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.CONDITIONS_TO_COVER), 0L); + } + + @Override + protected long countCoveredElements(DecoratorContext context) { + long uncoveredConditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.UNCOVERED_CONDITIONS), 0L); + long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.CONDITIONS_TO_COVER), 0L); + + return conditions - uncoveredConditions; + } + + @Override + protected Metric getGeneratedMetricForNewCode() { + return CoreMetrics.NEW_BRANCH_COVERAGE; + } + + @Override + protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) { + return MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_CONDITIONS_TO_COVER), periodIndex); + } + + @Override + protected long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex) { + long uncoveredConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_UNCOVERED_CONDITIONS), periodIndex, 0L); + long conditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_CONDITIONS_TO_COVER), periodIndex, 0L); + + return conditions - uncoveredConditions; + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/CommentDensityDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/compute/CommentDensityDecorator.java new file mode 100644 index 00000000000..0379552ffad --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/CommentDensityDecorator.java @@ -0,0 +1,90 @@ +/* + * 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.batch.compute; + +import java.util.Arrays; +import java.util.List; +import org.sonar.api.batch.Decorator; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependedUpon; +import org.sonar.api.batch.DependsUpon; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.MeasureUtils; +import org.sonar.api.measures.Metric; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Resource; + +public class CommentDensityDecorator implements Decorator { + + @DependsUpon + public List dependsUponMetrics() { + return Arrays.asList(CoreMetrics.NCLOC, CoreMetrics.COMMENT_LINES, CoreMetrics.PUBLIC_API, CoreMetrics.PUBLIC_UNDOCUMENTED_API); + } + + @DependedUpon + public List generatesMetrics() { + return Arrays.asList(CoreMetrics.COMMENT_LINES_DENSITY, CoreMetrics.PUBLIC_DOCUMENTED_API_DENSITY); + } + + @Override + public boolean shouldExecuteOnProject(Project project) { + return true; + } + + @Override + public void decorate(Resource resource, DecoratorContext context) { + saveCommentsDensity(context); + savePublicApiDensity(context); + } + + private void saveCommentsDensity(DecoratorContext context) { + if (context.getMeasure(CoreMetrics.COMMENT_LINES_DENSITY) != null) { + return; + } + + Measure ncloc = context.getMeasure(CoreMetrics.NCLOC); + Measure comments = context.getMeasure(CoreMetrics.COMMENT_LINES); + if (MeasureUtils.hasValue(ncloc) && MeasureUtils.hasValue(comments) && (comments.getValue() + ncloc.getValue()) > 0) { + double val = 100.0 * (comments.getValue() / (comments.getValue() + ncloc.getValue())); + context.saveMeasure(new Measure(CoreMetrics.COMMENT_LINES_DENSITY, val)); + } + } + + private void savePublicApiDensity(DecoratorContext context) { + if (context.getMeasure(CoreMetrics.PUBLIC_DOCUMENTED_API_DENSITY) != null) { + return; + } + + Measure publicApi = context.getMeasure(CoreMetrics.PUBLIC_API); + Measure publicUndocApi = context.getMeasure(CoreMetrics.PUBLIC_UNDOCUMENTED_API); + + if (MeasureUtils.hasValue(publicApi) && MeasureUtils.hasValue(publicUndocApi) && publicApi.getValue() > 0) { + double documentedAPI = publicApi.getValue() - publicUndocApi.getValue(); + Double value = 100.0 * (documentedAPI / publicApi.getValue()); + context.saveMeasure(new Measure(CoreMetrics.PUBLIC_DOCUMENTED_API_DENSITY, value)); + } + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/CountFalsePositivesDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/compute/CountFalsePositivesDecorator.java new file mode 100644 index 00000000000..1eb5456457d --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/CountFalsePositivesDecorator.java @@ -0,0 +1,86 @@ +/* + * 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.batch.compute; + +import org.sonar.api.batch.Decorator; +import org.sonar.api.batch.DecoratorBarriers; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependedUpon; +import org.sonar.api.batch.DependsUpon; +import org.sonar.api.component.ResourcePerspectives; +import org.sonar.api.issue.Issuable; +import org.sonar.api.issue.Issue; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.MeasureUtils; +import org.sonar.api.measures.Metric; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Resource; + +/** + * Computes the number of false-positives + * + * @since 3.6 + */ +@DependsUpon(DecoratorBarriers.END_OF_VIOLATION_TRACKING) +public class CountFalsePositivesDecorator implements Decorator { + + private final ResourcePerspectives perspectives; + + public CountFalsePositivesDecorator(ResourcePerspectives perspectives) { + this.perspectives = perspectives; + } + + @Override + public boolean shouldExecuteOnProject(Project project) { + return true; + } + + @DependedUpon + public Metric generatesFalsePositiveMeasure() { + return CoreMetrics.FALSE_POSITIVE_ISSUES; + } + + @Override + public void decorate(Resource resource, DecoratorContext context) { + Issuable issuable = perspectives.as(Issuable.class, resource); + if (issuable != null) { + int falsePositives = 0; + for (Issue issue : issuable.resolvedIssues()) { + if (Issue.RESOLUTION_FALSE_POSITIVE.equals(issue.resolution())) { + falsePositives++; + } + } + saveMeasure(context, CoreMetrics.FALSE_POSITIVE_ISSUES, falsePositives); + } + } + + private void saveMeasure(DecoratorContext context, Metric metric, int value) { + context.saveMeasure(metric, (double) (value + sumChildren(context, metric))); + } + + private int sumChildren(DecoratorContext context, Metric metric) { + return MeasureUtils.sum(true, context.getChildrenMeasures(metric)).intValue(); + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/CountUnresolvedIssuesDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/compute/CountUnresolvedIssuesDecorator.java new file mode 100644 index 00000000000..cd57819911a --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/CountUnresolvedIssuesDecorator.java @@ -0,0 +1,304 @@ +/* + * 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.batch.compute; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.HashMultiset; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ListMultimap; +import com.google.common.collect.Maps; +import com.google.common.collect.Multiset; +import com.google.common.collect.Sets; +import java.util.Calendar; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; +import org.apache.commons.lang.time.DateUtils; +import org.sonar.api.batch.Decorator; +import org.sonar.api.batch.DecoratorBarriers; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependedUpon; +import org.sonar.api.batch.DependsUpon; +import org.sonar.api.batch.RequiresDB; +import org.sonar.api.component.ResourcePerspectives; +import org.sonar.api.issue.Issuable; +import org.sonar.api.issue.Issue; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.MeasureUtils; +import org.sonar.api.measures.MeasuresFilters; +import org.sonar.api.measures.Metric; +import org.sonar.api.measures.RuleMeasure; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Resource; +import org.sonar.api.resources.ResourceUtils; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rules.RulePriority; +import org.sonar.batch.components.Period; +import org.sonar.batch.components.TimeMachineConfiguration; + +/** + * Computes metrics related to number of issues. + * + * @since 3.6 + */ +@DependsUpon(DecoratorBarriers.ISSUES_TRACKED) +@RequiresDB +public class CountUnresolvedIssuesDecorator implements Decorator { + + private final ResourcePerspectives perspectives; + private final TimeMachineConfiguration timeMachineConfiguration; + + public CountUnresolvedIssuesDecorator(ResourcePerspectives perspectives, TimeMachineConfiguration timeMachineConfiguration) { + this.perspectives = perspectives; + this.timeMachineConfiguration = timeMachineConfiguration; + } + + @Override + public boolean shouldExecuteOnProject(Project project) { + return true; + } + + @DependedUpon + public List generatesIssuesMetrics() { + return ImmutableList.of( + CoreMetrics.VIOLATIONS, + CoreMetrics.BLOCKER_VIOLATIONS, + CoreMetrics.CRITICAL_VIOLATIONS, + CoreMetrics.MAJOR_VIOLATIONS, + CoreMetrics.MINOR_VIOLATIONS, + CoreMetrics.INFO_VIOLATIONS, + CoreMetrics.NEW_VIOLATIONS, + CoreMetrics.NEW_BLOCKER_VIOLATIONS, + CoreMetrics.NEW_CRITICAL_VIOLATIONS, + CoreMetrics.NEW_MAJOR_VIOLATIONS, + CoreMetrics.NEW_MINOR_VIOLATIONS, + CoreMetrics.NEW_INFO_VIOLATIONS, + CoreMetrics.OPEN_ISSUES, + CoreMetrics.REOPENED_ISSUES, + CoreMetrics.CONFIRMED_ISSUES + ); + } + + @Override + public void decorate(Resource resource, DecoratorContext context) { + Issuable issuable = perspectives.as(Issuable.class, resource); + if (issuable != null) { + Collection issues = issuable.issues(); + boolean shouldSaveNewMetrics = shouldSaveNewMetrics(context); + + Multiset severityBag = HashMultiset.create(); + Map> rulesPerSeverity = Maps.newHashMap(); + ListMultimap issuesPerSeverity = ArrayListMultimap.create(); + int countOpen = 0; + int countReopened = 0; + int countConfirmed = 0; + + for (Issue issue : issues) { + severityBag.add(RulePriority.valueOf(issue.severity())); + Multiset rulesBag = initRules(rulesPerSeverity, RulePriority.valueOf(issue.severity())); + rulesBag.add(issue.ruleKey()); + issuesPerSeverity.put(RulePriority.valueOf(issue.severity()), issue); + + if (Issue.STATUS_OPEN.equals(issue.status())) { + countOpen++; + } else if (Issue.STATUS_REOPENED.equals(issue.status())) { + countReopened++; + } else if (Issue.STATUS_CONFIRMED.equals(issue.status())) { + countConfirmed++; + } + } + + for (RulePriority ruleSeverity : RulePriority.values()) { + saveIssuesForSeverity(context, ruleSeverity, severityBag); + saveIssuesPerRules(context, ruleSeverity, rulesPerSeverity); + saveNewIssuesForSeverity(context, ruleSeverity, issuesPerSeverity, shouldSaveNewMetrics); + saveNewIssuesPerRule(context, ruleSeverity, issues, shouldSaveNewMetrics); + } + + saveTotalIssues(context, issues); + saveNewIssues(context, issues, shouldSaveNewMetrics); + + saveMeasure(context, CoreMetrics.OPEN_ISSUES, countOpen); + saveMeasure(context, CoreMetrics.REOPENED_ISSUES, countReopened); + saveMeasure(context, CoreMetrics.CONFIRMED_ISSUES, countConfirmed); + } + } + + private void saveTotalIssues(DecoratorContext context, Collection issues) { + if (context.getMeasure(CoreMetrics.VIOLATIONS) == null) { + Collection childrenIssues = context.getChildrenMeasures(CoreMetrics.VIOLATIONS); + Double sum = MeasureUtils.sum(true, childrenIssues); + context.saveMeasure(CoreMetrics.VIOLATIONS, sum + issues.size()); + } + } + + private void saveNewIssues(DecoratorContext context, Collection issues, boolean shouldSaveNewMetrics) { + if (shouldSaveNewMetrics) { + Measure measure = new Measure(CoreMetrics.NEW_VIOLATIONS); + saveNewIssues(context, measure, issues); + } + } + + private void saveIssuesForSeverity(DecoratorContext context, RulePriority ruleSeverity, Multiset severitiesBag) { + Metric metric = SeverityUtils.severityToIssueMetric(ruleSeverity); + if (context.getMeasure(metric) == null) { + Collection children = context.getChildrenMeasures(MeasuresFilters.metric(metric)); + int sum = MeasureUtils.sum(true, children).intValue() + severitiesBag.count(ruleSeverity); + context.saveMeasure(metric, (double) sum); + } + } + + private void saveNewIssuesForSeverity(DecoratorContext context, RulePriority severity, ListMultimap issuesPerSeverities, boolean shouldSaveNewMetrics) { + if (shouldSaveNewMetrics) { + Metric metric = SeverityUtils.severityToNewMetricIssue(severity); + Measure measure = new Measure(metric); + saveNewIssues(context, measure, issuesPerSeverities.get(severity)); + } + } + + private void saveIssuesPerRules(DecoratorContext context, RulePriority severity, Map> rulesPerSeverity) { + Metric metric = SeverityUtils.severityToIssueMetric(severity); + + Collection children = context.getChildrenMeasures(MeasuresFilters.rules(metric)); + for (Measure child : children) { + RuleMeasure childRuleMeasure = (RuleMeasure) child; + RuleKey ruleKey = childRuleMeasure.ruleKey(); + if (ruleKey != null && MeasureUtils.hasValue(childRuleMeasure)) { + Multiset rulesBag = initRules(rulesPerSeverity, severity); + rulesBag.add(ruleKey, childRuleMeasure.getIntValue()); + } + } + + Multiset rulesBag = rulesPerSeverity.get(severity); + if (rulesBag != null) { + for (Multiset.Entry entry : rulesBag.entrySet()) { + RuleMeasure measure = RuleMeasure.createForRule(metric, entry.getElement(), (double) entry.getCount()); + measure.setSeverity(severity); + context.saveMeasure(measure); + } + } + } + + private void saveNewIssuesPerRule(DecoratorContext context, RulePriority severity, Collection issues, boolean shouldSaveNewMetrics) { + if (shouldSaveNewMetrics) { + Metric metric = SeverityUtils.severityToNewMetricIssue(severity); + ListMultimap childMeasuresPerRuleKeys = ArrayListMultimap.create(); + ListMultimap issuesPerRuleKeys = ArrayListMultimap.create(); + Set ruleKeys = Sets.newHashSet(); + + Collection children = context.getChildrenMeasures(MeasuresFilters.rules(metric)); + for (Measure child : children) { + RuleMeasure childRuleMeasure = (RuleMeasure) child; + RuleKey ruleKey = childRuleMeasure.ruleKey(); + if (ruleKey != null) { + childMeasuresPerRuleKeys.put(ruleKey, childRuleMeasure); + ruleKeys.add(ruleKey); + } + } + + for (Issue issue : issues) { + if (RulePriority.valueOf(issue.severity()).equals(severity)) { + ruleKeys.add(issue.ruleKey()); + issuesPerRuleKeys.put(issue.ruleKey(), issue); + } + } + + for (RuleKey ruleKey : ruleKeys) { + RuleMeasure measure = RuleMeasure.createForRule(metric, ruleKey, null); + measure.setSeverity(severity); + for (Period period : timeMachineConfiguration.periods()) { + int variationIndex = period.getIndex(); + double sum = MeasureUtils.sumOnVariation(true, variationIndex, childMeasuresPerRuleKeys.get(ruleKey)) + countIssues(issuesPerRuleKeys.get(ruleKey), period); + measure.setVariation(variationIndex, sum); + } + context.saveMeasure(measure); + } + } + } + + private void saveNewIssues(DecoratorContext context, Measure measure, Collection issues) { + for (Period period : timeMachineConfiguration.periods()) { + int variationIndex = period.getIndex(); + Collection children = context.getChildrenMeasures(measure.getMetric()); + double sum = MeasureUtils.sumOnVariation(true, variationIndex, children) + countIssues(issues, period); + measure.setVariation(variationIndex, sum); + } + context.saveMeasure(measure); + } + + private void saveMeasure(DecoratorContext context, Metric metric, int value) { + context.saveMeasure(metric, (double) (value + sumChildren(context, metric))); + } + + private int sumChildren(DecoratorContext context, Metric metric) { + int sum = 0; + if (!ResourceUtils.isFile(context.getResource())) { + sum = MeasureUtils.sum(true, context.getChildrenMeasures(metric)).intValue(); + } + return sum; + } + + private Multiset initRules(Map> rulesPerSeverity, RulePriority severity) { + Multiset rulesBag = rulesPerSeverity.get(severity); + if (rulesBag == null) { + rulesBag = HashMultiset.create(); + rulesPerSeverity.put(severity, rulesBag); + } + return rulesBag; + } + + private int countIssues(Collection issues, Period period) { + // SONAR-3647 Use real snapshot date and not target date in order to stay consistent with other measure variations + Date datePlusOneSecond = period.getDate() != null ? DateUtils.addSeconds(period.getDate(), 1) : null; + return countIssuesAfterDate(issues, datePlusOneSecond); + } + + @VisibleForTesting + int countIssuesAfterDate(Collection issues, @Nullable Date date) { + if (issues == null) { + return 0; + } + int count = 0; + for (Issue issue : issues) { + if (isAfter(issue, date)) { + count++; + } + } + return count; + } + + private boolean isAfter(Issue issue, @Nullable Date date) { + return date == null || (issue.creationDate() != null && DateUtils.truncatedCompareTo(issue.creationDate(), date, Calendar.SECOND) > 0); + } + + private boolean shouldSaveNewMetrics(DecoratorContext context) { + return context.getMeasure(CoreMetrics.NEW_VIOLATIONS) == null; + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/CoverageDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/compute/CoverageDecorator.java new file mode 100644 index 00000000000..7d8bed2ab61 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/CoverageDecorator.java @@ -0,0 +1,86 @@ +/* + * 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.batch.compute; + +import java.util.Collection; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependsUpon; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.MeasureUtils; +import org.sonar.api.measures.Metric; +import org.sonar.batch.sensor.coverage.CoverageConstants; + +public final class CoverageDecorator extends AbstractCoverageDecorator { + + @DependsUpon + public Collection usedMetrics() { + return CoverageConstants.COVERAGE_METRICS; + } + + @Override + protected Metric getGeneratedMetric() { + return CoreMetrics.COVERAGE; + } + + @Override + protected Long countElements(DecoratorContext context) { + long linesToCover = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.LINES_TO_COVER), 0L); + long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.CONDITIONS_TO_COVER), 0L); + + return linesToCover + conditions; + } + + @Override + protected long countCoveredElements(DecoratorContext context) { + long uncoveredLines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.UNCOVERED_LINES), 0L); + long lines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.LINES_TO_COVER), 0L); + long uncoveredConditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.UNCOVERED_CONDITIONS), 0L); + long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.CONDITIONS_TO_COVER), 0L); + + return lines + conditions - uncoveredConditions - uncoveredLines; + } + + @Override + protected Metric getGeneratedMetricForNewCode() { + return CoreMetrics.NEW_COVERAGE; + } + + @Override + protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) { + Long newLinesToCover = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_LINES_TO_COVER), periodIndex); + if (newLinesToCover == null) { + return null; + } + + long newConditionsToCover = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_CONDITIONS_TO_COVER), periodIndex, 0L); + + return newLinesToCover + newConditionsToCover; + } + + @Override + protected long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex) { + long newLines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_LINES_TO_COVER), periodIndex, 0L); + long newUncoveredLines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_UNCOVERED_LINES), periodIndex, 0L); + long newUncoveredConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_UNCOVERED_CONDITIONS), periodIndex, 0L); + long newConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_CONDITIONS_TO_COVER), periodIndex, 0L); + + return newLines + newConditions - newUncoveredConditions - newUncoveredLines; + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/DirectoriesDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/compute/DirectoriesDecorator.java new file mode 100644 index 00000000000..e1dc25e7740 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/DirectoriesDecorator.java @@ -0,0 +1,69 @@ +/* + * 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.batch.compute; + +import java.util.Collection; +import org.sonar.api.batch.Decorator; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependedUpon; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +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; + +/** + * @since 2.2 + */ +public final class DirectoriesDecorator implements Decorator { + + @Override + public boolean shouldExecuteOnProject(Project project) { + return true; + } + + @DependedUpon + public Metric generateDirectoriesMetric() { + return CoreMetrics.DIRECTORIES; + } + + /** + * {@inheritDoc} + */ + @Override + public void decorate(Resource resource, DecoratorContext context) { + if (MeasureUtils.hasValue(context.getMeasure(CoreMetrics.DIRECTORIES))) { + return; + } + + if (Resource.QUALIFIER_DIRECTORY.equals(resource.getQualifier())) { + context.saveMeasure(CoreMetrics.DIRECTORIES, 1.0); + + } else if (ResourceUtils.isSet(resource)) { + Collection childrenMeasures = context.getChildrenMeasures(CoreMetrics.DIRECTORIES); + Double sum = MeasureUtils.sum(false, childrenMeasures); + if (sum != null) { + context.saveMeasure(CoreMetrics.DIRECTORIES, sum); + } + } + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/FilesDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/compute/FilesDecorator.java new file mode 100644 index 00000000000..27b0cbd07f8 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/FilesDecorator.java @@ -0,0 +1,65 @@ +/* + * 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.batch.compute; + +import java.util.Collection; +import org.sonar.api.batch.Decorator; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependedUpon; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.MeasureUtils; +import org.sonar.api.measures.Metric; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Resource; + +/** + * @since 2.2 + */ +public final class FilesDecorator implements Decorator { + + @Override + public boolean shouldExecuteOnProject(Project project) { + return true; + } + + @DependedUpon + public Metric generateDirectoriesMetric() { + return CoreMetrics.FILES; + } + + @Override + public void decorate(Resource resource, DecoratorContext context) { + if (MeasureUtils.hasValue(context.getMeasure(CoreMetrics.FILES))) { + return; + } + + if (Resource.QUALIFIER_CLASS.equals(resource.getQualifier()) || Resource.QUALIFIER_FILE.equals(resource.getQualifier())) { + context.saveMeasure(CoreMetrics.FILES, 1.0); + + } else { + Collection childrenMeasures = context.getChildrenMeasures(CoreMetrics.FILES); + Double sum = MeasureUtils.sum(false, childrenMeasures); + if (sum != null) { + context.saveMeasure(CoreMetrics.FILES, sum); + } + } + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/ItBranchCoverageDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/compute/ItBranchCoverageDecorator.java new file mode 100644 index 00000000000..926a34df070 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/ItBranchCoverageDecorator.java @@ -0,0 +1,73 @@ +/* + * 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.batch.compute; + +import com.google.common.collect.ImmutableList; +import java.util.List; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependsUpon; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.MeasureUtils; +import org.sonar.api.measures.Metric; + +public final class ItBranchCoverageDecorator extends AbstractCoverageDecorator { + + @DependsUpon + public List dependsUponMetrics() { + return ImmutableList.of(CoreMetrics.IT_UNCOVERED_CONDITIONS, CoreMetrics.IT_CONDITIONS_TO_COVER, + CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS, CoreMetrics.NEW_IT_CONDITIONS_TO_COVER); + } + + @Override + protected Metric getGeneratedMetric() { + return CoreMetrics.IT_BRANCH_COVERAGE; + } + + @Override + protected Long countElements(DecoratorContext context) { + return MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_CONDITIONS_TO_COVER), 0L); + } + + @Override + protected long countCoveredElements(DecoratorContext context) { + long uncoveredConditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_UNCOVERED_CONDITIONS), 0L); + long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_CONDITIONS_TO_COVER), 0L); + + return conditions - uncoveredConditions; + } + + @Override + protected Metric getGeneratedMetricForNewCode() { + return CoreMetrics.NEW_IT_BRANCH_COVERAGE; + } + + @Override + protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) { + return MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_CONDITIONS_TO_COVER), periodIndex); + } + + @Override + protected long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex) { + long uncoveredConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS), periodIndex, 0L); + long conditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_CONDITIONS_TO_COVER), periodIndex, 0L); + + return conditions - uncoveredConditions; + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/ItCoverageDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/compute/ItCoverageDecorator.java new file mode 100644 index 00000000000..4d99b759170 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/ItCoverageDecorator.java @@ -0,0 +1,87 @@ +/* + * 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.batch.compute; + +import com.google.common.collect.ImmutableList; +import java.util.Collection; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependsUpon; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.MeasureUtils; +import org.sonar.api.measures.Metric; + +public final class ItCoverageDecorator extends AbstractCoverageDecorator { + + @DependsUpon + public Collection usedMetrics() { + return ImmutableList.of(CoreMetrics.IT_LINES_TO_COVER, CoreMetrics.IT_UNCOVERED_LINES, CoreMetrics.NEW_IT_LINES_TO_COVER, + CoreMetrics.NEW_IT_UNCOVERED_LINES, CoreMetrics.IT_CONDITIONS_TO_COVER, CoreMetrics.IT_UNCOVERED_CONDITIONS, + CoreMetrics.NEW_IT_CONDITIONS_TO_COVER, CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS); + } + + @Override + protected Metric getGeneratedMetric() { + return CoreMetrics.IT_COVERAGE; + } + + @Override + protected Long countElements(DecoratorContext context) { + long lines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_LINES_TO_COVER), 0L); + long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_CONDITIONS_TO_COVER), 0L); + + return lines + conditions; + } + + @Override + protected long countCoveredElements(DecoratorContext context) { + long uncoveredLines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_UNCOVERED_LINES), 0L); + long lines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_LINES_TO_COVER), 0L); + long uncoveredConditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_UNCOVERED_CONDITIONS), 0L); + long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_CONDITIONS_TO_COVER), 0L); + + return lines + conditions - uncoveredConditions - uncoveredLines; + } + + @Override + protected Metric getGeneratedMetricForNewCode() { + return CoreMetrics.NEW_IT_COVERAGE; + } + + @Override + protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) { + Long newLinesToCover = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_LINES_TO_COVER), periodIndex); + if (newLinesToCover == null) { + return null; + } + + long newConditionsToCover = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_CONDITIONS_TO_COVER), periodIndex, 0L); + return newLinesToCover + newConditionsToCover; + } + + @Override + protected long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex) { + long newLines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_LINES_TO_COVER), periodIndex, 0L); + long newUncoveredLines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_UNCOVERED_LINES), periodIndex, 0L); + long newUncoveredConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS), periodIndex, 0L); + long newConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_CONDITIONS_TO_COVER), periodIndex, 0L); + + return newLines + newConditions - newUncoveredConditions - newUncoveredLines; + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/ItLineCoverageDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/compute/ItLineCoverageDecorator.java new file mode 100644 index 00000000000..dddddd0aac4 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/ItLineCoverageDecorator.java @@ -0,0 +1,73 @@ +/* + * 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.batch.compute; + +import com.google.common.collect.ImmutableList; +import java.util.List; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependsUpon; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.MeasureUtils; +import org.sonar.api.measures.Metric; + +public final class ItLineCoverageDecorator extends AbstractCoverageDecorator { + + @DependsUpon + public List dependsUponMetrics() { + return ImmutableList.of(CoreMetrics.IT_UNCOVERED_LINES, CoreMetrics.IT_LINES_TO_COVER, CoreMetrics.NEW_IT_UNCOVERED_LINES, + CoreMetrics.NEW_IT_LINES_TO_COVER); + } + + @Override + protected Metric getGeneratedMetric() { + return CoreMetrics.IT_LINE_COVERAGE; + } + + @Override + protected Long countElements(DecoratorContext context) { + return MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_LINES_TO_COVER), 0L); + } + + @Override + protected long countCoveredElements(DecoratorContext context) { + long uncoveredLines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_UNCOVERED_LINES), 0L); + long lines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_LINES_TO_COVER), 0L); + + return lines - uncoveredLines; + } + + @Override + protected Metric getGeneratedMetricForNewCode() { + return CoreMetrics.NEW_IT_LINE_COVERAGE; + } + + @Override + protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) { + return MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_LINES_TO_COVER), periodIndex); + } + + @Override + protected long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex) { + long uncoveredLines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_UNCOVERED_LINES), periodIndex, 0L); + long lines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_LINES_TO_COVER), periodIndex, 0L); + + return lines - uncoveredLines; + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/LineCoverageDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/compute/LineCoverageDecorator.java new file mode 100644 index 00000000000..71c6a034ac6 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/LineCoverageDecorator.java @@ -0,0 +1,72 @@ +/* + * 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.batch.compute; + +import java.util.Collection; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependsUpon; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.MeasureUtils; +import org.sonar.api.measures.Metric; +import org.sonar.batch.sensor.coverage.CoverageConstants; + +public final class LineCoverageDecorator extends AbstractCoverageDecorator { + + @DependsUpon + public Collection dependsUponMetrics() { + return CoverageConstants.LINE_COVERAGE_METRICS; + } + + @Override + protected Metric getGeneratedMetric() { + return CoreMetrics.LINE_COVERAGE; + } + + @Override + protected Long countElements(DecoratorContext context) { + return MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.LINES_TO_COVER), 0L); + } + + @Override + protected long countCoveredElements(DecoratorContext context) { + long uncoveredLines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.UNCOVERED_LINES), 0L); + long lines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.LINES_TO_COVER), 0L); + + return lines - uncoveredLines; + } + + @Override + protected Metric getGeneratedMetricForNewCode() { + return CoreMetrics.NEW_LINE_COVERAGE; + } + + @Override + protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) { + return MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_LINES_TO_COVER), periodIndex); + } + + @Override + protected long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex) { + long uncoveredLines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_UNCOVERED_LINES), periodIndex, 0L); + long lines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_LINES_TO_COVER), periodIndex, 0L); + + return lines - uncoveredLines; + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/ManualMeasureDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/compute/ManualMeasureDecorator.java new file mode 100644 index 00000000000..94346b30b8f --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/ManualMeasureDecorator.java @@ -0,0 +1,79 @@ +/* + * 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.batch.compute; + +import java.util.List; +import org.sonar.api.batch.Decorator; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.Phase; +import org.sonar.api.batch.RequiresDB; +import org.sonar.api.database.DatabaseSession; +import org.sonar.api.measures.Measure; +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.jpa.entity.ManualMeasure; + +import static com.google.common.base.Preconditions.checkState; + +@Phase(name = Phase.Name.PRE) +@RequiresDB +public class ManualMeasureDecorator implements Decorator { + + private DatabaseSession session; + private MetricFinder metricFinder; + + public ManualMeasureDecorator(DatabaseSession session, MetricFinder metricFinder) { + this.session = session; + this.metricFinder = metricFinder; + } + + @Override + public boolean shouldExecuteOnProject(Project project) { + return true; + } + + @Override + public void decorate(Resource resource, DecoratorContext context) { + if (resource.getId() != null) { + List manualMeasures = session.getResults(ManualMeasure.class, "resourceId", resource.getId()); + for (ManualMeasure manualMeasure : manualMeasures) { + context.saveMeasure(copy(manualMeasure)); + } + } + } + + private Measure copy(ManualMeasure manualMeasure) { + Metric metric = metricFinder.findById(manualMeasure.getMetricId()); + checkState(metric != null, "Unable to find manual metric with id: " + manualMeasure.getMetricId()); + + Measure measure = new Measure(metric); + measure.setValue(manualMeasure.getValue(), 5); + measure.setData(manualMeasure.getTextValue()); + measure.setDescription(manualMeasure.getDescription()); + return measure; + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/NewCoverageAggregator.java b/sonar-batch/src/main/java/org/sonar/batch/compute/NewCoverageAggregator.java new file mode 100644 index 00000000000..1923d5211a6 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/NewCoverageAggregator.java @@ -0,0 +1,99 @@ +/* + * 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.batch.compute; + +import java.util.Arrays; +import java.util.List; +import org.apache.commons.lang.ArrayUtils; +import org.sonar.api.batch.Decorator; +import org.sonar.api.batch.DecoratorBarriers; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependedUpon; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.Metric; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Qualifiers; +import org.sonar.api.resources.Resource; +import org.sonar.api.resources.Scopes; + +@DependedUpon(DecoratorBarriers.END_OF_TIME_MACHINE) +public final class NewCoverageAggregator implements Decorator { + + @Override + public boolean shouldExecuteOnProject(Project project) { + return true; + } + + @DependedUpon + public List generatesNewCoverageMetrics() { + return Arrays.asList( + CoreMetrics.NEW_LINES_TO_COVER, CoreMetrics.NEW_UNCOVERED_LINES, CoreMetrics.NEW_CONDITIONS_TO_COVER, CoreMetrics.NEW_UNCOVERED_CONDITIONS, + CoreMetrics.NEW_IT_LINES_TO_COVER, CoreMetrics.NEW_IT_UNCOVERED_LINES, CoreMetrics.NEW_IT_CONDITIONS_TO_COVER, CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS, + CoreMetrics.NEW_OVERALL_LINES_TO_COVER, CoreMetrics.NEW_OVERALL_UNCOVERED_LINES, CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER, CoreMetrics.NEW_OVERALL_UNCOVERED_CONDITIONS); + } + + @Override + public void decorate(Resource resource, DecoratorContext context) { + if (shouldDecorate(resource)) { + int maxPeriods = Qualifiers.isView(resource, true) ? 3 : 5; + aggregate(context, CoreMetrics.NEW_LINES_TO_COVER, maxPeriods); + aggregate(context, CoreMetrics.NEW_UNCOVERED_LINES, maxPeriods); + aggregate(context, CoreMetrics.NEW_CONDITIONS_TO_COVER, maxPeriods); + aggregate(context, CoreMetrics.NEW_UNCOVERED_CONDITIONS, maxPeriods); + aggregate(context, CoreMetrics.NEW_IT_LINES_TO_COVER, maxPeriods); + aggregate(context, CoreMetrics.NEW_IT_UNCOVERED_LINES, maxPeriods); + aggregate(context, CoreMetrics.NEW_IT_CONDITIONS_TO_COVER, maxPeriods); + aggregate(context, CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS, maxPeriods); + aggregate(context, CoreMetrics.NEW_OVERALL_LINES_TO_COVER, maxPeriods); + aggregate(context, CoreMetrics.NEW_OVERALL_UNCOVERED_LINES, maxPeriods); + aggregate(context, CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER, maxPeriods); + aggregate(context, CoreMetrics.NEW_OVERALL_UNCOVERED_CONDITIONS, maxPeriods); + } + } + + void aggregate(DecoratorContext context, Metric metric, int maxPeriods) { + int[] variations = {0, 0, 0, 0, 0}; + boolean[] hasValues = {false, false, false, false, false}; + for (Measure child : context.getChildrenMeasures(metric)) { + for (int indexPeriod = 1; indexPeriod <= maxPeriods; indexPeriod++) { + Double variation = child.getVariation(indexPeriod); + if (variation != null) { + variations[indexPeriod - 1] = variations[indexPeriod - 1] + variation.intValue(); + hasValues[indexPeriod - 1] = true; + } + } + } + + if (ArrayUtils.contains(hasValues, true)) { + Measure measure = new Measure(metric); + for (int index = 0; index < 5; index++) { + if (hasValues[index]) { + measure.setVariation(index + 1, (double) variations[index]); + } + } + context.saveMeasure(measure); + } + } + + boolean shouldDecorate(Resource resource) { + return Scopes.isHigherThan(resource, Scopes.FILE); + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/NewCoverageFileAnalyzer.java b/sonar-batch/src/main/java/org/sonar/batch/compute/NewCoverageFileAnalyzer.java new file mode 100644 index 00000000000..ba36d5b782b --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/NewCoverageFileAnalyzer.java @@ -0,0 +1,73 @@ +/* + * 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.batch.compute; + +import java.util.List; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Metric; +import org.sonar.batch.components.TimeMachineConfiguration; +import org.sonar.batch.index.BatchComponentCache; +import org.sonar.batch.report.ReportPublisher; + +public class NewCoverageFileAnalyzer extends AbstractNewCoverageFileAnalyzer { + + public NewCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration, ReportPublisher publishReportJob, BatchComponentCache resourceCache) { + super(timeMachineConfiguration, publishReportJob, resourceCache); + } + + NewCoverageFileAnalyzer(List structs, ReportPublisher publishReportJob, BatchComponentCache resourceCache) { + super(structs, publishReportJob, resourceCache); + } + + @Override + public Metric getCoverageLineHitsDataMetric() { + return CoreMetrics.COVERAGE_LINE_HITS_DATA; + } + + @Override + public Metric getConditionsByLineMetric() { + return CoreMetrics.CONDITIONS_BY_LINE; + } + + @Override + public Metric getCoveredConditionsByLineMetric() { + return CoreMetrics.COVERED_CONDITIONS_BY_LINE; + } + + @Override + public Metric getNewLinesToCoverMetric() { + return CoreMetrics.NEW_LINES_TO_COVER; + } + + @Override + public Metric getNewUncoveredLinesMetric() { + return CoreMetrics.NEW_UNCOVERED_LINES; + } + + @Override + public Metric getNewConditionsToCoverMetric() { + return CoreMetrics.NEW_CONDITIONS_TO_COVER; + } + + @Override + public Metric getNewUncoveredConditionsMetric() { + return CoreMetrics.NEW_UNCOVERED_CONDITIONS; + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/NewItCoverageFileAnalyzer.java b/sonar-batch/src/main/java/org/sonar/batch/compute/NewItCoverageFileAnalyzer.java new file mode 100644 index 00000000000..48d62305706 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/NewItCoverageFileAnalyzer.java @@ -0,0 +1,68 @@ +/* + * 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.batch.compute; + +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Metric; +import org.sonar.batch.components.TimeMachineConfiguration; +import org.sonar.batch.index.BatchComponentCache; +import org.sonar.batch.report.ReportPublisher; + +public class NewItCoverageFileAnalyzer extends AbstractNewCoverageFileAnalyzer { + + public NewItCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration, ReportPublisher publishReportJob, BatchComponentCache resourceCache) { + super(timeMachineConfiguration, publishReportJob, resourceCache); + } + + @Override + public Metric getCoverageLineHitsDataMetric() { + return CoreMetrics.IT_COVERAGE_LINE_HITS_DATA; + } + + @Override + public Metric getConditionsByLineMetric() { + return CoreMetrics.IT_CONDITIONS_BY_LINE; + } + + @Override + public Metric getCoveredConditionsByLineMetric() { + return CoreMetrics.IT_COVERED_CONDITIONS_BY_LINE; + } + + @Override + public Metric getNewLinesToCoverMetric() { + return CoreMetrics.NEW_IT_LINES_TO_COVER; + } + + @Override + public Metric getNewUncoveredLinesMetric() { + return CoreMetrics.NEW_IT_UNCOVERED_LINES; + } + + @Override + public Metric getNewConditionsToCoverMetric() { + return CoreMetrics.NEW_IT_CONDITIONS_TO_COVER; + } + + @Override + public Metric getNewUncoveredConditionsMetric() { + return CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS; + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/NewOverallCoverageFileAnalyzer.java b/sonar-batch/src/main/java/org/sonar/batch/compute/NewOverallCoverageFileAnalyzer.java new file mode 100644 index 00000000000..1c2688c6243 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/NewOverallCoverageFileAnalyzer.java @@ -0,0 +1,68 @@ +/* + * 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.batch.compute; + +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Metric; +import org.sonar.batch.components.TimeMachineConfiguration; +import org.sonar.batch.index.BatchComponentCache; +import org.sonar.batch.report.ReportPublisher; + +public class NewOverallCoverageFileAnalyzer extends AbstractNewCoverageFileAnalyzer { + + public NewOverallCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration, ReportPublisher publishReportJob, BatchComponentCache resourceCache) { + super(timeMachineConfiguration, publishReportJob, resourceCache); + } + + @Override + public Metric getCoverageLineHitsDataMetric() { + return CoreMetrics.OVERALL_COVERAGE_LINE_HITS_DATA; + } + + @Override + public Metric getConditionsByLineMetric() { + return CoreMetrics.OVERALL_CONDITIONS_BY_LINE; + } + + @Override + public Metric getCoveredConditionsByLineMetric() { + return CoreMetrics.OVERALL_COVERED_CONDITIONS_BY_LINE; + } + + @Override + public Metric getNewLinesToCoverMetric() { + return CoreMetrics.NEW_OVERALL_LINES_TO_COVER; + } + + @Override + public Metric getNewUncoveredLinesMetric() { + return CoreMetrics.NEW_OVERALL_UNCOVERED_LINES; + } + + @Override + public Metric getNewConditionsToCoverMetric() { + return CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER; + } + + @Override + public Metric getNewUncoveredConditionsMetric() { + return CoreMetrics.NEW_OVERALL_UNCOVERED_CONDITIONS; + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/OverallBranchCoverageDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/compute/OverallBranchCoverageDecorator.java new file mode 100644 index 00000000000..271cfcd795f --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/OverallBranchCoverageDecorator.java @@ -0,0 +1,73 @@ +/* + * 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.batch.compute; + +import com.google.common.collect.ImmutableList; +import java.util.List; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependsUpon; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.MeasureUtils; +import org.sonar.api.measures.Metric; + +public final class OverallBranchCoverageDecorator extends AbstractCoverageDecorator { + + @DependsUpon + public List dependsUponMetrics() { + return ImmutableList.of(CoreMetrics.OVERALL_UNCOVERED_CONDITIONS, CoreMetrics.OVERALL_CONDITIONS_TO_COVER, + CoreMetrics.NEW_OVERALL_UNCOVERED_CONDITIONS, CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER); + } + + @Override + protected Metric getGeneratedMetric() { + return CoreMetrics.OVERALL_BRANCH_COVERAGE; + } + + @Override + protected Long countElements(DecoratorContext context) { + return MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_CONDITIONS_TO_COVER), 0L); + } + + @Override + protected long countCoveredElements(DecoratorContext context) { + long uncoveredConditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_UNCOVERED_CONDITIONS), 0L); + long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_CONDITIONS_TO_COVER), 0L); + + return conditions - uncoveredConditions; + } + + @Override + protected Metric getGeneratedMetricForNewCode() { + return CoreMetrics.NEW_OVERALL_BRANCH_COVERAGE; + } + + @Override + protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) { + return MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER), periodIndex); + } + + @Override + protected long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex) { + long uncoveredConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_UNCOVERED_CONDITIONS), periodIndex, 0L); + long conditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER), periodIndex, 0L); + + return conditions - uncoveredConditions; + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/OverallCoverageDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/compute/OverallCoverageDecorator.java new file mode 100644 index 00000000000..c4a4d037770 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/OverallCoverageDecorator.java @@ -0,0 +1,88 @@ +/* + * 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.batch.compute; + +import com.google.common.collect.ImmutableList; +import java.util.Collection; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependsUpon; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.MeasureUtils; +import org.sonar.api.measures.Metric; + +public final class OverallCoverageDecorator extends AbstractCoverageDecorator { + + @DependsUpon + public Collection usedMetrics() { + return ImmutableList.of(CoreMetrics.OVERALL_LINES_TO_COVER, CoreMetrics.OVERALL_UNCOVERED_LINES, CoreMetrics.NEW_OVERALL_LINES_TO_COVER, + CoreMetrics.NEW_OVERALL_UNCOVERED_LINES, CoreMetrics.OVERALL_CONDITIONS_TO_COVER, CoreMetrics.OVERALL_UNCOVERED_CONDITIONS, + CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER, CoreMetrics.NEW_OVERALL_UNCOVERED_CONDITIONS); + } + + @Override + protected Metric getGeneratedMetric() { + return CoreMetrics.OVERALL_COVERAGE; + } + + @Override + protected Long countElements(DecoratorContext context) { + long lines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_LINES_TO_COVER), 0L); + long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_CONDITIONS_TO_COVER), 0L); + + return lines + conditions; + } + + @Override + protected long countCoveredElements(DecoratorContext context) { + long uncoveredLines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_UNCOVERED_LINES), 0L); + long lines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_LINES_TO_COVER), 0L); + long uncoveredConditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_UNCOVERED_CONDITIONS), 0L); + long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_CONDITIONS_TO_COVER), 0L); + + return lines + conditions - uncoveredConditions - uncoveredLines; + } + + @Override + protected Metric getGeneratedMetricForNewCode() { + return CoreMetrics.NEW_OVERALL_COVERAGE; + } + + @Override + protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) { + Long newLinesToCover = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_LINES_TO_COVER), periodIndex); + if (newLinesToCover == null) { + return null; + } + + long newConditionsToCover = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER), periodIndex, 0L); + + return newLinesToCover + newConditionsToCover; + } + + @Override + protected long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex) { + long newLines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_LINES_TO_COVER), periodIndex, 0L); + long newUncoveredLines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_UNCOVERED_LINES), periodIndex, 0L); + long newUncoveredConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_UNCOVERED_CONDITIONS), periodIndex, 0L); + long newConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER), periodIndex, 0L); + + return newLines + newConditions - newUncoveredConditions - newUncoveredLines; + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/OverallLineCoverageDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/compute/OverallLineCoverageDecorator.java new file mode 100644 index 00000000000..a41440e6314 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/OverallLineCoverageDecorator.java @@ -0,0 +1,73 @@ +/* + * 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.batch.compute; + +import com.google.common.collect.ImmutableList; +import java.util.List; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependsUpon; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.MeasureUtils; +import org.sonar.api.measures.Metric; + +public final class OverallLineCoverageDecorator extends AbstractCoverageDecorator { + + @DependsUpon + public List dependsUponMetrics() { + return ImmutableList.of(CoreMetrics.OVERALL_UNCOVERED_LINES, CoreMetrics.OVERALL_LINES_TO_COVER, CoreMetrics.NEW_OVERALL_UNCOVERED_LINES, + CoreMetrics.NEW_OVERALL_LINES_TO_COVER); + } + + @Override + protected Metric getGeneratedMetric() { + return CoreMetrics.OVERALL_LINE_COVERAGE; + } + + @Override + protected Long countElements(DecoratorContext context) { + return MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_LINES_TO_COVER), 0L); + } + + @Override + protected long countCoveredElements(DecoratorContext context) { + long uncoveredLines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_UNCOVERED_LINES), 0L); + long lines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.OVERALL_LINES_TO_COVER), 0L); + + return lines - uncoveredLines; + } + + @Override + protected Metric getGeneratedMetricForNewCode() { + return CoreMetrics.NEW_OVERALL_LINE_COVERAGE; + } + + @Override + protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) { + return MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_LINES_TO_COVER), periodIndex); + } + + @Override + protected long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex) { + long uncoveredLines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_UNCOVERED_LINES), periodIndex, 0L); + long lines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_OVERALL_LINES_TO_COVER), periodIndex, 0L); + + return lines - uncoveredLines; + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/SeverityUtils.java b/sonar-batch/src/main/java/org/sonar/batch/compute/SeverityUtils.java new file mode 100644 index 00000000000..fd92039ce98 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/SeverityUtils.java @@ -0,0 +1,66 @@ +/* + * 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.batch.compute; + +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Metric; +import org.sonar.api.rules.RulePriority; + +final class SeverityUtils { + private SeverityUtils() { + // only static methods + } + + static Metric severityToIssueMetric(RulePriority severity) { + Metric metric; + if (severity.equals(RulePriority.BLOCKER)) { + metric = CoreMetrics.BLOCKER_VIOLATIONS; + } else if (severity.equals(RulePriority.CRITICAL)) { + metric = CoreMetrics.CRITICAL_VIOLATIONS; + } else if (severity.equals(RulePriority.MAJOR)) { + metric = CoreMetrics.MAJOR_VIOLATIONS; + } else if (severity.equals(RulePriority.MINOR)) { + metric = CoreMetrics.MINOR_VIOLATIONS; + } else if (severity.equals(RulePriority.INFO)) { + metric = CoreMetrics.INFO_VIOLATIONS; + } else { + throw new IllegalArgumentException("Unsupported severity: " + severity); + } + return metric; + } + + static Metric severityToNewMetricIssue(RulePriority severity) { + Metric metric; + if (severity.equals(RulePriority.BLOCKER)) { + metric = CoreMetrics.NEW_BLOCKER_VIOLATIONS; + } else if (severity.equals(RulePriority.CRITICAL)) { + metric = CoreMetrics.NEW_CRITICAL_VIOLATIONS; + } else if (severity.equals(RulePriority.MAJOR)) { + metric = CoreMetrics.NEW_MAJOR_VIOLATIONS; + } else if (severity.equals(RulePriority.MINOR)) { + metric = CoreMetrics.NEW_MINOR_VIOLATIONS; + } else if (severity.equals(RulePriority.INFO)) { + metric = CoreMetrics.NEW_INFO_VIOLATIONS; + } else { + throw new IllegalArgumentException("Unsupported severity: " + severity); + } + return metric; + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/TimeMachineConfigurationPersister.java b/sonar-batch/src/main/java/org/sonar/batch/compute/TimeMachineConfigurationPersister.java new file mode 100644 index 00000000000..1255c64a35f --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/TimeMachineConfigurationPersister.java @@ -0,0 +1,83 @@ +/* + * 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.batch.compute; + +import java.util.List; +import org.sonar.api.batch.Decorator; +import org.sonar.api.batch.DecoratorBarriers; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependedUpon; +import org.sonar.api.batch.RequiresDB; +import org.sonar.api.database.DatabaseSession; +import org.sonar.api.database.model.Snapshot; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Resource; +import org.sonar.api.resources.ResourceUtils; +import org.sonar.batch.components.PastSnapshot; +import org.sonar.batch.components.TimeMachineConfiguration; +import org.sonar.batch.index.BatchComponentCache; + +import static org.sonar.api.utils.DateUtils.dateToLong; + +@DependedUpon(DecoratorBarriers.END_OF_TIME_MACHINE) +@RequiresDB +public final class TimeMachineConfigurationPersister implements Decorator { + + private final TimeMachineConfiguration timeMachineConfiguration; + private BatchComponentCache resourceCache; + private DatabaseSession session; + + public TimeMachineConfigurationPersister(TimeMachineConfiguration timeMachineConfiguration, BatchComponentCache resourceCache, DatabaseSession session) { + this.timeMachineConfiguration = timeMachineConfiguration; + this.resourceCache = resourceCache; + this.session = session; + } + + @Override + public void decorate(Resource resource, DecoratorContext context) { + if (ResourceUtils.isProject(resource)) { + persistConfiguration(resource); + } + } + + void persistConfiguration(Resource module) { + List pastSnapshots = timeMachineConfiguration.getProjectPastSnapshots(); + Snapshot projectSnapshot = resourceCache.get(module).snapshot(); + for (PastSnapshot pastSnapshot : pastSnapshots) { + Snapshot snapshot = session.reattach(Snapshot.class, projectSnapshot.getId()); + updatePeriodParams(snapshot, pastSnapshot); + updatePeriodParams(projectSnapshot, pastSnapshot); + session.save(snapshot); + } + session.commit(); + } + + @Override + public boolean shouldExecuteOnProject(Project project) { + return true; + } + + private void updatePeriodParams(Snapshot snapshot, PastSnapshot pastSnapshot) { + int periodIndex = pastSnapshot.getIndex(); + snapshot.setPeriodMode(periodIndex, pastSnapshot.getMode()); + snapshot.setPeriodModeParameter(periodIndex, pastSnapshot.getModeParameter()); + snapshot.setPeriodDateMs(periodIndex, dateToLong(pastSnapshot.getDate())); + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/UnitTestDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/compute/UnitTestDecorator.java new file mode 100644 index 00000000000..3f5d641af0c --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/UnitTestDecorator.java @@ -0,0 +1,95 @@ +/* + * 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.batch.compute; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import org.sonar.api.batch.Decorator; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependedUpon; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +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; + +public class UnitTestDecorator implements Decorator { + + @DependedUpon + public List generatesMetrics() { + return Arrays.asList(CoreMetrics.TEST_EXECUTION_TIME, CoreMetrics.TESTS, CoreMetrics.TEST_ERRORS, CoreMetrics.TEST_FAILURES, CoreMetrics.TEST_SUCCESS_DENSITY); + } + + @Override + public boolean shouldExecuteOnProject(Project project) { + return !Project.AnalysisType.STATIC.equals(project.getAnalysisType()); + } + + public boolean shouldDecorateResource(Resource resource) { + return ResourceUtils.isUnitTestFile(resource) || !ResourceUtils.isEntity(resource); + } + + @Override + public void decorate(Resource resource, DecoratorContext context) { + if (shouldDecorateResource(resource)) { + sumChildren(context, CoreMetrics.TEST_EXECUTION_TIME); + sumChildren(context, CoreMetrics.SKIPPED_TESTS); + Double tests = sumChildren(context, CoreMetrics.TESTS); + Double errors = sumChildren(context, CoreMetrics.TEST_ERRORS); + Double failures = sumChildren(context, CoreMetrics.TEST_FAILURES); + + if (isPositive(tests, true) && isPositive(errors, false) && isPositive(failures, false)) { + Double errorsAndFailuresRatio = (errors + failures) * 100.0 / tests; + context.saveMeasure(CoreMetrics.TEST_SUCCESS_DENSITY, 100.0 - errorsAndFailuresRatio); + } + } + } + + private boolean isPositive(Double d, boolean strict) { + return d != null && (strict ? d > 0.0 : d >= 0.0); + } + + private Double sumChildren(DecoratorContext jobContext, Metric metric) { + Collection childrenMeasures = jobContext.getChildrenMeasures(metric); + if (childrenMeasures != null && !childrenMeasures.isEmpty()) { + Double sum = 0.0; + boolean hasChildrenMeasures = false; + for (Measure measure : childrenMeasures) { + if (MeasureUtils.hasValue(measure)) { + sum += measure.getValue(); + hasChildrenMeasures = true; + } + } + if (hasChildrenMeasures) { + jobContext.saveMeasure(metric, sum); + return sum; + } + } + return null; + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/VariationDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/compute/VariationDecorator.java new file mode 100644 index 00000000000..f3885ef3f8c --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/VariationDecorator.java @@ -0,0 +1,205 @@ +/* + * 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.batch.compute; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.batch.Decorator; +import org.sonar.api.batch.DecoratorBarriers; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependedUpon; +import org.sonar.api.batch.DependsUpon; +import org.sonar.api.batch.RequiresDB; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.MeasuresFilters; +import org.sonar.api.measures.Metric; +import org.sonar.api.measures.MetricFinder; +import org.sonar.api.measures.RuleMeasure; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Qualifiers; +import org.sonar.api.resources.Resource; +import org.sonar.api.resources.Scopes; +import org.sonar.api.rules.Rule; +import org.sonar.api.rules.RuleFinder; +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; + +@DependedUpon(DecoratorBarriers.END_OF_TIME_MACHINE) +@RequiresDB +public class VariationDecorator implements Decorator { + + private List projectPastSnapshots; + private MetricFinder metricFinder; + private PastMeasuresLoader pastMeasuresLoader; + private RuleFinder ruleFinder; + + 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) { + this.pastMeasuresLoader = pastMeasuresLoader; + this.projectPastSnapshots = projectPastSnapshots; + this.metricFinder = metricFinder; + this.ruleFinder = ruleFinder; + } + + @Override + public boolean shouldExecuteOnProject(Project project) { + return true; + } + + @DependsUpon + public Collection dependsUponMetrics() { + return pastMeasuresLoader.getMetrics(); + } + + @Override + public void decorate(Resource resource, DecoratorContext context) { + for (PastSnapshot projectPastSnapshot : projectPastSnapshots) { + if (shouldComputeVariation(resource)) { + computeVariation(resource, context, projectPastSnapshot); + } + } + } + + boolean shouldComputeVariation(Resource resource) { + if (Scopes.FILE.equals(resource.getScope()) && !Qualifiers.UNIT_TEST_FILE.equals(resource.getQualifier())) { + return false; + } + + // measures on files are currently purged, so past measures are not available on files + return StringUtils.equals(Scopes.PROJECT, resource.getScope()) || StringUtils.equals(Scopes.DIRECTORY, resource.getScope()); + } + + private void computeVariation(Resource resource, DecoratorContext context, PastSnapshot pastSnapshot) { + List pastMeasures = pastMeasuresLoader.getPastMeasures(resource, pastSnapshot); + compareWithPastMeasures(context, pastSnapshot.getIndex(), pastMeasures); + } + + private void compareWithPastMeasures(DecoratorContext context, int index, List pastMeasures) { + Map pastMeasuresByKey = new HashMap<>(); + for (Object[] pastMeasure : pastMeasures) { + pastMeasuresByKey.put(new MeasureKey(pastMeasure), pastMeasure); + } + + // for each measure, search equivalent past measure + for (Measure measure : context.getMeasures(MeasuresFilters.all())) { + // compare with past measure + Integer metricId = measure.getMetric().getId(); + if (metricId == null) { + Metric metric = metricFinder.findByKey(measure.getMetric().getKey()); + if (metric == null) { + throw new IllegalStateException("Unknow metric with key: " + measure.getMetric().getKey()); + } + metricId = metric.getId(); + } + Characteristic characteristic = measure.getCharacteristic(); + Integer characteristicId = characteristic != null ? characteristic.id() : null; + Integer personId = measure.getPersonId(); + Integer ruleId = null; + if (measure instanceof RuleMeasure) { + Rule rule = ruleFinder.findByKey(((RuleMeasure) measure).ruleKey()); + if (rule != null) { + ruleId = rule.getId(); + } + } + + Object[] pastMeasure = pastMeasuresByKey.get(new MeasureKey(metricId, characteristicId, personId, ruleId)); + if (updateVariation(measure, pastMeasure, index)) { + context.saveMeasure(measure); + } + } + } + + boolean updateVariation(Measure measure, Object[] pastMeasure, int index) { + if (pastMeasure != null && PastMeasuresLoader.hasValue(pastMeasure) && measure.getValue() != null) { + double variation = measure.getValue() - PastMeasuresLoader.getValue(pastMeasure); + measure.setVariation(index, variation); + return true; + } + return false; + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } + + static final class MeasureKey { + int metricId; + Integer characteristicId; + Integer personId; + Integer ruleId; + + MeasureKey(Object[] pastFields) { + metricId = PastMeasuresLoader.getMetricId(pastFields); + characteristicId = PastMeasuresLoader.getCharacteristicId(pastFields); + personId = PastMeasuresLoader.getPersonId(pastFields); + ruleId = PastMeasuresLoader.getRuleId(pastFields); + } + + MeasureKey(int metricId, @Nullable Integer characteristicId, @Nullable Integer personId, @Nullable Integer ruleId) { + this.metricId = metricId; + this.characteristicId = characteristicId; + this.personId = personId; + this.ruleId = ruleId; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + MeasureKey that = (MeasureKey) o; + if (metricId != that.metricId) { + return false; + } + if (characteristicId != null ? !characteristicId.equals(that.characteristicId) : that.characteristicId != null) { + return false; + } + if (personId != null ? !personId.equals(that.personId) : that.personId != null) { + return false; + } + if (ruleId != null ? !ruleId.equals(that.ruleId) : that.ruleId != null) { + return false; + } + return true; + } + + @Override + public int hashCode() { + int result = metricId; + result = 31 * result + (characteristicId != null ? characteristicId.hashCode() : 0); + result = 31 * result + (personId != null ? personId.hashCode() : 0); + result = 31 * result + (ruleId != null ? ruleId.hashCode() : 0); + return result; + } + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/package-info.java b/sonar-batch/src/main/java/org/sonar/batch/compute/package-info.java new file mode 100644 index 00000000000..7fd21f3ba7c --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/compute/package-info.java @@ -0,0 +1,24 @@ +/* + * 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. + */ +@ParametersAreNonnullByDefault +package org.sonar.batch.compute; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-batch/src/test/java/org/sonar/batch/compute/ApplyProjectRolesDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/compute/ApplyProjectRolesDecoratorTest.java new file mode 100644 index 00000000000..cd48e6a315f --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/compute/ApplyProjectRolesDecoratorTest.java @@ -0,0 +1,83 @@ +/* + * 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.batch.compute; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.resources.Project; +import org.sonar.api.security.ResourcePermissions; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class ApplyProjectRolesDecoratorTest { + + private ResourcePermissions resourcePermissions; + private ApplyProjectRolesDecorator decorator; + + @Before + public void init() { + resourcePermissions = mock(ResourcePermissions.class); + decorator = new ApplyProjectRolesDecorator(resourcePermissions); + } + + @Test + public void alwaysExecute() { + assertThat(decorator.shouldExecuteOnProject(new Project("project"))).isTrue(); + } + + @Test + public void doNotGrantDefaultRolesWhenExistingPermissions() { + Project project = new Project("project"); + project.setId(10); + when(resourcePermissions.hasRoles(project)).thenReturn(true); + + decorator.decorate(project, null); + + verify(resourcePermissions, never()).grantDefaultRoles(project); + } + + @Test + public void doNotApplySecurityOnModules() { + Project project = new Project("project"); + Project module = new Project("module").setParent(project); + module.setId(10); + when(resourcePermissions.hasRoles(project)).thenReturn(false); + + decorator.decorate(module, null); + + verify(resourcePermissions, never()).grantDefaultRoles(module); + } + + @Test + public void grantDefaultRolesWhenNoPermissions() { + Project project = new Project("project"); + project.setId(10); + when(resourcePermissions.hasRoles(project)).thenReturn(false); + + decorator.decorate(project, null); + + verify(resourcePermissions).grantDefaultRoles(project); + } + +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/compute/BranchCoverageDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/compute/BranchCoverageDecoratorTest.java new file mode 100644 index 00000000000..a7f9e098376 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/compute/BranchCoverageDecoratorTest.java @@ -0,0 +1,72 @@ +/* + * 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.batch.compute; + +import org.junit.Before; +import org.junit.Test; +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.Scopes; + +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.verify; +import static org.mockito.Mockito.when; + +public class BranchCoverageDecoratorTest { + private final BranchCoverageDecorator decorator = new BranchCoverageDecorator(); + private final Project resource = mock(Project.class); + + @Before + public void setUp() { + when(resource.getScope()).thenReturn(Scopes.PROJECT); + when(resource.getQualifier()).thenReturn(Qualifiers.PROJECT); + } + + @Test + public void shouldSaveBranchCoverage() { + DecoratorContext context = mockContext(20, 15); + + decorator.decorate(resource, context); + + verify(context).saveMeasure(CoreMetrics.BRANCH_COVERAGE, 25.0); + } + + @Test + public void shouldNotSaveBranchCoverageIfMissingConditions() { + DecoratorContext context = mock(DecoratorContext.class); + + decorator.decorate(resource, context); + + verify(context, never()).saveMeasure(eq(CoreMetrics.BRANCH_COVERAGE), anyDouble()); + } + + private static DecoratorContext mockContext(int conditions, int uncoveredConditions) { + DecoratorContext context = mock(DecoratorContext.class); + when(context.getMeasure(CoreMetrics.CONDITIONS_TO_COVER)).thenReturn(new Measure(CoreMetrics.CONDITIONS_TO_COVER, (double) conditions)); + when(context.getMeasure(CoreMetrics.UNCOVERED_CONDITIONS)).thenReturn(new Measure(CoreMetrics.UNCOVERED_CONDITIONS, (double) uncoveredConditions)); + return context; + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/compute/CommentDensityDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/compute/CommentDensityDecoratorTest.java new file mode 100644 index 00000000000..dadbb945e90 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/compute/CommentDensityDecoratorTest.java @@ -0,0 +1,76 @@ +/* + * 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.batch.compute; + +import org.junit.Test; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.test.IsMeasure; + +import static org.mockito.Matchers.argThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class CommentDensityDecoratorTest { + + @Test + public void densityIsBalancedByNcloc() { + DecoratorContext context = mock(DecoratorContext.class); + when(context.getMeasure(CoreMetrics.NCLOC)).thenReturn(new Measure(CoreMetrics.NCLOC, 300.0)); + when(context.getMeasure(CoreMetrics.COMMENT_LINES)).thenReturn(new Measure(CoreMetrics.COMMENT_LINES, 200.0)); + CommentDensityDecorator decorator = new CommentDensityDecorator(); + decorator.decorate(null, context); + // 200 / (200 + 300) = 40% + verify(context).saveMeasure(argThat(new IsMeasure(CoreMetrics.COMMENT_LINES_DENSITY, 40.0))); + } + + @Test + public void noDensityIfUnknownComments() { + DecoratorContext context = mock(DecoratorContext.class); + when(context.getMeasure(CoreMetrics.NCLOC)).thenReturn(new Measure(CoreMetrics.NCLOC, 300.0)); + CommentDensityDecorator decorator = new CommentDensityDecorator(); + decorator.decorate(null, context); + verify(context, never()).saveMeasure(argThat(new IsMeasure(CoreMetrics.COMMENT_LINES_DENSITY))); + } + + @Test + public void noDensityIfZeroNcloc() { + DecoratorContext context = mock(DecoratorContext.class); + when(context.getMeasure(CoreMetrics.NCLOC)).thenReturn(new Measure(CoreMetrics.NCLOC, 0.0)); + when(context.getMeasure(CoreMetrics.COMMENT_LINES)).thenReturn(new Measure(CoreMetrics.COMMENT_LINES, 0.0)); + CommentDensityDecorator decorator = new CommentDensityDecorator(); + decorator.decorate(null, context); + verify(context, never()).saveMeasure(argThat(new IsMeasure(CoreMetrics.COMMENT_LINES_DENSITY))); + } + + @Test + public void zeroDensityWhenZeroComments() { + DecoratorContext context = mock(DecoratorContext.class); + when(context.getMeasure(CoreMetrics.NCLOC)).thenReturn(new Measure(CoreMetrics.NCLOC, 40.0)); + when(context.getMeasure(CoreMetrics.COMMENT_LINES)).thenReturn(new Measure(CoreMetrics.COMMENT_LINES, 0.0)); + CommentDensityDecorator decorator = new CommentDensityDecorator(); + decorator.decorate(null, context); + verify(context).saveMeasure(argThat(new IsMeasure(CoreMetrics.COMMENT_LINES_DENSITY, 0.0))); + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/compute/CountFalsePositivesDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/compute/CountFalsePositivesDecoratorTest.java new file mode 100644 index 00000000000..37eea57e8e6 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/compute/CountFalsePositivesDecoratorTest.java @@ -0,0 +1,81 @@ +/* + * 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.batch.compute; + +import java.util.Arrays; +import org.junit.Test; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.component.ResourcePerspectives; +import org.sonar.api.issue.Issuable; +import org.sonar.api.issue.Issue; +import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.resources.File; +import org.sonar.api.resources.Project; +import org.sonar.api.rule.RuleKey; +import org.sonar.java.api.JavaClass; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +public class CountFalsePositivesDecoratorTest { + + ResourcePerspectives perspectives = mock(ResourcePerspectives.class); + CountFalsePositivesDecorator decorator = new CountFalsePositivesDecorator(perspectives); + + @Test + public void should_count_false_positives() { + DefaultIssue falsePositive = new DefaultIssue().setRuleKey(RuleKey.parse("squid:AvoidCycles")) + .setResolution(Issue.RESOLUTION_FALSE_POSITIVE).setStatus(Issue.STATUS_RESOLVED); + DefaultIssue fixed = new DefaultIssue().setRuleKey(RuleKey.parse("squid:AvoidCycles")) + .setResolution(Issue.RESOLUTION_FIXED).setStatus(Issue.STATUS_RESOLVED); + + File file = File.create("foo.c"); + Issuable issuable = mock(Issuable.class); + when(perspectives.as(Issuable.class, file)).thenReturn(issuable); + when(issuable.resolvedIssues()).thenReturn(Arrays.asList(falsePositive, fixed)); + + DecoratorContext context = mock(DecoratorContext.class); + decorator.decorate(file, context); + + verify(context).saveMeasure(CoreMetrics.FALSE_POSITIVE_ISSUES, 1.0); + } + + @Test + public void should_declare_metadata() { + assertThat(decorator.shouldExecuteOnProject(new Project("foo"))).isTrue(); + assertThat(decorator.generatesFalsePositiveMeasure()).isEqualTo(CoreMetrics.FALSE_POSITIVE_ISSUES); + assertThat(decorator.toString()).isEqualTo("CountFalsePositivesDecorator"); + } + + @Test + public void should_ignore_classes_and_methods() { + JavaClass javaClass = JavaClass.create("Foo.java"); + when(perspectives.as(Issuable.class, javaClass)).thenReturn(null); + + DecoratorContext context = mock(DecoratorContext.class); + decorator.decorate(javaClass, context); + + verifyZeroInteractions(context); + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/compute/CountUnresolvedIssuesDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/compute/CountUnresolvedIssuesDecoratorTest.java new file mode 100644 index 00000000000..8473e0a3da7 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/compute/CountUnresolvedIssuesDecoratorTest.java @@ -0,0 +1,372 @@ +/* + * 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.batch.compute; + +import com.google.common.collect.Lists; +import java.util.Calendar; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import org.apache.commons.lang.ObjectUtils; +import org.apache.commons.lang.time.DateUtils; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentMatcher; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.component.ResourcePerspectives; +import org.sonar.api.issue.Issuable; +import org.sonar.api.issue.Issue; +import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.MeasuresFilter; +import org.sonar.api.measures.Metric; +import org.sonar.api.measures.RuleMeasure; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Resource; +import org.sonar.api.resources.Scopes; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rule.Severity; +import org.sonar.api.rules.Rule; +import org.sonar.api.rules.RulePriority; +import org.sonar.api.test.IsRuleMeasure; +import org.sonar.batch.components.Period; +import org.sonar.batch.components.TimeMachineConfiguration; + +import static com.google.common.collect.Lists.newArrayList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyDouble; +import static org.mockito.Mockito.argThat; +import static org.mockito.Mockito.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.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +public class CountUnresolvedIssuesDecoratorTest { + + CountUnresolvedIssuesDecorator decorator; + TimeMachineConfiguration timeMachineConfiguration; + Issuable issuable; + DecoratorContext context; + Resource resource; + Project project; + Rule ruleA1; + Rule ruleA2; + Rule ruleB1; + Date rightNow; + Date tenDaysAgo; + Date afterTenDaysAgo; + Date fiveDaysAgo; + Date afterFiveDaysAgo; + Date sameSecond; + + @Before + public void before() { + ruleA1 = Rule.create().setRepositoryKey("ruleA1").setKey("ruleA1").setName("nameA1"); + ruleA2 = Rule.create().setRepositoryKey("ruleA2").setKey("ruleA2").setName("nameA2"); + ruleB1 = Rule.create().setRepositoryKey("ruleB1").setKey("ruleB1").setName("nameB1"); + + rightNow = new Date(); + tenDaysAgo = DateUtils.addDays(rightNow, -10); + afterTenDaysAgo = DateUtils.addDays(tenDaysAgo, 1); + fiveDaysAgo = DateUtils.addDays(rightNow, -5); + afterFiveDaysAgo = DateUtils.addDays(fiveDaysAgo, 1); + sameSecond = DateUtils.truncate(rightNow, Calendar.SECOND); + + timeMachineConfiguration = mock(TimeMachineConfiguration.class); + when(timeMachineConfiguration.periods()).thenReturn(newArrayList(new Period(1, afterFiveDaysAgo), new Period(2, afterTenDaysAgo))); + + project = mock(Project.class); + resource = mock(Resource.class); + context = mock(DecoratorContext.class); + when(context.getResource()).thenReturn(resource); + when(context.getProject()).thenReturn(project); + when(context.getMeasure(CoreMetrics.NEW_VIOLATIONS)).thenReturn(null); + + issuable = mock(Issuable.class); + ResourcePerspectives perspectives = mock(ResourcePerspectives.class); + when(perspectives.as(Issuable.class, resource)).thenReturn(issuable); + decorator = new CountUnresolvedIssuesDecorator(perspectives, timeMachineConfiguration); + } + + @Test + public void should_be_depended_upon_metric() { + assertThat(decorator.generatesIssuesMetrics()).hasSize(15); + } + + @Test + public void should_count_issues() { + when(resource.getScope()).thenReturn(Scopes.PROJECT); + when(issuable.issues()).thenReturn(createIssues()); + when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.emptyList()); + + decorator.decorate(resource, context); + + verify(context).saveMeasure(CoreMetrics.VIOLATIONS, 4.0); + } + + @Test + public void should_do_nothing_when_issuable_is_null() { + ResourcePerspectives perspectives = mock(ResourcePerspectives.class); + when(perspectives.as(Issuable.class, resource)).thenReturn(null); + CountUnresolvedIssuesDecorator decorator = new CountUnresolvedIssuesDecorator(perspectives, timeMachineConfiguration); + + decorator.decorate(resource, context); + + verifyZeroInteractions(context); + } + + /** + * See http://jira.codehaus.org/browse/SONAR-1729 + */ + @Test + public void should_not_count_issues_if_measure_already_exists() { + when(resource.getScope()).thenReturn(Scopes.PROJECT); + when(issuable.issues()).thenReturn(createIssues()); + when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.emptyList()); + when(context.getMeasure(CoreMetrics.VIOLATIONS)).thenReturn(new Measure(CoreMetrics.VIOLATIONS, 3000.0)); + when(context.getMeasure(CoreMetrics.MAJOR_VIOLATIONS)).thenReturn(new Measure(CoreMetrics.MAJOR_VIOLATIONS, 500.0)); + + decorator.decorate(resource, context); + + verify(context, never()).saveMeasure(eq(CoreMetrics.VIOLATIONS), anyDouble());// not changed + verify(context, never()).saveMeasure(eq(CoreMetrics.MAJOR_VIOLATIONS), anyDouble());// not changed + verify(context, times(1)).saveMeasure(eq(CoreMetrics.CRITICAL_VIOLATIONS), anyDouble());// did not exist + } + + @Test + public void should_save_zero_on_projects() { + when(resource.getScope()).thenReturn(Scopes.PROJECT); + when(issuable.issues()).thenReturn(Lists.newArrayList()); + when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.emptyList()); + + decorator.decorate(resource, context); + + verify(context).saveMeasure(CoreMetrics.VIOLATIONS, 0.0); + } + + @Test + public void should_save_zero_on_directories() { + when(resource.getScope()).thenReturn(Scopes.DIRECTORY); + when(issuable.issues()).thenReturn(Lists.newArrayList()); + when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.emptyList()); + + decorator.decorate(resource, context); + + verify(context).saveMeasure(CoreMetrics.VIOLATIONS, 0.0); + } + + @Test + public void should_count_issues_by_severity() { + when(resource.getScope()).thenReturn(Scopes.PROJECT); + when(issuable.issues()).thenReturn(createIssues()); + when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.emptyList()); + + decorator.decorate(resource, context); + + verify(context).saveMeasure(CoreMetrics.BLOCKER_VIOLATIONS, 0.0); + verify(context).saveMeasure(CoreMetrics.CRITICAL_VIOLATIONS, 2.0); + verify(context).saveMeasure(CoreMetrics.MAJOR_VIOLATIONS, 1.0); + verify(context).saveMeasure(CoreMetrics.MINOR_VIOLATIONS, 1.0); + verify(context).saveMeasure(CoreMetrics.INFO_VIOLATIONS, 0.0); + } + + @Test + public void should_count_issues_per_rule() { + List issues = newArrayList(); + issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name())); + issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name())); + issues.add(new DefaultIssue().setRuleKey(ruleA2.ruleKey()).setSeverity(RulePriority.MAJOR.name())); + when(issuable.issues()).thenReturn(issues); + + decorator.decorate(resource, context); + + verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.CRITICAL_VIOLATIONS, ruleA1, 2.0))); + verify(context, never()).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.MAJOR_VIOLATIONS, ruleA1, 0.0))); + verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.MAJOR_VIOLATIONS, ruleA2, 1.0))); + } + + @Test + public void same_rule_should_have_different_severities() { + List issues = newArrayList(); + issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name())); + issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name())); + issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.MINOR.name())); + when(issuable.issues()).thenReturn(issues); + + decorator.decorate(resource, context); + + verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.CRITICAL_VIOLATIONS, ruleA1, 2.0))); + verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.MINOR_VIOLATIONS, ruleA1, 1.0))); + } + + @Test + public void should_count_issues_after_date() { + List issues = createIssuesForNewMetrics(); + + assertThat(decorator.countIssuesAfterDate(null, fiveDaysAgo)).isEqualTo(0); + assertThat(decorator.countIssuesAfterDate(issues, fiveDaysAgo)).isEqualTo(1); // 1 rightNow + assertThat(decorator.countIssuesAfterDate(issues, tenDaysAgo)).isEqualTo(3); // 1 rightNow + 2 fiveDaysAgo + assertThat(decorator.countIssuesAfterDate(issues, sameSecond)).isEqualTo(0); // 0 + } + + @Test + public void should_clear_cache_after_execution() { + Issue issue1 = new DefaultIssue().setRuleKey(RuleKey.of(ruleA1.getRepositoryKey(), ruleA1.getKey())).setSeverity(RulePriority.CRITICAL.name()).setCreationDate(rightNow); + Issue issue2 = new DefaultIssue().setRuleKey(RuleKey.of(ruleA2.getRepositoryKey(), ruleA2.getKey())).setSeverity(RulePriority.CRITICAL.name()).setCreationDate(rightNow); + when(issuable.issues()).thenReturn(newArrayList(issue1)).thenReturn(newArrayList(issue2)); + + decorator.decorate(resource, context); + decorator.decorate(resource, context); + + verify(context, times(2)).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS, 1.0, 1.0))); + verify(context, never()).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS, 2.0, 2.0))); + } + + @Test + public void should_save_severity_new_issues() { + when(issuable.issues()).thenReturn(createIssuesForNewMetrics()); + + decorator.decorate(resource, context); + + // remember : period1 is 5daysAgo, period2 is 10daysAgo + verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_BLOCKER_VIOLATIONS, 0.0, 0.0))); + verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS, 1.0, 1.0))); + verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_MAJOR_VIOLATIONS, 0.0, 1.0))); + verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_MINOR_VIOLATIONS, 0.0, 1.0))); + verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_INFO_VIOLATIONS, 0.0, 0.0))); + } + + @Test + public void should_save_rule_new_issues() { + when(issuable.issues()).thenReturn(createIssuesForNewMetrics()); + + decorator.decorate(resource, context); + + // remember : period1 is 5daysAgo, period2 is 10daysAgo + verify(context).saveMeasure(argThat(new IsVariationRuleMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS, ruleA1, 1.0, 1.0))); + verify(context).saveMeasure(argThat(new IsVariationRuleMeasure(CoreMetrics.NEW_MAJOR_VIOLATIONS, ruleA2, 0.0, 1.0))); + verify(context).saveMeasure(argThat(new IsVariationRuleMeasure(CoreMetrics.NEW_MINOR_VIOLATIONS, ruleB1, 0.0, 1.0))); + } + + @Test + public void should_not_save_new_issues_if_measure_already_computed() { + when(context.getMeasure(CoreMetrics.NEW_VIOLATIONS)).thenReturn(new Measure()); + when(issuable.issues()).thenReturn(createIssuesForNewMetrics()); + + decorator.decorate(resource, context); + + verify(context, never()).saveMeasure(argThat(new IsMetricMeasure(CoreMetrics.NEW_BLOCKER_VIOLATIONS))); + verify(context, never()).saveMeasure(argThat(new IsMetricMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS))); + verify(context, never()).saveMeasure(argThat(new IsMetricMeasure(CoreMetrics.NEW_MAJOR_VIOLATIONS))); + verify(context, never()).saveMeasure(argThat(new IsMetricMeasure(CoreMetrics.NEW_MINOR_VIOLATIONS))); + verify(context, never()).saveMeasure(argThat(new IsMetricMeasure(CoreMetrics.NEW_INFO_VIOLATIONS))); + verify(context, never()).saveMeasure(argThat(new IsMetricMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS))); + } + + List createIssues() { + List issues = newArrayList(); + issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(Severity.CRITICAL).setStatus(Issue.STATUS_OPEN)); + issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(Severity.CRITICAL).setStatus(Issue.STATUS_REOPENED)); + issues.add(new DefaultIssue().setRuleKey(ruleA2.ruleKey()).setSeverity(Severity.MAJOR).setStatus(Issue.STATUS_REOPENED)); + issues.add(new DefaultIssue().setRuleKey(ruleB1.ruleKey()).setSeverity(Severity.MINOR).setStatus(Issue.STATUS_OPEN)); + return issues; + } + + List createIssuesForNewMetrics() { + List issues = newArrayList(); + issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name()).setCreationDate(rightNow).setStatus(Issue.STATUS_OPEN)); + issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name()).setCreationDate(tenDaysAgo).setStatus(Issue.STATUS_OPEN)); + issues.add(new DefaultIssue().setRuleKey(ruleA2.ruleKey()).setSeverity(RulePriority.MAJOR.name()).setCreationDate(fiveDaysAgo).setStatus(Issue.STATUS_REOPENED)); + issues.add(new DefaultIssue().setRuleKey(ruleA2.ruleKey()).setSeverity(RulePriority.MAJOR.name()).setCreationDate(tenDaysAgo).setStatus(Issue.STATUS_REOPENED)); + issues.add(new DefaultIssue().setRuleKey(ruleB1.ruleKey()).setSeverity(RulePriority.MINOR.name()).setCreationDate(fiveDaysAgo).setStatus(Issue.STATUS_OPEN)); + issues.add(new DefaultIssue().setRuleKey(ruleB1.ruleKey()).setSeverity(RulePriority.MINOR.name()).setCreationDate(tenDaysAgo).setStatus(Issue.STATUS_OPEN)); + return issues; + } + + class IsVariationRuleMeasure extends ArgumentMatcher { + Metric metric = null; + Rule rule = null; + Double var1 = null; + Double var2 = null; + + public IsVariationRuleMeasure(Metric metric, Rule rule, Double var1, Double var2) { + this.metric = metric; + this.rule = rule; + this.var1 = var1; + this.var2 = var2; + } + + public boolean matches(Object o) { + if (!(o instanceof RuleMeasure)) { + return false; + } + RuleMeasure m = (RuleMeasure) o; + return ObjectUtils.equals(metric, m.getMetric()) && + ObjectUtils.equals(rule.ruleKey(), m.ruleKey()) && + ObjectUtils.equals(var1, m.getVariation1()) && + ObjectUtils.equals(var2, m.getVariation2()); + } + } + + class IsVariationMeasure extends ArgumentMatcher { + Metric metric = null; + Double var1 = null; + Double var2 = null; + + public IsVariationMeasure(Metric metric, Double var1, Double var2) { + this.metric = metric; + this.var1 = var1; + this.var2 = var2; + } + + public boolean matches(Object o) { + if (!(o instanceof Measure)) { + return false; + } + Measure m = (Measure) o; + return ObjectUtils.equals(metric, m.getMetric()) && + ObjectUtils.equals(var1, m.getVariation1()) && + ObjectUtils.equals(var2, m.getVariation2()) && + !(m instanceof RuleMeasure); + } + } + + class IsMetricMeasure extends ArgumentMatcher { + Metric metric = null; + + public IsMetricMeasure(Metric metric) { + this.metric = metric; + } + + public boolean matches(Object o) { + if (!(o instanceof Measure)) { + return false; + } + Measure m = (Measure) o; + return ObjectUtils.equals(metric, m.getMetric()); + } + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/compute/CoverageDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/compute/CoverageDecoratorTest.java new file mode 100644 index 00000000000..5994f3e72e6 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/compute/CoverageDecoratorTest.java @@ -0,0 +1,143 @@ +/* + * 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.batch.compute; + +import java.util.Collection; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.Metric; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Scopes; + +import static org.assertj.core.api.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.verify; +import static org.mockito.Mockito.when; + +public class CoverageDecoratorTest { + private CoverageDecorator decorator; + private final Project project = mock(Project.class); + + @Before + public void before() { + when(project.getScope()).thenReturn(Scopes.PROJECT); + decorator = new CoverageDecorator(); + } + + @Test + public void should_use_metrics() { + Collection metrics = decorator.usedMetrics(); + + assertThat(metrics).containsOnly(CoreMetrics.LINES_TO_COVER, CoreMetrics.UNCOVERED_LINES, CoreMetrics.NEW_LINES_TO_COVER, + CoreMetrics.NEW_UNCOVERED_LINES, CoreMetrics.CONDITIONS_TO_COVER, CoreMetrics.UNCOVERED_CONDITIONS, + CoreMetrics.NEW_CONDITIONS_TO_COVER, CoreMetrics.NEW_UNCOVERED_CONDITIONS); + } + + @Test + public void coverage() { + DecoratorContext context = mockContext(50, 40, 10, 8); + + decorator.decorate(project, context); + + // (50-40 covered lines + 10-8 covered conditions) / (50 lines + 10 conditions) + verify(context).saveMeasure(CoreMetrics.COVERAGE, 20.0); + } + + @Test + public void coverageCanBe0() { + DecoratorContext context = mockContext(50, 50, 5, 5); + + decorator.decorate(project, context); + + verify(context).saveMeasure(CoreMetrics.COVERAGE, 0.0); + } + + @Test + public void coverageCanBe100() { + DecoratorContext context = mockContext(50, 0, 5, 0); + + decorator.decorate(project, context); + + verify(context).saveMeasure(CoreMetrics.COVERAGE, 100.0); + } + + @Test + public void noCoverageIfNoElements() { + DecoratorContext context = mock(DecoratorContext.class); + + decorator.decorate(project, context); + + verify(context, never()).saveMeasure(eq(CoreMetrics.COVERAGE), anyDouble()); + } + + @Test + public void should_count_elements_for_new_code() { + Measure newLines = measureWithVariation(1, 100.0); + Measure newConditions = measureWithVariation(1, 1.0); + DecoratorContext context = mockNewContext(newLines, null, null, newConditions); + + long count = decorator.countElementsForNewCode(context, 1); + + assertThat(count).isEqualTo(101).isEqualTo(100 + 1); + } + + @Test + public void should_count_covered_elements_for_new_code() { + Measure newLines = measureWithVariation(1, 100.0); + Measure newUncoveredConditions = measureWithVariation(1, 10.0); + Measure newUncoveredLines = measureWithVariation(1, 5.0); + Measure newConditions = measureWithVariation(1, 1.0); + DecoratorContext context = mockNewContext(newLines, newUncoveredConditions, newUncoveredLines, newConditions); + + long count = decorator.countCoveredElementsForNewCode(context, 1); + + assertThat(count).isEqualTo(86).isEqualTo(100 + 1 - 10 - 5); + } + + private static DecoratorContext mockContext(int lines, int uncoveredLines, int conditions, int uncoveredConditions) { + DecoratorContext context = mock(DecoratorContext.class); + when(context.getMeasure(CoreMetrics.LINES_TO_COVER)).thenReturn(new Measure(CoreMetrics.LINES_TO_COVER, (double) lines)); + when(context.getMeasure(CoreMetrics.UNCOVERED_LINES)).thenReturn(new Measure(CoreMetrics.UNCOVERED_LINES, (double) uncoveredLines)); + when(context.getMeasure(CoreMetrics.CONDITIONS_TO_COVER)).thenReturn(new Measure(CoreMetrics.CONDITIONS_TO_COVER, (double) conditions)); + when(context.getMeasure(CoreMetrics.UNCOVERED_CONDITIONS)).thenReturn(new Measure(CoreMetrics.UNCOVERED_CONDITIONS, (double) uncoveredConditions)); + return context; + } + + private static DecoratorContext mockNewContext(Measure newLines, Measure newUncoveredConditions, Measure newUncoveredLines, Measure newConditions) { + DecoratorContext context = mock(DecoratorContext.class); + when(context.getMeasure(CoreMetrics.NEW_LINES_TO_COVER)).thenReturn(newLines); + when(context.getMeasure(CoreMetrics.NEW_UNCOVERED_LINES)).thenReturn(newUncoveredLines); + when(context.getMeasure(CoreMetrics.NEW_UNCOVERED_CONDITIONS)).thenReturn(newUncoveredConditions); + when(context.getMeasure(CoreMetrics.NEW_CONDITIONS_TO_COVER)).thenReturn(newConditions); + return context; + } + + private static Measure measureWithVariation(int period, double variation) { + Measure measure = mock(Measure.class); + when(measure.getVariation(period)).thenReturn(variation); + return measure; + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/compute/DirectoriesDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/compute/DirectoriesDecoratorTest.java new file mode 100644 index 00000000000..5e854bc9913 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/compute/DirectoriesDecoratorTest.java @@ -0,0 +1,90 @@ +/* + * 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.batch.compute; + +import java.util.Arrays; +import java.util.Collections; +import org.junit.Test; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.resources.Directory; +import org.sonar.api.resources.File; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Resource; + +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.verify; +import static org.mockito.Mockito.when; + +public class DirectoriesDecoratorTest { + + @Test + public void doNotInsertZeroOnFiles() { + DirectoriesDecorator decorator = new DirectoriesDecorator(); + Resource file = File.create("foo.php"); + DecoratorContext context = mock(DecoratorContext.class); + + decorator.decorate(file, context); + + verify(context, never()).saveMeasure(eq(CoreMetrics.DIRECTORIES), anyDouble()); + } + + @Test + public void directoryCountsForOne() { + DirectoriesDecorator decorator = new DirectoriesDecorator(); + Resource directory = Directory.create("org/foo"); + DecoratorContext context = mock(DecoratorContext.class); + decorator.decorate(directory, context); + verify(context).saveMeasure(CoreMetrics.DIRECTORIES, 1.0); + } + + @Test + public void countProjectDirectories() { + DirectoriesDecorator decorator = new DirectoriesDecorator(); + Resource project = new Project("project"); + DecoratorContext context = mock(DecoratorContext.class); + + when(context.getChildrenMeasures(CoreMetrics.DIRECTORIES)).thenReturn(Arrays.asList( + new Measure(CoreMetrics.DIRECTORIES, 1.0), + new Measure(CoreMetrics.DIRECTORIES, 1.0), + new Measure(CoreMetrics.DIRECTORIES, 1.0) + )); + decorator.decorate(project, context); + verify(context).saveMeasure(CoreMetrics.DIRECTORIES, 3.0); + } + + @Test + public void noProjectValueWhenOnlyPackages() { + DirectoriesDecorator decorator = new DirectoriesDecorator(); + Resource project = new Project("project"); + DecoratorContext context = mock(DecoratorContext.class); + when(context.getChildrenMeasures(CoreMetrics.DIRECTORIES)).thenReturn(Collections.emptyList()); + when(context.getChildrenMeasures(CoreMetrics.PACKAGES)).thenReturn(Arrays.asList( + new Measure(CoreMetrics.PACKAGES, 1.0), + new Measure(CoreMetrics.PACKAGES, 1.0) + )); + decorator.decorate(project, context); + verify(context, never()).saveMeasure(eq(CoreMetrics.DIRECTORIES), anyDouble()); + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/compute/FilesDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/compute/FilesDecoratorTest.java new file mode 100644 index 00000000000..f750aebcdde --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/compute/FilesDecoratorTest.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.batch.compute; + +import java.util.Arrays; +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 static org.assertj.core.api.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)); + } + +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/compute/ItBranchCoverageDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/compute/ItBranchCoverageDecoratorTest.java new file mode 100644 index 00000000000..0e5b70a37e3 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/compute/ItBranchCoverageDecoratorTest.java @@ -0,0 +1,72 @@ +/* + * 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.batch.compute; + +import org.junit.Before; +import org.junit.Test; +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.Scopes; + +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.verify; +import static org.mockito.Mockito.when; + +public class ItBranchCoverageDecoratorTest { + private final ItBranchCoverageDecorator decorator = new ItBranchCoverageDecorator(); + private final Project resource = mock(Project.class); + + @Before + public void setUp() { + when(resource.getScope()).thenReturn(Scopes.PROJECT); + when(resource.getQualifier()).thenReturn(Qualifiers.PROJECT); + } + + @Test + public void shouldSaveBranchCoverage() { + DecoratorContext context = mockContext(20, 15); + + decorator.decorate(resource, context); + + verify(context).saveMeasure(CoreMetrics.IT_BRANCH_COVERAGE, 25.0); + } + + @Test + public void shouldNotSaveBranchCoverageIfMissingConditions() { + DecoratorContext context = mock(DecoratorContext.class); + + decorator.decorate(resource, context); + + verify(context, never()).saveMeasure(eq(CoreMetrics.IT_BRANCH_COVERAGE), anyDouble()); + } + + private static DecoratorContext mockContext(int conditions, int uncoveredConditions) { + DecoratorContext context = mock(DecoratorContext.class); + when(context.getMeasure(CoreMetrics.IT_CONDITIONS_TO_COVER)).thenReturn(new Measure(CoreMetrics.IT_CONDITIONS_TO_COVER, (double) conditions)); + when(context.getMeasure(CoreMetrics.IT_UNCOVERED_CONDITIONS)).thenReturn(new Measure(CoreMetrics.IT_UNCOVERED_CONDITIONS, (double) uncoveredConditions)); + return context; + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/compute/ItCoverageDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/compute/ItCoverageDecoratorTest.java new file mode 100644 index 00000000000..839577fb1aa --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/compute/ItCoverageDecoratorTest.java @@ -0,0 +1,142 @@ +/* + * 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.batch.compute; + +import java.util.Collection; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.Metric; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Scopes; + +import static org.assertj.core.api.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.verify; +import static org.mockito.Mockito.when; + +public class ItCoverageDecoratorTest { + private final ItCoverageDecorator decorator = new ItCoverageDecorator(); + private final Project project = mock(Project.class); + + @Before + public void before() { + when(project.getScope()).thenReturn(Scopes.PROJECT); + } + + @Test + public void should_use_metrics() { + Collection metrics = decorator.usedMetrics(); + + assertThat(metrics).containsOnly(CoreMetrics.IT_LINES_TO_COVER, CoreMetrics.IT_UNCOVERED_LINES, CoreMetrics.NEW_IT_LINES_TO_COVER, + CoreMetrics.NEW_IT_UNCOVERED_LINES, CoreMetrics.IT_CONDITIONS_TO_COVER, CoreMetrics.IT_UNCOVERED_CONDITIONS, + CoreMetrics.NEW_IT_CONDITIONS_TO_COVER, CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS); + } + + @Test + public void coverage() { + DecoratorContext context = mockContext(50, 40, 10, 8); + + decorator.decorate(project, context); + + // (50-40 covered lines + 10-8 covered conditions) / (50 lines + 10 conditions) + verify(context).saveMeasure(CoreMetrics.IT_COVERAGE, 20.0); + } + + @Test + public void coverageCanBe0() { + DecoratorContext context = mockContext(50, 50, 5, 5); + + decorator.decorate(project, context); + + verify(context).saveMeasure(CoreMetrics.IT_COVERAGE, 0.0); + } + + @Test + public void coverageCanBe100() { + DecoratorContext context = mockContext(50, 0, 5, 0); + + decorator.decorate(project, context); + + verify(context).saveMeasure(CoreMetrics.IT_COVERAGE, 100.0); + } + + @Test + public void noCoverageIfNoElements() { + DecoratorContext context = mock(DecoratorContext.class); + + decorator.decorate(project, context); + + verify(context, never()).saveMeasure(eq(CoreMetrics.IT_COVERAGE), anyDouble()); + } + + @Test + public void should_count_elements_for_new_code() { + Measure newLines = measureWithVariation(1, 100.0); + Measure newConditions = measureWithVariation(1, 1.0); + DecoratorContext context = mockNewContext(newLines, null, null, newConditions); + + long count = decorator.countElementsForNewCode(context, 1); + + assertThat(count).isEqualTo(101).isEqualTo(100 + 1); + } + + @Test + public void should_count_covered_elements_for_new_code() { + Measure newLines = measureWithVariation(1, 100.0); + Measure newUncoveredConditions = measureWithVariation(1, 10.0); + Measure newUncoveredLines = measureWithVariation(1, 5.0); + Measure newConditions = measureWithVariation(1, 1.0); + DecoratorContext context = mockNewContext(newLines, newUncoveredConditions, newUncoveredLines, newConditions); + + long count = decorator.countCoveredElementsForNewCode(context, 1); + + assertThat(count).isEqualTo(86).isEqualTo(100 + 1 - 10 - 5); + } + + private static DecoratorContext mockContext(int lines, int uncoveredLines, int conditions, int uncoveredConditions) { + DecoratorContext context = mock(DecoratorContext.class); + when(context.getMeasure(CoreMetrics.IT_LINES_TO_COVER)).thenReturn(new Measure(CoreMetrics.IT_LINES_TO_COVER, (double) lines)); + when(context.getMeasure(CoreMetrics.IT_UNCOVERED_LINES)).thenReturn(new Measure(CoreMetrics.IT_UNCOVERED_LINES, (double) uncoveredLines)); + when(context.getMeasure(CoreMetrics.IT_CONDITIONS_TO_COVER)).thenReturn(new Measure(CoreMetrics.IT_CONDITIONS_TO_COVER, (double) conditions)); + when(context.getMeasure(CoreMetrics.IT_UNCOVERED_CONDITIONS)).thenReturn(new Measure(CoreMetrics.IT_UNCOVERED_CONDITIONS, (double) uncoveredConditions)); + return context; + } + + private static DecoratorContext mockNewContext(Measure newLines, Measure newUncoveredConditions, Measure newUncoveredLines, Measure newConditions) { + DecoratorContext context = mock(DecoratorContext.class); + when(context.getMeasure(CoreMetrics.NEW_IT_LINES_TO_COVER)).thenReturn(newLines); + when(context.getMeasure(CoreMetrics.NEW_IT_UNCOVERED_LINES)).thenReturn(newUncoveredLines); + when(context.getMeasure(CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS)).thenReturn(newUncoveredConditions); + when(context.getMeasure(CoreMetrics.NEW_IT_CONDITIONS_TO_COVER)).thenReturn(newConditions); + return context; + } + + private static Measure measureWithVariation(int period, double variation) { + Measure measure = mock(Measure.class); + when(measure.getVariation(period)).thenReturn(variation); + return measure; + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/compute/ItLineCoverageDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/compute/ItLineCoverageDecoratorTest.java new file mode 100644 index 00000000000..95e7177b840 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/compute/ItLineCoverageDecoratorTest.java @@ -0,0 +1,99 @@ +/* + * 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.batch.compute; + +import java.util.List; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.Metric; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Scopes; + +import static org.assertj.core.api.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.verify; +import static org.mockito.Mockito.when; + +public class ItLineCoverageDecoratorTest { + private final ItLineCoverageDecorator decorator = new ItLineCoverageDecorator(); + private final Project project = mock(Project.class); + + @Before + public void before() { + when(project.getScope()).thenReturn(Scopes.PROJECT); + } + + @Test + public void should_depend_on_coverage_metrics() { + List metrics = decorator.dependsUponMetrics(); + + assertThat(metrics).containsOnly(CoreMetrics.IT_UNCOVERED_LINES, CoreMetrics.IT_LINES_TO_COVER, CoreMetrics.NEW_IT_UNCOVERED_LINES, CoreMetrics.NEW_IT_LINES_TO_COVER); + } + + @Test + public void lineCoverage() { + DecoratorContext context = mockContext(50, 10); + + decorator.decorate(project, context); + + // 50-10 covered lines / 50 lines + verify(context).saveMeasure(CoreMetrics.IT_LINE_COVERAGE, 80.0); + } + + @Test + public void zeroCoveredLines() { + DecoratorContext context = mockContext(50, 50); + + decorator.decorate(project, context); + + verify(context).saveMeasure(CoreMetrics.IT_LINE_COVERAGE, 0.0); + } + + @Test + public void allCoveredLines() { + DecoratorContext context = mockContext(50, 00); + + decorator.decorate(project, context); + + verify(context).saveMeasure(CoreMetrics.IT_LINE_COVERAGE, 100.0); + } + + @Test + public void noLineCoverageIfNoLines() { + DecoratorContext context = mock(DecoratorContext.class); + + decorator.decorate(project, context); + + verify(context, never()).saveMeasure(eq(CoreMetrics.IT_LINE_COVERAGE), anyDouble()); + } + + private static DecoratorContext mockContext(int lines, int uncoveredLines) { + DecoratorContext context = mock(DecoratorContext.class); + when(context.getMeasure(CoreMetrics.IT_LINES_TO_COVER)).thenReturn(new Measure(CoreMetrics.IT_LINES_TO_COVER, (double) lines)); + when(context.getMeasure(CoreMetrics.IT_UNCOVERED_LINES)).thenReturn(new Measure(CoreMetrics.IT_UNCOVERED_LINES, (double) uncoveredLines)); + return context; + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/compute/LineCoverageDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/compute/LineCoverageDecoratorTest.java new file mode 100644 index 00000000000..2a49f83aaf4 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/compute/LineCoverageDecoratorTest.java @@ -0,0 +1,98 @@ +/* + * 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.batch.compute; + +import org.junit.Before; +import org.junit.Test; +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.Scopes; + +import static org.assertj.core.api.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.verify; +import static org.mockito.Mockito.when; + +public class LineCoverageDecoratorTest { + + private LineCoverageDecorator decorator; + private final Project project = mock(Project.class); + + @Before + public void before() { + when(project.getScope()).thenReturn(Scopes.PROJECT); + decorator = new LineCoverageDecorator(); + } + + @Test + public void should_depend_on_coverage_metrics() { + assertThat(decorator.dependsUponMetrics()).containsOnly(CoreMetrics.UNCOVERED_LINES, CoreMetrics.LINES_TO_COVER, CoreMetrics.NEW_UNCOVERED_LINES, + CoreMetrics.NEW_LINES_TO_COVER); + } + + @Test + public void lineCoverage() { + DecoratorContext context = mockContext(50, 10); + + decorator.decorate(project, context); + + // 50-10 covered lines / 50 lines + verify(context).saveMeasure(CoreMetrics.LINE_COVERAGE, 80.0); + } + + @Test + public void zeroCoveredLines() { + DecoratorContext context = mockContext(50, 50); + + decorator.decorate(project, context); + + verify(context).saveMeasure(CoreMetrics.LINE_COVERAGE, 0.0); + } + + @Test + public void allCoveredLines() { + DecoratorContext context = mockContext(50, 00); + + decorator.decorate(project, context); + + verify(context).saveMeasure(CoreMetrics.LINE_COVERAGE, 100.0); + } + + @Test + public void noLineCoverageIfNoLines() { + DecoratorContext context = mock(DecoratorContext.class); + + decorator.decorate(project, context); + + verify(context, never()).saveMeasure(eq(CoreMetrics.LINE_COVERAGE), anyDouble()); + } + + private static DecoratorContext mockContext(int lines, int uncoveredLines) { + DecoratorContext context = mock(DecoratorContext.class); + when(context.getMeasure(CoreMetrics.LINES_TO_COVER)).thenReturn(new Measure(CoreMetrics.LINES_TO_COVER, (double) lines)); + when(context.getMeasure(CoreMetrics.UNCOVERED_LINES)).thenReturn(new Measure(CoreMetrics.UNCOVERED_LINES, (double) uncoveredLines)); + return context; + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/compute/ManualMeasureDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/compute/ManualMeasureDecoratorTest.java new file mode 100644 index 00000000000..bd86438ad05 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/compute/ManualMeasureDecoratorTest.java @@ -0,0 +1,52 @@ +/* + * 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.batch.compute; + +import org.junit.Test; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.measures.Metric; +import org.sonar.api.resources.File; +import org.sonar.api.test.IsMeasure; +import org.sonar.core.metric.DefaultMetricFinder; +import org.sonar.jpa.test.AbstractDbUnitTestCase; + +import static org.mockito.Matchers.argThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +public class ManualMeasureDecoratorTest extends AbstractDbUnitTestCase { + + private Metric reviewNote = new Metric.Builder("review_note", "Note", Metric.ValueType.FLOAT).create().setId(2); + + @Test + public void testCopyManualMeasures() throws Exception { + setupData("testCopyManualMeasures"); + + File javaFile = File.create("Foo.java"); + javaFile.setId(40); + + ManualMeasureDecorator decorator = new ManualMeasureDecorator(getSession(), new DefaultMetricFinder(getSessionFactory())); + DecoratorContext context = mock(DecoratorContext.class); + decorator.decorate(javaFile, context); + + verify(context).saveMeasure(argThat(new IsMeasure(reviewNote, 6.0, "six"))); + } + +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/compute/NewCoverageAggregatorTest.java b/sonar-batch/src/test/java/org/sonar/batch/compute/NewCoverageAggregatorTest.java new file mode 100644 index 00000000000..7951e3a7add --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/compute/NewCoverageAggregatorTest.java @@ -0,0 +1,90 @@ +/* + * 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.batch.compute; + +import java.util.Arrays; +import java.util.Collections; +import org.junit.Test; +import org.mockito.ArgumentMatcher; +import org.mockito.Matchers; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; + +import static org.mockito.Matchers.argThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class NewCoverageAggregatorTest { + + @Test + public void shouldNotSaveDataWhenNoMeasures() { + NewCoverageAggregator aggregator = new NewCoverageAggregator(); + DecoratorContext context = mock(DecoratorContext.class); + when(context.getChildrenMeasures(CoreMetrics.NEW_LINES_TO_COVER)).thenReturn(Collections.emptyList()); + + aggregator.aggregate(context, CoreMetrics.NEW_LINES_TO_COVER, 3); + + verify(context, never()).saveMeasure(Matchers.anyObject()); + } + + @Test + public void shouldNotsetZeroWhenNoValueOnPeriod() { + NewCoverageAggregator aggregator = new NewCoverageAggregator(); + DecoratorContext context = mock(DecoratorContext.class); + when(context.getChildrenMeasures(CoreMetrics.NEW_LINES_TO_COVER)).thenReturn(Arrays.asList(newMeasure(null, 3.0, 2.0), newMeasure(null, 13.0, null))); + + aggregator.aggregate(context, CoreMetrics.NEW_LINES_TO_COVER, 3); + + verify(context).saveMeasure(argThat(new ArgumentMatcher() { + @Override + public boolean matches(Object o) { + Measure m = (Measure) o; + return m.getVariation1() == null; + } + })); + } + + @Test + public void shouldSumValues() { + NewCoverageAggregator aggregator = new NewCoverageAggregator(); + DecoratorContext context = mock(DecoratorContext.class); + when(context.getChildrenMeasures(CoreMetrics.NEW_LINES_TO_COVER)).thenReturn(Arrays.asList(newMeasure(null, 3.0, 2.0), newMeasure(null, 13.0, null))); + + aggregator.aggregate(context, CoreMetrics.NEW_LINES_TO_COVER, 3); + + verify(context).saveMeasure(argThat(new ArgumentMatcher() { + @Override + public boolean matches(Object o) { + Measure m = (Measure) o; + return m.getVariation2() == 16.0 && m.getVariation3() == 2.0; + } + })); + } + + private Measure newMeasure(Double variation1, Double variation2, Double variation3) { + return new Measure(CoreMetrics.NEW_LINES_TO_COVER) + .setVariation1(variation1) + .setVariation2(variation2) + .setVariation3(variation3); + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/compute/NewCoverageFileAnalyzerTest.java b/sonar-batch/src/test/java/org/sonar/batch/compute/NewCoverageFileAnalyzerTest.java new file mode 100644 index 00000000000..6deb673fa50 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/compute/NewCoverageFileAnalyzerTest.java @@ -0,0 +1,297 @@ +/* + * 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.batch.compute; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.mockito.ArgumentMatcher; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.Metric; +import org.sonar.api.resources.File; +import org.sonar.api.resources.Resource; +import org.sonar.api.utils.DateUtils; +import org.sonar.batch.index.BatchComponentCache; +import org.sonar.batch.protocol.output.BatchReport; +import org.sonar.batch.protocol.output.BatchReport.Changesets.Changeset; +import org.sonar.batch.protocol.output.BatchReportWriter; +import org.sonar.batch.report.ReportPublisher; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.argThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class NewCoverageFileAnalyzerTest { + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + private DecoratorContext context; + private NewCoverageFileAnalyzer decorator; + private BatchReportWriter writer; + + @Before + public void prepare() throws Exception { + context = mock(DecoratorContext.class); + Resource f = File.create("src/Foo.java").setEffectiveKey("foo:src/Foo.java"); + when(context.getResource()).thenReturn(f); + BatchComponentCache cache = new BatchComponentCache(); + cache.add(f, null); + List structs = Arrays.asList( + new AbstractNewCoverageFileAnalyzer.PeriodStruct(1, newDate("2009-12-25")), + new AbstractNewCoverageFileAnalyzer.PeriodStruct(3, newDate("2011-02-18"))); + ReportPublisher publishReportJob = mock(ReportPublisher.class); + java.io.File reportBaseDir = temp.newFolder(); + when(publishReportJob.getReportDir()).thenReturn(reportBaseDir); + writer = new BatchReportWriter(reportBaseDir); + decorator = new NewCoverageFileAnalyzer(structs, publishReportJob, cache); + + } + + @Test + public void shouldDoNothingIfNoScmData() { + when(context.getMeasure(CoreMetrics.COVERAGE_LINE_HITS_DATA)) + .thenReturn(new Measure(CoreMetrics.COVERAGE_LINE_HITS_DATA, "1=10")); + + decorator.doDecorate(context); + verify(context, never()).saveMeasure(any(Measure.class)); + } + + @Test + public void shouldDoNothingIfNoCoverageData() { + writer.writeComponentChangesets(BatchReport.Changesets.newBuilder() + .setComponentRef(1) + .addChangeset(Changeset.newBuilder() + .setDate(DateUtils.parseDateTime("2008-05-18T00:00:00+0000").getTime()) + .build()) + .addChangesetIndexByLine(0) + .build()); + + decorator.doDecorate(context); + + verify(context, never()).saveMeasure(any(Measure.class)); + } + + @Test + public void shouldGetNewLines() { + when(context.getMeasure(CoreMetrics.COVERAGE_LINE_HITS_DATA)).thenReturn( + new Measure(CoreMetrics.COVERAGE_LINE_HITS_DATA, "10=2;11=3")); + writer.writeComponentChangesets(BatchReport.Changesets.newBuilder() + .setComponentRef(1) + .addChangeset(Changeset.newBuilder() + .build()) + .addChangeset(Changeset.newBuilder() + .setDate(DateUtils.parseDateTime("2007-01-15T00:00:00+0000").getTime()) + .build()) + .addChangeset(Changeset.newBuilder() + .setDate(DateUtils.parseDateTime("2011-01-01T00:00:00+0000").getTime()) + .build()) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(1) + .addChangesetIndexByLine(2) + .build()); + + decorator.doDecorate(context); + + // line 11 has been updated after date1 (2009-12-25). This line is covered. + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_LINES_TO_COVER, 1, 1.0))); + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_LINES, 1, 0.0))); + + // no line have been updated after date3 (2011-02-18) + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_LINES_TO_COVER, 3, null))); + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_LINES, 3, null))); + + // no data on other periods + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_LINES_TO_COVER, 2, null))); + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_LINES_TO_COVER, 4, null))); + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_LINES_TO_COVER, 5, null))); + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_LINES, 2, null))); + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_LINES, 4, null))); + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_LINES, 5, null))); + } + + @Test + public void shouldGetNewConditions() { + when(context.getMeasure(CoreMetrics.COVERAGE_LINE_HITS_DATA)).thenReturn( + new Measure(CoreMetrics.COVERAGE_LINE_HITS_DATA, "10=2;11=3")); + when(context.getMeasure(CoreMetrics.CONDITIONS_BY_LINE)).thenReturn( + new Measure(CoreMetrics.CONDITIONS_BY_LINE, "11=4")); + when(context.getMeasure(CoreMetrics.COVERED_CONDITIONS_BY_LINE)).thenReturn( + new Measure(CoreMetrics.COVERED_CONDITIONS_BY_LINE, "11=1")); + writer.writeComponentChangesets(BatchReport.Changesets.newBuilder() + .setComponentRef(1) + .addChangeset(Changeset.newBuilder() + .build()) + .addChangeset(Changeset.newBuilder() + .setDate(DateUtils.parseDateTime("2007-01-15T00:00:00+0000").getTime()) + .build()) + .addChangeset(Changeset.newBuilder() + .setDate(DateUtils.parseDateTime("2011-01-01T00:00:00+0000").getTime()) + .build()) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(1) + .addChangesetIndexByLine(2) + .build()); + + decorator.doDecorate(context); + + // line 11 has been updated after date1 (2009-12-25). This line has 1 covered condition amongst 4 + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_CONDITIONS_TO_COVER, 1, 4.0))); + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_CONDITIONS, 1, 3.0))); + + // no line have been updated after date3 (2011-02-18) + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_CONDITIONS_TO_COVER, 3, null))); + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_CONDITIONS, 3, null))); + + // no data on other periods + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_CONDITIONS_TO_COVER, 2, null))); + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_CONDITIONS_TO_COVER, 4, null))); + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_CONDITIONS_TO_COVER, 5, null))); + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_CONDITIONS, 2, null))); + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_CONDITIONS, 4, null))); + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_CONDITIONS, 5, null))); + } + + @Test + public void shouldNotGetNewConditionsWhenNewLineHasNoConditions() { + when(context.getMeasure(CoreMetrics.COVERAGE_LINE_HITS_DATA)).thenReturn( + new Measure(CoreMetrics.COVERAGE_LINE_HITS_DATA, "10=2;11=3")); + when(context.getMeasure(CoreMetrics.CONDITIONS_BY_LINE)).thenReturn( + new Measure(CoreMetrics.CONDITIONS_BY_LINE, "10=1")); + when(context.getMeasure(CoreMetrics.COVERED_CONDITIONS_BY_LINE)).thenReturn( + new Measure(CoreMetrics.COVERED_CONDITIONS_BY_LINE, "10=1")); + writer.writeComponentChangesets(BatchReport.Changesets.newBuilder() + .setComponentRef(1) + .addChangeset(Changeset.newBuilder() + .build()) + .addChangeset(Changeset.newBuilder() + .setDate(DateUtils.parseDateTime("2007-01-15T00:00:00+0000").getTime()) + .build()) + .addChangeset(Changeset.newBuilder() + .setDate(DateUtils.parseDateTime("2011-01-01T00:00:00+0000").getTime()) + .build()) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(1) + .addChangesetIndexByLine(2) + .build()); + + decorator.doDecorate(context); + + // line 11 has been updated after date1 (2009-12-25) but it has no conditions + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_CONDITIONS_TO_COVER, 1, 0.0))); + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_CONDITIONS, 1, 0.0))); + } + + @Test + public void shouldLeaveNullValueWhenNothingHasChanged() { + + when(context.getMeasure(CoreMetrics.COVERAGE_LINE_HITS_DATA)).thenReturn( + new Measure(CoreMetrics.COVERAGE_LINE_HITS_DATA, "2=1;3=1")); + when(context.getMeasure(CoreMetrics.CONDITIONS_BY_LINE)).thenReturn( + new Measure(CoreMetrics.CONDITIONS_BY_LINE, "2=1")); + when(context.getMeasure(CoreMetrics.COVERED_CONDITIONS_BY_LINE)).thenReturn( + new Measure(CoreMetrics.COVERED_CONDITIONS_BY_LINE, "2=1")); + writer.writeComponentChangesets(BatchReport.Changesets.newBuilder() + .setComponentRef(1) + .addChangeset(Changeset.newBuilder() + .setDate(DateUtils.parseDateTime("2008-08-02T13:56:37+0200").getTime()) + .build()) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .addChangesetIndexByLine(0) + .build()); + + decorator.doDecorate(context); + + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_LINES_TO_COVER, 1, null))); + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_LINES, 1, null))); + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_CONDITIONS_TO_COVER, 1, null))); + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_CONDITIONS, 1, null))); + + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_LINES_TO_COVER, 3, null))); + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_LINES, 3, null))); + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_CONDITIONS_TO_COVER, 3, null))); + verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_UNCOVERED_CONDITIONS, 3, null))); + } + + static class VariationMatcher extends ArgumentMatcher { + Metric metric; + int index; + Double variation; + + VariationMatcher(Metric metric, int index, Double variation) { + this.metric = metric; + this.index = index; + this.variation = variation; + } + + @Override + public boolean matches(Object o) { + Measure m = (Measure) o; + if (m.getMetric().equals(metric)) { + if ((variation == null && m.getVariation(index) == null) || + (variation != null && variation.equals(m.getVariation(index)))) { + return true; + } + } + return false; + } + } + + private Date newDate(String s) throws ParseException { + return new SimpleDateFormat(DateUtils.DATE_FORMAT).parse(s); + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/compute/OverallBranchCoverageDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/compute/OverallBranchCoverageDecoratorTest.java new file mode 100644 index 00000000000..9c5e585c969 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/compute/OverallBranchCoverageDecoratorTest.java @@ -0,0 +1,72 @@ +/* + * 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.batch.compute; + +import org.junit.Before; +import org.junit.Test; +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.Scopes; + +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.verify; +import static org.mockito.Mockito.when; + +public class OverallBranchCoverageDecoratorTest { + private final OverallBranchCoverageDecorator decorator = new OverallBranchCoverageDecorator(); + private final Project resource = mock(Project.class); + + @Before + public void setUp() { + when(resource.getScope()).thenReturn(Scopes.PROJECT); + when(resource.getQualifier()).thenReturn(Qualifiers.PROJECT); + } + + @Test + public void shouldSaveBranchCoverage() { + DecoratorContext context = mockContext(20, 15); + + decorator.decorate(resource, context); + + verify(context).saveMeasure(CoreMetrics.OVERALL_BRANCH_COVERAGE, 25.0); + } + + @Test + public void shouldNotSaveBranchCoverageIfMissingConditions() { + DecoratorContext context = mock(DecoratorContext.class); + + decorator.decorate(resource, context); + + verify(context, never()).saveMeasure(eq(CoreMetrics.OVERALL_BRANCH_COVERAGE), anyDouble()); + } + + private static DecoratorContext mockContext(int conditions, int uncoveredConditions) { + DecoratorContext context = mock(DecoratorContext.class); + when(context.getMeasure(CoreMetrics.OVERALL_CONDITIONS_TO_COVER)).thenReturn(new Measure(CoreMetrics.OVERALL_CONDITIONS_TO_COVER, (double) conditions)); + when(context.getMeasure(CoreMetrics.OVERALL_UNCOVERED_CONDITIONS)).thenReturn(new Measure(CoreMetrics.OVERALL_UNCOVERED_CONDITIONS, (double) uncoveredConditions)); + return context; + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/compute/OverallCoverageDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/compute/OverallCoverageDecoratorTest.java new file mode 100644 index 00000000000..d694227c754 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/compute/OverallCoverageDecoratorTest.java @@ -0,0 +1,142 @@ +/* + * 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.batch.compute; + +import java.util.Collection; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.Metric; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Scopes; + +import static org.assertj.core.api.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.verify; +import static org.mockito.Mockito.when; + +public class OverallCoverageDecoratorTest { + private final OverallCoverageDecorator decorator = new OverallCoverageDecorator(); + private final Project project = mock(Project.class); + + @Before + public void before() { + when(project.getScope()).thenReturn(Scopes.PROJECT); + } + + @Test + public void should_use_metrics() { + Collection metrics = decorator.usedMetrics(); + + assertThat(metrics).containsOnly(CoreMetrics.OVERALL_LINES_TO_COVER, CoreMetrics.OVERALL_UNCOVERED_LINES, CoreMetrics.NEW_OVERALL_LINES_TO_COVER, + CoreMetrics.NEW_OVERALL_UNCOVERED_LINES, CoreMetrics.OVERALL_CONDITIONS_TO_COVER, CoreMetrics.OVERALL_UNCOVERED_CONDITIONS, + CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER, CoreMetrics.NEW_OVERALL_UNCOVERED_CONDITIONS); + } + + @Test + public void coverage() { + DecoratorContext context = mockContext(50, 40, 10, 8); + + decorator.decorate(project, context); + + // (50-40 covered lines + 10-8 covered conditions) / (50 lines + 10 conditions) + verify(context).saveMeasure(CoreMetrics.OVERALL_COVERAGE, 20.0); + } + + @Test + public void coverageCanBe0() { + DecoratorContext context = mockContext(50, 50, 5, 5); + + decorator.decorate(project, context); + + verify(context).saveMeasure(CoreMetrics.OVERALL_COVERAGE, 0.0); + } + + @Test + public void coverageCanBe100() { + DecoratorContext context = mockContext(50, 0, 5, 0); + + decorator.decorate(project, context); + + verify(context).saveMeasure(CoreMetrics.OVERALL_COVERAGE, 100.0); + } + + @Test + public void noCoverageIfNoElements() { + DecoratorContext context = mock(DecoratorContext.class); + + decorator.decorate(project, context); + + verify(context, never()).saveMeasure(eq(CoreMetrics.OVERALL_COVERAGE), anyDouble()); + } + + @Test + public void should_count_elements_for_new_code() { + Measure newLines = measureWithVariation(1, 100.0); + Measure newConditions = measureWithVariation(1, 1.0); + DecoratorContext context = mockNewContext(newLines, null, null, newConditions); + + long count = decorator.countElementsForNewCode(context, 1); + + assertThat(count).isEqualTo(101).isEqualTo(100 + 1); + } + + @Test + public void should_count_covered_elements_for_new_code() { + Measure newLines = measureWithVariation(1, 100.0); + Measure newUncoveredConditions = measureWithVariation(1, 10.0); + Measure newUncoveredLines = measureWithVariation(1, 5.0); + Measure newConditions = measureWithVariation(1, 1.0); + DecoratorContext context = mockNewContext(newLines, newUncoveredConditions, newUncoveredLines, newConditions); + + long count = decorator.countCoveredElementsForNewCode(context, 1); + + assertThat(count).isEqualTo(86).isEqualTo(100 + 1 - 10 - 5); + } + + private static DecoratorContext mockContext(int lines, int uncoveredLines, int conditions, int uncoveredConditions) { + DecoratorContext context = mock(DecoratorContext.class); + when(context.getMeasure(CoreMetrics.OVERALL_LINES_TO_COVER)).thenReturn(new Measure(CoreMetrics.OVERALL_LINES_TO_COVER, (double) lines)); + when(context.getMeasure(CoreMetrics.OVERALL_UNCOVERED_LINES)).thenReturn(new Measure(CoreMetrics.OVERALL_UNCOVERED_LINES, (double) uncoveredLines)); + when(context.getMeasure(CoreMetrics.OVERALL_CONDITIONS_TO_COVER)).thenReturn(new Measure(CoreMetrics.OVERALL_CONDITIONS_TO_COVER, (double) conditions)); + when(context.getMeasure(CoreMetrics.OVERALL_UNCOVERED_CONDITIONS)).thenReturn(new Measure(CoreMetrics.OVERALL_UNCOVERED_CONDITIONS, (double) uncoveredConditions)); + return context; + } + + private static DecoratorContext mockNewContext(Measure newLines, Measure newUncoveredConditions, Measure newUncoveredLines, Measure newConditions) { + DecoratorContext context = mock(DecoratorContext.class); + when(context.getMeasure(CoreMetrics.NEW_OVERALL_LINES_TO_COVER)).thenReturn(newLines); + when(context.getMeasure(CoreMetrics.NEW_OVERALL_UNCOVERED_LINES)).thenReturn(newUncoveredLines); + when(context.getMeasure(CoreMetrics.NEW_OVERALL_UNCOVERED_CONDITIONS)).thenReturn(newUncoveredConditions); + when(context.getMeasure(CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER)).thenReturn(newConditions); + return context; + } + + private static Measure measureWithVariation(int period, double variation) { + Measure measure = mock(Measure.class); + when(measure.getVariation(period)).thenReturn(variation); + return measure; + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/compute/OverallLineCoverageDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/compute/OverallLineCoverageDecoratorTest.java new file mode 100644 index 00000000000..17d54526a35 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/compute/OverallLineCoverageDecoratorTest.java @@ -0,0 +1,100 @@ +/* + * 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.batch.compute; + +import java.util.List; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.Metric; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Scopes; + +import static org.assertj.core.api.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.verify; +import static org.mockito.Mockito.when; + +public class OverallLineCoverageDecoratorTest { + private final OverallLineCoverageDecorator decorator = new OverallLineCoverageDecorator(); + private final Project project = mock(Project.class); + + @Before + public void before() { + when(project.getScope()).thenReturn(Scopes.PROJECT); + } + + @Test + public void should_depend_on_coverage_metrics() { + List metrics = decorator.dependsUponMetrics(); + + assertThat(metrics).containsOnly(CoreMetrics.OVERALL_UNCOVERED_LINES, CoreMetrics.OVERALL_LINES_TO_COVER, CoreMetrics.NEW_OVERALL_UNCOVERED_LINES, + CoreMetrics.NEW_OVERALL_LINES_TO_COVER); + } + + @Test + public void lineCoverage() { + DecoratorContext context = mockContext(50, 10); + + decorator.decorate(project, context); + + // 50-10 covered lines / 50 lines + verify(context).saveMeasure(CoreMetrics.OVERALL_LINE_COVERAGE, 80.0); + } + + @Test + public void zeroCoveredLines() { + DecoratorContext context = mockContext(50, 50); + + decorator.decorate(project, context); + + verify(context).saveMeasure(CoreMetrics.OVERALL_LINE_COVERAGE, 0.0); + } + + @Test + public void allCoveredLines() { + DecoratorContext context = mockContext(50, 00); + + decorator.decorate(project, context); + + verify(context).saveMeasure(CoreMetrics.OVERALL_LINE_COVERAGE, 100.0); + } + + @Test + public void noLineCoverageIfNoLines() { + DecoratorContext context = mock(DecoratorContext.class); + + decorator.decorate(project, context); + + verify(context, never()).saveMeasure(eq(CoreMetrics.OVERALL_LINE_COVERAGE), anyDouble()); + } + + private static DecoratorContext mockContext(int lines, int uncoveredLines) { + DecoratorContext context = mock(DecoratorContext.class); + when(context.getMeasure(CoreMetrics.OVERALL_LINES_TO_COVER)).thenReturn(new Measure(CoreMetrics.OVERALL_LINES_TO_COVER, (double) lines)); + when(context.getMeasure(CoreMetrics.OVERALL_UNCOVERED_LINES)).thenReturn(new Measure(CoreMetrics.OVERALL_UNCOVERED_LINES, (double) uncoveredLines)); + return context; + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/compute/TimeMachineConfigurationPersisterTest.java b/sonar-batch/src/test/java/org/sonar/batch/compute/TimeMachineConfigurationPersisterTest.java new file mode 100644 index 00000000000..2c48e9c6614 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/compute/TimeMachineConfigurationPersisterTest.java @@ -0,0 +1,59 @@ +/* + * 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.batch.compute; + +import java.util.Arrays; +import org.junit.Test; +import org.sonar.api.database.model.Snapshot; +import org.sonar.api.resources.Project; +import org.sonar.api.utils.DateUtils; +import org.sonar.batch.components.PastSnapshot; +import org.sonar.batch.components.TimeMachineConfiguration; +import org.sonar.batch.index.BatchComponentCache; +import org.sonar.jpa.test.AbstractDbUnitTestCase; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class TimeMachineConfigurationPersisterTest extends AbstractDbUnitTestCase { + + @Test + public void shouldSaveConfigurationInSnapshotsTable() { + setupData("shared"); + + TimeMachineConfiguration timeMachineConfiguration = mock(TimeMachineConfiguration.class); + PastSnapshot vs1 = new PastSnapshot("days", DateUtils.parseDate("2009-01-25"), getSession().getSingleResult(Snapshot.class, "id", 100)) + .setModeParameter("30").setIndex(1); + PastSnapshot vs3 = new PastSnapshot("version", DateUtils.parseDate("2008-12-13"), getSession().getSingleResult(Snapshot.class, "id", 300)) + .setModeParameter("1.2.3").setIndex(3); + when(timeMachineConfiguration.getProjectPastSnapshots()).thenReturn(Arrays.asList(vs1, vs3)); + Snapshot projectSnapshot = getSession().getSingleResult(Snapshot.class, "id", 1000); + + BatchComponentCache resourceCache = new BatchComponentCache(); + Project project = new Project("foo"); + resourceCache.add(project, null).setSnapshot(projectSnapshot); + + TimeMachineConfigurationPersister persister = new TimeMachineConfigurationPersister(timeMachineConfiguration, resourceCache, getSession()); + + persister.persistConfiguration(project); + + checkTables("shouldSaveConfigurationInSnapshotsTable", "snapshots"); + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/compute/UnitTestDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/compute/UnitTestDecoratorTest.java new file mode 100644 index 00000000000..eb9bd93a4d1 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/compute/UnitTestDecoratorTest.java @@ -0,0 +1,87 @@ +/* + * 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.batch.compute; + +import java.util.Arrays; +import org.hamcrest.Matchers; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.Metric; +import org.sonar.api.resources.Project; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Matchers.doubleThat; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class UnitTestDecoratorTest { + + private UnitTestDecorator decorator; + private DecoratorContext context; + + @Before + public void setUp() { + decorator = new UnitTestDecorator(); + context = mock(DecoratorContext.class); + } + + @Test + public void generatesMetrics() { + assertThat(decorator.generatesMetrics()).hasSize(5); + } + + @Test + public void doNotDecorateStaticAnalysis() { + Project project = mock(Project.class); + when(project.getAnalysisType()).thenReturn(Project.AnalysisType.STATIC); + assertThat(decorator.shouldExecuteOnProject(project)).isFalse(); + + when(project.getAnalysisType()).thenReturn(Project.AnalysisType.DYNAMIC); + assertThat(decorator.shouldExecuteOnProject(project)).isTrue(); + } + + @Test + public void shouldSumChildren() { + Project project = mock(Project.class); + mockChildrenMeasures(CoreMetrics.TESTS, 3.0); + mockChildrenMeasures(CoreMetrics.TEST_ERRORS, 1.0); + mockChildrenMeasures(CoreMetrics.TEST_FAILURES, 1.0); + mockChildrenMeasures(CoreMetrics.SKIPPED_TESTS, 1.0); + mockChildrenMeasures(CoreMetrics.TEST_EXECUTION_TIME, 1.0); + + decorator.decorate(project, context); + + verify(context).saveMeasure(eq(CoreMetrics.TESTS), eq(6.0)); + verify(context).saveMeasure(eq(CoreMetrics.TEST_ERRORS), eq(2.0)); + verify(context).saveMeasure(eq(CoreMetrics.TEST_FAILURES), eq(2.0)); + verify(context).saveMeasure(eq(CoreMetrics.SKIPPED_TESTS), eq(2.0)); + verify(context).saveMeasure(eq(CoreMetrics.TEST_EXECUTION_TIME), eq(2.0)); + verify(context).saveMeasure(eq(CoreMetrics.TEST_SUCCESS_DENSITY), doubleThat(Matchers.closeTo(33.3, 0.1))); + } + + private void mockChildrenMeasures(Metric metric, double value) { + when(context.getChildrenMeasures(metric)).thenReturn(Arrays.asList(new Measure(metric, value), new Measure(metric, value))); + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/compute/VariationDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/compute/VariationDecoratorTest.java new file mode 100644 index 00000000000..21f26e09090 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/compute/VariationDecoratorTest.java @@ -0,0 +1,149 @@ +/* + * 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.batch.compute; + +import java.util.Arrays; +import java.util.Date; +import org.junit.Test; +import org.mockito.Matchers; +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.MeasuresFilter; +import org.sonar.api.measures.Metric; +import org.sonar.api.measures.MetricFinder; +import org.sonar.api.measures.RuleMeasure; +import org.sonar.api.resources.Directory; +import org.sonar.api.resources.File; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Resource; +import org.sonar.api.rules.Rule; +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.jpa.test.AbstractDbUnitTestCase; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class VariationDecoratorTest extends AbstractDbUnitTestCase { + + public static final int NCLOC_ID = 12; + public static final Metric NCLOC = new Metric("ncloc").setId(NCLOC_ID); + + public static final int COVERAGE_ID = 16; + public static final Metric COVERAGE = new Metric("coverage").setId(COVERAGE_ID); + + public static final int VIOLATIONS_ID = 17; + public static final Metric VIOLATIONS = new Metric("violations").setId(VIOLATIONS_ID); + + @Test + public void shouldComputeVariations() { + TimeMachineConfiguration timeMachineConfiguration = mock(TimeMachineConfiguration.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(File.create("foo/bar.c"))).isFalse(); + } + + @Test + public void shouldCompareAndSaveVariation() { + Resource dir = Directory.create("org/foo"); + + PastMeasuresLoader pastMeasuresLoader = mock(PastMeasuresLoader.class); + PastSnapshot pastSnapshot1 = new PastSnapshot("days", new Date()).setIndex(1); + PastSnapshot pastSnapshot3 = new PastSnapshot("days", new Date()).setIndex(3); + + // first past analysis + when(pastMeasuresLoader.getPastMeasures(dir, pastSnapshot1)).thenReturn(Arrays.asList( + new Object[] {NCLOC_ID, null, null, null, 180.0}, + new Object[] {COVERAGE_ID, null, null, null, 75.0})); + + // second past analysis + when(pastMeasuresLoader.getPastMeasures(dir, pastSnapshot3)).thenReturn(Arrays.asList( + new Object[] {NCLOC_ID, null, null, null, 240.0})); + + // current analysis + DecoratorContext context = mock(DecoratorContext.class); + Measure currentNcloc = newMeasure(NCLOC, 200.0); + Measure currentCoverage = newMeasure(COVERAGE, 80.0); + when(context.getMeasures(Matchers.anyObject())).thenReturn(Arrays.asList(currentNcloc, currentCoverage)); + + 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(context, times(3)).saveMeasure(Matchers.anyObject()); + + assertThat(currentNcloc.getVariation1()).isEqualTo(20.0); + assertThat(currentNcloc.getVariation2()).isNull(); + assertThat(currentNcloc.getVariation3()).isEqualTo(-40.0); + + assertThat(currentCoverage.getVariation1()).isEqualTo(5.0); + assertThat(currentCoverage.getVariation2()).isNull(); + assertThat(currentCoverage.getVariation3()).isNull(); + } + + @Test + public void shouldComputeVariationOfRuleMeasures() { + RuleFinder ruleFinder = mock(RuleFinder.class); + + Rule rule1 = Rule.create("repo", "rule1"); + rule1.setId(1); + Rule rule2 = Rule.create("repo", "rule2"); + rule2.setId(2); + + when(ruleFinder.findByKey(rule1.ruleKey())).thenReturn(rule1); + when(ruleFinder.findByKey(rule2.ruleKey())).thenReturn(rule2); + + Resource dir = Directory.create("org/foo"); + + PastMeasuresLoader pastMeasuresLoader = mock(PastMeasuresLoader.class); + PastSnapshot pastSnapshot1 = new PastSnapshot("days", new Date()).setIndex(1); + + // first past analysis + when(pastMeasuresLoader.getPastMeasures(dir, pastSnapshot1)).thenReturn(Arrays.asList( + new Object[] {VIOLATIONS_ID, null, null, null, 180.0},// total + new Object[] {VIOLATIONS_ID, null, null, rule1.getId(), 100.0},// rule 1 + new Object[] {VIOLATIONS_ID, null, null, rule2.getId(), 80.0})); // rule 2 + + // current analysis + DecoratorContext context = mock(DecoratorContext.class); + Measure violations = newMeasure(VIOLATIONS, 200.0); + Measure violationsRule1 = RuleMeasure.createForRule(VIOLATIONS, rule1, 130.0); + Measure violationsRule2 = RuleMeasure.createForRule(VIOLATIONS, rule2, 70.0); + when(context.getMeasures(Matchers.anyObject())).thenReturn(Arrays.asList(violations, violationsRule1, violationsRule2)); + + VariationDecorator decorator = new VariationDecorator(pastMeasuresLoader, mock(MetricFinder.class), Arrays.asList(pastSnapshot1), ruleFinder); + decorator.decorate(dir, context); + + // context updated for each variation + verify(context, times(3)).saveMeasure(Matchers.anyObject()); + + assertThat(violations.getVariation1()).isEqualTo(20.0); + } + + private Measure newMeasure(Metric metric, double value) { + return new Measure(metric, value); + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java index 41bdd9c67df..8d24834d97b 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java @@ -66,7 +66,7 @@ public class MeasuresMediumTest { .newScanTask(new File(projectDir, "sonar-project.properties")) .start(); - assertThat(result.allMeasures()).hasSize(61); + assertThat(result.allMeasures()).hasSize(90); } @Test @@ -93,7 +93,7 @@ public class MeasuresMediumTest { .build()) .start(); - assertThat(result.allMeasures()).hasSize(25); + assertThat(result.allMeasures()).hasSize(33); assertThat(result.allMeasures()).contains(new DefaultMeasure() .forMetric(CoreMetrics.LINES) diff --git a/sonar-batch/src/test/resources/org/sonar/batch/compute/ManualMeasureDecoratorTest/testCopyManualMeasures.xml b/sonar-batch/src/test/resources/org/sonar/batch/compute/ManualMeasureDecoratorTest/testCopyManualMeasures.xml new file mode 100644 index 00000000000..0307f16e6e3 --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/compute/ManualMeasureDecoratorTest/testCopyManualMeasures.xml @@ -0,0 +1,11 @@ + + \ No newline at end of file diff --git a/sonar-batch/src/test/resources/org/sonar/batch/compute/ProjectLinksSensorTest/shouldDeleteMissingLinks.xml b/sonar-batch/src/test/resources/org/sonar/batch/compute/ProjectLinksSensorTest/shouldDeleteMissingLinks.xml new file mode 100644 index 00000000000..836bb4630e9 --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/compute/ProjectLinksSensorTest/shouldDeleteMissingLinks.xml @@ -0,0 +1,10 @@ + + + 4.0.0 + org.codehaus.sonar + sonar + pom + 1.8-SNAPSHOT + + \ No newline at end of file diff --git a/sonar-batch/src/test/resources/org/sonar/batch/compute/ProjectLinksSensorTest/shouldSaveLinks.xml b/sonar-batch/src/test/resources/org/sonar/batch/compute/ProjectLinksSensorTest/shouldSaveLinks.xml new file mode 100644 index 00000000000..a44ea429019 --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/compute/ProjectLinksSensorTest/shouldSaveLinks.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + org.codehaus.sonar + sonar + pom + 1.8-SNAPSHOT + http://sonar.codehaus.org + + + SonarSource SA + http://www.sonarsource.com + + 2009 + + + jira + http://jira.codehaus.org/browse/SONAR + + + + + Sonar users mailing list + http://xircles.codehaus.org/projects/sonar/lists + http://xircles.codehaus.org/projects/sonar/lists + user@sonar.codehaus.org + http://www.nabble.com/Sonar-f30151.html + + + + + scm:svn:http://svn.codehaus.org/sonar/trunk + scm:svn:https://svn.codehaus.org/sonar/trunk + http://svn.sonar.codehaus.org + + + + bamboo + http://bamboo.ci.codehaus.org/browse/SONAR/ + + + + + GNU Lesser General Public License (LGPL), v.3 + http://www.gnu.org/licenses/lgpl.txt + repo + + + + \ No newline at end of file diff --git a/sonar-batch/src/test/resources/org/sonar/batch/compute/TimeMachineConfigurationPersisterTest/shared.xml b/sonar-batch/src/test/resources/org/sonar/batch/compute/TimeMachineConfigurationPersisterTest/shared.xml new file mode 100644 index 00000000000..70c8178d4e8 --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/compute/TimeMachineConfigurationPersisterTest/shared.xml @@ -0,0 +1,42 @@ + + + + + + + + + + diff --git a/sonar-batch/src/test/resources/org/sonar/batch/compute/TimeMachineConfigurationPersisterTest/shouldSaveConfigurationInSnapshotsTable-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/compute/TimeMachineConfigurationPersisterTest/shouldSaveConfigurationInSnapshotsTable-result.xml new file mode 100644 index 00000000000..34fdf2d4d32 --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/compute/TimeMachineConfigurationPersisterTest/shouldSaveConfigurationInSnapshotsTable-result.xml @@ -0,0 +1,42 @@ + + + + + + + + + + diff --git a/sonar-batch/src/test/resources/org/sonar/batch/compute/ViolationPersisterDecoratorTest/shared.xml b/sonar-batch/src/test/resources/org/sonar/batch/compute/ViolationPersisterDecoratorTest/shared.xml new file mode 100644 index 00000000000..519ce8d5157 --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/compute/ViolationPersisterDecoratorTest/shared.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/sonar-batch/src/test/resources/org/sonar/batch/compute/ViolationPersisterDecoratorTest/shouldCopyPermanentIdFromReferenceViolation-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/compute/ViolationPersisterDecoratorTest/shouldCopyPermanentIdFromReferenceViolation-result.xml new file mode 100644 index 00000000000..061041849aa --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/compute/ViolationPersisterDecoratorTest/shouldCopyPermanentIdFromReferenceViolation-result.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/sonar-batch/src/test/resources/org/sonar/batch/compute/ViolationPersisterDecoratorTest/shouldSaveViolations-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/compute/ViolationPersisterDecoratorTest/shouldSaveViolations-result.xml new file mode 100644 index 00000000000..f1bbc0bda6f --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/compute/ViolationPersisterDecoratorTest/shouldSaveViolations-result.xml @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/sonar-batch/src/test/resources/org/sonar/batch/compute/ViolationTrackingTest/example1-v1.txt b/sonar-batch/src/test/resources/org/sonar/batch/compute/ViolationTrackingTest/example1-v1.txt new file mode 100644 index 00000000000..1920333ddb6 --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/compute/ViolationTrackingTest/example1-v1.txt @@ -0,0 +1,12 @@ +package example1; + +public class Toto { + + public void doSomething() { + // doSomething + } + + public void doSomethingElse() { + // doSomethingElse + } +} diff --git a/sonar-batch/src/test/resources/org/sonar/batch/compute/ViolationTrackingTest/example1-v2.txt b/sonar-batch/src/test/resources/org/sonar/batch/compute/ViolationTrackingTest/example1-v2.txt new file mode 100644 index 00000000000..231532452b2 --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/compute/ViolationTrackingTest/example1-v2.txt @@ -0,0 +1,22 @@ +package example1; + +public class Toto { + + public Toto(){} + + public void doSomethingNew() { + // doSomethingNew + } + + public void doSomethingElseNew() { + // doSomethingElseNew + } + + public void doSomething() { + // doSomething + } + + public void doSomethingElse() { + // doSomethingElse + } +} diff --git a/sonar-batch/src/test/resources/org/sonar/batch/compute/ViolationTrackingTest/example2-v1.txt b/sonar-batch/src/test/resources/org/sonar/batch/compute/ViolationTrackingTest/example2-v1.txt new file mode 100644 index 00000000000..a920afe459b --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/compute/ViolationTrackingTest/example2-v1.txt @@ -0,0 +1,7 @@ +package example2; + +public class Toto { + void method1() { + System.out.println("toto"); + } +} diff --git a/sonar-batch/src/test/resources/org/sonar/batch/compute/ViolationTrackingTest/example2-v2.txt b/sonar-batch/src/test/resources/org/sonar/batch/compute/ViolationTrackingTest/example2-v2.txt new file mode 100644 index 00000000000..c5c8250cf65 --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/compute/ViolationTrackingTest/example2-v2.txt @@ -0,0 +1,16 @@ +package example2; + +public class Toto { + + void method2() { + System.out.println("toto"); + } + + void method1() { + System.out.println("toto"); + } + + void method3() { + System.out.println("toto"); + } +}