]> source.dussan.org Git - sonarqube.git/blob
8b7bee5e2251f72160c822623317c9b1eb7e50be
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2022 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 java.util.Collection;
23 import java.util.Optional;
24 import org.junit.Before;
25 import org.junit.Rule;
26 import org.junit.Test;
27 import org.mockito.ArgumentCaptor;
28 import org.sonar.api.notifications.Notification;
29 import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
30 import org.sonar.ce.task.projectanalysis.analysis.Branch;
31 import org.sonar.ce.task.projectanalysis.component.Component;
32 import org.sonar.ce.task.projectanalysis.component.DefaultBranchImpl;
33 import org.sonar.ce.task.projectanalysis.component.ReportComponent;
34 import org.sonar.ce.task.projectanalysis.component.TreeRootHolder;
35 import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule;
36 import org.sonar.ce.task.projectanalysis.event.Event;
37 import org.sonar.ce.task.projectanalysis.event.EventRepository;
38 import org.sonar.ce.task.projectanalysis.measure.Measure;
39 import org.sonar.ce.task.projectanalysis.measure.MeasureRepository;
40 import org.sonar.ce.task.projectanalysis.measure.QualityGateStatus;
41 import org.sonar.ce.task.projectanalysis.metric.Metric;
42 import org.sonar.ce.task.projectanalysis.metric.MetricRepository;
43 import org.sonar.ce.task.step.TestComputationStepContext;
44 import org.sonar.db.component.BranchType;
45 import org.sonar.server.notification.NotificationService;
46 import org.sonar.server.project.Project;
47 import org.sonar.server.qualitygate.notification.QGChangeNotification;
48
49 import static java.util.Collections.emptyList;
50 import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
51 import static org.assertj.core.api.Assertions.assertThat;
52 import static org.mockito.ArgumentMatchers.eq;
53 import static org.mockito.Mockito.mock;
54 import static org.mockito.Mockito.reset;
55 import static org.mockito.Mockito.verify;
56 import static org.mockito.Mockito.verifyNoInteractions;
57 import static org.mockito.Mockito.verifyNoMoreInteractions;
58 import static org.mockito.Mockito.when;
59 import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY;
60 import static org.sonar.ce.task.projectanalysis.measure.Measure.Level.ERROR;
61 import static org.sonar.ce.task.projectanalysis.measure.Measure.Level.OK;
62 import static org.sonar.db.component.BranchDto.DEFAULT_PROJECT_MAIN_BRANCH_NAME;
63
64 public class QualityGateEventsStepTest {
65   private static final String PROJECT_VERSION = randomAlphabetic(19);
66   private static final ReportComponent PROJECT_COMPONENT = ReportComponent.builder(Component.Type.PROJECT, 1)
67     .setUuid("uuid 1")
68     .setKey("key 1")
69     .setProjectVersion(PROJECT_VERSION)
70     .setBuildString("V1.9")
71     .setScmRevisionId("456def")
72     .addChildren(ReportComponent.builder(Component.Type.DIRECTORY, 2).build())
73     .build();
74   private static final String INVALID_ALERT_STATUS = "trololo";
75   private static final String ALERT_TEXT = "alert text";
76   private static final QualityGateStatus OK_QUALITY_GATE_STATUS = new QualityGateStatus(OK, ALERT_TEXT);
77   private static final QualityGateStatus ERROR_QUALITY_GATE_STATUS = new QualityGateStatus(ERROR, ALERT_TEXT);
78
79   @Rule
80   public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
81
82   @Rule
83   public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
84
85   private ArgumentCaptor<Event> eventArgumentCaptor = ArgumentCaptor.forClass(Event.class);
86   private ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(Notification.class);
87
88   private Metric alertStatusMetric = mock(Metric.class);
89
90   private MetricRepository metricRepository = mock(MetricRepository.class);
91   private MeasureRepository measureRepository = mock(MeasureRepository.class);
92   private EventRepository eventRepository = mock(EventRepository.class);
93   private NotificationService notificationService = mock(NotificationService.class);
94   private QualityGateEventsStep underTest = new QualityGateEventsStep(treeRootHolder, metricRepository, measureRepository, eventRepository, notificationService,
95     analysisMetadataHolder);
96
97   @Before
98   public void setUp() {
99     when(metricRepository.getByKey(ALERT_STATUS_KEY)).thenReturn(alertStatusMetric);
100     analysisMetadataHolder
101       .setProject(new Project(PROJECT_COMPONENT.getUuid(), PROJECT_COMPONENT.getKey(), PROJECT_COMPONENT.getName(), PROJECT_COMPONENT.getDescription(), emptyList()));
102     analysisMetadataHolder.setBranch(mock(Branch.class));
103     treeRootHolder.setRoot(PROJECT_COMPONENT);
104   }
105
106   @Test
107   public void no_event_if_no_raw_ALERT_STATUS_measure() {
108     when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(Optional.empty());
109
110     underTest.execute(new TestComputationStepContext());
111
112     verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, alertStatusMetric);
113     verifyNoMoreInteractions(measureRepository, eventRepository);
114   }
115
116   @Test
117   public void no_event_created_if_raw_ALERT_STATUS_measure_is_null() {
118     when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(of(Measure.newMeasureBuilder().createNoValue()));
119
120     underTest.execute(new TestComputationStepContext());
121
122     verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, alertStatusMetric);
123     verifyNoMoreInteractions(measureRepository, eventRepository);
124   }
125
126   private static Optional<Measure> of(Measure measure) {
127     return Optional.of(measure);
128   }
129
130   @Test
131   public void no_event_created_if_raw_ALERT_STATUS_measure_is_unsupported_value() {
132     when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(of(Measure.newMeasureBuilder().create(INVALID_ALERT_STATUS)));
133
134     underTest.execute(new TestComputationStepContext());
135
136     verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, alertStatusMetric);
137     verifyNoMoreInteractions(measureRepository, eventRepository);
138   }
139
140   @Test
141   public void no_event_created_if_no_base_ALERT_STATUS_and_raw_is_OK() {
142     QualityGateStatus someQGStatus = new QualityGateStatus(Measure.Level.OK);
143
144     when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(of(Measure.newMeasureBuilder().setQualityGateStatus(someQGStatus).createNoValue()));
145     when(measureRepository.getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(of(Measure.newMeasureBuilder().createNoValue()));
146
147     underTest.execute(new TestComputationStepContext());
148
149     verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, alertStatusMetric);
150     verify(measureRepository).getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric);
151     verifyNoMoreInteractions(measureRepository, eventRepository);
152   }
153
154   @Test
155   public void event_created_if_base_ALERT_STATUS_has_no_alertStatus_and_raw_is_ERROR() {
156     verify_event_created_if_no_base_ALERT_STATUS_measure(ERROR, "Failed");
157   }
158
159   @Test
160   public void event_created_if_base_ALERT_STATUS_has_invalid_alertStatus_and_raw_is_ERROR() {
161     verify_event_created_if_no_base_ALERT_STATUS_measure(ERROR, "Failed");
162   }
163
164   private void verify_event_created_if_no_base_ALERT_STATUS_measure(Measure.Level rawAlterStatus, String expectedLabel) {
165     QualityGateStatus someQGStatus = new QualityGateStatus(rawAlterStatus, ALERT_TEXT);
166
167     when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(of(Measure.newMeasureBuilder().setQualityGateStatus(someQGStatus).createNoValue()));
168     when(measureRepository.getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(of(Measure.newMeasureBuilder().createNoValue()));
169
170     underTest.execute(new TestComputationStepContext());
171
172     verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, alertStatusMetric);
173     verify(measureRepository).getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric);
174     verify(eventRepository).add(eq(PROJECT_COMPONENT), eventArgumentCaptor.capture());
175     verifyNoMoreInteractions(measureRepository, eventRepository);
176
177     Event event = eventArgumentCaptor.getValue();
178     assertThat(event.getCategory()).isEqualTo(Event.Category.ALERT);
179     assertThat(event.getName()).isEqualTo(expectedLabel);
180     assertThat(event.getDescription()).isEqualTo(ALERT_TEXT);
181     assertThat(event.getData()).isNull();
182
183     ArgumentCaptor<Collection> collectionCaptor = ArgumentCaptor.forClass(Collection.class);
184     verify(notificationService).deliverEmails(collectionCaptor.capture());
185     verify(notificationService).deliver(notificationArgumentCaptor.capture());
186     Notification notification = notificationArgumentCaptor.getValue();
187     assertThat(collectionCaptor.getValue()).hasSize(1);
188     assertThat(collectionCaptor.getValue().iterator().next()).isSameAs(notification);
189     assertThat(notification).isInstanceOf(QGChangeNotification.class);
190     assertThat(notification.getType()).isEqualTo("alerts");
191     assertThat(notification.getFieldValue("projectKey")).isEqualTo(PROJECT_COMPONENT.getKey());
192     assertThat(notification.getFieldValue("projectName")).isEqualTo(PROJECT_COMPONENT.getName());
193     assertThat(notification.getFieldValue("projectVersion")).isEqualTo(PROJECT_COMPONENT.getProjectAttributes().getProjectVersion());
194     assertThat(notification.getFieldValue("branch")).isNull();
195     assertThat(notification.getFieldValue("alertLevel")).isEqualTo(rawAlterStatus.name());
196     assertThat(notification.getFieldValue("alertName")).isEqualTo(expectedLabel);
197   }
198
199   @Test
200   public void no_event_created_if_base_ALERT_STATUS_measure_but_status_is_the_same() {
201     when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric))
202       .thenReturn(of(Measure.newMeasureBuilder().setQualityGateStatus(OK_QUALITY_GATE_STATUS).createNoValue()));
203     when(measureRepository.getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric))
204       .thenReturn(of(Measure.newMeasureBuilder().setQualityGateStatus(OK_QUALITY_GATE_STATUS).createNoValue()));
205
206     underTest.execute(new TestComputationStepContext());
207
208     verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, alertStatusMetric);
209     verify(measureRepository).getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric);
210     verifyNoMoreInteractions(measureRepository, eventRepository);
211   }
212
213   @Test
214   public void event_created_if_base_ALERT_STATUS_measure_exists_and_status_has_changed() {
215     verify_event_created_if_base_ALERT_STATUS_measure_exists_and_status_has_changed(OK, ERROR_QUALITY_GATE_STATUS, "Failed");
216     verify_event_created_if_base_ALERT_STATUS_measure_exists_and_status_has_changed(ERROR, OK_QUALITY_GATE_STATUS, "Passed");
217   }
218
219   private void verify_event_created_if_base_ALERT_STATUS_measure_exists_and_status_has_changed(Measure.Level previousAlertStatus,
220     QualityGateStatus newQualityGateStatus, String expectedLabel) {
221     when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric))
222       .thenReturn(of(Measure.newMeasureBuilder().setQualityGateStatus(newQualityGateStatus).createNoValue()));
223     when(measureRepository.getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(
224       of(Measure.newMeasureBuilder().setQualityGateStatus(new QualityGateStatus(previousAlertStatus)).createNoValue()));
225
226     underTest.execute(new TestComputationStepContext());
227
228     verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, alertStatusMetric);
229     verify(measureRepository).getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric);
230     verify(eventRepository).add(eq(PROJECT_COMPONENT), eventArgumentCaptor.capture());
231     verifyNoMoreInteractions(measureRepository, eventRepository);
232
233     Event event = eventArgumentCaptor.getValue();
234     assertThat(event.getCategory()).isEqualTo(Event.Category.ALERT);
235     assertThat(event.getName()).isEqualTo(expectedLabel);
236     assertThat(event.getDescription()).isEqualTo(ALERT_TEXT);
237     assertThat(event.getData()).isNull();
238
239     verify(notificationService).deliver(notificationArgumentCaptor.capture());
240     Notification notification = notificationArgumentCaptor.getValue();
241     assertThat(notification.getType()).isEqualTo("alerts");
242     assertThat(notification.getFieldValue("projectKey")).isEqualTo(PROJECT_COMPONENT.getKey());
243     assertThat(notification.getFieldValue("projectName")).isEqualTo(PROJECT_COMPONENT.getName());
244     assertThat(notification.getFieldValue("projectVersion")).isEqualTo(PROJECT_COMPONENT.getProjectAttributes().getProjectVersion());
245     assertThat(notification.getFieldValue("branch")).isNull();
246     assertThat(notification.getFieldValue("alertLevel")).isEqualTo(newQualityGateStatus.getStatus().name());
247     assertThat(notification.getFieldValue("alertName")).isEqualTo(expectedLabel);
248
249     reset(measureRepository, eventRepository, notificationService);
250   }
251
252   @Test
253   public void verify_branch_name_is_not_set_in_notification_when_main() {
254     analysisMetadataHolder.setBranch(new DefaultBranchImpl(DEFAULT_PROJECT_MAIN_BRANCH_NAME));
255
256     when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric))
257       .thenReturn(of(Measure.newMeasureBuilder().setQualityGateStatus(OK_QUALITY_GATE_STATUS).createNoValue()));
258     when(measureRepository.getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(
259       of(Measure.newMeasureBuilder().setQualityGateStatus(new QualityGateStatus(ERROR)).createNoValue()));
260
261     underTest.execute(new TestComputationStepContext());
262
263     verify(notificationService).deliver(notificationArgumentCaptor.capture());
264     Notification notification = notificationArgumentCaptor.getValue();
265     assertThat(notification.getType()).isEqualTo("alerts");
266     assertThat(notification.getFieldValue("projectKey")).isEqualTo(PROJECT_COMPONENT.getKey());
267     assertThat(notification.getFieldValue("projectName")).isEqualTo(PROJECT_COMPONENT.getName());
268     assertThat(notification.getFieldValue("projectVersion")).isEqualTo(PROJECT_COMPONENT.getProjectAttributes().getProjectVersion());
269     assertThat(notification.getFieldValue("branch")).isNull();
270
271     reset(measureRepository, eventRepository, notificationService);
272   }
273
274   @Test
275   public void no_alert_on_pull_request_branches() {
276     Branch pr = mock(Branch.class);
277     when(pr.getType()).thenReturn(BranchType.PULL_REQUEST);
278     analysisMetadataHolder.setBranch(pr);
279     TreeRootHolder treeRootHolder = mock(TreeRootHolder.class);
280     MetricRepository metricRepository = mock(MetricRepository.class);
281     MeasureRepository measureRepository = mock(MeasureRepository.class);
282     EventRepository eventRepository = mock(EventRepository.class);
283     NotificationService notificationService = mock(NotificationService.class);
284
285     QualityGateEventsStep underTest = new QualityGateEventsStep(treeRootHolder, metricRepository, measureRepository,
286       eventRepository, notificationService, analysisMetadataHolder);
287
288     underTest.execute(new TestComputationStepContext());
289
290     verifyNoInteractions(treeRootHolder, metricRepository, measureRepository, eventRepository, notificationService);
291   }
292 }