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.qualityprofile;
22 import com.google.common.collect.ArrayListMultimap;
23 import com.google.common.collect.Multimap;
24 import java.util.Random;
25 import java.util.stream.Collectors;
26 import java.util.stream.IntStream;
27 import org.assertj.core.groups.Tuple;
28 import org.junit.Test;
29 import org.mockito.ArgumentCaptor;
30 import org.sonar.api.notifications.Notification;
31 import org.sonar.api.resources.Language;
32 import org.sonar.api.resources.Languages;
33 import org.sonar.db.qualityprofile.ActiveRuleKey;
34 import org.sonar.server.notification.NotificationManager;
35 import org.sonar.server.qualityprofile.BuiltInQualityProfilesNotification.Profile;
37 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
38 import static org.assertj.core.api.Java6Assertions.assertThat;
39 import static org.assertj.core.api.Java6Assertions.tuple;
40 import static org.mockito.Mockito.mock;
41 import static org.mockito.Mockito.verify;
42 import static org.mockito.Mockito.verifyNoMoreInteractions;
43 import static org.sonar.server.language.LanguageTesting.newLanguage;
44 import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.ACTIVATED;
45 import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.DEACTIVATED;
46 import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.UPDATED;
48 public class BuiltInQualityProfilesNotificationSenderTest {
50 private static final Random RANDOM = new Random();
51 private NotificationManager notificationManager = mock(NotificationManager.class);
54 public void add_profile_to_notification_for_added_rules() throws Exception {
55 Multimap<QProfileName, ActiveRuleChange> profiles = ArrayListMultimap.create();
56 Languages languages = new Languages();
57 Tuple expectedTuple = addProfile(profiles, languages, ACTIVATED);
59 BuiltInQualityProfilesNotificationSender underTest = new BuiltInQualityProfilesNotificationSender(notificationManager, languages);
60 underTest.send(profiles);
62 ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(Notification.class);
63 verify(notificationManager).scheduleForSending(notificationArgumentCaptor.capture());
64 verifyNoMoreInteractions(notificationManager);
65 assertThat(BuiltInQualityProfilesNotification.parse(notificationArgumentCaptor.getValue()).getProfiles())
66 .extracting(Profile::getProfileName, Profile::getLanguage, Profile::getNewRules)
67 .containsExactlyInAnyOrder(expectedTuple);
71 public void add_profile_to_notification_for_updated_rules() throws Exception {
72 Multimap<QProfileName, ActiveRuleChange> profiles = ArrayListMultimap.create();
73 Languages languages = new Languages();
74 Tuple expectedTuple = addProfile(profiles, languages, UPDATED);
76 BuiltInQualityProfilesNotificationSender underTest = new BuiltInQualityProfilesNotificationSender(notificationManager, languages);
77 underTest.send(profiles);
79 ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(Notification.class);
80 verify(notificationManager).scheduleForSending(notificationArgumentCaptor.capture());
81 verifyNoMoreInteractions(notificationManager);
82 assertThat(BuiltInQualityProfilesNotification.parse(notificationArgumentCaptor.getValue()).getProfiles())
83 .extracting(Profile::getProfileName, Profile::getLanguage, Profile::getUpdatedRules)
84 .containsExactlyInAnyOrder(expectedTuple);
88 public void add_profile_to_notification_for_removed_rules() throws Exception {
89 Multimap<QProfileName, ActiveRuleChange> profiles = ArrayListMultimap.create();
90 Languages languages = new Languages();
91 Tuple expectedTuple = addProfile(profiles, languages, DEACTIVATED);
93 BuiltInQualityProfilesNotificationSender underTest = new BuiltInQualityProfilesNotificationSender(notificationManager, languages);
94 underTest.send(profiles);
96 ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(Notification.class);
97 verify(notificationManager).scheduleForSending(notificationArgumentCaptor.capture());
98 verifyNoMoreInteractions(notificationManager);
99 assertThat(BuiltInQualityProfilesNotification.parse(notificationArgumentCaptor.getValue()).getProfiles())
100 .extracting(Profile::getProfileName, Profile::getLanguage, Profile::getRemovedRules)
101 .containsExactlyInAnyOrder(expectedTuple);
105 public void add_multiple_profiles_to_notification() throws Exception {
106 Multimap<QProfileName, ActiveRuleChange> profiles = ArrayListMultimap.create();
107 Languages languages = new Languages();
108 Tuple expectedTuple1 = addProfile(profiles, languages, ACTIVATED);
109 Tuple expectedTuple2 = addProfile(profiles, languages, ACTIVATED);
111 BuiltInQualityProfilesNotificationSender underTest = new BuiltInQualityProfilesNotificationSender(notificationManager, languages);
112 underTest.send(profiles);
114 ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(Notification.class);
115 verify(notificationManager).scheduleForSending(notificationArgumentCaptor.capture());
116 verifyNoMoreInteractions(notificationManager);
117 assertThat(BuiltInQualityProfilesNotification.parse(notificationArgumentCaptor.getValue()).getProfiles())
118 .extracting(Profile::getProfileName, Profile::getLanguage, Profile::getNewRules)
119 .containsExactlyInAnyOrder(expectedTuple1, expectedTuple2);
122 private Tuple addProfile(Multimap<QProfileName, ActiveRuleChange> profiles, Languages languages, ActiveRuleChange.Type type) {
123 String profileName = randomLowerCaseText();
124 Language language = newLanguage(randomLowerCaseText(), randomLowerCaseText());
125 languages.add(language);
126 int numberOfChanges = RANDOM.nextInt(1000);
128 new QProfileName(language.getKey(), profileName),
129 IntStream.range(0, numberOfChanges).mapToObj(i -> new ActiveRuleChange(type, ActiveRuleKey.parse("qp:repo:rule" + i))).collect(Collectors.toSet()));
130 return tuple(profileName, language.getName(), numberOfChanges);
133 private static String randomLowerCaseText() {
134 return randomAlphanumeric(20).toLowerCase();