Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

ProjectFilterTest.java 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2018 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. package org.sonarqube.tests.project;
  21. import com.sonar.orchestrator.Orchestrator;
  22. import com.sonar.orchestrator.build.SonarScanner;
  23. import java.io.IOException;
  24. import java.util.ArrayList;
  25. import java.util.List;
  26. import org.assertj.core.groups.Tuple;
  27. import org.junit.Before;
  28. import org.junit.ClassRule;
  29. import org.junit.Rule;
  30. import org.junit.Test;
  31. import org.sonarqube.qa.util.Tester;
  32. import org.sonarqube.ws.Common;
  33. import org.sonarqube.ws.Components.Component;
  34. import org.sonarqube.ws.Components.SearchProjectsWsResponse;
  35. import org.sonarqube.ws.Organizations.Organization;
  36. import org.sonarqube.ws.client.components.SearchProjectsRequest;
  37. import org.sonarqube.ws.client.projects.CreateRequest;
  38. import static java.util.Arrays.asList;
  39. import static java.util.Collections.singletonList;
  40. import static org.assertj.core.api.Assertions.assertThat;
  41. import static org.assertj.core.groups.Tuple.tuple;
  42. import static util.ItUtils.concat;
  43. import static util.ItUtils.newProjectKey;
  44. import static util.ItUtils.projectDir;
  45. import static util.ItUtils.restoreProfile;
  46. import static util.ItUtils.sanitizeTimezones;
  47. /**
  48. * Tests WS api/components/search_projects
  49. */
  50. public class ProjectFilterTest {
  51. @ClassRule
  52. public static Orchestrator orchestrator = ProjectSuite.ORCHESTRATOR;
  53. @Rule
  54. public Tester tester = new Tester(orchestrator);
  55. private Organization organization;
  56. @Before
  57. public void setUp() {
  58. organization = tester.organizations().generate();
  59. restoreProfile(orchestrator, ProjectFilterTest.class.getResource("/projectSearch/SearchProjectsTest/with-many-rules.xml"), organization.getKey());
  60. }
  61. @Test
  62. public void filter_projects_by_measure_values() throws Exception {
  63. String projectKey = newProjectKey();
  64. analyzeProject(projectKey, "shared/xoo-sample");
  65. verifyFilterMatches(projectKey, "ncloc > 1");
  66. verifyFilterMatches(projectKey, "ncloc > 1 and duplicated_lines_density <= 100");
  67. verifyFilterDoesNotMatch("ncloc <= 1");
  68. }
  69. @Test
  70. public void find_projects_with_no_data() throws Exception {
  71. String projectKey = newProjectKey();
  72. analyzeProject(projectKey, "shared/xoo-sample");
  73. verifyFilterMatches(projectKey, "coverage = NO_DATA");
  74. verifyFilterDoesNotMatch("ncloc = NO_DATA");
  75. }
  76. @Test
  77. public void provisioned_projects_should_be_included_to_results() throws Exception {
  78. String projectKey = newProjectKey();
  79. tester.wsClient().projects().create(new CreateRequest().setProject(projectKey).setName(projectKey).setOrganization(organization.getKey()));
  80. SearchProjectsWsResponse response = searchProjects(new SearchProjectsRequest().setOrganization(organization.getKey()));
  81. assertThat(response.getComponentsList()).extracting(Component::getKey).containsOnly(projectKey);
  82. }
  83. @Test
  84. public void return_leak_period_date() throws Exception {
  85. tester.settings().setGlobalSettings("sonar.leak.period", "previous_version");
  86. // This project has a leak period
  87. String projectKey1 = newProjectKey();
  88. analyzeProject(projectKey1, "shared/xoo-sample", "sonar.projectDate", "2016-12-31");
  89. analyzeProject(projectKey1, "shared/xoo-sample");
  90. // This project has only one analysis, so no leak period
  91. String projectKey2 = newProjectKey();
  92. analyzeProject(projectKey2, "shared/xoo-sample");
  93. // This project is provisioned, so has no leak period
  94. String projectKey3 = newProjectKey();
  95. tester.wsClient().projects().create(new CreateRequest().setProject(projectKey3).setName(projectKey3).setOrganization(organization.getKey()));
  96. SearchProjectsWsResponse response = searchProjects(
  97. new SearchProjectsRequest().setF(singletonList("leakPeriodDate")).setOrganization(organization.getKey()));
  98. assertThat(response.getComponentsList()).extracting(Component::getKey, Component::hasLeakPeriodDate)
  99. .containsOnly(
  100. tuple(projectKey1, true),
  101. tuple(projectKey2, false),
  102. tuple(projectKey3, false));
  103. Component project1 = response.getComponentsList().stream().filter(component -> component.getKey().equals(projectKey1)).findFirst()
  104. .orElseThrow(() -> new IllegalStateException("Project1 is not found"));
  105. assertThat(sanitizeTimezones(project1.getLeakPeriodDate())).isEqualTo("2016-12-31T00:00:00+0000");
  106. }
  107. @Test
  108. public void filter_by_text_query() throws IOException {
  109. analyzeProject("project1", "shared/xoo-sample", "sonar.projectName", "apachee");
  110. analyzeProject("project2", "shared/xoo-sample", "sonar.projectName", "Apache");
  111. analyzeProject("project3", "shared/xoo-multi-modules-sample", "sonar.projectName", "Apache Foundation");
  112. analyzeProject("project4", "shared/xoo-multi-modules-sample", "sonar.projectName", "Windows");
  113. // Search only by text query
  114. assertThat(searchProjects("query = \"apache\"").getComponentsList()).extracting(Component::getKey).containsExactly("project2", "project3", "project1");
  115. assertThat(searchProjects("query = \"pAch\"").getComponentsList()).extracting(Component::getKey).containsExactly("project2", "project3", "project1");
  116. assertThat(searchProjects("query = \"hee\"").getComponentsList()).extracting(Component::getKey).containsExactly("project1");
  117. assertThat(searchProjects("query = \"project1\"").getComponentsList()).extracting(Component::getKey).containsExactly("project1");
  118. assertThat(searchProjects("query = \"unknown\"").getComponentsList()).isEmpty();
  119. // Search by metric criteria and text query
  120. assertThat(searchProjects(new SearchProjectsRequest().setFilter("query = \"pAch\" AND ncloc > 50")).getComponentsList())
  121. .extracting(Component::getKey).containsExactly("project3");
  122. assertThat(searchProjects(new SearchProjectsRequest().setFilter("query = \"nd\" AND ncloc > 50")).getComponentsList())
  123. .extracting(Component::getKey).containsExactly("project3", "project4");
  124. assertThat(searchProjects(new SearchProjectsRequest().setFilter("query = \"unknown\" AND ncloc > 50")).getComponentsList()).isEmpty();
  125. // Check facets
  126. assertThat(searchProjects(new SearchProjectsRequest().setFilter("query = \"apache\"").setFacets(singletonList("ncloc"))).getFacets().getFacets(0).getValuesList())
  127. .extracting(Common.FacetValue::getVal, Common.FacetValue::getCount)
  128. .containsOnly(tuple("*-1000.0", 3L), tuple("1000.0-10000.0", 0L), tuple("10000.0-100000.0", 0L), tuple("100000.0-500000.0", 0L), tuple("500000.0-*", 0L));
  129. assertThat(searchProjects(new SearchProjectsRequest().setFilter("query = \"unknown\"").setFacets(singletonList("ncloc"))).getFacets().getFacets(0)
  130. .getValuesList()).extracting(Common.FacetValue::getVal, Common.FacetValue::getCount)
  131. .containsOnly(tuple("*-1000.0", 0L), tuple("1000.0-10000.0", 0L), tuple("10000.0-100000.0", 0L), tuple("100000.0-500000.0", 0L), tuple("500000.0-*", 0L));
  132. }
  133. @Test
  134. public void should_return_facets() throws Exception {
  135. analyzeProject(newProjectKey(), "shared/xoo-sample");
  136. analyzeProject(newProjectKey(), "shared/xoo-multi-modules-sample");
  137. SearchProjectsWsResponse response = searchProjects(new SearchProjectsRequest().setOrganization(organization.getKey()).setFacets(asList(
  138. "alert_status",
  139. "coverage",
  140. "duplicated_lines_density",
  141. "languages",
  142. "ncloc",
  143. "reliability_rating",
  144. "security_rating",
  145. "sqale_rating",
  146. "tags")));
  147. checkFacet(response, "alert_status",
  148. tuple("OK", 2L),
  149. tuple("WARN", 0L),
  150. tuple("ERROR", 0L));
  151. checkFacet(response, "coverage",
  152. tuple("NO_DATA", 2L),
  153. tuple("*-30.0", 0L),
  154. tuple("30.0-50.0", 0L),
  155. tuple("50.0-70.0", 0L),
  156. tuple("70.0-80.0", 0L),
  157. tuple("80.0-*", 0L));
  158. checkFacet(response, "duplicated_lines_density",
  159. tuple("NO_DATA", 0L),
  160. tuple("*-3.0", 2L),
  161. tuple("3.0-5.0", 0L),
  162. tuple("5.0-10.0", 0L),
  163. tuple("10.0-20.0", 0L),
  164. tuple("20.0-*", 0L));
  165. checkFacet(response, "languages",
  166. tuple("xoo", 2L));
  167. checkFacet(response, "ncloc",
  168. tuple("*-1000.0", 2L),
  169. tuple("1000.0-10000.0", 0L),
  170. tuple("10000.0-100000.0", 0L),
  171. tuple("100000.0-500000.0", 0L),
  172. tuple("500000.0-*", 0L));
  173. checkFacet(response, "reliability_rating",
  174. tuple("1", 2L),
  175. tuple("2", 0L),
  176. tuple("3", 0L),
  177. tuple("4", 0L),
  178. tuple("5", 0L));
  179. checkFacet(response, "security_rating",
  180. tuple("1", 2L),
  181. tuple("2", 0L),
  182. tuple("3", 0L),
  183. tuple("4", 0L),
  184. tuple("5", 0L));
  185. checkFacet(response, "sqale_rating",
  186. tuple("1", 0L),
  187. tuple("2", 0L),
  188. tuple("3", 0L),
  189. tuple("4", 2L),
  190. tuple("5", 0L));
  191. checkFacet(response, "tags");
  192. }
  193. @Test
  194. public void should_return_facets_on_leak() throws Exception {
  195. tester.settings().setGlobalSettings("sonar.leak.period", "previous_version");
  196. // This project has no duplication on new code
  197. String projectKey1 = newProjectKey();
  198. analyzeProject(projectKey1, "shared/xoo-sample", "sonar.projectDate", "2016-12-31");
  199. analyzeProject(projectKey1, "shared/xoo-sample");
  200. // This project has 0% duplication on new code
  201. String projectKey2 = newProjectKey();
  202. analyzeProject(projectKey2, "projectSearch/xoo-history-v1", "sonar.projectDate", "2016-12-31");
  203. analyzeProject(projectKey2, "projectSearch/xoo-history-v2");
  204. SearchProjectsWsResponse response = searchProjects(new SearchProjectsRequest().setOrganization(organization.getKey()).setFacets(asList(
  205. "new_reliability_rating", "new_security_rating", "new_maintainability_rating", "new_coverage", "new_duplicated_lines_density", "new_lines")));
  206. checkFacet(response, "new_reliability_rating",
  207. tuple("1", 2L),
  208. tuple("2", 0L),
  209. tuple("3", 0L),
  210. tuple("4", 0L),
  211. tuple("5", 0L));
  212. checkFacet(response, "new_security_rating",
  213. tuple("1", 2L),
  214. tuple("2", 0L),
  215. tuple("3", 0L),
  216. tuple("4", 0L),
  217. tuple("5", 0L));
  218. checkFacet(response, "new_maintainability_rating",
  219. tuple("1", 2L),
  220. tuple("2", 0L),
  221. tuple("3", 0L),
  222. tuple("4", 0L),
  223. tuple("5", 0L));
  224. checkFacet(response, "new_coverage",
  225. tuple("NO_DATA", 2L),
  226. tuple("*-30.0", 0L),
  227. tuple("30.0-50.0", 0L),
  228. tuple("50.0-70.0", 0L),
  229. tuple("70.0-80.0", 0L),
  230. tuple("80.0-*", 0L));
  231. checkFacet(response, "new_duplicated_lines_density",
  232. tuple("NO_DATA", 1L),
  233. tuple("*-3.0", 1L),
  234. tuple("3.0-5.0", 0L),
  235. tuple("5.0-10.0", 0L),
  236. tuple("10.0-20.0", 0L),
  237. tuple("20.0-*", 0L));
  238. checkFacet(response, "new_lines",
  239. tuple("*-1000.0", 2L),
  240. tuple("1000.0-10000.0", 0L),
  241. tuple("10000.0-100000.0", 0L),
  242. tuple("100000.0-500000.0", 0L),
  243. tuple("500000.0-*", 0L));
  244. }
  245. private void checkFacet(SearchProjectsWsResponse response, String facetKey, Tuple... values) {
  246. Common.Facet facet = response.getFacets().getFacetsList().stream().filter(f -> f.getProperty().equals(facetKey)).findAny().get();
  247. assertThat(facet.getValuesList()).extracting(Common.FacetValue::getVal, Common.FacetValue::getCount).containsExactlyInAnyOrder(values);
  248. }
  249. private void analyzeProject(String projectKey, String relativePath, String... properties) {
  250. List<String> keyValueProperties = new ArrayList<>(asList(
  251. "sonar.projectKey", projectKey,
  252. "sonar.organization", organization.getKey(),
  253. "sonar.profile", "with-many-rules",
  254. "sonar.login", "admin", "sonar.password", "admin",
  255. "sonar.scm.disabled", "false"));
  256. orchestrator.executeBuild(SonarScanner.create(projectDir(relativePath), concat(keyValueProperties.toArray(new String[0]), properties)));
  257. }
  258. private SearchProjectsWsResponse searchProjects(String filter) throws IOException {
  259. return searchProjects(new SearchProjectsRequest().setOrganization(organization.getKey()).setFilter(filter));
  260. }
  261. private SearchProjectsWsResponse searchProjects(SearchProjectsRequest request) {
  262. return tester.wsClient().components().searchProjects(request);
  263. }
  264. private void verifyFilterMatches(String projectKey, String filter) throws IOException {
  265. assertThat(searchProjects(filter).getComponentsList()).extracting(Component::getKey).containsOnly(projectKey);
  266. }
  267. private void verifyFilterDoesNotMatch(String filter) throws IOException {
  268. assertThat(searchProjects(filter).getComponentsCount()).isZero();
  269. }
  270. }