]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-9442 Send email to profile admin on each real qprofile update
authorDaniel Schwarz <daniel.schwarz@sonarsource.com>
Tue, 20 Jun 2017 10:17:17 +0000 (12:17 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Thu, 29 Jun 2017 15:23:19 +0000 (17:23 +0200)
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdate.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileUpdateImpl.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RegisterQualityProfiles.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryRule.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/RegisterQualityProfilesNotificationTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/RegisterQualityProfilesTest.java

index 885833d9d37919affb18039fbb4452dbf805fb79..507125d1a7c232c5f94ed9499ff00fd296ee41d7 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.server.qualityprofile;
 
+import java.util.List;
 import org.sonar.db.DbSession;
 import org.sonar.db.qualityprofile.RulesProfileDto;
 
@@ -27,5 +28,5 @@ public interface BuiltInQProfileUpdate {
    * Persist a built-in profile and associate it to all existing organizations.
    * Db sessions are committed.
    */
-  void update(DbSession dbSession, BuiltInQProfile builtInQProfile, RulesProfileDto ruleProfile);
+  List<ActiveRuleChange> update(DbSession dbSession, BuiltInQProfile builtInQProfile, RulesProfileDto ruleProfile);
 }
index de3c45dd3bc7f521e72c346fb41c05269471dc02..3338faacb3324ef61f15047b5fa2549355c4fbbd 100644 (file)
@@ -44,7 +44,7 @@ public class BuiltInQProfileUpdateImpl implements BuiltInQProfileUpdate {
     this.activeRuleIndexer = activeRuleIndexer;
   }
 
-  public void update(DbSession dbSession, BuiltInQProfile builtIn, RulesProfileDto ruleProfile) {
+  public List<ActiveRuleChange> update(DbSession dbSession, BuiltInQProfile builtIn, RulesProfileDto ruleProfile) {
     // Keep reference to all the activated rules before update
     Set<RuleKey> toBeDeactivated = dbClient.activeRuleDao().selectByRuleProfile(dbSession, ruleProfile)
       .stream()
@@ -64,6 +64,7 @@ public class BuiltInQProfileUpdateImpl implements BuiltInQProfileUpdate {
 
     dbSession.commit();
     activeRuleIndexer.indexChanges(dbSession, changes);
+    return changes;
   }
 
   private static RuleActivation convert(org.sonar.api.rules.ActiveRule ar) {
index 89c900f9a108cc4a124e146fab3c9aa808886100..f13a0e6efbe99dd770399362ba78be5a99263538 100644 (file)
@@ -97,9 +97,11 @@ public class RegisterQualityProfiles {
   private void update(DbSession dbSession, BuiltInQProfile builtIn, RulesProfileDto ruleProfile) {
     LOGGER.info("Update profile {}", builtIn.getQProfileName());
 
-    builtInQProfileUpdate.update(dbSession, builtIn, ruleProfile);
+    List<ActiveRuleChange> activeRuleChanges = builtInQProfileUpdate.update(dbSession, builtIn, ruleProfile);
 
-    builtInQualityProfilesNotification.send();
+    if (!activeRuleChanges.isEmpty()) {
+      builtInQualityProfilesNotification.send();
+    }
   }
 
   /**
index 4320a94ca4fe05eabc00ecebcf8bf920eb156fe2..8c93d260da9691783ccf00829ded85cc7b9b1137 100644 (file)
@@ -60,8 +60,8 @@ public class BuiltInQProfileRepositoryRule extends ExternalResource implements B
     return add(language, profileName, false);
   }
 
-  public BuiltInQProfile add(Language language, String profileName, boolean isDefault) {
-    BuiltInQProfile builtIn = create(language, profileName, isDefault);
+  public BuiltInQProfile add(Language language, String profileName, boolean isDefault, org.sonar.api.rules.ActiveRule... rules) {
+    BuiltInQProfile builtIn = create(language, profileName, isDefault, rules);
     profiles.add(builtIn);
     return builtIn;
   }
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/RegisterQualityProfilesNotificationTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/RegisterQualityProfilesNotificationTest.java
new file mode 100644 (file)
index 0000000..c9fc944
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.qualityprofile;
+
+import java.util.Arrays;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.rules.ActiveRule;
+import org.sonar.api.rules.RulePriority;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
+import org.sonar.api.utils.log.LogTester;
+import org.sonar.core.util.UuidFactoryFast;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbTester;
+import org.sonar.db.qualityprofile.ActiveRuleDto;
+import org.sonar.db.qualityprofile.RulesProfileDto;
+import org.sonar.db.rule.RuleDefinitionDto;
+import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
+import org.sonar.server.rule.index.RuleIndex;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.util.TypeValidations;
+
+import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
+import static org.apache.commons.lang.math.RandomUtils.nextLong;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.sonar.api.rules.Rule.create;
+import static org.sonar.api.rules.RulePriority.MAJOR;
+import static org.sonar.db.qualityprofile.QualityProfileTesting.newRuleProfileDto;
+import static org.sonar.server.language.LanguageTesting.newLanguage;
+
+public class RegisterQualityProfilesNotificationTest {
+
+  private System2 system2 = new AlwaysIncreasingSystem2();
+  @Rule
+  public DbTester db = DbTester.create(system2);
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+  @Rule
+  public BuiltInQProfileRepositoryRule builtInQProfileRepositoryRule = new BuiltInQProfileRepositoryRule();
+  @Rule
+  public LogTester logTester = new LogTester();
+
+  private DbClient dbClient = db.getDbClient();
+  private TypeValidations typeValidations = mock(TypeValidations.class);
+  private ActiveRuleIndexer activeRuleIndexer = mock(ActiveRuleIndexer.class);
+  private BuiltInQProfileInsert builtInQProfileInsert = new BuiltInQProfileInsertImpl(dbClient, system2, UuidFactoryFast.getInstance(), typeValidations, activeRuleIndexer);
+  private RuleActivator ruleActivator = new RuleActivator(system2, dbClient, mock(RuleIndex.class), new RuleActivatorContextFactory(dbClient), typeValidations, activeRuleIndexer,
+    userSessionRule);
+  private BuiltInQProfileUpdate builtInQProfileUpdate = new BuiltInQProfileUpdateImpl(dbClient, ruleActivator, activeRuleIndexer);
+  private BuiltInQualityProfilesNotification builtInQualityProfilesNotification = mock(BuiltInQualityProfilesNotification.class);
+  private RegisterQualityProfiles underTest = new RegisterQualityProfiles(builtInQProfileRepositoryRule, dbClient,
+    builtInQProfileInsert, builtInQProfileUpdate, builtInQualityProfilesNotification);
+
+  @Test
+  public void does_not_send_notification_on_new_profile() {
+    String language = newLanguageKey();
+    builtInQProfileRepositoryRule.add(newLanguage(language), "Sonar way");
+    builtInQProfileRepositoryRule.initialize();
+
+    underTest.start();
+
+    verifyZeroInteractions(builtInQualityProfilesNotification);
+  }
+
+  @Test
+  public void does_not_send_notification_when_built_in_profile_is_not_updated() {
+    String language = newLanguageKey();
+    RuleDefinitionDto dbRule = db.rules().insert(r -> r.setLanguage(language));
+    RulesProfileDto dbProfile = insertBuiltInProfile(language);
+    activateRuleInDb(dbProfile, dbRule, MAJOR);
+    addPluginProfile(dbProfile, dbRule);
+    builtInQProfileRepositoryRule.initialize();
+
+    underTest.start();
+
+    verifyZeroInteractions(builtInQualityProfilesNotification);
+  }
+
+  @Test
+  public void send_notification_when_built_in_profile_contains_new_rule() {
+    String language = newLanguageKey();
+    RuleDefinitionDto existingRule = db.rules().insert(r -> r.setLanguage(language));
+    RulesProfileDto dbProfile = insertBuiltInProfile(language);
+    activateRuleInDb(dbProfile, existingRule, MAJOR);
+    RuleDefinitionDto newRule = db.rules().insert(r -> r.setLanguage(language));
+    addPluginProfile(dbProfile, existingRule, newRule);
+    builtInQProfileRepositoryRule.initialize();
+
+    underTest.start();
+
+    verify(builtInQualityProfilesNotification).send();
+  }
+
+  private void addPluginProfile(RulesProfileDto dbProfile, RuleDefinitionDto... dbRules) {
+    RulesProfile pluginProfile = RulesProfile.create(dbProfile.getName(), dbProfile.getLanguage());
+    Arrays.stream(dbRules).forEach(dbRule -> pluginProfile.activateRule(create(dbRule.getRepositoryKey(), dbRule.getRuleKey()), MAJOR));
+    builtInQProfileRepositoryRule.add(newLanguage(dbProfile.getLanguage()), dbProfile.getName(), false, pluginProfile.getActiveRules().toArray(new ActiveRule[0]));
+  }
+
+  private RulesProfileDto insertBuiltInProfile(String language) {
+    RulesProfileDto ruleProfileDto = newRuleProfileDto(rp -> rp.setIsBuiltIn(true).setLanguage(language));
+    db.getDbClient().qualityProfileDao().insert(db.getSession(), ruleProfileDto);
+    db.commit();
+    return ruleProfileDto;
+  }
+
+  private void activateRuleInDb(RulesProfileDto profile, RuleDefinitionDto rule, RulePriority severity) {
+    ActiveRuleDto dto = new ActiveRuleDto()
+      .setProfileId(profile.getId())
+      .setSeverity(severity.name())
+      .setRuleId(rule.getId())
+      .setCreatedAt(nextLong())
+      .setUpdatedAt(nextLong());
+    db.getDbClient().activeRuleDao().insert(db.getSession(), dto);
+    db.commit();
+  }
+
+  private static String newLanguageKey() {
+    return randomAlphanumeric(20).toLowerCase();
+  }
+}
index 205b293986326816b54298de5709e3d63767dbcd..3600b290b6ae42554240e404be34b5f9fa6e7d3a 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.server.qualityprofile;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import org.junit.Rule;
 import org.junit.Test;
@@ -39,8 +40,6 @@ import org.sonar.server.tester.UserSessionRule;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.sonar.db.qualityprofile.QualityProfileTesting.newRuleProfileDto;
 
 public class RegisterQualityProfilesTest {
@@ -61,11 +60,7 @@ public class RegisterQualityProfilesTest {
   private DbClient dbClient = db.getDbClient();
   private DummyBuiltInQProfileInsert insert = new DummyBuiltInQProfileInsert();
   private DummyBuiltInQProfileUpdate update = new DummyBuiltInQProfileUpdate();
-  private BuiltInQualityProfilesNotification builtInQualityProfilesNotification = mock(BuiltInQualityProfilesNotification.class);
-  private RegisterQualityProfiles underTest = new RegisterQualityProfiles(
-    builtInQProfileRepositoryRule,
-    dbClient,
-    insert, update, builtInQualityProfilesNotification);
+  private RegisterQualityProfiles underTest = new RegisterQualityProfiles(builtInQProfileRepositoryRule, dbClient, insert, update, mock(BuiltInQualityProfilesNotification.class));
 
   @Test
   public void start_fails_if_BuiltInQProfileRepository_has_not_been_initialized() {
@@ -137,29 +132,6 @@ public class RegisterQualityProfilesTest {
     assertThat(logTester.logs(LoggerLevel.INFO)).contains("Update profile foo/Sonar way");
   }
 
-  @Test
-  public void does_not_send_notification_on_new_profile() {
-    builtInQProfileRepositoryRule.add(FOO_LANGUAGE, "Sonar way");
-    builtInQProfileRepositoryRule.initialize();
-
-    underTest.start();
-
-    verifyZeroInteractions(builtInQualityProfilesNotification);
-  }
-
-  @Test
-  public void send_notification_when_built_in_profile_is_updated() {
-    RulesProfileDto ruleProfile = newRuleProfileDto(rp -> rp.setIsBuiltIn(true).setName("Sonar way").setLanguage(FOO_LANGUAGE.getKey()));
-    db.getDbClient().qualityProfileDao().insert(db.getSession(), ruleProfile);
-    db.commit();
-    builtInQProfileRepositoryRule.add(FOO_LANGUAGE, ruleProfile.getName(), false);
-    builtInQProfileRepositoryRule.initialize();
-
-    underTest.start();
-
-    verify(builtInQualityProfilesNotification).send();
-  }
-
   private String selectPersistedName(QProfileDto profile) {
     return db.qualityProfiles().selectByUuid(profile.getKee()).get().getName();
   }
@@ -186,8 +158,9 @@ public class RegisterQualityProfilesTest {
     private final List<BuiltInQProfile> callLogs = new ArrayList<>();
 
     @Override
-    public void update(DbSession dbSession, BuiltInQProfile builtIn, RulesProfileDto ruleProfile) {
+    public List<ActiveRuleChange> update(DbSession dbSession, BuiltInQProfile builtIn, RulesProfileDto ruleProfile) {
       callLogs.add(builtIn);
+      return Collections.emptyList();
     }
   }
 }