3 * Copyright (C) 2009-2024 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.builtin;
22 import com.google.common.collect.ArrayListMultimap;
23 import com.google.common.collect.Multimap;
24 import org.assertj.core.groups.Tuple;
25 import org.junit.Test;
26 import org.mockito.ArgumentCaptor;
27 import org.sonar.api.config.internal.MapSettings;
28 import org.sonar.api.notifications.Notification;
29 import org.sonar.api.resources.Language;
30 import org.sonar.api.resources.Languages;
31 import org.sonar.core.util.Uuids;
32 import org.sonar.db.qualityprofile.ActiveRuleKey;
33 import org.sonar.db.rule.RuleDto;
34 import org.sonar.server.notification.NotificationManager;
35 import org.sonar.server.qualityprofile.ActiveRuleChange;
36 import org.sonar.server.qualityprofile.builtin.BuiltInQPChangeNotificationBuilder.Profile;
38 import static java.util.Arrays.asList;
39 import static org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric;
40 import static org.assertj.core.api.Assertions.assertThat;
41 import static org.assertj.core.api.Assertions.tuple;
42 import static org.mockito.Mockito.mock;
43 import static org.mockito.Mockito.verify;
44 import static org.mockito.Mockito.verifyNoInteractions;
45 import static org.mockito.Mockito.verifyNoMoreInteractions;
46 import static org.sonar.core.config.CorePropertyDefinitions.DISABLE_NOTIFICATION_ON_BUILT_IN_QPROFILES;
47 import static org.sonar.server.language.LanguageTesting.newLanguage;
48 import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.ACTIVATED;
49 import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.DEACTIVATED;
50 import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.UPDATED;
52 public class BuiltInQualityProfilesUpdateListenerTest {
54 private NotificationManager notificationManager = mock(NotificationManager.class);
55 private MapSettings settings = new MapSettings();
58 public void add_profile_to_notification_for_added_rules() {
59 enableNotificationInGlobalSettings();
60 Multimap<QProfileName, ActiveRuleChange> profiles = ArrayListMultimap.create();
61 Languages languages = new Languages();
62 Tuple expectedTuple = addProfile(profiles, languages, ACTIVATED);
64 BuiltInQualityProfilesUpdateListener underTest = new BuiltInQualityProfilesUpdateListener(notificationManager, languages, settings.asConfig());
65 underTest.onChange(profiles, 0, 1);
67 ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(Notification.class);
68 verify(notificationManager).scheduleForSending(notificationArgumentCaptor.capture());
69 verifyNoMoreInteractions(notificationManager);
70 assertThat(BuiltInQPChangeNotificationBuilder.parse(notificationArgumentCaptor.getValue()).getProfiles())
71 .extracting(Profile::getProfileName, Profile::getLanguageKey, Profile::getLanguageName, Profile::getNewRules)
72 .containsExactlyInAnyOrder(expectedTuple);
76 public void add_profile_to_notification_for_updated_rules() {
77 enableNotificationInGlobalSettings();
78 Multimap<QProfileName, ActiveRuleChange> profiles = ArrayListMultimap.create();
79 Languages languages = new Languages();
80 Tuple expectedTuple = addProfile(profiles, languages, UPDATED);
82 BuiltInQualityProfilesUpdateListener underTest = new BuiltInQualityProfilesUpdateListener(notificationManager, languages, settings.asConfig());
83 underTest.onChange(profiles, 0, 1);
85 ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(Notification.class);
86 verify(notificationManager).scheduleForSending(notificationArgumentCaptor.capture());
87 verifyNoMoreInteractions(notificationManager);
88 assertThat(BuiltInQPChangeNotificationBuilder.parse(notificationArgumentCaptor.getValue()).getProfiles())
89 .extracting(Profile::getProfileName, Profile::getLanguageKey, Profile::getLanguageName, Profile::getUpdatedRules)
90 .containsExactlyInAnyOrder(expectedTuple);
94 public void add_profile_to_notification_for_removed_rules() {
95 enableNotificationInGlobalSettings();
96 Multimap<QProfileName, ActiveRuleChange> profiles = ArrayListMultimap.create();
97 Languages languages = new Languages();
98 Tuple expectedTuple = addProfile(profiles, languages, DEACTIVATED);
100 BuiltInQualityProfilesUpdateListener underTest = new BuiltInQualityProfilesUpdateListener(notificationManager, languages, settings.asConfig());
101 underTest.onChange(profiles, 0, 1);
103 ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(Notification.class);
104 verify(notificationManager).scheduleForSending(notificationArgumentCaptor.capture());
105 verifyNoMoreInteractions(notificationManager);
106 assertThat(BuiltInQPChangeNotificationBuilder.parse(notificationArgumentCaptor.getValue()).getProfiles())
107 .extracting(Profile::getProfileName, Profile::getLanguageKey, Profile::getLanguageName, Profile::getRemovedRules)
108 .containsExactlyInAnyOrder(expectedTuple);
112 public void add_multiple_profiles_to_notification() {
113 enableNotificationInGlobalSettings();
114 Multimap<QProfileName, ActiveRuleChange> profiles = ArrayListMultimap.create();
115 Languages languages = new Languages();
116 Tuple expectedTuple1 = addProfile(profiles, languages, ACTIVATED);
117 Tuple expectedTuple2 = addProfile(profiles, languages, ACTIVATED);
119 BuiltInQualityProfilesUpdateListener underTest = new BuiltInQualityProfilesUpdateListener(notificationManager, languages, settings.asConfig());
120 underTest.onChange(profiles, 0, 1);
122 ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(Notification.class);
123 verify(notificationManager).scheduleForSending(notificationArgumentCaptor.capture());
124 verifyNoMoreInteractions(notificationManager);
125 assertThat(BuiltInQPChangeNotificationBuilder.parse(notificationArgumentCaptor.getValue()).getProfiles())
126 .extracting(Profile::getProfileName, Profile::getLanguageKey, Profile::getLanguageName, Profile::getNewRules)
127 .containsExactlyInAnyOrder(expectedTuple1, expectedTuple2);
131 public void add_start_and_end_dates_to_notification() {
132 enableNotificationInGlobalSettings();
133 Multimap<QProfileName, ActiveRuleChange> profiles = ArrayListMultimap.create();
134 Languages languages = new Languages();
135 addProfile(profiles, languages, ACTIVATED);
136 long startDate = 10_000_000_000L;
137 long endDate = 15_000_000_000L;
139 BuiltInQualityProfilesUpdateListener underTest = new BuiltInQualityProfilesUpdateListener(notificationManager, languages, settings.asConfig());
140 underTest.onChange(profiles, startDate, endDate);
142 ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(Notification.class);
143 verify(notificationManager).scheduleForSending(notificationArgumentCaptor.capture());
144 verifyNoMoreInteractions(notificationManager);
145 assertThat(BuiltInQPChangeNotificationBuilder.parse(notificationArgumentCaptor.getValue()).getProfiles())
146 .extracting(Profile::getStartDate, Profile::getEndDate)
147 .containsExactlyInAnyOrder(tuple(startDate, endDate));
151 public void avoid_notification_if_configured_in_settings() {
152 settings.setProperty(DISABLE_NOTIFICATION_ON_BUILT_IN_QPROFILES, true);
153 Multimap<QProfileName, ActiveRuleChange> profiles = ArrayListMultimap.create();
154 Languages languages = new Languages();
155 addProfile(profiles, languages, ACTIVATED);
157 BuiltInQualityProfilesUpdateListener underTest = new BuiltInQualityProfilesUpdateListener(notificationManager, languages, settings.asConfig());
158 underTest.onChange(profiles, 0, 1);
160 verifyNoInteractions(notificationManager);
163 private Tuple addProfile(Multimap<QProfileName, ActiveRuleChange> profiles, Languages languages, ActiveRuleChange.Type type) {
164 String profileName = randomLowerCaseText();
165 String ruleUuid1 = Uuids.createFast();
166 String ruleUuid2 = Uuids.createFast();
167 Language language = newLanguage(randomLowerCaseText(), randomLowerCaseText());
168 languages.add(language);
169 profiles.putAll(new QProfileName(language.getKey(), profileName),
170 asList(new ActiveRuleChange(
172 ActiveRuleKey.parse("qp:repo:rule1"), new RuleDto().setUuid(ruleUuid1)),
173 new ActiveRuleChange(type, ActiveRuleKey.parse("qp:repo:rule2"), new RuleDto().setUuid(ruleUuid2))));
174 return tuple(profileName, language.getKey(), language.getName(), 2);
177 private static String randomLowerCaseText() {
178 return randomAlphanumeric(20).toLowerCase();
181 private void enableNotificationInGlobalSettings() {
182 settings.setProperty(DISABLE_NOTIFICATION_ON_BUILT_IN_QPROFILES, false);