]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10040 add maximum value to ws API
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 6 Nov 2017 10:25:35 +0000 (11:25 +0100)
committerGuillaume Jambet <guillaume.jambet@gmail.com>
Wed, 8 Nov 2017 12:51:31 +0000 (13:51 +0100)
18 files changed:
server/sonar-server/src/main/java/org/sonar/server/ce/ws/ActivityAction.java
server/sonar-server/src/main/java/org/sonar/server/component/ws/TreeAction.java
server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java
server/sonar-server/src/main/java/org/sonar/server/organization/ws/SearchMembersAction.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ProjectsAction.java
server/sonar-server/src/main/java/org/sonar/server/ws/ws/ListAction.java
server/sonar-server/src/main/resources/org/sonar/server/ws/ws/list-example.json
server/sonar-server/src/test/java/org/sonar/server/ce/ws/ActivityActionTest.java
server/sonar-server/src/test/java/org/sonar/server/component/ws/TreeActionTest.java
server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeActionTest.java
server/sonar-server/src/test/java/org/sonar/server/organization/ws/SearchMembersActionTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ProjectsActionTest.java
server/sonar-server/src/test/java/org/sonar/server/ws/ws/WebServicesWsTest.java
server/sonar-server/src/test/resources/org/sonar/server/ws/ws/WebServicesWsTest/list_including_internals.json
sonar-plugin-api/src/main/java/org/sonar/api/server/ws/WebService.java
sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/ValidatingRequest.java
sonar-plugin-api/src/test/java/org/sonar/api/server/ws/RequestTest.java
sonar-plugin-api/src/test/java/org/sonar/api/server/ws/WebServiceTest.java

index e54d06826cfcbc712ba5942bba6318631dd4368b..3d2d55203ca74dbe9a7f3a70b52d46bdfb628137 100644 (file)
@@ -294,8 +294,6 @@ public class ActivityAction implements CeWsAction {
 
     checkRequest(activityWsRequest.getComponentId() == null || activityWsRequest.getQuery() == null, "%s and %s must not be set at the same time",
       PARAM_COMPONENT_ID, PARAM_COMPONENT_QUERY);
-    checkRequest(activityWsRequest.getPageSize() <= MAX_PAGE_SIZE, "The '%s' parameter must be less than %d", Param.PAGE_SIZE, MAX_PAGE_SIZE);
-
     return activityWsRequest;
   }
 }
