]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8117 Extract update of quality gate condition into QualityGateConditionsUpdater
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Tue, 20 Sep 2016 17:32:01 +0000 (19:32 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Thu, 22 Sep 2016 12:10:31 +0000 (14:10 +0200)
13 files changed:
server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGateConditionsUpdater.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/UpdateConditionAction.java
server/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGateConditionsUpdaterTest.java
server/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGatesTest.java
server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QualityGatesWsTest.java
server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/UpdateConditionActionTest.java [new file with mode: 0644]
sonar-ws/src/main/java/org/sonarqube/ws/client/qualitygate/QualityGatesService.java
sonar-ws/src/main/java/org/sonarqube/ws/client/qualitygate/QualityGatesWsParameters.java
sonar-ws/src/main/java/org/sonarqube/ws/client/qualitygate/UpdateConditionRequest.java [new file with mode: 0644]
sonar-ws/src/main/protobuf/ws-qualitygates.proto
sonar-ws/src/test/java/org/sonarqube/ws/client/qualitygate/QualityGatesServiceTest.java
sonar-ws/src/test/java/org/sonarqube/ws/client/qualitygate/UpdateConditionRequestTest.java [new file with mode: 0644]

index f5a988c1ce57bb2f8a41df7a6ed8df15b9ae8b9e..1dbe6f9150e50ad38507add5ce7b345b762c2a2f 100644 (file)
@@ -65,6 +65,24 @@ public class QualityGateConditionsUpdater {
     return newCondition;
   }
 
+  public QualityGateConditionDto updateCondition(DbSession dbSession, long condId, String metricKey, String operator,
+    @Nullable String warningThreshold, @Nullable String errorThreshold, @Nullable Integer period) {
+    QualityGateConditionDto condition = getNonNullCondition(dbSession, condId);
+    MetricDto metric = getNonNullMetric(dbSession, metricKey);
+    validateCondition(metric, operator, warningThreshold, errorThreshold, period);
+    checkConditionDoesNotAlreadyExistOnSameMetricAndPeriod(getConditions(dbSession, condition.getQualityGateId(), condition.getId()), metric, period);
+
+    condition
+      .setMetricId(metric.getId())
+      .setMetricKey(metric.getKey())
+      .setOperator(operator)
+      .setWarningThreshold(warningThreshold)
+      .setErrorThreshold(errorThreshold)
+      .setPeriod(period);
+    dbClient.gateConditionDao().update(condition, dbSession);
+    return condition;
+  }
+
   private QualityGateDto getNonNullQgate(DbSession dbSession, long id) {
     QualityGateDto qGate = dbClient.qualityGateDao().selectById(dbSession, id);
     if (qGate == null) {
@@ -81,6 +99,14 @@ public class QualityGateConditionsUpdater {
     return metric;
   }
 
+  private QualityGateConditionDto getNonNullCondition(DbSession dbSession, long id) {
+    QualityGateConditionDto condition = dbClient.gateConditionDao().selectById(id, dbSession);
+    if (condition == null) {
+      throw new NotFoundException("There is no condition with id=" + id);
+    }
+    return condition;
+  }
+
   private Collection<QualityGateConditionDto> getConditions(DbSession dbSession, long qGateId, @Nullable Long conditionId) {
     Collection<QualityGateConditionDto> conditions = dbClient.gateConditionDao().selectForQualityGate(qGateId, dbSession);
     if (conditionId == null) {
index 5dfa118f475c02985150585afd52c24b9a64a557..4743bb2871776249418cf47e56d342118d1c1f21 100644 (file)
  */
 package org.sonar.server.qualitygate;
 
-import com.google.common.base.Predicate;
 import com.google.common.base.Strings;
 import java.util.Collection;
-import java.util.stream.Collectors;
 import javax.annotation.CheckForNull;
-import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
-import org.apache.commons.lang.BooleanUtils;
-import org.apache.commons.lang.ObjectUtils;
 import org.apache.commons.lang.StringUtils;
-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.api.web.UserRole;
 import org.sonar.core.permission.GlobalPermissions;
@@ -54,8 +47,6 @@ import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.user.UserSession;
 import org.sonar.server.util.Validation;
 
-import static java.lang.String.format;
-
 /**
  * Methods from this class should be moved to {@link QualityGateUpdater} and to new classes QualityGateFinder / QualityGateConditionsUpdater / etc.
  * in order to have classes with clearer responsibilities and more easily testable (without having to use too much mocks)
@@ -170,24 +161,6 @@ public class QualityGates {
     }
   }
 
-  public QualityGateConditionDto updateCondition(long condId, String metricKey, String operator,
-    @Nullable String warningThreshold, @Nullable String errorThreshold, @Nullable Integer period) {
-    checkPermission();
-    QualityGateConditionDto condition = getNonNullCondition(condId);
-    Metric metric = getNonNullMetric(metricKey);
-    validateCondition(metric, operator, warningThreshold, errorThreshold, period);
-    checkConditionDoesNotAlreadyExistOnSameMetricAndPeriod(getConditions(condition.getQualityGateId(), condition.getId()), metric, period);
-    condition
-      .setMetricId(metric.getId())
-      .setMetricKey(metric.getKey())
-      .setOperator(operator)
-      .setWarningThreshold(warningThreshold)
-      .setErrorThreshold(errorThreshold)
-      .setPeriod(period);
-    conditionDao.update(condition);
-    return condition;
-  }
-
   public Collection<QualityGateConditionDto> listConditions(long qGateId) {
     Collection<QualityGateConditionDto> conditionsForGate = conditionDao.selectForQualityGate(qGateId);
     for (QualityGateConditionDto condition : conditionsForGate) {
@@ -227,70 +200,6 @@ public class QualityGates {
     }
   }
 
-  private Collection<QualityGateConditionDto> getConditions(long qGateId, @Nullable Long conditionId) {
-    Collection<QualityGateConditionDto> conditions = conditionDao.selectForQualityGate(qGateId);
-    if (conditionId == null) {
-      return conditions;
-    }
-    return conditionDao.selectForQualityGate(qGateId).stream()
-      .filter(condition -> condition.getId() != conditionId)
-      .collect(Collectors.toList());
-  }
-
-  private static void validateCondition(Metric metric, String operator, @Nullable String warningThreshold, @Nullable String errorThreshold, @Nullable Integer period) {
-    Errors errors = new Errors();
-    validateMetric(metric, errors);
-    checkOperator(metric, operator, errors);
-    checkThresholds(warningThreshold, errorThreshold, errors);
-    checkPeriod(metric, period, errors);
-    if (!errors.isEmpty()) {
-      throw new BadRequestException(errors);
-    }
-  }
-
-  private static void checkConditionDoesNotAlreadyExistOnSameMetricAndPeriod(Collection<QualityGateConditionDto> conditions, Metric metric, @Nullable final Integer period) {
-    if (conditions.isEmpty()) {
-      return;
-    }
-
-    boolean conditionExists = conditions.stream().anyMatch(new MatchMetricAndPeriod(metric.getId(), period)::apply);
-    if (conditionExists) {
-      String errorMessage = period == null
-        ? format("Condition on metric '%s' already exists.", metric.getName())
-        : format("Condition on metric '%s' over leak period already exists.", metric.getName());
-      throw new BadRequestException(errorMessage);
-    }
-  }
-
-  private static void checkPeriod(Metric metric, @Nullable Integer period, Errors errors) {
-    if (period == null) {
-      errors.check(!metric.getKey().startsWith("new_"), "A period must be selected for differential metrics.");
-    } else {
-      errors.check(period == 1, "The only valid quality gate period is 1, the leak period.");
-    }
-  }
-
-  private static void checkThresholds(@Nullable String warningThreshold, @Nullable String errorThreshold, Errors errors) {
-    errors.check(warningThreshold != null || errorThreshold != null, "At least one threshold (warning, error) must be set.");
-  }
-
-  private static void checkOperator(Metric metric, String operator, Errors errors) {
-    errors
-      .check(QualityGateConditionDto.isOperatorAllowed(operator, metric.getType()), format("Operator %s is not allowed for metric type %s.", operator, metric.getType()));
-  }
-
-  private static void validateMetric(Metric metric, Errors errors) {
-    errors.check(isAlertable(metric), format("Metric '%s' cannot be used to define a condition.", metric.getKey()));
-  }
-
-  private static boolean isAlertable(Metric metric) {
-    return isAvailableForInit(metric) && BooleanUtils.isFalse(metric.isHidden());
-  }
-
-  private static boolean isAvailableForInit(Metric metric) {
-    return !metric.isDataType() && !CoreMetrics.ALERT_STATUS.equals(metric) && ValueType.RATING != metric.getType();
-  }
-
   private boolean isDefault(QualityGateDto qGate) {
     return qGate.getId().equals(getDefaultId());
   }
@@ -329,14 +238,6 @@ public class QualityGates {
     return qGate;
   }
 
-  private Metric getNonNullMetric(String metricKey) {
-    Metric metric = metricFinder.findByKey(metricKey);
-    if (metric == null) {
-      throw new NotFoundException("There is no metric with key=" + metricKey);
-    }
-    return metric;
-  }
-
   private QualityGateConditionDto getNonNullCondition(long id) {
     QualityGateConditionDto condition = conditionDao.selectById(id);
     if (condition == null) {
@@ -374,21 +275,4 @@ public class QualityGates {
       throw new ForbiddenException("Insufficient privileges");
     }
   }
-
-  private static class MatchMetricAndPeriod implements Predicate<QualityGateConditionDto> {
-    private final int metricId;
-    @CheckForNull
-    private final Integer period;
-
-    public MatchMetricAndPeriod(int metricId, @Nullable Integer period) {
-      this.metricId = metricId;
-      this.period = period;
-    }
-
-    @Override
-    public boolean apply(@Nonnull QualityGateConditionDto input) {
-      return input.getMetricId() == metricId &&
-        ObjectUtils.equals(input.getPeriod(), period);
-    }
-  }
 }
index 1c9f637a59ec9ae8531288f9ddc6e6c3de4944b1..b5a427a617ffe29652ecd49adff488b640982bc0 100644 (file)
@@ -22,46 +22,98 @@ package org.sonar.server.qualitygate.ws;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
-import org.sonar.server.qualitygate.QualityGates;
-import org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.qualitygate.QualityGateConditionDto;
+import org.sonar.server.qualitygate.QualityGateConditionsUpdater;
+import org.sonar.server.user.UserSession;
+import org.sonarqube.ws.WsQualityGates.UpdateConditionWsResponse;
+import org.sonarqube.ws.client.qualitygate.UpdateConditionRequest;
+
+import static org.sonar.core.permission.GlobalPermissions.QUALITY_GATE_ADMIN;
+import static org.sonar.server.qualitygate.ws.QualityGatesWs.addConditionParams;
+import static org.sonar.server.ws.WsUtils.writeProtobuf;
+import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.ACTION_UPDATE_CONDITION;
+import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_ERROR;
+import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_ID;
+import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_METRIC;
+import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_OPERATOR;
+import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_PERIOD;
+import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_WARNING;
 
 public class UpdateConditionAction implements QualityGatesWsAction {
 
-  private final QualityGates qualityGates;
+  private final UserSession userSession;
+  private final DbClient dbClient;
+  private final QualityGateConditionsUpdater qualityGateConditionsUpdater;
 
-  public UpdateConditionAction(QualityGates qualityGates) {
-    this.qualityGates = qualityGates;
+  public UpdateConditionAction(UserSession userSession, DbClient dbClient, QualityGateConditionsUpdater qualityGateConditionsUpdater) {
+    this.userSession = userSession;
+    this.dbClient = dbClient;
+    this.qualityGateConditionsUpdater = qualityGateConditionsUpdater;
   }
 
   @Override
   public void define(WebService.NewController controller) {
-    WebService.NewAction createCondition = controller.createAction("update_condition")
+    WebService.NewAction createCondition = controller.createAction(ACTION_UPDATE_CONDITION)
       .setDescription("Update a condition attached to a quality gate. Require Administer Quality Gates permission")
       .setPost(true)
       .setSince("4.3")
       .setHandler(this);
 
     createCondition
-      .createParam(QualityGatesWsParameters.PARAM_ID)
+      .createParam(PARAM_ID)
       .setDescription("Condition ID")
       .setRequired(true)
       .setExampleValue("10");
 
-    QualityGatesWs.addConditionParams(createCondition);
+    addConditionParams(createCondition);
   }
 
   @Override
   public void handle(Request request, Response response) {
-    QualityGatesWs.writeQualityGateCondition(
-      qualityGates.updateCondition(
-        QualityGatesWs.parseId(request, QualityGatesWsParameters.PARAM_ID),
-        request.mandatoryParam(QualityGatesWsParameters.PARAM_METRIC),
-        request.mandatoryParam(QualityGatesWsParameters.PARAM_OPERATOR),
-        request.param(QualityGatesWsParameters.PARAM_WARNING),
-        request.param(QualityGatesWsParameters.PARAM_ERROR),
-        request.paramAsInt(QualityGatesWsParameters.PARAM_PERIOD)
-        ), response.newJsonWriter()
-      ).close();
+    userSession.checkPermission(QUALITY_GATE_ADMIN);
+
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      writeProtobuf(doHandle(toWsRequest(request), dbSession), request, response);
+      dbSession.commit();
+    } finally {
+      dbClient.closeSession(dbSession);
+    }
+  }
+
+  private UpdateConditionWsResponse doHandle(UpdateConditionRequest request, DbSession dbSession) {
+    QualityGateConditionDto condition = qualityGateConditionsUpdater.updateCondition(dbSession, request.getConditionId(), request.getMetricKey(), request.getOperator(),
+      request.getWarning(), request.getError(), request.getPeriod());
+    UpdateConditionWsResponse.Builder response = UpdateConditionWsResponse.newBuilder()
+      .setId(condition.getId())
+      .setMetric(condition.getMetricKey())
+      .setOp(condition.getOperator());
+    String warning = condition.getWarningThreshold();
+    if (warning != null) {
+      response.setWarning(warning);
+    }
+    String error = condition.getErrorThreshold();
+    if (error != null) {
+      response.setError(error);
+    }
+    Integer period = condition.getPeriod();
+    if (period != null) {
+      response.setPeriod(period);
+    }
+    return response.build();
+  }
+
+  private static UpdateConditionRequest toWsRequest(Request request) {
+    return UpdateConditionRequest.builder()
+      .setConditionId(request.mandatoryParamAsInt(PARAM_ID))
+      .setMetricKey(request.mandatoryParam(PARAM_METRIC))
+      .setOperator(request.mandatoryParam(PARAM_OPERATOR))
+      .setWarning(request.param(PARAM_WARNING))
+      .setError(request.param(PARAM_ERROR))
+      .setPeriod(request.paramAsInt(PARAM_PERIOD))
+      .build();
   }
 
 }
index 8bd0c1194bd9b3769f386415effc83a600ff18ce..dab499a560f7724a9994722eaf152d7e71ec05b6 100644 (file)
@@ -23,6 +23,7 @@ package org.sonar.server.qualitygate;
 import com.tngtech.java.junit.dataprovider.DataProvider;
 import com.tngtech.java.junit.dataprovider.DataProviderRunner;
 import com.tngtech.java.junit.dataprovider.UseDataProvider;
+import javax.annotation.Nullable;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -73,7 +74,6 @@ public class QualityGateConditionsUpdaterTest {
   @Before
   public void setUp() throws Exception {
     qualityGateDto = qualityGateDbTester.insertQualityGate();
-
     dbClient.metricDao().insert(dbSession, coverageMetricDto);
     dbSession.commit();
   }
@@ -82,13 +82,7 @@ public class QualityGateConditionsUpdaterTest {
   public void create_warning_condition_without_period() {
     QualityGateConditionDto result = underTest.createCondition(dbSession, qualityGateDto.getId(), "coverage", "LT", "90", null, null);
 
-    assertThat(result.getQualityGateId()).isEqualTo(qualityGateDto.getId());
-    assertThat(result.getMetricId()).isEqualTo(coverageMetricDto.getId().longValue());
-    assertThat(result.getOperator()).isEqualTo("LT");
-    assertThat(result.getWarningThreshold()).isEqualTo("90");
-    assertThat(result.getErrorThreshold()).isNull();
-    assertThat(result.getPeriod()).isNull();
-    assertThat(dbClient.gateConditionDao().selectById(result.getId(), dbSession)).isNotNull();
+    verifyCondition(result, coverageMetricDto.getId(), "LT", "90", null, null);
   }
 
   @Test
@@ -101,14 +95,7 @@ public class QualityGateConditionsUpdaterTest {
 
     QualityGateConditionDto result = underTest.createCondition(dbSession, qualityGateDto.getId(), "new_coverage", "LT", null, "80", 1);
 
-    assertThat(result.getQualityGateId()).isEqualTo(qualityGateDto.getId());
-    assertThat(result.getMetricId()).isEqualTo(metricDto.getId().longValue());
-    assertThat(result.getMetricKey()).isEqualTo("new_coverage");
-    assertThat(result.getOperator()).isEqualTo("LT");
-    assertThat(result.getWarningThreshold()).isNull();
-    assertThat(result.getErrorThreshold()).isEqualTo("80");
-    assertThat(result.getPeriod()).isEqualTo(1);
-    assertThat(dbClient.gateConditionDao().selectById(result.getId(), dbSession)).isNotNull();
+    verifyCondition(result, metricDto.getId(), "LT", null, "80", 1);
   }
 
   @Test
@@ -127,9 +114,9 @@ public class QualityGateConditionsUpdaterTest {
   @Test
   public void fail_to_create_condition_when_condition_on_same_metric_and_on_leak_period_already_exist() throws Exception {
     dbClient.gateConditionDao().insert(new QualityGateConditionDto()
-        .setQualityGateId(qualityGateDto.getId())
-        .setMetricId(coverageMetricDto.getId())
-        .setPeriod(1),
+      .setQualityGateId(qualityGateDto.getId())
+      .setMetricId(coverageMetricDto.getId())
+      .setPeriod(1),
       dbSession);
 
     expectedException.expect(BadRequestException.class);
@@ -185,6 +172,50 @@ public class QualityGateConditionsUpdaterTest {
     underTest.createCondition(dbSession, qualityGateDto.getId(), "coverage", "EQ", null, "90", 6);
   }
 
+  @Test
+  public void update_condition() {
+    QualityGateConditionDto condition = insertCondition(coverageMetricDto.getId(), "LT", null, "80", null);
+
+    QualityGateConditionDto result = underTest.updateCondition(dbSession, condition.getId(), "coverage", "GT", "60", null, 1);
+
+    verifyCondition(result, coverageMetricDto.getId(), "GT", "60", null, 1);
+  }
+
+  @Test
+  public void update_condition_over_leak_period() {
+    QualityGateConditionDto condition = insertCondition(coverageMetricDto.getId(), "GT", "80", null, 1);
+
+    QualityGateConditionDto result = underTest.updateCondition(dbSession, condition.getId(), "coverage", "LT", null, "80", null);
+
+    verifyCondition(result, coverageMetricDto.getId(), "LT", null, "80", null);
+  }
+
+  @Test
+  @UseDataProvider("invalid_metrics")
+  public void fail_to_update_condition_on_invalid_metric(String metricKey, Metric.ValueType valueType, boolean hidden) {
+    MetricDto metricDto = dbClient.metricDao().insert(dbSession, newMetricDto()
+      .setKey(metricKey)
+      .setValueType(valueType.name())
+      .setHidden(hidden));
+    QualityGateConditionDto condition = insertCondition(metricDto.getId(), "LT", null, "80", null);
+    dbSession.commit();
+
+    expectedException.expect(BadRequestException.class);
+    expectedException.expectMessage("Metric '" + metricKey + "' cannot be used to define a condition.");
+    underTest.updateCondition(dbSession, condition.getId(), metricDto.getKey(), "GT", "60", null, 1);
+  }
+
+  @Test
+  public void fail_to_update_condition_when_condition_on_same_metric_already_exist() throws Exception {
+    QualityGateConditionDto conditionNotOnLeakPeriod = insertCondition(coverageMetricDto.getId(), "GT", "80", null, null);
+    QualityGateConditionDto conditionOnLeakPeriod = insertCondition(coverageMetricDto.getId(), "GT", "80", null, 1);
+
+    expectedException.expect(BadRequestException.class);
+    expectedException.expectMessage("Condition on metric 'Coverage' over leak period already exists.");
+    // Update condition not on leak period to be on leak period => will fail as this condition already exist
+    underTest.updateCondition(dbSession, conditionNotOnLeakPeriod.getId(), coverageMetricDto.getKey(), "GT", "80", null, 1);
+  }
+
   @DataProvider
   public static Object[][] invalid_metrics() {
     return new Object[][] {
@@ -195,4 +226,34 @@ public class QualityGateConditionsUpdaterTest {
     };
   }
 
+  private QualityGateConditionDto insertCondition(long metricId, String operator, @Nullable String warning, @Nullable String error,
+    @Nullable Integer period) {
+    QualityGateConditionDto qualityGateConditionDto = new QualityGateConditionDto().setQualityGateId(qualityGateDto.getId())
+      .setMetricId(metricId)
+      .setOperator(operator)
+      .setWarningThreshold(warning)
+      .setErrorThreshold(error)
+      .setPeriod(period);
+    dbClient.gateConditionDao().insert(qualityGateConditionDto, dbSession);
+    dbSession.commit();
+    return qualityGateConditionDto;
+  }
+
+  private void verifyCondition(QualityGateConditionDto dto, int metricId, String operator, @Nullable String warning, @Nullable String error, @Nullable Integer period) {
+    QualityGateConditionDto reloaded = dbClient.gateConditionDao().selectById(dto.getId(), dbSession);
+    assertThat(reloaded.getQualityGateId()).isEqualTo(qualityGateDto.getId());
+    assertThat(reloaded.getMetricId()).isEqualTo(metricId);
+    assertThat(reloaded.getOperator()).isEqualTo(operator);
+    assertThat(reloaded.getWarningThreshold()).isEqualTo(warning);
+    assertThat(reloaded.getErrorThreshold()).isEqualTo(error);
+    assertThat(reloaded.getPeriod()).isEqualTo(period);
+
+    assertThat(dto.getQualityGateId()).isEqualTo(qualityGateDto.getId());
+    assertThat(dto.getMetricId()).isEqualTo(metricId);
+    assertThat(dto.getOperator()).isEqualTo(operator);
+    assertThat(dto.getWarningThreshold()).isEqualTo(warning);
+    assertThat(dto.getErrorThreshold()).isEqualTo(error);
+    assertThat(dto.getPeriod()).isEqualTo(period);
+  }
+
 }
index 8a12dd1f046e47035e0fa37a0f715960b852ce93..8f10230fe31e1da355297cebf50bd0535b359f73 100644 (file)
@@ -57,8 +57,6 @@ import org.sonar.server.tester.MockUserSession;
 import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.user.UserSession;
 
-import static java.util.Arrays.asList;
-import static java.util.Collections.singletonList;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyLong;
@@ -260,37 +258,6 @@ public class QualityGatesTest {
     assertThat(underTest.getDefault()).isNull();
   }
 
-  @Test
-  public void should_update_condition() {
-    String metricKey = "new_coverage";
-    String operator = "LT";
-    String errorThreshold = "80";
-    addMetric(metricKey, "New Coverage");
-
-    QualityGateConditionDto condition = insertQualityGateConditionDto(newCondition(metricKey, METRIC_ID));
-    when(conditionDao.selectForQualityGate(QUALITY_GATE_ID)).thenReturn(singletonList(condition));
-
-    assertThat(underTest.updateCondition(condition.getId(), metricKey, operator, null, errorThreshold, 1)).isEqualTo(condition);
-    verify(conditionDao).update(condition);
-  }
-
-  @Test
-  public void fail_to_update_condition_when_condition_on_same_metric_already_exist() throws Exception {
-    String metricKey = "coverage";
-    addMetric(metricKey, "Coverage");
-    when(dao.selectById(QUALITY_GATE_ID)).thenReturn(new QualityGateDto().setId(QUALITY_GATE_ID));
-
-    QualityGateConditionDto conditionNotOnLeakPeriod = insertQualityGateConditionDto(newCondition(metricKey, METRIC_ID)).setPeriod(0);
-    QualityGateConditionDto conditionOnLeakPeriod = insertQualityGateConditionDto(newCondition(metricKey, METRIC_ID)).setPeriod(1);
-    when(conditionDao.selectForQualityGate(QUALITY_GATE_ID)).thenReturn(asList(conditionNotOnLeakPeriod, conditionOnLeakPeriod));
-
-    expectedException.expect(BadRequestException.class);
-    expectedException.expectMessage("Condition on metric 'Coverage' over leak period already exists.");
-
-    // Update condition not on leak period to be on leak period => will fail as this condition already exist
-    underTest.updateCondition(conditionNotOnLeakPeriod.getId(), metricKey, "LT", null, "60", 1);
-  }
-
   @Test
   public void should_list_conditions() {
     long qGateId = QUALITY_GATE_ID;
index c5e1430bc25e5b88369c9e5216fcf4c8d0c50e44..bfdbee6307ef8d96f0276b8af1c3d7bb60b2e2b6 100644 (file)
@@ -72,7 +72,7 @@ public class QualityGatesWsTest {
       new ListAction(qGates), new ShowAction(qGates), new SearchAction(projectFinder),
       new CreateAction(null, null, null), new CopyAction(qGates), new DestroyAction(qGates), new RenameAction(qGates),
       new SetAsDefaultAction(qGates), new UnsetDefaultAction(qGates),
-      new CreateConditionAction(null, null, null), new UpdateConditionAction(qGates), new DeleteConditionAction(qGates),
+      new CreateConditionAction(null, null, null), new UpdateConditionAction(null, null, null), new DeleteConditionAction(qGates),
       selectAction, new DeselectAction(qGates, mock(DbClient.class), mock(ComponentFinder.class)), new AppAction(null, null)));
   }
 
@@ -305,26 +305,6 @@ public class QualityGatesWsTest {
     tester.newGetRequest("api/qualitygates", "show").setParam("id", "12345").setParam("name", "Polop").execute();
   }
 
-  @Test
-  public void update_condition_nominal() throws Exception {
-    long condId = 12345L;
-    String metricKey = "coverage";
-    String operator = "LT";
-    String warningThreshold = "80";
-    String errorThreshold = "75";
-    when(qGates.updateCondition(condId, metricKey, operator, warningThreshold, errorThreshold, null))
-      .thenReturn(new QualityGateConditionDto().setId(condId).setMetricId(10).setMetricKey(metricKey)
-        .setOperator(operator).setWarningThreshold(warningThreshold).setErrorThreshold(errorThreshold));
-    tester.newPostRequest("api/qualitygates", "update_condition")
-      .setParam("id", Long.toString(condId))
-      .setParam("metric", metricKey)
-      .setParam("op", operator)
-      .setParam("warning", warningThreshold)
-      .setParam("error", errorThreshold)
-      .execute()
-      .assertJson("{\"id\":12345,\"metric\":\"coverage\",\"op\":\"LT\",\"warning\":\"80\",\"error\":\"75\"}");
-  }
-
   @Test
   public void delete_condition_nominal() throws Exception {
     long condId = 12345L;
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/UpdateConditionActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/UpdateConditionActionTest.java
new file mode 100644 (file)
index 0000000..9c8acdf
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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 java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import javax.annotation.Nullable;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.metric.MetricDto;
+import org.sonar.db.qualitygate.QualityGateConditionDto;
+import org.sonar.db.qualitygate.QualityGateDbTester;
+import org.sonar.db.qualitygate.QualityGateDto;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.qualitygate.QualityGateConditionsUpdater;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.WsActionTester;
+import org.sonarqube.ws.MediaTypes;
+import org.sonarqube.ws.WsQualityGates.CreateConditionWsResponse;
+
+import static org.assertj.core.api.Java6Assertions.assertThat;
+import static org.sonar.core.permission.GlobalPermissions.QUALITY_GATE_ADMIN;
+import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION;
+import static org.sonar.db.metric.MetricTesting.newMetricDto;
+import static org.sonar.server.computation.task.projectanalysis.metric.Metric.MetricType.PERCENT;
+import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_ERROR;
+import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_ID;
+import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_METRIC;
+import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_OPERATOR;
+import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_PERIOD;
+import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_WARNING;
+
+public class UpdateConditionActionTest {
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Rule
+  public UserSessionRule userSession = UserSessionRule.standalone();
+
+  @Rule
+  public DbTester db = DbTester.create(System2.INSTANCE);
+
+  DbClient dbClient = db.getDbClient();
+  DbSession dbSession = db.getSession();
+  QualityGateDbTester qualityGateDbTester = new QualityGateDbTester(db);
+
+  UpdateConditionAction underTest = new UpdateConditionAction(userSession, dbClient, new QualityGateConditionsUpdater(dbClient));
+
+  QualityGateDto qualityGateDto;
+  QualityGateConditionDto conditionDto;
+
+  MetricDto coverageMetricDto = newMetricDto()
+    .setKey("coverage")
+    .setShortName("Coverage")
+    .setValueType(PERCENT.name())
+    .setHidden(false);
+
+  WsActionTester ws = new WsActionTester(underTest);
+
+  @Before
+  public void setUp() throws Exception {
+    MetricDto metricDto = dbClient.metricDao().insert(dbSession, coverageMetricDto);
+    qualityGateDto = qualityGateDbTester.insertQualityGate();
+    conditionDto = new QualityGateConditionDto().setQualityGateId(qualityGateDto.getId())
+      .setMetricId(metricDto.getId())
+      .setOperator("GT")
+      .setWarningThreshold(null)
+      .setErrorThreshold("80")
+      .setPeriod(1);
+    dbClient.gateConditionDao().insert(conditionDto, dbSession);
+    dbSession.commit();
+  }
+
+  @Test
+  public void update_warning_condition() throws Exception {
+    setUserAsQualityGateAdmin();
+
+    CreateConditionWsResponse response = executeRequest(conditionDto.getId(), coverageMetricDto.getKey(), "LT", "90", null, null);
+
+    assertCondition(response, "LT", "90", null, null);
+  }
+
+  @Test
+  public void update_error_condition() throws Exception {
+    setUserAsQualityGateAdmin();
+
+    CreateConditionWsResponse response = executeRequest(conditionDto.getId(), coverageMetricDto.getKey(), "LT", null, "90", null);
+
+    assertCondition(response, "LT", null, "90", null);
+  }
+
+  @Test
+  public void update_condition_over_leak_period() throws Exception {
+    setUserAsQualityGateAdmin();
+
+    CreateConditionWsResponse response = executeRequest(conditionDto.getId(), coverageMetricDto.getKey(), "LT", null, "90", 1);
+
+    assertCondition(response, "LT", null, "90", 1);
+  }
+
+  @Test
+  public void fail_when_not_quality_gate_admin() throws Exception {
+    setUserAsNotQualityGateAdmin();
+
+    expectedException.expect(ForbiddenException.class);
+    executeRequest(conditionDto.getId(), coverageMetricDto.getKey(), "LT", "90", null, null);
+  }
+
+  @Test
+  public void test_ws_definition() {
+    WebService.Action action = ws.getDef();
+    assertThat(action).isNotNull();
+    assertThat(action.isInternal()).isFalse();
+    assertThat(action.isPost()).isTrue();
+    assertThat(action.responseExampleAsString()).isNull();
+    assertThat(action.params()).hasSize(6);
+  }
+
+  private void assertCondition(CreateConditionWsResponse response, String operator, @Nullable String warning, @Nullable String error, @Nullable Integer period) {
+    List<QualityGateConditionDto> conditionDtoList = new ArrayList<>(dbClient.gateConditionDao().selectForQualityGate(qualityGateDto.getId(), dbSession));
+    assertThat(conditionDtoList).hasSize(1);
+    QualityGateConditionDto qualityGateConditionDto = conditionDtoList.get(0);
+    assertThat(qualityGateConditionDto.getQualityGateId()).isEqualTo(qualityGateDto.getId());
+    assertThat(qualityGateConditionDto.getMetricId()).isEqualTo(coverageMetricDto.getId().longValue());
+    assertThat(qualityGateConditionDto.getOperator()).isEqualTo(operator);
+    assertThat(qualityGateConditionDto.getWarningThreshold()).isEqualTo(warning);
+    assertThat(qualityGateConditionDto.getErrorThreshold()).isEqualTo(error);
+    assertThat(qualityGateConditionDto.getPeriod()).isEqualTo(period);
+
+    assertThat(response.getId()).isEqualTo(qualityGateConditionDto.getId());
+    assertThat(response.getMetric()).isEqualTo(coverageMetricDto.getKey());
+    assertThat(response.getOp()).isEqualTo(operator);
+    if (warning != null) {
+      assertThat(response.getWarning()).isEqualTo(warning);
+    } else {
+      assertThat(response.hasWarning()).isFalse();
+    }
+    if (error != null) {
+      assertThat(response.getError()).isEqualTo(error);
+    } else {
+      assertThat(response.hasError()).isFalse();
+    }
+    if (period != null) {
+      assertThat(response.getPeriod()).isEqualTo(period);
+    } else {
+      assertThat(response.hasPeriod()).isFalse();
+    }
+  }
+
+  private CreateConditionWsResponse executeRequest(long conditionId, String metricKey, String operator, @Nullable String warning, @Nullable String error,
+    @Nullable Integer period) {
+    TestRequest request = ws.newRequest()
+      .setMediaType(MediaTypes.PROTOBUF)
+      .setParam(PARAM_ID, Long.toString(conditionId))
+      .setParam(PARAM_METRIC, metricKey)
+      .setParam(PARAM_OPERATOR, operator);
+    if (warning != null) {
+      request.setParam(PARAM_WARNING, warning);
+    }
+    if (error != null) {
+      request.setParam(PARAM_ERROR, error);
+    }
+    if (period != null) {
+      request.setParam(PARAM_PERIOD, Integer.toString(period));
+    }
+    try {
+      return CreateConditionWsResponse.parseFrom(request.execute().getInputStream());
+    } catch (IOException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+
+  private void setUserAsQualityGateAdmin() {
+    userSession.login("project-admin").setGlobalPermissions(QUALITY_GATE_ADMIN);
+  }
+
+  private void setUserAsNotQualityGateAdmin() {
+    userSession.login("not-admin").setGlobalPermissions(SCAN_EXECUTION);
+  }
+}
index a4b09d6a3570ba81cfb61db89e8d282923b4a875..d77534878de06c8c893d6b83a0db12651501b91f 100644 (file)
@@ -22,6 +22,7 @@ package org.sonarqube.ws.client.qualitygate;
 import org.sonarqube.ws.WsQualityGates.CreateConditionWsResponse;
 import org.sonarqube.ws.WsQualityGates.CreateWsResponse;
 import org.sonarqube.ws.WsQualityGates.ProjectStatusWsResponse;
+import org.sonarqube.ws.WsQualityGates.UpdateConditionWsResponse;
 import org.sonarqube.ws.client.BaseService;
 import org.sonarqube.ws.client.GetRequest;
 import org.sonarqube.ws.client.PostRequest;
@@ -31,10 +32,12 @@ import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.ACTIO
 import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.ACTION_CREATE_CONDITION;
 import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.ACTION_PROJECT_STATUS;
 import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.ACTION_SELECT;
+import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.ACTION_UPDATE_CONDITION;
 import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.CONTROLLER_QUALITY_GATES;
 import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_ANALYSIS_ID;
 import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_ERROR;
 import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_GATE_ID;
+import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_ID;
 import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_METRIC;
 import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_NAME;
 import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_OPERATOR;
@@ -80,4 +83,15 @@ public class QualityGatesService extends BaseService {
       .setParam(PARAM_PERIOD, request.getPeriod()),
       CreateConditionWsResponse.parser());
   }
+
+  public UpdateConditionWsResponse updateCondition(UpdateConditionRequest request) {
+    return call(new PostRequest(path(ACTION_UPDATE_CONDITION))
+        .setParam(PARAM_ID, request.getConditionId())
+        .setParam(PARAM_METRIC, request.getMetricKey())
+        .setParam(PARAM_OPERATOR, request.getOperator())
+        .setParam(PARAM_WARNING, request.getWarning())
+        .setParam(PARAM_ERROR, request.getError())
+        .setParam(PARAM_PERIOD, request.getPeriod()),
+      UpdateConditionWsResponse.parser());
+  }
 }
index 1f9fe030d8ed72bf829665cd90477c7d6ec86a6d..d984571e7c0744e9f298d872a429600a574ac78e 100644 (file)
@@ -29,6 +29,7 @@ public class QualityGatesWsParameters {
   public static final String ACTION_SELECT = "select";
   public static final String ACTION_CREATE = "create";
   public static final String ACTION_CREATE_CONDITION = "create_condition";
+  public static final String ACTION_UPDATE_CONDITION = "update_condition";
 
   public static final String PARAM_ANALYSIS_ID = "analysisId";
   public static final String PARAM_PROJECT_ID = "projectId";
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/qualitygate/UpdateConditionRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/qualitygate/UpdateConditionRequest.java
new file mode 100644 (file)
index 0000000..13abf90
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.sonarqube.ws.client.qualitygate;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Strings.isNullOrEmpty;
+
+public class UpdateConditionRequest {
+
+  private final long conditionId;
+  private final String metricKey;
+  private final String operator;
+  private final String warning;
+  private final String error;
+  private final Integer period;
+
+  public UpdateConditionRequest(Builder builder) {
+    this.conditionId = builder.conditionId;
+    this.metricKey = builder.metricKey;
+    this.operator = builder.operator;
+    this.warning = builder.warning;
+    this.error = builder.error;
+    this.period = builder.period;
+  }
+
+  public long getConditionId() {
+    return conditionId;
+  }
+
+  public String getMetricKey() {
+    return metricKey;
+  }
+
+  public String getOperator() {
+    return operator;
+  }
+
+  @CheckForNull
+  public String getWarning() {
+    return warning;
+  }
+
+  @CheckForNull
+  public String getError() {
+    return error;
+  }
+
+  @CheckForNull
+  public Integer getPeriod() {
+    return period;
+  }
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private long conditionId;
+    private String metricKey;
+    private String operator;
+    private String warning;
+    private String error;
+    private Integer period;
+
+    private Builder() {
+      // enforce factory method use
+    }
+
+    public Builder setConditionId(long conditionId) {
+      this.conditionId = conditionId;
+      return this;
+    }
+
+    public Builder setMetricKey(String metricKey) {
+      this.metricKey = metricKey;
+      return this;
+    }
+
+    public Builder setOperator(String operator) {
+      this.operator = operator;
+      return this;
+    }
+
+    public Builder setWarning(@Nullable String warning) {
+      this.warning = warning;
+      return this;
+    }
+
+    public Builder setError(@Nullable String error) {
+      this.error = error;
+      return this;
+    }
+
+    public Builder setPeriod(@Nullable Integer period) {
+      this.period = period;
+      return this;
+    }
+
+    public UpdateConditionRequest build() {
+      checkArgument(conditionId > 0, "Condition id is mandatory and must not be empty");
+      checkArgument(!isNullOrEmpty(metricKey), "Metric key is mandatory and must not be empty");
+      checkArgument(!isNullOrEmpty(operator), "Operator is mandatory and must not be empty");
+      return new UpdateConditionRequest(this);
+    }
+  }
+}
index 125e5667d8d9a0b0fb228beada65c8f94e90124b..ff1fc8703765886cd3bce4e63193f6568de1567e 100644 (file)
@@ -107,5 +107,15 @@ message CreateConditionWsResponse {
   optional int32 period = 6;
 }
 
+// POST api/qualitygates/update_condition
+message UpdateConditionWsResponse {
+  optional int64 id = 1;
+  optional string metric = 2;
+  optional string op = 3;
+  optional string warning = 4;
+  optional string error = 5;
+  optional int32 period = 6;
+}
+
 
 
index 386587a536b0435e96d3032a66b46f1a055dd89a..66d6a62fff417fa3aa7e4fa88a6308960a44aa64 100644 (file)
@@ -25,6 +25,7 @@ import org.junit.Test;
 import org.sonarqube.ws.WsQualityGates.CreateConditionWsResponse;
 import org.sonarqube.ws.WsQualityGates.CreateWsResponse;
 import org.sonarqube.ws.WsQualityGates.ProjectStatusWsResponse;
+import org.sonarqube.ws.WsQualityGates.UpdateConditionWsResponse;
 import org.sonarqube.ws.client.GetRequest;
 import org.sonarqube.ws.client.PostRequest;
 import org.sonarqube.ws.client.ServiceTester;
@@ -35,6 +36,7 @@ import static org.mockito.Mockito.mock;
 import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_ANALYSIS_ID;
 import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_ERROR;
 import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_GATE_ID;
+import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_ID;
 import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_METRIC;
 import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_NAME;
 import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_OPERATOR;
@@ -123,4 +125,29 @@ public class QualityGatesServiceTest {
       .hasParam(PARAM_PERIOD, 1)
       .andNoOtherParam();
   }
+
+  @Test
+  public void update_condition() {
+    underTest.updateCondition(UpdateConditionRequest.builder()
+      .setConditionId(10)
+      .setMetricKey("metric")
+      .setOperator("LT")
+      .setWarning("warning")
+      .setError("error")
+      .setPeriod(1)
+      .build());
+
+    PostRequest request = serviceTester.getPostRequest();
+
+    assertThat(serviceTester.getPostParser()).isSameAs(UpdateConditionWsResponse.parser());
+    serviceTester.assertThat(request)
+      .hasPath("update_condition")
+      .hasParam(PARAM_ID, 10)
+      .hasParam(PARAM_METRIC, "metric")
+      .hasParam(PARAM_OPERATOR, "LT")
+      .hasParam(PARAM_WARNING, "warning")
+      .hasParam(PARAM_ERROR, "error")
+      .hasParam(PARAM_PERIOD, 1)
+      .andNoOtherParam();
+  }
 }
diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/qualitygate/UpdateConditionRequestTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/qualitygate/UpdateConditionRequestTest.java
new file mode 100644 (file)
index 0000000..3864615
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.sonarqube.ws.client.qualitygate;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class UpdateConditionRequestTest {
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  UpdateConditionRequest.Builder underTest = UpdateConditionRequest.builder();
+
+  @Test
+  public void create_condition_request() {
+    UpdateConditionRequest result = underTest
+      .setConditionId(10)
+      .setMetricKey("metric")
+      .setOperator("LT")
+      .setWarning("warning")
+      .setError("error")
+      .setPeriod(1)
+      .build();
+
+    assertThat(result.getConditionId()).isEqualTo(10);
+    assertThat(result.getMetricKey()).isEqualTo("metric");
+    assertThat(result.getOperator()).isEqualTo("LT");
+    assertThat(result.getWarning()).isEqualTo("warning");
+    assertThat(result.getError()).isEqualTo("error");
+    assertThat(result.getPeriod()).isEqualTo(1);
+  }
+
+  @Test
+  public void fail_when_no_quality_gate() {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Condition id is mandatory and must not be empty");
+
+    underTest
+      .setMetricKey("metric")
+      .setOperator("LT")
+      .setWarning("warning")
+      .build();
+  }
+
+  @Test
+  public void fail_when_no_metric() {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Metric key is mandatory and must not be empty");
+
+    underTest
+      .setConditionId(10)
+      .setOperator("LT")
+      .setWarning("warning")
+      .build();
+  }
+
+  @Test
+  public void fail_when_no_operator() {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Operator is mandatory and must not be empty");
+
+    underTest
+      .setConditionId(10)
+      .setMetricKey("metric")
+      .setWarning("warning")
+      .build();
+  }
+
+}