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