3 * Copyright (C) 2009-2022 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.issue.notification;
22 import com.google.common.collect.ImmutableSet;
23 import com.google.common.collect.ListMultimap;
24 import com.tngtech.java.junit.dataprovider.DataProvider;
25 import com.tngtech.java.junit.dataprovider.DataProviderRunner;
26 import com.tngtech.java.junit.dataprovider.UseDataProvider;
27 import java.util.Random;
29 import java.util.function.Consumer;
30 import java.util.stream.IntStream;
31 import java.util.stream.Stream;
32 import org.junit.Test;
33 import org.junit.runner.RunWith;
34 import org.mockito.ArgumentCaptor;
35 import org.mockito.Mockito;
36 import org.sonar.api.issue.Issue;
37 import org.sonar.server.issue.notification.FPOrWontFixNotification.FpOrWontFix;
38 import org.sonar.server.issue.notification.IssuesChangesNotificationBuilder.Change;
39 import org.sonar.server.issue.notification.IssuesChangesNotificationBuilder.ChangedIssue;
40 import org.sonar.server.issue.notification.IssuesChangesNotificationBuilder.Project;
41 import org.sonar.server.issue.notification.IssuesChangesNotificationBuilder.User;
42 import org.sonar.server.issue.notification.IssuesChangesNotificationBuilder.UserChange;
43 import org.sonar.server.notification.NotificationDispatcherMetadata;
44 import org.sonar.server.notification.NotificationManager;
45 import org.sonar.server.notification.email.EmailNotificationChannel;
46 import org.sonar.server.notification.email.EmailNotificationChannel.EmailDeliveryRequest;
48 import static java.util.Collections.singleton;
49 import static java.util.stream.Collectors.toSet;
50 import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
51 import static org.assertj.core.api.Assertions.assertThat;
52 import static org.junit.Assert.fail;
53 import static org.mockito.ArgumentMatchers.any;
54 import static org.mockito.ArgumentMatchers.anySet;
55 import static org.mockito.Mockito.mock;
56 import static org.mockito.Mockito.reset;
57 import static org.mockito.Mockito.spy;
58 import static org.mockito.Mockito.times;
59 import static org.mockito.Mockito.verify;
60 import static org.mockito.Mockito.verifyNoMoreInteractions;
61 import static org.mockito.Mockito.verifyZeroInteractions;
62 import static org.mockito.Mockito.when;
63 import static org.sonar.api.issue.Issue.RESOLUTION_FALSE_POSITIVE;
64 import static org.sonar.api.issue.Issue.RESOLUTION_WONT_FIX;
65 import static org.sonar.core.util.stream.MoreCollectors.index;
66 import static org.sonar.server.issue.notification.IssuesChangesNotificationBuilderTesting.newProject;
67 import static org.sonar.server.issue.notification.IssuesChangesNotificationBuilderTesting.newRandomNotAHotspotRule;
68 import static org.sonar.server.notification.NotificationDispatcherMetadata.GLOBAL_NOTIFICATION;
69 import static org.sonar.server.notification.NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION;
70 import static org.sonar.server.notification.NotificationManager.SubscriberPermissionsOnProject.ALL_MUST_HAVE_ROLE_USER;
72 @RunWith(DataProviderRunner.class)
73 public class FPOrWontFixNotificationHandlerTest {
74 private static final String DO_NOT_FIX_ISSUE_CHANGE_DISPATCHER_KEY = "NewFalsePositiveIssue";
75 private NotificationManager notificationManager = mock(NotificationManager.class);
76 private EmailNotificationChannel emailNotificationChannel = mock(EmailNotificationChannel.class);
77 private IssuesChangesNotificationSerializer serializerMock = mock(IssuesChangesNotificationSerializer.class);
78 private IssuesChangesNotificationSerializer serializer = spy(new IssuesChangesNotificationSerializer());
79 private Class<Set<EmailDeliveryRequest>> requestSetType = (Class<Set<EmailDeliveryRequest>>) (Class<?>) Set.class;
80 private FPOrWontFixNotificationHandler underTest = new FPOrWontFixNotificationHandler(notificationManager, emailNotificationChannel, serializer);
83 public void getMetadata_returns_same_instance_as_static_method() {
84 assertThat(underTest.getMetadata().get()).isSameAs(FPOrWontFixNotificationHandler.newMetadata());
88 public void verify_fpOrWontFixIssues_notification_dispatcher_key() {
89 NotificationDispatcherMetadata metadata = FPOrWontFixNotificationHandler.newMetadata();
91 assertThat(metadata.getDispatcherKey()).isEqualTo(DO_NOT_FIX_ISSUE_CHANGE_DISPATCHER_KEY);
95 public void fpOrWontFixIssues_notification_is_disabled_at_global_level() {
96 NotificationDispatcherMetadata metadata = FPOrWontFixNotificationHandler.newMetadata();
98 assertThat(metadata.getProperty(GLOBAL_NOTIFICATION)).isEqualTo("false");
102 public void fpOrWontFixIssues_notification_is_enable_at_project_level() {
103 NotificationDispatcherMetadata metadata = FPOrWontFixNotificationHandler.newMetadata();
105 assertThat(metadata.getProperty(PER_PROJECT_NOTIFICATION)).isEqualTo("true");
109 public void getNotificationClass_is_IssueChangeNotification() {
110 assertThat(underTest.getNotificationClass()).isEqualTo(IssuesChangesNotification.class);
114 public void deliver_has_no_effect_if_emailNotificationChannel_is_disabled() {
115 when(emailNotificationChannel.isActivated()).thenReturn(false);
116 Set<IssuesChangesNotification> notifications = IntStream.range(0, 1 + new Random().nextInt(10))
117 .mapToObj(i -> mock(IssuesChangesNotification.class))
120 int deliver = underTest.deliver(notifications);
122 assertThat(deliver).isZero();
123 verifyZeroInteractions(notificationManager);
124 verify(emailNotificationChannel).isActivated();
125 verifyNoMoreInteractions(emailNotificationChannel);
126 notifications.forEach(Mockito::verifyZeroInteractions);
130 public void deliver_parses_every_notification_in_order() {
131 Set<IssuesChangesNotification> notifications = IntStream.range(0, 5 + new Random().nextInt(10))
132 .mapToObj(i -> mock(IssuesChangesNotification.class))
134 when(emailNotificationChannel.isActivated()).thenReturn(true);
135 when(serializerMock.from(any(IssuesChangesNotification.class))).thenReturn(mock(IssuesChangesNotificationBuilder.class));
136 FPOrWontFixNotificationHandler underTest = new FPOrWontFixNotificationHandler(notificationManager, emailNotificationChannel, serializerMock);
138 underTest.deliver(notifications);
140 notifications.forEach(notification -> verify(serializerMock).from(notification));
144 public void deliver_fails_with_IAE_if_serializer_throws_IAE() {
145 Set<IssuesChangesNotification> notifications = IntStream.range(0, 3 + new Random().nextInt(10))
146 .mapToObj(i -> mock(IssuesChangesNotification.class))
148 when(emailNotificationChannel.isActivated()).thenReturn(true);
149 IllegalArgumentException expected = new IllegalArgumentException("faking serializer#from throwing a IllegalArgumentException");
150 when(serializerMock.from(any(IssuesChangesNotification.class)))
151 .thenReturn(mock(IssuesChangesNotificationBuilder.class))
152 .thenReturn(mock(IssuesChangesNotificationBuilder.class))
153 .thenThrow(expected);
154 FPOrWontFixNotificationHandler underTest = new FPOrWontFixNotificationHandler(notificationManager, emailNotificationChannel, serializerMock);
157 underTest.deliver(notifications);
158 fail("should have throws IAE");
159 } catch (IllegalArgumentException e) {
160 verify(serializerMock, times(3)).from(any(IssuesChangesNotification.class));
161 assertThat(e).isSameAs(expected);
166 public void deliver_has_no_effect_if_no_issue_has_new_resolution() {
167 when(emailNotificationChannel.isActivated()).thenReturn(true);
168 Change changeMock = mock(Change.class);
169 Set<IssuesChangesNotification> notifications = IntStream.range(0, 2 + new Random().nextInt(5))
170 .mapToObj(j -> new IssuesChangesNotificationBuilder(randomIssues(t -> t.setNewResolution(null)).collect(toSet()), changeMock))
171 .map(serializer::serialize)
175 int deliver = underTest.deliver(notifications);
177 assertThat(deliver).isZero();
178 verify(serializer, times(notifications.size())).from(any(IssuesChangesNotification.class));
179 verifyZeroInteractions(changeMock);
180 verifyNoMoreInteractions(serializer);
181 verifyZeroInteractions(notificationManager);
182 verify(emailNotificationChannel).isActivated();
183 verifyNoMoreInteractions(emailNotificationChannel);
187 @UseDataProvider("notFPorWontFixResolution")
188 public void deliver_has_no_effect_if_no_issue_has_FP_or_wontfix_resolution(String newResolution) {
189 when(emailNotificationChannel.isActivated()).thenReturn(true);
190 Change changeMock = mock(Change.class);
191 Set<IssuesChangesNotification> notifications = IntStream.range(0, 2 + new Random().nextInt(5))
192 .mapToObj(j -> new IssuesChangesNotificationBuilder(randomIssues(t -> t.setNewResolution(newResolution)).collect(toSet()), changeMock))
193 .map(serializer::serialize)
197 int deliver = underTest.deliver(notifications);
199 assertThat(deliver).isZero();
200 verify(serializer, times(notifications.size())).from(any(IssuesChangesNotification.class));
201 verifyZeroInteractions(changeMock);
202 verifyNoMoreInteractions(serializer);
203 verifyZeroInteractions(notificationManager);
204 verify(emailNotificationChannel).isActivated();
205 verifyNoMoreInteractions(emailNotificationChannel);
209 public static Object[][] notFPorWontFixResolution() {
210 return new Object[][] {
212 {randomAlphabetic(9)},
213 {Issue.RESOLUTION_FIXED},
214 {Issue.RESOLUTION_REMOVED}
219 @UseDataProvider("FPorWontFixResolution")
220 public void deliver_checks_by_projectKey_if_notifications_have_subscribed_assignee_to_FPorWontFix_notifications(String newResolution) {
221 Project projectKey1 = newProject(randomAlphabetic(4));
222 Project projectKey2 = newProject(randomAlphabetic(5));
223 Project projectKey3 = newProject(randomAlphabetic(6));
224 Project projectKey4 = newProject(randomAlphabetic(7));
225 Change changeMock = mock(Change.class);
226 // some notifications with some issues on project1
227 Stream<IssuesChangesNotificationBuilder> project1Notifications = IntStream.range(0, 1 + new Random().nextInt(2))
228 .mapToObj(j -> new IssuesChangesNotificationBuilder(
229 randomIssues(t -> t.setProject(projectKey1).setNewResolution(newResolution)).collect(toSet()),
231 // some notifications with some issues on project2
232 Stream<IssuesChangesNotificationBuilder> project2Notifications = IntStream.range(0, 1 + new Random().nextInt(2))
233 .mapToObj(j -> new IssuesChangesNotificationBuilder(
234 randomIssues(t -> t.setProject(projectKey2).setNewResolution(newResolution)).collect(toSet()),
236 // some notifications with some issues on project3 and project 4
237 Stream<IssuesChangesNotificationBuilder> project3And4Notifications = IntStream.range(0, 1 + new Random().nextInt(2))
238 .mapToObj(j -> new IssuesChangesNotificationBuilder(
240 randomIssues(t -> t.setProject(projectKey3).setNewResolution(newResolution)),
241 randomIssues(t -> t.setProject(projectKey4).setNewResolution(newResolution)))
244 when(emailNotificationChannel.isActivated()).thenReturn(true);
246 Set<IssuesChangesNotification> notifications = Stream.of(project1Notifications, project2Notifications, project3And4Notifications)
248 .map(serializer::serialize)
250 int deliver = underTest.deliver(notifications);
252 assertThat(deliver).isZero();
253 verify(notificationManager).findSubscribedEmailRecipients(DO_NOT_FIX_ISSUE_CHANGE_DISPATCHER_KEY, projectKey1.getKey(), ALL_MUST_HAVE_ROLE_USER);
254 verify(notificationManager).findSubscribedEmailRecipients(DO_NOT_FIX_ISSUE_CHANGE_DISPATCHER_KEY, projectKey2.getKey(), ALL_MUST_HAVE_ROLE_USER);
255 verify(notificationManager).findSubscribedEmailRecipients(DO_NOT_FIX_ISSUE_CHANGE_DISPATCHER_KEY, projectKey3.getKey(), ALL_MUST_HAVE_ROLE_USER);
256 verify(notificationManager).findSubscribedEmailRecipients(DO_NOT_FIX_ISSUE_CHANGE_DISPATCHER_KEY, projectKey4.getKey(), ALL_MUST_HAVE_ROLE_USER);
257 verifyNoMoreInteractions(notificationManager);
258 verify(emailNotificationChannel).isActivated();
259 verifyNoMoreInteractions(emailNotificationChannel);
260 verifyZeroInteractions(changeMock);
264 @UseDataProvider("FPorWontFixResolution")
265 public void deliver_does_not_send_email_request_for_notifications_a_subscriber_is_the_changeAuthor_of(String newResolution) {
266 Project project = newProject(randomAlphabetic(5));
267 User subscriber1 = newUser("subscriber1");
268 User subscriber2 = newUser("subscriber2");
269 User subscriber3 = newUser("subscriber3");
270 User otherChangeAuthor = newUser("otherChangeAuthor");
272 // subscriber1 is the changeAuthor of some notifications with issues assigned to subscriber1 only
273 Set<IssuesChangesNotificationBuilder> subscriber1Notifications = IntStream.range(0, 1 + new Random().nextInt(2))
274 .mapToObj(j -> new IssuesChangesNotificationBuilder(
275 randomIssues(t -> t.setProject(project).setNewResolution(newResolution).setAssignee(subscriber2)).collect(toSet()),
276 newUserChange(subscriber1)))
278 // subscriber1 is the changeAuthor of some notifications with issues assigned to subscriber1 and subscriber2
279 Set<IssuesChangesNotificationBuilder> subscriber1and2Notifications = IntStream.range(0, 1 + new Random().nextInt(2))
280 .mapToObj(j -> new IssuesChangesNotificationBuilder(
282 randomIssues(t -> t.setProject(project).setNewResolution(newResolution).setAssignee(subscriber2)),
283 randomIssues(t -> t.setProject(project).setNewResolution(newResolution).setAssignee(subscriber1)))
285 newUserChange(subscriber1)))
287 // subscriber2 is the changeAuthor of some notifications with issues assigned to subscriber2 only
288 Set<IssuesChangesNotificationBuilder> subscriber2Notifications = IntStream.range(0, 1 + new Random().nextInt(2))
289 .mapToObj(j -> new IssuesChangesNotificationBuilder(
290 randomIssues(t -> t.setProject(project).setNewResolution(newResolution).setAssignee(subscriber2)).collect(toSet()),
291 newUserChange(subscriber2)))
293 // subscriber2 is the changeAuthor of some notifications with issues assigned to subscriber2 and subscriber 3
294 Set<IssuesChangesNotificationBuilder> subscriber2And3Notifications = IntStream.range(0, 1 + new Random().nextInt(2))
295 .mapToObj(j -> new IssuesChangesNotificationBuilder(
297 randomIssues(t -> t.setProject(project).setNewResolution(newResolution).setAssignee(subscriber2)),
298 randomIssues(t -> t.setProject(project).setNewResolution(newResolution).setAssignee(subscriber3)))
300 newUserChange(subscriber2)))
302 // subscriber3 is the changeAuthor of no notification
303 // otherChangeAuthor has some notifications
304 Set<IssuesChangesNotificationBuilder> otherChangeAuthorNotifications = IntStream.range(0, 1 + new Random().nextInt(2))
305 .mapToObj(j -> new IssuesChangesNotificationBuilder(randomIssues(t -> t.setProject(project).setNewResolution(newResolution)).collect(toSet()),
306 newUserChange(otherChangeAuthor)))
308 when(emailNotificationChannel.isActivated()).thenReturn(true);
310 Set<String> subscriberLogins = ImmutableSet.of(subscriber1.getLogin(), subscriber2.getLogin(), subscriber3.getLogin());
311 when(notificationManager.findSubscribedEmailRecipients(DO_NOT_FIX_ISSUE_CHANGE_DISPATCHER_KEY, project.getKey(), ALL_MUST_HAVE_ROLE_USER))
312 .thenReturn(subscriberLogins.stream().map(FPOrWontFixNotificationHandlerTest::emailRecipientOf).collect(toSet()));
314 int deliveredCount = new Random().nextInt(200);
315 when(emailNotificationChannel.deliverAll(anySet()))
316 .thenReturn(deliveredCount)
317 .thenThrow(new IllegalStateException("deliver should be called only once"));
319 Set<IssuesChangesNotification> notifications = Stream.of(
320 subscriber1Notifications.stream(),
321 subscriber1and2Notifications.stream(),
322 subscriber2Notifications.stream(),
323 subscriber2And3Notifications.stream(),
324 otherChangeAuthorNotifications.stream())
326 .map(serializer::serialize)
330 int deliver = underTest.deliver(notifications);
332 assertThat(deliver).isEqualTo(deliveredCount);
333 verify(notificationManager).findSubscribedEmailRecipients(DO_NOT_FIX_ISSUE_CHANGE_DISPATCHER_KEY, project.getKey(), ALL_MUST_HAVE_ROLE_USER);
334 verifyNoMoreInteractions(notificationManager);
335 verify(emailNotificationChannel).isActivated();
336 ArgumentCaptor<Set<EmailDeliveryRequest>> captor = ArgumentCaptor.forClass(requestSetType);
337 verify(emailNotificationChannel).deliverAll(captor.capture());
338 verifyNoMoreInteractions(emailNotificationChannel);
339 ListMultimap<String, EmailDeliveryRequest> requestsByRecipientEmail = captor.getValue().stream()
340 .collect(index(EmailDeliveryRequest::getRecipientEmail));
341 assertThat(requestsByRecipientEmail.get(emailOf(subscriber1.getLogin())))
344 subscriber2Notifications.stream()
345 .map(notif -> newEmailDeliveryRequest(notif, subscriber1, toFpOrWontFix(newResolution))),
346 subscriber2And3Notifications.stream()
347 .map(notif -> newEmailDeliveryRequest(notif, subscriber1, toFpOrWontFix(newResolution))),
348 otherChangeAuthorNotifications.stream()
349 .map(notif -> newEmailDeliveryRequest(notif, subscriber1, toFpOrWontFix(newResolution))))
351 .toArray(EmailDeliveryRequest[]::new));
352 assertThat(requestsByRecipientEmail.get(emailOf(subscriber2.getLogin())))
355 subscriber1Notifications.stream()
356 .map(notif -> newEmailDeliveryRequest(notif, subscriber2, toFpOrWontFix(newResolution))),
357 subscriber1and2Notifications.stream()
358 .map(notif -> newEmailDeliveryRequest(notif, subscriber2, toFpOrWontFix(newResolution))),
359 otherChangeAuthorNotifications.stream()
360 .map(notif -> newEmailDeliveryRequest(notif, subscriber2, toFpOrWontFix(newResolution))))
362 .toArray(EmailDeliveryRequest[]::new));
363 assertThat(requestsByRecipientEmail.get(emailOf(subscriber3.getLogin())))
366 subscriber1Notifications.stream()
367 .map(notif -> newEmailDeliveryRequest(notif, subscriber3, toFpOrWontFix(newResolution))),
368 subscriber1and2Notifications.stream()
369 .map(notif -> newEmailDeliveryRequest(notif, subscriber3, toFpOrWontFix(newResolution))),
370 subscriber2Notifications.stream()
371 .map(notif -> newEmailDeliveryRequest(notif, subscriber3, toFpOrWontFix(newResolution))),
372 subscriber2And3Notifications.stream()
373 .map(notif -> newEmailDeliveryRequest(notif, subscriber3, toFpOrWontFix(newResolution))),
374 otherChangeAuthorNotifications.stream()
375 .map(notif -> newEmailDeliveryRequest(notif, subscriber3, toFpOrWontFix(newResolution))))
377 .toArray(EmailDeliveryRequest[]::new));
378 assertThat(requestsByRecipientEmail.get(emailOf(otherChangeAuthor.getLogin())))
383 @UseDataProvider("oneOrMoreProjectCounts")
384 public void deliver_send_a_separated_email_request_for_FPs_and_Wont_Fix_issues(int projectCount) {
385 Set<Project> projects = IntStream.range(0, projectCount).mapToObj(i -> newProject("prk_key_" + i)).collect(toSet());
386 User subscriber1 = newUser("subscriber1");
387 User changeAuthor = newUser("changeAuthor");
389 Set<ChangedIssue> fpIssues = projects.stream()
390 .flatMap(project -> randomIssues(t -> t.setProject(project).setNewResolution(RESOLUTION_FALSE_POSITIVE).setAssignee(subscriber1)))
392 Set<ChangedIssue> wontFixIssues = projects.stream()
393 .flatMap(project -> randomIssues(t -> t.setProject(project).setNewResolution(RESOLUTION_WONT_FIX).setAssignee(subscriber1)))
395 UserChange userChange = newUserChange(changeAuthor);
396 IssuesChangesNotificationBuilder fpAndWontFixNotifications = new IssuesChangesNotificationBuilder(
397 Stream.concat(fpIssues.stream(), wontFixIssues.stream()).collect(toSet()),
399 when(emailNotificationChannel.isActivated()).thenReturn(true);
400 projects.forEach(project -> when(notificationManager.findSubscribedEmailRecipients(DO_NOT_FIX_ISSUE_CHANGE_DISPATCHER_KEY, project.getKey(), ALL_MUST_HAVE_ROLE_USER))
401 .thenReturn(singleton(emailRecipientOf(subscriber1.getLogin()))));
403 int deliveredCount = new Random().nextInt(200);
404 when(emailNotificationChannel.deliverAll(anySet()))
405 .thenReturn(deliveredCount)
406 .thenThrow(new IllegalStateException("deliver should be called only once"));
407 Set<IssuesChangesNotification> notifications = singleton(serializer.serialize(fpAndWontFixNotifications));
410 int deliver = underTest.deliver(notifications);
412 assertThat(deliver).isEqualTo(deliveredCount);
414 .forEach(project -> verify(notificationManager).findSubscribedEmailRecipients(DO_NOT_FIX_ISSUE_CHANGE_DISPATCHER_KEY, project.getKey(), ALL_MUST_HAVE_ROLE_USER));
415 verifyNoMoreInteractions(notificationManager);
416 verify(emailNotificationChannel).isActivated();
417 ArgumentCaptor<Set<EmailDeliveryRequest>> captor = ArgumentCaptor.forClass(requestSetType);
418 verify(emailNotificationChannel).deliverAll(captor.capture());
419 verifyNoMoreInteractions(emailNotificationChannel);
420 ListMultimap<String, EmailDeliveryRequest> requestsByRecipientEmail = captor.getValue().stream()
421 .collect(index(EmailDeliveryRequest::getRecipientEmail));
422 assertThat(requestsByRecipientEmail.get(emailOf(subscriber1.getLogin())))
424 new EmailDeliveryRequest(emailOf(subscriber1.getLogin()), new FPOrWontFixNotification(
425 userChange, wontFixIssues, FpOrWontFix.WONT_FIX)),
426 new EmailDeliveryRequest(emailOf(subscriber1.getLogin()), new FPOrWontFixNotification(
427 userChange, fpIssues, FpOrWontFix.FP)));
431 public static Object[][] oneOrMoreProjectCounts() {
432 return new Object[][] {
434 {2 + new Random().nextInt(3)},
438 private static EmailDeliveryRequest newEmailDeliveryRequest(IssuesChangesNotificationBuilder notif, User user, FpOrWontFix resolution) {
439 return new EmailDeliveryRequest(
440 emailOf(user.getLogin()),
441 new FPOrWontFixNotification(notif.getChange(), notif.getIssues(), resolution));
444 private static FpOrWontFix toFpOrWontFix(String newResolution) {
445 if (newResolution.equals(Issue.RESOLUTION_WONT_FIX)) {
446 return FpOrWontFix.WONT_FIX;
448 if (newResolution.equals(RESOLUTION_FALSE_POSITIVE)) {
449 return FpOrWontFix.FP;
451 throw new IllegalArgumentException("unsupported resolution " + newResolution);
454 private static long counter = 233_343;
456 private static UserChange newUserChange(User subscriber1) {
457 return new UserChange(counter += 100, subscriber1);
460 public User newUser(String subscriber1) {
461 return new User(subscriber1, subscriber1 + "_login", subscriber1 + "_name");
465 public static Object[][] FPorWontFixResolution() {
466 return new Object[][] {
467 {RESOLUTION_FALSE_POSITIVE},
468 {Issue.RESOLUTION_WONT_FIX}
472 private static Stream<ChangedIssue> randomIssues(Consumer<ChangedIssue.Builder> consumer) {
473 return IntStream.range(0, 1 + new Random().nextInt(5))
475 ChangedIssue.Builder builder = new ChangedIssue.Builder("key_" + i)
476 .setAssignee(new User(randomAlphabetic(3), randomAlphabetic(4), randomAlphabetic(5)))
477 .setNewStatus(randomAlphabetic(12))
478 .setNewResolution(randomAlphabetic(13))
479 .setRule(newRandomNotAHotspotRule(randomAlphabetic(8)))
480 .setProject(new Project.Builder(randomAlphabetic(9))
481 .setKey(randomAlphabetic(10))
482 .setProjectName(randomAlphabetic(11))
484 consumer.accept(builder);
485 return builder.build();
489 private static NotificationManager.EmailRecipient emailRecipientOf(String assignee1) {
490 return new NotificationManager.EmailRecipient(assignee1, emailOf(assignee1));
493 private static String emailOf(String assignee1) {
494 return assignee1 + "@baffe";