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.

IssueIndexerTest.java 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2020 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.index;
  21. import java.util.Arrays;
  22. import java.util.Collection;
  23. import java.util.Date;
  24. import java.util.HashSet;
  25. import java.util.List;
  26. import java.util.function.Predicate;
  27. import java.util.stream.Collectors;
  28. import org.elasticsearch.search.SearchHit;
  29. import org.junit.Before;
  30. import org.junit.Rule;
  31. import org.junit.Test;
  32. import org.junit.rules.ExpectedException;
  33. import org.sonar.api.resources.Qualifiers;
  34. import org.sonar.api.utils.log.LogTester;
  35. import org.sonar.api.utils.log.LoggerLevel;
  36. import org.sonar.db.DbSession;
  37. import org.sonar.db.DbTester;
  38. import org.sonar.db.component.ComponentDto;
  39. import org.sonar.db.component.ComponentTesting;
  40. import org.sonar.db.es.EsQueueDto;
  41. import org.sonar.db.issue.IssueDto;
  42. import org.sonar.db.issue.IssueTesting;
  43. import org.sonar.db.organization.OrganizationDto;
  44. import org.sonar.db.rule.RuleDefinitionDto;
  45. import org.sonar.server.es.EsTester;
  46. import org.sonar.server.es.IndexingResult;
  47. import org.sonar.server.es.ProjectIndexer;
  48. import org.sonar.server.permission.index.AuthorizationScope;
  49. import org.sonar.server.permission.index.IndexPermissions;
  50. import org.sonar.server.security.SecurityStandards;
  51. import org.sonar.server.security.SecurityStandards.SQCategory;
  52. import org.sonar.server.security.SecurityStandards.VulnerabilityProbability;
  53. import static java.util.Arrays.asList;
  54. import static java.util.Collections.emptyList;
  55. import static java.util.Collections.emptySet;
  56. import static org.assertj.core.api.Assertions.assertThat;
  57. import static org.junit.rules.ExpectedException.none;
  58. import static org.sonar.db.component.ComponentTesting.newFileDto;
  59. import static org.sonar.server.issue.IssueDocTesting.newDoc;
  60. import static org.sonar.server.issue.index.IssueIndexDefinition.TYPE_ISSUE;
  61. import static org.sonar.server.permission.index.IndexAuthorizationConstants.TYPE_AUTHORIZATION;
  62. import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_POROUS_DEFENSES;
  63. public class IssueIndexerTest {
  64. @Rule
  65. public EsTester es = EsTester.create();
  66. @Rule
  67. public DbTester db = DbTester.create();
  68. @Rule
  69. public ExpectedException expectedException = none();
  70. @Rule
  71. public LogTester logTester = new LogTester();
  72. private OrganizationDto organization;
  73. private IssueIndexer underTest = new IssueIndexer(es.client(), db.getDbClient(), new IssueIteratorFactory(db.getDbClient()));
  74. @Before
  75. public void setUp() {
  76. organization = db.organizations().insert();
  77. }
  78. @Test
  79. public void test_getIndexTypes() {
  80. assertThat(underTest.getIndexTypes()).containsExactly(TYPE_ISSUE);
  81. }
  82. @Test
  83. public void test_getAuthorizationScope() {
  84. AuthorizationScope scope = underTest.getAuthorizationScope();
  85. assertThat(scope.getIndexType().getIndex()).isEqualTo(IssueIndexDefinition.DESCRIPTOR);
  86. assertThat(scope.getIndexType().getType()).isEqualTo(TYPE_AUTHORIZATION);
  87. Predicate<IndexPermissions> projectPredicate = scope.getProjectPredicate();
  88. IndexPermissions project = new IndexPermissions("P1", Qualifiers.PROJECT);
  89. IndexPermissions file = new IndexPermissions("F1", Qualifiers.FILE);
  90. assertThat(projectPredicate.test(project)).isTrue();
  91. assertThat(projectPredicate.test(file)).isFalse();
  92. }
  93. @Test
  94. public void indexOnStartup_scrolls_db_and_adds_all_issues_to_index() {
  95. IssueDto issue1 = db.issues().insert(organization);
  96. IssueDto issue2 = db.issues().insert(organization);
  97. underTest.indexOnStartup(emptySet());
  98. assertThatIndexHasOnly(issue1, issue2);
  99. }
  100. @Test
  101. public void verify_indexed_fields() {
  102. RuleDefinitionDto rule = db.rules().insert();
  103. ComponentDto project = db.components().insertPrivateProject(organization);
  104. ComponentDto dir = db.components().insertComponent(ComponentTesting.newDirectory(project, "src/main/java/foo"));
  105. ComponentDto file = db.components().insertComponent(newFileDto(project, dir, "F1"));
  106. IssueDto issue = db.issues().insert(rule, project, file);
  107. underTest.indexOnStartup(emptySet());
  108. IssueDoc doc = es.getDocuments(TYPE_ISSUE, IssueDoc.class).get(0);
  109. assertThat(doc.getId()).isEqualTo(issue.getKey());
  110. assertThat(doc.organizationUuid()).isEqualTo(organization.getUuid());
  111. assertThat(doc.assigneeUuid()).isEqualTo(issue.getAssigneeUuid());
  112. assertThat(doc.authorLogin()).isEqualTo(issue.getAuthorLogin());
  113. assertThat(doc.componentUuid()).isEqualTo(file.uuid());
  114. assertThat(doc.projectUuid()).isEqualTo(project.uuid());
  115. assertThat(doc.branchUuid()).isEqualTo(project.uuid());
  116. assertThat(doc.isMainBranch()).isTrue();
  117. assertThat(doc.closeDate()).isEqualTo(issue.getIssueCloseDate());
  118. assertThat(doc.creationDate()).isEqualToIgnoringMillis(issue.getIssueCreationDate());
  119. assertThat(doc.directoryPath()).isEqualTo(dir.path());
  120. assertThat(doc.filePath()).isEqualTo(file.path());
  121. assertThat(doc.language()).isEqualTo(issue.getLanguage());
  122. assertThat(doc.line()).isEqualTo(issue.getLine());
  123. // functional date
  124. assertThat(doc.updateDate()).isEqualToIgnoringMillis(new Date(issue.getIssueUpdateTime()));
  125. assertThat(doc.getCwe()).containsExactlyInAnyOrder(SecurityStandards.UNKNOWN_STANDARD);
  126. assertThat(doc.getOwaspTop10()).isEmpty();
  127. assertThat(doc.getSansTop25()).isEmpty();
  128. assertThat(doc.getSonarSourceSecurityCategory()).isEqualTo(SQCategory.OTHERS);
  129. assertThat(doc.getVulnerabilityProbability()).isEqualTo(VulnerabilityProbability.LOW);
  130. }
  131. @Test
  132. public void verify_security_standards_indexation() {
  133. RuleDefinitionDto rule = db.rules().insert(r -> r.setSecurityStandards(new HashSet<>(Arrays.asList("cwe:123", "owaspTop10:a3", "cwe:863"))));
  134. ComponentDto project = db.components().insertPrivateProject(organization);
  135. ComponentDto dir = db.components().insertComponent(ComponentTesting.newDirectory(project, "src/main/java/foo"));
  136. ComponentDto file = db.components().insertComponent(newFileDto(project, dir, "F1"));
  137. IssueDto issue = db.issues().insert(rule, project, file);
  138. underTest.indexOnStartup(emptySet());
  139. IssueDoc doc = es.getDocuments(TYPE_ISSUE, IssueDoc.class).get(0);
  140. assertThat(doc.getCwe()).containsExactlyInAnyOrder("123", "863");
  141. assertThat(doc.getOwaspTop10()).containsExactlyInAnyOrder("a3");
  142. assertThat(doc.getSansTop25()).containsExactlyInAnyOrder(SANS_TOP_25_POROUS_DEFENSES);
  143. }
  144. @Test
  145. public void indexOnStartup_does_not_fail_on_errors_and_does_enable_recovery_mode() {
  146. es.lockWrites(TYPE_ISSUE);
  147. db.issues().insert(organization);
  148. try {
  149. // FIXME : test also message
  150. expectedException.expect(IllegalStateException.class);
  151. underTest.indexOnStartup(emptySet());
  152. } finally {
  153. assertThatIndexHasSize(0);
  154. assertThatEsQueueTableHasSize(0);
  155. es.unlockWrites(TYPE_ISSUE);
  156. }
  157. }
  158. @Test
  159. public void indexOnAnalysis_indexes_the_issues_of_project() {
  160. RuleDefinitionDto rule = db.rules().insert();
  161. ComponentDto project = db.components().insertPrivateProject(organization);
  162. ComponentDto file = db.components().insertComponent(newFileDto(project));
  163. IssueDto issue = db.issues().insert(rule, project, file);
  164. ComponentDto otherProject = db.components().insertPrivateProject(organization);
  165. ComponentDto fileOnOtherProject = db.components().insertComponent(newFileDto(otherProject));
  166. underTest.indexOnAnalysis(project.uuid());
  167. assertThatIndexHasOnly(issue);
  168. }
  169. @Test
  170. public void indexOnAnalysis_does_not_delete_orphan_docs() {
  171. RuleDefinitionDto rule = db.rules().insert();
  172. ComponentDto project = db.components().insertPrivateProject(organization);
  173. ComponentDto file = db.components().insertComponent(newFileDto(project));
  174. IssueDto issue = db.issues().insert(rule, project, file);
  175. // orphan in the project
  176. addIssueToIndex(project.uuid(), "orphan");
  177. underTest.indexOnAnalysis(project.uuid());
  178. assertThat(es.getDocuments(TYPE_ISSUE))
  179. .extracting(SearchHit::getId)
  180. .containsExactlyInAnyOrder(issue.getKey(), "orphan");
  181. }
  182. /**
  183. * Indexing recovery is handled by Compute Engine, without using
  184. * the table es_queue
  185. */
  186. @Test
  187. public void indexOnAnalysis_does_not_fail_on_errors_and_does_not_enable_recovery_mode() {
  188. es.lockWrites(TYPE_ISSUE);
  189. IssueDto issue = db.issues().insert(organization);
  190. try {
  191. // FIXME : test also message
  192. expectedException.expect(IllegalStateException.class);
  193. underTest.indexOnAnalysis(issue.getProjectUuid());
  194. } finally {
  195. assertThatIndexHasSize(0);
  196. assertThatEsQueueTableHasSize(0);
  197. es.unlockWrites(TYPE_ISSUE);
  198. }
  199. }
  200. @Test
  201. public void index_is_not_updated_when_creating_project() {
  202. // it's impossible to already have an issue on a project
  203. // that is being created, but it's just to verify that
  204. // indexing is disabled
  205. IssueDto issue = db.issues().insert(organization);
  206. IndexingResult result = indexProject(issue.getProjectUuid(), ProjectIndexer.Cause.PROJECT_CREATION);
  207. assertThat(result.getTotal()).isEqualTo(0L);
  208. assertThatIndexHasSize(0);
  209. }
  210. @Test
  211. public void index_is_not_updated_when_updating_project_key() {
  212. // issue is inserted to verify that indexing of project is not triggered
  213. IssueDto issue = db.issues().insert(organization);
  214. IndexingResult result = indexProject(issue.getProjectUuid(), ProjectIndexer.Cause.PROJECT_KEY_UPDATE);
  215. assertThat(result.getTotal()).isEqualTo(0L);
  216. assertThatIndexHasSize(0);
  217. }
  218. @Test
  219. public void index_is_not_updated_when_updating_tags() {
  220. // issue is inserted to verify that indexing of project is not triggered
  221. IssueDto issue = db.issues().insert(organization);
  222. IndexingResult result = indexProject(issue.getProjectUuid(), ProjectIndexer.Cause.PROJECT_TAGS_UPDATE);
  223. assertThat(result.getTotal()).isEqualTo(0L);
  224. assertThatIndexHasSize(0);
  225. }
  226. @Test
  227. public void index_is_updated_when_deleting_project() {
  228. addIssueToIndex("P1", "I1");
  229. assertThatIndexHasSize(1);
  230. IndexingResult result = indexProject("P1", ProjectIndexer.Cause.PROJECT_DELETION);
  231. assertThat(result.getTotal()).isEqualTo(1L);
  232. assertThat(result.getSuccess()).isEqualTo(1L);
  233. assertThatIndexHasSize(0);
  234. }
  235. @Test
  236. public void errors_during_project_deletion_are_recovered() {
  237. addIssueToIndex("P1", "I1");
  238. assertThatIndexHasSize(1);
  239. es.lockWrites(TYPE_ISSUE);
  240. IndexingResult result = indexProject("P1", ProjectIndexer.Cause.PROJECT_DELETION);
  241. assertThat(result.getTotal()).isEqualTo(1L);
  242. assertThat(result.getFailures()).isEqualTo(1L);
  243. // index is still read-only, fail to recover
  244. result = recover();
  245. assertThat(result.getTotal()).isEqualTo(1L);
  246. assertThat(result.getFailures()).isEqualTo(1L);
  247. assertThatIndexHasSize(1);
  248. es.unlockWrites(TYPE_ISSUE);
  249. result = recover();
  250. assertThat(result.getTotal()).isEqualTo(1L);
  251. assertThat(result.getFailures()).isEqualTo(0L);
  252. assertThatIndexHasSize(0);
  253. }
  254. @Test
  255. public void commitAndIndexIssues_commits_db_transaction_and_adds_issues_to_index() {
  256. RuleDefinitionDto rule = db.rules().insert();
  257. ComponentDto project = db.components().insertPrivateProject(organization);
  258. ComponentDto file = db.components().insertComponent(newFileDto(project));
  259. // insert issues in db without committing
  260. IssueDto issue1 = IssueTesting.newIssue(rule, project, file);
  261. IssueDto issue2 = IssueTesting.newIssue(rule, project, file);
  262. db.getDbClient().issueDao().insert(db.getSession(), issue1, issue2);
  263. underTest.commitAndIndexIssues(db.getSession(), asList(issue1, issue2));
  264. // issues are persisted and indexed
  265. assertThatIndexHasOnly(issue1, issue2);
  266. assertThatDbHasOnly(issue1, issue2);
  267. assertThatEsQueueTableHasSize(0);
  268. }
  269. @Test
  270. public void commitAndIndexIssues_removes_issue_from_index_if_it_does_not_exist_in_db() {
  271. IssueDto issue1 = new IssueDto().setKee("I1").setProjectUuid("P1");
  272. addIssueToIndex(issue1.getProjectUuid(), issue1.getKey());
  273. IssueDto issue2 = db.issues().insert(organization);
  274. underTest.commitAndIndexIssues(db.getSession(), asList(issue1, issue2));
  275. // issue1 is removed from index, issue2 is persisted and indexed
  276. assertThatIndexHasOnly(issue2);
  277. assertThatDbHasOnly(issue2);
  278. assertThatEsQueueTableHasSize(0);
  279. }
  280. @Test
  281. public void indexing_errors_during_commitAndIndexIssues_are_recovered() {
  282. RuleDefinitionDto rule = db.rules().insert();
  283. ComponentDto project = db.components().insertPrivateProject(organization);
  284. ComponentDto file = db.components().insertComponent(newFileDto(project));
  285. // insert issues in db without committing
  286. IssueDto issue1 = IssueTesting.newIssue(rule, project, file);
  287. IssueDto issue2 = IssueTesting.newIssue(rule, project, file);
  288. db.getDbClient().issueDao().insert(db.getSession(), issue1, issue2);
  289. // index is read-only
  290. es.lockWrites(TYPE_ISSUE);
  291. underTest.commitAndIndexIssues(db.getSession(), asList(issue1, issue2));
  292. // issues are persisted but not indexed
  293. assertThatIndexHasSize(0);
  294. assertThatDbHasOnly(issue1, issue2);
  295. assertThatEsQueueTableHasSize(2);
  296. // re-enable write on index
  297. es.unlockWrites(TYPE_ISSUE);
  298. // emulate the recovery daemon
  299. IndexingResult result = recover();
  300. assertThatEsQueueTableHasSize(0);
  301. assertThatIndexHasOnly(issue1, issue2);
  302. assertThat(result.isSuccess()).isTrue();
  303. assertThat(result.getTotal()).isEqualTo(2L);
  304. }
  305. @Test
  306. public void recovery_does_not_fail_if_unsupported_docIdType() {
  307. EsQueueDto item = EsQueueDto.create(TYPE_ISSUE.format(), "I1", "unknown", "P1");
  308. db.getDbClient().esQueueDao().insert(db.getSession(), item);
  309. db.commit();
  310. recover();
  311. assertThat(logTester.logs(LoggerLevel.ERROR))
  312. .filteredOn(l -> l.contains("Unsupported es_queue.doc_id_type for issues. Manual fix is required: "))
  313. .hasSize(1);
  314. assertThatEsQueueTableHasSize(1);
  315. }
  316. @Test
  317. public void indexing_recovers_multiple_errors_on_the_same_issue() {
  318. es.lockWrites(TYPE_ISSUE);
  319. IssueDto issue = db.issues().insert(organization);
  320. // three changes on the same issue
  321. underTest.commitAndIndexIssues(db.getSession(), asList(issue));
  322. underTest.commitAndIndexIssues(db.getSession(), asList(issue));
  323. underTest.commitAndIndexIssues(db.getSession(), asList(issue));
  324. assertThatIndexHasSize(0);
  325. // three attempts of indexing are stored in es_queue recovery table
  326. assertThatEsQueueTableHasSize(3);
  327. es.unlockWrites(TYPE_ISSUE);
  328. recover();
  329. assertThatIndexHasOnly(issue);
  330. assertThatEsQueueTableHasSize(0);
  331. }
  332. @Test
  333. public void indexing_recovers_multiple_errors_on_the_same_project() {
  334. RuleDefinitionDto rule = db.rules().insert();
  335. ComponentDto project = db.components().insertPrivateProject(organization);
  336. ComponentDto file = db.components().insertComponent(newFileDto(project));
  337. IssueDto issue1 = db.issues().insert(rule, project, file);
  338. IssueDto issue2 = db.issues().insert(rule, project, file);
  339. es.lockWrites(TYPE_ISSUE);
  340. IndexingResult result = indexProject(project.uuid(), ProjectIndexer.Cause.PROJECT_DELETION);
  341. assertThat(result.getTotal()).isEqualTo(2L);
  342. assertThat(result.getFailures()).isEqualTo(2L);
  343. // index is still read-only, fail to recover
  344. result = recover();
  345. assertThat(result.getTotal()).isEqualTo(2L);
  346. assertThat(result.getFailures()).isEqualTo(2L);
  347. assertThatIndexHasSize(0);
  348. es.unlockWrites(TYPE_ISSUE);
  349. result = recover();
  350. assertThat(result.getTotal()).isEqualTo(2L);
  351. assertThat(result.getFailures()).isEqualTo(0L);
  352. assertThatIndexHasSize(2);
  353. assertThatEsQueueTableHasSize(0);
  354. }
  355. private IndexingResult indexProject(String projectUuid, ProjectIndexer.Cause cause) {
  356. Collection<EsQueueDto> items = underTest.prepareForRecovery(db.getSession(), asList(projectUuid), cause);
  357. db.commit();
  358. return underTest.index(db.getSession(), items);
  359. }
  360. @Test
  361. public void deleteByKeys_deletes_docs_by_keys() {
  362. addIssueToIndex("P1", "Issue1");
  363. addIssueToIndex("P1", "Issue2");
  364. addIssueToIndex("P1", "Issue3");
  365. addIssueToIndex("P2", "Issue4");
  366. assertThatIndexHasOnly("Issue1", "Issue2", "Issue3", "Issue4");
  367. underTest.deleteByKeys("P1", asList("Issue1", "Issue2"));
  368. assertThatIndexHasOnly("Issue3", "Issue4");
  369. }
  370. @Test
  371. public void deleteByKeys_does_not_recover_from_errors() {
  372. addIssueToIndex("P1", "Issue1");
  373. es.lockWrites(TYPE_ISSUE);
  374. try {
  375. // FIXME : test also message
  376. expectedException.expect(IllegalStateException.class);
  377. underTest.deleteByKeys("P1", asList("Issue1"));
  378. } finally {
  379. assertThatIndexHasOnly("Issue1");
  380. assertThatEsQueueTableHasSize(0);
  381. es.unlockWrites(TYPE_ISSUE);
  382. }
  383. }
  384. @Test
  385. public void nothing_to_do_when_delete_issues_on_empty_list() {
  386. addIssueToIndex("P1", "Issue1");
  387. addIssueToIndex("P1", "Issue2");
  388. addIssueToIndex("P1", "Issue3");
  389. underTest.deleteByKeys("P1", emptyList());
  390. assertThatIndexHasOnly("Issue1", "Issue2", "Issue3");
  391. }
  392. /**
  393. * This is a technical constraint, to ensure, that the indexers can be called in any order, during startup.
  394. */
  395. @Test
  396. public void parent_child_relationship_does_not_require_ordering_of_index_requests() {
  397. IssueDoc issueDoc = new IssueDoc();
  398. issueDoc.setKey("key");
  399. issueDoc.setProjectUuid("parent-does-not-exist");
  400. new IssueIndexer(es.client(), db.getDbClient(), new IssueIteratorFactory(db.getDbClient()))
  401. .index(asList(issueDoc).iterator());
  402. assertThat(es.countDocuments(TYPE_ISSUE)).isEqualTo(1L);
  403. }
  404. @Test
  405. public void index_issue_in_non_main_branch() {
  406. RuleDefinitionDto rule = db.rules().insert();
  407. ComponentDto project = db.components().insertPrivateProject(organization);
  408. ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setKey("feature/foo"));
  409. ComponentDto dir = db.components().insertComponent(ComponentTesting.newDirectory(branch, "src/main/java/foo"));
  410. ComponentDto file = db.components().insertComponent(newFileDto(branch, dir, "F1"));
  411. IssueDto issue = db.issues().insert(rule, branch, file);
  412. underTest.indexOnStartup(emptySet());
  413. IssueDoc doc = es.getDocuments(TYPE_ISSUE, IssueDoc.class).get(0);
  414. assertThat(doc.getId()).isEqualTo(issue.getKey());
  415. assertThat(doc.organizationUuid()).isEqualTo(organization.getUuid());
  416. assertThat(doc.componentUuid()).isEqualTo(file.uuid());
  417. assertThat(doc.projectUuid()).isEqualTo(branch.getMainBranchProjectUuid());
  418. assertThat(doc.branchUuid()).isEqualTo(branch.uuid());
  419. assertThat(doc.isMainBranch()).isFalse();
  420. }
  421. private void addIssueToIndex(String projectUuid, String issueKey) {
  422. es.putDocuments(TYPE_ISSUE,
  423. newDoc().setKey(issueKey).setProjectUuid(projectUuid));
  424. }
  425. private void assertThatIndexHasSize(long expectedSize) {
  426. assertThat(es.countDocuments(TYPE_ISSUE)).isEqualTo(expectedSize);
  427. }
  428. private void assertThatIndexHasOnly(IssueDto... expectedIssues) {
  429. assertThat(es.getDocuments(TYPE_ISSUE))
  430. .extracting(SearchHit::getId)
  431. .containsExactlyInAnyOrder(Arrays.stream(expectedIssues).map(IssueDto::getKey).toArray(String[]::new));
  432. }
  433. private void assertThatIndexHasOnly(String... expectedKeys) {
  434. List<IssueDoc> issues = es.getDocuments(TYPE_ISSUE, IssueDoc.class);
  435. assertThat(issues).extracting(IssueDoc::key).containsOnly(expectedKeys);
  436. }
  437. private void assertThatEsQueueTableHasSize(int expectedSize) {
  438. assertThat(db.countRowsOfTable("es_queue")).isEqualTo(expectedSize);
  439. }
  440. private void assertThatDbHasOnly(IssueDto... expectedIssues) {
  441. try (DbSession otherSession = db.getDbClient().openSession(false)) {
  442. List<String> keys = Arrays.stream(expectedIssues).map(IssueDto::getKey).collect(Collectors.toList());
  443. assertThat(db.getDbClient().issueDao().selectByKeys(otherSession, keys)).hasSize(expectedIssues.length);
  444. }
  445. }
  446. private IndexingResult recover() {
  447. Collection<EsQueueDto> items = db.getDbClient().esQueueDao().selectForRecovery(db.getSession(), System.currentTimeMillis() + 1_000L, 10);
  448. return underTest.index(db.getSession(), items);
  449. }
  450. }