in which case, no QualityGate measure must be created nor any measure have its QualityGateStatus be updatedtags/5.2-RC1
@@ -30,7 +30,14 @@ public interface MutableQualityGateHolder extends QualityGateHolder { | |||
* @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 | |||
* @throws IllegalStateException if the holder has already been initialized | |||
*/ | |||
void setQualityGate(QualityGate qualityGate); | |||
/** | |||
* Sets that there is no quality gate for the project of the currently processed {@link ReportQueue.Item}. | |||
* | |||
* @throws IllegalStateException if the holder has already been initialized | |||
*/ | |||
void setNoQualityGate(); | |||
} |
@@ -19,13 +19,14 @@ | |||
*/ | |||
package org.sonar.server.computation.qualitygate; | |||
import com.google.common.base.Optional; | |||
import org.sonar.server.computation.ReportQueue; | |||
public interface QualityGateHolder { | |||
/** | |||
* The QualityGate for the project of the current {@link ReportQueue.Item}. | |||
* The QualityGate for the project of the current {@link ReportQueue.Item} if there is any. | |||
* | |||
* @throws IllegalStateException if the holder is empty (ie. there is no quality gate yet) | |||
* @throws IllegalStateException if the holder has not been initialized (ie. we don't know yet what is the QualityGate) | |||
*/ | |||
QualityGate getQualityGate(); | |||
Optional<QualityGate> getQualityGate(); | |||
} |
@@ -19,29 +19,44 @@ | |||
*/ | |||
package org.sonar.server.computation.qualitygate; | |||
import java.util.Objects; | |||
import com.google.common.base.Optional; | |||
import javax.annotation.CheckForNull; | |||
import static com.google.common.base.Optional.absent; | |||
import static com.google.common.base.Optional.of; | |||
import static com.google.common.base.Preconditions.checkState; | |||
import static java.util.Objects.requireNonNull; | |||
public class QualityGateHolderImpl implements MutableQualityGateHolder { | |||
private boolean initialized = false; | |||
@CheckForNull | |||
private QualityGate qualityGate; | |||
private Optional<QualityGate> qualityGate; | |||
@Override | |||
public void setQualityGate(QualityGate qualityGate) { | |||
// fail fast | |||
Objects.requireNonNull(qualityGate); | |||
requireNonNull(qualityGate); | |||
checkNotInitialized(); | |||
this.initialized = true; | |||
this.qualityGate = of(qualityGate); | |||
} | |||
@Override | |||
public void setNoQualityGate() { | |||
checkNotInitialized(); | |||
this.initialized = true; | |||
this.qualityGate = absent(); | |||
} | |||
if (this.qualityGate != null) { | |||
throw new IllegalStateException("QualityGate can be set only once"); | |||
} | |||
this.qualityGate = qualityGate; | |||
private void checkNotInitialized() { | |||
checkState(!initialized, "QualityGateHolder can be initialized only once"); | |||
} | |||
@Override | |||
public QualityGate getQualityGate() { | |||
if (qualityGate == null) { | |||
throw new IllegalStateException("QualityGate has not been set yet"); | |||
} | |||
public Optional<QualityGate> getQualityGate() { | |||
checkState(initialized, "QualityGate has not been set yet"); | |||
return qualityGate; | |||
} | |||
} |
@@ -19,7 +19,7 @@ | |||
*/ | |||
package org.sonar.server.computation.step; | |||
import java.util.Collections; | |||
import com.google.common.base.Optional; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.sonar.api.config.Settings; | |||
import org.sonar.api.utils.log.Logger; | |||
@@ -29,7 +29,6 @@ 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; | |||
@@ -45,7 +44,6 @@ 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.<Condition>emptyList()); | |||
private final TreeRootHolder treeRootHolder; | |||
private final ProjectSettingsRepository projectSettingsRepository; | |||
@@ -77,16 +75,23 @@ public class QualityGateLoadingStep implements ComputationStep { | |||
if (qualityGateSetting == null || StringUtils.isBlank(qualityGateSetting)) { | |||
LOGGER.debug("No quality gate is configured for project " + projectKey); | |||
qualityGateHolder.setQualityGate(DEFAULT_QUALITY_GATE); | |||
qualityGateHolder.setNoQualityGate(); | |||
return; | |||
} | |||
try { | |||
long qualityGateId = Long.parseLong(qualityGateSetting.trim()); | |||
qualityGateHolder.setQualityGate(qualityGateService.findById(qualityGateId).or(DEFAULT_QUALITY_GATE)); | |||
long qualityGateId = Long.parseLong(qualityGateSetting); | |||
Optional<QualityGate> qualityGate = qualityGateService.findById(qualityGateId); | |||
if (qualityGate.isPresent()) { | |||
qualityGateHolder.setQualityGate(qualityGate.get()); | |||
} | |||
else { | |||
qualityGateHolder.setNoQualityGate(); | |||
} | |||
} catch (NumberFormatException e) { | |||
LOGGER.error(String.format("Unsupported value in property %s, using empty Quality Gate", PROPERTY_QUALITY_GATE)); | |||
qualityGateHolder.setQualityGate(DEFAULT_QUALITY_GATE); | |||
throw new IllegalStateException( | |||
String.format("Unsupported value (%s) in property %s", qualityGateSetting, PROPERTY_QUALITY_GATE), | |||
e); | |||
} | |||
} | |||
@@ -40,6 +40,7 @@ import org.sonar.server.computation.qualitygate.Condition; | |||
import org.sonar.server.computation.qualitygate.ConditionEvaluator; | |||
import org.sonar.server.computation.qualitygate.EvaluationResult; | |||
import org.sonar.server.computation.qualitygate.EvaluationResultTextConverter; | |||
import org.sonar.server.computation.qualitygate.QualityGate; | |||
import org.sonar.server.computation.qualitygate.QualityGateHolder; | |||
import static org.sonar.server.computation.component.Component.Type.PROJECT; | |||
@@ -85,9 +86,12 @@ public class QualityGateMeasuresStep implements ComputationStep { | |||
private void executeForProject(Component project) { | |||
QualityGateDetailsDataBuilder builder = new QualityGateDetailsDataBuilder(); | |||
updateMeasures(project, qualityGateHolder.getQualityGate().getConditions(), builder); | |||
Optional<QualityGate> qualityGate = qualityGateHolder.getQualityGate(); | |||
if (qualityGate.isPresent()) { | |||
updateMeasures(project, qualityGate.get().getConditions(), builder); | |||
addProjectMeasure(project, builder); | |||
addProjectMeasure(project, builder); | |||
} | |||
} | |||
private void updateMeasures(Component project, Set<Condition> conditions, QualityGateDetailsDataBuilder builder) { |
@@ -19,27 +19,25 @@ | |||
*/ | |||
package org.sonar.server.computation.qualitygate; | |||
import java.util.Objects; | |||
import com.google.common.base.Optional; | |||
import org.junit.rules.ExternalResource; | |||
public class MutableQualityGateHolderRule extends ExternalResource implements MutableQualityGateHolder { | |||
private QualityGate qualityGate; | |||
private MutableQualityGateHolder delegate = new QualityGateHolderImpl(); | |||
@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; | |||
delegate.setQualityGate(qualityGate); | |||
} | |||
@Override | |||
public QualityGate getQualityGate() { | |||
if (this.qualityGate == null) { | |||
throw new IllegalStateException("QualityGate has not been set"); | |||
} | |||
return qualityGate; | |||
public void setNoQualityGate() { | |||
delegate.setNoQualityGate(); | |||
} | |||
@Override | |||
public Optional<QualityGate> getQualityGate() { | |||
return delegate.getQualityGate(); | |||
} | |||
@Override | |||
@@ -48,6 +46,6 @@ public class MutableQualityGateHolderRule extends ExternalResource implements Mu | |||
} | |||
public void reset() { | |||
this.qualityGate = null; | |||
this.delegate = new QualityGateHolderImpl(); | |||
} | |||
} |
@@ -23,6 +23,7 @@ import java.util.Collections; | |||
import org.junit.Test; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.guava.api.Assertions.assertThat; | |||
public class QualityGateHolderImplTest { | |||
@@ -52,7 +53,16 @@ public class QualityGateHolderImplTest { | |||
holder.setQualityGate(QUALITY_GATE); | |||
assertThat(holder.getQualityGate()).isSameAs(QUALITY_GATE); | |||
assertThat(holder.getQualityGate().get()).isSameAs(QUALITY_GATE); | |||
} | |||
@Test | |||
public void getQualityGate_returns_absent_if_holder_initialized_with_setNoQualityGate() { | |||
QualityGateHolderImpl holder = new QualityGateHolderImpl(); | |||
holder.setNoQualityGate(); | |||
assertThat(holder.getQualityGate()).isAbsent(); | |||
} | |||
} |
@@ -23,6 +23,7 @@ import com.google.common.base.Optional; | |||
import java.util.Collections; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.sonar.api.config.Settings; | |||
import org.sonar.server.computation.batch.TreeRootHolderRule; | |||
import org.sonar.server.computation.component.Component; | |||
@@ -34,6 +35,7 @@ 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.assertj.guava.api.Assertions.assertThat; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.verify; | |||
import static org.mockito.Mockito.verifyNoMoreInteractions; | |||
@@ -41,8 +43,10 @@ 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(); | |||
private static final DumbComponent PROJECT_ALONE = DumbComponent.builder(Component.Type.PROJECT, 1).setKey(PROJECT_KEY).build(); | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
@Rule | |||
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule(); | |||
@Rule | |||
@@ -60,7 +64,7 @@ public class QualityGateLoadingStepTest { | |||
underTest.execute(); | |||
verifyDefaultQualityGateHasBeenSet(); | |||
verifyNoQualityGate(); | |||
// verify only project is processed | |||
verify(projectSettingsRepository).getProjectSettings(PROJECT_KEY); | |||
@@ -69,20 +73,13 @@ public class QualityGateLoadingStepTest { | |||
@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 "); | |||
} | |||
expectedException.expect(IllegalStateException.class); | |||
expectedException.expectMessage(String.format("Unsupported value (%s) in property sonar.qualitygate", "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)); | |||
when(projectSettingsRepository.getProjectSettings(PROJECT_KEY)).thenReturn(new Settings().setProperty("sonar.qualitygate", "10 sds")); | |||
underTest.execute(); | |||
verifyDefaultQualityGateHasBeenSet(); | |||
mutableQualityGateHolder.reset(); | |||
} | |||
@Test | |||
@@ -93,7 +90,7 @@ public class QualityGateLoadingStepTest { | |||
underTest.execute(); | |||
verifyDefaultQualityGateHasBeenSet(); | |||
verifyNoQualityGate(); | |||
} | |||
@Test | |||
@@ -106,12 +103,11 @@ public class QualityGateLoadingStepTest { | |||
underTest.execute(); | |||
assertThat(mutableQualityGateHolder.getQualityGate()).isSameAs(qualityGate); | |||
assertThat(mutableQualityGateHolder.getQualityGate().get()).isSameAs(qualityGate); | |||
} | |||
private void verifyDefaultQualityGateHasBeenSet() { | |||
assertThat(mutableQualityGateHolder.getQualityGate().getName()).isEqualTo("default Quality Gate"); | |||
assertThat(mutableQualityGateHolder.getQualityGate().getConditions()).isEmpty(); | |||
private void verifyNoQualityGate() { | |||
assertThat(mutableQualityGateHolder.getQualityGate()).isAbsent(); | |||
} | |||
} |
@@ -112,6 +112,15 @@ public class QualityGateMeasuresStepTest { | |||
verifyNoMoreInteractions(measureRepository); | |||
} | |||
@Test | |||
public void no_measure_if_there_is_no_qualitygate() { | |||
qualityGateHolder.setNoQualityGate(); | |||
underTest.execute(); | |||
verifyNoMoreInteractions(measureRepository); | |||
} | |||
@Test | |||
public void new_measures_are_created_even_if_there_is_no_rawMeasure_for_metric_of_condition() { | |||
Condition equals2Condition = createEqualsCondition(INT_METRIC_1, "2", null); |