3 * Copyright (C) 2009-2024 SonarSource SA
4 * mailto:info AT sonarsource DOT com
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.
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.
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.
20 package org.sonar.ce.task.projectanalysis.step;
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.time.ZoneId;
26 import java.time.ZonedDateTime;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.List;
30 import java.util.Optional;
31 import java.util.Random;
32 import java.util.stream.Stream;
33 import javax.annotation.Nullable;
34 import org.junit.Before;
35 import org.junit.Rule;
36 import org.junit.Test;
37 import org.junit.runner.RunWith;
38 import org.slf4j.event.Level;
39 import org.sonar.api.testfixtures.log.LogTester;
40 import org.sonar.api.utils.MessageException;
41 import org.sonar.api.utils.System2;
42 import org.sonar.ce.task.log.CeTaskMessages;
43 import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder;
44 import org.sonar.ce.task.projectanalysis.component.Component;
45 import org.sonar.ce.task.projectanalysis.component.ReportComponent;
46 import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule;
47 import org.sonar.ce.task.projectanalysis.period.NewCodePeriodResolver;
48 import org.sonar.ce.task.projectanalysis.period.Period;
49 import org.sonar.ce.task.projectanalysis.period.PeriodHolderImpl;
50 import org.sonar.ce.task.step.ComputationStep;
51 import org.sonar.ce.task.step.TestComputationStepContext;
52 import org.sonar.core.util.SequenceUuidFactory;
53 import org.sonar.db.DbTester;
54 import org.sonar.db.component.ComponentDto;
55 import org.sonar.db.component.SnapshotDto;
56 import org.sonar.db.event.EventTesting;
57 import org.sonar.db.newcodeperiod.NewCodePeriodDao;
58 import org.sonar.db.newcodeperiod.NewCodePeriodType;
59 import org.sonar.server.project.Project;
61 import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
62 import static org.assertj.core.api.Assertions.assertThat;
63 import static org.assertj.core.api.Assertions.assertThatThrownBy;
64 import static org.assertj.core.api.Assertions.fail;
65 import static org.mockito.ArgumentMatchers.any;
66 import static org.mockito.Mockito.mock;
67 import static org.mockito.Mockito.verify;
68 import static org.mockito.Mockito.verifyNoInteractions;
69 import static org.mockito.Mockito.verifyNoMoreInteractions;
70 import static org.mockito.Mockito.when;
71 import static org.sonar.db.component.SnapshotDto.STATUS_PROCESSED;
72 import static org.sonar.db.component.SnapshotDto.STATUS_UNPROCESSED;
73 import static org.sonar.db.event.EventDto.CATEGORY_VERSION;
74 import static org.sonar.db.event.EventTesting.newEvent;
76 @RunWith(DataProviderRunner.class)
77 public class LoadPeriodsStepIT extends BaseStepTest {
79 public DbTester dbTester = DbTester.create(System2.INSTANCE);
81 public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
83 public LogTester logTester = new LogTester();
85 private final AnalysisMetadataHolder analysisMetadataHolder = mock(AnalysisMetadataHolder.class);
86 private final PeriodHolderImpl periodsHolder = new PeriodHolderImpl();
87 private final System2 system2Mock = mock(System2.class);
88 private final NewCodePeriodDao dao = new NewCodePeriodDao(system2Mock, new SequenceUuidFactory());
89 private final NewCodePeriodResolver newCodePeriodResolver = new NewCodePeriodResolver(dbTester.getDbClient(), analysisMetadataHolder);
90 private final ZonedDateTime analysisDate = ZonedDateTime.of(2019, 3, 20, 5, 30, 40, 0, ZoneId.systemDefault());
91 private final CeTaskMessages ceTaskMessages = mock(CeTaskMessages.class);
92 private final LoadPeriodsStep underTest = new LoadPeriodsStep(analysisMetadataHolder, dao, treeRootHolder, periodsHolder, dbTester.getDbClient(), newCodePeriodResolver,
93 ceTaskMessages, system2Mock);
95 private ComponentDto project;
98 protected ComputationStep step() {
103 public void setUp() {
104 logTester.setLevel(Level.TRACE);
105 project = dbTester.components().insertPublicProject().getMainBranchComponent();
107 when(analysisMetadataHolder.isBranch()).thenReturn(true);
108 when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false);
109 when(analysisMetadataHolder.getAnalysisDate()).thenReturn(analysisDate.toInstant().toEpochMilli());
113 public void no_period_on_first_analysis() {
116 when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(true);
117 underTest.execute(new TestComputationStepContext());
119 verify(analysisMetadataHolder).isFirstAnalysis();
120 verify(analysisMetadataHolder).isBranch();
121 verify(analysisMetadataHolder).getProject();
122 verify(analysisMetadataHolder).getNewCodeReferenceBranch();
123 assertThat(periodsHolder.hasPeriod()).isFalse();
124 verifyNoMoreInteractions(analysisMetadataHolder);
128 public void no_period_date_if_not_branch() {
129 when(analysisMetadataHolder.isBranch()).thenReturn(false);
130 underTest.execute(new TestComputationStepContext());
132 verify(analysisMetadataHolder).isBranch();
133 assertThat(periodsHolder.hasPeriod()).isFalse();
134 verifyNoMoreInteractions(analysisMetadataHolder);
138 public void load_default_if_nothing_defined() {
141 SnapshotDto analysis = dbTester.components().insertSnapshot(project,
142 snapshot -> snapshot.setCreatedAt(milisSinceEpoch(2019, 3, 15, 0)));
144 underTest.execute(new TestComputationStepContext());
146 assertPeriod(NewCodePeriodType.PREVIOUS_VERSION, null, analysis.getCreatedAt());
147 verifyDebugLogs("Resolving first analysis as new code period as there is only one existing version");
151 public void load_number_of_days_global() {
152 setGlobalPeriod(NewCodePeriodType.NUMBER_OF_DAYS, "10");
154 testNumberOfDays(project);
158 public void load_number_of_days_on_project() {
159 setGlobalPeriod(NewCodePeriodType.PREVIOUS_VERSION, null);
160 setProjectPeriod(project.uuid(), NewCodePeriodType.NUMBER_OF_DAYS, "10");
162 testNumberOfDays(project);
166 public void load_number_of_days_on_branch() {
167 ComponentDto branch = dbTester.components().insertProjectBranch(project);
169 setGlobalPeriod(NewCodePeriodType.PREVIOUS_VERSION, null);
170 setProjectPeriod(project.uuid(), NewCodePeriodType.PREVIOUS_VERSION, null);
171 setBranchPeriod(project.uuid(), branch.uuid(), NewCodePeriodType.NUMBER_OF_DAYS, "10");
173 testNumberOfDays(branch);
174 verifyNoInteractions(ceTaskMessages);
178 public void load_reference_branch() {
179 ComponentDto branch = dbTester.components().insertProjectBranch(project);
182 setProjectPeriod(project.uuid(), NewCodePeriodType.REFERENCE_BRANCH, "master");
184 underTest.execute(new TestComputationStepContext());
185 assertPeriod(NewCodePeriodType.REFERENCE_BRANCH, "master", null);
186 verifyNoInteractions(ceTaskMessages);
190 public void scanner_overrides_branch_new_code_reference_branch() {
191 ComponentDto branch = dbTester.components().insertProjectBranch(project);
194 setBranchPeriod(project.uuid(), branch.uuid(), NewCodePeriodType.REFERENCE_BRANCH, "master");
196 String newCodeReferenceBranch = "newCodeReferenceBranch";
197 when(analysisMetadataHolder.getNewCodeReferenceBranch()).thenReturn(Optional.of(newCodeReferenceBranch));
199 underTest.execute(new TestComputationStepContext());
200 assertPeriod(NewCodePeriodType.REFERENCE_BRANCH, newCodeReferenceBranch, null);
201 verify(ceTaskMessages).add(any(CeTaskMessages.Message.class));
205 public void scanner_defines_new_code_reference_branch() {
206 ComponentDto branch = dbTester.components().insertProjectBranch(project);
209 String newCodeReferenceBranch = "newCodeReferenceBranch";
210 when(analysisMetadataHolder.getNewCodeReferenceBranch()).thenReturn(Optional.of(newCodeReferenceBranch));
212 underTest.execute(new TestComputationStepContext());
213 assertPeriod(NewCodePeriodType.REFERENCE_BRANCH, newCodeReferenceBranch, null);
214 verifyNoInteractions(ceTaskMessages);
218 public void scanner_overrides_project_new_code_reference_branch() {
219 ComponentDto branch = dbTester.components().insertProjectBranch(project);
222 setProjectPeriod(project.uuid(), NewCodePeriodType.REFERENCE_BRANCH, "master");
224 String newCodeReferenceBranch = "newCodeReferenceBranch";
225 when(analysisMetadataHolder.getNewCodeReferenceBranch()).thenReturn(Optional.of(newCodeReferenceBranch));
227 underTest.execute(new TestComputationStepContext());
228 assertPeriod(NewCodePeriodType.REFERENCE_BRANCH, newCodeReferenceBranch, null);
229 verifyNoInteractions(ceTaskMessages);
233 public void load_reference_branch_without_fork_date_in_report() {
234 ComponentDto branch = dbTester.components().insertProjectBranch(project);
237 setProjectPeriod(project.uuid(), NewCodePeriodType.REFERENCE_BRANCH, "master");
239 underTest.execute(new TestComputationStepContext());
240 assertPeriod(NewCodePeriodType.REFERENCE_BRANCH, "master", null);
241 verifyNoInteractions(ceTaskMessages);
244 private void testNumberOfDays(ComponentDto projectOrBranch) {
245 setupRoot(projectOrBranch);
247 SnapshotDto analysis = dbTester.components().insertSnapshot(projectOrBranch,
248 snapshot -> snapshot.setCreatedAt(milisSinceEpoch(2019, 3, 15, 0)));
250 underTest.execute(new TestComputationStepContext());
252 assertPeriod(NewCodePeriodType.NUMBER_OF_DAYS, "10", analysis.getCreatedAt());
253 verifyDebugLogs("Resolving new code period by 10 days: 2019-03-10");
257 public void load_specific_analysis() {
258 ComponentDto branch = dbTester.components().insertProjectBranch(project);
259 SnapshotDto selectedAnalysis = dbTester.components().insertSnapshot(branch);
260 SnapshotDto aVersionAnalysis = dbTester.components().insertSnapshot(branch, snapshot -> snapshot.setCreatedAt(milisSinceEpoch(2019, 3, 12, 0)).setLast(false));
261 dbTester.events().insertEvent(EventTesting.newEvent(aVersionAnalysis).setName("a_version").setCategory(CATEGORY_VERSION));
262 dbTester.components().insertSnapshot(branch, snapshot -> snapshot.setCreatedAt(milisSinceEpoch(2019, 3, 15, 0)).setLast(true));
264 setBranchPeriod(project.uuid(), branch.uuid(), NewCodePeriodType.SPECIFIC_ANALYSIS, selectedAnalysis.getUuid());
267 underTest.execute(new TestComputationStepContext());
269 assertPeriod(NewCodePeriodType.SPECIFIC_ANALYSIS, selectedAnalysis.getUuid(), selectedAnalysis.getCreatedAt());
270 verifyDebugLogs("Resolving new code period with a specific analysis");
271 verifyNoInteractions(ceTaskMessages);
275 public void throw_ISE_if_no_analysis_found_for_number_of_days() {
276 setProjectPeriod(project.uuid(), NewCodePeriodType.NUMBER_OF_DAYS, "10");
280 assertThatThrownBy(() -> underTest.execute(new TestComputationStepContext()))
281 .isInstanceOf(IllegalStateException.class)
282 .hasMessageContaining("Attempting to resolve period while no analysis exist");
286 public void throw_ISE_if_no_analysis_found_with_default() {
289 assertThatThrownBy(() -> underTest.execute(new TestComputationStepContext()))
290 .isInstanceOf(IllegalStateException.class)
291 .hasMessageContaining("Attempting to resolve period while no analysis exist");
295 public void ignore_unprocessed_snapshots() {
296 SnapshotDto analysis1 = dbTester.components()
297 .insertSnapshot(project, snapshot -> snapshot.setStatus(STATUS_UNPROCESSED).setCreatedAt(milisSinceEpoch(2019, 3, 12, 0)).setLast(false));
298 SnapshotDto analysis2 = dbTester.components().insertSnapshot(project,
299 snapshot -> snapshot.setStatus(STATUS_PROCESSED).setProjectVersion("not provided").setCreatedAt(milisSinceEpoch(2019, 3, 15, 0)).setLast(false));
300 dbTester.events().insertEvent(newEvent(analysis1).setName("not provided").setCategory(CATEGORY_VERSION).setDate(analysis1.getCreatedAt()));
301 dbTester.events().insertEvent(newEvent(analysis2).setName("not provided").setCategory(CATEGORY_VERSION).setDate(analysis2.getCreatedAt()));
303 setProjectPeriod(project.uuid(), NewCodePeriodType.NUMBER_OF_DAYS, "10");
305 underTest.execute(new TestComputationStepContext());
307 assertPeriod(NewCodePeriodType.NUMBER_OF_DAYS, "10", analysis2.getCreatedAt());
308 verifyDebugLogs("Resolving new code period by 10 days: 2019-03-10");
312 public void throw_ISE_when_specific_analysis_is_set_but_does_not_exist_in_DB() {
313 ComponentDto project = dbTester.components().insertPublicProject().getMainBranchComponent();
314 setProjectPeriod(project.uuid(), NewCodePeriodType.SPECIFIC_ANALYSIS, "nonexistent");
315 setupRoot(project, project.uuid(), "any-string");
317 assertThatThrownBy(() -> underTest.execute(new TestComputationStepContext()))
318 .isInstanceOf(IllegalStateException.class)
319 .hasMessage("Analysis 'nonexistent' of project '" + project.uuid() + "' defined as the baseline does not exist");
323 public void throw_ISE_when_specific_analysis_is_set_but_does_not_belong_to_current_project() {
324 ComponentDto otherProject = dbTester.components().insertPublicProject().getMainBranchComponent();
325 SnapshotDto otherProjectAnalysis = dbTester.components().insertSnapshot(otherProject);
326 setBranchPeriod(project.uuid(), project.uuid(), NewCodePeriodType.SPECIFIC_ANALYSIS, otherProjectAnalysis.getUuid());
329 assertThatThrownBy(() -> underTest.execute(new TestComputationStepContext()))
330 .isInstanceOf(IllegalStateException.class)
331 .hasMessage("Analysis '" + otherProjectAnalysis.getUuid() + "' of project '" + project.uuid() + "' defined as the baseline does not exist");
335 public void throw_ISE_when_specific_analysis_is_set_but_does_not_belong_to_current_branch() {
336 ComponentDto otherBranch = dbTester.components().insertProjectBranch(project);
337 SnapshotDto otherBranchAnalysis = dbTester.components().insertSnapshot(otherBranch);
338 setBranchPeriod(project.uuid(), project.uuid(), NewCodePeriodType.SPECIFIC_ANALYSIS, otherBranchAnalysis.getUuid());
341 assertThatThrownBy(() -> underTest.execute(new TestComputationStepContext()))
342 .isInstanceOf(IllegalStateException.class)
343 .hasMessage("Analysis '" + otherBranchAnalysis.getUuid() + "' of project '" + project.uuid() + "' defined as the baseline does not exist");
347 public void load_previous_version() {
348 SnapshotDto analysis1 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226379600000L).setProjectVersion("0.9").setLast(false)); // 2008-11-11
349 SnapshotDto analysis2 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226494680000L).setProjectVersion("1.0").setLast(false)); // 2008-11-12
350 SnapshotDto analysis3 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227157200000L).setProjectVersion("1.1").setLast(false)); // 2008-11-20
351 SnapshotDto analysis4 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227358680000L).setProjectVersion("1.1").setLast(false)); // 2008-11-22
352 SnapshotDto analysis5 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227934800000L).setProjectVersion("1.1").setLast(true)); // 2008-11-29
353 dbTester.events().insertEvent(newEvent(analysis1).setName("0.9").setCategory(CATEGORY_VERSION).setDate(analysis1.getCreatedAt()));
354 dbTester.events().insertEvent(newEvent(analysis2).setName("1.0").setCategory(CATEGORY_VERSION).setDate(analysis2.getCreatedAt()));
355 dbTester.events().insertEvent(newEvent(analysis5).setName("1.1").setCategory(CATEGORY_VERSION).setDate(analysis5.getCreatedAt()));
356 setupRoot(project, "1.1");
357 setProjectPeriod(project.uuid(), NewCodePeriodType.PREVIOUS_VERSION, null);
359 underTest.execute(new TestComputationStepContext());
361 assertPeriod(NewCodePeriodType.PREVIOUS_VERSION, "1.0", analysis2.getCreatedAt());
363 verifyDebugLogs("Resolving new code period by previous version: 1.0");
367 public void load_previous_version_when_version_is_changing() {
368 SnapshotDto analysis1 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226379600000L).setProjectVersion("0.9").setLast(false)); // 2008-11-11
369 SnapshotDto analysis2 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226494680000L).setProjectVersion("0.9").setLast(true)); // 2008-11-12
371 dbTester.events().insertEvent(newEvent(analysis2).setName("0.9").setCategory(CATEGORY_VERSION).setDate(analysis2.getCreatedAt()));
372 setupRoot(project, "1.0");
373 setProjectPeriod(project.uuid(), NewCodePeriodType.PREVIOUS_VERSION, null);
375 underTest.execute(new TestComputationStepContext());
377 assertPeriod(NewCodePeriodType.PREVIOUS_VERSION, "0.9", analysis2.getCreatedAt());
379 verifyDebugLogs("Resolving new code period by previous version: 0.9");
383 @UseDataProvider("zeroOrLess")
384 public void fail_with_MessageException_if_period_is_0_or_less(int zeroOrLess) {
386 setProjectPeriod(project.uuid(), NewCodePeriodType.NUMBER_OF_DAYS, String.valueOf(zeroOrLess));
388 verifyFailWithInvalidValueMessageException(String.valueOf(zeroOrLess),
389 "Invalid code period '" + zeroOrLess + "': number of days is <= 0");
393 public void load_previous_version_with_previous_version_deleted() {
394 SnapshotDto analysis1 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226379600000L).setProjectVersion("0.9").setLast(false)); // 2008-11-11
395 SnapshotDto analysis2 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226494680000L).setProjectVersion("1.0").setLast(false)); // 2008-11-12
396 SnapshotDto analysis3 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227157200000L).setProjectVersion("1.1").setLast(true)); // 2008-11-20
397 dbTester.events().insertEvent(newEvent(analysis1).setName("0.9").setCategory(CATEGORY_VERSION));
398 // The "1.0" version was deleted from the history
399 setupRoot(project, "1.1");
401 underTest.execute(new TestComputationStepContext());
403 // Analysis form 2008-11-11
404 assertPeriod(NewCodePeriodType.PREVIOUS_VERSION, "0.9", analysis1.getCreatedAt());
408 public void load_previous_version_with_first_analysis_when_no_previous_version_found() {
409 SnapshotDto analysis1 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226379600000L).setProjectVersion("1.1").setLast(false)); // 2008-11-11
410 SnapshotDto analysis2 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227934800000L).setProjectVersion("1.1").setLast(true)); // 2008-11-29
411 dbTester.events().insertEvent(newEvent(analysis2).setName("1.1").setCategory(CATEGORY_VERSION));
412 setupRoot(project, "1.1");
414 underTest.execute(new TestComputationStepContext());
416 assertPeriod(NewCodePeriodType.PREVIOUS_VERSION, null, analysis1.getCreatedAt());
418 verifyDebugLogs("Resolving first analysis as new code period as there is only one existing version");
422 public void load_previous_version_with_first_analysis_when_previous_snapshot_is_the_last_one() {
423 SnapshotDto analysis = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226379600000L).setProjectVersion("0.9").setLast(true)); // 2008-11-11
424 dbTester.events().insertEvent(newEvent(analysis).setName("0.9").setCategory(CATEGORY_VERSION));
425 setupRoot(project, "1.1");
427 dbTester.newCodePeriods().insert(NewCodePeriodType.PREVIOUS_VERSION, null);
429 underTest.execute(new TestComputationStepContext());
431 assertPeriod(NewCodePeriodType.PREVIOUS_VERSION, "0.9", analysis.getCreatedAt());
432 verifyDebugLogs("Resolving new code period by previous version: 0.9");
436 @UseDataProvider("anyValidLeakPeriodSettingValue")
437 public void leak_period_setting_is_ignored_for_PR(NewCodePeriodType type, @Nullable String value) {
438 when(analysisMetadataHolder.isBranch()).thenReturn(false);
440 dbTester.newCodePeriods().insert(type, value);
442 underTest.execute(new TestComputationStepContext());
444 assertThat(periodsHolder.hasPeriod()).isFalse();
447 private void verifyFailWithInvalidValueMessageException(String propertyValue, String debugLog, String... otherDebugLogs) {
449 underTest.execute(new TestComputationStepContext());
450 fail("a Message Exception should have been thrown");
451 } catch (MessageException e) {
452 verifyInvalidValueMessage(e, propertyValue);
453 verifyDebugLogs(debugLog, otherDebugLogs);
458 public static Object[][] zeroOrLess() {
459 return new Object[][] {
461 {-1 - new Random().nextInt(30)}
466 public static Object[][] stringConsideredAsVersions() {
467 return new Object[][] {
468 {randomAlphabetic(5)},
473 {"01-12-2018"}, // unsupported date format
478 public static Object[][] projectVersionNullOrNot() {
479 return new Object[][] {
481 {randomAlphabetic(15)},
486 public static Object[][] anyValidLeakPeriodSettingValue() {
487 return new Object[][] {
489 {NewCodePeriodType.NUMBER_OF_DAYS, "100"},
491 {NewCodePeriodType.PREVIOUS_VERSION, null}
495 private List<SnapshotDto> createSnapshots(ComponentDto project) {
496 ArrayList<SnapshotDto> list = new ArrayList<>();
497 list.add(dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226379600000L).setLast(false))); // 2008-11-11
498 list.add(dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226494680000L).setLast(false))); // 2008-11-12
499 list.add(dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227157200000L).setLast(false))); // 2008-11-20
500 list.add(dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227358680000L).setLast(false))); // 2008-11-22
501 list.add(dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227934800000L).setLast(true))); // 2008-11-29
505 private long milisSinceEpoch(int year, int month, int day, int hour) {
506 return ZonedDateTime.of(year, month, day, hour, 0, 0, 0, ZoneId.systemDefault())
507 .toInstant().toEpochMilli();
510 private void setProjectPeriod(String projectUuid, NewCodePeriodType type, @Nullable String value) {
511 dbTester.newCodePeriods().insert(projectUuid, type, value);
514 private void setBranchPeriod(String projectUuid, String branchUuid, NewCodePeriodType type, @Nullable String value) {
515 dbTester.newCodePeriods().insert(projectUuid, branchUuid, type, value);
518 private void setGlobalPeriod(NewCodePeriodType type, @Nullable String value) {
519 dbTester.newCodePeriods().insert(type, value);
522 private void assertPeriod(NewCodePeriodType type, @Nullable String value, @Nullable Long date) {
523 Period period = periodsHolder.getPeriod();
524 assertThat(period).isNotNull();
525 assertThat(period.getMode()).isEqualTo(type.name());
526 assertThat(period.getModeParameter()).isEqualTo(value);
527 assertThat(period.getDate()).isEqualTo(date);
530 private void verifyDebugLogs(String log, String... otherLogs) {
531 assertThat(logTester.logs(Level.DEBUG))
532 .contains(Stream.concat(Stream.of(log), Arrays.stream(otherLogs)).toArray(String[]::new));
535 private void setupRoot(ComponentDto branchComponent) {
536 setupRoot(branchComponent, "any-string");
539 private void setupRoot(ComponentDto branchComponent, String projectUuid, String version) {
540 treeRootHolder.setRoot(ReportComponent
541 .builder(Component.Type.PROJECT, 1)
542 .setUuid(branchComponent.uuid())
543 .setKey(branchComponent.getKey())
544 .setProjectVersion(version)
547 Project project = mock(Project.class);
548 when(project.getUuid()).thenReturn(projectUuid);
549 when(analysisMetadataHolder.getProject()).thenReturn(project);
552 private void setupRoot(ComponentDto branchComponent, String version) {
553 setupRoot(branchComponent, project.uuid(), version);
556 private static void verifyInvalidValueMessage(MessageException e, String propertyValue) {
557 assertThat(e).hasMessage("Invalid new code period. '" + propertyValue
558 + "' is not one of: integer > 0, date before current analysis j, \"previous_version\", or version string that exists in the project' \n" +
559 "Please contact a project administrator to correct this setting");