]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5007 add tests
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Tue, 20 May 2014 21:01:12 +0000 (23:01 +0200)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Tue, 20 May 2014 21:01:12 +0000 (23:01 +0200)
20 files changed:
sonar-plugin-api/src/main/java/org/sonar/api/server/ws/Request.java
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/SimpleGetRequest.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/ValidatingRequest.java [new file with mode: 0644]
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
sonar-server/src/main/java/org/sonar/server/rule2/RuleTagHelper.java
sonar-server/src/main/java/org/sonar/server/rule2/ws/RuleMapping.java
sonar-server/src/main/java/org/sonar/server/rule2/ws/SearchAction.java
sonar-server/src/main/java/org/sonar/server/search/QueryOptions.java
sonar-server/src/main/java/org/sonar/server/search/Result.java
sonar-server/src/main/java/org/sonar/server/search/ws/SearchOptions.java
sonar-server/src/main/java/org/sonar/server/ws/InternalRequest.java [deleted file]
sonar-server/src/main/java/org/sonar/server/ws/ServletRequest.java
sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.java
sonar-server/src/test/java/org/sonar/server/rule2/RuleTagHelperTest.java
sonar-server/src/test/java/org/sonar/server/search/QueryOptionsTest.java
sonar-server/src/test/java/org/sonar/server/search/ws/SearchOptionsTest.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java
sonar-server/src/test/java/org/sonar/server/ws/WsTester.java

index 9d969a68ce7cbed06f602317e4734512ffa32510..8cb158e87ebc77bc7c2318a28876a23be5ea0144 100644 (file)
@@ -22,28 +22,15 @@ package org.sonar.api.server.ws;
 import com.google.common.base.Splitter;
 import com.google.common.collect.Lists;
 import org.apache.commons.lang.StringUtils;
-import org.slf4j.LoggerFactory;
 
 import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
 import java.util.List;