index 0fc4dd804aaa7e31b3215784e080146c34fc6844..5e742a29e82918e7577a3f2874ff2520bbfd82c7 100644 (file)
@@ -296,7 +296,6 @@ public class TreeAction implements ComponentsWsAction {
       .setAsc(request.mandatoryParamAsBoolean(Param.ASCENDING))
       .setPage(request.mandatoryParamAsInt(Param.PAGE))
       .setPageSize(request.mandatoryParamAsInt(Param.PAGE_SIZE));
-    checkRequest(treeWsRequest.getPageSize() <= MAX_SIZE, "The '%s' parameter must be less than %d", Param.PAGE_SIZE, MAX_SIZE);
     String searchQuery = treeWsRequest.getQuery();
     checkRequest(searchQuery == null || searchQuery.length() >= QUERY_MINIMUM_LENGTH,
       "The '%s' parameter must have at least %d characters", Param.TEXT_QUERY, QUERY_MINIMUM_LENGTH);
index 188fce832df5b96a7a7f42b8503db402103c2053..892d64fc30333901b4295d92c244d44587d7f82f 100644 (file)
@@ -308,7 +308,6 @@ public class ComponentTreeAction implements MeasuresWsAction {
       .setPage(request.mandatoryParamAsInt(Param.PAGE))
       .setPageSize(request.mandatoryParamAsInt(Param.PAGE_SIZE))
       .setQuery(request.param(Param.TEXT_QUERY));
-    checkRequest(componentTreeWsRequest.getPageSize() <= MAX_SIZE, "The '%s' parameter must be less than %d", Param.PAGE_SIZE, MAX_SIZE);
     String searchQuery = componentTreeWsRequest.getQuery();
     checkRequest(searchQuery == null || searchQuery.length() >= QUERY_MINIMUM_LENGTH,
       "The '%s' parameter must have at least %d characters", Param.TEXT_QUERY, QUERY_MINIMUM_LENGTH);
index 1d87cfaac362693f329cab3a676487f596e4a057..deb4db66886db3d752c1ae6462aede7394484f01 100644 (file)
@@ -160,8 +160,6 @@ public class SearchMembersAction implements OrganizationsWsAction {
 
   private static SearchOptions buildSearchOptions(Request request) {
     int pageSize = request.mandatoryParamAsInt(Param.PAGE_SIZE);
-    checkArgument(pageSize <= SearchOptions.MAX_LIMIT, "Page size must lower than or equal to %s", SearchOptions.MAX_LIMIT);
-
     return new SearchOptions().setPage(request.mandatoryParamAsInt(Param.PAGE), pageSize);
   }
 
index cdb9f246679fdf95b9506ba7650f7980dd46690c..abde10c79bf1e84b241294ceecaea84ea2f3cdca 100644 (file)
@@ -41,7 +41,6 @@ import org.sonar.db.qualityprofile.QProfileDto;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.user.UserSession;
 
-import static com.google.common.base.Preconditions.checkArgument;
 import static java.util.Comparator.comparing;
 import static org.sonar.api.utils.Paging.forPageIndex;
 import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01;
@@ -99,7 +98,6 @@ public class ProjectsAction implements QProfileWsAction {
       String query = request.param(Param.TEXT_QUERY);
       int page = request.mandatoryParamAsInt(Param.PAGE);
       int pageSize = request.mandatoryParamAsInt(Param.PAGE_SIZE);
-      checkArgument(pageSize <= MAX_PAGE_SIZE, "The '%s' parameter must be less than %s", Param.PAGE_SIZE, MAX_PAGE_SIZE);
 
       List<ProjectQprofileAssociationDto> projects = loadAllProjects(profileKey, session, selected, query).stream()
         .sorted(comparing(ProjectQprofileAssociationDto::getProjectName)
index 8f91b4d02793a3ce8e9e7d01df76199e9512b88a..126bfd341f6b2f8758a510c55cce52fcf57b408c 100644 (file)
@@ -22,7 +22,6 @@ package org.sonar.server.ws.ws;
 import com.google.common.collect.Ordering;
 import java.util.Comparator;
 import java.util.List;
-import java.util.Set;
 import org.sonar.api.server.ws.Change;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
@@ -31,6 +30,7 @@ import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.core.util.stream.MoreCollectors;
 
 import static com.google.common.base.Preconditions.checkState;
+import static java.util.Optional.ofNullable;
 
 public class ListAction implements WebServicesWsAction {
   private WebService.Context context;
@@ -134,14 +134,9 @@ public class ListAction implements WebServicesWsAction {
     writer.prop("deprecatedKey", param.deprecatedKey());
     writer.prop("deprecatedKeySince", param.deprecatedKeySince());
     writer.prop("maxValuesAllowed", param.maxValuesAllowed());
-    Set<String> possibleValues = param.possibleValues();
-    if (possibleValues != null) {
-      writer.name("possibleValues").beginArray().values(possibleValues).endArray();
-    }
-    Integer maximumLength = param.maximumLength();
-    if (maximumLength != null) {
-      writer.prop("maximumLength", maximumLength);
-    }
+    ofNullable(param.possibleValues()).ifPresent(possibleValues -> writer.name("possibleValues").beginArray().values(possibleValues).endArray());
+    ofNullable(param.maximumLength()).ifPresent(maximumLength -> writer.prop("maximumLength", maximumLength));
+    ofNullable(param.maximumValue()).ifPresent(maximumValue -> writer.prop("maximumValue", maximumValue));
     writer.endObject();
   }
 
index 2734b17d98c73aba9c1e980fbb20ab5d4dab338f..ade270b1dbdb66ca8a9fc690e49851a8ee5155dd 100644 (file)
             }
           ],
           "params": [
+            {
+              "key": "maximum_value",
+              "maximumValue": 12,
+              "required": false,
+              "internal": false
+            },
             {
               "key": "name",
               "required": false,
index 856ef29b1d6c148aa85c3fc1fea72ebd6c214413..0f97dde5b8aeba0cada3a0c47af6f3d5fc1c17f2 100644 (file)
@@ -395,8 +395,8 @@ public class ActivityActionTest {
 
   @Test
   public void fail_if_page_size_greater_than_1000() {
-    expectedException.expect(BadRequestException.class);
-    expectedException.expectMessage("The 'ps' parameter must be less than 1000");
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("'ps' value (1001) must be less than 1000");
 
     ws.newRequest()
       .setParam(Param.PAGE_SIZE, "1001")
index dc8ffbf335deb1343e326b76b0033d89b273b2f8..4efbd778940ee69eb61bb53edefcdd46ef3f804d 100644 (file)
@@ -386,8 +386,8 @@ public class TreeActionTest {
 
   @Test
   public void fail_when_page_size_above_500() {
-    expectedException.expect(BadRequestException.class);
-    expectedException.expectMessage("The 'ps' parameter must be less than 500");
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("'ps' value (501) must be less than 500");
     componentDb.insertComponent(newPrivateProjectDto(db.getDefaultOrganization(), "project-uuid"));
     db.commit();
 
index 52911d542b7e7cb740c18b32c45cf8af0ed18f79..0b9e192bea01081ee96d5805d827d53b092a9081 100644 (file)
@@ -71,7 +71,6 @@ import static org.sonar.api.utils.DateUtils.parseDateTime;
 import static org.sonar.api.web.UserRole.USER;
 import static org.sonar.db.component.ComponentTesting.newDirectory;
 import static org.sonar.db.component.ComponentTesting.newFileDto;
-import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
 import static org.sonar.db.component.ComponentTesting.newProjectCopy;
 import static org.sonar.db.component.SnapshotTesting.newAnalysis;
 import static org.sonar.db.measure.MeasureTesting.newMeasureDto;
@@ -765,14 +764,14 @@ public class ComponentTreeActionTest {
     db.components().insertSnapshot(project);
     insertNclocMetric();
 
-    expectedException.expect(BadRequestException.class);
-    expectedException.expectMessage("The 'ps' parameter must be less than 500");
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("'ps' value (2540) must be less than 500");
 
     ws.newRequest()
       .setParam(PARAM_COMPONENT, project.getKey())
       .setParam(PARAM_METRIC_KEYS, "ncloc")
       .setParam(Param.PAGE_SIZE, "2540")
-      .executeProtobuf(ComponentTreeWsResponse.class);
+      .execute();
   }
 
   @Test
index 584dadca43b800c070a9ee31a7463c8e6f97c201..4b9608912d7e6240a27dbfd6347024d8f89240e0 100644 (file)
@@ -268,7 +268,7 @@ public class SearchMembersActionTest {
     request.setPageSize(501);
 
     expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("Page size must lower than or equal to 500");
+    expectedException.expectMessage("'ps' value (501) must be less than 500");
 
     call();
   }
index 7051702e9e45cb4f262ef7e7f99ae7bd0113b276..477ef473107098b514e88f872602eba4b9a413e3 100644 (file)
@@ -200,7 +200,7 @@ public class ProjectsActionTest {
   @Test
   public void fail_if_page_size_greater_than_500() throws Exception {
     expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("The 'ps' parameter must be less than 500");
+    expectedException.expectMessage("'ps' value (501) must be less than 500");
 
     newRequest().setParam(PARAM_KEY, xooP1.getKee()).setParam(Param.PAGE_SIZE, "501").execute();
   }
index dd8110eb008f27a3e9d1c69bfaca5fa9846be30f..d9e1fc2fc4f4531b72dd68e264cf64b3d44233bd 100644 (file)
@@ -125,6 +125,7 @@ public class WebServicesWsTest {
         .setDefaultValue("BLOCKER");
       create.createParam("name");
       create.createParam("internal").setInternal(true);
+      create.createParam("maximum_value").setMaximumValue(12);
 
       newController.createAction("internal_action")
         .setDescription("Internal Action Description")
index e4e70d2d40f8dd19163484b3bfe1e2bd147ac419..dddcd8edbe6e2016cf2b3599e31bc78986022381 100644 (file)
-{"webServices": [
-  {
-    "path": "api/metric",
-    "since": "3.2",
-    "description": "Metrics",
-    "actions": [
-      {
-        "key": "create",
-        "description": "Create metric",
-        "since": "4.1",
-        "internal": false,
-        "post": true,
-        "hasResponseExample": true,
-        "params": [
-          {
-            "key": "name",
-            "required": false,
-            "internal": false
-          },
-          {
-            "key": "severity",
-            "description": "Severity",
-            "required": false,
-            "internal": false,
-            "defaultValue": "BLOCKER",
-            "exampleValue": "INFO",
-            "possibleValues": ["BLOCKER", "INFO"]
-          },
-          {
-            "key": "internal",
-            "required": false,
-            "internal": true
-          }
-        ]
-      },
-      {
-        "key": "internal_action",
-        "since": "5.3",
-        "internal": true,
-        "post": false,
-        "hasResponseExample": true
-      },
-      {
-        "key": "show",
-        "since": "3.2",
-        "internal": false,
-        "post": false,
-        "hasResponseExample": true
-      }
-    ]
-  },
-  {
-    "path": "api/webservices",
-    "description": "Get information on the web api supported on this instance.",
-    "since": "4.2",
-    "actions": [
-      {
-        "key": "list",
-        "since": "4.2",
-        "description": "List web services",
-        "internal": false,
-        "post": false,
-        "hasResponseExample": true,
-        "params": [
-          {
-            "key": "include_internals",
-            "description": "Include web services that are implemented for internal use only. Their forward-compatibility is not assured",
-            "required": false,
-            "internal": false,
-            "defaultValue": "false",
-            "possibleValues": ["true", "false", "yes", "no"]
-          }
-        ]
-      },
-      {
-        "key": "response_example",
-        "since": "4.4",
-        "description": "Display web service response example",
-        "internal": false,
-        "post": false,
-        "hasResponseExample": true,
-        "params": [
-          {
-            "key": "action",
-            "required": true,
-            "internal": false,
-            "description": "Action of the web service",
-            "exampleValue": "search"
-          },
-          {
-            "key": "controller",
-            "required": true,
-            "internal": false,
-            "description": "Controller of the web service",
-            "exampleValue": "api/issues"
-          }
-        ]
-      }
-    ]
-  }
-]}
+{
+  "webServices": [
+    {
+      "path": "api/metric",
+      "since": "3.2",
+      "description": "Metrics",
+      "actions": [
+        {
+          "key": "create",
+          "description": "Create metric",
+          "since": "4.1",
+          "internal": false,
+          "post": true,
+          "hasResponseExample": true,
+          "params": [
+            {
+              "key": "maximum_value",
+              "maximumValue": 12
+            },
+            {
+              "key": "name",
+              "required": false,
+              "internal": false
+            },
+            {
+              "key": "severity",
+              "description": "Severity",
+              "required": false,
+              "internal": false,
+              "defaultValue": "BLOCKER",
+              "exampleValue": "INFO",
+              "possibleValues": [
+                "BLOCKER",
+                "INFO"
+              ]
+            },
+            {
+              "key": "internal",
+              "required": false,
+              "internal": true
+            }
+          ]
+        },
+        {
+          "key": "internal_action",
+          "since": "5.3",
+          "internal": true,
+          "post": false,
+          "hasResponseExample": true
+        },
+        {
+          "key": "show",
+          "since": "3.2",
+          "internal": false,
+          "post": false,
+          "hasResponseExample": true
+        }
+      ]
+    },
+    {
+      "path": "api/webservices",
+      "description": "Get information on the web api supported on this instance.",
+      "since": "4.2",
+      "actions": [
+        {
+          "key": "list",
+          "since": "4.2",
+          "description": "List web services",
+          "internal": false,
+          "post": false,
+          "hasResponseExample": true,
+          "params": [
+            {
+              "key": "include_internals",
+              "description": "Include web services that are implemented for internal use only. Their forward-compatibility is not assured",
+              "required": false,
+              "internal": false,
+              "defaultValue": "false",
+              "possibleValues": [
+                "true",
+                "false",
+                "yes",
+                "no"
+              ]
+            }
+          ]
+        },
+        {
+          "key": "response_example",
+          "since": "4.4",
+          "description": "Display web service response example",
+          "internal": false,
+          "post": false,
+          "hasResponseExample": true,
+          "params": [
+            {
+              "key": "action",
+              "required": true,
+              "internal": false,
+              "description": "Action of the web service",
+              "exampleValue": "search"
+            },
+            {
+              "key": "controller",
+              "required": true,
+              "internal": false,
+              "description": "Controller of the web service",
+              "exampleValue": "api/issues"
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
index 9d07ee5307ad534d151c6a5541593856d6335ab0..02285cab9baadaafe4bdb4a5102dc8eb73af1ef7 100644 (file)
@@ -386,10 +386,11 @@ public interface WebService extends Definable<WebService.Context> {
 
     public NewParam createPageSize(int defaultPageSize, int maxPageSize) {
       return createParam(Param.PAGE_SIZE)
-        .setDescription("Page size. Must be greater than 0 and less than " + maxPageSize)
-        .setExampleValue("20")
         .setDeprecatedKey("pageSize", "5.2")
-        .setDefaultValue(String.valueOf(defaultPageSize));
+        .setDefaultValue(String.valueOf(defaultPageSize))
+        .setMaximumValue(maxPageSize)
+        .setDescription("Page size. Must be greater than 0 and less than " + maxPageSize)
+        .setExampleValue("20");
     }
 
     /**
@@ -635,6 +636,7 @@ public interface WebService extends Definable<WebService.Context> {
     private Set<String> possibleValues = null;
     private Integer maxValuesAllowed;
     private Integer maximumLength;
+    private Integer maximumValue;
 
     private NewParam(String key) {
       this.key = key;
@@ -779,6 +781,14 @@ public interface WebService extends Definable<WebService.Context> {
       return this;
     }
 
+    /**
+     * @since 7.0
+     */
+    public NewParam setMaximumValue(@Nullable Integer maximumValue) {
+      this.maximumValue = maximumValue;
+      return this;
+    }
+
     @Override
     public String toString() {
       return key;
@@ -834,6 +844,7 @@ public interface WebService extends Definable<WebService.Context> {
     private final boolean internal;
     private final Set<String> possibleValues;
     private final Integer maximumLength;
+    private final Integer maximumValue;
     private final Integer maxValuesAllowed;
 
     protected Param(Action action, NewParam newParam) {
@@ -850,6 +861,7 @@ public interface WebService extends Definable<WebService.Context> {
       this.possibleValues = newParam.possibleValues;
       this.maxValuesAllowed = newParam.maxValuesAllowed;
       this.maximumLength = newParam.maximumLength;
+      this.maximumValue = newParam.maximumValue;
       checkArgument(!required || defaultValue == null, "Default value must not be set on parameter '%s?%s' as it's marked as required", action, key);
     }
 
@@ -938,7 +950,7 @@ public interface WebService extends Definable<WebService.Context> {
     }
 
     /**
-     * Specify the maximum number of values allowed when using this a parameter
+     * Specify the maximum number of values allowed when using {@link Request#multiParam(String)}
      *
      * @since 6.4
      */
@@ -956,6 +968,16 @@ public interface WebService extends Definable<WebService.Context> {
       return maximumLength;
     }
 
+    /**
+     * Specify the maximum value of the numeric variable used in this parameter
+     *
+     * @since 7.0
+     */
+    @CheckForNull
+    public Integer maximumValue() {
+      return maximumValue;
+    }
+
     @Override
     public String toString() {
       return key;
index 495cd8e5d821805ca5882ac6fb1b79d6a8c741f2..a9141a3943d7a0a30f60c03d8b6c65d03c0d3f4f 100644 (file)
@@ -32,6 +32,7 @@ import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.WebService;
 
 import static com.google.common.base.Preconditions.checkArgument;
+import static java.lang.String.format;
 import static java.util.Collections.emptyList;
 import static java.util.Collections.singletonList;
 import static java.util.Objects.requireNonNull;
@@ -68,21 +69,15 @@ public abstract class ValidatingRequest extends Request {
   @CheckForNull
   public String param(String key) {
     WebService.Param definition = action.param(key);
-    String value = defaultString(readParam(key, definition), definition.defaultValue());
-
-    Integer maximumLength = definition.maximumLength();
-    if (value != null && maximumLength != null) {
-      int valueLength = value.length();
-      checkArgument(valueLength <= maximumLength,
-        "'%s' length (%s) is longer than the maximum authorized (%s)",
-        key, valueLength, maximumLength);
-    }
-
-    String trimmedValue = value == null ? null : CharMatcher.WHITESPACE.trimFrom(value);
-    if (trimmedValue != null) {
-      validateValue(trimmedValue, definition);
+    String valueOrDefault = defaultString(readParam(key, definition), definition.defaultValue());
+    String value = valueOrDefault == null ? null : CharMatcher.WHITESPACE.trimFrom(valueOrDefault);
+    if (value == null) {
+      return null;
     }
-    return trimmedValue;
+    validatePossibleValues(key, value, definition);
+    validateMaximumLength(key, definition, valueOrDefault);
+    validateMaximumValue(key, definition, value);
+    return value;
   }
 
   @Override
@@ -167,12 +162,42 @@ public abstract class ValidatingRequest extends Request {
   private static List<String> validateValues(List<String> values, WebService.Param definition) {
     Integer maximumValues = definition.maxValuesAllowed();
     checkArgument(maximumValues == null || values.size() <= maximumValues, "'%s' can contains only %s values, got %s", definition.key(), maximumValues, values.size());
-    values.forEach(value -> validateValue(value, definition));
+    values.forEach(value -> validatePossibleValues(definition.key(), value, definition));
     return values;
   }
 
-  private static void validateValue(String value, WebService.Param definition) {
+  private static void validatePossibleValues(String key, String value, WebService.Param definition) {
     Set<String> possibleValues = definition.possibleValues();
-    checkArgument(possibleValues == null || possibleValues.contains(value), "Value of parameter '%s' (%s) must be one of: %s", definition.key(), value, possibleValues);
+    if (possibleValues == null) {
+      return;
+    }
+    checkArgument(possibleValues.contains(value), "Value of parameter '%s' (%s) must be one of: %s", key, value, possibleValues);
   }
+
+  private static void validateMaximumLength(String key, WebService.Param definition, String valueOrDefault) {
+    Integer maximumLength = definition.maximumLength();
+    if (maximumLength == null) {
+      return;
+    }
+    int valueLength = valueOrDefault.length();
+    checkArgument(valueLength <= maximumLength, "'%s' length (%s) is longer than the maximum authorized (%s)", key, valueLength, maximumLength);
+  }
+
+  private static void validateMaximumValue(String key, WebService.Param definition, String value) {
+    Integer maximumValue = definition.maximumValue();
+    if (maximumValue == null) {
+      return;
+    }
+    int valueAsInt = validateAsNumeric(key, value);
+    checkArgument(valueAsInt <= maximumValue, "'%s' value (%s) must be less than %s", key, valueAsInt, maximumValue);
+  }
+
+  private static int validateAsNumeric(String key, String value) {
+    try {
+      return Integer.parseInt(value);
+    } catch (NumberFormatException exception) {
+      throw new IllegalStateException(format("'%s' value '%s' cannot be parsed as an integer", key, value), exception);
+    }
+  }
+
 }
index e95cf3077db2f3e134422b2397062626314ed74d..4f3ee5aaa698be1823b89686461fa5af93459f12 100644 (file)
@@ -121,6 +121,28 @@ public class RequestTest {
     underTest.setParam(parameter, repeat("X", 11)).param(parameter);
   }
 
+  @Test
+  public void maximum_value_ok() {
+    String param = "maximum_value_param";
+    defineParameterTestAction(newParam -> newParam.setMaximumValue(10), param);
+    String expected = "10";
+
+    String actual = underTest.setParam(param, expected).param(param);
+
+    assertThat(actual).isEqualTo(expected);
+  }
+
+  @Test
+  public void maximum_value_not_ok() {
+    String param = "maximum_value_param";
+    defineParameterTestAction(newParam -> newParam.setMaximumValue(10), param);
+
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage(format("'%s' value (11) must be less than 10", param));
+
+    underTest.setParam(param, "11").param(param);
+  }
+
   @Test
   public void required_param_as_strings() {
     underTest.setParam("a_required_string", "foo,bar");
@@ -495,7 +517,7 @@ public class RequestTest {
 
   @DataProvider
   public static Object[][] date_times() {
-    return new Object[][]{
+    return new Object[][] {
       {"2014-05-27", parseDate("2014-05-27")},
       {"2014-05-27T15:50:45+0100", parseDateTime("2014-05-27T15:50:45+0100")},
       {null, null}
index 4b674ea392c52e465646d10233d25fca1973b6ea..3cf9d04101f8add9db21e36850982c609aa173dd 100644 (file)
@@ -315,6 +315,20 @@ public class WebServiceTest {
     assertThat(action.param("string_value").maximumLength()).isEqualTo(24);
   }
 
+  @Test
+  public void param_with_maximum_value() {
+    ((WebService) context -> {
+      NewController newController = context.createController("api/custom_measures");
+      NewAction create = newDefaultAction(newController, "create");
+      create.createParam("numeric_value")
+        .setMaximumValue(10);
+      newController.done();
+    }).define(context);
+
+    WebService.Action action = context.controller("api/custom_measures").action("create");
+    assertThat(action.param("numeric_value").maximumValue()).isEqualTo(10);
+  }
+
   @Test
   public void fail_if_required_param_has_default_value() {
     expectedException.expect(IllegalArgumentException.class);