]> source.dussan.org Git - sonarqube.git/blob
1c9a6f786e95ba5367f5a0fc89a696dd2c1835e2
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2017 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.computation.task.projectanalysis.api.posttask;
21
22 import com.google.common.collect.ImmutableMap;
23 import com.tngtech.java.junit.dataprovider.DataProvider;
24 import com.tngtech.java.junit.dataprovider.DataProviderRunner;
25 import com.tngtech.java.junit.dataprovider.UseDataProvider;
26 import java.util.Date;
27 import java.util.List;
28 import java.util.Optional;
29 import javax.annotation.Nullable;
30 import org.apache.commons.lang.RandomStringUtils;
31 import org.junit.Before;
32 import org.junit.Rule;
33 import org.junit.Test;
34 import org.junit.runner.RunWith;
35 import org.mockito.ArgumentCaptor;
36 import org.mockito.InOrder;
37 import org.sonar.api.ce.posttask.PostProjectAnalysisTask;
38 import org.sonar.api.ce.posttask.Project;
39 import org.sonar.api.utils.System2;
40 import org.sonar.ce.queue.CeTask;
41 import org.sonar.db.component.BranchType;
42 import org.sonar.scanner.protocol.output.ScannerReport;
43 import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
44 import org.sonar.server.computation.task.projectanalysis.analysis.Branch;
45 import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReaderRule;
46 import org.sonar.server.computation.task.projectanalysis.component.DefaultBranchImpl;
47 import org.sonar.server.computation.task.projectanalysis.metric.Metric;
48 import org.sonar.server.computation.task.projectanalysis.qualitygate.Condition;
49 import org.sonar.server.computation.task.projectanalysis.qualitygate.ConditionStatus;
50 import org.sonar.server.computation.task.projectanalysis.qualitygate.MutableQualityGateHolderRule;
51 import org.sonar.server.computation.task.projectanalysis.qualitygate.MutableQualityGateStatusHolderRule;
52 import org.sonar.server.computation.task.projectanalysis.qualitygate.QualityGate;
53 import org.sonar.server.computation.task.projectanalysis.qualitygate.QualityGateStatus;
54
55 import static com.google.common.collect.ImmutableList.of;
56 import static java.util.Arrays.asList;
57 import static org.assertj.core.api.Assertions.assertThat;
58 import static org.assertj.core.data.MapEntry.entry;
59 import static org.mockito.Matchers.any;
60 import static org.mockito.Mockito.doThrow;
61 import static org.mockito.Mockito.inOrder;
62 import static org.mockito.Mockito.mock;
63 import static org.mockito.Mockito.verify;
64 import static org.mockito.Mockito.when;
65
66 @RunWith(DataProviderRunner.class)
67 public class PostProjectAnalysisTasksExecutorTest {
68   private static final long QUALITY_GATE_ID = 98451;
69   private static final String QUALITY_GATE_NAME = "qualityGate name";
70   private static final Condition CONDITION_1 = createCondition("metric key 1");
71   private static final Condition CONDITION_2 = createCondition("metric key 2");
72
73   @Rule
74   public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
75   @Rule
76   public MutableQualityGateHolderRule qualityGateHolder = new MutableQualityGateHolderRule();
77   @Rule
78   public MutableQualityGateStatusHolderRule qualityGateStatusHolder = new MutableQualityGateStatusHolderRule();
79   @Rule
80   public BatchReportReaderRule reportReader = new BatchReportReaderRule();
81
82   private System2 system2 = mock(System2.class);
83   private ArgumentCaptor<PostProjectAnalysisTask.ProjectAnalysis> projectAnalysisArgumentCaptor = ArgumentCaptor.forClass(PostProjectAnalysisTask.ProjectAnalysis.class);
84   private CeTask ceTask = new CeTask.Builder()
85     .setOrganizationUuid("org1")
86     .setType("type")
87     .setUuid("uuid")
88     .setComponentKey("component key")
89     .setComponentName("component name")
90     .setComponentUuid("component uuid")
91     .build();
92   private PostProjectAnalysisTask postProjectAnalysisTask = mock(PostProjectAnalysisTask.class);
93   private PostProjectAnalysisTasksExecutor underTest = new PostProjectAnalysisTasksExecutor(
94     ceTask, analysisMetadataHolder, qualityGateHolder, qualityGateStatusHolder,
95     reportReader, system2,
96     new PostProjectAnalysisTask[] {postProjectAnalysisTask});
97
98   @Before
99   public void setUp() throws Exception {
100     qualityGateHolder.setQualityGate(new QualityGate(QUALITY_GATE_ID, QUALITY_GATE_NAME, of(CONDITION_1, CONDITION_2)));
101     qualityGateStatusHolder.setStatus(QualityGateStatus.OK, ImmutableMap.of(
102       CONDITION_1, ConditionStatus.create(ConditionStatus.EvaluationStatus.OK, "value"),
103       CONDITION_2, ConditionStatus.NO_VALUE_STATUS));
104     analysisMetadataHolder.setBranch(null);
105   }
106
107   @Test
108   @UseDataProvider("booleanValues")
109   public void does_not_fail_when_there_is_no_PostProjectAnalysisTasksExecutor(boolean allStepsExecuted) {
110     new PostProjectAnalysisTasksExecutor(ceTask, analysisMetadataHolder, qualityGateHolder, qualityGateStatusHolder, reportReader, system2)
111       .finished(allStepsExecuted);
112   }
113
114   @Test
115   @UseDataProvider("booleanValues")
116   public void finished_calls_all_PostProjectAnalysisTask_in_order_of_the_array_and_passes_the_same_object_to_all(boolean allStepsExecuted) {
117     PostProjectAnalysisTask postProjectAnalysisTask1 = mock(PostProjectAnalysisTask.class);
118     PostProjectAnalysisTask postProjectAnalysisTask2 = mock(PostProjectAnalysisTask.class);
119     InOrder inOrder = inOrder(postProjectAnalysisTask1, postProjectAnalysisTask2);
120
121     new PostProjectAnalysisTasksExecutor(
122       ceTask, analysisMetadataHolder, qualityGateHolder, qualityGateStatusHolder, reportReader,
123       system2, new PostProjectAnalysisTask[] {postProjectAnalysisTask1, postProjectAnalysisTask2})
124         .finished(allStepsExecuted);
125
126     inOrder.verify(postProjectAnalysisTask1).finished(projectAnalysisArgumentCaptor.capture());
127     inOrder.verify(postProjectAnalysisTask2).finished(projectAnalysisArgumentCaptor.capture());
128     inOrder.verifyNoMoreInteractions();
129
130     List<PostProjectAnalysisTask.ProjectAnalysis> allValues = projectAnalysisArgumentCaptor.getAllValues();
131     assertThat(allValues).hasSize(2);
132     assertThat(allValues.get(0)).isSameAs(allValues.get(1));
133   }
134
135   @Test
136   @UseDataProvider("booleanValues")
137   public void CeTask_status_depends_on_finished_method_argument_is_true_or_false(boolean allStepsExecuted) {
138     underTest.finished(allStepsExecuted);
139
140     verify(postProjectAnalysisTask).finished(projectAnalysisArgumentCaptor.capture());
141
142     assertThat(projectAnalysisArgumentCaptor.getValue().getCeTask().getStatus())
143       .isEqualTo(
144         allStepsExecuted ? org.sonar.api.ce.posttask.CeTask.Status.SUCCESS : org.sonar.api.ce.posttask.CeTask.Status.FAILED);
145   }
146
147   @Test
148   public void ceTask_uuid_is_UUID_of_CeTask() {
149     underTest.finished(true);
150
151     verify(postProjectAnalysisTask).finished(projectAnalysisArgumentCaptor.capture());
152
153     assertThat(projectAnalysisArgumentCaptor.getValue().getCeTask().getId())
154       .isEqualTo(ceTask.getUuid());
155   }
156
157   @Test
158   public void project_uuid_key_and_name_come_from_CeTask() {
159     underTest.finished(true);
160
161     verify(postProjectAnalysisTask).finished(projectAnalysisArgumentCaptor.capture());
162
163     Project project = projectAnalysisArgumentCaptor.getValue().getProject();
164     assertThat(project.getUuid()).isEqualTo(ceTask.getComponentUuid());
165     assertThat(project.getKey()).isEqualTo(ceTask.getComponentKey());
166     assertThat(project.getName()).isEqualTo(ceTask.getComponentName());
167   }
168
169   @Test
170   public void date_comes_from_AnalysisMetadataHolder() {
171     analysisMetadataHolder.setAnalysisDate(8_465_132_498L);
172     analysisMetadataHolder.setUuid(RandomStringUtils.randomAlphanumeric(40));
173
174     underTest.finished(true);
175
176     verify(postProjectAnalysisTask).finished(projectAnalysisArgumentCaptor.capture());
177
178     assertThat(projectAnalysisArgumentCaptor.getValue().getDate())
179       .isEqualTo(new Date(analysisMetadataHolder.getAnalysisDate()));
180   }
181
182   @Test
183   public void date_comes_from_system2_if_not_set_in_AnalysisMetadataHolder() {
184     long now = 1_999_663L;
185     when(system2.now()).thenReturn(now);
186
187     underTest.finished(false);
188
189     verify(postProjectAnalysisTask).finished(projectAnalysisArgumentCaptor.capture());
190
191     assertThat(projectAnalysisArgumentCaptor.getValue().getDate()).isEqualTo(new Date(now));
192   }
193
194   @Test
195   public void analysisDate_and_analysisUuid_comes_from_AnalysisMetadataHolder_when_set() {
196     analysisMetadataHolder.setAnalysisDate(8465132498L);
197     analysisMetadataHolder.setUuid(RandomStringUtils.randomAlphanumeric(40));
198
199     underTest.finished(true);
200
201     verify(postProjectAnalysisTask).finished(projectAnalysisArgumentCaptor.capture());
202
203     assertThat(projectAnalysisArgumentCaptor.getValue().getAnalysis().get().getDate())
204       .isEqualTo(new Date(analysisMetadataHolder.getAnalysisDate()));
205     assertThat(projectAnalysisArgumentCaptor.getValue().getAnalysis().get().getAnalysisUuid())
206       .isEqualTo(analysisMetadataHolder.getUuid());
207   }
208
209   @Test
210   public void analysis_is_empty_when_not_set_in_AnalysisMetadataHolder() {
211     underTest.finished(false);
212
213     verify(postProjectAnalysisTask).finished(projectAnalysisArgumentCaptor.capture());
214
215     assertThat(projectAnalysisArgumentCaptor.getValue().getAnalysis()).isEmpty();
216   }
217
218   @Test
219   public void branch_is_empty_when_not_set_in_AnalysisMetadataHolder() {
220     underTest.finished(false);
221
222     verify(postProjectAnalysisTask).finished(projectAnalysisArgumentCaptor.capture());
223
224     assertThat(projectAnalysisArgumentCaptor.getValue().getBranch()).isEmpty();
225   }
226
227   @Test
228   public void branch_is_empty_when_legacy_branch_implementation_is_used() {
229     analysisMetadataHolder.setBranch(new DefaultBranchImpl("feature/foo"));
230
231     underTest.finished(true);
232
233     verify(postProjectAnalysisTask).finished(projectAnalysisArgumentCaptor.capture());
234
235     assertThat(projectAnalysisArgumentCaptor.getValue().getBranch()).isEmpty();
236   }
237
238   @Test
239   public void branch_comes_from_AnalysisMetadataHolder_when_set() {
240     analysisMetadataHolder.setBranch(new Branch() {
241       @Override
242       public BranchType getType() {
243         return BranchType.SHORT;
244       }
245
246       @Override
247       public boolean isMain() {
248         return false;
249       }
250
251       @Override
252       public boolean isLegacyFeature() {
253         return false;
254       }
255
256       @Override
257       public Optional<String> getMergeBranchUuid() {
258         return Optional.empty();
259       }
260
261       @Override
262       public String getName() {
263         return "feature/foo";
264       }
265
266       @Override
267       public boolean supportsCrossProjectCpd() {
268         throw new UnsupportedOperationException();
269       }
270
271       @Override
272       public String generateKey(ScannerReport.Component module, @Nullable ScannerReport.Component fileOrDir) {
273         throw new UnsupportedOperationException();
274       }
275     });
276
277     underTest.finished(true);
278
279     verify(postProjectAnalysisTask).finished(projectAnalysisArgumentCaptor.capture());
280
281     org.sonar.api.ce.posttask.Branch branch = projectAnalysisArgumentCaptor.getValue().getBranch().get();
282     assertThat(branch.isMain()).isFalse();
283     assertThat(branch.getName()).hasValue("feature/foo");
284     assertThat(branch.getType()).isEqualTo(BranchImpl.Type.SHORT);
285   }
286
287   @Test
288   public void qualityGate_is_null_when_finished_method_argument_is_false() {
289     underTest.finished(false);
290
291     verify(postProjectAnalysisTask).finished(projectAnalysisArgumentCaptor.capture());
292
293     assertThat(projectAnalysisArgumentCaptor.getValue().getQualityGate()).isNull();
294   }
295
296   @Test
297   public void qualityGate_is_populated_when_finished_method_argument_is_true() {
298     underTest.finished(true);
299
300     verify(postProjectAnalysisTask).finished(projectAnalysisArgumentCaptor.capture());
301
302     org.sonar.api.ce.posttask.QualityGate qualityGate = projectAnalysisArgumentCaptor.getValue().getQualityGate();
303     assertThat(qualityGate.getStatus()).isEqualTo(org.sonar.api.ce.posttask.QualityGate.Status.OK);
304     assertThat(qualityGate.getId()).isEqualTo(String.valueOf(QUALITY_GATE_ID));
305     assertThat(qualityGate.getName()).isEqualTo(QUALITY_GATE_NAME);
306     assertThat(qualityGate.getConditions()).hasSize(2);
307   }
308
309   @Test
310   public void scannerContext_loads_properties_from_scanner_report() {
311     reportReader.putContextProperties(asList(ScannerReport.ContextProperty.newBuilder().setKey("foo").setValue("bar").build()));
312     underTest.finished(true);
313
314     verify(postProjectAnalysisTask).finished(projectAnalysisArgumentCaptor.capture());
315
316     org.sonar.api.ce.posttask.ScannerContext scannerContext = projectAnalysisArgumentCaptor.getValue().getScannerContext();
317     assertThat(scannerContext.getProperties()).containsExactly(entry("foo", "bar"));
318   }
319
320   @Test
321   @UseDataProvider("booleanValues")
322   public void finished_does_not_fail_if_listener_throws_exception_and_execute_subsequent_listeners(boolean allStepsExecuted) {
323     PostProjectAnalysisTask postProjectAnalysisTask1 = mock(PostProjectAnalysisTask.class);
324     PostProjectAnalysisTask postProjectAnalysisTask2 = mock(PostProjectAnalysisTask.class);
325     PostProjectAnalysisTask postProjectAnalysisTask3 = mock(PostProjectAnalysisTask.class);
326     InOrder inOrder = inOrder(postProjectAnalysisTask1, postProjectAnalysisTask2, postProjectAnalysisTask3);
327
328     doThrow(new RuntimeException("Faking a listener throws an exception"))
329       .when(postProjectAnalysisTask2)
330       .finished(any(PostProjectAnalysisTask.ProjectAnalysis.class));
331
332     new PostProjectAnalysisTasksExecutor(
333       ceTask, analysisMetadataHolder, qualityGateHolder, qualityGateStatusHolder, reportReader,
334       system2, new PostProjectAnalysisTask[] {postProjectAnalysisTask1, postProjectAnalysisTask2, postProjectAnalysisTask3})
335         .finished(allStepsExecuted);
336
337     inOrder.verify(postProjectAnalysisTask1).finished(projectAnalysisArgumentCaptor.capture());
338     inOrder.verify(postProjectAnalysisTask2).finished(projectAnalysisArgumentCaptor.capture());
339     inOrder.verify(postProjectAnalysisTask3).finished(projectAnalysisArgumentCaptor.capture());
340     inOrder.verifyNoMoreInteractions();
341   }
342
343   @DataProvider
344   public static Object[][] booleanValues() {
345     return new Object[][] {
346       {true},
347       {false}
348     };
349   }
350
351   private static Condition createCondition(String metricKey) {
352     Metric metric = mock(Metric.class);
353     when(metric.getKey()).thenReturn(metricKey);
354     return new Condition(metric, Condition.Operator.EQUALS.getDbValue(), "error threshold", "warn threshold", false);
355   }
356
357 }