You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SearchActionTest.java 62KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2021 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.sonar.server.issue.ws;
  21. import com.google.common.collect.Sets;
  22. import com.google.gson.JsonElement;
  23. import com.google.gson.JsonParser;
  24. import java.time.Clock;
  25. import java.util.Arrays;
  26. import java.util.Collections;
  27. import java.util.List;
  28. import java.util.Random;
  29. import java.util.function.Consumer;
  30. import java.util.stream.Collectors;
  31. import java.util.stream.IntStream;
  32. import java.util.stream.Stream;
  33. import org.junit.Before;
  34. import org.junit.Rule;
  35. import org.junit.Test;
  36. import org.junit.rules.ExpectedException;
  37. import org.sonar.api.resources.Languages;
  38. import org.sonar.api.rule.RuleStatus;
  39. import org.sonar.api.rules.RuleType;
  40. import org.sonar.api.server.ws.WebService;
  41. import org.sonar.api.utils.Durations;
  42. import org.sonar.api.utils.System2;
  43. import org.sonar.core.util.Uuids;
  44. import org.sonar.db.DbClient;
  45. import org.sonar.db.DbSession;
  46. import org.sonar.db.DbTester;
  47. import org.sonar.db.component.BranchType;
  48. import org.sonar.db.component.ComponentDto;
  49. import org.sonar.db.component.ComponentTesting;
  50. import org.sonar.db.component.SnapshotDto;
  51. import org.sonar.db.issue.IssueChangeDto;
  52. import org.sonar.db.issue.IssueDto;
  53. import org.sonar.db.permission.GroupPermissionDto;
  54. import org.sonar.db.protobuf.DbCommons;
  55. import org.sonar.db.protobuf.DbIssues;
  56. import org.sonar.db.rule.RuleDefinitionDto;
  57. import org.sonar.db.rule.RuleDto;
  58. import org.sonar.db.rule.RuleMetadataDto;
  59. import org.sonar.db.rule.RuleTesting;
  60. import org.sonar.db.user.UserDto;
  61. import org.sonar.server.es.EsTester;
  62. import org.sonar.server.es.SearchOptions;
  63. import org.sonar.server.issue.AvatarResolverImpl;
  64. import org.sonar.server.issue.IssueFieldsSetter;
  65. import org.sonar.server.issue.TextRangeResponseFormatter;
  66. import org.sonar.server.issue.TransitionService;
  67. import org.sonar.server.issue.index.IssueIndex;
  68. import org.sonar.server.issue.index.IssueIndexSyncProgressChecker;
  69. import org.sonar.server.issue.index.IssueIndexer;
  70. import org.sonar.server.issue.index.IssueIteratorFactory;
  71. import org.sonar.server.issue.index.IssueQuery;
  72. import org.sonar.server.issue.index.IssueQueryFactory;
  73. import org.sonar.server.issue.workflow.FunctionExecutor;
  74. import org.sonar.server.issue.workflow.IssueWorkflow;
  75. import org.sonar.server.permission.index.PermissionIndexer;
  76. import org.sonar.server.permission.index.WebAuthorizationTypeSupport;
  77. import org.sonar.server.tester.UserSessionRule;
  78. import org.sonar.server.ws.TestRequest;
  79. import org.sonar.server.ws.TestResponse;
  80. import org.sonar.server.ws.WsActionTester;
  81. import org.sonarqube.ws.Common;
  82. import org.sonarqube.ws.Common.Severity;
  83. import org.sonarqube.ws.Issues.Issue;
  84. import org.sonarqube.ws.Issues.SearchWsResponse;
  85. import static java.util.Arrays.asList;
  86. import static java.util.Collections.singletonList;
  87. import static org.assertj.core.api.Assertions.assertThat;
  88. import static org.assertj.core.api.Assertions.assertThatThrownBy;
  89. import static org.assertj.core.groups.Tuple.tuple;
  90. import static org.junit.rules.ExpectedException.none;
  91. import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
  92. import static org.sonar.api.issue.Issue.STATUS_RESOLVED;
  93. import static org.sonar.api.resources.Qualifiers.UNIT_TEST_FILE;
  94. import static org.sonar.api.rules.RuleType.CODE_SMELL;
  95. import static org.sonar.api.server.ws.WebService.Param.FACETS;
  96. import static org.sonar.api.utils.DateUtils.formatDateTime;
  97. import static org.sonar.api.utils.DateUtils.parseDate;
  98. import static org.sonar.api.utils.DateUtils.parseDateTime;
  99. import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
  100. import static org.sonar.db.component.ComponentDto.PULL_REQUEST_SEPARATOR;
  101. import static org.sonar.db.component.ComponentTesting.newFileDto;
  102. import static org.sonar.db.issue.IssueTesting.newDto;
  103. import static org.sonar.server.tester.UserSessionRule.standalone;
  104. import static org.sonarqube.ws.Common.RuleType.BUG;
  105. import static org.sonarqube.ws.Common.RuleType.SECURITY_HOTSPOT_VALUE;
  106. import static org.sonarqube.ws.Common.RuleType.VULNERABILITY;
  107. import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_BRANCH;
  108. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ADDITIONAL_FIELDS;
  109. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ASSIGNEES;
  110. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_KEYS;
  111. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CREATED_AFTER;
  112. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_HIDE_COMMENTS;
  113. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PULL_REQUEST;
  114. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_RULES;
  115. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SINCE_LEAK_PERIOD;
  116. public class SearchActionTest {
  117. @Rule
  118. public UserSessionRule userSession = standalone();
  119. @Rule
  120. public DbTester db = DbTester.create();
  121. @Rule
  122. public EsTester es = EsTester.create();
  123. @Rule
  124. public ExpectedException expectedException = none();
  125. private final DbClient dbClient = db.getDbClient();
  126. private final DbSession session = db.getSession();
  127. private final IssueIndex issueIndex = new IssueIndex(es.client(), System2.INSTANCE, userSession, new WebAuthorizationTypeSupport(userSession));
  128. private final IssueIndexer issueIndexer = new IssueIndexer(es.client(), dbClient, new IssueIteratorFactory(dbClient), null);
  129. private final IssueQueryFactory issueQueryFactory = new IssueQueryFactory(dbClient, Clock.systemUTC(), userSession);
  130. private final IssueFieldsSetter issueFieldsSetter = new IssueFieldsSetter();
  131. private final IssueWorkflow issueWorkflow = new IssueWorkflow(new FunctionExecutor(issueFieldsSetter), issueFieldsSetter);
  132. private final SearchResponseLoader searchResponseLoader = new SearchResponseLoader(userSession, dbClient, new TransitionService(userSession, issueWorkflow));
  133. private final Languages languages = new Languages();
  134. private final UserResponseFormatter userFormatter = new UserResponseFormatter(new AvatarResolverImpl());
  135. private final SearchResponseFormat searchResponseFormat = new SearchResponseFormat(new Durations(), languages, new TextRangeResponseFormatter(), userFormatter);
  136. private final IssueIndexSyncProgressChecker issueIndexSyncProgressChecker = new IssueIndexSyncProgressChecker(dbClient);
  137. private final WsActionTester ws = new WsActionTester(
  138. new SearchAction(userSession, issueIndex, issueQueryFactory, issueIndexSyncProgressChecker, searchResponseLoader, searchResponseFormat, System2.INSTANCE, dbClient));
  139. private final PermissionIndexer permissionIndexer = new PermissionIndexer(dbClient, es.client(), issueIndexer);
  140. @Before
  141. public void setUp() {
  142. issueWorkflow.start();
  143. }
  144. @Test
  145. public void response_contains_all_fields_except_additional_fields() {
  146. UserDto user = db.users().insertUser();
  147. userSession.logIn(user);
  148. ComponentDto project = db.components().insertPublicProject();
  149. indexPermissions();
  150. ComponentDto file = db.components().insertComponent(newFileDto(project));
  151. UserDto simon = db.users().insertUser();
  152. RuleDefinitionDto rule = newIssueRule().getDefinition();
  153. IssueDto issue = db.issues().insertIssue(rule, project, file, i -> i
  154. .setEffort(10L)
  155. .setLine(42)
  156. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  157. .setMessage("the message")
  158. .setStatus(STATUS_RESOLVED)
  159. .setResolution(RESOLUTION_FIXED)
  160. .setSeverity("MAJOR")
  161. .setType(CODE_SMELL)
  162. .setAuthorLogin("John")
  163. .setAssigneeUuid(simon.getUuid())
  164. .setTags(asList("bug", "owasp"))
  165. .setIssueCreationDate(parseDate("2014-09-03"))
  166. .setIssueUpdateDate(parseDate("2017-12-04")));
  167. indexIssues();
  168. SearchWsResponse response = ws.newRequest()
  169. .executeProtobuf(SearchWsResponse.class);
  170. assertThat(response.getIssuesList())
  171. .extracting(
  172. Issue::getKey, Issue::getRule, Issue::getSeverity, Issue::getComponent, Issue::getResolution, Issue::getStatus, Issue::getMessage, Issue::getEffort,
  173. Issue::getAssignee, Issue::getAuthor, Issue::getLine, Issue::getHash, Issue::getTagsList, Issue::getCreationDate, Issue::getUpdateDate)
  174. .containsExactlyInAnyOrder(
  175. tuple(issue.getKey(), rule.getKey().toString(), Severity.MAJOR, file.getKey(), RESOLUTION_FIXED, STATUS_RESOLVED, "the message", "10min",
  176. simon.getLogin(), "John", 42, "a227e508d6646b55a086ee11d63b21e9", asList("bug", "owasp"), formatDateTime(issue.getIssueCreationDate()),
  177. formatDateTime(issue.getIssueUpdateDate())));
  178. }
  179. @Test
  180. public void issue_on_external_rule() {
  181. ComponentDto project = db.components().insertPublicProject();
  182. indexPermissions();
  183. ComponentDto file = db.components().insertComponent(newFileDto(project));
  184. RuleDefinitionDto rule = db.rules().insertIssueRule(RuleTesting.EXTERNAL_XOO, r -> r.setIsExternal(true).setLanguage("xoo"));
  185. IssueDto issue = db.issues().insertIssue(rule, project, file);
  186. indexIssues();
  187. SearchWsResponse response = ws.newRequest()
  188. .executeProtobuf(SearchWsResponse.class);
  189. assertThat(response.getIssuesList())
  190. .extracting(Issue::getKey, Issue::getRule, Issue::getExternalRuleEngine)
  191. .containsExactlyInAnyOrder(tuple(issue.getKey(), rule.getKey().toString(), "xoo"));
  192. }
  193. @Test
  194. public void issue_on_external_adhoc_rule_without_metadata() {
  195. ComponentDto project = db.components().insertPublicProject();
  196. indexPermissions();
  197. ComponentDto file = db.components().insertComponent(newFileDto(project));
  198. RuleDefinitionDto rule = db.rules().insertIssueRule(RuleTesting.EXTERNAL_XOO, r -> r.setIsExternal(true).setLanguage("xoo").setIsAdHoc(true));
  199. IssueDto issue = db.issues().insertIssue(rule, project, file);
  200. indexIssues();
  201. SearchWsResponse response = ws.newRequest()
  202. .executeProtobuf(SearchWsResponse.class);
  203. assertThat(response.getIssuesList())
  204. .extracting(Issue::getKey, Issue::getRule, Issue::getExternalRuleEngine)
  205. .containsExactlyInAnyOrder(tuple(issue.getKey(), rule.getKey().toString(), "xoo"));
  206. }
  207. @Test
  208. public void issue_on_external_adhoc_rule_with_metadata() {
  209. ComponentDto project = db.components().insertPublicProject();
  210. indexPermissions();
  211. ComponentDto file = db.components().insertComponent(newFileDto(project));
  212. RuleDefinitionDto rule = db.rules().insertIssueRule(RuleTesting.EXTERNAL_XOO, r -> r.setIsExternal(true).setLanguage("xoo").setIsAdHoc(true));
  213. RuleMetadataDto ruleMetadata = db.rules().insertOrUpdateMetadata(rule, m -> m.setAdHocName("different_rule_name"));
  214. IssueDto issue = db.issues().insertIssue(rule, project, file);
  215. indexIssues();
  216. SearchWsResponse response = ws.newRequest()
  217. .setParam("additionalFields", "rules")
  218. .executeProtobuf(SearchWsResponse.class);
  219. assertThat(response.getIssuesList())
  220. .extracting(Issue::getKey, Issue::getRule, Issue::getExternalRuleEngine)
  221. .containsExactlyInAnyOrder(tuple(issue.getKey(), rule.getKey().toString(), "xoo"));
  222. assertThat(response.getRules().getRulesList())
  223. .extracting(Common.Rule::getKey, Common.Rule::getName)
  224. .containsExactlyInAnyOrder(tuple(rule.getKey().toString(), ruleMetadata.getAdHocName()));
  225. }
  226. @Test
  227. public void issue_with_cross_file_locations() {
  228. ComponentDto project = db.components().insertPublicProject();
  229. indexPermissions();
  230. ComponentDto file = db.components().insertComponent(newFileDto(project));
  231. ComponentDto anotherFile = db.components().insertComponent(newFileDto(project));
  232. DbIssues.Locations.Builder locations = DbIssues.Locations.newBuilder().addFlow(DbIssues.Flow.newBuilder().addAllLocation(Arrays.asList(
  233. DbIssues.Location.newBuilder()
  234. .setComponentId(file.uuid())
  235. .setMsg("FLOW MESSAGE")
  236. .setTextRange(DbCommons.TextRange.newBuilder()
  237. .setStartLine(1)
  238. .setEndLine(1)
  239. .setStartOffset(0)
  240. .setEndOffset(12)
  241. .build())
  242. .build(),
  243. DbIssues.Location.newBuilder()
  244. .setComponentId(anotherFile.uuid())
  245. .setMsg("ANOTHER FLOW MESSAGE")
  246. .setTextRange(DbCommons.TextRange.newBuilder()
  247. .setStartLine(1)
  248. .setEndLine(1)
  249. .setStartOffset(0)
  250. .setEndOffset(12)
  251. .build())
  252. .build(),
  253. DbIssues.Location.newBuilder()
  254. // .setComponentId(no component id set)
  255. .setMsg("FLOW MESSAGE WITHOUT FILE UUID")
  256. .setTextRange(DbCommons.TextRange.newBuilder()
  257. .setStartLine(1)
  258. .setEndLine(1)
  259. .setStartOffset(0)
  260. .setEndOffset(12)
  261. .build())
  262. .build())));
  263. RuleDefinitionDto rule = newIssueRule().getDefinition();
  264. db.issues().insertIssue(rule, project, file, i -> i.setLocations(locations.build()));
  265. indexIssues();
  266. SearchWsResponse result = ws.newRequest().executeProtobuf(SearchWsResponse.class);
  267. assertThat(result.getIssuesCount()).isEqualTo(1);
  268. assertThat(result.getIssues(0).getFlows(0).getLocationsList()).extracting(Common.Location::getComponent, Common.Location::getMsg)
  269. .containsExactlyInAnyOrder(
  270. tuple(file.getKey(), "FLOW MESSAGE"),
  271. tuple(anotherFile.getKey(), "ANOTHER FLOW MESSAGE"),
  272. tuple(file.getKey(), "FLOW MESSAGE WITHOUT FILE UUID"));
  273. }
  274. @Test
  275. public void issue_with_comments() {
  276. UserDto john = db.users().insertUser(u -> u.setLogin("john").setName("John"));
  277. UserDto fabrice = db.users().insertUser(u -> u.setLogin("fabrice").setName("Fabrice").setEmail("fabrice@email.com"));
  278. ComponentDto project = db.components().insertPublicProject();
  279. indexPermissions();
  280. ComponentDto file = db.components().insertComponent(newFileDto(project));
  281. RuleDefinitionDto rule = newIssueRule().getDefinition();
  282. IssueDto issue = db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
  283. dbClient.issueChangeDao().insert(session,
  284. new IssueChangeDto()
  285. .setUuid(Uuids.createFast())
  286. .setIssueKey(issue.getKey())
  287. .setKey("COMMENT-ABCD")
  288. .setChangeData("*My comment*")
  289. .setChangeType(IssueChangeDto.TYPE_COMMENT)
  290. .setUserUuid(john.getUuid())
  291. .setProjectUuid(project.projectUuid())
  292. .setIssueChangeCreationDate(parseDateTime("2014-09-09T12:00:00+0000").getTime()));
  293. dbClient.issueChangeDao().insert(session,
  294. new IssueChangeDto()
  295. .setUuid(Uuids.createFast())
  296. .setIssueKey(issue.getKey())
  297. .setKey("COMMENT-ABCE")
  298. .setChangeData("Another comment")
  299. .setChangeType(IssueChangeDto.TYPE_COMMENT)
  300. .setUserUuid(fabrice.getUuid())
  301. .setProjectUuid(project.projectUuid())
  302. .setIssueChangeCreationDate(parseDateTime("2014-09-10T12:00:00+0000").getTime()));
  303. session.commit();
  304. indexIssues();
  305. userSession.logIn(john);
  306. ws.newRequest()
  307. .setParam("additionalFields", "comments,users")
  308. .execute()
  309. .assertJson(this.getClass(), "issue_with_comments.json");
  310. }
  311. @Test
  312. public void issue_with_comment_hidden() {
  313. UserDto john = db.users().insertUser(u -> u.setLogin("john").setName("John").setEmail("john@email.com"));
  314. UserDto fabrice = db.users().insertUser(u -> u.setLogin("fabrice").setName("Fabrice").setEmail("fabrice@email.com"));
  315. ComponentDto project = db.components().insertPublicProject();
  316. indexPermissions();
  317. ComponentDto file = db.components().insertComponent(newFileDto(project));
  318. RuleDefinitionDto rule = newIssueRule().getDefinition();
  319. IssueDto issue = db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
  320. dbClient.issueChangeDao().insert(session,
  321. new IssueChangeDto()
  322. .setUuid(Uuids.createFast())
  323. .setIssueKey(issue.getKey())
  324. .setKey("COMMENT-ABCD")
  325. .setChangeData("*My comment*")
  326. .setChangeType(IssueChangeDto.TYPE_COMMENT)
  327. .setUserUuid(john.getUuid())
  328. .setProjectUuid(project.projectUuid())
  329. .setCreatedAt(parseDateTime("2014-09-09T12:00:00+0000").getTime()));
  330. dbClient.issueChangeDao().insert(session,
  331. new IssueChangeDto()
  332. .setUuid(Uuids.createFast())
  333. .setIssueKey(issue.getKey())
  334. .setKey("COMMENT-ABCE")
  335. .setChangeData("Another comment")
  336. .setChangeType(IssueChangeDto.TYPE_COMMENT)
  337. .setUserUuid(fabrice.getUuid())
  338. .setProjectUuid(project.projectUuid())
  339. .setCreatedAt(parseDateTime("2014-09-10T19:10:03+0000").getTime()));
  340. session.commit();
  341. indexIssues();
  342. userSession.logIn(john);
  343. SearchWsResponse response = ws.newRequest()
  344. .setParam(PARAM_HIDE_COMMENTS, "true")
  345. .executeProtobuf(SearchWsResponse.class);
  346. assertThat(response.getIssuesList())
  347. .extracting(Issue::getKey, i -> i.getComments().getCommentsList())
  348. .containsExactlyInAnyOrder(tuple(issue.getKey(), Collections.emptyList()));
  349. }
  350. @Test
  351. public void load_additional_fields() {
  352. UserDto simon = db.users().insertUser(u -> u.setLogin("simon").setName("Simon").setEmail("simon@email.com"));
  353. ComponentDto project = db.components().insertPublicProject();
  354. indexPermissions();
  355. ComponentDto file = db.components().insertComponent(newFileDto(project));
  356. RuleDefinitionDto rule = newIssueRule().getDefinition();
  357. db.issues().insertIssue(rule, project, file, i -> i.setAssigneeUuid(simon.getUuid()).setType(CODE_SMELL));
  358. indexIssues();
  359. userSession.logIn("john");
  360. ws.newRequest()
  361. .setParam("additionalFields", "_all").execute()
  362. .assertJson(this.getClass(), "load_additional_fields.json");
  363. }
  364. @Test
  365. public void load_additional_fields_with_issue_admin_permission() {
  366. UserDto simon = db.users().insertUser(u -> u.setLogin("simon").setName("Simon").setEmail("simon@email.com"));
  367. UserDto fabrice = db.users().insertUser(u -> u.setLogin("fabrice").setName("Fabrice").setEmail("fabrice@email.com"));
  368. ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto("PROJECT_ID").setDbKey("PROJECT_KEY").setLanguage("java"));
  369. grantPermissionToAnyone(project, ISSUE_ADMIN);
  370. indexPermissions();
  371. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY").setLanguage("js"));
  372. IssueDto issue = newDto(newIssueRule(), file, project)
  373. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
  374. .setAuthorLogin(fabrice.getLogin())
  375. .setAssigneeUuid(simon.getUuid())
  376. .setType(CODE_SMELL);
  377. dbClient.issueDao().insert(session, issue);
  378. session.commit();
  379. indexIssues();
  380. userSession.logIn("john")
  381. .addProjectPermission(ISSUE_ADMIN, project); // granted by Anyone
  382. ws.newRequest()
  383. .setParam("additionalFields", "_all").execute()
  384. .assertJson(this.getClass(), "load_additional_fields_with_issue_admin_permission.json");
  385. }
  386. @Test
  387. public void search_by_rule_key() {
  388. RuleDto rule = newIssueRule();
  389. ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto("PROJECT_ID").setDbKey("PROJECT_KEY").setLanguage("java"));
  390. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY").setLanguage("java"));
  391. db.issues().insertIssue(rule.getDefinition(), project, file);
  392. session.commit();
  393. indexIssues();
  394. userSession.logIn("john")
  395. .addProjectPermission(ISSUE_ADMIN, project); // granted by Anyone
  396. indexPermissions();
  397. TestResponse execute = ws.newRequest()
  398. .setParam(PARAM_RULES, rule.getKey().toString())
  399. .setParam("additionalFields", "_all")
  400. .execute();
  401. execute.assertJson(this.getClass(), "result_for_rule_search.json");
  402. }
  403. @Test
  404. public void search_by_non_existing_rule_key() {
  405. RuleDto rule = newIssueRule();
  406. ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto("PROJECT_ID").setDbKey("PROJECT_KEY").setLanguage("java"));
  407. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY").setLanguage("java"));
  408. db.issues().insertIssue(rule.getDefinition(), project, file);
  409. session.commit();
  410. indexIssues();
  411. userSession.logIn("john")
  412. .addProjectPermission(ISSUE_ADMIN, project); // granted by Anyone
  413. indexPermissions();
  414. TestResponse execute = ws.newRequest()
  415. .setParam(PARAM_RULES, "nonexisting:rulekey")
  416. .setParam("additionalFields", "_all")
  417. .execute();
  418. execute.assertJson(this.getClass(), "no_issue.json");
  419. }
  420. @Test
  421. public void issue_on_removed_file() {
  422. RuleDto rule = newIssueRule();
  423. ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto("PROJECT_ID").setDbKey("PROJECT_KEY"));
  424. indexPermissions();
  425. ComponentDto removedFile = db.components().insertComponent(newFileDto(project, null).setUuid("REMOVED_FILE_ID")
  426. .setDbKey("REMOVED_FILE_KEY")
  427. .setEnabled(false));
  428. IssueDto issue = newDto(rule, removedFile, project)
  429. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
  430. .setComponent(removedFile)
  431. .setStatus("OPEN").setResolution("OPEN")
  432. .setSeverity("MAJOR")
  433. .setIssueCreationDate(parseDateTime("2014-09-04T00:00:00+0100"))
  434. .setIssueUpdateDate(parseDateTime("2017-12-04T00:00:00+0100"));
  435. dbClient.issueDao().insert(session, issue);
  436. session.commit();
  437. indexIssues();
  438. ws.newRequest()
  439. .execute()
  440. .assertJson(this.getClass(), "issue_on_removed_file.json");
  441. }
  442. @Test
  443. public void apply_paging_with_one_component() {
  444. RuleDto rule = newIssueRule();
  445. ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto("PROJECT_ID").setDbKey("PROJECT_KEY"));
  446. indexPermissions();
  447. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY"));
  448. for (int i = 0; i < SearchOptions.MAX_PAGE_SIZE + 1; i++) {
  449. IssueDto issue = newDto(rule, file, project).setAssigneeUuid(null);
  450. dbClient.issueDao().insert(session, issue);
  451. }
  452. session.commit();
  453. indexIssues();
  454. ws.newRequest().setParam(PARAM_COMPONENT_KEYS, file.getKey()).execute()
  455. .assertJson(this.getClass(), "apply_paging_with_one_component.json");
  456. }
  457. @Test
  458. public void components_contains_sub_projects() {
  459. ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto("PROJECT_ID").setDbKey("ProjectHavingModule"));
  460. indexPermissions();
  461. ComponentDto module = db.components().insertComponent(ComponentTesting.newModuleDto(project).setDbKey("ModuleHavingFile"));
  462. ComponentDto file = db.components().insertComponent(newFileDto(module, null, "BCDE").setDbKey("FileLinkedToModule"));
  463. IssueDto issue = newDto(newIssueRule(), file, project);
  464. dbClient.issueDao().insert(session, issue);
  465. session.commit();
  466. indexIssues();
  467. ws.newRequest().setParam(PARAM_ADDITIONAL_FIELDS, "_all").execute()
  468. .assertJson(this.getClass(), "components_contains_sub_projects.json");
  469. }
  470. @Test
  471. public void filter_by_assigned_to_me() {
  472. UserDto john = db.users().insertUser(u -> u.setLogin("john").setName("John").setEmail("john@email.com"));
  473. UserDto alice = db.users().insertUser(u -> u.setLogin("alice").setName("Alice").setEmail("alice@email.com"));
  474. ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto("PROJECT_ID").setDbKey("PROJECT_KEY"));
  475. indexPermissions();
  476. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY"));
  477. RuleDto rule = newIssueRule();
  478. IssueDto issue1 = newDto(rule, file, project)
  479. .setIssueCreationDate(parseDate("2014-09-04"))
  480. .setIssueUpdateDate(parseDate("2017-12-04"))
  481. .setEffort(10L)
  482. .setStatus("OPEN")
  483. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
  484. .setSeverity("MAJOR")
  485. .setAssigneeUuid(john.getUuid());
  486. IssueDto issue2 = newDto(rule, file, project)
  487. .setIssueCreationDate(parseDate("2014-09-04"))
  488. .setIssueUpdateDate(parseDate("2017-12-04"))
  489. .setEffort(10L)
  490. .setStatus("OPEN")
  491. .setKee("7b112bd4-b650-4037-80bc-82fd47d4eac2")
  492. .setSeverity("MAJOR")
  493. .setAssigneeUuid(alice.getUuid());
  494. IssueDto issue3 = newDto(rule, file, project)
  495. .setIssueCreationDate(parseDate("2014-09-04"))
  496. .setIssueUpdateDate(parseDate("2017-12-04"))
  497. .setEffort(10L)
  498. .setStatus("OPEN")
  499. .setKee("82fd47d4-4037-b650-80bc-7b112bd4eac2")
  500. .setSeverity("MAJOR")
  501. .setAssigneeUuid(null);
  502. dbClient.issueDao().insert(session, issue1, issue2, issue3);
  503. session.commit();
  504. indexIssues();
  505. userSession.logIn(john);
  506. ws.newRequest()
  507. .setParam("resolved", "false")
  508. .setParam("assignees", "__me__")
  509. .setParam(FACETS, "assignees,assigned_to_me")
  510. .execute()
  511. .assertJson(this.getClass(), "filter_by_assigned_to_me.json");
  512. }
  513. @Test
  514. public void filter_by_leak_period() {
  515. UserDto john = db.users().insertUser(u -> u.setLogin("john").setName("John").setEmail("john@email.com"));
  516. UserDto alice = db.users().insertUser(u -> u.setLogin("alice").setName("Alice").setEmail("alice@email.com"));
  517. ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto("PROJECT_ID").setDbKey("PROJECT_KEY"));
  518. SnapshotDto snapshotDto = db.components().insertSnapshot(project, s -> s.setLast(true).setPeriodDate(parseDateTime("2014-09-05T00:00:00+0100").getTime()));
  519. indexPermissions();
  520. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY"));
  521. RuleDto rule = newIssueRule();
  522. IssueDto issue1 = newDto(rule, file, project)
  523. .setIssueCreationDate(parseDateTime("2014-09-04T00:00:00+0100"))
  524. .setIssueUpdateDate(parseDateTime("2017-12-04T00:00:00+0100"))
  525. .setEffort(10L)
  526. .setStatus("OPEN")
  527. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
  528. .setSeverity("MAJOR")
  529. .setAssigneeUuid(john.getUuid());
  530. IssueDto issue2 = newDto(rule, file, project)
  531. .setIssueCreationDate(parseDateTime("2014-09-06T00:00:00+0100"))
  532. .setIssueUpdateDate(parseDateTime("2017-12-04T00:00:00+0100"))
  533. .setEffort(10L)
  534. .setStatus("OPEN")
  535. .setKee("7b112bd4-b650-4037-80bc-82fd47d4eac2")
  536. .setSeverity("MAJOR")
  537. .setAssigneeUuid(alice.getUuid());
  538. dbClient.issueDao().insert(session, issue1, issue2);
  539. session.commit();
  540. indexIssues();
  541. userSession.logIn(john);
  542. ws.newRequest()
  543. .setParam(PARAM_SINCE_LEAK_PERIOD, "true")
  544. .setParam(PARAM_COMPONENT_KEYS, "PROJECT_KEY")
  545. .execute()
  546. .assertJson(this.getClass(), "filter_by_leak_period.json");
  547. }
  548. @Test
  549. public void filter_by_leak_period_without_a_period() {
  550. UserDto john = db.users().insertUser(u -> u.setLogin("john").setName("John").setEmail("john@email.com"));
  551. UserDto alice = db.users().insertUser(u -> u.setLogin("alice").setName("Alice").setEmail("alice@email.com"));
  552. ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto("PROJECT_ID").setDbKey("PROJECT_KEY"));
  553. SnapshotDto snapshotDto = db.components().insertSnapshot(project);
  554. indexPermissions();
  555. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY"));
  556. RuleDto rule = newIssueRule();
  557. IssueDto issue1 = newDto(rule, file, project)
  558. .setIssueCreationDate(parseDateTime("2014-09-04T00:00:00+0100"))
  559. .setIssueUpdateDate(parseDateTime("2017-12-04T00:00:00+0100"))
  560. .setEffort(10L)
  561. .setStatus("OPEN")
  562. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
  563. .setSeverity("MAJOR")
  564. .setAssigneeUuid(john.getUuid());
  565. IssueDto issue2 = newDto(rule, file, project)
  566. .setIssueCreationDate(parseDateTime("2014-09-04T00:00:00+0100"))
  567. .setIssueUpdateDate(parseDateTime("2017-12-04T00:00:00+0100"))
  568. .setEffort(10L)
  569. .setStatus("OPEN")
  570. .setKee("7b112bd4-b650-4037-80bc-82fd47d4eac2")
  571. .setSeverity("MAJOR")
  572. .setAssigneeUuid(alice.getUuid());
  573. dbClient.issueDao().insert(session, issue1, issue2);
  574. session.commit();
  575. indexIssues();
  576. userSession.logIn(john);
  577. ws.newRequest()
  578. .setParam(PARAM_COMPONENT_KEYS, "PROJECT_KEY")
  579. .setParam(PARAM_SINCE_LEAK_PERIOD, "true")
  580. .execute()
  581. .assertJson(this.getClass(), "empty_result.json");
  582. }
  583. @Test
  584. public void filter_by_leak_period_has_no_effect_on_prs() {
  585. UserDto john = db.users().insertUser(u -> u.setLogin("john").setName("John").setEmail("john@email.com"));
  586. UserDto alice = db.users().insertUser(u -> u.setLogin("alice").setName("Alice").setEmail("alice@email.com"));
  587. ComponentDto project = db.components().insertPublicProject(c -> c.setUuid("PROJECT_ID").setDbKey("PROJECT_KEY"));
  588. ComponentDto pr = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.PULL_REQUEST).setKey("pr"));
  589. SnapshotDto snapshotDto = db.components().insertSnapshot(pr);
  590. indexPermissions();
  591. ComponentDto file = db.components().insertComponent(newFileDto(pr, null, "FILE_ID").setDbKey("FILE_KEY" + PULL_REQUEST_SEPARATOR + "pr"));
  592. RuleDto rule = newIssueRule();
  593. IssueDto issue1 = newDto(rule, file, pr)
  594. .setIssueCreationDate(parseDateTime("2014-09-04T00:00:00+0100"))
  595. .setIssueUpdateDate(parseDateTime("2017-12-04T00:00:00+0100"))
  596. .setEffort(10L)
  597. .setStatus("OPEN")
  598. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
  599. .setSeverity("MAJOR")
  600. .setAssigneeUuid(john.getUuid());
  601. IssueDto issue2 = newDto(rule, file, pr)
  602. .setIssueCreationDate(parseDateTime("2014-09-04T00:00:00+0100"))
  603. .setIssueUpdateDate(parseDateTime("2017-12-04T00:00:00+0100"))
  604. .setEffort(10L)
  605. .setStatus("OPEN")
  606. .setKee("7b112bd4-b650-4037-80bc-82fd47d4eac2")
  607. .setSeverity("MAJOR")
  608. .setAssigneeUuid(alice.getUuid());
  609. dbClient.issueDao().insert(session, issue1, issue2);
  610. session.commit();
  611. indexIssues();
  612. userSession.logIn(john);
  613. ws.newRequest()
  614. .setParam(PARAM_COMPONENT_KEYS, "PROJECT_KEY")
  615. .setParam(PARAM_PULL_REQUEST, "pr")
  616. .setParam(PARAM_SINCE_LEAK_PERIOD, "true")
  617. .execute()
  618. .assertJson(this.getClass(), "filter_by_leak_period_has_no_effect_on_prs.json");
  619. }
  620. @Test
  621. public void return_empty_when_login_is_unknown() {
  622. UserDto john = db.users().insertUser(u -> u.setLogin("john").setName("John").setEmail("john@email.com"));
  623. UserDto alice = db.users().insertUser(u -> u.setLogin("alice").setName("Alice").setEmail("alice@email.com"));
  624. ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto("PROJECT_ID").setDbKey("PROJECT_KEY"));
  625. indexPermissions();
  626. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY"));
  627. RuleDto rule = newIssueRule();
  628. IssueDto issue1 = newDto(rule, file, project)
  629. .setIssueCreationDate(parseDate("2014-09-04"))
  630. .setIssueUpdateDate(parseDate("2017-12-04"))
  631. .setEffort(10L)
  632. .setStatus("OPEN")
  633. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
  634. .setSeverity("MAJOR")
  635. .setAssigneeUuid(john.getUuid());
  636. IssueDto issue2 = newDto(rule, file, project)
  637. .setIssueCreationDate(parseDate("2014-09-04"))
  638. .setIssueUpdateDate(parseDate("2017-12-04"))
  639. .setEffort(10L)
  640. .setStatus("OPEN")
  641. .setKee("7b112bd4-b650-4037-80bc-82fd47d4eac2")
  642. .setSeverity("MAJOR")
  643. .setAssigneeUuid(alice.getUuid());
  644. IssueDto issue3 = newDto(rule, file, project)
  645. .setIssueCreationDate(parseDate("2014-09-04"))
  646. .setIssueUpdateDate(parseDate("2017-12-04"))
  647. .setEffort(10L)
  648. .setStatus("OPEN")
  649. .setKee("82fd47d4-4037-b650-80bc-7b112bd4eac2")
  650. .setSeverity("MAJOR")
  651. .setAssigneeUuid(null);
  652. dbClient.issueDao().insert(session, issue1, issue2, issue3);
  653. session.commit();
  654. indexIssues();
  655. userSession.logIn(john);
  656. SearchWsResponse response = ws.newRequest()
  657. .setParam("resolved", "false")
  658. .setParam("assignees", "unknown")
  659. .setParam(FACETS, "assignees")
  660. .executeProtobuf(SearchWsResponse.class);
  661. assertThat(response.getIssuesList()).isEmpty();
  662. }
  663. @Test
  664. public void filter_by_assigned_to_me_when_not_authenticate() {
  665. UserDto poy = db.users().insertUser(u -> u.setLogin("poy").setName("poypoy").setEmail("poypoy@email.com"));
  666. userSession.logIn(poy);
  667. UserDto alice = db.users().insertUser(u -> u.setLogin("alice").setName("Alice").setEmail("alice@email.com"));
  668. UserDto john = db.users().insertUser(u -> u.setLogin("john").setName("John").setEmail("john@email.com"));
  669. ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto("PROJECT_ID").setDbKey("PROJECT_KEY"));
  670. indexPermissions();
  671. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY"));
  672. RuleDto rule = newIssueRule();
  673. IssueDto issue1 = newDto(rule, file, project)
  674. .setStatus("OPEN")
  675. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
  676. .setAssigneeUuid(john.getUuid());
  677. IssueDto issue2 = newDto(rule, file, project)
  678. .setStatus("OPEN")
  679. .setKee("7b112bd4-b650-4037-80bc-82fd47d4eac2")
  680. .setAssigneeUuid(alice.getUuid());
  681. IssueDto issue3 = newDto(rule, file, project)
  682. .setStatus("OPEN")
  683. .setKee("82fd47d4-4037-b650-80bc-7b112bd4eac2")
  684. .setAssigneeUuid(null);
  685. dbClient.issueDao().insert(session, issue1, issue2, issue3);
  686. session.commit();
  687. indexIssues();
  688. ws.newRequest()
  689. .setParam("resolved", "false")
  690. .setParam("assignees", "__me__")
  691. .execute()
  692. .assertJson(this.getClass(), "empty_result.json");
  693. }
  694. @Test
  695. public void search_by_author() {
  696. ComponentDto project = db.components().insertPublicProject();
  697. ComponentDto file = db.components().insertComponent(newFileDto(project, null));
  698. RuleDefinitionDto rule = db.rules().insertIssueRule();
  699. IssueDto issue1 = db.issues().insertIssue(rule, project, file, i -> i.setAuthorLogin("leia"));
  700. IssueDto issue2 = db.issues().insertIssue(rule, project, file, i -> i.setAuthorLogin("luke"));
  701. IssueDto issue3 = db.issues().insertIssue(rule, project, file, i -> i.setAuthorLogin("han, solo"));
  702. indexPermissions();
  703. indexIssues();
  704. SearchWsResponse response = ws.newRequest()
  705. .setMultiParam("author", asList("leia", "han, solo"))
  706. .setParam(FACETS, "author")
  707. .executeProtobuf(SearchWsResponse.class);
  708. assertThat(response.getIssuesList())
  709. .extracting(Issue::getKey)
  710. .containsExactlyInAnyOrder(issue1.getKey(), issue3.getKey());
  711. Common.Facet facet = response.getFacets().getFacetsList().get(0);
  712. assertThat(facet.getProperty()).isEqualTo("author");
  713. assertThat(facet.getValuesList())
  714. .extracting(Common.FacetValue::getVal, Common.FacetValue::getCount)
  715. .containsExactlyInAnyOrder(
  716. tuple("leia", 1L),
  717. tuple("luke", 1L),
  718. tuple("han, solo", 1L));
  719. assertThat(ws.newRequest()
  720. .setMultiParam("author", singletonList("unknown"))
  721. .executeProtobuf(SearchWsResponse.class).getIssuesList())
  722. .isEmpty();
  723. }
  724. @Test
  725. public void filter_by_test_scope() {
  726. ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto("PROJECT_ID").setDbKey("PROJECT_KEY"));
  727. indexPermissions();
  728. ComponentDto mainCodeFile = db.components().insertComponent(
  729. newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY"));
  730. ComponentDto testCodeFile = db.components().insertComponent(
  731. newFileDto(project, null, "ANOTHER_FILE_ID").setDbKey("ANOTHER_FILE_KEY").setQualifier(UNIT_TEST_FILE));
  732. RuleDto rule = newIssueRule();
  733. IssueDto issue1 = newDto(rule, mainCodeFile, project)
  734. .setIssueCreationDate(parseDate("2014-09-04"))
  735. .setIssueUpdateDate(parseDate("2017-12-04"))
  736. .setEffort(10L)
  737. .setStatus("OPEN")
  738. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
  739. .setSeverity("MAJOR");
  740. IssueDto issue2 = newDto(rule, mainCodeFile, project)
  741. .setIssueCreationDate(parseDate("2014-09-04"))
  742. .setIssueUpdateDate(parseDate("2017-12-04"))
  743. .setEffort(10L)
  744. .setStatus("OPEN")
  745. .setKee("7b112bd4-b650-4037-80bc-82fd47d4eac2")
  746. .setSeverity("MAJOR");
  747. IssueDto issue3 = newDto(rule, testCodeFile, project)
  748. .setIssueCreationDate(parseDate("2014-09-04"))
  749. .setIssueUpdateDate(parseDate("2017-12-04"))
  750. .setEffort(10L)
  751. .setStatus("OPEN")
  752. .setKee("82fd47d4-4037-b650-80bc-7b112bd4eac2")
  753. .setSeverity("MAJOR");
  754. dbClient.issueDao().insert(session, issue1, issue2, issue3);
  755. session.commit();
  756. indexIssues();
  757. ws.newRequest()
  758. .setParam("scopes", "TEST")
  759. .setParam(FACETS, "scopes")
  760. .execute()
  761. .assertJson(this.getClass(), "filter_by_test_scope.json");
  762. }
  763. @Test
  764. public void filter_by_main_scope() {
  765. ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto("PROJECT_ID").setDbKey("PROJECT_KEY"));
  766. indexPermissions();
  767. ComponentDto mainCodeFile = db.components().insertComponent(
  768. newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY"));
  769. ComponentDto testCodeFile = db.components().insertComponent(
  770. newFileDto(project, null, "ANOTHER_FILE_ID").setDbKey("ANOTHER_FILE_KEY").setQualifier(UNIT_TEST_FILE));
  771. RuleDto rule = newIssueRule();
  772. IssueDto issue1 = newDto(rule, mainCodeFile, project)
  773. .setType(CODE_SMELL)
  774. .setIssueCreationDate(parseDate("2014-09-04"))
  775. .setIssueUpdateDate(parseDate("2017-12-04"))
  776. .setEffort(10L)
  777. .setStatus("OPEN")
  778. .setKee("83ec1d05-9397-4137-9978-85368bcc3b90")
  779. .setSeverity("MAJOR");
  780. IssueDto issue2 = newDto(rule, mainCodeFile, project)
  781. .setType(CODE_SMELL)
  782. .setIssueCreationDate(parseDate("2014-09-04"))
  783. .setIssueUpdateDate(parseDate("2017-12-04"))
  784. .setEffort(10L)
  785. .setStatus("OPEN")
  786. .setKee("7b112bd4-b650-4037-80bc-82fd47d4eac2")
  787. .setSeverity("MAJOR");
  788. IssueDto issue3 = newDto(rule, testCodeFile, project)
  789. .setType(CODE_SMELL)
  790. .setIssueCreationDate(parseDate("2014-09-04"))
  791. .setIssueUpdateDate(parseDate("2017-12-04"))
  792. .setEffort(10L)
  793. .setStatus("OPEN")
  794. .setKee("82fd47d4-4037-b650-80bc-7b112bd4eac2")
  795. .setSeverity("MAJOR");
  796. dbClient.issueDao().insert(session, issue1, issue2, issue3);
  797. session.commit();
  798. indexIssues();
  799. ws.newRequest()
  800. .setParam("scopes", "MAIN")
  801. .setParam(FACETS, "scopes")
  802. .execute()
  803. .assertJson(this.getClass(), "filter_by_main_scope.json");
  804. }
  805. @Test
  806. public void filter_by_scope_always_returns_all_scope_facet_values() {
  807. ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto("PROJECT_ID").setDbKey("PROJECT_KEY"));
  808. indexPermissions();
  809. ComponentDto mainCodeFile = db.components().insertComponent(
  810. newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY"));
  811. RuleDto rule = newIssueRule();
  812. IssueDto issue1 = newDto(rule, mainCodeFile, project)
  813. .setType(CODE_SMELL)
  814. .setIssueCreationDate(parseDate("2014-09-04"))
  815. .setIssueUpdateDate(parseDate("2017-12-04"))
  816. .setEffort(10L)
  817. .setStatus("OPEN")
  818. .setKee("83ec1d05-9397-4137-9978-85368bcc3b90")
  819. .setSeverity("MAJOR");
  820. IssueDto issue2 = newDto(rule, mainCodeFile, project)
  821. .setType(CODE_SMELL)
  822. .setIssueCreationDate(parseDate("2014-09-04"))
  823. .setIssueUpdateDate(parseDate("2017-12-04"))
  824. .setEffort(10L)
  825. .setStatus("OPEN")
  826. .setKee("7b112bd4-b650-4037-80bc-82fd47d4eac2")
  827. .setSeverity("MAJOR");
  828. dbClient.issueDao().insert(session, issue1, issue2);
  829. session.commit();
  830. indexIssues();
  831. ws.newRequest()
  832. .setParam("scopes", "MAIN")
  833. .setParam(FACETS, "scopes")
  834. .execute()
  835. .assertJson(this.getClass(), "filter_by_main_scope_2.json");
  836. }
  837. @Test
  838. public void sort_by_updated_at() {
  839. RuleDto rule = newIssueRule();
  840. ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto("PROJECT_ID").setDbKey("PROJECT_KEY"));
  841. indexPermissions();
  842. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY"));
  843. dbClient.issueDao().insert(session, newDto(rule, file, project)
  844. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac1")
  845. .setIssueUpdateDate(parseDateTime("2014-11-02T00:00:00+0100")));
  846. dbClient.issueDao().insert(session, newDto(rule, file, project)
  847. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
  848. .setIssueUpdateDate(parseDateTime("2014-11-01T00:00:00+0100")));
  849. dbClient.issueDao().insert(session, newDto(rule, file, project)
  850. .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac3")
  851. .setIssueUpdateDate(parseDateTime("2014-11-03T00:00:00+0100")));
  852. session.commit();
  853. indexIssues();
  854. TestResponse response = ws.newRequest()
  855. .setParam("s", IssueQuery.SORT_BY_UPDATE_DATE)
  856. .setParam("asc", "false")
  857. .execute();
  858. JsonElement parse = new JsonParser().parse(response.getInput());
  859. assertThat(parse.getAsJsonObject().get("issues").getAsJsonArray())
  860. .extracting(o -> o.getAsJsonObject().get("key").getAsString())
  861. .containsExactly("82fd47d4-b650-4037-80bc-7b112bd4eac3", "82fd47d4-b650-4037-80bc-7b112bd4eac1", "82fd47d4-b650-4037-80bc-7b112bd4eac2");
  862. }
  863. @Test
  864. public void only_vulnerabilities_are_returned_by_cwe() {
  865. ComponentDto project = db.components().insertPublicProject();
  866. ComponentDto file = db.components().insertComponent(newFileDto(project));
  867. Consumer<RuleDefinitionDto> ruleConsumer = ruleDefinitionDto -> ruleDefinitionDto
  868. .setSecurityStandards(Sets.newHashSet("cwe:20", "cwe:564", "cwe:89", "cwe:943", "owaspTop10:a1"))
  869. .setSystemTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  870. Consumer<IssueDto> issueConsumer = issueDto -> issueDto.setTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  871. RuleDefinitionDto hotspotRule = db.rules().insertHotspotRule(ruleConsumer);
  872. db.issues().insertHotspot(hotspotRule, project, file, issueConsumer);
  873. RuleDefinitionDto issueRule = db.rules().insertIssueRule(ruleConsumer);
  874. IssueDto issueDto1 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  875. IssueDto issueDto2 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  876. IssueDto issueDto3 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(CODE_SMELL));
  877. indexPermissions();
  878. indexIssues();
  879. SearchWsResponse result = ws.newRequest()
  880. .setParam("cwe", "20")
  881. .executeProtobuf(SearchWsResponse.class);
  882. assertThat(result.getIssuesList())
  883. .extracting(Issue::getKey)
  884. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey());
  885. }
  886. @Test
  887. public void only_vulnerabilities_are_returned_by_owasp() {
  888. ComponentDto project = db.components().insertPublicProject();
  889. ComponentDto file = db.components().insertComponent(newFileDto(project));
  890. Consumer<RuleDefinitionDto> ruleConsumer = ruleDefinitionDto -> ruleDefinitionDto
  891. .setSecurityStandards(Sets.newHashSet("cwe:20", "cwe:564", "cwe:89", "cwe:943", "owaspTop10:a1"))
  892. .setSystemTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  893. Consumer<IssueDto> issueConsumer = issueDto -> issueDto.setTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  894. RuleDefinitionDto hotspotRule = db.rules().insertHotspotRule(ruleConsumer);
  895. db.issues().insertHotspot(hotspotRule, project, file, issueConsumer);
  896. RuleDefinitionDto issueRule = db.rules().insertIssueRule(ruleConsumer);
  897. IssueDto issueDto1 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  898. IssueDto issueDto2 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  899. IssueDto issueDto3 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(CODE_SMELL));
  900. indexPermissions();
  901. indexIssues();
  902. SearchWsResponse result = ws.newRequest()
  903. .setParam("owaspTop10", "a1")
  904. .executeProtobuf(SearchWsResponse.class);
  905. assertThat(result.getIssuesList())
  906. .extracting(Issue::getKey)
  907. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey());
  908. }
  909. @Test
  910. public void only_vulnerabilities_are_returned_by_sansTop25() {
  911. ComponentDto project = db.components().insertPublicProject();
  912. ComponentDto file = db.components().insertComponent(newFileDto(project));
  913. Consumer<RuleDefinitionDto> ruleConsumer = ruleDefinitionDto -> ruleDefinitionDto
  914. .setSecurityStandards(Sets.newHashSet("cwe:266", "cwe:732", "owaspTop10:a5"))
  915. .setSystemTags(Sets.newHashSet("cert", "cwe", "owasp-a5", "sans-top25-porous"));
  916. Consumer<IssueDto> issueConsumer = issueDto -> issueDto.setTags(Sets.newHashSet("cert", "cwe", "owasp-a5", "sans-top25-porous"));
  917. RuleDefinitionDto hotspotRule = db.rules().insertHotspotRule(ruleConsumer);
  918. db.issues().insertHotspot(hotspotRule, project, file, issueConsumer);
  919. RuleDefinitionDto issueRule = db.rules().insertIssueRule(ruleConsumer);
  920. IssueDto issueDto1 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  921. IssueDto issueDto2 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  922. IssueDto issueDto3 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(CODE_SMELL));
  923. indexPermissions();
  924. indexIssues();
  925. SearchWsResponse result = ws.newRequest()
  926. .setParam("sansTop25", "porous-defenses")
  927. .executeProtobuf(SearchWsResponse.class);
  928. assertThat(result.getIssuesList())
  929. .extracting(Issue::getKey)
  930. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey());
  931. }
  932. @Test
  933. public void only_vulnerabilities_are_returned_by_sonarsource_security() {
  934. ComponentDto project = db.components().insertPublicProject();
  935. ComponentDto file = db.components().insertComponent(newFileDto(project));
  936. Consumer<RuleDefinitionDto> ruleConsumer = ruleDefinitionDto -> ruleDefinitionDto
  937. .setSecurityStandards(Sets.newHashSet("cwe:20", "cwe:564", "cwe:89", "cwe:943", "owaspTop10:a1"))
  938. .setSystemTags(Sets.newHashSet("cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  939. Consumer<IssueDto> issueConsumer = issueDto -> issueDto.setTags(Sets.newHashSet("cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  940. RuleDefinitionDto hotspotRule = db.rules().insertHotspotRule(ruleConsumer);
  941. db.issues().insertHotspot(hotspotRule, project, file, issueConsumer);
  942. RuleDefinitionDto issueRule = db.rules().insertIssueRule(ruleConsumer);
  943. IssueDto issueDto1 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  944. IssueDto issueDto2 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  945. IssueDto issueDto3 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(CODE_SMELL));
  946. indexPermissions();
  947. indexIssues();
  948. SearchWsResponse result = ws.newRequest()
  949. .setParam("sonarsourceSecurity", "sql-injection")
  950. .executeProtobuf(SearchWsResponse.class);
  951. assertThat(result.getIssuesList())
  952. .extracting(Issue::getKey)
  953. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey());
  954. }
  955. @Test
  956. public void security_hotspots_are_not_returned_by_default() {
  957. ComponentDto project = db.components().insertPublicProject();
  958. ComponentDto file = db.components().insertComponent(newFileDto(project));
  959. RuleDefinitionDto rule = db.rules().insertIssueRule();
  960. db.issues().insertIssue(rule, project, file, i -> i.setType(RuleType.BUG));
  961. db.issues().insertIssue(rule, project, file, i -> i.setType(RuleType.VULNERABILITY));
  962. db.issues().insertIssue(rule, project, file, i -> i.setType(CODE_SMELL));
  963. db.issues().insertHotspot(project, file);
  964. indexPermissions();
  965. indexIssues();
  966. SearchWsResponse result = ws.newRequest().executeProtobuf(SearchWsResponse.class);
  967. assertThat(result.getIssuesList())
  968. .extracting(Issue::getType)
  969. .containsExactlyInAnyOrder(BUG, VULNERABILITY, Common.RuleType.CODE_SMELL);
  970. }
  971. @Test
  972. public void security_hotspots_are_not_returned_by_issues_param() {
  973. ComponentDto project = db.components().insertPublicProject();
  974. ComponentDto file = db.components().insertComponent(newFileDto(project));
  975. RuleDefinitionDto issueRule = db.rules().insertIssueRule();
  976. IssueDto bugIssue = db.issues().insertIssue(issueRule, project, file, i -> i.setType(RuleType.BUG));
  977. IssueDto vulnerabilityIssue = db.issues().insertIssue(issueRule, project, file, i -> i.setType(RuleType.VULNERABILITY));
  978. IssueDto codeSmellIssue = db.issues().insertIssue(issueRule, project, file, i -> i.setType(CODE_SMELL));
  979. RuleDefinitionDto hotspotRule = db.rules().insertHotspotRule();
  980. IssueDto hotspot = db.issues().insertHotspot(hotspotRule, project, file);
  981. indexPermissions();
  982. indexIssues();
  983. SearchWsResponse result = ws.newRequest()
  984. .setParam("issues", Stream.of(bugIssue, vulnerabilityIssue, codeSmellIssue, hotspot).map(IssueDto::getKey).collect(Collectors.joining(",")))
  985. .executeProtobuf(SearchWsResponse.class);
  986. assertThat(result.getIssuesList())
  987. .extracting(Issue::getType)
  988. .containsExactlyInAnyOrder(BUG, VULNERABILITY, Common.RuleType.CODE_SMELL);
  989. }
  990. @Test
  991. public void security_hotspots_are_not_returned_by_cwe() {
  992. ComponentDto project = db.components().insertPublicProject();
  993. ComponentDto file = db.components().insertComponent(newFileDto(project));
  994. Consumer<RuleDefinitionDto> ruleConsumer = ruleDefinitionDto -> ruleDefinitionDto
  995. .setSecurityStandards(Sets.newHashSet("cwe:20", "cwe:564", "cwe:89", "cwe:943", "owaspTop10:a1"))
  996. .setSystemTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  997. Consumer<IssueDto> issueConsumer = issueDto -> issueDto.setTags(Sets.newHashSet("bad-practice", "cwe", "owasp-a1", "sans-top25-insecure", "sql"));
  998. RuleDefinitionDto hotspotRule = db.rules().insertHotspotRule(ruleConsumer);
  999. db.issues().insertHotspot(hotspotRule, project, file, issueConsumer);
  1000. RuleDefinitionDto issueRule = db.rules().insertIssueRule(ruleConsumer);
  1001. IssueDto issueDto1 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1002. IssueDto issueDto2 = db.issues().insertIssue(issueRule, project, file, issueConsumer, issueDto -> issueDto.setType(RuleType.VULNERABILITY));
  1003. indexPermissions();
  1004. indexIssues();
  1005. SearchWsResponse result = ws.newRequest()
  1006. .setParam("cwe", "20")
  1007. .executeProtobuf(SearchWsResponse.class);
  1008. assertThat(result.getIssuesList())
  1009. .extracting(Issue::getKey)
  1010. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey());
  1011. }
  1012. @Test
  1013. public void security_hotspots_are_not_returned_by_assignees() {
  1014. UserDto user = db.users().insertUser();
  1015. ComponentDto project = db.components().insertPublicProject();
  1016. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1017. RuleDefinitionDto hotspotRule = db.rules().insertHotspotRule();
  1018. db.issues().insertHotspot(hotspotRule, project, file, issueDto -> issueDto.setAssigneeUuid(user.getUuid()));
  1019. RuleDefinitionDto issueRule = db.rules().insertIssueRule();
  1020. IssueDto issueDto1 = db.issues().insertIssue(issueRule, project, file, issueDto -> issueDto.setAssigneeUuid(user.getUuid()));
  1021. IssueDto issueDto2 = db.issues().insertIssue(issueRule, project, file, issueDto -> issueDto.setAssigneeUuid(user.getUuid()));
  1022. IssueDto issueDto3 = db.issues().insertIssue(issueRule, project, file, issueDto -> issueDto.setAssigneeUuid(user.getUuid()));
  1023. IssueDto issueDto4 = db.issues().insertIssue(issueRule, project, file, issueDto -> issueDto.setAssigneeUuid(user.getUuid()));
  1024. indexPermissions();
  1025. indexIssues();
  1026. SearchWsResponse result = ws.newRequest()
  1027. .setParam(PARAM_ASSIGNEES, user.getLogin())
  1028. .executeProtobuf(SearchWsResponse.class);
  1029. assertThat(result.getIssuesList())
  1030. .extracting(Issue::getKey)
  1031. .containsExactlyInAnyOrder(issueDto1.getKey(), issueDto2.getKey(), issueDto3.getKey(), issueDto4.getKey());
  1032. }
  1033. @Test
  1034. public void security_hotspots_are_not_returned_by_rule() {
  1035. ComponentDto project = db.components().insertPublicProject();
  1036. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1037. RuleDefinitionDto hotspotRule = db.rules().insertHotspotRule();
  1038. db.issues().insertHotspot(hotspotRule, project, file);
  1039. indexPermissions();
  1040. indexIssues();
  1041. SearchWsResponse result = ws.newRequest()
  1042. .setParam("rules", hotspotRule.getKey().toString())
  1043. .executeProtobuf(SearchWsResponse.class);
  1044. assertThat(result.getIssuesList()).isEmpty();
  1045. }
  1046. @Test
  1047. public void security_hotspots_are_not_returned_by_issues_param_only() {
  1048. ComponentDto project = db.components().insertPublicProject();
  1049. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1050. RuleDefinitionDto rule = db.rules().insertHotspotRule();
  1051. List<IssueDto> hotspots = IntStream.range(1, 2 + new Random().nextInt(10))
  1052. .mapToObj(value -> db.issues().insertHotspot(rule, project, file))
  1053. .collect(Collectors.toList());
  1054. indexPermissions();
  1055. indexIssues();
  1056. SearchWsResponse result = ws.newRequest()
  1057. .setParam("issues", hotspots.stream().map(IssueDto::getKey).collect(Collectors.joining(",")))
  1058. .executeProtobuf(SearchWsResponse.class);
  1059. assertThat(result.getIssuesList())
  1060. .isEmpty();
  1061. }
  1062. @Test
  1063. public void fail_if_trying_to_filter_issues_by_hotspots() {
  1064. ComponentDto project = db.components().insertPublicProject();
  1065. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1066. RuleDefinitionDto issueRule = newIssueRule().getDefinition();
  1067. RuleDefinitionDto hotspotRule = newHotspotRule().getDefinition();
  1068. db.issues().insertIssue(issueRule, project, file, i -> i.setType(RuleType.BUG));
  1069. db.issues().insertIssue(issueRule, project, file, i -> i.setType(RuleType.VULNERABILITY));
  1070. db.issues().insertIssue(issueRule, project, file, i -> i.setType(CODE_SMELL));
  1071. db.issues().insertHotspot(hotspotRule, project, file);
  1072. indexPermissions();
  1073. indexIssues();
  1074. TestRequest request = ws.newRequest()
  1075. .setParam("types", RuleType.SECURITY_HOTSPOT.toString());
  1076. assertThatThrownBy(request::execute)
  1077. .isInstanceOf(IllegalArgumentException.class)
  1078. .hasMessage("Value of parameter 'types' (SECURITY_HOTSPOT) must be one of: [CODE_SMELL, BUG, VULNERABILITY]");
  1079. }
  1080. @Test
  1081. public void security_hotspot_are_ignored_when_filtering_by_severities() {
  1082. ComponentDto project = db.components().insertPublicProject();
  1083. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1084. RuleDefinitionDto issueRule = db.rules().insertIssueRule();
  1085. IssueDto bugIssue = db.issues().insertIssue(issueRule, project, file, i -> i.setType(RuleType.BUG).setSeverity(Severity.MAJOR.name()));
  1086. IssueDto vulnerabilityIssue = db.issues().insertIssue(issueRule, project, file, i -> i.setType(RuleType.VULNERABILITY).setSeverity(Severity.MAJOR.name()));
  1087. IssueDto codeSmellIssue = db.issues().insertIssue(issueRule, project, file, i -> i.setType(CODE_SMELL).setSeverity(Severity.MAJOR.name()));
  1088. RuleDefinitionDto hotspotRule = db.rules().insertHotspotRule();
  1089. db.issues().insertHotspot(hotspotRule, project, file, i -> i.setSeverity(Severity.MAJOR.name()));
  1090. indexPermissions();
  1091. indexIssues();
  1092. SearchWsResponse result = ws.newRequest()
  1093. .setParam("severities", Severity.MAJOR.name())
  1094. .setParam(FACETS, "severities")
  1095. .executeProtobuf(SearchWsResponse.class);
  1096. assertThat(result.getIssuesList())
  1097. .extracting(Issue::getKey, Issue::getType)
  1098. .containsExactlyInAnyOrder(
  1099. tuple(bugIssue.getKey(), BUG),
  1100. tuple(vulnerabilityIssue.getKey(), VULNERABILITY),
  1101. tuple(codeSmellIssue.getKey(), Common.RuleType.CODE_SMELL));
  1102. assertThat(result.getFacets().getFacets(0).getValuesList())
  1103. .extracting(Common.FacetValue::getVal, Common.FacetValue::getCount)
  1104. .containsExactlyInAnyOrder(tuple("MAJOR", 3L), tuple("INFO", 0L), tuple("MINOR", 0L), tuple("CRITICAL", 0L), tuple("BLOCKER", 0L));
  1105. }
  1106. @Test
  1107. public void return_total_effort() {
  1108. UserDto john = db.users().insertUser();
  1109. userSession.logIn(john);
  1110. RuleDefinitionDto rule = db.rules().insertIssueRule();
  1111. ComponentDto project = db.components().insertPublicProject();
  1112. ComponentDto file = db.components().insertComponent(newFileDto(project));
  1113. IssueDto issue1 = db.issues().insertIssue(rule, project, file, i -> i.setEffort(10L));
  1114. IssueDto issue2 = db.issues().insertIssue(rule, project, file, i -> i.setEffort(15L));
  1115. indexPermissions();
  1116. indexIssues();
  1117. SearchWsResponse response = ws.newRequest().executeProtobuf(SearchWsResponse.class);
  1118. assertThat(response.getEffortTotal()).isEqualTo(25L);
  1119. }
  1120. @Test
  1121. public void paging() {
  1122. RuleDto rule = newIssueRule();
  1123. ComponentDto project = db.components().insertComponent(ComponentTesting.newPublicProjectDto("PROJECT_ID").setDbKey("PROJECT_KEY"));
  1124. indexPermissions();
  1125. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "FILE_ID").setDbKey("FILE_KEY"));
  1126. for (int i = 0; i < 12; i++) {
  1127. IssueDto issue = newDto(rule, file, project);
  1128. dbClient.issueDao().insert(session, issue);
  1129. }
  1130. session.commit();
  1131. indexIssues();
  1132. ws.newRequest()
  1133. .setParam(WebService.Param.PAGE, "2")
  1134. .setParam(WebService.Param.PAGE_SIZE, "9")
  1135. .execute()
  1136. .assertJson(this.getClass(), "paging.json");
  1137. }
  1138. @Test
  1139. public void paging_with_page_size_to_minus_one() {
  1140. expectedException.expect(IllegalArgumentException.class);
  1141. expectedException.expectMessage("Page size must be between 1 and 500 (got -1)");
  1142. ws.newRequest()
  1143. .setParam(WebService.Param.PAGE, "1")
  1144. .setParam(WebService.Param.PAGE_SIZE, "-1")
  1145. .execute();
  1146. }
  1147. @Test
  1148. public void default_page_size_is_100() {
  1149. ws.newRequest()
  1150. .execute()
  1151. .assertJson(this.getClass(), "default_page_size_is_100.json");
  1152. }
  1153. // SONAR-10217
  1154. @Test
  1155. public void empty_search_with_unknown_branch() {
  1156. SearchWsResponse response = ws.newRequest()
  1157. .setParam("onComponentOnly", "true")
  1158. .setParam("componentKeys", "foo")
  1159. .setParam("branch", "bar")
  1160. .executeProtobuf(SearchWsResponse.class);
  1161. assertThat(response)
  1162. .extracting(SearchWsResponse::getIssuesList, r -> r.getPaging().getTotal())
  1163. .containsExactlyInAnyOrder(Collections.emptyList(), 0);
  1164. }
  1165. @Test
  1166. public void empty_search() {
  1167. SearchWsResponse response = ws.newRequest().executeProtobuf(SearchWsResponse.class);
  1168. assertThat(response)
  1169. .extracting(SearchWsResponse::getIssuesList, r -> r.getPaging().getTotal())
  1170. .containsExactlyInAnyOrder(Collections.emptyList(), 0);
  1171. }
  1172. @Test
  1173. public void fail_when_invalid_format() {
  1174. expectedException.expect(IllegalArgumentException.class);
  1175. expectedException.expectMessage("Date 'wrong-date-input' cannot be parsed as either a date or date+time");
  1176. ws.newRequest()
  1177. .setParam(PARAM_CREATED_AFTER, "wrong-date-input")
  1178. .execute();
  1179. }
  1180. @Test
  1181. public void test_definition() {
  1182. WebService.Action def = ws.getDef();
  1183. assertThat(def.key()).isEqualTo("search");
  1184. assertThat(def.isInternal()).isFalse();
  1185. assertThat(def.isPost()).isFalse();
  1186. assertThat(def.since()).isEqualTo("3.6");
  1187. assertThat(def.responseExampleAsString()).isNotEmpty();
  1188. assertThat(def.params()).extracting("key").containsExactlyInAnyOrder(
  1189. "additionalFields", "asc", "assigned", "assignees", "author", "componentKeys", "branch", "pullRequest", "createdAfter", "createdAt",
  1190. "createdBefore", "createdInLast", "directories", "facets", "files", "issues", "scopes", "languages", "onComponentOnly",
  1191. "p", "projects", "ps", "resolutions", "resolved", "rules", "s", "severities", "sinceLeakPeriod", "statuses", "tags", "types", "owaspTop10", "sansTop25",
  1192. "cwe", "sonarsourceSecurity", "timeZone");
  1193. WebService.Param branch = def.param(PARAM_BRANCH);
  1194. assertThat(branch.isInternal()).isFalse();
  1195. assertThat(branch.isRequired()).isFalse();
  1196. assertThat(branch.since()).isEqualTo("6.6");
  1197. WebService.Param projectUuids = def.param("projects");
  1198. assertThat(projectUuids.description()).isEqualTo("To retrieve issues associated to a specific list of projects (comma-separated list of project keys). " +
  1199. "This parameter is mostly used by the Issues page, please prefer usage of the componentKeys parameter. If this parameter is set, projectUuids must not be set.");
  1200. }
  1201. private RuleDto newIssueRule() {
  1202. RuleDto rule = RuleTesting.newXooX1()
  1203. .setName("Rule name")
  1204. .setDescription("Rule desc")
  1205. .setStatus(RuleStatus.READY);
  1206. db.rules().insert(rule.getDefinition());
  1207. return rule;
  1208. }
  1209. private RuleDto newHotspotRule() {
  1210. RuleDto rule = RuleTesting.newXooX2()
  1211. .setName("Rule name")
  1212. .setDescription("Rule desc")
  1213. .setStatus(RuleStatus.READY)
  1214. .setType(SECURITY_HOTSPOT_VALUE);
  1215. db.rules().insert(rule.getDefinition());
  1216. return rule;
  1217. }
  1218. private void indexPermissions() {
  1219. permissionIndexer.indexAll(permissionIndexer.getIndexTypes());
  1220. }
  1221. private void indexIssues() {
  1222. issueIndexer.indexAllIssues();
  1223. }
  1224. private void grantPermissionToAnyone(ComponentDto project, String permission) {
  1225. dbClient.groupPermissionDao().insert(session,
  1226. new GroupPermissionDto()
  1227. .setUuid(Uuids.createFast())
  1228. .setGroupUuid(null)
  1229. .setComponentUuid(project.uuid())
  1230. .setComponentName(project.name())
  1231. .setRole(permission), project, null);
  1232. session.commit();
  1233. userSession.logIn().addProjectPermission(permission, project);
  1234. }
  1235. }