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.

PostProjectAnalysisTasksExecutorTest.java 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2019 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.ce.task.projectanalysis.api.posttask;
  21. import com.google.common.collect.ImmutableMap;
  22. import com.tngtech.java.junit.dataprovider.DataProvider;
  23. import com.tngtech.java.junit.dataprovider.DataProviderRunner;
  24. import com.tngtech.java.junit.dataprovider.UseDataProvider;
  25. import java.util.Date;
  26. import java.util.HashMap;
  27. import java.util.List;
  28. import java.util.Map;
  29. import java.util.Random;
  30. import javax.annotation.Nullable;
  31. import org.apache.commons.lang.RandomStringUtils;
  32. import org.junit.Before;
  33. import org.junit.Rule;
  34. import org.junit.Test;
  35. import org.junit.runner.RunWith;
  36. import org.mockito.ArgumentCaptor;
  37. import org.mockito.InOrder;
  38. import org.sonar.api.ce.posttask.PostProjectAnalysisTask;
  39. import org.sonar.api.ce.posttask.Project;
  40. import org.sonar.api.utils.System2;
  41. import org.sonar.api.utils.log.LogTester;
  42. import org.sonar.api.utils.log.LoggerLevel;
  43. import org.sonar.ce.task.CeTask;
  44. import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
  45. import org.sonar.ce.task.projectanalysis.analysis.Branch;
  46. import org.sonar.ce.task.projectanalysis.analysis.Organization;
  47. import org.sonar.ce.task.projectanalysis.batch.BatchReportReaderRule;
  48. import org.sonar.ce.task.projectanalysis.metric.Metric;
  49. import org.sonar.ce.task.projectanalysis.qualitygate.Condition;
  50. import org.sonar.ce.task.projectanalysis.qualitygate.ConditionStatus;
  51. import org.sonar.ce.task.projectanalysis.qualitygate.MutableQualityGateHolderRule;
  52. import org.sonar.ce.task.projectanalysis.qualitygate.MutableQualityGateStatusHolderRule;
  53. import org.sonar.ce.task.projectanalysis.qualitygate.QualityGate;
  54. import org.sonar.ce.task.projectanalysis.qualitygate.QualityGateStatus;
  55. import org.sonar.db.component.BranchType;
  56. import org.sonar.db.organization.OrganizationDto;
  57. import org.sonar.scanner.protocol.output.ScannerReport;
  58. import static com.google.common.collect.ImmutableList.of;
  59. import static java.util.Arrays.asList;
  60. import static java.util.stream.Collectors.toList;
  61. import static org.assertj.core.api.Assertions.assertThat;
  62. import static org.assertj.core.api.ThrowableAssert.catchThrowable;
  63. import static org.assertj.core.data.MapEntry.entry;
  64. import static org.mockito.ArgumentMatchers.any;
  65. import static org.mockito.Mockito.doAnswer;
  66. import static org.mockito.Mockito.doThrow;
  67. import static org.mockito.Mockito.inOrder;
  68. import static org.mockito.Mockito.mock;
  69. import static org.mockito.Mockito.verify;
  70. import static org.mockito.Mockito.when;
  71. @RunWith(DataProviderRunner.class)
  72. public class PostProjectAnalysisTasksExecutorTest {
  73. private static final long QUALITY_GATE_ID = 98451;
  74. private static final String QUALITY_GATE_NAME = "qualityGate name";
  75. private static final Condition CONDITION_1 = createCondition("metric key 1");
  76. private static final Condition CONDITION_2 = createCondition("metric key 2");
  77. @Rule
  78. public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
  79. @Rule
  80. public MutableQualityGateHolderRule qualityGateHolder = new MutableQualityGateHolderRule();
  81. @Rule
  82. public MutableQualityGateStatusHolderRule qualityGateStatusHolder = new MutableQualityGateStatusHolderRule();
  83. @Rule
  84. public BatchReportReaderRule reportReader = new BatchReportReaderRule();
  85. @Rule
  86. public LogTester logTester = new LogTester();
  87. private String organizationUuid = "org1";
  88. private String organizationKey = organizationUuid + "_key";
  89. private String organizationName = organizationUuid + "_name";
  90. private System2 system2 = mock(System2.class);
  91. private ArgumentCaptor<PostProjectAnalysisTask.Context> taskContextCaptor = ArgumentCaptor.forClass(PostProjectAnalysisTask.Context.class);
  92. private CeTask.Component component = new CeTask.Component("component uuid", "component key", "component name");
  93. private CeTask ceTask = new CeTask.Builder()
  94. .setOrganizationUuid(organizationUuid)
  95. .setType("type")
  96. .setUuid("uuid")
  97. .setComponent(component)
  98. .setMainComponent(component)
  99. .build();
  100. private PostProjectAnalysisTask postProjectAnalysisTask = newPostProjectAnalysisTask("PT1");
  101. private PostProjectAnalysisTasksExecutor underTest = new PostProjectAnalysisTasksExecutor(
  102. ceTask, analysisMetadataHolder, qualityGateHolder, qualityGateStatusHolder,
  103. reportReader, system2,
  104. new PostProjectAnalysisTask[] {postProjectAnalysisTask});
  105. @Before
  106. public void setUp() throws Exception {
  107. qualityGateHolder.setQualityGate(new QualityGate(QUALITY_GATE_ID, QUALITY_GATE_NAME, of(CONDITION_1, CONDITION_2)));
  108. qualityGateStatusHolder.setStatus(QualityGateStatus.OK, ImmutableMap.of(
  109. CONDITION_1, ConditionStatus.create(ConditionStatus.EvaluationStatus.OK, "value"),
  110. CONDITION_2, ConditionStatus.NO_VALUE_STATUS));
  111. Branch branch = mock(Branch.class);
  112. when(branch.getType()).thenReturn(BranchType.LONG);
  113. analysisMetadataHolder
  114. .setBranch(branch)
  115. .setOrganizationsEnabled(new Random().nextBoolean())
  116. .setOrganization(Organization.from(
  117. new OrganizationDto().setKey(organizationKey).setName(organizationName).setUuid(organizationUuid).setDefaultQualityGateUuid("foo")));
  118. reportReader.setMetadata(ScannerReport.Metadata.newBuilder().build());
  119. }
  120. @Test
  121. @UseDataProvider("booleanValues")
  122. public void does_not_fail_when_there_is_no_PostProjectAnalysisTasksExecutor(boolean allStepsExecuted) {
  123. new PostProjectAnalysisTasksExecutor(ceTask, analysisMetadataHolder, qualityGateHolder, qualityGateStatusHolder, reportReader, system2)
  124. .finished(allStepsExecuted);
  125. }
  126. @Test
  127. @UseDataProvider("booleanValues")
  128. public void finished_calls_all_PostProjectAnalysisTask_in_order_of_the_array_and_passes_the_same_object_to_all(boolean allStepsExecuted) {
  129. PostProjectAnalysisTask postProjectAnalysisTask1 = newPostProjectAnalysisTask("PT1");
  130. PostProjectAnalysisTask postProjectAnalysisTask2 = newPostProjectAnalysisTask("PT2");
  131. InOrder inOrder = inOrder(postProjectAnalysisTask1, postProjectAnalysisTask2);
  132. new PostProjectAnalysisTasksExecutor(
  133. ceTask, analysisMetadataHolder, qualityGateHolder, qualityGateStatusHolder, reportReader,
  134. system2, new PostProjectAnalysisTask[] {postProjectAnalysisTask1, postProjectAnalysisTask2})
  135. .finished(allStepsExecuted);
  136. inOrder.verify(postProjectAnalysisTask1).finished(taskContextCaptor.capture());
  137. inOrder.verify(postProjectAnalysisTask1).getDescription();
  138. inOrder.verify(postProjectAnalysisTask2).finished(taskContextCaptor.capture());
  139. inOrder.verify(postProjectAnalysisTask2).getDescription();
  140. inOrder.verifyNoMoreInteractions();
  141. ArgumentCaptor<PostProjectAnalysisTask.Context> taskContextCaptor = this.taskContextCaptor;
  142. List<PostProjectAnalysisTask.ProjectAnalysis> allValues = getAllProjectAnalyses(taskContextCaptor);
  143. assertThat(allValues).hasSize(2);
  144. assertThat(allValues.get(0)).isSameAs(allValues.get(1));
  145. assertThat(logTester.logs()).hasSize(2);
  146. List<String> logs = logTester.logs(LoggerLevel.INFO);
  147. assertThat(logs).hasSize(2);
  148. assertThat(logs.get(0)).matches("^PT1 \\| status=SUCCESS \\| time=\\d+ms$");
  149. assertThat(logs.get(1)).matches("^PT2 \\| status=SUCCESS \\| time=\\d+ms$");
  150. }
  151. @Test
  152. @UseDataProvider("booleanValues")
  153. public void organization_is_null_when_organization_are_disabled(boolean allStepsExecuted) {
  154. analysisMetadataHolder
  155. .setOrganizationsEnabled(false)
  156. .setOrganization(Organization.from(
  157. new OrganizationDto().setKey(organizationKey).setName(organizationName).setUuid(organizationUuid).setDefaultQualityGateUuid("foo")));
  158. underTest.finished(allStepsExecuted);
  159. verify(postProjectAnalysisTask).finished(taskContextCaptor.capture());
  160. assertThat(taskContextCaptor.getValue().getProjectAnalysis().getOrganization()).isEmpty();
  161. }
  162. @Test
  163. @UseDataProvider("booleanValues")
  164. public void organization_is_not_null_when_organization_are_enabled(boolean allStepsExecuted) {
  165. analysisMetadataHolder
  166. .setOrganizationsEnabled(true)
  167. .setOrganization(Organization.from(
  168. new OrganizationDto().setKey(organizationKey).setName(organizationName).setUuid(organizationUuid).setDefaultQualityGateUuid("foo")));
  169. underTest.finished(allStepsExecuted);
  170. verify(postProjectAnalysisTask).finished(taskContextCaptor.capture());
  171. org.sonar.api.ce.posttask.Organization organization = taskContextCaptor.getValue().getProjectAnalysis().getOrganization().get();
  172. assertThat(organization.getKey()).isEqualTo(organizationKey);
  173. assertThat(organization.getName()).isEqualTo(organizationName);
  174. }
  175. @Test
  176. @UseDataProvider("booleanValues")
  177. public void CeTask_status_depends_on_finished_method_argument_is_true_or_false(boolean allStepsExecuted) {
  178. underTest.finished(allStepsExecuted);
  179. verify(postProjectAnalysisTask).finished(taskContextCaptor.capture());
  180. assertThat(taskContextCaptor.getValue().getProjectAnalysis().getCeTask().getStatus())
  181. .isEqualTo(
  182. allStepsExecuted ? org.sonar.api.ce.posttask.CeTask.Status.SUCCESS : org.sonar.api.ce.posttask.CeTask.Status.FAILED);
  183. }
  184. @Test
  185. public void ceTask_uuid_is_UUID_of_CeTask() {
  186. underTest.finished(true);
  187. verify(postProjectAnalysisTask).finished(taskContextCaptor.capture());
  188. assertThat(taskContextCaptor.getValue().getProjectAnalysis().getCeTask().getId())
  189. .isEqualTo(ceTask.getUuid());
  190. }
  191. @Test
  192. public void project_uuid_key_and_name_come_from_CeTask() {
  193. underTest.finished(true);
  194. verify(postProjectAnalysisTask).finished(taskContextCaptor.capture());
  195. Project project = taskContextCaptor.getValue().getProjectAnalysis().getProject();
  196. assertThat(project.getUuid()).isEqualTo(ceTask.getComponent().get().getUuid());
  197. assertThat(project.getKey()).isEqualTo(ceTask.getComponent().get().getKey().get());
  198. assertThat(project.getName()).isEqualTo(ceTask.getComponent().get().getName().get());
  199. }
  200. @Test
  201. public void date_comes_from_AnalysisMetadataHolder() {
  202. analysisMetadataHolder.setAnalysisDate(8_465_132_498L);
  203. analysisMetadataHolder.setUuid(RandomStringUtils.randomAlphanumeric(40));
  204. underTest.finished(true);
  205. verify(postProjectAnalysisTask).finished(taskContextCaptor.capture());
  206. assertThat(taskContextCaptor.getValue().getProjectAnalysis().getDate())
  207. .isEqualTo(new Date(analysisMetadataHolder.getAnalysisDate()));
  208. }
  209. @Test
  210. public void date_comes_from_system2_if_not_set_in_AnalysisMetadataHolder() {
  211. long now = 1_999_663L;
  212. when(system2.now()).thenReturn(now);
  213. underTest.finished(false);
  214. verify(postProjectAnalysisTask).finished(taskContextCaptor.capture());
  215. assertThat(taskContextCaptor.getValue().getProjectAnalysis().getDate()).isEqualTo(new Date(now));
  216. }
  217. @Test
  218. public void analysisDate_and_analysisUuid_comes_from_AnalysisMetadataHolder_when_set() {
  219. analysisMetadataHolder.setAnalysisDate(8465132498L);
  220. analysisMetadataHolder.setUuid(RandomStringUtils.randomAlphanumeric(40));
  221. underTest.finished(true);
  222. verify(postProjectAnalysisTask).finished(taskContextCaptor.capture());
  223. assertThat(taskContextCaptor.getValue().getProjectAnalysis().getAnalysis().get().getDate())
  224. .isEqualTo(new Date(analysisMetadataHolder.getAnalysisDate()));
  225. assertThat(taskContextCaptor.getValue().getProjectAnalysis().getAnalysis().get().getAnalysisUuid())
  226. .isEqualTo(analysisMetadataHolder.getUuid());
  227. }
  228. @Test
  229. public void analysis_is_empty_when_not_set_in_AnalysisMetadataHolder() {
  230. underTest.finished(false);
  231. verify(postProjectAnalysisTask).finished(taskContextCaptor.capture());
  232. assertThat(taskContextCaptor.getValue().getProjectAnalysis().getAnalysis()).isEmpty();
  233. }
  234. @Test
  235. public void branch_comes_from_AnalysisMetadataHolder_when_set() {
  236. analysisMetadataHolder.setBranch(new Branch() {
  237. @Override
  238. public BranchType getType() {
  239. return BranchType.SHORT;
  240. }
  241. @Override
  242. public boolean isMain() {
  243. return false;
  244. }
  245. @Override
  246. public String getMergeBranchUuid() {
  247. throw new UnsupportedOperationException();
  248. }
  249. @Override
  250. public String getName() {
  251. return "feature/foo";
  252. }
  253. @Override
  254. public boolean supportsCrossProjectCpd() {
  255. throw new UnsupportedOperationException();
  256. }
  257. @Override
  258. public String getPullRequestKey() {
  259. throw new UnsupportedOperationException();
  260. }
  261. @Override
  262. public String getTargetBranchName() {
  263. throw new UnsupportedOperationException();
  264. }
  265. @Override
  266. public String generateKey(String projectKey, @Nullable String fileOrDirPath) {
  267. throw new UnsupportedOperationException();
  268. }
  269. });
  270. underTest.finished(true);
  271. verify(postProjectAnalysisTask).finished(taskContextCaptor.capture());
  272. org.sonar.api.ce.posttask.Branch branch = taskContextCaptor.getValue().getProjectAnalysis().getBranch().get();
  273. assertThat(branch.isMain()).isFalse();
  274. assertThat(branch.getName()).hasValue("feature/foo");
  275. assertThat(branch.getType()).isEqualTo(BranchImpl.Type.SHORT);
  276. }
  277. @Test
  278. public void qualityGate_is_null_when_finished_method_argument_is_false() {
  279. underTest.finished(false);
  280. verify(postProjectAnalysisTask).finished(taskContextCaptor.capture());
  281. assertThat(taskContextCaptor.getValue().getProjectAnalysis().getQualityGate()).isNull();
  282. }
  283. @Test
  284. public void qualityGate_is_populated_when_finished_method_argument_is_true() {
  285. underTest.finished(true);
  286. verify(postProjectAnalysisTask).finished(taskContextCaptor.capture());
  287. org.sonar.api.ce.posttask.QualityGate qualityGate = taskContextCaptor.getValue().getProjectAnalysis().getQualityGate();
  288. assertThat(qualityGate.getStatus()).isEqualTo(org.sonar.api.ce.posttask.QualityGate.Status.OK);
  289. assertThat(qualityGate.getId()).isEqualTo(String.valueOf(QUALITY_GATE_ID));
  290. assertThat(qualityGate.getName()).isEqualTo(QUALITY_GATE_NAME);
  291. assertThat(qualityGate.getConditions()).hasSize(2);
  292. }
  293. @Test
  294. public void scannerContext_loads_properties_from_scanner_report() {
  295. reportReader.putContextProperties(asList(ScannerReport.ContextProperty.newBuilder().setKey("foo").setValue("bar").build()));
  296. underTest.finished(true);
  297. verify(postProjectAnalysisTask).finished(taskContextCaptor.capture());
  298. org.sonar.api.ce.posttask.ScannerContext scannerContext = taskContextCaptor.getValue().getProjectAnalysis().getScannerContext();
  299. assertThat(scannerContext.getProperties()).containsExactly(entry("foo", "bar"));
  300. }
  301. @Test
  302. @UseDataProvider("booleanValues")
  303. public void logStatistics_add_fails_when_NPE_if_key_or_value_is_null(boolean allStepsExecuted) {
  304. underTest.finished(allStepsExecuted);
  305. verify(postProjectAnalysisTask).finished(taskContextCaptor.capture());
  306. PostProjectAnalysisTask.LogStatistics logStatistics = taskContextCaptor.getValue().getLogStatistics();
  307. assertThat(catchThrowable(() -> logStatistics.add(null, "foo")))
  308. .isInstanceOf(NullPointerException.class)
  309. .hasMessage("Statistic has null key");
  310. assertThat(catchThrowable(() -> logStatistics.add(null, null)))
  311. .isInstanceOf(NullPointerException.class)
  312. .hasMessage("Statistic has null key");
  313. assertThat(catchThrowable(() -> logStatistics.add("bar", null)))
  314. .isInstanceOf(NullPointerException.class)
  315. .hasMessage("Statistic with key [bar] has null value");
  316. }
  317. @Test
  318. @UseDataProvider("booleanValues")
  319. public void logStatistics_add_fails_with_IAE_if_key_is_time_or_status_ignoring_case(boolean allStepsExecuted) {
  320. underTest.finished(allStepsExecuted);
  321. verify(postProjectAnalysisTask).finished(taskContextCaptor.capture());
  322. PostProjectAnalysisTask.LogStatistics logStatistics = taskContextCaptor.getValue().getLogStatistics();
  323. for (String reservedKey : asList("time", "TIME", "TImE", "status", "STATUS", "STaTuS")) {
  324. assertThat(catchThrowable(() -> logStatistics.add(reservedKey, "foo")))
  325. .isInstanceOf(IllegalArgumentException.class)
  326. .hasMessage("Statistic with key [" + reservedKey + "] is not accepted");
  327. }
  328. }
  329. @Test
  330. @UseDataProvider("booleanValues")
  331. public void logStatistics_add_fails_with_IAE_if_same_key_with_exact_case_added_twice(boolean allStepsExecuted) {
  332. underTest.finished(allStepsExecuted);
  333. verify(postProjectAnalysisTask).finished(taskContextCaptor.capture());
  334. PostProjectAnalysisTask.LogStatistics logStatistics = taskContextCaptor.getValue().getLogStatistics();
  335. String key = RandomStringUtils.randomAlphabetic(10);
  336. logStatistics.add(key, new Object());
  337. assertThat(catchThrowable(() -> logStatistics.add(key, "bar")))
  338. .isInstanceOf(IllegalArgumentException.class)
  339. .hasMessage("Statistic with key [" + key + "] is already present");
  340. }
  341. @Test
  342. @UseDataProvider("booleanValues")
  343. public void logStatistics_adds_statistics_to_end_of_task_log(boolean allStepsExecuted) {
  344. Map<String, Object> stats = new HashMap<>();
  345. for (int i = 0; i <= new Random().nextInt(10); i++) {
  346. stats.put("statKey_" + i, "statVal_" + i);
  347. }
  348. PostProjectAnalysisTask logStatisticsTask = mock(PostProjectAnalysisTask.class);
  349. when(logStatisticsTask.getDescription()).thenReturn("PT1");
  350. doAnswer(i -> {
  351. PostProjectAnalysisTask.Context context = i.getArgument(0);
  352. stats.forEach((k, v) -> context.getLogStatistics().add(k, v));
  353. return null;
  354. }).when(logStatisticsTask)
  355. .finished(any(PostProjectAnalysisTask.Context.class));
  356. new PostProjectAnalysisTasksExecutor(
  357. ceTask, analysisMetadataHolder, qualityGateHolder, qualityGateStatusHolder, reportReader,
  358. system2, new PostProjectAnalysisTask[] {logStatisticsTask})
  359. .finished(allStepsExecuted);
  360. verify(logStatisticsTask).finished(taskContextCaptor.capture());
  361. assertThat(logTester.logs()).hasSize(1);
  362. List<String> logs = logTester.logs(LoggerLevel.INFO);
  363. assertThat(logs).hasSize(1);
  364. StringBuilder expectedLog = new StringBuilder("^PT1 ");
  365. stats.forEach((k, v) -> expectedLog.append("\\| " + k + "=" + v + " "));
  366. expectedLog.append("\\| status=SUCCESS \\| time=\\d+ms$");
  367. assertThat(logs.get(0)).matches(expectedLog.toString());
  368. }
  369. @Test
  370. @UseDataProvider("booleanValues")
  371. public void finished_does_not_fail_if_listener_throws_exception_and_execute_subsequent_listeners(boolean allStepsExecuted) {
  372. PostProjectAnalysisTask postProjectAnalysisTask1 = newPostProjectAnalysisTask("PT1");
  373. PostProjectAnalysisTask postProjectAnalysisTask2 = newPostProjectAnalysisTask("PT2");
  374. PostProjectAnalysisTask postProjectAnalysisTask3 = newPostProjectAnalysisTask("PT3");
  375. InOrder inOrder = inOrder(postProjectAnalysisTask1, postProjectAnalysisTask2, postProjectAnalysisTask3);
  376. doThrow(new RuntimeException("Faking a listener throws an exception"))
  377. .when(postProjectAnalysisTask2)
  378. .finished(any(PostProjectAnalysisTask.Context.class));
  379. new PostProjectAnalysisTasksExecutor(
  380. ceTask, analysisMetadataHolder, qualityGateHolder, qualityGateStatusHolder, reportReader,
  381. system2, new PostProjectAnalysisTask[] {postProjectAnalysisTask1, postProjectAnalysisTask2, postProjectAnalysisTask3})
  382. .finished(allStepsExecuted);
  383. inOrder.verify(postProjectAnalysisTask1).finished(taskContextCaptor.capture());
  384. inOrder.verify(postProjectAnalysisTask1).getDescription();
  385. inOrder.verify(postProjectAnalysisTask2).finished(taskContextCaptor.capture());
  386. inOrder.verify(postProjectAnalysisTask2).getDescription();
  387. inOrder.verify(postProjectAnalysisTask3).finished(taskContextCaptor.capture());
  388. inOrder.verify(postProjectAnalysisTask3).getDescription();
  389. inOrder.verifyNoMoreInteractions();
  390. assertThat(logTester.logs()).hasSize(4);
  391. List<String> logs = logTester.logs(LoggerLevel.INFO);
  392. assertThat(logs).hasSize(3);
  393. assertThat(logs.get(0)).matches("^PT1 \\| status=SUCCESS \\| time=\\d+ms$");
  394. assertThat(logs.get(1)).matches("^PT2 \\| status=FAILED \\| time=\\d+ms$");
  395. assertThat(logs.get(2)).matches("^PT3 \\| status=SUCCESS \\| time=\\d+ms$");
  396. }
  397. @DataProvider
  398. public static Object[][] booleanValues() {
  399. return new Object[][] {
  400. {true},
  401. {false}
  402. };
  403. }
  404. private static Condition createCondition(String metricKey) {
  405. Metric metric = mock(Metric.class);
  406. when(metric.getKey()).thenReturn(metricKey);
  407. return new Condition(metric, Condition.Operator.LESS_THAN.getDbValue(), "error threshold");
  408. }
  409. private static PostProjectAnalysisTask newPostProjectAnalysisTask(String description) {
  410. PostProjectAnalysisTask res = mock(PostProjectAnalysisTask.class);
  411. when(res.getDescription()).thenReturn(description);
  412. doAnswer(i -> null).when(res).finished(any(PostProjectAnalysisTask.Context.class));
  413. return res;
  414. }
  415. private static List<PostProjectAnalysisTask.ProjectAnalysis> getAllProjectAnalyses(ArgumentCaptor<PostProjectAnalysisTask.Context> taskContextCaptor) {
  416. return taskContextCaptor.getAllValues()
  417. .stream()
  418. .map(PostProjectAnalysisTask.Context::getProjectAnalysis)
  419. .collect(toList());
  420. }
  421. }