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