From 44c81c62d68011465ab9ff44036f4feadef06830 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Lievremont Date: Mon, 3 Mar 2014 18:32:10 +0100 Subject: [PATCH] SONAR-5087 Add WS to find rules for issues UI --- .../org/sonar/server/paging/PagedResult.java | 45 ++++++++ .../{qualityprofile => paging}/Paging.java | 2 +- .../PagingResult.java | 2 +- .../org/sonar/server/platform/Platform.java | 1 + .../qualityprofile/QProfileRuleLookup.java | 3 + .../server/qualityprofile/QProfiles.java | 2 + .../java/org/sonar/server/rule/RuleQuery.java | 100 ++++++++++++++++ .../org/sonar/server/rule/RuleRegistry.java | 28 ++++- .../java/org/sonar/server/rule/Rules.java | 5 + .../server/rule/ws/RuleSearchWsHandler.java | 107 ++++++++++++++++++ .../org/sonar/server/rule/ws/RulesWs.java | 13 ++- .../QProfileRuleLookupTest.java | 2 + .../server/qualityprofile/QProfilesTest.java | 2 + .../server/rule/ws/AddTagsWsHandlerTest.java | 2 +- .../rule/ws/RemoveTagsWsHandlerTest.java | 2 +- .../rule/ws/RuleSearchWsHandlerTest.java | 102 +++++++++++++++++ .../server/rule/ws/RuleShowWsHandlerTest.java | 2 +- .../org/sonar/server/rule/ws/RulesWsTest.java | 15 ++- 18 files changed, 426 insertions(+), 9 deletions(-) create mode 100644 sonar-server/src/main/java/org/sonar/server/paging/PagedResult.java rename sonar-server/src/main/java/org/sonar/server/{qualityprofile => paging}/Paging.java (97%) rename sonar-server/src/main/java/org/sonar/server/{qualityprofile => paging}/PagingResult.java (97%) create mode 100644 sonar-server/src/main/java/org/sonar/server/rule/RuleQuery.java create mode 100644 sonar-server/src/main/java/org/sonar/server/rule/ws/RuleSearchWsHandler.java create mode 100644 sonar-server/src/test/java/org/sonar/server/rule/ws/RuleSearchWsHandlerTest.java diff --git a/sonar-server/src/main/java/org/sonar/server/paging/PagedResult.java b/sonar-server/src/main/java/org/sonar/server/paging/PagedResult.java new file mode 100644 index 00000000000..d960093faa0 --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/paging/PagedResult.java @@ -0,0 +1,45 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.paging; + +import java.util.Collection; + +/** + * @since 4.3 + */ +public class PagedResult { + + private Collection results; + + private PagingResult paging; + + public PagedResult(Collection results, PagingResult paging) { + this.results = results; + this.paging = paging; + } + + public Collection results() { + return this.results; + } + + public PagingResult paging() { + return this.paging; + } +} diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/Paging.java b/sonar-server/src/main/java/org/sonar/server/paging/Paging.java similarity index 97% rename from sonar-server/src/main/java/org/sonar/server/qualityprofile/Paging.java rename to sonar-server/src/main/java/org/sonar/server/paging/Paging.java index 2b4648651c3..10b2f434926 100644 --- a/sonar-server/src/main/java/org/sonar/server/qualityprofile/Paging.java +++ b/sonar-server/src/main/java/org/sonar/server/paging/Paging.java @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.qualityprofile; +package org.sonar.server.paging; /** * Heavily inspired by {@link org.sonar.api.utils.Paging} diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/PagingResult.java b/sonar-server/src/main/java/org/sonar/server/paging/PagingResult.java similarity index 97% rename from sonar-server/src/main/java/org/sonar/server/qualityprofile/PagingResult.java rename to sonar-server/src/main/java/org/sonar/server/paging/PagingResult.java index aa82b4ba568..14ec1200ba1 100644 --- a/sonar-server/src/main/java/org/sonar/server/qualityprofile/PagingResult.java +++ b/sonar-server/src/main/java/org/sonar/server/paging/PagingResult.java @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.qualityprofile; +package org.sonar.server.paging; /** * Heavily inspired by {@link org.sonar.api.utils.Paging} diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java index 9417925697a..17ab1030baa 100644 --- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java +++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java @@ -373,6 +373,7 @@ public final class Platform { servicesContainer.addSingleton(RuleRepositories.class); servicesContainer.addSingleton(RulesWs.class); servicesContainer.addSingleton(RuleShowWsHandler.class); + servicesContainer.addSingleton(RuleSearchWsHandler.class); servicesContainer.addSingleton(AddTagsWsHandler.class); servicesContainer.addSingleton(RemoveTagsWsHandler.class); diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRuleLookup.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRuleLookup.java index 15c7ba8f3d8..a68554a45d1 100644 --- a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRuleLookup.java +++ b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileRuleLookup.java @@ -19,6 +19,9 @@ */ package org.sonar.server.qualityprofile; +import org.sonar.server.paging.Paging; +import org.sonar.server.paging.PagingResult; + import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Maps; import org.apache.commons.lang.StringUtils; diff --git a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java index 4442553a8c3..3de9aa427ab 100644 --- a/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java +++ b/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java @@ -20,6 +20,8 @@ package org.sonar.server.qualityprofile; +import org.sonar.server.paging.Paging; + import com.google.common.base.Strings; import org.sonar.api.ServerComponent; import org.sonar.api.component.Component; diff --git a/sonar-server/src/main/java/org/sonar/server/rule/RuleQuery.java b/sonar-server/src/main/java/org/sonar/server/rule/RuleQuery.java new file mode 100644 index 00000000000..1c9916047b8 --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/rule/RuleQuery.java @@ -0,0 +1,100 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.rule; + +import org.sonar.server.paging.Paging; + +import javax.annotation.Nullable; + +/** + * @since 4.3 + */ +public class RuleQuery { + + private static final int DEFAULT_PAGE_SIZE = 25; + + private String key; + + private String query; + + private Paging paging; + + private RuleQuery(@Nullable String key, @Nullable String query, Paging paging) { + this.key = key; + this.query = query; + this.paging = paging; + } + + public String key() { + return this.key; + } + + public String query() { + return this.query; + } + + public Paging paging() { + return this.paging; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private String key; + + private String query; + + private int pageSize; + + private int page; + + private Builder() { + this.page = 0; + this.pageSize = DEFAULT_PAGE_SIZE; + } + + public Builder withKey(String key) { + this.key = key; + return this; + } + + public Builder withSearchQuery(String query) { + this.query = query; + return this; + } + + public Builder withPageSize(int pageSize) { + this.pageSize = pageSize; + return this; + } + + public Builder withPage(int page) { + this.page = page; + return this; + } + + public RuleQuery build() { + return new RuleQuery(key, query, Paging.create(pageSize, page)); + } + } +} diff --git a/sonar-server/src/main/java/org/sonar/server/rule/RuleRegistry.java b/sonar-server/src/main/java/org/sonar/server/rule/RuleRegistry.java index f89cf8ebf3f..c8570d771e3 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/RuleRegistry.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/RuleRegistry.java @@ -20,6 +20,8 @@ package org.sonar.server.rule; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; import com.google.common.collect.Multimap; import org.elasticsearch.ElasticSearchException; import org.elasticsearch.common.collect.Lists; @@ -28,13 +30,17 @@ import org.elasticsearch.common.io.BytesStream; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.index.query.FilterBuilders; +import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHits; +import org.elasticsearch.search.sort.SortOrder; import org.sonar.api.rule.RuleKey; import org.sonar.api.utils.TimeProfiler; import org.sonar.core.rule.*; import org.sonar.server.es.ESIndex; import org.sonar.server.es.SearchQuery; import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.paging.PagedResult; +import org.sonar.server.paging.PagingResult; import javax.annotation.CheckForNull; @@ -45,6 +51,7 @@ import java.util.List; import java.util.Map; import static com.google.common.collect.Lists.newArrayList; +import static org.sonar.api.rules.Rule.STATUS_REMOVED; /** * Fill search index with rules @@ -97,7 +104,7 @@ public class RuleRegistry { searchQuery.searchString(params.remove(PARAM_NAMEORKEY)); } if (!params.containsKey(PARAM_STATUS)) { - searchQuery.notField(PARAM_STATUS, org.sonar.api.rules.Rule.STATUS_REMOVED); + searchQuery.notField(PARAM_STATUS, STATUS_REMOVED); } for (Map.Entry param : params.entrySet()) { @@ -115,6 +122,25 @@ public class RuleRegistry { } } + public PagedResult find(RuleQuery query) { + SearchHits hits = searchIndex.executeRequest( + searchIndex.client().prepareSearch(INDEX_RULES).setTypes(TYPE_RULE) + .setPostFilter( + FilterBuilders.boolFilter() + .must(FilterBuilders.termFilter(RuleDocument.FIELD_NAME, query.query())) + .mustNot(FilterBuilders.termFilter(RuleDocument.FIELD_STATUS, STATUS_REMOVED)) + ) + .addSort(RuleDocument.FIELD_NAME, SortOrder.ASC) + .setSize(query.paging().pageSize()) + .setFrom(query.paging().offset())); + + Builder rulesBuilder = ImmutableList.builder(); + for (SearchHit hit: hits.hits()) { + rulesBuilder.add(RuleDocumentParser.parse(hit.sourceAsMap())); + } + return new PagedResult(rulesBuilder.build(), PagingResult.create(query.paging().pageSize(), query.paging().pageIndex(), hits.getTotalHits())); + } + /** * Create or update definition of rule identified by ruleId * diff --git a/sonar-server/src/main/java/org/sonar/server/rule/Rules.java b/sonar-server/src/main/java/org/sonar/server/rule/Rules.java index 0f9d4731765..4faac5f6ae2 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/Rules.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/Rules.java @@ -27,6 +27,7 @@ import org.sonar.core.rule.RuleDao; import org.sonar.core.rule.RuleDto; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.paging.PagedResult; import org.sonar.server.qualityprofile.QProfileValidations; import org.sonar.server.user.UserSession; import org.sonar.server.util.RubyUtils; @@ -94,6 +95,10 @@ public class Rules implements ServerExtension { return ruleRegistry.findByKey(key); } + public PagedResult find(RuleQuery query) { + return ruleRegistry.find(query); + } + // // Rule validation // diff --git a/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleSearchWsHandler.java b/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleSearchWsHandler.java new file mode 100644 index 00000000000..ed76a8c16ae --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleSearchWsHandler.java @@ -0,0 +1,107 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.rule.ws; + +import org.sonar.api.resources.Language; +import org.sonar.api.resources.Languages; +import org.sonar.api.rule.RuleKey; +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.utils.text.JsonWriter; +import org.sonar.server.paging.PagedResult; +import org.sonar.server.rule.Rule; +import org.sonar.server.rule.RuleQuery; +import org.sonar.server.rule.Rules; + +import javax.annotation.CheckForNull; + +import java.util.Collection; +import java.util.Collections; + +public class RuleSearchWsHandler implements RequestHandler { + + private final Rules rules; + private final Languages languages; + + public RuleSearchWsHandler(Rules rules, Languages languages) { + this.rules = rules; + this.languages = languages; + } + + @Override + public void handle(Request request, Response response) { + final String ruleKeyParam = request.param("k"); + Collection foundRules = Collections.emptyList(); + boolean hasMore = false; + if (ruleKeyParam == null) { + final String ruleSearchParam = request.param("s"); + final int pageSize = request.paramAsInt("ps", 25); + final int pageIndex = request.paramAsInt("p", 1); + PagedResult searchResult = rules.find(RuleQuery.builder() + .withSearchQuery(ruleSearchParam) + .withPageSize(pageSize) + .withPage(pageIndex) + .build()); + foundRules = searchResult.results(); + hasMore = searchResult.paging().hasNextPage(); + } else { + RuleKey ruleKey = RuleKey.parse(ruleKeyParam); + Rule rule = findRule(ruleKey); + if (rule != null) { + foundRules = Collections.singleton(rule); + } + hasMore = false; + } + + JsonWriter json = response.newJsonWriter(); + json.beginObject().name("results").beginArray(); + for(Rule rule: foundRules) { + json.beginObject(); + writeRule(rule, json); + json.endObject(); + } + json.endArray().prop("more", hasMore).endObject().close(); + } + + @CheckForNull + private Rule findRule(RuleKey ruleKey) { + return rules.findByKey(ruleKey); + } + + private void writeRule(Rule rule, JsonWriter json) { + String languageName = null; + String languageKey = rule.language(); + if (languageKey != null) { + Language language = languages.get(languageKey); + if (language != null) { + languageName = language.getName(); + } else { + languageName = languageKey; + } + } + json + .prop("key", rule.ruleKey().toString()) + .prop("name", rule.name()) + .prop("language", languageName) + ; + } +} diff --git a/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWs.java b/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWs.java index b225e1a57f5..30f363d37cc 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWs.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWs.java @@ -23,11 +23,13 @@ import org.sonar.api.server.ws.WebService; public class RulesWs implements WebService { + private final RuleSearchWsHandler searchHandler; private final RuleShowWsHandler showHandler; private final AddTagsWsHandler addTagsWsHandler; private final RemoveTagsWsHandler removeTagsWsHandler; - public RulesWs(RuleShowWsHandler showHandler, AddTagsWsHandler addTagsWsHandler, RemoveTagsWsHandler removeTagsWsHandler) { + public RulesWs(RuleSearchWsHandler searchHandler, RuleShowWsHandler showHandler, AddTagsWsHandler addTagsWsHandler, RemoveTagsWsHandler removeTagsWsHandler) { + this.searchHandler = searchHandler; this.showHandler = showHandler; this.addTagsWsHandler = addTagsWsHandler; this.removeTagsWsHandler = removeTagsWsHandler; @@ -38,6 +40,15 @@ public class RulesWs implements WebService { NewController controller = context.newController("api/rules") .setDescription("Coding rules"); + controller.newAction("list") + .setDescription("List rules that match the given criteria") + .setSince("4.3") + .setHandler(searchHandler) + .newParam("s", "An optional query that will be matched against rule titles.") + .newParam("k", "An optional query that will be matched exactly agains rule keys.") + .newParam("ps", "Optional page size (default is 25).") + .newParam("p", "Optional page number (default is 0)."); + controller.newAction("show") .setDescription("Detail of rule") .setSince("4.2") diff --git a/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRuleLookupTest.java b/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRuleLookupTest.java index b1a0a4838db..6b8d5b228cf 100644 --- a/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRuleLookupTest.java +++ b/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileRuleLookupTest.java @@ -19,6 +19,8 @@ */ package org.sonar.server.qualityprofile; +import org.sonar.server.paging.Paging; + import com.github.tlrx.elasticsearch.test.EsSetup; import org.apache.commons.io.IOUtils; import org.elasticsearch.client.Requests; diff --git a/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfilesTest.java b/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfilesTest.java index 56e569d3c89..b14fa1ab1e4 100644 --- a/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfilesTest.java +++ b/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfilesTest.java @@ -20,6 +20,8 @@ package org.sonar.server.qualityprofile; +import org.sonar.server.paging.Paging; + import com.google.common.collect.Maps; import org.junit.Before; import org.junit.Test; diff --git a/sonar-server/src/test/java/org/sonar/server/rule/ws/AddTagsWsHandlerTest.java b/sonar-server/src/test/java/org/sonar/server/rule/ws/AddTagsWsHandlerTest.java index 937dc82d929..158df4e432c 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule/ws/AddTagsWsHandlerTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule/ws/AddTagsWsHandlerTest.java @@ -52,7 +52,7 @@ public class AddTagsWsHandlerTest { @Before public void setUp() throws Exception { - tester = new WsTester(new RulesWs(mock(RuleShowWsHandler.class), new AddTagsWsHandler(rules), mock(RemoveTagsWsHandler.class))); + tester = new WsTester(new RulesWs(mock(RuleSearchWsHandler.class), mock(RuleShowWsHandler.class), new AddTagsWsHandler(rules), mock(RemoveTagsWsHandler.class))); } @Test diff --git a/sonar-server/src/test/java/org/sonar/server/rule/ws/RemoveTagsWsHandlerTest.java b/sonar-server/src/test/java/org/sonar/server/rule/ws/RemoveTagsWsHandlerTest.java index 2e033536d5b..0d3f045de3d 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule/ws/RemoveTagsWsHandlerTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule/ws/RemoveTagsWsHandlerTest.java @@ -52,7 +52,7 @@ public class RemoveTagsWsHandlerTest { @Before public void setUp() throws Exception { - tester = new WsTester(new RulesWs(mock(RuleShowWsHandler.class), mock(AddTagsWsHandler.class), new RemoveTagsWsHandler(rules))); + tester = new WsTester(new RulesWs(mock(RuleSearchWsHandler.class), mock(RuleShowWsHandler.class), mock(AddTagsWsHandler.class), new RemoveTagsWsHandler(rules))); } @Test diff --git a/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleSearchWsHandlerTest.java b/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleSearchWsHandlerTest.java new file mode 100644 index 00000000000..af418c5f418 --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleSearchWsHandlerTest.java @@ -0,0 +1,102 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.rule.ws; + +import com.google.common.collect.ImmutableList; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.sonar.api.resources.Language; +import org.sonar.api.resources.Languages; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.server.ws.WsTester; +import org.sonar.server.paging.PagedResult; +import org.sonar.server.paging.PagingResult; +import org.sonar.server.rule.Rule; +import org.sonar.server.rule.RuleQuery; +import org.sonar.server.rule.Rules; +import org.sonar.server.user.MockUserSession; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class RuleSearchWsHandlerTest { + + @Mock + Rules rules; + + @Mock + Languages languages; + + Rule.Builder ruleBuilder = new Rule.Builder() + .setKey("AvoidCycle") + .setRepositoryKey("squid") + .setName("Avoid cycle") + .setDescription("Avoid cycle between packages") + .setLanguage("java"); + + WsTester tester; + + @Before + public void setUp() throws Exception { + tester = new WsTester(new RulesWs(new RuleSearchWsHandler(rules, languages), mock(RuleShowWsHandler.class), mock(AddTagsWsHandler.class), mock(RemoveTagsWsHandler.class))); + } + + @Test + public void search_rules() throws Exception { + final int pageSize = 10; + final int pageIndex = 2; + Rule rule = ruleBuilder.build(); + + when(rules.find(any(RuleQuery.class))).thenReturn( + new PagedResult(ImmutableList.of(rule), PagingResult.create(pageSize, pageIndex, 1))); + Language lang = mock(Language.class); + when(lang.getName()).thenReturn("Java"); + when(languages.get("java")).thenReturn(lang); + + MockUserSession.set(); + WsTester.TestRequest request = tester.newRequest("list").setParam("ps", "10").setParam("p", "2"); + request.execute().assertJson("{'more':false,'results':[" + + "{'key':'squid:AvoidCycle','name':'Avoid cycle','language':'Java'}" + + "]}"); + } + + @Test + public void search_rule_by_key() throws Exception { + String ruleKey = "squid:AvoidCycle"; + Rule rule = ruleBuilder.build(); + + when(rules.findByKey(RuleKey.parse(ruleKey))).thenReturn(rule); + Language lang = mock(Language.class); + when(lang.getName()).thenReturn("Java"); + when(languages.get("java")).thenReturn(lang); + + MockUserSession.set(); + WsTester.TestRequest request = tester.newRequest("list").setParam("k", ruleKey); + request.execute().assertJson("{'more':false,'results':[" + + "{'key':'squid:AvoidCycle','name':'Avoid cycle','language':'Java'}" + + "]}"); + } +} diff --git a/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleShowWsHandlerTest.java b/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleShowWsHandlerTest.java index 5a94be39387..bfb526c84f2 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleShowWsHandlerTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleShowWsHandlerTest.java @@ -69,7 +69,7 @@ public class RuleShowWsHandlerTest { @Before public void setUp() throws Exception { - tester = new WsTester(new RulesWs(new RuleShowWsHandler(rules, ruleFinder, i18n), mock(AddTagsWsHandler.class), mock(RemoveTagsWsHandler.class))); + tester = new WsTester(new RulesWs(mock(RuleSearchWsHandler.class), new RuleShowWsHandler(rules, ruleFinder, i18n), mock(AddTagsWsHandler.class), mock(RemoveTagsWsHandler.class))); } @Test diff --git a/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWsTest.java b/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWsTest.java index 9537435bab5..d41159a2ddc 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWsTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWsTest.java @@ -32,6 +32,9 @@ import static org.fest.assertions.Assertions.assertThat; @RunWith(MockitoJUnitRunner.class) public class RulesWsTest { + @Mock + RuleSearchWsHandler searchHandler; + @Mock RuleShowWsHandler showHandler; @@ -45,7 +48,7 @@ public class RulesWsTest { @Before public void setUp() { - tester = new WsTester(new RulesWs(showHandler, addTagsWsHandler, removeTagsWsHandler)); + tester = new WsTester(new RulesWs(searchHandler, showHandler, addTagsWsHandler, removeTagsWsHandler)); } @Test @@ -54,7 +57,15 @@ public class RulesWsTest { assertThat(controller).isNotNull(); assertThat(controller.path()).isEqualTo("api/rules"); assertThat(controller.description()).isNotEmpty(); - assertThat(controller.actions()).hasSize(3); + assertThat(controller.actions()).hasSize(4); + + WebService.Action list = controller.action("list"); + assertThat(list).isNotNull(); + assertThat(list.handler()).isNotNull(); + assertThat(list.since()).isEqualTo("4.3"); + assertThat(list.isPost()).isFalse(); + assertThat(list.isInternal()).isFalse(); + assertThat(list.params()).hasSize(4); WebService.Action show = controller.action("show"); assertThat(show).isNotNull(); -- 2.39.5