From 3867d47f87b70dd4aaab4a390485675a3672e5a3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=A9bastien=20Lesaint?= Date: Mon, 8 Jun 2015 16:56:11 +0200 Subject: [PATCH] SONAR-6620 add step to retrieve project's QualityGate --- .../container/ComputeEngineContainerImpl.java | 5 + .../computation/qualitygate/Condition.java | 103 +++++++++++++++ .../qualitygate/MutableQualityGateHolder.java | 36 ++++++ .../computation/qualitygate/QualityGate.java | 46 +++++++ .../qualitygate/QualityGateHolder.java | 31 +++++ .../qualitygate/QualityGateHolderImpl.java | 47 +++++++ .../qualitygate/QualityGateService.java | 29 +++++ .../qualitygate/QualityGateServiceImpl.java | 67 ++++++++++ .../computation/qualitygate/package-info.java | 24 ++++ .../computation/step/ComputationSteps.java | 2 + .../step/QualityGateLoadingStep.java | 97 +++++++++++++++ .../qualitygate/ConditionTest.java | 67 ++++++++++ .../MutableQualityGateHolderRule.java | 53 ++++++++ .../QualityGateHolderImplTest.java | 58 +++++++++ .../QualityGateServiceImplTest.java | 88 +++++++++++++ .../step/QualityGateLoadingStepTest.java | 117 ++++++++++++++++++ 16 files changed, 870 insertions(+) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/Condition.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/MutableQualityGateHolder.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGate.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGateHolder.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGateHolderImpl.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGateService.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGateServiceImpl.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/package-info.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityGateLoadingStep.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/computation/qualitygate/ConditionTest.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/computation/qualitygate/MutableQualityGateHolderRule.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/computation/qualitygate/QualityGateHolderImplTest.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/computation/qualitygate/QualityGateServiceImplTest.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/computation/step/QualityGateLoadingStepTest.java diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java index f3386a42786..959f20b081b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java @@ -53,6 +53,8 @@ import org.sonar.server.computation.measure.MeasureRepositoryImpl; import org.sonar.server.computation.measure.MetricCache; import org.sonar.server.computation.metric.MetricRepositoryImpl; import org.sonar.server.computation.period.PeriodsHolderImpl; +import org.sonar.server.computation.qualitygate.QualityGateHolderImpl; +import org.sonar.server.computation.qualitygate.QualityGateServiceImpl; import org.sonar.server.computation.step.ComputationStep; import org.sonar.server.computation.step.ComputationSteps; import org.sonar.server.view.index.ViewIndex; @@ -128,6 +130,7 @@ public class ComputeEngineContainerImpl extends ComponentContainer implements Co BatchReportDirectoryHolderImpl.class, TreeRootHolderImpl.class, PeriodsHolderImpl.class, + QualityGateHolderImpl.class, BatchReportReaderImpl.class, @@ -139,6 +142,8 @@ public class ComputeEngineContainerImpl extends ComponentContainer implements Co ProjectSettingsRepository.class, DbIdsRepository.class, + QualityGateServiceImpl.class, + // issues ScmAccountCacheLoader.class, ScmAccountCache.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/Condition.java b/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/Condition.java new file mode 100644 index 00000000000..7e18390fb5a --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/Condition.java @@ -0,0 +1,103 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.computation.qualitygate; + +import com.google.common.base.Objects; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; +import org.sonar.server.computation.metric.Metric; + +import static java.util.Objects.hash; +import static java.util.Objects.requireNonNull; + +@Immutable +public class Condition { + + private final Metric metric; + @CheckForNull + private final Integer period; + private final String operator; + @CheckForNull + private final String warningThreshold; + @CheckForNull + private final String errorThreshold; + + public Condition(Metric metric, @Nullable Integer period, + String operator, @Nullable String errorThreshold, @Nullable String warningThreshold) { + this.metric = requireNonNull(metric); + this.operator = requireNonNull(operator); + this.period = period; + this.errorThreshold = errorThreshold; + this.warningThreshold = warningThreshold; + } + + public Metric getMetric() { + return metric; + } + + @CheckForNull + public Integer getPeriod() { + return period; + } + + public String getOperator() { + return operator; + } + + @CheckForNull + public String getWarningThreshold() { + return warningThreshold; + } + + @CheckForNull + public String getErrorThreshold() { + return errorThreshold; + } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Condition that = (Condition) o; + return java.util.Objects.equals(metric, that.metric) + && java.util.Objects.equals(period, that.period); + } + + @Override + public int hashCode() { + return hash(metric, period); + } + + @Override + public String toString() { + return Objects.toStringHelper(this) + .add("metric", metric) + .add("period", period) + .add("operator", operator) + .add("warningThreshold", warningThreshold) + .add("errorThreshold", errorThreshold) + .toString(); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/MutableQualityGateHolder.java b/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/MutableQualityGateHolder.java new file mode 100644 index 00000000000..e977bfc7c29 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/MutableQualityGateHolder.java @@ -0,0 +1,36 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.computation.qualitygate; + +import org.sonar.server.computation.ReportQueue; +import org.sonar.server.computation.component.Component; + +public interface MutableQualityGateHolder extends QualityGateHolder { + /** + * Sets the quality gate for the project of the currently processed {@link ReportQueue.Item}. + * Settings a quality gate more than once is not allowed and it can never be set to {@code null}. + * + * @param qualityGate a {@link Component}, can not be {@code null} + * + * @throws NullPointerException if {@code qualityGate} is {@code null} + * @throws IllegalStateException if the quality gate has already been set + */ + void setQualityGate(QualityGate qualityGate); +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGate.java b/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGate.java new file mode 100644 index 00000000000..5978b1069c9 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGate.java @@ -0,0 +1,46 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.computation.qualitygate; + +import java.util.Objects; +import java.util.Set; +import javax.annotation.concurrent.Immutable; + +import static com.google.common.base.Predicates.notNull; +import static com.google.common.collect.FluentIterable.from; + +@Immutable +public class QualityGate { + private final String name; + private final Set conditions; + + public QualityGate(String name, Iterable conditions) { + this.name = Objects.requireNonNull(name); + this.conditions = from(conditions).filter(notNull()).toSet(); + } + + public String getName() { + return name; + } + + public Set getConditions() { + return conditions; + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGateHolder.java b/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGateHolder.java new file mode 100644 index 00000000000..bba76845499 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGateHolder.java @@ -0,0 +1,31 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.computation.qualitygate; + +import org.sonar.server.computation.ReportQueue; + +public interface QualityGateHolder { + /** + * The QualityGate for the project of the current {@link ReportQueue.Item}. + * + * @throws IllegalStateException if the holder is empty (ie. there is no quality gate yet) + */ + QualityGate getQualityGate(); +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGateHolderImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGateHolderImpl.java new file mode 100644 index 00000000000..707c7d7aea1 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGateHolderImpl.java @@ -0,0 +1,47 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.computation.qualitygate; + +import java.util.Objects; +import javax.annotation.CheckForNull; + +public class QualityGateHolderImpl implements MutableQualityGateHolder { + @CheckForNull + private QualityGate qualityGate; + + @Override + public void setQualityGate(QualityGate qualityGate) { + // fail fast + Objects.requireNonNull(qualityGate); + + if (this.qualityGate != null) { + throw new IllegalStateException("QualityGate can be set only once"); + } + this.qualityGate = qualityGate; + } + + @Override + public QualityGate getQualityGate() { + if (qualityGate == null) { + throw new IllegalStateException("QualityGate has not been set yet"); + } + return qualityGate; + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGateService.java b/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGateService.java new file mode 100644 index 00000000000..e722eedc038 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGateService.java @@ -0,0 +1,29 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.computation.qualitygate; + +import com.google.common.base.Optional; + +public interface QualityGateService { + /** + * Retrieve the {@link QualityGate} from the database with the specified id, it it exists. + */ + Optional findById(long id); +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGateServiceImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGateServiceImpl.java new file mode 100644 index 00000000000..2f3d3ef0168 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGateServiceImpl.java @@ -0,0 +1,67 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.computation.qualitygate; + +import com.google.common.base.Function; +import com.google.common.base.Optional; +import javax.annotation.Nonnull; +import org.sonar.core.qualitygate.db.QualityGateConditionDao; +import org.sonar.core.qualitygate.db.QualityGateConditionDto; +import org.sonar.core.qualitygate.db.QualityGateDao; +import org.sonar.core.qualitygate.db.QualityGateDto; +import org.sonar.server.computation.metric.Metric; +import org.sonar.server.computation.metric.MetricRepository; + +import static com.google.common.collect.FluentIterable.from; + +public class QualityGateServiceImpl implements QualityGateService { + private final QualityGateDao qualityGateDao; + private final QualityGateConditionDao conditionDao; + private final Function conditionDtoToBean; + + public QualityGateServiceImpl(QualityGateDao qualityGateDao, QualityGateConditionDao conditionDao, final MetricRepository metricRepository) { + this.qualityGateDao = qualityGateDao; + this.conditionDao = conditionDao; + this.conditionDtoToBean = new Function() { + @Override + @Nonnull + public Condition apply(@Nonnull QualityGateConditionDto input) { + Metric metric = metricRepository.getByKey(input.getMetricKey()); + return new Condition(metric, input.getPeriod(), input.getOperator(), input.getErrorThreshold(), input.getWarningThreshold()); + } + }; + } + + @Override + public Optional findById(long id) { + QualityGateDto qualityGateDto = qualityGateDao.selectById(id); + if (qualityGateDto == null) { + return Optional.absent(); + } + return Optional.of(toQualityGate(qualityGateDto)); + } + + private QualityGate toQualityGate(QualityGateDto qualityGateDto) { + Iterable conditions = from(conditionDao.selectForQualityGate(qualityGateDto.getId())).transform(conditionDtoToBean); + + return new QualityGate(qualityGateDto.getName(), conditions); + } + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/package-info.java new file mode 100644 index 00000000000..bdef32c3b7e --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +@ParametersAreNonnullByDefault +package org.sonar.server.computation.qualitygate; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java index 57396619bdb..2d13c1a1529 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java @@ -47,6 +47,8 @@ public class ComputationSteps { // Read report ParseReportStep.class, + QualityGateLoadingStep.class, + // data computation QualityProfileEventsStep.class, QualityGateEventsStep.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityGateLoadingStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityGateLoadingStep.java new file mode 100644 index 00000000000..3bfb04aa958 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityGateLoadingStep.java @@ -0,0 +1,97 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.computation.step; + +import java.util.Collections; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.config.Settings; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.sonar.server.computation.ReportQueue; +import org.sonar.server.computation.component.Component; +import org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor; +import org.sonar.server.computation.component.ProjectSettingsRepository; +import org.sonar.server.computation.component.TreeRootHolder; +import org.sonar.server.computation.qualitygate.Condition; +import org.sonar.server.computation.qualitygate.MutableQualityGateHolder; +import org.sonar.server.computation.qualitygate.QualityGate; +import org.sonar.server.computation.qualitygate.QualityGateService; + +import static org.sonar.server.computation.component.Component.Type.PROJECT; +import static org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor.Order.PRE_ORDER; + +/** + * This step retrieves the QualityGate for the current {@link ReportQueue.Item} and stores it in + * {@link MutableQualityGateHolder}. + */ +public class QualityGateLoadingStep implements ComputationStep { + private static final Logger LOGGER = Loggers.get(QualityGateLoadingStep.class); + + private static final String PROPERTY_QUALITY_GATE = "sonar.qualitygate"; + private static final QualityGate DEFAULT_QUALITY_GATE = new QualityGate("default Quality Gate", Collections.emptyList()); + + private final TreeRootHolder treeRootHolder; + private final ProjectSettingsRepository projectSettingsRepository; + private final QualityGateService qualityGateService; + private final MutableQualityGateHolder qualityGateHolder; + + public QualityGateLoadingStep(TreeRootHolder treeRootHolder, ProjectSettingsRepository projectSettingsRepository, + QualityGateService qualityGateService, MutableQualityGateHolder qualityGateHolder) { + this.treeRootHolder = treeRootHolder; + this.projectSettingsRepository = projectSettingsRepository; + this.qualityGateService = qualityGateService; + this.qualityGateHolder = qualityGateHolder; + } + + @Override + public void execute() { + new DepthTraversalTypeAwareVisitor(PROJECT, PRE_ORDER) { + @Override + public void visitProject(Component project) { + executeForProject(project); + } + }.visit(treeRootHolder.getRoot()); + } + + private void executeForProject(Component project) { + String projectKey = project.getKey(); + Settings settings = projectSettingsRepository.getProjectSettings(projectKey); + String qualityGateSetting = settings.getString(PROPERTY_QUALITY_GATE); + + if (qualityGateSetting == null || StringUtils.isBlank(qualityGateSetting)) { + LOGGER.debug("No quality gate is configured for project " + projectKey); + qualityGateHolder.setQualityGate(DEFAULT_QUALITY_GATE); + return; + } + + try { + long qualityGateId = Long.valueOf(qualityGateSetting.trim()); + qualityGateHolder.setQualityGate(qualityGateService.findById(qualityGateId).or(DEFAULT_QUALITY_GATE)); + } catch (NumberFormatException e) { + LOGGER.error(String.format("Unsupported value in property %s, using empty Quality Gate", PROPERTY_QUALITY_GATE)); + qualityGateHolder.setQualityGate(DEFAULT_QUALITY_GATE); + } + } + + @Override + public String getDescription() { + return "Retrieve Quality Gate"; + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/qualitygate/ConditionTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/qualitygate/ConditionTest.java new file mode 100644 index 00000000000..e53d09f3d5a --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/qualitygate/ConditionTest.java @@ -0,0 +1,67 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.computation.qualitygate; + +import org.junit.Test; +import org.sonar.server.computation.metric.Metric; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ConditionTest { + private static final Metric SOME_METRIC = mock(Metric.class); + private static final String SOME_OPERATOR = "ope"; + + @Test(expected = NullPointerException.class) + public void constructor_throws_NPE_for_null_metric_argument() { + new Condition(null, null, SOME_OPERATOR, null, null); + } + + @Test(expected = NullPointerException.class) + public void constructor_throws_NPE_for_null_operator_argument() { + new Condition(SOME_METRIC, null, null, null, null); + } + + @Test + public void verify_getters() { + Integer period = 1; + String error = "error threshold"; + String warning = "warning threshold"; + + Condition condition = new Condition(SOME_METRIC, period, SOME_OPERATOR, error, warning); + + assertThat(condition.getMetric()).isSameAs(SOME_METRIC); + assertThat(condition.getOperator()).isSameAs(SOME_OPERATOR); + assertThat(condition.getPeriod()).isEqualTo(period); + assertThat(condition.getErrorThreshold()).isEqualTo(error); + assertThat(condition.getWarningThreshold()).isEqualTo(warning); + } + + @Test + public void all_fields_are_displayed_in_toString() { + when(SOME_METRIC.toString()).thenReturn("metric1"); + + assertThat(new Condition(SOME_METRIC, 1, SOME_OPERATOR, "error_l", "warn").toString()) + .isEqualTo("Condition{metric=metric1, period=1, operator=ope, warningThreshold=warn, errorThreshold=error_l}"); + + } + +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/qualitygate/MutableQualityGateHolderRule.java b/server/sonar-server/src/test/java/org/sonar/server/computation/qualitygate/MutableQualityGateHolderRule.java new file mode 100644 index 00000000000..22367f7bc43 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/qualitygate/MutableQualityGateHolderRule.java @@ -0,0 +1,53 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.computation.qualitygate; + +import java.util.Objects; +import org.junit.rules.ExternalResource; + +public class MutableQualityGateHolderRule extends ExternalResource implements MutableQualityGateHolder { + private QualityGate qualityGate; + + @Override + public void setQualityGate(QualityGate qualityGate) { + Objects.requireNonNull(qualityGate); + if (this.qualityGate != null) { + throw new IllegalStateException("QualityGate can not be set more than once"); + } + this.qualityGate = qualityGate; + } + + @Override + public QualityGate getQualityGate() { + if (this.qualityGate == null) { + throw new IllegalStateException("QualityGate has not been set"); + } + return qualityGate; + } + + @Override + protected void after() { + reset(); + } + + public void reset() { + this.qualityGate = null; + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/qualitygate/QualityGateHolderImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/qualitygate/QualityGateHolderImplTest.java new file mode 100644 index 00000000000..64b417bcdd8 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/qualitygate/QualityGateHolderImplTest.java @@ -0,0 +1,58 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.computation.qualitygate; + +import java.util.Collections; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class QualityGateHolderImplTest { + + public static final QualityGate QUALITY_GATE = new QualityGate("name", Collections.emptyList()); + + @Test(expected = IllegalStateException.class) + public void getQualityGate_throws_ISE_if_QualityGate_not_set() { + new QualityGateHolderImpl().getQualityGate(); + } + + @Test(expected = NullPointerException.class) + public void setQualityGate_throws_NPE_if_argument_is_null() { + new QualityGateHolderImpl().setQualityGate(null); + } + + @Test(expected = IllegalStateException.class) + public void setQualityGate_throws_ISE_if_called_twice() { + QualityGateHolderImpl holder = new QualityGateHolderImpl(); + + holder.setQualityGate(QUALITY_GATE); + holder.setQualityGate(QUALITY_GATE); + } + + @Test + public void getQualityGate_returns_QualityGate_set_by_setQualityGate() { + QualityGateHolderImpl holder = new QualityGateHolderImpl(); + + holder.setQualityGate(QUALITY_GATE); + + assertThat(holder.getQualityGate()).isSameAs(QUALITY_GATE); + } + +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/qualitygate/QualityGateServiceImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/qualitygate/QualityGateServiceImplTest.java new file mode 100644 index 00000000000..dfb6bd3b843 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/qualitygate/QualityGateServiceImplTest.java @@ -0,0 +1,88 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.computation.qualitygate; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; +import java.util.Collections; +import org.junit.Test; +import org.sonar.core.qualitygate.db.QualityGateConditionDao; +import org.sonar.core.qualitygate.db.QualityGateConditionDto; +import org.sonar.core.qualitygate.db.QualityGateDao; +import org.sonar.core.qualitygate.db.QualityGateDto; +import org.sonar.server.computation.metric.Metric; +import org.sonar.server.computation.metric.MetricRepository; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.guava.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class QualityGateServiceImplTest { + private static final long SOME_ID = 123; + private static final String SOME_NAME = "some name"; + private static final QualityGateDto QUALITY_GATE_DTO = new QualityGateDto().setId(SOME_ID).setName(SOME_NAME); + private static final String METRIC_KEY_1 = "metric_key_1"; + private static final String METRIC_KEY_2 = "metric_key_2"; + private static final Metric METRIC_1 = mock(Metric.class); + private static final Metric METRIC_2 = mock(Metric.class); + private static final QualityGateConditionDto CONDITION_1 = new QualityGateConditionDto().setId(321).setMetricKey(METRIC_KEY_1).setOperator("=").setPeriod(1).setWarningThreshold("warnin_th").setErrorThreshold("error_th"); + private static final QualityGateConditionDto CONDITION_2 = new QualityGateConditionDto().setId(456).setMetricKey(METRIC_KEY_2).setOperator("="); + + private QualityGateDao qualityGateDao = mock(QualityGateDao.class); + private QualityGateConditionDao qualityGateConditionDao = mock(QualityGateConditionDao.class); + private MetricRepository metricRepository = mock(MetricRepository.class); + private QualityGateServiceImpl underTest = new QualityGateServiceImpl(qualityGateDao, qualityGateConditionDao, metricRepository); + + @Test + public void findById_returns_absent_when_QualityGateDto_does_not_exist() { + assertThat(underTest.findById(SOME_ID)).isAbsent(); + } + + @Test + public void findById_returns_QualityGate_with_empty_set_of_conditions_when_there_is_none_in_DB() { + when(qualityGateDao.selectById(SOME_ID)).thenReturn(QUALITY_GATE_DTO); + when(qualityGateConditionDao.selectForQualityGate(SOME_ID)).thenReturn(Collections.emptyList()); + + Optional res = underTest.findById(SOME_ID); + + assertThat(res).isPresent(); + assertThat(res.get().getName()).isEqualTo(SOME_NAME); + assertThat(res.get().getConditions()).isEmpty(); + } + + @Test + public void findById_returns_conditions_when_there_is_some_in_DB() { + when(qualityGateDao.selectById(SOME_ID)).thenReturn(QUALITY_GATE_DTO); + when(qualityGateConditionDao.selectForQualityGate(SOME_ID)).thenReturn(ImmutableList.of(CONDITION_1, CONDITION_2)); + // metrics are always supposed to be there + when(metricRepository.getByKey(METRIC_KEY_1)).thenReturn(METRIC_1); + when(metricRepository.getByKey(METRIC_KEY_2)).thenReturn(METRIC_2); + + Optional res = underTest.findById(SOME_ID); + + assertThat(res).isPresent(); + assertThat(res.get().getName()).isEqualTo(SOME_NAME); + assertThat(res.get().getConditions()).containsOnly( + new Condition(METRIC_1, CONDITION_1.getPeriod(), CONDITION_1.getOperator(), CONDITION_1.getErrorThreshold(), CONDITION_1.getWarningThreshold()), + new Condition(METRIC_2, CONDITION_2.getPeriod(), CONDITION_2.getOperator(), CONDITION_2.getErrorThreshold(), CONDITION_2.getWarningThreshold()) + ); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/QualityGateLoadingStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/QualityGateLoadingStepTest.java new file mode 100644 index 00000000000..ee4b3256062 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/QualityGateLoadingStepTest.java @@ -0,0 +1,117 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.computation.step; + +import com.google.common.base.Optional; +import java.util.Collections; +import org.junit.Rule; +import org.junit.Test; +import org.sonar.api.config.Settings; +import org.sonar.server.computation.batch.TreeRootHolderRule; +import org.sonar.server.computation.component.Component; +import org.sonar.server.computation.component.DumbComponent; +import org.sonar.server.computation.component.ProjectSettingsRepository; +import org.sonar.server.computation.qualitygate.Condition; +import org.sonar.server.computation.qualitygate.MutableQualityGateHolderRule; +import org.sonar.server.computation.qualitygate.QualityGate; +import org.sonar.server.computation.qualitygate.QualityGateService; + +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.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +public class QualityGateLoadingStepTest { + private static final String PROJECT_KEY = "project key"; + public static final DumbComponent PROJECT_ALONE = DumbComponent.builder(Component.Type.PROJECT, 1).setKey(PROJECT_KEY).build(); + + @Rule + public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule(); + @Rule + public MutableQualityGateHolderRule mutableQualityGateHolder = new MutableQualityGateHolderRule(); + + private ProjectSettingsRepository projectSettingsRepository = mock(ProjectSettingsRepository.class); + private QualityGateService qualityGateService = mock(QualityGateService.class); + + private QualityGateLoadingStep underTest = new QualityGateLoadingStep(treeRootHolder, projectSettingsRepository, qualityGateService, mutableQualityGateHolder); + + @Test + public void execute_sets_default_QualityGate_when_project_has_no_settings() { + treeRootHolder.setRoot(DumbComponent.builder(Component.Type.PROJECT, 1).setKey(PROJECT_KEY).addChildren(DumbComponent.builder(Component.Type.FILE, 2).build()).build()); + when(projectSettingsRepository.getProjectSettings(PROJECT_KEY)).thenReturn(new Settings()); + + underTest.execute(); + + verifyDefaultQualityGateHasBeenSet(); + + // verify only project is processed + verify(projectSettingsRepository).getProjectSettings(PROJECT_KEY); + verifyNoMoreInteractions(projectSettingsRepository); + } + + @Test + public void execute_sets_default_QualityGate_when_property_value_is_not_a_long() { + verify_execute_sets_default_QualityGate_when_property_value_is_not_a_long(""); + verify_execute_sets_default_QualityGate_when_property_value_is_not_a_long(" "); + verify_execute_sets_default_QualityGate_when_property_value_is_not_a_long(" 10 sds "); + } + + private void verify_execute_sets_default_QualityGate_when_property_value_is_not_a_long(String value) { + treeRootHolder.setRoot(PROJECT_ALONE); + when(projectSettingsRepository.getProjectSettings(PROJECT_KEY)).thenReturn(new Settings().setProperty("sonar.qualitygate", value)); + + underTest.execute(); + + verifyDefaultQualityGateHasBeenSet(); + + mutableQualityGateHolder.reset(); + } + + @Test + public void execute_sets_default_QualityGate_if_it_can_not_be_found_by_service() { + treeRootHolder.setRoot(PROJECT_ALONE); + when(projectSettingsRepository.getProjectSettings(PROJECT_KEY)).thenReturn(new Settings().setProperty("sonar.qualitygate", 10)); + when(qualityGateService.findById(10)).thenReturn(Optional.absent()); + + underTest.execute(); + + verifyDefaultQualityGateHasBeenSet(); + } + + @Test + public void execute_sets_QualityGate_if_it_can_be_found_by_service() { + QualityGate qualityGate = new QualityGate("name", Collections.emptyList()); + + treeRootHolder.setRoot(PROJECT_ALONE); + when(projectSettingsRepository.getProjectSettings(PROJECT_KEY)).thenReturn(new Settings().setProperty("sonar.qualitygate", 10)); + when(qualityGateService.findById(10)).thenReturn(Optional.of(qualityGate)); + + underTest.execute(); + + assertThat(mutableQualityGateHolder.getQualityGate()).isSameAs(qualityGate); + } + + private void verifyDefaultQualityGateHasBeenSet() { + assertThat(mutableQualityGateHolder.getQualityGate().getName()).isEqualTo("default Quality Gate"); + assertThat(mutableQualityGateHolder.getQualityGate().getConditions()).isEmpty(); + } + +} -- 2.39.5