From: Simon Brandhof Date: Tue, 20 May 2014 21:01:12 +0000 (+0200) Subject: SONAR-5007 add tests X-Git-Tag: 4.4-RC1~965 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=57ec7e177f89ea5290184040ff9ed6ba74f5331f;p=sonarqube.git SONAR-5007 add tests --- diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/Request.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/Request.java index 9d969a68ce7..8cb158e87eb 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/Request.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/Request.java @@ -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 paramAsStrings(String key) { - WebService.Param definition = action.param(key); - String value = readParamOrDefaultValue(key, definition); - if (value == null) { - return null; - } - List values = Lists.newArrayList(Splitter.on(',').omitEmptyStrings().trimResults().split(value)); - for (String s : values) { - validate(s, definition); - } - return values; - } - - @CheckForNull - public > List paramAsEnums(String key, Class enumClass) { - WebService.Param definition = action.param(key); - String value = readParamOrDefaultValue(key, definition); - if (value == null) { - return null; - } - Iterable values = Splitter.on(',').omitEmptyStrings().trimResults().split(value); - List 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 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 > List paramAsEnums(String key, Class enumClass) { + String value = param(key); + if (value == null) { + return null; + } + Iterable values = Splitter.on(',').omitEmptyStrings().trimResults().split(value); + List result = Lists.newArrayList(); + for (String s : values) { + result.add(Enum.valueOf(enumClass, s)); + } + return result; + } } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/WebService.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/WebService.java index 9508fd1d179..5e464a4200f 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/WebService.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/WebService.java @@ -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. - *

- * Note that the parameter supports values with type Iterable, for example : - *

