*/
package org.sonar.db.qualitygate;
+import java.util.Arrays;
+import java.util.function.Consumer;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
db.commit();
}
- public QualityGateConditionDto addCondition(QualityGateDto qualityGate, MetricDto metric) {
+ @SafeVarargs
+ public final QualityGateConditionDto addCondition(QualityGateDto qualityGate, MetricDto metric, Consumer<QualityGateConditionDto>... dtoPopulators) {
QualityGateConditionDto condition = new QualityGateConditionDto().setQualityGateId(qualityGate.getId())
.setMetricId(metric.getId())
.setOperator("GT")
.setWarningThreshold(randomNumeric(10))
.setErrorThreshold(randomNumeric(10));
+ Arrays.stream(dtoPopulators).forEach(dtoPopulator -> dtoPopulator.accept(condition));
dbClient.gateConditionDao().insert(condition, dbSession);
db.commit();
return condition;
import java.util.Optional;
import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.property.PropertyDto;
import org.sonar.db.qualitygate.QualityGateDto;
-import org.sonar.server.exceptions.NotFoundException;
import static org.apache.commons.lang.StringUtils.isBlank;
import static org.sonar.server.qualitygate.QualityGates.SONAR_QUALITYGATE_PROPERTY;
+import static org.sonar.server.ws.WsUtils.checkFound;
public class QualityGateFinder {
public Optional<QualityGateData> getQualityGate(DbSession dbSession, long componentId) {
Optional<Long> qualityGateId = dbClient.projectQgateAssociationDao().selectQGateIdByComponentId(dbSession, componentId);
if (qualityGateId.isPresent()) {
- return Optional.of(new QualityGateData(selectOrFailById(dbSession, qualityGateId.get()), false));
+ return Optional.of(new QualityGateData(getById(dbSession, qualityGateId.get()), false));
} else {
QualityGateDto defaultQualityGate = getDefault(dbSession);
if (defaultQualityGate == null) {
}
}
+ public QualityGateDto getById(DbSession dbSession, long qualityGateId) {
+ return checkFound(dbClient.qualityGateDao().selectById(dbSession, qualityGateId), "No quality gate has been found for id %s", qualityGateId);
+ }
+
+ public QualityGateDto getByNameOrId(DbSession dbSession, @Nullable String name, @Nullable Long id) {
+ if (name != null) {
+ return checkFound(dbClient.qualityGateDao().selectByName(dbSession, name), "No quality gate has been found for name %s", name);
+ }
+ if (id != null) {
+ return getById(dbSession, id);
+ }
+ throw new IllegalArgumentException("No parameter has been set to identify a quality gate");
+ }
+
@CheckForNull
private QualityGateDto getDefault(DbSession dbSession) {
Long defaultId = getDefaultId(dbSession);
if (defaultId == null) {
return null;
}
- return selectOrFailById(dbSession, defaultId);
- }
-
- private QualityGateDto selectOrFailById(DbSession dbSession, long qualityGateId) {
- QualityGateDto qualityGateDto = dbClient.qualityGateDao().selectById(dbSession, qualityGateId);
- if (qualityGateDto == null) {
- throw new NotFoundException(String.format("No quality gate has been found for id %s", qualityGateId));
- }
- return qualityGateDto;
+ return getById(dbSession, defaultId);
}
@CheckForNull
return isDefault;
}
}
+
}
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.apache.commons.lang.StringUtils;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.measures.MetricFinder;
import org.sonar.api.web.UserRole;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException;
import static org.sonar.server.util.Validation.CANT_BE_EMPTY_MESSAGE;
import static org.sonar.server.util.Validation.IS_ALREADY_USED_MESSAGE;
-import static org.sonar.server.ws.WsUtils.checkFound;
import static org.sonar.server.ws.WsUtils.checkRequest;
/**
- * Methods from this class should be moved to {@link QualityGateUpdater} and to new classes QualityGateFinder / QualityGateConditionsUpdater / etc.
+ * Methods from this class should be moved to {@link QualityGateUpdater} and to classes QualityGateFinder / QualityGateConditionsUpdater / etc.
* in order to have classes with clearer responsibilities and more easily testable (without having to use too much mocks)
*/
public class QualityGates {
private final DbClient dbClient;
private final QualityGateDao dao;
private final QualityGateConditionDao conditionDao;
- private final MetricFinder metricFinder;
private final PropertiesDao propertiesDao;
private final UserSession userSession;
private final DefaultOrganizationProvider organizationProvider;
- public QualityGates(DbClient dbClient, MetricFinder metricFinder, UserSession userSession, DefaultOrganizationProvider organizationProvider) {
+ public QualityGates(DbClient dbClient, UserSession userSession, DefaultOrganizationProvider organizationProvider) {
this.dbClient = dbClient;
this.dao = dbClient.qualityGateDao();
this.conditionDao = dbClient.gateConditionDao();
- this.metricFinder = metricFinder;
this.propertiesDao = dbClient.propertiesDao();
this.userSession = userSession;
this.organizationProvider = organizationProvider;
}
- public QualityGateDto get(Long qGateId) {
- return getNonNullQgate(qGateId);
- }
-
- public QualityGateDto get(String qGateName) {
- return getNonNullQgate(qGateName);
- }
-
public QualityGateDto rename(long idToRename, String name) {
checkIsQualityGateAdministrator();
try (DbSession dbSession = dbClient.openSession(false)) {
}
}
- public Collection<QualityGateConditionDto> listConditions(long qGateId) {
- try (DbSession dbSession = dbClient.openSession(false)) {
- Collection<QualityGateConditionDto> conditionsForGate = conditionDao.selectForQualityGate(dbSession, qGateId);
- for (QualityGateConditionDto condition : conditionsForGate) {
- Metric metric = metricFinder.findById((int) condition.getMetricId());
- if (metric == null) {
- throw new IllegalStateException("Could not find metric with id " + condition.getMetricId());
- }
- condition.setMetricKey(metric.getKey());
- }
- return conditionsForGate;
- }
- }
-
public void dissociateProject(DbSession dbSession, ComponentDto project) {
checkProjectAdmin(project);
propertiesDao.deleteProjectProperty(SONAR_QUALITYGATE_PROPERTY, project.getId(), dbSession);
return qGate;
}
- private QualityGateDto getNonNullQgate(String name) {
- try (DbSession dbSession = dbClient.openSession(false)) {
- return checkFound(dao.selectByName(dbSession, name), "There is no quality gate with name=%s", name);
- }
- }
-
private void validateQualityGate(DbSession dbSession, @Nullable Long updatingQgateId, @Nullable String name) {
List<String> errors = new ArrayList<>();
if (Strings.isNullOrEmpty(name)) {
.endObject();
}
- static JsonWriter writeQualityGateCondition(QualityGateConditionDto condition, JsonWriter writer) {
- writer.beginObject()
- .prop(PARAM_ID, condition.getId())
- .prop(PARAM_METRIC, condition.getMetricKey())
- .prop(PARAM_OPERATOR, condition.getOperator());
- if (condition.getWarningThreshold() != null) {
- writer.prop(PARAM_WARNING, condition.getWarningThreshold());
- }
- if (condition.getErrorThreshold() != null) {
- writer.prop(PARAM_ERROR, condition.getErrorThreshold());
- }
- if (condition.getPeriod() != null) {
- writer.prop(PARAM_PERIOD, condition.getPeriod());
- }
- writer.endObject();
- return writer;
- }
-
}
import com.google.common.io.Resources;
import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
import javax.annotation.Nullable;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.metric.MetricDto;
import org.sonar.db.qualitygate.QualityGateConditionDto;
import org.sonar.db.qualitygate.QualityGateDto;
-import org.sonar.server.qualitygate.QualityGates;
+import org.sonar.server.qualitygate.QualityGateFinder;
+import org.sonarqube.ws.Qualitygates.ShowWsResponse;
-import static org.sonar.server.ws.WsUtils.checkRequest;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+import static org.sonar.core.util.Protobuf.setNullable;
+import static org.sonar.core.util.stream.MoreCollectors.toList;
+import static org.sonar.core.util.stream.MoreCollectors.toSet;
+import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_ID;
import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_NAME;
+import static org.sonar.server.ws.WsUtils.writeProtobuf;
public class ShowAction implements QualityGatesWsAction {
- private final QualityGates qualityGates;
+ private final DbClient dbClient;
+ private final QualityGateFinder qualityGateFinder;
- public ShowAction(QualityGates qualityGates) {
- this.qualityGates = qualityGates;
+ public ShowAction(DbClient dbClient, QualityGateFinder qualityGateFinder) {
+ this.dbClient = dbClient;
+ this.qualityGateFinder = qualityGateFinder;
}
@Override
WebService.NewAction action = controller.createAction("show")
.setDescription("Display the details of a quality gate")
.setSince("4.3")
- .setResponseExample(Resources.getResource(this.getClass(), "example-show.json"))
+ .setResponseExample(Resources.getResource(this.getClass(), "show-example.json"))
.setHandler(this);
action.createParam(PARAM_ID)
@Override
public void handle(Request request, Response response) {
- Long qGateId = request.paramAsLong(PARAM_ID);
- String qGateName = request.param(PARAM_NAME);
- checkOneOfIdOrNamePresent(qGateId, qGateName);
+ Long id = request.paramAsLong(PARAM_ID);
+ String name = request.param(PARAM_NAME);
+ checkOneOfIdOrNamePresent(id, name);
- QualityGateDto qGate = qGateId == null ? qualityGates.get(qGateName) : qualityGates.get(qGateId);
- qGateId = qGate.getId();
-
- try (JsonWriter writer = response.newJsonWriter()) {
- writer.beginObject()
- .prop(PARAM_ID, qGate.getId())
- .prop(PARAM_NAME, qGate.getName());
- Collection<QualityGateConditionDto> conditions = qualityGates.listConditions(qGateId);
- if (!conditions.isEmpty()) {
- writer.name("conditions").beginArray();
- for (QualityGateConditionDto condition : conditions) {
- QualityGatesWs.writeQualityGateCondition(condition, writer);
- }
- writer.endArray();
- }
- writer.endObject().close();
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ QualityGateDto qualityGate = qualityGateFinder.getByNameOrId(dbSession, name, id);
+ Collection<QualityGateConditionDto> conditions = getConditions(dbSession, qualityGate);
+ Map<Integer, MetricDto> metricsById = getMetricsById(dbSession, conditions);
+ writeProtobuf(buildResponse(qualityGate, conditions, metricsById), request, response);
}
}
+ public Collection<QualityGateConditionDto> getConditions(DbSession dbSession, QualityGateDto qualityGate) {
+ return dbClient.gateConditionDao().selectForQualityGate(dbSession, qualityGate.getId());
+ }
+
+ private Map<Integer, MetricDto> getMetricsById(DbSession dbSession, Collection<QualityGateConditionDto> conditions) {
+ Set<Integer> metricIds = conditions.stream().map(c -> (int) c.getMetricId()).collect(toSet());
+ return dbClient.metricDao().selectByIds(dbSession, metricIds).stream()
+ .filter(MetricDto::isEnabled)
+ .collect(uniqueIndex(MetricDto::getId));
+ }
+
+ private static ShowWsResponse buildResponse(QualityGateDto qualityGate, Collection<QualityGateConditionDto> conditions, Map<Integer, MetricDto> metricsById) {
+ return ShowWsResponse.newBuilder()
+ .setId(qualityGate.getId())
+ .setName(qualityGate.getName())
+ .addAllConditions(conditions.stream()
+ .map(toWsCondition(metricsById))
+ .collect(toList()))
+ .build();
+ }
+
+ private static Function<QualityGateConditionDto, ShowWsResponse.Condition> toWsCondition(Map<Integer, MetricDto> metricsById) {
+ return condition -> {
+ int metricId = (int) condition.getMetricId();
+ MetricDto metric = metricsById.get(metricId);
+ checkState(metric != null, "Could not find metric with id %s", metricId);
+ ShowWsResponse.Condition.Builder builder = ShowWsResponse.Condition.newBuilder()
+ .setId(condition.getId())
+ .setMetric(metric.getKey())
+ .setOp(condition.getOperator());
+ setNullable(condition.getPeriod(), builder::setPeriod);
+ setNullable(condition.getErrorThreshold(), builder::setError);
+ setNullable(condition.getWarningThreshold(), builder::setWarning);
+ return builder.build();
+ };
+ }
+
private static void checkOneOfIdOrNamePresent(@Nullable Long qGateId, @Nullable String qGateName) {
- checkRequest(qGateId == null ^ qGateName == null, "Either '%s' or '%s' must be provided", PARAM_ID, PARAM_NAME);
+ checkArgument(qGateId == null ^ qGateName == null, "Either '%s' or '%s' must be provided", PARAM_ID, PARAM_NAME);
}
}
+++ /dev/null
-{
- "id": 2,
- "name": "My Quality Gate",
- "conditions": [
- {
- "id": 9,
- "metric": "blocker_violations",
- "op": "GT",
- "error": "0"
- },
- {
- "id": 10,
- "metric": "critical_violations",
- "op": "GT",
- "warning": "0"
- }
- ]
-}
--- /dev/null
+{
+ "id": 2,
+ "name": "My Quality Gate",
+ "conditions": [
+ {
+ "id": 9,
+ "metric": "blocker_violations",
+ "op": "GT",
+ "error": "0"
+ },
+ {
+ "id": 10,
+ "metric": "critical_violations",
+ "period": 1,
+ "op": "LT",
+ "warning": "0"
+ }
+ ]
+}
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.ComponentTesting;
import org.sonar.db.qualitygate.QualityGateDto;
import org.sonar.server.exceptions.NotFoundException;
public ExpectedException expectedException = ExpectedException.none();
@Rule
- public DbTester dbTester = DbTester.create(System2.INSTANCE);
+ public DbTester db = DbTester.create(System2.INSTANCE);
- private DbSession dbSession = dbTester.getSession();
+ private DbSession dbSession = db.getSession();
- private QualityGateFinder underTest = new QualityGateFinder(dbTester.getDbClient());
+ private QualityGateFinder underTest = new QualityGateFinder(db.getDbClient());
@Test
public void return_default_quality_gate_for_project() {
- ComponentDto project = dbTester.components().insertComponent(ComponentTesting.newPrivateProjectDto(dbTester.getDefaultOrganization()));
- QualityGateDto dbQualityGate = dbTester.qualityGates().createDefaultQualityGate("Sonar way");
+ ComponentDto project = db.components().insertPrivateProject();
+ QualityGateDto dbQualityGate = db.qualityGates().createDefaultQualityGate("Sonar way");
Optional<QualityGateFinder.QualityGateData> result = underTest.getQualityGate(dbSession, project.getId());
@Test
public void return_project_quality_gate_over_default() {
- ComponentDto project = dbTester.components().insertComponent(ComponentTesting.newPrivateProjectDto(dbTester.organizations().insert()));
- dbTester.qualityGates().createDefaultQualityGate("Sonar way");
- QualityGateDto dbQualityGate = dbTester.qualityGates().insertQualityGate("My team QG");
- dbTester.qualityGates().associateProjectToQualityGate(project, dbQualityGate);
+ ComponentDto project = db.components().insertPrivateProject();
+ db.qualityGates().createDefaultQualityGate("Sonar way");
+ QualityGateDto dbQualityGate = db.qualityGates().insertQualityGate("My team QG");
+ db.qualityGates().associateProjectToQualityGate(project, dbQualityGate);
Optional<QualityGateFinder.QualityGateData> result = underTest.getQualityGate(dbSession, project.getId());
@Test
public void return_nothing_when_no_default_qgate_and_no_qgate_defined_for_project() {
- ComponentDto project = dbTester.components().insertComponent(ComponentTesting.newPrivateProjectDto(dbTester.getDefaultOrganization()));
+ ComponentDto project = db.components().insertPrivateProject();
Optional<QualityGateFinder.QualityGateData> result = underTest.getQualityGate(dbSession, project.getId());
@Test
public void fail_when_default_qgate_defined_in_properties_does_not_exists() throws Exception {
- ComponentDto project = dbTester.components().insertComponent(ComponentTesting.newPrivateProjectDto(dbTester.organizations().insert()));
- QualityGateDto dbQualityGate = dbTester.qualityGates().createDefaultQualityGate("Sonar way");
- dbTester.getDbClient().qualityGateDao().delete(dbQualityGate, dbSession);
+ ComponentDto project = db.components().insertPrivateProject();
+ QualityGateDto dbQualityGate = db.qualityGates().createDefaultQualityGate("Sonar way");
+ db.getDbClient().qualityGateDao().delete(dbQualityGate, dbSession);
expectedException.expect(NotFoundException.class);
underTest.getQualityGate(dbSession, project.getId());
@Test
public void fail_when_project_qgate_defined_in_properties_does_not_exists() throws Exception {
- ComponentDto project = dbTester.components().insertComponent(ComponentTesting.newPrivateProjectDto(dbTester.getDefaultOrganization()));
- QualityGateDto dbQualityGate = dbTester.qualityGates().insertQualityGate("My team QG");
- dbTester.qualityGates().associateProjectToQualityGate(project, dbQualityGate);
- dbTester.getDbClient().qualityGateDao().delete(dbQualityGate, dbSession);
+ ComponentDto project = db.components().insertPrivateProject();
+ QualityGateDto dbQualityGate = db.qualityGates().insertQualityGate("My team QG");
+ db.qualityGates().associateProjectToQualityGate(project, dbQualityGate);
+ db.getDbClient().qualityGateDao().delete(dbQualityGate, dbSession);
expectedException.expect(NotFoundException.class);
underTest.getQualityGate(dbSession, project.getId());
}
+
+ @Test
+ public void get_by_name_or_id() {
+ QualityGateDto qualityGate = db.qualityGates().insertQualityGate();
+
+ assertThat(underTest.getByNameOrId(db.getSession(), qualityGate.getName(), null)).isNotNull();
+ assertThat(underTest.getByNameOrId(db.getSession(), null, qualityGate.getId())).isNotNull();
+ }
+
+ @Test
+ public void fail_get_by_name_or_id_when_name_matches_nothing() {
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage("No quality gate has been found for name UNKNOWN");
+
+ underTest.getByNameOrId(db.getSession(), "UNKNOWN", null);
+ }
+
+ @Test
+ public void fail_get_by_name_or_id_when_id_matches_nothing() {
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage("No quality gate has been found for id 123");
+
+ underTest.getByNameOrId(db.getSession(), null, 123L);
+ }
+
+ @Test
+ public void fail_get_by_name_or_id_when_parameters_are_null() {
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("No parameter has been set to identify a quality gate");
+
+ underTest.getByNameOrId(db.getSession(), null, null);
+ }
}
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import java.util.Collection;
-import java.util.Iterator;
import java.util.List;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.ExpectedException;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.measures.Metric.ValueType;
-import org.sonar.api.measures.MetricFinder;
import org.sonar.core.util.Uuids;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
private QualityGateConditionDao conditionDao = mock(QualityGateConditionDao.class);
private PropertiesDao propertiesDao = mock(PropertiesDao.class);
private ComponentDao componentDao = mock(ComponentDao.class);
- private MetricFinder metricFinder = mock(MetricFinder.class);
private QualityGates underTest;
@Before
when(componentDao.selectOrFailById(eq(dbSession), anyLong())).thenReturn(
newPrivateProjectDto(OrganizationTesting.newOrganizationDto(), PROJECT_UUID).setId(1L).setDbKey(PROJECT_KEY));
- underTest = new QualityGates(dbClient, metricFinder, userSession, organizationProvider);
+ underTest = new QualityGates(dbClient, userSession, organizationProvider);
userSession.logIn().addPermission(OrganizationPermission.ADMINISTER_QUALITY_GATES, organizationProvider.get().getUuid());
}
assertThat(underTest.list()).isEqualTo(allQgates);
}
- @Test
- public void should_get_qgate_by_id() {
- long id = QUALITY_GATE_ID;
- final String name = "Golden";
- QualityGateDto existing = new QualityGateDto().setId(id).setName(name);
- when(dao.selectById(dbSession, id)).thenReturn(existing);
- assertThat(underTest.get(id)).isEqualTo(existing);
- verify(dao).selectById(dbSession, id);
- }
-
- @Test
- public void should_get_qgate_by_name() {
- long id = QUALITY_GATE_ID;
- final String name = "Golden";
- QualityGateDto existing = new QualityGateDto().setId(id).setName(name);
- when(dao.selectByName(dbSession, name)).thenReturn(existing);
- assertThat(underTest.get(name)).isEqualTo(existing);
- verify(dao).selectByName(dbSession, name);
- }
-
- @Test(expected = NotFoundException.class)
- public void should_fail_to_find_qgate_by_name() {
- underTest.get("Does not exist");
- }
-
@Test
public void should_rename_qgate() {
long id = QUALITY_GATE_ID;
assertThat(underTest.getDefault()).isNull();
}
- @Test
- public void should_list_conditions() {
- long qGateId = QUALITY_GATE_ID;
- long metric1Id = 1L;
- String metric1Key = "polop";
- long metric2Id = 2L;
- String metric2Key = "palap";
- QualityGateConditionDto cond1 = new QualityGateConditionDto().setMetricId(metric1Id);
- QualityGateConditionDto cond2 = new QualityGateConditionDto().setMetricId(metric2Id);
- Collection<QualityGateConditionDto> conditions = ImmutableList.of(cond1, cond2);
- when(conditionDao.selectForQualityGate(dbSession, qGateId)).thenReturn(conditions);
- Metric metric1 = mock(Metric.class);
- when(metric1.getKey()).thenReturn(metric1Key);
- when(metricFinder.findById((int) metric1Id)).thenReturn(metric1);
- Metric metric2 = mock(Metric.class);
- when(metric2.getKey()).thenReturn(metric2Key);
- when(metricFinder.findById((int) metric2Id)).thenReturn(metric2);
- assertThat(underTest.listConditions(qGateId)).isEqualTo(conditions);
- Iterator<QualityGateConditionDto> iterator = conditions.iterator();
- assertThat(iterator.next().getMetricKey()).isEqualTo(metric1Key);
- assertThat(iterator.next().getMetricKey()).isEqualTo(metric2Key);
- }
-
- @Test(expected = IllegalStateException.class)
- public void should_do_a_sanity_check_when_listing_conditions() {
- long qGateId = QUALITY_GATE_ID;
- long metric1Id = 1L;
- String metric1Key = "polop";
- long metric2Id = 2L;
- QualityGateConditionDto cond1 = new QualityGateConditionDto().setMetricId(metric1Id);
- QualityGateConditionDto cond2 = new QualityGateConditionDto().setMetricId(metric2Id);
- Collection<QualityGateConditionDto> conditions = ImmutableList.of(cond1, cond2);
- when(conditionDao.selectForQualityGate(dbSession, qGateId)).thenReturn(conditions);
- Metric metric1 = mock(Metric.class);
- when(metric1.getKey()).thenReturn(metric1Key);
- when(metricFinder.findById((int) metric1Id)).thenReturn(metric1);
- underTest.listConditions(qGateId);
- }
-
@Test
public void should_copy_qgate() {
String name = "Atlantis";
verify(conditionDao, times(conditions.size())).insert(any(QualityGateConditionDto.class), eq(dbSession));
}
- @Test
- public void should_list_gate_metrics() {
- Metric dataMetric = mock(Metric.class);
- when(dataMetric.isDataType()).thenReturn(true);
- Metric hiddenMetric = mock(Metric.class);
- when(hiddenMetric.isHidden()).thenReturn(true);
- Metric nullHiddenMetric = mock(Metric.class);
- when(nullHiddenMetric.isHidden()).thenReturn(null);
- Metric alertMetric = CoreMetrics.ALERT_STATUS;
- Metric ratingMetric = mock(Metric.class);
- when(ratingMetric.getType()).thenReturn(ValueType.RATING);
- Metric classicMetric = mock(Metric.class);
- when(classicMetric.getType()).thenReturn(ValueType.BOOL);
- when(metricFinder.findAll()).thenReturn(ImmutableList.of(
- dataMetric, hiddenMetric, nullHiddenMetric, alertMetric, ratingMetric, classicMetric));
- }
-
}
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
-import org.sonar.api.measures.MetricFinder;
import org.sonar.api.server.ws.Change;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.System2;
import static java.lang.String.format;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
-import static org.mockito.Mockito.mock;
import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES;
import static org.sonar.server.qualitygate.QualityGates.SONAR_QUALITYGATE_PROPERTY;
private DbClient dbClient = db.getDbClient();
private DbSession dbSession = db.getSession();
private TestDefaultOrganizationProvider organizationProvider = TestDefaultOrganizationProvider.from(db);
- private QualityGates qualityGates = new QualityGates(dbClient, mock(MetricFinder.class), userSession, organizationProvider);
+ private QualityGates qualityGates = new QualityGates(dbClient, userSession, organizationProvider);
private WsActionTester ws;
private ComponentDto project;
private QualityGateDto gate;
assertThat(def.isPost()).isTrue();
assertThat(def.since()).isEqualTo("4.3");
assertThat(def.changelog()).extracting(Change::getVersion, Change::getDescription).containsExactly(
- tuple("6.6", "The parameter 'gateId' was removed")
- );
+ tuple("6.6", "The parameter 'gateId' was removed"));
assertThat(def.params()).extracting(WebService.Param::key)
.containsExactlyInAnyOrder("projectId", "projectKey");
import org.sonar.db.DbClient;
import org.sonar.db.qualitygate.ProjectQgateAssociation;
import org.sonar.db.qualitygate.ProjectQgateAssociationQuery;
-import org.sonar.db.qualitygate.QualityGateConditionDto;
import org.sonar.db.qualitygate.QualityGateDto;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.exceptions.BadRequestException;
tester = new WsTester(new QualityGatesWs(
new ListAction(qGates),
- new ShowAction(qGates),
new SearchAction(projectFinder),
new CreateAction(null, null, null, null),
new CopyAction(qGates),
assertThat(controller).isNotNull();
assertThat(controller.path()).isEqualTo("api/qualitygates");
assertThat(controller.description()).isNotEmpty();
- assertThat(controller.actions()).hasSize(15);
+ assertThat(controller.actions()).hasSize(14);
Action list = controller.action("list");
assertThat(list).isNotNull();
assertThat(list.isPost()).isFalse();
assertThat(list.isInternal()).isFalse();
- Action show = controller.action("show");
- assertThat(show).isNotNull();
- assertThat(show.handler()).isNotNull();
- assertThat(show.since()).isEqualTo("4.3");
- assertThat(show.isPost()).isFalse();
- assertThat(show.param("id")).isNotNull();
- assertThat(show.isInternal()).isFalse();
-
Action create = controller.action("create");
assertThat(create).isNotNull();
assertThat(create.handler()).isNotNull();
"{\"qualitygates\":[{\"id\":42,\"name\":\"Golden\"},{\"id\":43,\"name\":\"Star\"},{\"id\":666,\"name\":\"Ninth\"}],\"default\":42}");
}
- @Test
- public void show_empty() throws Exception {
- long gateId = 12345L;
- when(qGates.get(gateId)).thenReturn(new QualityGateDto().setId(gateId).setName("Golden"));
- tester.newGetRequest("api/qualitygates", "show").setParam("id", Long.toString(gateId)).execute().assertJson(
- "{\"id\":12345,\"name\":\"Golden\"}");
- }
-
- @Test
- public void show_by_id_nominal() throws Exception {
- long gateId = 12345L;
- when(qGates.get(gateId)).thenReturn(new QualityGateDto().setId(gateId).setName("Golden"));
- when(qGates.listConditions(gateId)).thenReturn(ImmutableList.of(
- new QualityGateConditionDto().setId(1L).setMetricKey("ncloc").setOperator("GT").setErrorThreshold("10000"),
- new QualityGateConditionDto().setId(2L).setMetricKey("new_coverage").setOperator("LT").setWarningThreshold("90").setPeriod(3)));
- tester.newGetRequest("api/qualitygates", "show").setParam("id", Long.toString(gateId)).execute().assertJson(
- "{\"id\":12345,\"name\":\"Golden\",\"conditions\":["
- + "{\"id\":1,\"metric\":\"ncloc\",\"op\":\"GT\",\"error\":\"10000\"},"
- + "{\"id\":2,\"metric\":\"new_coverage\",\"op\":\"LT\",\"warning\":\"90\",\"period\":3}"
- + "]}");
- }
-
- @Test
- public void show_by_name_nominal() throws Exception {
- long qGateId = 12345L;
- String gateName = "Golden";
- when(qGates.get(gateName)).thenReturn(new QualityGateDto().setId(qGateId).setName(gateName));
- when(qGates.listConditions(qGateId)).thenReturn(ImmutableList.of(
- new QualityGateConditionDto().setId(1L).setMetricKey("ncloc").setOperator("GT").setErrorThreshold("10000"),
- new QualityGateConditionDto().setId(2L).setMetricKey("new_coverage").setOperator("LT").setWarningThreshold("90").setPeriod(3)));
- tester.newGetRequest("api/qualitygates", "show").setParam("name", gateName).execute().assertJson(
- "{\"id\":12345,\"name\":\"Golden\",\"conditions\":["
- + "{\"id\":1,\"metric\":\"ncloc\",\"op\":\"GT\",\"error\":\"10000\"},"
- + "{\"id\":2,\"metric\":\"new_coverage\",\"op\":\"LT\",\"warning\":\"90\",\"period\":3}"
- + "]}");
- }
-
- @Test(expected = BadRequestException.class)
- public void show_without_parameters() throws Exception {
- tester.newGetRequest("api/qualitygates", "show").execute();
- }
-
- @Test(expected = BadRequestException.class)
- public void show_with_both_parameters() throws Exception {
- tester.newGetRequest("api/qualitygates", "show").setParam("id", "12345").setParam("name", "Polop").execute();
- }
-
@Test
public void search_with_query() throws Exception {
long gateId = 12345L;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.qualitygate.ws;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.server.ws.WebService.Param;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+import org.sonar.db.metric.MetricDto;
+import org.sonar.db.qualitygate.QualityGateConditionDto;
+import org.sonar.db.qualitygate.QualityGateDto;
+import org.sonar.server.qualitygate.QualityGateFinder;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsActionTester;
+import org.sonarqube.ws.Qualitygates.ShowWsResponse;
+import org.sonarqube.ws.Qualitygates.ShowWsResponse.Condition;
+
+import static java.lang.String.format;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.AssertionsForClassTypes.tuple;
+import static org.sonar.test.JsonAssert.assertJson;
+
+public class ShowActionTest {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
+ @Rule
+ public DbTester db = DbTester.create(System2.INSTANCE);
+
+ private WsActionTester ws = new WsActionTester(new ShowAction(db.getDbClient(), new QualityGateFinder(db.getDbClient())));
+
+ @Test
+ public void verify_definition() {
+ WebService.Action action = ws.getDef();
+ assertThat(action.since()).isEqualTo("4.3");
+ assertThat(action.changelog()).isEmpty();
+ assertThat(action.params())
+ .extracting(Param::key, Param::isRequired)
+ .containsExactlyInAnyOrder(tuple("id", false), tuple("name", false));
+ }
+
+ @Test
+ public void json_example() {
+ QualityGateDto qualityGate = db.qualityGates().insertQualityGate("My Quality Gate");
+ MetricDto blockerViolationsMetric = db.measures().insertMetric(m -> m.setKey("blocker_violations"));
+ MetricDto criticalViolationsMetric = db.measures().insertMetric(m -> m.setKey("critical_violations"));
+ db.qualityGates().addCondition(qualityGate, blockerViolationsMetric, c -> c.setOperator("GT").setPeriod(null).setErrorThreshold("0").setWarningThreshold(null));
+ db.qualityGates().addCondition(qualityGate, criticalViolationsMetric, c -> c.setOperator("LT").setPeriod(1).setErrorThreshold(null).setWarningThreshold("0"));
+
+ String response = ws.newRequest()
+ .setParam("name", qualityGate.getName())
+ .execute()
+ .getInput();
+
+ assertJson(response).ignoreFields("id")
+ .isSimilarTo(getClass().getResource("show-example.json"));
+ }
+
+ @Test
+ public void show() {
+ QualityGateDto qualityGate = db.qualityGates().insertQualityGate();
+ MetricDto metric = db.measures().insertMetric();
+ QualityGateConditionDto condition1 = db.qualityGates().addCondition(qualityGate, metric, c -> c.setOperator("GT").setPeriod(null));
+ QualityGateConditionDto condition2 = db.qualityGates().addCondition(qualityGate, metric, c -> c.setOperator("LT").setPeriod(1));
+
+ ShowWsResponse response = ws.newRequest().setParam("name", qualityGate.getName())
+ .executeProtobuf(ShowWsResponse.class);
+
+ assertThat(response.getId()).isEqualTo(qualityGate.getId());
+ assertThat(response.getName()).isEqualTo(qualityGate.getName());
+ assertThat(response.getConditionsList()).hasSize(2);
+ assertThat(response.getConditionsList())
+ .extracting(Condition::getId, Condition::getMetric, Condition::hasPeriod, Condition::getPeriod, Condition::getOp, Condition::getError, Condition::getWarning)
+ .containsExactlyInAnyOrder(
+ tuple(condition1.getId(), metric.getKey(), false, 0, "GT", condition1.getErrorThreshold(), condition1.getWarningThreshold()),
+ tuple(condition2.getId(), metric.getKey(), true, 1, "LT", condition2.getErrorThreshold(), condition2.getWarningThreshold()));
+ }
+
+ @Test
+ public void show_by_id() {
+ QualityGateDto qualityGate = db.qualityGates().insertQualityGate();
+
+ ShowWsResponse response = ws.newRequest().setParam("id", qualityGate.getId().toString())
+ .executeProtobuf(ShowWsResponse.class);
+
+ assertThat(response.getId()).isEqualTo(qualityGate.getId());
+ assertThat(response.getName()).isEqualTo(qualityGate.getName());
+ }
+
+ @Test
+ public void no_condition() {
+ QualityGateDto qualityGate = db.qualityGates().insertQualityGate();
+
+ ShowWsResponse response = ws.newRequest().setParam("name", qualityGate.getName())
+ .executeProtobuf(ShowWsResponse.class);
+
+ assertThat(response.getId()).isEqualTo(qualityGate.getId());
+ assertThat(response.getName()).isEqualTo(qualityGate.getName());
+ assertThat(response.getConditionsList()).isEmpty();
+ }
+
+ @Test
+ public void fail_when_no_name_or_id() {
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("Either 'id' or 'name' must be provided");
+
+ ws.newRequest().execute();
+ }
+
+ @Test
+ public void fail_when_both_name_or_id() {
+ QualityGateDto qualityGate = db.qualityGates().insertQualityGate();
+
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("Either 'id' or 'name' must be provided");
+
+ ws.newRequest()
+ .setParam("name", qualityGate.getName())
+ .setParam("id", qualityGate.getId().toString())
+ .execute();
+ }
+
+ @Test
+ public void fail_when_condition_is_on_disabled_metric() {
+ QualityGateDto qualityGate = db.qualityGates().insertQualityGate();
+ MetricDto metric = db.measures().insertMetric();
+ db.qualityGates().addCondition(qualityGate, metric);
+ db.getDbClient().metricDao().disableCustomByKey(db.getSession(), metric.getKey());
+ db.commit();
+
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage(format("Could not find metric with id %s", metric.getId()));
+
+ ws.newRequest()
+ .setParam("name", qualityGate.getName())
+ .execute();
+ }
+}
optional int32 period = 6;
}
+// GET api/qualitygates/show
+message ShowWsResponse {
+ optional int64 id = 1;
+ optional string name = 2;
+ repeated Condition conditions = 3;
+
+ message Condition {
+ optional int64 id = 1;
+ optional string metric = 2;
+ optional int32 period = 3;
+ optional string op = 4;
+ optional string warning = 5;
+ optional string error = 6;
+ }
+}
+