3 * Copyright (C) 2009-2017 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.server.computation.task.projectanalysis.step;
22 import com.google.common.base.Optional;
23 import org.junit.Before;
24 import org.junit.Rule;
25 import org.junit.Test;
26 import org.mockito.ArgumentCaptor;
27 import org.sonar.api.notifications.Notification;
28 import org.sonar.db.component.BranchType;
29 import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
30 import org.sonar.server.computation.task.projectanalysis.analysis.Branch;
31 import org.sonar.server.computation.task.projectanalysis.analysis.Project;
32 import org.sonar.server.computation.task.projectanalysis.component.Component;
33 import org.sonar.server.computation.task.projectanalysis.component.DefaultBranchImpl;
34 import org.sonar.server.computation.task.projectanalysis.component.ReportComponent;
35 import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder;
36 import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
37 import org.sonar.server.computation.task.projectanalysis.event.Event;
38 import org.sonar.server.computation.task.projectanalysis.event.EventRepository;
39 import org.sonar.server.computation.task.projectanalysis.measure.Measure;
40 import org.sonar.server.computation.task.projectanalysis.measure.MeasureRepository;
41 import org.sonar.server.computation.task.projectanalysis.measure.QualityGateStatus;
42 import org.sonar.server.computation.task.projectanalysis.metric.Metric;
43 import org.sonar.server.computation.task.projectanalysis.metric.MetricRepository;
44 import org.sonar.server.notification.NotificationService;
46 import static org.assertj.core.api.Assertions.assertThat;
47 import static org.mockito.Matchers.eq;
48 import static org.mockito.Mockito.mock;
49 import static org.mockito.Mockito.reset;
50 import static org.mockito.Mockito.verify;
51 import static org.mockito.Mockito.verifyNoMoreInteractions;
52 import static org.mockito.Mockito.verifyZeroInteractions;
53 import static org.mockito.Mockito.when;
54 import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY;
55 import static org.sonar.server.computation.task.projectanalysis.measure.Measure.Level.ERROR;
56 import static org.sonar.server.computation.task.projectanalysis.measure.Measure.Level.OK;
57 import static org.sonar.server.computation.task.projectanalysis.measure.Measure.Level.WARN;
59 public class QualityGateEventsStepTest {
60 private static final ReportComponent PROJECT_COMPONENT = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("uuid 1").setKey("key 1")
61 .addChildren(ReportComponent.builder(Component.Type.MODULE, 2).setVersion("V1.9").build())
63 private static final String INVALID_ALERT_STATUS = "trololo";
64 private static final String ALERT_TEXT = "alert text";
65 private static final QualityGateStatus OK_QUALITY_GATE_STATUS = new QualityGateStatus(OK, ALERT_TEXT);
66 private static final QualityGateStatus WARN_QUALITY_GATE_STATUS = new QualityGateStatus(WARN, ALERT_TEXT);
67 private static final QualityGateStatus ERROR_QUALITY_GATE_STATUS = new QualityGateStatus(ERROR, ALERT_TEXT);
70 public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
73 public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
75 private ArgumentCaptor<Event> eventArgumentCaptor = ArgumentCaptor.forClass(Event.class);
76 private ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(Notification.class);
78 private Metric alertStatusMetric = mock(Metric.class);
80 private MetricRepository metricRepository = mock(MetricRepository.class);
81 private MeasureRepository measureRepository = mock(MeasureRepository.class);
82 private EventRepository eventRepository = mock(EventRepository.class);
83 private NotificationService notificationService = mock(NotificationService.class);
84 private QualityGateEventsStep underTest = new QualityGateEventsStep(treeRootHolder, metricRepository, measureRepository, eventRepository, notificationService,
85 analysisMetadataHolder);
89 when(metricRepository.getByKey(ALERT_STATUS_KEY)).thenReturn(alertStatusMetric);
90 analysisMetadataHolder.setProject(new Project(PROJECT_COMPONENT.getUuid(), PROJECT_COMPONENT.getKey(), PROJECT_COMPONENT.getName()));
91 analysisMetadataHolder.setBranch(null);
92 treeRootHolder.setRoot(PROJECT_COMPONENT);
96 public void no_event_if_no_raw_ALERT_STATUS_measure() {
97 when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(Optional.<Measure>absent());
101 verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, alertStatusMetric);
102 verifyNoMoreInteractions(measureRepository, eventRepository);
106 public void no_event_created_if_raw_ALERT_STATUS_measure_is_null() {
107 when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(of(Measure.newMeasureBuilder().createNoValue()));
111 verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, alertStatusMetric);
112 verifyNoMoreInteractions(measureRepository, eventRepository);
115 private static Optional<Measure> of(Measure measure) {
116 return Optional.of((Measure) measure);
120 public void no_event_created_if_raw_ALERT_STATUS_measure_is_unsupported_value() {
121 when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(of(Measure.newMeasureBuilder().create(INVALID_ALERT_STATUS)));
125 verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, alertStatusMetric);
126 verifyNoMoreInteractions(measureRepository, eventRepository);
130 public void no_event_created_if_no_base_ALERT_STATUS_and_raw_is_OK() {
131 QualityGateStatus someQGStatus = new QualityGateStatus(Measure.Level.OK);
133 when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(of(Measure.newMeasureBuilder().setQualityGateStatus(someQGStatus).createNoValue()));
134 when(measureRepository.getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(of(Measure.newMeasureBuilder().createNoValue()));
138 verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, alertStatusMetric);
139 verify(measureRepository).getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric);
140 verifyNoMoreInteractions(measureRepository, eventRepository);
144 public void event_created_if_no_base_ALERT_STATUS_and_raw_is_WARN() {
145 verify_event_created_if_no_base_ALERT_STATUS_measure(WARN, "Orange");
149 public void event_created_if_base_ALERT_STATUS_and_raw_is_ERROR() {
150 verify_event_created_if_no_base_ALERT_STATUS_measure(ERROR, "Red");
154 public void event_created_if_base_ALERT_STATUS_has_no_alertStatus_and_raw_is_ERROR() {
155 verify_event_created_if_no_base_ALERT_STATUS_measure(ERROR, "Red");
159 public void event_created_if_base_ALERT_STATUS_has_no_alertStatus_and_raw_is_WARN() {
160 verify_event_created_if_no_base_ALERT_STATUS_measure(WARN, "Orange");
164 public void event_created_if_base_ALERT_STATUS_has_invalid_alertStatus_and_raw_is_ERROR() {
165 verify_event_created_if_no_base_ALERT_STATUS_measure(ERROR, "Red");
169 public void event_created_if_base_ALERT_STATUS_has_invalid_alertStatus_and_raw_is_WARN() {
170 verify_event_created_if_no_base_ALERT_STATUS_measure(WARN, "Orange");
173 private void verify_event_created_if_no_base_ALERT_STATUS_measure(Measure.Level rawAlterStatus, String expectedLabel) {
174 QualityGateStatus someQGStatus = new QualityGateStatus(rawAlterStatus, ALERT_TEXT);
176 when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(of(Measure.newMeasureBuilder().setQualityGateStatus(someQGStatus).createNoValue()));
177 when(measureRepository.getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(of(Measure.newMeasureBuilder().createNoValue()));
181 verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, alertStatusMetric);
182 verify(measureRepository).getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric);
183 verify(eventRepository).add(eq(PROJECT_COMPONENT), eventArgumentCaptor.capture());
184 verifyNoMoreInteractions(measureRepository, eventRepository);
186 Event event = eventArgumentCaptor.getValue();
187 assertThat(event.getCategory()).isEqualTo(Event.Category.ALERT);
188 assertThat(event.getName()).isEqualTo(expectedLabel);
189 assertThat(event.getDescription()).isEqualTo(ALERT_TEXT);
190 assertThat(event.getData()).isNull();
192 verify(notificationService).deliver(notificationArgumentCaptor.capture());
193 Notification notification = notificationArgumentCaptor.getValue();
194 assertThat(notification.getType()).isEqualTo("alerts");
195 assertThat(notification.getFieldValue("projectKey")).isEqualTo(PROJECT_COMPONENT.getPublicKey());
196 assertThat(notification.getFieldValue("projectName")).isEqualTo(PROJECT_COMPONENT.getName());
197 assertThat(notification.getFieldValue("projectVersion")).isEqualTo(PROJECT_COMPONENT.getReportAttributes().getVersion());
198 assertThat(notification.getFieldValue("branch")).isNull();
199 assertThat(notification.getFieldValue("alertLevel")).isEqualTo(rawAlterStatus.name());
200 assertThat(notification.getFieldValue("alertName")).isEqualTo(expectedLabel);
204 public void no_event_created_if_base_ALERT_STATUS_measure_but_status_is_the_same() {
205 when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric))
206 .thenReturn(of(Measure.newMeasureBuilder().setQualityGateStatus(OK_QUALITY_GATE_STATUS).createNoValue()));
207 when(measureRepository.getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric))
208 .thenReturn(of(Measure.newMeasureBuilder().setQualityGateStatus(OK_QUALITY_GATE_STATUS).createNoValue()));
212 verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, alertStatusMetric);
213 verify(measureRepository).getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric);
214 verifyNoMoreInteractions(measureRepository, eventRepository);
218 public void event_created_if_base_ALERT_STATUS_measure_exists_and_status_has_changed() {
219 verify_event_created_if_base_ALERT_STATUS_measure_exists_and_status_has_changed(OK, WARN_QUALITY_GATE_STATUS, "Orange (was Green)");
220 verify_event_created_if_base_ALERT_STATUS_measure_exists_and_status_has_changed(OK, ERROR_QUALITY_GATE_STATUS, "Red (was Green)");
221 verify_event_created_if_base_ALERT_STATUS_measure_exists_and_status_has_changed(WARN, OK_QUALITY_GATE_STATUS, "Green (was Orange)");
222 verify_event_created_if_base_ALERT_STATUS_measure_exists_and_status_has_changed(WARN, ERROR_QUALITY_GATE_STATUS, "Red (was Orange)");
223 verify_event_created_if_base_ALERT_STATUS_measure_exists_and_status_has_changed(ERROR, OK_QUALITY_GATE_STATUS, "Green (was Red)");
224 verify_event_created_if_base_ALERT_STATUS_measure_exists_and_status_has_changed(ERROR, WARN_QUALITY_GATE_STATUS, "Orange (was Red)");
227 private void verify_event_created_if_base_ALERT_STATUS_measure_exists_and_status_has_changed(Measure.Level previousAlertStatus,
228 QualityGateStatus newQualityGateStatus, String expectedLabel) {
229 when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric))
230 .thenReturn(of(Measure.newMeasureBuilder().setQualityGateStatus(newQualityGateStatus).createNoValue()));
231 when(measureRepository.getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(
232 of(Measure.newMeasureBuilder().setQualityGateStatus(new QualityGateStatus(previousAlertStatus)).createNoValue()));
236 verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, alertStatusMetric);
237 verify(measureRepository).getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric);
238 verify(eventRepository).add(eq(PROJECT_COMPONENT), eventArgumentCaptor.capture());
239 verifyNoMoreInteractions(measureRepository, eventRepository);
241 Event event = eventArgumentCaptor.getValue();
242 assertThat(event.getCategory()).isEqualTo(Event.Category.ALERT);
243 assertThat(event.getName()).isEqualTo(expectedLabel);
244 assertThat(event.getDescription()).isEqualTo(ALERT_TEXT);
245 assertThat(event.getData()).isNull();
247 verify(notificationService).deliver(notificationArgumentCaptor.capture());
248 Notification notification = notificationArgumentCaptor.getValue();
249 assertThat(notification.getType()).isEqualTo("alerts");
250 assertThat(notification.getFieldValue("projectKey")).isEqualTo(PROJECT_COMPONENT.getPublicKey());
251 assertThat(notification.getFieldValue("projectName")).isEqualTo(PROJECT_COMPONENT.getName());
252 assertThat(notification.getFieldValue("projectVersion")).isEqualTo(PROJECT_COMPONENT.getReportAttributes().getVersion());
253 assertThat(notification.getFieldValue("branch")).isNull();
254 assertThat(notification.getFieldValue("alertLevel")).isEqualTo(newQualityGateStatus.getStatus().name());
255 assertThat(notification.getFieldValue("alertName")).isEqualTo(expectedLabel);
257 reset(measureRepository, eventRepository, notificationService);
261 public void verify_branch_name_is_set_in_notification_when_not_main() {
262 String branchName = "feature1";
263 analysisMetadataHolder.setBranch(new DefaultBranchImpl(branchName) {
265 public boolean isMain() {
270 when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric))
271 .thenReturn(of(Measure.newMeasureBuilder().setQualityGateStatus(WARN_QUALITY_GATE_STATUS).createNoValue()));
272 when(measureRepository.getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(
273 of(Measure.newMeasureBuilder().setQualityGateStatus(new QualityGateStatus(ERROR)).createNoValue()));
277 verify(notificationService).deliver(notificationArgumentCaptor.capture());
278 Notification notification = notificationArgumentCaptor.getValue();
279 assertThat(notification.getType()).isEqualTo("alerts");
280 assertThat(notification.getFieldValue("projectKey")).isEqualTo(PROJECT_COMPONENT.getPublicKey());
281 assertThat(notification.getFieldValue("projectName")).isEqualTo(PROJECT_COMPONENT.getName());
282 assertThat(notification.getFieldValue("projectVersion")).isEqualTo(PROJECT_COMPONENT.getReportAttributes().getVersion());
283 assertThat(notification.getFieldValue("branch")).isEqualTo(branchName);
285 reset(measureRepository, eventRepository, notificationService);
289 public void verify_branch_name_is_not_set_in_notification_when_main() {
290 analysisMetadataHolder.setBranch(new DefaultBranchImpl());
292 when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric))
293 .thenReturn(of(Measure.newMeasureBuilder().setQualityGateStatus(WARN_QUALITY_GATE_STATUS).createNoValue()));
294 when(measureRepository.getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(
295 of(Measure.newMeasureBuilder().setQualityGateStatus(new QualityGateStatus(ERROR)).createNoValue()));
299 verify(notificationService).deliver(notificationArgumentCaptor.capture());
300 Notification notification = notificationArgumentCaptor.getValue();
301 assertThat(notification.getType()).isEqualTo("alerts");
302 assertThat(notification.getFieldValue("projectKey")).isEqualTo(PROJECT_COMPONENT.getPublicKey());
303 assertThat(notification.getFieldValue("projectName")).isEqualTo(PROJECT_COMPONENT.getName());
304 assertThat(notification.getFieldValue("projectVersion")).isEqualTo(PROJECT_COMPONENT.getReportAttributes().getVersion());
305 assertThat(notification.getFieldValue("branch")).isEqualTo(null);
307 reset(measureRepository, eventRepository, notificationService);
311 public void no_alert_on_short_living_branches() {
312 Branch shortBranch = mock(Branch.class);
313 when(shortBranch.getType()).thenReturn(BranchType.SHORT);
314 analysisMetadataHolder.setBranch(shortBranch);
315 TreeRootHolder treeRootHolder = mock(TreeRootHolder.class);
316 MetricRepository metricRepository = mock(MetricRepository.class);
317 MeasureRepository measureRepository = mock(MeasureRepository.class);
318 EventRepository eventRepository = mock(EventRepository.class);
319 NotificationService notificationService = mock(NotificationService.class);
321 QualityGateEventsStep underTest = new QualityGateEventsStep(treeRootHolder, metricRepository, measureRepository,
322 eventRepository, notificationService, analysisMetadataHolder);
326 verifyZeroInteractions(treeRootHolder, metricRepository, measureRepository, eventRepository, notificationService);