]> source.dussan.org Git - sonarqube.git/blob
47f9b6bf0426a069ed9648ec2bfd1ae761d30847
[sonarqube.git] /
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.step;
21
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.Random;
31 import java.util.stream.Stream;
32 import javax.annotation.Nullable;
33 import org.junit.Before;
34 import org.junit.Rule;
35 import org.junit.Test;
36 import org.junit.rules.ExpectedException;
37 import org.junit.runner.RunWith;
38 import org.sonar.api.utils.MessageException;
39 import org.sonar.api.utils.System2;
40 import org.sonar.api.utils.log.LogAndArguments;
41 import org.sonar.api.utils.log.LogTester;
42 import org.sonar.api.utils.log.LoggerLevel;
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.db.organization.OrganizationDto;
60 import org.sonar.server.project.Project;
61
62 import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
63 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
64 import static org.assertj.core.api.Assertions.assertThat;
65 import static org.assertj.core.api.Assertions.fail;
66 import static org.mockito.Mockito.mock;
67 import static org.mockito.Mockito.verify;
68 import static org.mockito.Mockito.verifyNoMoreInteractions;
69 import static org.mockito.Mockito.when;
70 import static org.sonar.db.component.SnapshotDto.STATUS_PROCESSED;
71 import static org.sonar.db.component.SnapshotDto.STATUS_UNPROCESSED;
72 import static org.sonar.db.event.EventDto.CATEGORY_VERSION;
73 import static org.sonar.db.event.EventTesting.newEvent;
74
75 @RunWith(DataProviderRunner.class)
76 public class LoadPeriodsStepTest extends BaseStepTest {
77   @Rule
78   public DbTester dbTester = DbTester.create(System2.INSTANCE);
79   @Rule
80   public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
81   @Rule
82   public LogTester logTester = new LogTester();
83   @Rule
84   public ExpectedException expectedException = ExpectedException.none();
85
86   private AnalysisMetadataHolder analysisMetadataHolder = mock(AnalysisMetadataHolder.class);
87   private PeriodHolderImpl periodsHolder = new PeriodHolderImpl();
88   private System2 system2Mock = mock(System2.class);
89   private NewCodePeriodDao dao = new NewCodePeriodDao(system2Mock, new SequenceUuidFactory());
90   private NewCodePeriodResolver newCodePeriodResolver = new NewCodePeriodResolver(dbTester.getDbClient());
91   private ZonedDateTime analysisDate = ZonedDateTime.of(2019, 3, 20, 5, 30, 40, 0, ZoneId.systemDefault());
92
93   private LoadPeriodsStep underTest = new LoadPeriodsStep(analysisMetadataHolder, dao, treeRootHolder, periodsHolder, dbTester.getDbClient(), newCodePeriodResolver);
94
95   private OrganizationDto organization;
96   private ComponentDto project;
97
98   @Override
99   protected ComputationStep step() {
100     return underTest;
101   }
102
103   @Before
104   public void setUp() {
105     organization = dbTester.organizations().insert();
106     project = dbTester.components().insertMainBranch(organization);
107
108     when(analysisMetadataHolder.isBranch()).thenReturn(true);
109     when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false);
110     when(analysisMetadataHolder.getAnalysisDate()).thenReturn(analysisDate.toInstant().toEpochMilli());
111   }
112
113   @Test
114   public void no_period_on_first_analysis() {
115     when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(true);
116     underTest.execute(new TestComputationStepContext());
117
118     verify(analysisMetadataHolder).isFirstAnalysis();
119     assertThat(periodsHolder.hasPeriod()).isFalse();
120     verifyNoMoreInteractions(analysisMetadataHolder);
121   }
122
123   @Test
124   public void no_period_if_not_LLB() {
125     when(analysisMetadataHolder.isBranch()).thenReturn(false);
126     underTest.execute(new TestComputationStepContext());
127
128     verify(analysisMetadataHolder).isFirstAnalysis();
129     verify(analysisMetadataHolder).isBranch();
130     assertThat(periodsHolder.hasPeriod()).isFalse();
131     verifyNoMoreInteractions(analysisMetadataHolder);
132   }
133
134   @Test
135   public void load_default_if_nothing_defined() {
136     setupRoot(project);
137
138     SnapshotDto analysis = dbTester.components().insertSnapshot(project,
139       snapshot -> snapshot.setCreatedAt(milisSinceEpoch(2019, 3, 15, 0)));
140
141     underTest.execute(new TestComputationStepContext());
142
143     assertPeriod(NewCodePeriodType.PREVIOUS_VERSION, null, analysis.getCreatedAt());
144     verifyDebugLogs("Resolving first analysis as new code period as there is only one existing version");
145   }
146
147   @Test
148   public void load_number_of_days_global() {
149     setGlobalPeriod(NewCodePeriodType.NUMBER_OF_DAYS, "10");
150
151     testNumberOfDays(project);
152   }
153
154   @Test
155   public void load_number_of_days_on_project() {
156     setGlobalPeriod(NewCodePeriodType.PREVIOUS_VERSION, null);
157     setProjectPeriod(project.uuid(), NewCodePeriodType.NUMBER_OF_DAYS, "10");
158
159     testNumberOfDays(project);
160   }
161
162   @Test
163   public void load_number_of_days_on_branch() {
164     ComponentDto branch = dbTester.components().insertProjectBranch(project);
165
166     setGlobalPeriod(NewCodePeriodType.PREVIOUS_VERSION, null);
167     setProjectPeriod(project.uuid(), NewCodePeriodType.PREVIOUS_VERSION, null);
168     setBranchPeriod(project.uuid(), branch.uuid(), NewCodePeriodType.NUMBER_OF_DAYS, "10");
169
170     testNumberOfDays(branch);
171   }
172
173   private void testNumberOfDays(ComponentDto projectOrBranch) {
174     setupRoot(projectOrBranch);
175
176     SnapshotDto analysis = dbTester.components().insertSnapshot(projectOrBranch,
177       snapshot -> snapshot.setCreatedAt(milisSinceEpoch(2019, 3, 15, 0)));
178
179     underTest.execute(new TestComputationStepContext());
180
181     assertPeriod(NewCodePeriodType.NUMBER_OF_DAYS, "10", analysis.getCreatedAt());
182     verifyDebugLogs("Resolving new code period by 10 days: 2019-03-10");
183   }
184
185   @Test
186   public void load_specific_analysis() {
187     ComponentDto branch = dbTester.components().insertProjectBranch(project);
188     SnapshotDto selectedAnalysis = dbTester.components().insertSnapshot(branch);
189     SnapshotDto aVersionAnalysis = dbTester.components().insertSnapshot(branch, snapshot -> snapshot.setCreatedAt(milisSinceEpoch(2019, 3, 12, 0)).setLast(false));
190     dbTester.events().insertEvent(EventTesting.newEvent(aVersionAnalysis).setName("a_version").setCategory(CATEGORY_VERSION));
191     dbTester.components().insertSnapshot(branch, snapshot -> snapshot.setCreatedAt(milisSinceEpoch(2019, 3, 15, 0)).setLast(true));
192
193     setBranchPeriod(project.uuid(), branch.uuid(), NewCodePeriodType.SPECIFIC_ANALYSIS, selectedAnalysis.getUuid());
194     setupRoot(branch);
195
196     underTest.execute(new TestComputationStepContext());
197
198     assertPeriod(NewCodePeriodType.SPECIFIC_ANALYSIS, selectedAnalysis.getUuid(), selectedAnalysis.getCreatedAt());
199     verifyDebugLogs("Resolving new code period with a specific analysis");
200   }
201
202   @Test
203   public void throw_ISE_if_no_analysis_found_for_number_of_days() {
204     setProjectPeriod(project.uuid(), NewCodePeriodType.NUMBER_OF_DAYS, "10");
205
206     setupRoot(project);
207
208     expectedException.expect(IllegalStateException.class);
209     expectedException.expectMessage("Attempting to resolve period while no analysis exist");
210
211     underTest.execute(new TestComputationStepContext());
212   }
213
214   @Test
215   public void throw_ISE_if_no_analysis_found_with_default() {
216     setupRoot(project);
217
218     expectedException.expect(IllegalStateException.class);
219     expectedException.expectMessage("Attempting to resolve period while no analysis exist");
220
221     underTest.execute(new TestComputationStepContext());
222   }
223
224   @Test
225   public void ignore_unprocessed_snapshots() {
226     SnapshotDto analysis1 = dbTester.components()
227       .insertSnapshot(project, snapshot -> snapshot.setStatus(STATUS_UNPROCESSED).setCreatedAt(milisSinceEpoch(2019, 3, 12, 0)).setLast(false));
228     SnapshotDto analysis2 = dbTester.components().insertSnapshot(project,
229       snapshot -> snapshot.setStatus(STATUS_PROCESSED).setProjectVersion("not provided").setCreatedAt(milisSinceEpoch(2019, 3, 15, 0)).setLast(false));
230     dbTester.events().insertEvent(newEvent(analysis1).setName("not provided").setCategory(CATEGORY_VERSION).setDate(analysis1.getCreatedAt()));
231     dbTester.events().insertEvent(newEvent(analysis2).setName("not provided").setCategory(CATEGORY_VERSION).setDate(analysis2.getCreatedAt()));
232     setupRoot(project);
233     setProjectPeriod(project.uuid(), NewCodePeriodType.NUMBER_OF_DAYS, "10");
234
235     underTest.execute(new TestComputationStepContext());
236
237     assertPeriod(NewCodePeriodType.NUMBER_OF_DAYS, "10", analysis2.getCreatedAt());
238     verifyDebugLogs("Resolving new code period by 10 days: 2019-03-10");
239   }
240
241   @Test
242   public void throw_ISE_when_specific_analysis_is_set_but_does_not_exist_in_DB() {
243     OrganizationDto organization = dbTester.organizations().insert();
244     ComponentDto project = dbTester.components().insertMainBranch(organization);
245     setProjectPeriod(project.uuid(), NewCodePeriodType.SPECIFIC_ANALYSIS, "nonexistent");
246     setupRoot(project);
247
248     expectedException.expect(IllegalStateException.class);
249     expectedException.expectMessage("Analysis 'nonexistent' of project '" + project.uuid() + "' defined as the baseline does not exist");
250
251     underTest.execute(new TestComputationStepContext());
252   }
253
254   @Test
255   public void throw_ISE_when_specific_analysis_is_set_but_does_not_belong_to_current_project() {
256     ComponentDto otherProject = dbTester.components().insertMainBranch(organization);
257     SnapshotDto otherProjectAnalysis = dbTester.components().insertSnapshot(otherProject);
258     setBranchPeriod(project.uuid(), project.uuid(), NewCodePeriodType.SPECIFIC_ANALYSIS, otherProjectAnalysis.getUuid());
259     setupRoot(project);
260
261     expectedException.expect(IllegalStateException.class);
262     expectedException.expectMessage("Analysis '" + otherProjectAnalysis.getUuid() + "' of project '" + project.uuid()
263       + "' defined as the baseline does not exist");
264
265     underTest.execute(new TestComputationStepContext());
266   }
267
268   @Test
269   public void throw_ISE_when_specific_analysis_is_set_but_does_not_belong_to_current_branch() {
270     ComponentDto otherBranch = dbTester.components().insertProjectBranch(project);
271     SnapshotDto otherBranchAnalysis = dbTester.components().insertSnapshot(otherBranch);
272     setBranchPeriod(project.uuid(), project.uuid(), NewCodePeriodType.SPECIFIC_ANALYSIS, otherBranchAnalysis.getUuid());
273     setupRoot(project);
274
275     expectedException.expect(IllegalStateException.class);
276     expectedException.expectMessage("Analysis '" + otherBranchAnalysis.getUuid() + "' of project '" + project.uuid()
277       + "' defined as the baseline does not exist");
278
279     underTest.execute(new TestComputationStepContext());
280   }
281
282   @Test
283   public void load_previous_version() {
284     SnapshotDto analysis1 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226379600000L).setProjectVersion("0.9").setLast(false)); // 2008-11-11
285     SnapshotDto analysis2 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226494680000L).setProjectVersion("1.0").setLast(false)); // 2008-11-12
286     SnapshotDto analysis3 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227157200000L).setProjectVersion("1.1").setLast(false)); // 2008-11-20
287     SnapshotDto analysis4 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227358680000L).setProjectVersion("1.1").setLast(false)); // 2008-11-22
288     SnapshotDto analysis5 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227934800000L).setProjectVersion("1.1").setLast(true)); // 2008-11-29
289     dbTester.events().insertEvent(newEvent(analysis1).setName("0.9").setCategory(CATEGORY_VERSION).setDate(analysis1.getCreatedAt()));
290     dbTester.events().insertEvent(newEvent(analysis2).setName("1.0").setCategory(CATEGORY_VERSION).setDate(analysis2.getCreatedAt()));
291     dbTester.events().insertEvent(newEvent(analysis5).setName("1.1").setCategory(CATEGORY_VERSION).setDate(analysis4.getCreatedAt()));
292     setupRoot(project, "1.1");
293     setProjectPeriod(project.uuid(), NewCodePeriodType.PREVIOUS_VERSION, null);
294
295     underTest.execute(new TestComputationStepContext());
296
297     assertPeriod(NewCodePeriodType.PREVIOUS_VERSION, "1.0", analysis2.getCreatedAt());
298
299     verifyDebugLogs("Resolving new code period by previous version: 1.0");
300   }
301
302   @Test
303   @UseDataProvider("zeroOrLess")
304   public void fail_with_MessageException_if_period_is_0_or_less(int zeroOrLess) {
305     setupRoot(project);
306     setProjectPeriod(project.uuid(), NewCodePeriodType.NUMBER_OF_DAYS, String.valueOf(zeroOrLess));
307
308     verifyFailWithInvalidValueMessageException(String.valueOf(zeroOrLess),
309       "Invalid code period '" + zeroOrLess + "': number of days is <= 0");
310   }
311
312   @Test
313   public void load_previous_version_with_previous_version_deleted() {
314     SnapshotDto analysis1 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226379600000L).setProjectVersion("0.9").setLast(false)); // 2008-11-11
315     SnapshotDto analysis2 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226494680000L).setProjectVersion("1.0").setLast(false)); // 2008-11-12
316     SnapshotDto analysis3 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227157200000L).setProjectVersion("1.1").setLast(false)); // 2008-11-20
317     dbTester.events().insertEvent(newEvent(analysis1).setName("0.9").setCategory(CATEGORY_VERSION));
318     // The "1.0" version was deleted from the history
319     dbTester.events().insertEvent(newEvent(analysis3).setName("1.1").setCategory(CATEGORY_VERSION));
320     setupRoot(project, "1.1");
321
322     underTest.execute(new TestComputationStepContext());
323
324     // Analysis form 2008-11-11
325     assertPeriod(NewCodePeriodType.PREVIOUS_VERSION, "0.9", analysis1.getCreatedAt());
326   }
327
328   @Test
329   public void load_previous_version_with_first_analysis_when_no_previous_version_found() {
330     SnapshotDto analysis1 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226379600000L).setProjectVersion("1.1").setLast(false)); // 2008-11-11
331     SnapshotDto analysis2 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227934800000L).setProjectVersion("1.1").setLast(true)); // 2008-11-29
332     dbTester.events().insertEvent(newEvent(analysis2).setName("1.1").setCategory(CATEGORY_VERSION));
333     setupRoot(project, "1.1");
334
335     underTest.execute(new TestComputationStepContext());
336
337     assertPeriod(NewCodePeriodType.PREVIOUS_VERSION, null, analysis1.getCreatedAt());
338
339     verifyDebugLogs("Resolving first analysis as new code period as there is only one existing version");
340   }
341
342   @Test
343   public void load_previous_version_with_first_analysis_when_previous_snapshot_is_the_last_one() {
344     SnapshotDto analysis = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226379600000L).setProjectVersion("0.9").setLast(true)); // 2008-11-11
345     dbTester.events().insertEvent(newEvent(analysis).setName("0.9").setCategory(CATEGORY_VERSION));
346     setupRoot(project, "1.1");
347
348     dbTester.newCodePeriods().insert(NewCodePeriodType.PREVIOUS_VERSION, null);
349
350     underTest.execute(new TestComputationStepContext());
351
352     assertPeriod(NewCodePeriodType.PREVIOUS_VERSION, null, analysis.getCreatedAt());
353     verifyDebugLogs("Resolving first analysis as new code period as there is only one existing version");
354   }
355
356   @Test
357   @UseDataProvider("anyValidLeakPeriodSettingValue")
358   public void leak_period_setting_is_ignored_for_PR(NewCodePeriodType type, @Nullable String value) {
359     when(analysisMetadataHolder.isBranch()).thenReturn(false);
360
361     dbTester.newCodePeriods().insert(type, value);
362
363     underTest.execute(new TestComputationStepContext());
364
365     assertThat(periodsHolder.hasPeriod()).isFalse();
366   }
367
368   private void verifyFailWithInvalidValueMessageException(String propertyValue, String debugLog, String... otherDebugLogs) {
369     try {
370       underTest.execute(new TestComputationStepContext());
371       fail("a Message Exception should have been thrown");
372     } catch (MessageException e) {
373       verifyInvalidValueMessage(e, propertyValue);
374       verifyDebugLogs(debugLog, otherDebugLogs);
375     }
376   }
377
378   @DataProvider
379   public static Object[][] zeroOrLess() {
380     return new Object[][]{
381       {0},
382       {-1 - new Random().nextInt(30)}
383     };
384   }
385
386   @DataProvider
387   public static Object[][] stringConsideredAsVersions() {
388     return new Object[][]{
389       {randomAlphabetic(5)},
390       {"1,3"},
391       {"1.3"},
392       {"0 1"},
393       {"1-SNAPSHOT"},
394       {"01-12-2018"}, // unsupported date format
395     };
396   }
397
398   @DataProvider
399   public static Object[][] projectVersionNullOrNot() {
400     return new Object[][]{
401       {null},
402       {randomAlphabetic(15)},
403     };
404   }
405
406   @DataProvider
407   public static Object[][] anyValidLeakPeriodSettingValue() {
408     return new Object[][]{
409       // days
410       {NewCodePeriodType.NUMBER_OF_DAYS, "100"},
411       // previous_version
412       {NewCodePeriodType.PREVIOUS_VERSION, null}
413     };
414   }
415
416   private List<SnapshotDto> createSnapshots(ComponentDto project) {
417     ArrayList<SnapshotDto> list = new ArrayList<>();
418     list.add(dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226379600000L).setLast(false))); // 2008-11-11
419     list.add(dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226494680000L).setLast(false))); // 2008-11-12
420     list.add(dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227157200000L).setLast(false))); // 2008-11-20
421     list.add(dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227358680000L).setLast(false))); // 2008-11-22
422     list.add(dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227934800000L).setLast(true))); // 2008-11-29
423     return list;
424   }
425
426   private long milisSinceEpoch(int year, int month, int day, int hour) {
427     return ZonedDateTime.of(year, month, day, hour, 0, 0, 0, ZoneId.systemDefault())
428       .toInstant().toEpochMilli();
429   }
430
431   private void setProjectPeriod(String projectUuid, NewCodePeriodType type, @Nullable String value) {
432     dbTester.newCodePeriods().insert(projectUuid, type, value);
433   }
434
435   private void setBranchPeriod(String projectUuid, String branchUuid, NewCodePeriodType type, @Nullable String value) {
436     dbTester.newCodePeriods().insert(projectUuid, branchUuid, type, value);
437   }
438
439   private void setGlobalPeriod(NewCodePeriodType type, @Nullable String value) {
440     dbTester.newCodePeriods().insert(type, value);
441   }
442
443   private void assertPeriod(NewCodePeriodType type, @Nullable String value, long snapshotDate) {
444     Period period = periodsHolder.getPeriod();
445     assertThat(period).isNotNull();
446     assertThat(period.getMode()).isEqualTo(type.name());
447     assertThat(period.getModeParameter()).isEqualTo(value);
448     assertThat(period.getSnapshotDate()).isEqualTo(snapshotDate);
449   }
450
451   private void verifyDebugLogs(String log, String... otherLogs) {
452     assertThat(logTester.getLogs()).hasSize(1 + otherLogs.length);
453     assertThat(logTester.getLogs(LoggerLevel.DEBUG))
454       .extracting(LogAndArguments::getFormattedMsg)
455       .containsOnly(Stream.concat(Stream.of(log), Arrays.stream(otherLogs)).toArray(String[]::new));
456   }
457
458   private void setupRoot(ComponentDto project) {
459     setupRoot(project, randomAlphanumeric(3));
460   }
461
462   private void setupRoot(ComponentDto projectDto, String version) {
463     treeRootHolder.setRoot(ReportComponent
464       .builder(Component.Type.PROJECT, 1)
465       .setUuid(projectDto.uuid())
466       .setKey(projectDto.getKey())
467       .setProjectVersion(version)
468       .build());
469
470     Project project = mock(Project.class);
471     when(project.getUuid()).thenReturn(projectDto.getMainBranchProjectUuid() != null ? projectDto.getMainBranchProjectUuid() : projectDto.uuid());
472     when(analysisMetadataHolder.getProject()).thenReturn(project);
473   }
474
475   private static void verifyInvalidValueMessage(MessageException e, String propertyValue) {
476     assertThat(e).hasMessage("Invalid new code period. '" + propertyValue
477       + "' is not one of: integer > 0, date before current analysis j, \"previous_version\", or version string that exists in the project' \n" +
478       "Please contact a project administrator to correct this setting");
479   }
480
481 }