-     *   setPossibleValues(Arrays.asList("one", "two"), "three", "four");
-     * 
* * @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 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 index 00000000000..c7fa2a29267 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/SimpleGetRequest.java @@ -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 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 index 00000000000..002612f03c5 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/ValidatingRequest.java @@ -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 paramAsStrings(String key) { + WebService.Param definition = action.param(key); + String value = readParamOrDefaultValue(key, definition); + if (value == null) { + return null; + } + List values = Lists.newArrayList(Splitter.on(',').omitEmptyStrings().trimResults().split(value)); + for (String s : values) { + validate(s, definition); + } + return values; + } + + @CheckForNull + @Override + public > List paramAsEnums(String key, Class enumClass) { + WebService.Param definition = action.param(key); + String value = readParamOrDefaultValue(key, definition); + if (value == null) { + return null; + } + Iterable values = Splitter.on(',').omitEmptyStrings().trimResults().split(value); + List 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 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)); + } + } +} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/RequestTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/RequestTest.java index 76421b05c18..9d2926460f6 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/RequestTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/RequestTest.java @@ -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 params = Maps.newHashMap(); diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/WebServiceTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/WebServiceTest.java index ccebd01cd4b..4dab17f0641 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/WebServiceTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/WebServiceTest.java @@ -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 diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/RuleTagHelper.java b/sonar-server/src/main/java/org/sonar/server/rule2/RuleTagHelper.java index 99c95352754..c24205a293c 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule2/RuleTagHelper.java +++ b/sonar-server/src/main/java/org/sonar/server/rule2/RuleTagHelper.java @@ -50,6 +50,6 @@ class RuleTagHelper { } }); rule.setTags(withoutSystemTags); - return Sets.difference(initialTags, withoutSystemTags).size() > 0; + return withoutSystemTags.size()!=initialTags.size() || !withoutSystemTags.containsAll(initialTags); } } diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/ws/RuleMapping.java b/sonar-server/src/main/java/org/sonar/server/rule2/ws/RuleMapping.java index 2e131fa2eca..d9142351e39 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule2/ws/RuleMapping.java +++ b/sonar-server/src/main/java/org/sonar/server/rule2/ws/RuleMapping.java @@ -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; diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/ws/SearchAction.java b/sonar-server/src/main/java/org/sonar/server/rule2/ws/SearchAction.java index bde40f79dbb..45a832dc5ae 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule2/ws/SearchAction.java +++ b/sonar-server/src/main/java/org/sonar/server/rule2/ws/SearchAction.java @@ -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.builder().addAll(mapping.supportedFields()).add("actives").build()); + SearchOptions.definePageParams(action); defineRuleSearchParameters(action); } diff --git a/sonar-server/src/main/java/org/sonar/server/search/QueryOptions.java b/sonar-server/src/main/java/org/sonar/server/search/QueryOptions.java index 2a1c8e8c0a0..093a2e0cb37 100644 --- a/sonar-server/src/main/java/org/sonar/server/search/QueryOptions.java +++ b/sonar-server/src/main/java/org/sonar/server/search/QueryOptions.java @@ -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 fieldsToReturn = new HashSet(); /** @@ -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); - } } diff --git a/sonar-server/src/main/java/org/sonar/server/search/Result.java b/sonar-server/src/main/java/org/sonar/server/search/Result.java index 23a407a5e4b..12ba74557b6 100644 --- a/sonar-server/src/main/java/org/sonar/server/search/Result.java +++ b/sonar-server/src/main/java/org/sonar/server/search/Result.java @@ -39,7 +39,6 @@ public abstract class Result { private long total; private long timeInMillis; - public Result(SearchResponse response) { this.hits = new ArrayList(); this.facets = new HashMap>(); diff --git a/sonar-server/src/main/java/org/sonar/server/search/ws/SearchOptions.java b/sonar-server/src/main/java/org/sonar/server/search/ws/SearchOptions.java index 870b31f7d79..39115212805 100644 --- a/sonar-server/src/main/java/org/sonar/server/search/ws/SearchOptions.java +++ b/sonar-server/src/main/java/org/sonar/server/search/ws/SearchOptions.java @@ -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 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 it = newParam.possibleValues().iterator(); + .setPossibleValues(possibleFields); + if (possibleFields != null && possibleFields.size() > 1) { + Iterator 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 index 3895672e4c4..00000000000 --- a/sonar-server/src/main/java/org/sonar/server/ws/InternalRequest.java +++ /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); - } -} diff --git a/sonar-server/src/main/java/org/sonar/server/ws/ServletRequest.java b/sonar-server/src/main/java/org/sonar/server/ws/ServletRequest.java index 334fe83017e..134016fa517 100644 --- a/sonar-server/src/main/java/org/sonar/server/ws/ServletRequest.java +++ b/sonar-server/src/main/java/org/sonar/server/ws/ServletRequest.java @@ -19,10 +19,12 @@ */ 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 params; diff --git a/sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.java b/sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.java index bf989b6b2d2..f308e185053 100644 --- a/sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.java +++ b/sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.java @@ -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); diff --git a/sonar-server/src/test/java/org/sonar/server/rule2/RuleTagHelperTest.java b/sonar-server/src/test/java/org/sonar/server/rule2/RuleTagHelperTest.java index fe51a8cb689..5a9c07bf084 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule2/RuleTagHelperTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule2/RuleTagHelperTest.java @@ -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.emptySet()); + boolean changed = RuleTagHelper.applyTags(rule, Collections.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"); } diff --git a/sonar-server/src/test/java/org/sonar/server/search/QueryOptionsTest.java b/sonar-server/src/test/java/org/sonar/server/search/QueryOptionsTest.java index 5d9b507bada..abdb378360a 100644 --- a/sonar-server/src/test/java/org/sonar/server/search/QueryOptionsTest.java +++ b/sonar-server/src/test/java/org/sonar/server/search/QueryOptionsTest.java @@ -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 index 00000000000..6f1d7d5e08b --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/search/ws/SearchOptionsTest.java @@ -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"); + + } +} diff --git a/sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java b/sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java index 100a2a59d04..6bf8690856d 100644 --- a/sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java +++ b/sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java @@ -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 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"); diff --git a/sonar-server/src/test/java/org/sonar/server/ws/WsTester.java b/sonar-server/src/test/java/org/sonar/server/ws/WsTester.java index ae065f5139b..76d93201af5 100644 --- a/sonar-server/src/test/java/org/sonar/server/ws/WsTester.java +++ b/sonar-server/src/test/java/org/sonar/server/ws/WsTester.java @@ -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 params = Maps.newHashMap();