]> source.dussan.org Git - sonarqube.git/blob
6b85ad907e44c684bb6bc8ae47146acde78ae047
[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.server.issue.notification;
21
22 import java.util.Collections;
23 import java.util.Random;
24 import java.util.Set;
25 import java.util.stream.Collectors;
26 import java.util.stream.IntStream;
27 import java.util.stream.Stream;
28 import javax.annotation.Nullable;
29 import org.junit.Test;
30 import org.mockito.Mockito;
31 import org.sonar.server.notification.NotificationDispatcherMetadata;
32 import org.sonar.server.notification.NotificationManager;
33 import org.sonar.server.notification.NotificationManager.EmailRecipient;
34 import org.sonar.server.notification.email.EmailNotificationChannel;
35 import org.sonar.server.notification.email.EmailNotificationChannel.EmailDeliveryRequest;
36
37 import static java.util.Collections.emptySet;
38 import static java.util.stream.Collectors.toSet;
39 import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
40 import static org.assertj.core.api.Assertions.assertThat;
41 import static org.mockito.Mockito.mock;
42 import static org.mockito.Mockito.verify;
43 import static org.mockito.Mockito.verifyNoInteractions;
44 import static org.mockito.Mockito.verifyNoMoreInteractions;
45 import static org.mockito.Mockito.when;
46 import static org.sonar.server.notification.NotificationDispatcherMetadata.GLOBAL_NOTIFICATION;
47 import static org.sonar.server.notification.NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION;
48 import static org.sonar.server.notification.NotificationManager.SubscriberPermissionsOnProject.ALL_MUST_HAVE_ROLE_USER;
49
50 public class NewIssuesNotificationHandlerTest {
51   private static final String NEW_ISSUES_DISPATCHER_KEY = "NewIssues";
52   private NotificationManager notificationManager = mock(NotificationManager.class);
53   private EmailNotificationChannel emailNotificationChannel = mock(EmailNotificationChannel.class);
54   private NewIssuesNotificationHandler underTest = new NewIssuesNotificationHandler(notificationManager, emailNotificationChannel);
55
56   @Test
57   public void getMetadata_returns_same_instance_as_static_method() {
58     assertThat(underTest.getMetadata()).containsSame(NewIssuesNotificationHandler.newMetadata());
59   }
60
61   @Test
62   public void verify_myNewIssues_notification_dispatcher_key() {
63     NotificationDispatcherMetadata metadata = NewIssuesNotificationHandler.newMetadata();
64
65     assertThat(metadata.getDispatcherKey()).isEqualTo(NEW_ISSUES_DISPATCHER_KEY);
66   }
67
68   @Test
69   public void myNewIssues_notification_is_disabled_at_global_level() {
70     NotificationDispatcherMetadata metadata = NewIssuesNotificationHandler.newMetadata();
71
72     assertThat(metadata.getProperty(GLOBAL_NOTIFICATION)).isEqualTo("false");
73   }
74
75   @Test
76   public void myNewIssues_notification_is_enable_at_project_level() {
77     NotificationDispatcherMetadata metadata = NewIssuesNotificationHandler.newMetadata();
78
79     assertThat(metadata.getProperty(PER_PROJECT_NOTIFICATION)).isEqualTo("true");
80   }
81
82   @Test
83   public void getNotificationClass_is_NewIssuesNotification() {
84     assertThat(underTest.getNotificationClass()).isEqualTo(NewIssuesNotification.class);
85   }
86
87   @Test
88   public void deliver_has_no_effect_if_notifications_is_empty() {
89     when(emailNotificationChannel.isActivated()).thenReturn(true);
90     int deliver = underTest.deliver(Collections.emptyList());
91
92     assertThat(deliver).isZero();
93     verifyNoInteractions(notificationManager, emailNotificationChannel);
94   }
95
96   @Test
97   public void deliver_has_no_effect_if_emailNotificationChannel_is_disabled() {
98     when(emailNotificationChannel.isActivated()).thenReturn(false);
99     Set<NewIssuesNotification> notifications = IntStream.range(0, 1 + new Random().nextInt(10))
100       .mapToObj(i -> mock(NewIssuesNotification.class))
101       .collect(toSet());
102
103     int deliver = underTest.deliver(notifications);
104
105     assertThat(deliver).isZero();
106     verifyNoInteractions(notificationManager);
107     verify(emailNotificationChannel).isActivated();
108     verifyNoMoreInteractions(emailNotificationChannel);
109     notifications.forEach(Mockito::verifyNoInteractions);
110   }
111
112   @Test
113   public void deliver_has_no_effect_if_no_notification_has_projectKey() {
114     when(emailNotificationChannel.isActivated()).thenReturn(true);
115     Set<NewIssuesNotification> notifications = IntStream.range(0, 1 + new Random().nextInt(10))
116       .mapToObj(i -> newNotification(null))
117       .collect(toSet());
118
119     int deliver = underTest.deliver(notifications);
120
121     assertThat(deliver).isZero();
122     verifyNoInteractions(notificationManager);
123     verify(emailNotificationChannel).isActivated();
124     verifyNoMoreInteractions(emailNotificationChannel);
125     notifications.forEach(notification -> {
126       verify(notification).getProjectKey();
127       verifyNoMoreInteractions(notification);
128     });
129   }
130
131   @Test
132   public void deliver_has_no_effect_if_no_notification_has_subscribed_recipients_to_NewIssue_notifications() {
133     String projectKey = randomAlphabetic(12);
134     NewIssuesNotification notification = newNotification(projectKey);
135     when(emailNotificationChannel.isActivated()).thenReturn(true);
136     when(notificationManager.findSubscribedEmailRecipients(NEW_ISSUES_DISPATCHER_KEY, projectKey, ALL_MUST_HAVE_ROLE_USER))
137       .thenReturn(emptySet());
138
139     int deliver = underTest.deliver(Collections.singleton(notification));
140
141     assertThat(deliver).isZero();
142     verify(notificationManager).findSubscribedEmailRecipients(NEW_ISSUES_DISPATCHER_KEY, projectKey, ALL_MUST_HAVE_ROLE_USER);
143     verifyNoMoreInteractions(notificationManager);
144     verify(emailNotificationChannel).isActivated();
145     verifyNoMoreInteractions(emailNotificationChannel);
146   }
147
148   @Test
149   public void deliver_ignores_notification_without_projectKey() {
150     String projectKey = randomAlphabetic(10);
151     Set<NewIssuesNotification> withProjectKey = IntStream.range(0, 1 + new Random().nextInt(5))
152       .mapToObj(i -> newNotification(projectKey))
153       .collect(toSet());
154     Set<NewIssuesNotification> noProjectKey = IntStream.range(0, 1 + new Random().nextInt(5))
155       .mapToObj(i -> newNotification(null))
156       .collect(toSet());
157     Set<EmailRecipient> emailRecipients = IntStream.range(0, 1 + new Random().nextInt(10))
158       .mapToObj(i -> "user_" + i)
159       .map(login -> new EmailRecipient(login, emailOf(login)))
160       .collect(toSet());
161     Set<EmailDeliveryRequest> expectedRequests = emailRecipients.stream()
162       .flatMap(emailRecipient -> withProjectKey.stream().map(notif -> new EmailDeliveryRequest(emailRecipient.email(), notif)))
163       .collect(toSet());
164     when(emailNotificationChannel.isActivated()).thenReturn(true);
165     when(notificationManager.findSubscribedEmailRecipients(NEW_ISSUES_DISPATCHER_KEY, projectKey, ALL_MUST_HAVE_ROLE_USER))
166       .thenReturn(emailRecipients);
167
168     Set<NewIssuesNotification> notifications = Stream.of(withProjectKey.stream(), noProjectKey.stream())
169       .flatMap(t -> t)
170       .collect(toSet());
171     int deliver = underTest.deliver(notifications);
172
173     assertThat(deliver).isZero();
174     verify(notificationManager).findSubscribedEmailRecipients(NEW_ISSUES_DISPATCHER_KEY, projectKey, ALL_MUST_HAVE_ROLE_USER);
175     verifyNoMoreInteractions(notificationManager);
176     verify(emailNotificationChannel).isActivated();
177     verify(emailNotificationChannel).deliverAll(expectedRequests);
178     verifyNoMoreInteractions(emailNotificationChannel);
179   }
180
181   @Test
182   public void deliver_checks_by_projectKey_if_notifications_have_subscribed_assignee_to_NewIssue_notifications() {
183     String projectKey1 = randomAlphabetic(10);
184     String projectKey2 = randomAlphabetic(11);
185     Set<NewIssuesNotification> notifications1 = randomSetOfNotifications(projectKey1);
186     Set<NewIssuesNotification> notifications2 = randomSetOfNotifications(projectKey2);
187     when(emailNotificationChannel.isActivated()).thenReturn(true);
188
189     Set<EmailRecipient> emailRecipients1 = IntStream.range(0, 1 + new Random().nextInt(10))
190       .mapToObj(i -> "user1_" + i)
191       .map(login -> new EmailRecipient(login, emailOf(login)))
192       .collect(toSet());
193     Set<EmailRecipient> emailRecipients2 = IntStream.range(0, 1 + new Random().nextInt(10))
194       .mapToObj(i -> "user2_" + i)
195       .map(login -> new EmailRecipient(login, emailOf(login)))
196       .collect(toSet());
197     when(notificationManager.findSubscribedEmailRecipients(NEW_ISSUES_DISPATCHER_KEY, projectKey1, ALL_MUST_HAVE_ROLE_USER))
198       .thenReturn(emailRecipients1);
199     when(notificationManager.findSubscribedEmailRecipients(NEW_ISSUES_DISPATCHER_KEY, projectKey2, ALL_MUST_HAVE_ROLE_USER))
200       .thenReturn(emailRecipients2);
201     Set<EmailDeliveryRequest> expectedRequests = Stream.concat(
202       emailRecipients1.stream()
203         .flatMap(emailRecipient -> notifications1.stream().map(notif -> new EmailDeliveryRequest(emailRecipient.email(), notif))),
204       emailRecipients2.stream()
205         .flatMap(emailRecipient -> notifications2.stream().map(notif -> new EmailDeliveryRequest(emailRecipient.email(), notif))))
206       .collect(toSet());
207
208     int deliver = underTest.deliver(Stream.concat(notifications1.stream(), notifications2.stream()).collect(toSet()));
209
210     assertThat(deliver).isZero();
211     verify(notificationManager).findSubscribedEmailRecipients(NEW_ISSUES_DISPATCHER_KEY, projectKey1, ALL_MUST_HAVE_ROLE_USER);
212     verify(notificationManager).findSubscribedEmailRecipients(NEW_ISSUES_DISPATCHER_KEY, projectKey2, ALL_MUST_HAVE_ROLE_USER);
213     verifyNoMoreInteractions(notificationManager);
214     verify(emailNotificationChannel).isActivated();
215     verify(emailNotificationChannel).deliverAll(expectedRequests);
216     verifyNoMoreInteractions(emailNotificationChannel);
217   }
218
219   @Test
220   public void deliver_send_notifications_to_all_subscribers_of_all_projects() {
221     String projectKey1 = randomAlphabetic(10);
222     String projectKey2 = randomAlphabetic(11);
223     Set<NewIssuesNotification> notifications1 = randomSetOfNotifications(projectKey1);
224     Set<NewIssuesNotification> notifications2 = randomSetOfNotifications(projectKey2);
225     when(emailNotificationChannel.isActivated()).thenReturn(true);
226     when(notificationManager.findSubscribedEmailRecipients(NEW_ISSUES_DISPATCHER_KEY, projectKey1, ALL_MUST_HAVE_ROLE_USER))
227       .thenReturn(emptySet());
228     when(notificationManager.findSubscribedEmailRecipients(NEW_ISSUES_DISPATCHER_KEY, projectKey2, ALL_MUST_HAVE_ROLE_USER))
229       .thenReturn(emptySet());
230
231     int deliver = underTest.deliver(Stream.concat(notifications1.stream(), notifications2.stream()).collect(toSet()));
232
233     assertThat(deliver).isZero();
234     verify(notificationManager).findSubscribedEmailRecipients(NEW_ISSUES_DISPATCHER_KEY, projectKey1, ALL_MUST_HAVE_ROLE_USER);
235     verify(notificationManager).findSubscribedEmailRecipients(NEW_ISSUES_DISPATCHER_KEY, projectKey2, ALL_MUST_HAVE_ROLE_USER);
236     verifyNoMoreInteractions(notificationManager);
237     verify(emailNotificationChannel).isActivated();
238     verifyNoMoreInteractions(emailNotificationChannel);
239   }
240
241   private static Set<NewIssuesNotification> randomSetOfNotifications(@Nullable String projectKey) {
242     return IntStream.range(0, 1 + new Random().nextInt(5))
243       .mapToObj(i -> newNotification(projectKey))
244       .collect(Collectors.toSet());
245   }
246
247   private static NewIssuesNotification newNotification(@Nullable String projectKey) {
248     NewIssuesNotification notification = mock(NewIssuesNotification.class);
249     when(notification.getProjectKey()).thenReturn(projectKey);
250     return notification;
251   }
252
253   private static String emailOf(String assignee1) {
254     return assignee1 + "@donut";
255   }
256
257 }