-import java.util.Set;
 
 /**
  * @since 4.2
  */
 public abstract class Request {
 
-  private WebService.Action action;
-
-  protected void setAction(WebService.Action action) {
-    this.action = action;
-  }
-
-  public WebService.Action action() {
-    return action;
-  }
-
   /**
    * Returns the name of the HTTP method with which this request was made. Possible
    * values are GET and POST. Others are not supported.
@@ -105,75 +92,16 @@ public abstract class Request {
     return values;
   }
 
-  @CheckForNull
-  public String param(String key) {
-    return param(key, true);
-  }
-
-  @CheckForNull
-  String param(String key, boolean validateValue) {
-    WebService.Param definition = action.param(key);
-    String value = readParamOrDefaultValue(key, definition);
-    if (value != null && validateValue) {
-      validate(value, definition);
-    }
-    return value;
-  }
-
-  @CheckForNull
   public List<String> paramAsStrings(String key) {
-    WebService.Param definition = action.param(key);
-    String value = readParamOrDefaultValue(key, definition);
-    if (value == null) {
-      return null;
-    }
-    List<String> values = Lists.newArrayList(Splitter.on(',').omitEmptyStrings().trimResults().split(value));
-    for (String s : values) {
-      validate(s, definition);
-    }
-    return values;
-  }
-
-  @CheckForNull
-  public <E extends Enum<E>> List<E> paramAsEnums(String key, Class<E> enumClass) {
-    WebService.Param definition = action.param(key);
-    String value = readParamOrDefaultValue(key, definition);
-    if (value == null) {
-      return null;
-    }
-    Iterable<String> values = Splitter.on(',').omitEmptyStrings().trimResults().split(value);
-    List<E> result = Lists.newArrayList();
-    for (String s : values) {
-      validate(s, definition);
-      result.add(Enum.valueOf(enumClass, s));
-    }
-    return result;
-  }
-
-  @CheckForNull
-  private String readParamOrDefaultValue(String key, @Nullable WebService.Param definition) {
-    if (definition == null) {
-      String message = String.format("BUG - parameter '%s' is undefined for action '%s'", key, action.key());
-      LoggerFactory.getLogger(getClass()).error(message);
-      throw new IllegalArgumentException(message);
-    }
-    String value = StringUtils.defaultString(readParam(key), definition.defaultValue());
+    String value = param(key);
     if (value == null) {
       return null;
     }
-    return value;
+    return Lists.newArrayList(Splitter.on(',').omitEmptyStrings().trimResults().split(value));
   }
 
   @CheckForNull
-  protected abstract String readParam(String key);
-
-  private void validate(String value, WebService.Param definition) {
-    Set<String> possibleValues = definition.possibleValues();
-    if (possibleValues != null && !possibleValues.contains(value)) {
-      throw new IllegalArgumentException(String.format(
-        "Value of parameter '%s' (%s) must be one of: %s", definition.key(), value, possibleValues));
-    }
-  }
+  public abstract String param(String key);
 
   /**
    * @deprecated to be dropped in 4.4. Default values are declared in ws metadata
@@ -238,4 +166,18 @@ public abstract class Request {
     String s = param(key);
     return s == null ? null : Enum.valueOf(enumClass, s);
   }
+
+  @CheckForNull
+  public <E extends Enum<E>> List<E> paramAsEnums(String key, Class<E> enumClass) {
+    String value = param(key);
+    if (value == null) {
+      return null;
+    }
+    Iterable<String> values = Splitter.on(',').omitEmptyStrings().trimResults().split(value);
+    List<E> result = Lists.newArrayList();
+    for (String s : values) {
+      result.add(Enum.valueOf(enumClass, s));
+    }
+    return result;
+  }
 }
index 9508fd1d1798ac5d2b991fd22c319cb7b6027a8b..5e464a4200f530e5d867320756c3914a418994c4 100644 (file)
@@ -32,12 +32,10 @@ import org.sonar.api.ServerExtension;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
+
 import java.io.IOException;
 import java.net.URL;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 /**
  * Defines a web service. Note that contrary to the deprecated {@link org.sonar.api.web.Webservice}
@@ -467,39 +465,38 @@ public interface WebService extends ServerExtension {
     /**
      * Exhaustive list of possible values when it makes sense, for example
      * list of severities.
-     * <p/>
-     * Note that the parameter supports values with type Iterable, for example :
-     * <pre>
-     *   setPossibleValues(Arrays.asList("one", "two"), "three", "four");
-     * </pre>
      *
      * @since 4.4
      */
     public NewParam setPossibleValues(@Nullable Object... values) {
+      return setPossibleValues(values == null ? (Collection) null : Arrays.asList(values));
+    }
+
+    /**
+     * @since 4.4
+     */
+    public NewParam setBooleanPossibleValues() {
+      return setPossibleValues("true", "false");
+    }
+
+    /**
+     * Exhaustive list of possible values when it makes sense, for example
+     * list of severities.
+     *
+     * @since 4.4
+     */
+    public NewParam setPossibleValues(@Nullable Collection values) {
       if (values == null) {
         this.possibleValues = null;
       } else {
         this.possibleValues = Sets.newLinkedHashSet();
         for (Object value : values) {
-          if (value instanceof Iterable) {
-            for (Object o : (Iterable) value) {
-              this.possibleValues.add(o.toString());
-            }
-          } else {
-            this.possibleValues.add(value.toString());
-          }
+          this.possibleValues.add(value.toString());
         }
       }
       return this;
     }
 
-    /**
-     * @since 4.4
-     */
-    public NewParam setBooleanPossibleValues() {
-      return setPossibleValues("true", "false");
-    }
-
     /**
      * @since 4.4
      */
@@ -508,31 +505,6 @@ public interface WebService extends ServerExtension {
       return this;
     }
 
-    @CheckForNull
-    public String description() {
-      return description;
-    }
-
-    @CheckForNull
-    public String exampleValue() {
-      return exampleValue;
-    }
-
-    @CheckForNull
-    public String defaultValue() {
-      return defaultValue;
-    }
-
-    @CheckForNull
-    public boolean isRequired() {
-      return required;
-    }
-
-    @CheckForNull
-    public Set<String> possibleValues() {
-      return possibleValues;
-    }
-
     @Override
     public String toString() {
       return key;
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/SimpleGetRequest.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/SimpleGetRequest.java
new file mode 100644 (file)
index 0000000..c7fa2a2
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.server.ws.internal;
+
+import com.google.common.collect.Maps;
+import org.sonar.api.server.ws.Request;
+
+import javax.annotation.Nullable;
+import java.util.Map;
+
+/**
+ * Fake implementation of {@link org.sonar.api.server.ws.Request} used
+ * for testing. Call the method {@link #setParam(String, String)} to
+ * emulate some parameter values.
+ */
+public class SimpleGetRequest extends Request {
+
+  private final Map<String, String> params = Maps.newHashMap();
+
+  @Override
+  public String method() {
+    return "GET";
+  }
+
+  @Override
+  public String param(String key) {
+    return params.get(key);
+  }
+
+  public SimpleGetRequest setParam(String key, @Nullable String value) {
+    if (value != null) {
+      params.put(key, value);
+    }
+    return this;
+  }
+
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/ValidatingRequest.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/ValidatingRequest.java
new file mode 100644 (file)
index 0000000..002612f
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.api.server.ws.internal;
+
+import com.google.common.base.Splitter;
+import com.google.common.collect.Lists;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.WebService;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @since 4.2
+ */
+public abstract class ValidatingRequest extends Request {
+
+  private WebService.Action action;
+
+  public void setAction(WebService.Action action) {
+    this.action = action;
+  }
+
+  public WebService.Action action() {
+    return action;
+  }
+
+  @CheckForNull
+  public String param(String key) {
+    return param(key, true);
+  }
+
+  @CheckForNull
+  private String param(String key, boolean validateValue) {
+    WebService.Param definition = action.param(key);
+    String value = readParamOrDefaultValue(key, definition);
+    if (value != null && validateValue) {
+      validate(value, definition);
+    }
+    return value;
+  }
+
+  @CheckForNull
+  @Override
+  public List<String> paramAsStrings(String key) {
+    WebService.Param definition = action.param(key);
+    String value = readParamOrDefaultValue(key, definition);
+    if (value == null) {
+      return null;
+    }
+    List<String> values = Lists.newArrayList(Splitter.on(',').omitEmptyStrings().trimResults().split(value));
+    for (String s : values) {
+      validate(s, definition);
+    }
+    return values;
+  }
+
+  @CheckForNull
+  @Override
+  public <E extends Enum<E>> List<E> paramAsEnums(String key, Class<E> enumClass) {
+    WebService.Param definition = action.param(key);
+    String value = readParamOrDefaultValue(key, definition);
+    if (value == null) {
+      return null;
+    }
+    Iterable<String> values = Splitter.on(',').omitEmptyStrings().trimResults().split(value);
+    List<E> result = Lists.newArrayList();
+    for (String s : values) {
+      validate(s, definition);
+      result.add(Enum.valueOf(enumClass, s));
+    }
+    return result;
+  }
+
+  @CheckForNull
+  private String readParamOrDefaultValue(String key, @Nullable WebService.Param definition) {
+    if (definition == null) {
+      String message = String.format("BUG - parameter '%s' is undefined for action '%s'", key, action.key());
+      LoggerFactory.getLogger(getClass()).error(message);
+      throw new IllegalArgumentException(message);
+    }
+    String value = StringUtils.defaultString(readParam(key), definition.defaultValue());
+    if (value == null) {
+      return null;
+    }
+    return value;
+  }
+
+  @CheckForNull
+  protected abstract String readParam(String key);
+
+  private void validate(String value, WebService.Param definition) {
+    Set<String> possibleValues = definition.possibleValues();
+    if (possibleValues != null && !possibleValues.contains(value)) {
+      throw new IllegalArgumentException(String.format(
+        "Value of parameter '%s' (%s) must be one of: %s", definition.key(), value, possibleValues));
+    }
+  }
+}
index 76421b05c18f583d6524298174c28f26fe363eef..9d2926460f6d75c6aae883f04deb9d030cdb40bd 100644 (file)
@@ -23,6 +23,7 @@ import com.google.common.collect.Maps;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.server.ws.internal.ValidatingRequest;
 
 import javax.annotation.Nullable;
 import java.util.Map;
@@ -33,7 +34,7 @@ import static org.mockito.Mockito.mock;
 
 public class RequestTest {
 
-  private static class SimpleRequest extends Request {
+  private static class SimpleRequest extends ValidatingRequest {
 
     private final Map<String, String> params = Maps.newHashMap();
 
index ccebd01cd4b63b571ace1e4533db21ff7f1e8638..4dab17f0641a263586203e969b0270612816b147 100644 (file)
@@ -256,7 +256,7 @@ public class WebServiceTest {
         NewController newController = context.createController("api/rule");
         NewAction create = newController.createAction("create").setHandler(mock(RequestHandler.class));
         create.createParam("key").setDescription("Key of the new rule");
-        create.createParam("severity").setDefaultValue("MAJOR");
+        create.createParam("severity").setDefaultValue("MAJOR").setPossibleValues("INFO", "MAJOR", "BLOCKER");
         newController.done();
       }
     }.define(context);
@@ -271,6 +271,7 @@ public class WebServiceTest {
     assertThat(action.param("severity").key()).isEqualTo("severity");
     assertThat(action.param("severity").description()).isNull();
     assertThat(action.param("severity").defaultValue()).isEqualTo("MAJOR");
+    assertThat(action.param("severity").possibleValues()).containsOnly("INFO", "MAJOR", "BLOCKER");
   }
 
   @Test
index 99c95352754d185d2e870d4adffc692b7266e268..c24205a293c01fae90a126ba3c8acd2c624b3076 100644 (file)
@@ -50,6 +50,6 @@ class RuleTagHelper {
       }
     });
     rule.setTags(withoutSystemTags);
-    return Sets.difference(initialTags, withoutSystemTags).size() > 0;
+    return withoutSystemTags.size()!=initialTags.size() || !withoutSystemTags.containsAll(initialTags);
   }
 }
index 2e131fa2ecab4b81b231494d4b48091d4c3f20a7..d9142351e392fe15adde8f93ad8249a8e9834eca 100644 (file)
@@ -29,6 +29,9 @@ import org.sonar.server.rule2.index.RuleNormalizer;
 import org.sonar.server.search.ws.BaseMapping;
 import org.sonar.server.text.MacroInterpreter;
 
+/**
+ * Conversion between RuleDoc and WS JSON response
+ */
 public class RuleMapping extends BaseMapping {
 
   private final Languages languages;
index bde40f79dbb46a2f7becb1f670aa05b21f14d3c0..45a832dc5aeaf325c127bc9421f39284b941109d 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.server.rule2.ws;
 
+import com.google.common.collect.ImmutableList;
 import com.google.common.io.Resources;
 import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rule.Severity;
@@ -71,7 +72,9 @@ public class SearchAction implements RequestHandler {
       .setSince("4.4")
       .setHandler(this);
 
-    SearchOptions.defineGenericParameters(action, mapping.supportedFields(), "actives");
+    SearchOptions.defineFieldsParam(action,
+      ImmutableList.<String>builder().addAll(mapping.supportedFields()).add("actives").build());
+    SearchOptions.definePageParams(action);
     defineRuleSearchParameters(action);
   }
 
index 2a1c8e8c0a02a061f8ebcf6873d6c8f7314a1154..093a2e0cb375877bad352ff240f87cdbc6021438 100644 (file)
@@ -29,7 +29,7 @@ import java.util.HashSet;
 import java.util.Set;
 
 /**
- * Options about paging, sorting and fields to return
+ * Various Elasticsearch request options: paging, sorting, fields and facets
  *
  * @since 4.4
  */
@@ -39,13 +39,11 @@ public class QueryOptions {
 
   public static final int DEFAULT_OFFSET = 0;
   public static final int DEFAULT_LIMIT = 10;
-  public static final boolean DEFAULT_FACET = true;
+  public static final boolean DEFAULT_FACET = false;
 
   private int offset = DEFAULT_OFFSET;
   private int limit = DEFAULT_LIMIT;
-
   private boolean facet = DEFAULT_FACET;
-
   private Set<String> fieldsToReturn = new HashSet<String>();
 
   /**
@@ -83,10 +81,10 @@ public class QueryOptions {
    * Set offset and limit according to page approach
    */
   public QueryOptions setPage(int page, int pageSize) {
-    Preconditions.checkArgument(page > 0, "Page must be positive");
-    Preconditions.checkArgument(pageSize >= 0, "Page size must be positive or greater than 0");
-    this.offset = (page * pageSize) - pageSize;
-    this.limit = pageSize;
+    Preconditions.checkArgument(page >= 1, "Page must be greater or equal to 1 (got " + page + ")");
+    Preconditions.checkArgument(pageSize >= 0, "Page size must be greater or equal to 0 (got " + pageSize + ")");
+    setOffset((page * pageSize) - pageSize);
+    setLimit(pageSize);
     return this;
   }
 
@@ -129,8 +127,4 @@ public class QueryOptions {
     fieldsToReturn.addAll(Arrays.asList(c));
     return this;
   }
-
-  public boolean hasFieldToReturn(String key) {
-    return fieldsToReturn.isEmpty() || fieldsToReturn.contains(key);
-  }
 }
index 23a407a5e4b84ebe357cf1cb0ec135784afbe804..12ba74557b6b02f4fd029dd00c39db1693f78403 100644 (file)
@@ -39,7 +39,6 @@ public abstract class Result<K> {
   private long total;
   private long timeInMillis;
 
-
   public Result(SearchResponse response) {
     this.hits = new ArrayList<K>();
     this.facets = new HashMap<String, Collection<FacetValue>>();
index 870b31f7d79c81cf6d48f5bc7c5b4207139230a5..391152128050efa5f0ad45456c7a245756c041eb 100644 (file)
@@ -26,6 +26,7 @@ import org.sonar.server.search.Result;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
+import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 
@@ -92,16 +93,18 @@ public class SearchOptions {
     return options;
   }
 
-  public static void defineGenericParameters(WebService.NewAction action, Object... possibleValues) {
+  public static void defineFieldsParam(WebService.NewAction action, @Nullable Collection<String> possibleFields) {
     WebService.NewParam newParam = action
       .createParam(PARAM_FIELDS)
       .setDescription("Comma-separated list of the fields to be returned in response. All the fields are returned by default.")
-      .setPossibleValues(possibleValues);
-    if (newParam.possibleValues() != null && newParam.possibleValues().size() > 1) {
-      Iterator<String> it = newParam.possibleValues().iterator();
+      .setPossibleValues(possibleFields);
+    if (possibleFields != null && possibleFields.size() > 1) {
+      Iterator<String> it = possibleFields.iterator();
       newParam.setExampleValue(String.format("%s,%s", it.next(), it.next()));
     }
+  }
 
+  public static void definePageParams(WebService.NewAction action) {
     action
       .createParam(PARAM_PAGE)
       .setDescription("1-based page number")
diff --git a/sonar-server/src/main/java/org/sonar/server/ws/InternalRequest.java b/sonar-server/src/main/java/org/sonar/server/ws/InternalRequest.java
deleted file mode 100644 (file)
index 3895672..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.WebService;
-
-public abstract class InternalRequest extends Request {
-  @Override
-  protected void setAction(WebService.Action action) {
-    super.setAction(action);
-  }
-}
index 334fe83017e3a6971887780d25fb5e8c316d76e2..134016fa5172f86f68967fd963ed4269a8761b55 100644 (file)
  */
 package org.sonar.server.ws;
 
+import org.sonar.api.server.ws.internal.ValidatingRequest;
+
 import javax.servlet.http.HttpServletRequest;
 import java.util.Map;
 
-public class ServletRequest extends InternalRequest {
+public class ServletRequest extends ValidatingRequest {
 
   private final HttpServletRequest source;
   private final Map<String, String> params;
index bf989b6b2d26643dd7ba78cd85e737f3e2c317d2..f308e1850538fadad6df8ad8bb099b8eae70f53d 100644 (file)
@@ -26,6 +26,7 @@ import org.sonar.api.ServerComponent;
 import org.sonar.api.i18n.I18n;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.WebService;
+import org.sonar.api.server.ws.internal.ValidatingRequest;
 import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.exceptions.BadRequestException.Message;
@@ -75,7 +76,7 @@ public class WebServiceEngine implements ServerComponent, Startable {
     return context.controllers();
   }
 
-  public void execute(InternalRequest request, ServletResponse response,
+  public void execute(ValidatingRequest request, ServletResponse response,
                       String controllerPath, String actionKey) {
     try {
       WebService.Action action = getAction(controllerPath, actionKey);
index fe51a8cb6895cfc467b2a8b2f58b18048e314288..5a9c07bf08457c3863956da3fc06dd6de53da0a4 100644 (file)
@@ -33,22 +33,33 @@ public class RuleTagHelperTest {
   @Test
   public void applyTags() throws Exception {
     RuleDto rule = new RuleDto().setTags(Sets.newHashSet("performance"));
-    RuleTagHelper.applyTags(rule, Sets.newHashSet("java8", "security"));
+    boolean changed = RuleTagHelper.applyTags(rule, Sets.newHashSet("java8", "security"));
     assertThat(rule.getTags()).containsOnly("java8", "security");
+    assertThat(changed).isTrue();
   }
 
   @Test
   public void applyTags_remove_all_existing_tags() throws Exception {
     RuleDto rule = new RuleDto().setTags(Sets.newHashSet("performance"));
-    RuleTagHelper.applyTags(rule, Collections.<String>emptySet());
+    boolean changed = RuleTagHelper.applyTags(rule, Collections.<String>emptySet());
     assertThat(rule.getTags()).isEmpty();
+    assertThat(changed).isTrue();
+  }
+
+  @Test
+  public void applyTags_no_changes() throws Exception {
+    RuleDto rule = new RuleDto().setTags(Sets.newHashSet("performance"));
+    boolean changed = RuleTagHelper.applyTags(rule, Sets.newHashSet("performance"));
+    assertThat(rule.getTags()).containsOnly("performance");
+    assertThat(changed).isFalse();
   }
 
   @Test
   public void applyTags_validate_format() throws Exception {
     RuleDto rule = new RuleDto();
-    RuleTagHelper.applyTags(rule, Sets.newHashSet("java8", "security"));
+    boolean changed = RuleTagHelper.applyTags(rule, Sets.newHashSet("java8", "security"));
     assertThat(rule.getTags()).containsOnly("java8", "security");
+    assertThat(changed).isTrue();
 
     try {
       RuleTagHelper.applyTags(rule, Sets.newHashSet("Java Eight"));
@@ -64,8 +75,9 @@ public class RuleTagHelperTest {
       .setTags(Sets.newHashSet("performance"))
       .setSystemTags(Sets.newHashSet("security"));
 
-    RuleTagHelper.applyTags(rule, Sets.newHashSet("java8", "security"));
+    boolean changed = RuleTagHelper.applyTags(rule, Sets.newHashSet("java8", "security"));
 
+    assertThat(changed).isTrue();
     assertThat(rule.getTags()).containsOnly("java8");
     assertThat(rule.getSystemTags()).containsOnly("security");
   }
index 5d9b507bada4eb79b1f7594310d718ce68db8b23..abdb378360adb3db05346db60def74d3fa2a1c7b 100644 (file)
@@ -26,12 +26,49 @@ import org.junit.Test;
 import java.util.Arrays;
 
 import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
 
 public class QueryOptionsTest {
 
+  QueryOptions options = new QueryOptions();
+
+  @Test
+  public void page_shortcut_for_limit_and_offset() throws Exception {
+    options.setPage(3, 10);
+
+    assertThat(options.getLimit()).isEqualTo(10);
+    assertThat(options.getOffset()).isEqualTo(20);
+  }
+
+  @Test
+  public void page_starts_at_one() throws Exception {
+    options.setPage(1, 10);
+    assertThat(options.getLimit()).isEqualTo(10);
+    assertThat(options.getOffset()).isEqualTo(0);
+  }
+
+  @Test
+  public void page_must_be_strictly_positive() throws Exception {
+    try {
+      options.setPage(0, 10);
+      fail();
+    } catch (IllegalArgumentException e) {
+      assertThat(e).hasMessage("Page must be greater or equal to 1 (got 0)");
+    }
+  }
+
+  @Test
+  public void page_size_must_be_positive() throws Exception {
+    try {
+      options.setPage(2, -1);
+      fail();
+    } catch (IllegalArgumentException e) {
+      assertThat(e).hasMessage("Page size must be greater or equal to 0 (got -1)");
+    }
+  }
+
   @Test
   public void fields_to_return() throws Exception {
-    QueryOptions options = new QueryOptions();
     assertThat(options.getFieldsToReturn()).isEmpty();
 
     options.setFieldsToReturn(Arrays.asList("one", "two"));
@@ -46,8 +83,6 @@ public class QueryOptionsTest {
 
   @Test
   public void support_immutable_fields() throws Exception {
-    QueryOptions options = new QueryOptions();
-
     options.setFieldsToReturn(ImmutableList.of("one", "two"));
     assertThat(options.getFieldsToReturn()).containsOnly("one", "two");
 
@@ -57,4 +92,12 @@ public class QueryOptionsTest {
     options.addFieldsToReturn("four");
     assertThat(options.getFieldsToReturn()).containsOnly("one", "two", "three", "four");
   }
+
+  @Test
+  public void do_not_request_facets_by_default() throws Exception {
+    assertThat(options.isFacet()).isFalse();
+
+    options.setFacet(true);
+    assertThat(options.isFacet()).isTrue();
+  }
 }
diff --git a/sonar-server/src/test/java/org/sonar/server/search/ws/SearchOptionsTest.java b/sonar-server/src/test/java/org/sonar/server/search/ws/SearchOptionsTest.java
new file mode 100644 (file)
index 0000000..6f1d7d5
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.search.ws;
+
+import com.google.common.collect.Lists;
+import org.junit.Test;
+import org.skyscreamer.jsonassert.JSONAssert;
+import org.sonar.api.server.ws.RequestHandler;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.server.ws.internal.SimpleGetRequest;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.server.search.Result;
+
+import java.io.StringWriter;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class SearchOptionsTest {
+
+  @Test
+  public void create_from_http_request() throws Exception {
+    SimpleGetRequest request = new SimpleGetRequest();
+    request.setParam("p", "3");
+    request.setParam("ps", "10");
+    request.setParam("f", "name,repo");
+    request.setParam("severities", "BLOCKER");
+
+    SearchOptions options = SearchOptions.create(request);
+
+    assertThat(options.fields()).containsOnly("name", "repo");
+    assertThat(options.page()).isEqualTo(3);
+    assertThat(options.pageSize()).isEqualTo(10);
+  }
+
+  @Test
+  public void hasField() throws Exception {
+    SimpleGetRequest request = new SimpleGetRequest();
+    request.setParam("p", "3");
+    request.setParam("ps", "10");
+    request.setParam("f", "name,repo");
+    SearchOptions options = SearchOptions.create(request);
+
+    assertThat(options.hasField("repo")).isTrue();
+    assertThat(options.hasField("severity")).isFalse();
+  }
+
+  @Test
+  public void hasField_always_true_by_default() throws Exception {
+    SimpleGetRequest request = new SimpleGetRequest();
+    request.setParam("p", "3");
+    request.setParam("ps", "10");
+    SearchOptions options = SearchOptions.create(request);
+
+    assertThat(options.hasField("repo")).isTrue();
+  }
+
+  @Test
+  public void hasField_no_if_empty_value() throws Exception {
+    SimpleGetRequest request = new SimpleGetRequest();
+    request.setParam("p", "3");
+    request.setParam("ps", "10");
+    request.setParam("f", "");
+    SearchOptions options = SearchOptions.create(request);
+
+    assertThat(options.hasField("repo")).isFalse();
+  }
+
+  @Test
+  public void write_statistics_to_json_response() throws Exception {
+    SimpleGetRequest request = new SimpleGetRequest();
+    request.setParam("p", "3");
+    request.setParam("ps", "10");
+    request.setParam("f", "name,repo");
+    request.setParam("severities", "BLOCKER");
+
+    SearchOptions options = SearchOptions.create(request);
+    StringWriter json = new StringWriter();
+    JsonWriter jsonWriter = JsonWriter.of(json).beginObject();
+    Result result = mock(Result.class);
+    when(result.getTotal()).thenReturn(42L);
+    options.writeStatistics(jsonWriter, result);
+    jsonWriter.endObject().close();
+
+    JSONAssert.assertEquals("{\"total\": 42, \"p\": 3, \"ps\": 10}", json.toString(), true);
+  }
+
+  @Test
+  public void defineFieldsParam() throws Exception {
+    WebService.Context context = new WebService.Context();
+    new WebService() {
+      @Override
+      public void define(Context context) {
+        NewController newController = context.createController("api/foo");
+        NewAction action = newController.createAction("search").setHandler(mock(RequestHandler.class));
+        SearchOptions.defineFieldsParam(action, Lists.newArrayList("name", "lang", "severity"));
+        newController.done();
+      }
+    }.define(context);
+
+    WebService.Action searchAction = context.controller("api/foo").action("search");
+    WebService.Param param = searchAction.param("f");
+    assertThat(param).isNotNull();
+    assertThat(param.possibleValues()).containsOnly("name", "lang", "severity");
+    assertThat(param.exampleValue()).isEqualTo("name,lang");
+  }
+
+  @Test
+  public void definePageParams() throws Exception {
+    WebService.Context context = new WebService.Context();
+    new WebService() {
+      @Override
+      public void define(Context context) {
+        NewController newController = context.createController("api/foo");
+        NewAction action = newController.createAction("search").setHandler(mock(RequestHandler.class));
+        SearchOptions.definePageParams(action);
+        newController.done();
+      }
+    }.define(context);
+
+    WebService.Action searchAction = context.controller("api/foo").action("search");
+    WebService.Param page = searchAction.param("p");
+    assertThat(page).isNotNull();
+    assertThat(page.defaultValue()).isEqualTo("1");
+    WebService.Param pageSize = searchAction.param("ps");
+    assertThat(pageSize).isNotNull();
+    assertThat(pageSize.defaultValue()).isEqualTo("25");
+
+  }
+}
index 100a2a59d041cf2fc165c179849842f9c1334700..6bf8690856d43cb5de85108a81404d5fd361e5c9 100644 (file)
@@ -30,6 +30,7 @@ import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.RequestHandler;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
+import org.sonar.api.server.ws.internal.ValidatingRequest;
 import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.exceptions.BadRequestException.Message;
 import org.sonar.server.exceptions.ServerException;
@@ -49,7 +50,7 @@ import static org.mockito.Mockito.when;
 
 public class WebServiceEngineTest {
 
-  private static class SimpleRequest extends InternalRequest {
+  private static class SimpleRequest extends ValidatingRequest {
     private final String method;
     private Map<String, String> params = Maps.newHashMap();
 
@@ -102,7 +103,7 @@ public class WebServiceEngineTest {
 
   @Test
   public void execute_request() throws Exception {
-    InternalRequest request = new SimpleRequest("GET");
+    ValidatingRequest request = new SimpleRequest("GET");
     ServletResponse response = new ServletResponse();
     engine.execute(request, response, "api/system", "health");
 
@@ -111,7 +112,7 @@ public class WebServiceEngineTest {
 
   @Test
   public void no_content() throws Exception {
-    InternalRequest request = new SimpleRequest("GET");
+    ValidatingRequest request = new SimpleRequest("GET");
     ServletResponse response = new ServletResponse();
     engine.execute(request, response, "api/system", "alive");
 
@@ -120,7 +121,7 @@ public class WebServiceEngineTest {
 
   @Test
   public void bad_controller() throws Exception {
-    InternalRequest request = new SimpleRequest("GET");
+    ValidatingRequest request = new SimpleRequest("GET");
     ServletResponse response = new ServletResponse();
     engine.execute(request, response, "api/xxx", "health");
 
@@ -129,7 +130,7 @@ public class WebServiceEngineTest {
 
   @Test
   public void bad_action() throws Exception {
-    InternalRequest request = new SimpleRequest("GET");
+    ValidatingRequest request = new SimpleRequest("GET");
     ServletResponse response = new ServletResponse();
     engine.execute(request, response, "api/system", "xxx");
 
@@ -138,7 +139,7 @@ public class WebServiceEngineTest {
 
   @Test
   public void method_get_not_allowed() throws Exception {
-    InternalRequest request = new SimpleRequest("GET");
+    ValidatingRequest request = new SimpleRequest("GET");
     ServletResponse response = new ServletResponse();
     engine.execute(request, response, "api/system", "ping");
 
@@ -147,7 +148,7 @@ public class WebServiceEngineTest {
 
   @Test
   public void method_post_required() throws Exception {
-    InternalRequest request = new SimpleRequest("POST");
+    ValidatingRequest request = new SimpleRequest("POST");
     ServletResponse response = new ServletResponse();
     engine.execute(request, response, "api/system", "ping");
 
@@ -156,7 +157,7 @@ public class WebServiceEngineTest {
 
   @Test
   public void unknown_parameter_is_set() throws Exception {
-    InternalRequest request = new SimpleRequest("GET").setParam("unknown", "Unknown");
+    ValidatingRequest request = new SimpleRequest("GET").setParam("unknown", "Unknown");
     ServletResponse response = new ServletResponse();
     engine.execute(request, response, "api/system", "fail_with_undeclared_parameter");
 
@@ -165,7 +166,7 @@ public class WebServiceEngineTest {
 
   @Test
   public void required_parameter_is_not_set() throws Exception {
-    InternalRequest request = new SimpleRequest("GET");
+    ValidatingRequest request = new SimpleRequest("GET");
     ServletResponse response = new ServletResponse();
     engine.execute(request, response, "api/system", "print");
 
@@ -174,7 +175,7 @@ public class WebServiceEngineTest {
 
   @Test
   public void optional_parameter_is_not_set() throws Exception {
-    InternalRequest request = new SimpleRequest("GET").setParam("message", "Hello World");
+    ValidatingRequest request = new SimpleRequest("GET").setParam("message", "Hello World");
     ServletResponse response = new ServletResponse();
     engine.execute(request, response, "api/system", "print");
 
@@ -183,7 +184,7 @@ public class WebServiceEngineTest {
 
   @Test
   public void optional_parameter_is_set() throws Exception {
-    InternalRequest request = new SimpleRequest("GET")
+    ValidatingRequest request = new SimpleRequest("GET")
       .setParam("message", "Hello World")
       .setParam("author", "Marcel");
     ServletResponse response = new ServletResponse();
@@ -194,7 +195,7 @@ public class WebServiceEngineTest {
 
   @Test
   public void param_value_is_in_possible_values() throws Exception {
-    InternalRequest request = new SimpleRequest("GET")
+    ValidatingRequest request = new SimpleRequest("GET")
       .setParam("message", "Hello World")
       .setParam("format", "json");
     ServletResponse response = new ServletResponse();
@@ -205,7 +206,7 @@ public class WebServiceEngineTest {
 
   @Test
   public void param_value_is_not_in_possible_values() throws Exception {
-    InternalRequest request = new SimpleRequest("GET")
+    ValidatingRequest request = new SimpleRequest("GET")
       .setParam("message", "Hello World")
       .setParam("format", "html");
     ServletResponse response = new ServletResponse();
@@ -216,7 +217,7 @@ public class WebServiceEngineTest {
 
   @Test
   public void internal_error() throws Exception {
-    InternalRequest request = new SimpleRequest("GET");
+    ValidatingRequest request = new SimpleRequest("GET");
     ServletResponse response = new ServletResponse();
     engine.execute(request, response, "api/system", "fail");
 
@@ -227,7 +228,7 @@ public class WebServiceEngineTest {
 
   @Test
   public void bad_request_with_i18n_message() throws Exception {
-    InternalRequest request = new SimpleRequest("GET").setParam("count", "3");
+    ValidatingRequest request = new SimpleRequest("GET").setParam("count", "3");
     ServletResponse response = new ServletResponse();
     when(i18n.message(eq(Locale.getDefault()), eq("bad.request.reason"), anyString(), eq(0))).thenReturn("Bad request reason #0");
 
@@ -242,7 +243,7 @@ public class WebServiceEngineTest {
 
   @Test
   public void bad_request_with_multiple_messages() throws Exception {
-    InternalRequest request = new SimpleRequest("GET").setParam("count", "3");
+    ValidatingRequest request = new SimpleRequest("GET").setParam("count", "3");
     ServletResponse response = new ServletResponse();
 
     engine.execute(request, response, "api/system", "fail_with_multiple_messages");
@@ -258,7 +259,7 @@ public class WebServiceEngineTest {
 
   @Test
   public void bad_request_with_multiple_i18n_messages() throws Exception {
-    InternalRequest request = new SimpleRequest("GET").setParam("count", "3");
+    ValidatingRequest request = new SimpleRequest("GET").setParam("count", "3");
     ServletResponse response = new ServletResponse();
     when(i18n.message(Locale.getDefault(), "bad.request.reason", null, 0)).thenReturn("Bad request reason #0");
     when(i18n.message(Locale.getDefault(), "bad.request.reason", null, 1)).thenReturn("Bad request reason #1");
@@ -277,7 +278,7 @@ public class WebServiceEngineTest {
 
   @Test
   public void server_exception_with_i18n_message() throws Exception {
-    InternalRequest request = new SimpleRequest("GET");
+    ValidatingRequest request = new SimpleRequest("GET");
     ServletResponse response = new ServletResponse();
     when(i18n.message(eq(Locale.getDefault()), eq("not.found"), anyString())).thenReturn("Element is not found");
 
index ae065f5139b2900b1fd44e39549f2ea4b4da0ea6..76d93201af5c3fb4d6646c2e42a363fd28413f99 100644 (file)
@@ -25,6 +25,7 @@ import org.apache.commons.io.IOUtils;
 import org.skyscreamer.jsonassert.JSONAssert;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
+import org.sonar.api.server.ws.internal.ValidatingRequest;
 import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.api.utils.text.XmlWriter;
 
@@ -42,7 +43,7 @@ import java.util.Map;
  */
 public class WsTester {
 
-  public static class TestRequest extends InternalRequest {
+  public static class TestRequest extends ValidatingRequest {
 
     private final String method;
     private Map<String, String> params = Maps.newHashMap();