Decorators temporarily moved to package org.sonar.batch.compute of sonar-batch.
<artifactId>jfreechart</artifactId>
<scope>provided</scope>
</dependency>
- <dependency>
- <groupId>org.codehaus.sonar</groupId>
- <artifactId>sonar-batch</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
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(
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());
+++ /dev/null
-/*
- * 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();
- }
-}
+++ /dev/null
-/*
- * 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<Metric> generatesIssuesMetrics() {
- return ImmutableList.<Metric>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<Issue> issues = issuable.issues();
- boolean shouldSaveNewMetrics = shouldSaveNewMetrics(context);
-
- Multiset<RulePriority> severityBag = HashMultiset.create();
- Map<RulePriority, Multiset<RuleKey>> rulesPerSeverity = Maps.newHashMap();
- ListMultimap<RulePriority, Issue> issuesPerSeverity = ArrayListMultimap.create();
- int countOpen = 0;
- int countReopened = 0;
- int countConfirmed = 0;
-
- for (Issue issue : issues) {
- severityBag.add(RulePriority.valueOf(issue.severity()));
- Multiset<RuleKey> 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<Issue> issues) {
- if (context.getMeasure(CoreMetrics.VIOLATIONS) == null) {
- Collection<Measure> childrenIssues = context.getChildrenMeasures(CoreMetrics.VIOLATIONS);
- Double sum = MeasureUtils.sum(true, childrenIssues);
- context.saveMeasure(CoreMetrics.VIOLATIONS, sum + issues.size());
- }
- }
-
- private void saveNewIssues(DecoratorContext context, Collection<Issue> issues, boolean shouldSaveNewMetrics) {
- if (shouldSaveNewMetrics) {
- Measure measure = new Measure(CoreMetrics.NEW_VIOLATIONS);
- saveNewIssues(context, measure, issues);
- }
- }
-
- private void saveIssuesForSeverity(DecoratorContext context, RulePriority ruleSeverity, Multiset<RulePriority> severitiesBag) {
- Metric metric = SeverityUtils.severityToIssueMetric(ruleSeverity);
- if (context.getMeasure(metric) == null) {
- Collection<Measure> 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<RulePriority, Issue> 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<RulePriority, Multiset<RuleKey>> rulesPerSeverity) {
- Metric metric = SeverityUtils.severityToIssueMetric(severity);
-
- Collection<Measure> 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<RuleKey> rulesBag = initRules(rulesPerSeverity, severity);
- rulesBag.add(ruleKey, childRuleMeasure.getIntValue());
- }
- }
-
- Multiset<RuleKey> rulesBag = rulesPerSeverity.get(severity);
- if (rulesBag != null) {
- for (Multiset.Entry<RuleKey> 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<Issue> issues, boolean shouldSaveNewMetrics) {
- if (shouldSaveNewMetrics) {
- Metric metric = SeverityUtils.severityToNewMetricIssue(severity);
- ListMultimap<RuleKey, Measure> childMeasuresPerRuleKeys = ArrayListMultimap.create();
- ListMultimap<RuleKey, Issue> issuesPerRuleKeys = ArrayListMultimap.create();
- Set<RuleKey> ruleKeys = Sets.newHashSet();
-
- Collection<Measure> 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<Issue> issues) {
- for (Period period : timeMachineConfiguration.periods()) {
- int variationIndex = period.getIndex();
- Collection<Measure> 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<RuleKey> initRules(Map<RulePriority, Multiset<RuleKey>> rulesPerSeverity, RulePriority severity) {
- Multiset<RuleKey> rulesBag = rulesPerSeverity.get(severity);
- if (rulesBag == null) {
- rulesBag = HashMultiset.create();
- rulesPerSeverity.put(severity, rulesBag);
- }
- return rulesBag;
- }
-
- private int countIssues(Collection<Issue> 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<Issue> 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();
- }
-}
+++ /dev/null
-/*
- * 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;
- }
-}
+++ /dev/null
-/*
- * 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<String> 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);
- }
-
-}
+++ /dev/null
-/*
- * 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<Metric> 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);
-}
+++ /dev/null
-/*
- * 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<Metric> 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;
- }
-}
+++ /dev/null
-/*
- * 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<Metric> dependsUponMetrics() {
- return Arrays.<Metric>asList(CoreMetrics.NCLOC, CoreMetrics.COMMENT_LINES, CoreMetrics.PUBLIC_API, CoreMetrics.PUBLIC_UNDOCUMENTED_API);
- }
-
- @DependedUpon
- public List<Metric> generatesMetrics() {
- return Arrays.<Metric>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();
- }
-}
+++ /dev/null
-/*
- * 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<Metric> 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;
- }
-}
+++ /dev/null
-/*
- * 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<Measure> childrenMeasures = context.getChildrenMeasures(CoreMetrics.DIRECTORIES);
- Double sum = MeasureUtils.sum(false, childrenMeasures);
- if (sum != null) {
- context.saveMeasure(CoreMetrics.DIRECTORIES, sum);
- }
- }
- }
-}
+++ /dev/null
-/*
- * 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<Measure> childrenMeasures = context.getChildrenMeasures(CoreMetrics.FILES);
- Double sum = MeasureUtils.sum(false, childrenMeasures);
- if (sum != null) {
- context.saveMeasure(CoreMetrics.FILES, sum);
- }
- }
- }
-}
+++ /dev/null
-/*
- * 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<Metric> dependsUponMetrics() {
- return ImmutableList.<Metric>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;
- }
-}
+++ /dev/null
-/*
- * 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<Metric> usedMetrics() {
- return ImmutableList.<Metric>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;
- }
-}
+++ /dev/null
-/*
- * 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<Metric> dependsUponMetrics() {
- return ImmutableList.<Metric>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;
- }
-}
+++ /dev/null
-/*
- * 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<Metric> 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;
- }
-}
+++ /dev/null
-/*
- * 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<ManualMeasure> 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();
- }
-}
+++ /dev/null
-/*
- * 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<Metric> dependsUponMetrics() {
- return ImmutableList.<Metric>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;
- }
-}
+++ /dev/null
-/*
- * 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<Metric> usedMetrics() {
- return ImmutableList.<Metric>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;
- }
-}
+++ /dev/null
-/*
- * 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<Metric> dependsUponMetrics() {
- return ImmutableList.<Metric>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;
- }
-}
+++ /dev/null
-/*
- * 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<Metric> generatesMetrics() {
- return Arrays.<Metric>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<Measure> 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();
- }
-}
+++ /dev/null
-/*
- * 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<PeriodStruct> structs;
- private final ReportPublisher publishReportJob;
- private final BatchComponentCache resourceCache;
-
- public AbstractNewCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration, ReportPublisher publishReportJob, BatchComponentCache resourceCache) {
- this(Lists.<PeriodStruct>newArrayList(), publishReportJob, resourceCache);
- for (Period period : timeMachineConfiguration.periods()) {
- structs.add(new PeriodStruct(period.getIndex(), period.getDate()));
- }
- }
-
- AbstractNewCoverageFileAnalyzer(List<PeriodStruct> 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<Metric> dependsOnMetrics() {
-
- return Arrays.asList(getCoverageLineHitsDataMetric(), getConditionsByLineMetric(), getCoveredConditionsByLineMetric());
- }
-
- @DependedUpon
- public List<Metric> 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<Integer, Integer> hitsByLine = parseCountByLine(hitsByLineMeasure);
- Map<Integer, Integer> conditionsByLine = parseCountByLine(context.getMeasure(getConditionsByLineMetric()));
- Map<Integer, Integer> coveredConditionsByLine = parseCountByLine(context.getMeasure(getCoveredConditionsByLineMetric()));
-
- reset();
-
- for (Map.Entry<Integer, Integer> 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<Integer, Integer> 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;
- }
- }
-}
+++ /dev/null
-/*
- * 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<Metric> generatesNewCoverageMetrics() {
- return Arrays.<Metric>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);
- }
-}
+++ /dev/null
-/*
- * 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<PeriodStruct> 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;
- }
-}
+++ /dev/null
-/*
- * 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;
- }
-}
+++ /dev/null
-/*
- * 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;
- }
-}
+++ /dev/null
-/*
- * 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<PastSnapshot> 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()));
- }
-}
+++ /dev/null
-/*
- * 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<PastSnapshot> 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<PastSnapshot> 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<Metric> 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<Object[]> pastMeasures = pastMeasuresLoader.getPastMeasures(resource, pastSnapshot);
- compareWithPastMeasures(context, pastSnapshot.getIndex(), pastMeasures);
- }
-
- private void compareWithPastMeasures(DecoratorContext context, int index, List<Object[]> pastMeasures) {
- Map<MeasureKey, Object[]> 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;
- }
- }
-}
+++ /dev/null
-/*
- * 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;
public class CorePluginTest {
@Test
public void should_define_extensions() {
- assertThat(new CorePlugin().getExtensions().size()).isGreaterThan(10);
+ assertThat(new CorePlugin().getExtensions().size()).isGreaterThan(2);
}
}
+++ /dev/null
-/*
- * 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.<Issue>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);
- }
-}
+++ /dev/null
-/*
- * 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.<Measure>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.<Measure>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.<Issue>newArrayList());
- when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.<Measure>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.<Issue>newArrayList());
- when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.<Measure>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.<Measure>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<Issue> 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<Issue> 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<Issue> 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<Issue> createIssues() {
- List<Issue> 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<Issue> createIssuesForNewMetrics() {
- List<Issue> 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<Measure> {
- 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<Measure> {
- 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<Measure> {
- 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());
- }
- }
-}
+++ /dev/null
-/*
- * 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);
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
-}
+++ /dev/null
-/*
- * 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)));
- }
-}
+++ /dev/null
-/*
- * 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<Metric> 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;
- }
-}
+++ /dev/null
-/*
- * 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.<Measure>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.<Measure>emptyList());
- when(context.getChildrenMeasures(CoreMetrics.PACKAGES)).thenReturn(Arrays.<Measure>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());
- }
-}
+++ /dev/null
-/*
- * 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));
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
-}
+++ /dev/null
-/*
- * 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<Metric> 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;
- }
-}
+++ /dev/null
-/*
- * 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<Metric> 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;
- }
-}
+++ /dev/null
-/*
- * 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;
- }
-}
+++ /dev/null
-/*
- * 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")));
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
-}
+++ /dev/null
-/*
- * 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<Metric> 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;
- }
-}
+++ /dev/null
-/*
- * 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<Metric> 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;
- }
-}
+++ /dev/null
-/*
- * 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)));
- }
-}
+++ /dev/null
-/*
- * 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.<Measure>emptyList());
-
- aggregator.aggregate(context, CoreMetrics.NEW_LINES_TO_COVER, 3);
-
- verify(context, never()).saveMeasure(Matchers.<Measure>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<Measure>() {
- @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<Measure>() {
- @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);
- }
-}
+++ /dev/null
-/*
- * 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<AbstractNewCoverageFileAnalyzer.PeriodStruct> 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<Measure> {
- 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);
- }
-}
+++ /dev/null
-/*
- * 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");
- }
-}
+++ /dev/null
-/*
- * 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.<Object[]>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.<MeasuresFilter>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.<Measure>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.<MeasuresFilter>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.<Measure>anyObject());
-
- assertThat(violations.getVariation1()).isEqualTo(20.0);
- }
-
- private Measure newMeasure(Metric metric, double value) {
- return new Measure(metric, value);
- }
-}
+++ /dev/null
-<dataset>
- <metrics delete_historical_data="[null]" id="1" NAME="ncloc" VAL_TYPE="INT" DESCRIPTION="[null]" domain="[null]" short_name=""
- enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
- <metrics delete_historical_data="[null]" id="2" NAME="review_note" VAL_TYPE="INT" DESCRIPTION="[null]" domain="[null]" short_name=""
- enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
-
-
- <manual_measures id="1" metric_id="2" resource_id="30" value="3.14" text_value="pi" created_at="[null]" updated_at="[null]" description="this is pi" user_login="me"/>
- <manual_measures id="2" metric_id="2" resource_id="40" value="6" text_value="six" created_at="[null]" updated_at="[null]" description="this is six" user_login="me"/>
-
-</dataset>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>org.codehaus.sonar</groupId>
- <artifactId>sonar</artifactId>
- <packaging>pom</packaging>
- <version>1.8-SNAPSHOT</version>
-
-</project>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>org.codehaus.sonar</groupId>
- <artifactId>sonar</artifactId>
- <packaging>pom</packaging>
- <version>1.8-SNAPSHOT</version>
- <url>http://sonar.codehaus.org</url>
-
- <organization>
- <name>SonarSource SA</name>
- <url>http://www.sonarsource.com</url>
- </organization>
- <inceptionYear>2009</inceptionYear>
-
- <issueManagement>
- <system>jira</system>
- <url>http://jira.codehaus.org/browse/SONAR</url>
- </issueManagement>
-
- <mailingLists>
- <mailingList>
- <name>Sonar users mailing list</name>
- <subscribe>http://xircles.codehaus.org/projects/sonar/lists</subscribe>
- <unsubscribe>http://xircles.codehaus.org/projects/sonar/lists</unsubscribe>
- <post>user@sonar.codehaus.org</post>
- <archive>http://www.nabble.com/Sonar-f30151.html</archive>
- </mailingList>
- </mailingLists>
-
- <scm>
- <connection>scm:svn:http://svn.codehaus.org/sonar/trunk</connection>
- <developerConnection>scm:svn:https://svn.codehaus.org/sonar/trunk</developerConnection>
- <url>http://svn.sonar.codehaus.org</url>
- </scm>
-
- <ciManagement>
- <system>bamboo</system>
- <url>http://bamboo.ci.codehaus.org/browse/SONAR/</url>
- </ciManagement>
-
- <licenses>
- <license>
- <name>GNU Lesser General Public License (LGPL), v.3</name>
- <url>http://www.gnu.org/licenses/lgpl.txt</url>
- <distribution>repo</distribution>
- </license>
- </licenses>
-
-</project>
\ No newline at end of file
+++ /dev/null
-<dataset>
- <snapshots purge_status="[null]"
- period1_mode="[null]" period1_param="[null]" period1_date="[null]"
- period2_mode="[null]" period2_param="[null]" period2_date="[null]"
- period3_mode="[null]" period3_param="[null]" period3_date="[null]"
- period4_mode="[null]" period4_param="[null]" period4_date="[null]"
- period5_mode="[null]" period5_param="[null]" period5_date="[null]"
- id="100" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
- scope="PRJ" qualifier="TRK" created_at="1225544280000" build_date="1225544280000" version="[null]" path=""
- status="P" islast="false" depth="0" />
-
- <snapshots purge_status="[null]"
- period1_mode="[null]" period1_param="[null]" period1_date="[null]"
- period2_mode="[null]" period2_param="[null]" period2_date="[null]"
- period3_mode="[null]" period3_param="[null]" period3_date="[null]"
- period4_mode="[null]" period4_param="[null]" period4_date="[null]"
- period5_mode="[null]" period5_param="[null]" period5_date="[null]"
- id="200" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
- scope="PRJ" qualifier="TRK" created_at="1229345880000" build_date="1229345880000" version="[null]" path=""
- status="P" islast="false" depth="0" />
-
- <!-- Snapshot of previous version -->
- <snapshots purge_status="[null]"
- period1_mode="[null]" period1_param="[null]" period1_date="[null]"
- period2_mode="[null]" period2_param="[null]" period2_date="[null]"
- period3_mode="[null]" period3_param="[null]" period3_date="[null]"
- period4_mode="[null]" period4_param="[null]" period4_date="[null]"
- period5_mode="[null]" period5_param="[null]" period5_date="[null]"
- id="300" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
- scope="PRJ" qualifier="TRK" created_at="1229173080000" build_date="1229173080000" version="1.2.3" path=""
- status="P" islast="false" depth="0" />
-
- <snapshots purge_status="[null]"
- period1_mode="[null]" period1_param="[null]" period1_date="[null]"
- period2_mode="[null]" period2_param="[null]" period2_date="[null]"
- period3_mode="[null]" period3_param="[null]" period3_date="[null]"
- period4_mode="[null]" period4_param="[null]" period4_date="[null]"
- period5_mode="[null]" period5_param="[null]" period5_date="[null]"
- id="1000" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
- scope="PRJ" qualifier="TRK" created_at="1235566680000" build_date="1235566680000" version="[null]" path=""
- status="P" islast="false" depth="0" />
-</dataset>
+++ /dev/null
-<dataset>
- <snapshots purge_status="[null]"
- period1_mode="[null]" period1_param="[null]" period1_date="[null]"
- period2_mode="[null]" period2_param="[null]" period2_date="[null]"
- period3_mode="[null]" period3_param="[null]" period3_date="[null]"
- period4_mode="[null]" period4_param="[null]" period4_date="[null]"
- period5_mode="[null]" period5_param="[null]" period5_date="[null]"
- id="100" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
- scope="PRJ" qualifier="TRK" created_at="1225544280000" build_date="1225544280000" version="[null]" path=""
- status="P" islast="false" depth="0" />
-
- <snapshots purge_status="[null]"
- period1_mode="[null]" period1_param="[null]" period1_date="[null]"
- period2_mode="[null]" period2_param="[null]" period2_date="[null]"
- period3_mode="[null]" period3_param="[null]" period3_date="[null]"
- period4_mode="[null]" period4_param="[null]" period4_date="[null]"
- period5_mode="[null]" period5_param="[null]" period5_date="[null]"
- id="200" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
- scope="PRJ" qualifier="TRK" created_at="1229345880000" build_date="1229345880000" version="[null]" path=""
- status="P" islast="false" depth="0" />
-
- <!-- Snapshot of previous version -->
- <snapshots purge_status="[null]"
- period1_mode="[null]" period1_param="[null]" period1_date="[null]"
- period2_mode="[null]" period2_param="[null]" period2_date="[null]"
- period3_mode="[null]" period3_param="[null]" period3_date="[null]"
- period4_mode="[null]" period4_param="[null]" period4_date="[null]"
- period5_mode="[null]" period5_param="[null]" period5_date="[null]"
- id="300" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
- scope="PRJ" qualifier="TRK" created_at="1229173080000" build_date="1229173080000" version="1.2.3" path=""
- status="P" islast="false" depth="0" />
-
- <snapshots purge_status="[null]"
- period1_mode="days" period1_param="30" period1_date="1225544280000"
- period2_mode="[null]" period2_param="[null]" period2_date="[null]"
- period3_mode="version" period3_param="1.2.3" period3_date="1229173080000"
- period4_mode="[null]" period4_param="[null]" period4_date="[null]"
- period5_mode="[null]" period5_param="[null]" period5_date="[null]"
- id="1000" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
- scope="PRJ" qualifier="TRK" created_at="1235566680000" build_date="1235566680000" version="[null]" path=""
- status="P" islast="false" depth="0" />
-</dataset>
+++ /dev/null
-<dataset>
-
- <rules tags="[null]" system_tags="[null]" id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
- plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" status="READY"
- is_template="[false]" template_id="[null]"/>
-
- <rules tags="[null]" system_tags="[null]" id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
- plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" status="READY"
- is_template="[false]" template_id="[null]"/>
-
- <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
- name="Bar" long_name="org.foo.Bar" description="[null]"
- enabled="true" language="java" copy_resource_id="[null]" person_id="[null]" />
-
- <snapshots purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]"
- period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]"
- id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
- scope="FIL" qualifier="CLA" created_at="1225544280000" build_date="1225544280000" version="[null]" path=""
- status="U" islast="false" depth="3"/>
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <rules tags="[null]" system_tags="[null]" id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
- plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" status="READY"
- is_template="[false]" template_id="[null]"/>
-
- <rules tags="[null]" system_tags="[null]" id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
- plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" status="READY"
- is_template="[false]" template_id="[null]"/>
-
- <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
- name="Bar" long_name="org.foo.Bar" description="[null]"
- enabled="true" language="java" copy_resource_id="[null]" person_id="[null]" />
-
- <snapshots purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]"
- period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200"
- parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
- scope="FIL" qualifier="CLA" created_at="1225544280000" build_date="1225544280000" version="[null]" path=""
- status="U" islast="false" depth="3"/>
-
-</dataset>
+++ /dev/null
-<dataset>
- <rules tags="[null]" system_tags="[null]" id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
- plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" status="READY"
- is_template="[false]" template_id="[null]"/>
-
- <rules tags="[null]" system_tags="[null]" id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
- plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" status="READY"
- is_template="[false]" template_id="[null]"/>
-
- <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
- name="Bar" long_name="org.foo.Bar" description="[null]"
- enabled="true" language="java" copy_resource_id="[null]" person_id="[null]" />
-
- <snapshots purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]"
- period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200"
- parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
- scope="FIL" qualifier="CLA" created_at="1225544280000" build_date="1225544280000" version="[null]" path=""
- status="U" islast="false" depth="3"/>
-
-</dataset>
+++ /dev/null
-package example1;
-
-public class Toto {
-
- public void doSomething() {
- // doSomething
- }
-
- public void doSomethingElse() {
- // doSomethingElse
- }
-}
+++ /dev/null
-package example1;
-
-public class Toto {
-
- public Toto(){}
-
- public void doSomethingNew() {
- // doSomethingNew
- }
-
- public void doSomethingElseNew() {
- // doSomethingElseNew
- }
-
- public void doSomething() {
- // doSomething
- }
-
- public void doSomethingElse() {
- // doSomethingElse
- }
-}
+++ /dev/null
-package example2;
-
-public class Toto {
- void method1() {
- System.out.println("toto");
- }
-}
+++ /dev/null
-package example2;
-
-public class Toto {
-
- void method2() {
- System.out.println("toto");
- }
-
- void method1() {
- System.out.println("toto");
- }
-
- void method3() {
- System.out.println("toto");
- }
-}
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;
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());
--- /dev/null
+/*
+ * 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<Metric> 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);
+}
--- /dev/null
+/*
+ * 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<PeriodStruct> structs;
+ private final ReportPublisher publishReportJob;
+ private final BatchComponentCache resourceCache;
+
+ public AbstractNewCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration, ReportPublisher publishReportJob, BatchComponentCache resourceCache) {
+ this(new ArrayList<PeriodStruct>(), publishReportJob, resourceCache);
+ for (Period period : timeMachineConfiguration.periods()) {
+ structs.add(new PeriodStruct(period.getIndex(), period.getDate()));
+ }
+ }
+
+ AbstractNewCoverageFileAnalyzer(List<PeriodStruct> 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<Metric> dependsOnMetrics() {
+
+ return Arrays.asList(getCoverageLineHitsDataMetric(), getConditionsByLineMetric(), getCoveredConditionsByLineMetric());
+ }
+
+ @DependedUpon
+ public List<Metric> 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<Integer, Integer> hitsByLine = parseCountByLine(hitsByLineMeasure);
+ Map<Integer, Integer> conditionsByLine = parseCountByLine(context.getMeasure(getConditionsByLineMetric()));
+ Map<Integer, Integer> coveredConditionsByLine = parseCountByLine(context.getMeasure(getCoveredConditionsByLineMetric()));
+
+ reset();
+
+ for (Map.Entry<Integer, Integer> 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<Integer, Integer> 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;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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<String> 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);
+ }
+
+}
--- /dev/null
+/*
+ * 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<Metric> 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;
+ }
+}
--- /dev/null
+/*
+ * 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<Metric> dependsUponMetrics() {
+ return Arrays.<Metric>asList(CoreMetrics.NCLOC, CoreMetrics.COMMENT_LINES, CoreMetrics.PUBLIC_API, CoreMetrics.PUBLIC_UNDOCUMENTED_API);
+ }
+
+ @DependedUpon
+ public List<Metric> generatesMetrics() {
+ return Arrays.<Metric>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();
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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<Metric> generatesIssuesMetrics() {
+ return ImmutableList.<Metric>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<Issue> issues = issuable.issues();
+ boolean shouldSaveNewMetrics = shouldSaveNewMetrics(context);
+
+ Multiset<RulePriority> severityBag = HashMultiset.create();
+ Map<RulePriority, Multiset<RuleKey>> rulesPerSeverity = Maps.newHashMap();
+ ListMultimap<RulePriority, Issue> issuesPerSeverity = ArrayListMultimap.create();
+ int countOpen = 0;
+ int countReopened = 0;
+ int countConfirmed = 0;
+
+ for (Issue issue : issues) {
+ severityBag.add(RulePriority.valueOf(issue.severity()));
+ Multiset<RuleKey> 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<Issue> issues) {
+ if (context.getMeasure(CoreMetrics.VIOLATIONS) == null) {
+ Collection<Measure> childrenIssues = context.getChildrenMeasures(CoreMetrics.VIOLATIONS);
+ Double sum = MeasureUtils.sum(true, childrenIssues);
+ context.saveMeasure(CoreMetrics.VIOLATIONS, sum + issues.size());
+ }
+ }
+
+ private void saveNewIssues(DecoratorContext context, Collection<Issue> issues, boolean shouldSaveNewMetrics) {
+ if (shouldSaveNewMetrics) {
+ Measure measure = new Measure(CoreMetrics.NEW_VIOLATIONS);
+ saveNewIssues(context, measure, issues);
+ }
+ }
+
+ private void saveIssuesForSeverity(DecoratorContext context, RulePriority ruleSeverity, Multiset<RulePriority> severitiesBag) {
+ Metric metric = SeverityUtils.severityToIssueMetric(ruleSeverity);
+ if (context.getMeasure(metric) == null) {
+ Collection<Measure> 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<RulePriority, Issue> 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<RulePriority, Multiset<RuleKey>> rulesPerSeverity) {
+ Metric metric = SeverityUtils.severityToIssueMetric(severity);
+
+ Collection<Measure> 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<RuleKey> rulesBag = initRules(rulesPerSeverity, severity);
+ rulesBag.add(ruleKey, childRuleMeasure.getIntValue());
+ }
+ }
+
+ Multiset<RuleKey> rulesBag = rulesPerSeverity.get(severity);
+ if (rulesBag != null) {
+ for (Multiset.Entry<RuleKey> 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<Issue> issues, boolean shouldSaveNewMetrics) {
+ if (shouldSaveNewMetrics) {
+ Metric metric = SeverityUtils.severityToNewMetricIssue(severity);
+ ListMultimap<RuleKey, Measure> childMeasuresPerRuleKeys = ArrayListMultimap.create();
+ ListMultimap<RuleKey, Issue> issuesPerRuleKeys = ArrayListMultimap.create();
+ Set<RuleKey> ruleKeys = Sets.newHashSet();
+
+ Collection<Measure> 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<Issue> issues) {
+ for (Period period : timeMachineConfiguration.periods()) {
+ int variationIndex = period.getIndex();
+ Collection<Measure> 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<RuleKey> initRules(Map<RulePriority, Multiset<RuleKey>> rulesPerSeverity, RulePriority severity) {
+ Multiset<RuleKey> rulesBag = rulesPerSeverity.get(severity);
+ if (rulesBag == null) {
+ rulesBag = HashMultiset.create();
+ rulesPerSeverity.put(severity, rulesBag);
+ }
+ return rulesBag;
+ }
+
+ private int countIssues(Collection<Issue> 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<Issue> 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();
+ }
+}
--- /dev/null
+/*
+ * 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<Metric> 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;
+ }
+}
--- /dev/null
+/*
+ * 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<Measure> childrenMeasures = context.getChildrenMeasures(CoreMetrics.DIRECTORIES);
+ Double sum = MeasureUtils.sum(false, childrenMeasures);
+ if (sum != null) {
+ context.saveMeasure(CoreMetrics.DIRECTORIES, sum);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * 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<Measure> childrenMeasures = context.getChildrenMeasures(CoreMetrics.FILES);
+ Double sum = MeasureUtils.sum(false, childrenMeasures);
+ if (sum != null) {
+ context.saveMeasure(CoreMetrics.FILES, sum);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * 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<Metric> dependsUponMetrics() {
+ return ImmutableList.<Metric>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;
+ }
+}
--- /dev/null
+/*
+ * 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<Metric> usedMetrics() {
+ return ImmutableList.<Metric>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;
+ }
+}
--- /dev/null
+/*
+ * 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<Metric> dependsUponMetrics() {
+ return ImmutableList.<Metric>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;
+ }
+}
--- /dev/null
+/*
+ * 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<Metric> 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;
+ }
+}
--- /dev/null
+/*
+ * 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<ManualMeasure> 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();
+ }
+}
--- /dev/null
+/*
+ * 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<Metric> generatesNewCoverageMetrics() {
+ return Arrays.<Metric>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);
+ }
+}
--- /dev/null
+/*
+ * 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<PeriodStruct> 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;
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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<Metric> dependsUponMetrics() {
+ return ImmutableList.<Metric>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;
+ }
+}
--- /dev/null
+/*
+ * 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<Metric> usedMetrics() {
+ return ImmutableList.<Metric>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;
+ }
+}
--- /dev/null
+/*
+ * 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<Metric> dependsUponMetrics() {
+ return ImmutableList.<Metric>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;
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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<PastSnapshot> 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()));
+ }
+}
--- /dev/null
+/*
+ * 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<Metric> generatesMetrics() {
+ return Arrays.<Metric>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<Measure> 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();
+ }
+}
--- /dev/null
+/*
+ * 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<PastSnapshot> 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<PastSnapshot> 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<Metric> 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<Object[]> pastMeasures = pastMeasuresLoader.getPastMeasures(resource, pastSnapshot);
+ compareWithPastMeasures(context, pastSnapshot.getIndex(), pastMeasures);
+ }
+
+ private void compareWithPastMeasures(DecoratorContext context, int index, List<Object[]> pastMeasures) {
+ Map<MeasureKey, Object[]> 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;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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;
+
--- /dev/null
+/*
+ * 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);
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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)));
+ }
+}
--- /dev/null
+/*
+ * 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.<Issue>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);
+ }
+}
--- /dev/null
+/*
+ * 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.<Measure>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.<Measure>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.<Issue>newArrayList());
+ when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.<Measure>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.<Issue>newArrayList());
+ when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.<Measure>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.<Measure>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<Issue> 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<Issue> 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<Issue> 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<Issue> createIssues() {
+ List<Issue> 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<Issue> createIssuesForNewMetrics() {
+ List<Issue> 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<Measure> {
+ 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<Measure> {
+ 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<Measure> {
+ 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());
+ }
+ }
+}
--- /dev/null
+/*
+ * 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<Metric> 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;
+ }
+}
--- /dev/null
+/*
+ * 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.<Measure>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.<Measure>emptyList());
+ when(context.getChildrenMeasures(CoreMetrics.PACKAGES)).thenReturn(Arrays.<Measure>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());
+ }
+}
--- /dev/null
+/*
+ * 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));
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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<Metric> 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;
+ }
+}
--- /dev/null
+/*
+ * 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<Metric> 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;
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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")));
+ }
+
+}
--- /dev/null
+/*
+ * 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.<Measure>emptyList());
+
+ aggregator.aggregate(context, CoreMetrics.NEW_LINES_TO_COVER, 3);
+
+ verify(context, never()).saveMeasure(Matchers.<Measure>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<Measure>() {
+ @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<Measure>() {
+ @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);
+ }
+}
--- /dev/null
+/*
+ * 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<AbstractNewCoverageFileAnalyzer.PeriodStruct> 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<Measure> {
+ 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);
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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<Metric> 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;
+ }
+}
--- /dev/null
+/*
+ * 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<Metric> 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;
+ }
+}
--- /dev/null
+/*
+ * 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");
+ }
+}
--- /dev/null
+/*
+ * 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)));
+ }
+}
--- /dev/null
+/*
+ * 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.<Object[]>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.<MeasuresFilter>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.<Measure>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.<MeasuresFilter>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.<Measure>anyObject());
+
+ assertThat(violations.getVariation1()).isEqualTo(20.0);
+ }
+
+ private Measure newMeasure(Metric metric, double value) {
+ return new Measure(metric, value);
+ }
+}
.newScanTask(new File(projectDir, "sonar-project.properties"))
.start();
- assertThat(result.allMeasures()).hasSize(61);
+ assertThat(result.allMeasures()).hasSize(90);
}
@Test
.build())
.start();
- assertThat(result.allMeasures()).hasSize(25);
+ assertThat(result.allMeasures()).hasSize(33);
assertThat(result.allMeasures()).contains(new DefaultMeasure<Integer>()
.forMetric(CoreMetrics.LINES)
--- /dev/null
+<dataset>
+ <metrics delete_historical_data="[null]" id="1" NAME="ncloc" VAL_TYPE="INT" DESCRIPTION="[null]" domain="[null]" short_name=""
+ enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
+ <metrics delete_historical_data="[null]" id="2" NAME="review_note" VAL_TYPE="INT" DESCRIPTION="[null]" domain="[null]" short_name=""
+ enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
+
+
+ <manual_measures id="1" metric_id="2" resource_id="30" value="3.14" text_value="pi" created_at="[null]" updated_at="[null]" description="this is pi" user_login="me"/>
+ <manual_measures id="2" metric_id="2" resource_id="40" value="6" text_value="six" created_at="[null]" updated_at="[null]" description="this is six" user_login="me"/>
+
+</dataset>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar</artifactId>
+ <packaging>pom</packaging>
+ <version>1.8-SNAPSHOT</version>
+
+</project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar</artifactId>
+ <packaging>pom</packaging>
+ <version>1.8-SNAPSHOT</version>
+ <url>http://sonar.codehaus.org</url>
+
+ <organization>
+ <name>SonarSource SA</name>
+ <url>http://www.sonarsource.com</url>
+ </organization>
+ <inceptionYear>2009</inceptionYear>
+
+ <issueManagement>
+ <system>jira</system>
+ <url>http://jira.codehaus.org/browse/SONAR</url>
+ </issueManagement>
+
+ <mailingLists>
+ <mailingList>
+ <name>Sonar users mailing list</name>
+ <subscribe>http://xircles.codehaus.org/projects/sonar/lists</subscribe>
+ <unsubscribe>http://xircles.codehaus.org/projects/sonar/lists</unsubscribe>
+ <post>user@sonar.codehaus.org</post>
+ <archive>http://www.nabble.com/Sonar-f30151.html</archive>
+ </mailingList>
+ </mailingLists>
+
+ <scm>
+ <connection>scm:svn:http://svn.codehaus.org/sonar/trunk</connection>
+ <developerConnection>scm:svn:https://svn.codehaus.org/sonar/trunk</developerConnection>
+ <url>http://svn.sonar.codehaus.org</url>
+ </scm>
+
+ <ciManagement>
+ <system>bamboo</system>
+ <url>http://bamboo.ci.codehaus.org/browse/SONAR/</url>
+ </ciManagement>
+
+ <licenses>
+ <license>
+ <name>GNU Lesser General Public License (LGPL), v.3</name>
+ <url>http://www.gnu.org/licenses/lgpl.txt</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+
+</project>
\ No newline at end of file
--- /dev/null
+<dataset>
+ <snapshots purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ id="100" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1225544280000" build_date="1225544280000" version="[null]" path=""
+ status="P" islast="false" depth="0" />
+
+ <snapshots purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ id="200" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1229345880000" build_date="1229345880000" version="[null]" path=""
+ status="P" islast="false" depth="0" />
+
+ <!-- Snapshot of previous version -->
+ <snapshots purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ id="300" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1229173080000" build_date="1229173080000" version="1.2.3" path=""
+ status="P" islast="false" depth="0" />
+
+ <snapshots purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ id="1000" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1235566680000" build_date="1235566680000" version="[null]" path=""
+ status="P" islast="false" depth="0" />
+</dataset>
--- /dev/null
+<dataset>
+ <snapshots purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ id="100" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1225544280000" build_date="1225544280000" version="[null]" path=""
+ status="P" islast="false" depth="0" />
+
+ <snapshots purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ id="200" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1229345880000" build_date="1229345880000" version="[null]" path=""
+ status="P" islast="false" depth="0" />
+
+ <!-- Snapshot of previous version -->
+ <snapshots purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ id="300" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1229173080000" build_date="1229173080000" version="1.2.3" path=""
+ status="P" islast="false" depth="0" />
+
+ <snapshots purge_status="[null]"
+ period1_mode="days" period1_param="30" period1_date="1225544280000"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="version" period3_param="1.2.3" period3_date="1229173080000"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ id="1000" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1235566680000" build_date="1235566680000" version="[null]" path=""
+ status="P" islast="false" depth="0" />
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules tags="[null]" system_tags="[null]" id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
+ plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" status="READY"
+ is_template="[false]" template_id="[null]"/>
+
+ <rules tags="[null]" system_tags="[null]" id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
+ plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" status="READY"
+ is_template="[false]" template_id="[null]"/>
+
+ <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
+ name="Bar" long_name="org.foo.Bar" description="[null]"
+ enabled="true" language="java" copy_resource_id="[null]" person_id="[null]" />
+
+ <snapshots purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]"
+ period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ id="1000" project_id="200" parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
+ scope="FIL" qualifier="CLA" created_at="1225544280000" build_date="1225544280000" version="[null]" path=""
+ status="U" islast="false" depth="3"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules tags="[null]" system_tags="[null]" id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
+ plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" status="READY"
+ is_template="[false]" template_id="[null]"/>
+
+ <rules tags="[null]" system_tags="[null]" id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
+ plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" status="READY"
+ is_template="[false]" template_id="[null]"/>
+
+ <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
+ name="Bar" long_name="org.foo.Bar" description="[null]"
+ enabled="true" language="java" copy_resource_id="[null]" person_id="[null]" />
+
+ <snapshots purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]"
+ period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200"
+ parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
+ scope="FIL" qualifier="CLA" created_at="1225544280000" build_date="1225544280000" version="[null]" path=""
+ status="U" islast="false" depth="3"/>
+
+</dataset>
--- /dev/null
+<dataset>
+ <rules tags="[null]" system_tags="[null]" id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
+ plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" status="READY"
+ is_template="[false]" template_id="[null]"/>
+
+ <rules tags="[null]" system_tags="[null]" id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
+ plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" status="READY"
+ is_template="[false]" template_id="[null]"/>
+
+ <projects id="200" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar" root_id="[null]"
+ name="Bar" long_name="org.foo.Bar" description="[null]"
+ enabled="true" language="java" copy_resource_id="[null]" person_id="[null]" />
+
+ <snapshots purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]"
+ period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1000" project_id="200"
+ parent_snapshot_id="[null]" root_project_id="100" root_snapshot_id="[null]"
+ scope="FIL" qualifier="CLA" created_at="1225544280000" build_date="1225544280000" version="[null]" path=""
+ status="U" islast="false" depth="3"/>
+
+</dataset>
--- /dev/null
+package example1;
+
+public class Toto {
+
+ public void doSomething() {
+ // doSomething
+ }
+
+ public void doSomethingElse() {
+ // doSomethingElse
+ }
+}
--- /dev/null
+package example1;
+
+public class Toto {
+
+ public Toto(){}
+
+ public void doSomethingNew() {
+ // doSomethingNew
+ }
+
+ public void doSomethingElseNew() {
+ // doSomethingElseNew
+ }
+
+ public void doSomething() {
+ // doSomething
+ }
+
+ public void doSomethingElse() {
+ // doSomethingElse
+ }
+}
--- /dev/null
+package example2;
+
+public class Toto {
+ void method1() {
+ System.out.println("toto");
+ }
+}
--- /dev/null
+package example2;
+
+public class Toto {
+
+ void method2() {
+ System.out.println("toto");
+ }
+
+ void method1() {
+ System.out.println("toto");
+ }
+
+ void method3() {
+ System.out.println("toto");
+ }
+}