From: Teryk Bellahsene Date: Wed, 6 May 2015 12:25:01 +0000 (+0200) Subject: add top 5 rules on 'New Issues' and 'My New Issues' notifications X-Git-Tag: 5.2-RC1~2030 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=refs%2Fpull%2F294%2Fhead;p=sonarqube.git add top 5 rules on 'New Issues' and 'My New Issues' notifications --- diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/AbstractNewIssuesEmailTemplate.java b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/AbstractNewIssuesEmailTemplate.java index 6617ea1d7a0..044abf8543a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/AbstractNewIssuesEmailTemplate.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/AbstractNewIssuesEmailTemplate.java @@ -28,7 +28,7 @@ import org.sonar.api.rule.Severity; import org.sonar.api.utils.DateUtils; import org.sonar.plugins.emailnotifications.api.EmailMessage; import org.sonar.plugins.emailnotifications.api.EmailTemplate; -import org.sonar.server.issue.notification.NewIssuesStatistics.METRIC; +import org.sonar.server.issue.notification.NewIssuesStatistics.Metric; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; @@ -82,6 +82,7 @@ public abstract class AbstractNewIssuesEmailTemplate extends EmailTemplate { message.append("Project: ").append(projectName).append(NEW_LINE).append(NEW_LINE); appendSeverity(message, notification); appendAssignees(message, notification); + appendRules(message, notification); appendTags(message, notification); appendComponents(message, notification); appendFooter(message, notification); @@ -97,15 +98,15 @@ public abstract class AbstractNewIssuesEmailTemplate extends EmailTemplate { protected String subject(Notification notification, String projectName) { return String.format("%s: %s new issues (new debt: %s)", projectName, - notification.getFieldValue(METRIC.SEVERITY + COUNT), - notification.getFieldValue(METRIC.DEBT + COUNT)); + notification.getFieldValue(Metric.SEVERITY + COUNT), + notification.getFieldValue(Metric.DEBT + COUNT)); } - private boolean doNotHaveValue(Notification notification, METRIC metric) { + private boolean doNotHaveValue(Notification notification, Metric metric) { return notification.getFieldValue(metric + DOT + "1" + LABEL) == null; } - private void genericAppendOfMetric(METRIC metric, String label, StringBuilder message, Notification notification) { + private void genericAppendOfMetric(Metric metric, String label, StringBuilder message, Notification notification) { if (doNotHaveValue(notification, metric)) { return; } @@ -130,22 +131,26 @@ public abstract class AbstractNewIssuesEmailTemplate extends EmailTemplate { } protected void appendAssignees(StringBuilder message, Notification notification) { - genericAppendOfMetric(METRIC.ASSIGNEE, "Assignees", message, notification); + genericAppendOfMetric(Metric.ASSIGNEE, "Assignees", message, notification); } protected void appendComponents(StringBuilder message, Notification notification) { - genericAppendOfMetric(METRIC.COMPONENT, "Most impacted files", message, notification); + genericAppendOfMetric(Metric.COMPONENT, "Most impacted files", message, notification); } protected void appendTags(StringBuilder message, Notification notification) { - genericAppendOfMetric(METRIC.TAGS, "Tags", message, notification); + genericAppendOfMetric(Metric.TAG, "Tags", message, notification); + } + + protected void appendRules(StringBuilder message, Notification notification) { + genericAppendOfMetric(Metric.RULE, "Rules", message, notification); } protected void appendSeverity(StringBuilder message, Notification notification) { message .append(String.format("%s new issues (new debt: %s)", - notification.getFieldValue(METRIC.SEVERITY + COUNT), - notification.getFieldValue(METRIC.DEBT + COUNT))) + notification.getFieldValue(Metric.SEVERITY + COUNT), + notification.getFieldValue(Metric.DEBT + COUNT))) .append(NEW_LINE).append(NEW_LINE) .append(TAB) .append("Severity") @@ -153,10 +158,10 @@ public abstract class AbstractNewIssuesEmailTemplate extends EmailTemplate { .append(TAB) .append(TAB); - for (Iterator severityIterator = Lists.reverse(Severity.ALL).iterator(); severityIterator.hasNext();) { + for (Iterator severityIterator = Lists.reverse(Severity.ALL).iterator(); severityIterator.hasNext(); ) { String severity = severityIterator.next(); String severityLabel = i18n.message(getLocale(), "severity." + severity, severity); - message.append(severityLabel).append(": ").append(notification.getFieldValue(METRIC.SEVERITY + DOT + severity + COUNT)); + message.append(severityLabel).append(": ").append(notification.getFieldValue(Metric.SEVERITY + DOT + severity + COUNT)); if (severityIterator.hasNext()) { message.append(TAB); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/MyNewIssuesEmailTemplate.java b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/MyNewIssuesEmailTemplate.java index 8cd969cc9b1..fb500e48949 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/MyNewIssuesEmailTemplate.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/MyNewIssuesEmailTemplate.java @@ -24,7 +24,7 @@ import org.sonar.api.config.EmailSettings; import org.sonar.api.i18n.I18n; import org.sonar.api.notifications.Notification; import org.sonar.api.utils.DateUtils; -import org.sonar.server.issue.notification.NewIssuesStatistics.METRIC; +import org.sonar.server.issue.notification.NewIssuesStatistics.Metric; import java.util.Date; @@ -50,7 +50,7 @@ public class MyNewIssuesEmailTemplate extends AbstractNewIssuesEmailTemplate { @Override protected String subject(Notification notification, String projectName) { return String.format("You have %s new issues on project %s", - notification.getFieldValue(METRIC.SEVERITY + COUNT), + notification.getFieldValue(Metric.SEVERITY + COUNT), projectName); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/MyNewIssuesNotification.java b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/MyNewIssuesNotification.java index 615420541cd..ce4343f3de3 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/MyNewIssuesNotification.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/MyNewIssuesNotification.java @@ -22,6 +22,7 @@ package org.sonar.server.issue.notification; import org.sonar.api.utils.Durations; import org.sonar.server.db.DbClient; +import org.sonar.server.rule.index.RuleIndex; import org.sonar.server.user.index.UserIndex; import static org.sonar.server.issue.notification.AbstractNewIssuesEmailTemplate.FIELD_ASSIGNEE; @@ -30,8 +31,8 @@ public class MyNewIssuesNotification extends NewIssuesNotification { public static final String TYPE = "my-new-issues"; - MyNewIssuesNotification(UserIndex userIndex, DbClient dbClient, Durations durations) { - super(TYPE, userIndex, dbClient, durations); + MyNewIssuesNotification(UserIndex userIndex, RuleIndex ruleIndex, DbClient dbClient, Durations durations) { + super(TYPE, userIndex, ruleIndex, dbClient, durations); } public MyNewIssuesNotification setAssignee(String assignee) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesNotification.java b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesNotification.java index 58a9ed66f4e..bafb6daf244 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesNotification.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesNotification.java @@ -22,6 +22,7 @@ package org.sonar.server.issue.notification; import com.google.common.collect.Multiset; import org.sonar.api.component.Component; import org.sonar.api.notifications.Notification; +import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.Severity; import org.sonar.api.utils.DateUtils; import org.sonar.api.utils.Duration; @@ -30,7 +31,9 @@ import org.sonar.core.component.ComponentDto; import org.sonar.core.persistence.DbSession; import org.sonar.core.persistence.MyBatis; import org.sonar.server.db.DbClient; -import org.sonar.server.issue.notification.NewIssuesStatistics.METRIC; +import org.sonar.server.issue.notification.NewIssuesStatistics.Metric; +import org.sonar.server.rule.Rule; +import org.sonar.server.rule.index.RuleIndex; import org.sonar.server.user.index.UserDoc; import org.sonar.server.user.index.UserIndex; @@ -38,8 +41,11 @@ import java.util.Date; import java.util.List; import java.util.Locale; -import static org.sonar.server.issue.notification.NewIssuesEmailTemplate.*; -import static org.sonar.server.issue.notification.NewIssuesStatistics.METRIC.SEVERITY; +import static org.sonar.server.issue.notification.NewIssuesEmailTemplate.FIELD_PROJECT_DATE; +import static org.sonar.server.issue.notification.NewIssuesEmailTemplate.FIELD_PROJECT_KEY; +import static org.sonar.server.issue.notification.NewIssuesEmailTemplate.FIELD_PROJECT_NAME; +import static org.sonar.server.issue.notification.NewIssuesEmailTemplate.FIELD_PROJECT_UUID; +import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.SEVERITY; public class NewIssuesNotification extends Notification { @@ -47,18 +53,21 @@ public class NewIssuesNotification extends Notification { private static final long serialVersionUID = -6305871981920103093L; private static final String COUNT = ".count"; private static final String LABEL = ".label"; + private static final String DOT = "."; private final transient UserIndex userIndex; + private final transient RuleIndex ruleIndex; private final transient DbClient dbClient; private final transient Durations durations; - NewIssuesNotification(UserIndex userIndex, DbClient dbClient, Durations durations) { - this(TYPE, userIndex, dbClient, durations); + NewIssuesNotification(UserIndex userIndex, RuleIndex ruleIndex, DbClient dbClient, Durations durations) { + this(TYPE, userIndex, ruleIndex, dbClient, durations); } - protected NewIssuesNotification(String type, UserIndex userIndex, DbClient dbClient, Durations durations) { + protected NewIssuesNotification(String type, UserIndex userIndex, RuleIndex ruleIndex, DbClient dbClient, Durations durations) { super(type); this.userIndex = userIndex; + this.ruleIndex = ruleIndex; this.dbClient = dbClient; this.durations = durations; } @@ -82,20 +91,33 @@ public class NewIssuesNotification extends Notification { setAssigneesStatistics(stats); setTagsStatistics(stats); setComponentsStatistics(stats); + setRuleStatistics(stats); return this; } + protected void setRuleStatistics(NewIssuesStatistics.Stats stats) { + Metric metric = Metric.RULE; + List> metricStats = stats.statsForMetric(metric); + for (int i = 0; i < 5 && i < metricStats.size(); i++) { + String ruleKey = metricStats.get(i).getElement(); + Rule rule = ruleIndex.getByKey(RuleKey.parse(ruleKey)); + String name = rule.name() + " (" + rule.language() + ")"; + setFieldValue(metric + DOT + (i + 1) + LABEL, name); + setFieldValue(metric + DOT + (i + 1) + COUNT, String.valueOf(metricStats.get(i).getCount())); + } + } + protected void setComponentsStatistics(NewIssuesStatistics.Stats stats) { - METRIC metric = METRIC.COMPONENT; + Metric metric = Metric.COMPONENT; List> componentStats = stats.statsForMetric(metric); DbSession dbSession = dbClient.openSession(false); try { for (int i = 0; i < 5 && i < componentStats.size(); i++) { String uuid = componentStats.get(i).getElement(); String componentName = dbClient.componentDao().getByUuid(dbSession, uuid).name(); - setFieldValue(metric + "." + (i + 1) + LABEL, componentName); - setFieldValue(metric + "." + (i + 1) + COUNT, String.valueOf(componentStats.get(i).getCount())); + setFieldValue(metric + DOT + (i + 1) + LABEL, componentName); + setFieldValue(metric + DOT + (i + 1) + COUNT, String.valueOf(componentStats.get(i).getCount())); } } finally { MyBatis.closeQuietly(dbSession); @@ -103,35 +125,35 @@ public class NewIssuesNotification extends Notification { } protected void setTagsStatistics(NewIssuesStatistics.Stats stats) { - METRIC metric = METRIC.TAGS; + Metric metric = Metric.TAG; List> metricStats = stats.statsForMetric(metric); for (int i = 0; i < 5 && i < metricStats.size(); i++) { - setFieldValue(metric + "." + (i + 1) + COUNT, String.valueOf(metricStats.get(i).getCount())); - setFieldValue(metric + "." + (i + 1) + ".label", metricStats.get(i).getElement()); + setFieldValue(metric + DOT + (i + 1) + COUNT, String.valueOf(metricStats.get(i).getCount())); + setFieldValue(metric + DOT + (i + 1) + ".label", metricStats.get(i).getElement()); } } protected void setAssigneesStatistics(NewIssuesStatistics.Stats stats) { - METRIC metric = METRIC.ASSIGNEE; + Metric metric = Metric.ASSIGNEE; List> metricStats = stats.statsForMetric(metric); for (int i = 0; i < 5 && i < metricStats.size(); i++) { String login = metricStats.get(i).getElement(); UserDoc user = userIndex.getNullableByLogin(login); String name = user == null ? login : user.name(); - setFieldValue(metric + "." + (i + 1) + LABEL, name); - setFieldValue(metric + "." + (i + 1) + COUNT, String.valueOf(metricStats.get(i).getCount())); + setFieldValue(metric + DOT + (i + 1) + LABEL, name); + setFieldValue(metric + DOT + (i + 1) + COUNT, String.valueOf(metricStats.get(i).getCount())); } } public NewIssuesNotification setDebt(Duration debt) { - setFieldValue(METRIC.DEBT + COUNT, durations.format(Locale.ENGLISH, debt)); + setFieldValue(Metric.DEBT + COUNT, durations.format(Locale.ENGLISH, debt)); return this; } protected void setSeverityStatistics(NewIssuesStatistics.Stats stats) { setFieldValue(SEVERITY + COUNT, String.valueOf(stats.countForMetric(SEVERITY))); for (String severity : Severity.ALL) { - setFieldValue(SEVERITY + "." + severity + COUNT, String.valueOf(stats.countForMetric(SEVERITY, severity))); + setFieldValue(SEVERITY + DOT + severity + COUNT, String.valueOf(stats.countForMetric(SEVERITY, severity))); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesNotificationFactory.java b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesNotificationFactory.java index 6686587a82c..6fa32e95b07 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesNotificationFactory.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesNotificationFactory.java @@ -23,24 +23,27 @@ package org.sonar.server.issue.notification; import org.sonar.api.ServerComponent; import org.sonar.api.utils.Durations; import org.sonar.server.db.DbClient; +import org.sonar.server.rule.index.RuleIndex; import org.sonar.server.user.index.UserIndex; public class NewIssuesNotificationFactory implements ServerComponent { private final UserIndex userIndex; + private final RuleIndex ruleIndex; private final DbClient dbClient; private final Durations durations; - public NewIssuesNotificationFactory(UserIndex userIndex, DbClient dbClient, Durations durations) { + public NewIssuesNotificationFactory(UserIndex userIndex, RuleIndex ruleIndex, DbClient dbClient, Durations durations) { this.userIndex = userIndex; + this.ruleIndex = ruleIndex; this.dbClient = dbClient; this.durations = durations; } public MyNewIssuesNotification newMyNewIssuesNotification() { - return new MyNewIssuesNotification(userIndex, dbClient, durations); + return new MyNewIssuesNotification(userIndex, ruleIndex, dbClient, durations); } public NewIssuesNotification newNewIssuesNotication() { - return new NewIssuesNotification(userIndex, dbClient, durations); + return new NewIssuesNotification(userIndex, ruleIndex, dbClient, durations); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesStatistics.java b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesStatistics.java index f3eecd1fe13..396a4eab0ed 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesStatistics.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesStatistics.java @@ -23,6 +23,7 @@ package org.sonar.server.issue.notification; import com.google.common.collect.HashMultiset; import com.google.common.collect.Multiset; import org.sonar.api.issue.Issue; +import org.sonar.api.rule.RuleKey; import org.sonar.api.utils.Duration; import org.sonar.core.util.MultiSets; @@ -32,7 +33,11 @@ import java.util.List; import java.util.Map; import static com.google.common.base.Preconditions.checkArgument; -import static org.sonar.server.issue.notification.NewIssuesStatistics.METRIC.*; +import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.ASSIGNEE; +import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.COMPONENT; +import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.RULE; +import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.SEVERITY; +import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.TAG; public class NewIssuesStatistics { private Map assigneesStatistics = new LinkedHashMap<>(); @@ -65,11 +70,11 @@ public class NewIssuesStatistics { return globalStatistics.hasIssues(); } - enum METRIC { - SEVERITY(true), TAGS(true), COMPONENT(true), ASSIGNEE(true), DEBT(false); + enum Metric { + SEVERITY(true), TAG(true), COMPONENT(true), ASSIGNEE(true), DEBT(false), RULE(true); private final boolean isComputedByDistribution; - METRIC(boolean isComputedByDistribution) { + Metric(boolean isComputedByDistribution) { this.isComputedByDistribution = isComputedByDistribution; } @@ -79,11 +84,11 @@ public class NewIssuesStatistics { } public static class Stats { - private final Map> distributions = new EnumMap<>(METRIC.class); + private final Map> distributions = new EnumMap<>(Metric.class); private long debtInMinutes = 0L; public Stats() { - for (METRIC metric : METRIC.values()) { + for (Metric metric : Metric.values()) { if (metric.isComputedByDistribution()) { distributions.put(metric, HashMultiset.create()); } @@ -93,11 +98,15 @@ public class NewIssuesStatistics { public void add(Issue issue) { distributions.get(SEVERITY).add(issue.severity()); distributions.get(COMPONENT).add(issue.componentUuid()); + RuleKey ruleKey = issue.ruleKey(); + if (ruleKey != null) { + distributions.get(RULE).add(ruleKey.toString()); + } if (issue.assignee() != null) { distributions.get(ASSIGNEE).add(issue.assignee()); } for (String tag : issue.tags()) { - distributions.get(TAGS).add(tag); + distributions.get(TAG).add(tag); } Duration debt = issue.debt(); if (debt != null) { @@ -105,11 +114,11 @@ public class NewIssuesStatistics { } } - public int countForMetric(METRIC metric) { + public int countForMetric(Metric metric) { return distributionFor(metric).size(); } - public int countForMetric(METRIC metric, String label) { + public int countForMetric(Metric metric, String label) { return distributionFor(metric).count(label); } @@ -121,11 +130,11 @@ public class NewIssuesStatistics { return !distributionFor(SEVERITY).isEmpty(); } - public List> statsForMetric(METRIC metric) { + public List> statsForMetric(Metric metric) { return MultiSets.listOrderedByHighestCounts(distributionFor(metric)); } - private Multiset distributionFor(METRIC metric) { + private Multiset distributionFor(Metric metric) { checkArgument(metric.isComputedByDistribution()); return distributions.get(metric); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/notification/MyNewIssuesEmailTemplateTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/MyNewIssuesEmailTemplateTest.java index 509c6d8cc0d..8ab8fe56354 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/notification/MyNewIssuesEmailTemplateTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/MyNewIssuesEmailTemplateTest.java @@ -37,10 +37,16 @@ import java.util.Date; import java.util.Locale; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.*; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static org.sonar.server.issue.notification.NewIssuesStatistics.METRIC.*; +import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.COMPONENT; +import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.DEBT; +import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.RULE; +import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.SEVERITY; +import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.TAG; public class MyNewIssuesEmailTemplateTest { @@ -83,6 +89,7 @@ public class MyNewIssuesEmailTemplateTest { public void format_email_with_all_fields_filled() throws Exception { Notification notification = newNotification(); addTags(notification); + addRules(notification); addComponents(notification); EmailMessage message = sut.format(notification); @@ -149,10 +156,10 @@ public class MyNewIssuesEmailTemplateTest { private void addTags(Notification notification) { notification - .setFieldValue(TAGS + ".1.label", "oscar") - .setFieldValue(TAGS + ".1.count", "3") - .setFieldValue(TAGS + ".2.label", "cesar") - .setFieldValue(TAGS + ".2.count", "10"); + .setFieldValue(TAG + ".1.label", "oscar") + .setFieldValue(TAG + ".1.count", "3") + .setFieldValue(TAG + ".2.label", "cesar") + .setFieldValue(TAG + ".2.count", "10"); } private void addComponents(Notification notification) { @@ -162,4 +169,12 @@ public class MyNewIssuesEmailTemplateTest { .setFieldValue(COMPONENT + ".2.label", "/path/to/directory") .setFieldValue(COMPONENT + ".2.count", "7"); } + + private void addRules(Notification notification) { + notification + .setFieldValue(RULE + ".1.label", "Rule the Universe (Clojure)") + .setFieldValue(RULE + ".1.count", "42") + .setFieldValue(RULE + ".2.label", "Rule the World (Java)") + .setFieldValue(RULE + ".2.count", "5"); + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/notification/MyNewIssuesNotificationTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/MyNewIssuesNotificationTest.java index 80ac17846f9..840179fa11d 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/notification/MyNewIssuesNotificationTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/MyNewIssuesNotificationTest.java @@ -23,6 +23,7 @@ package org.sonar.server.issue.notification; import org.junit.Test; import org.sonar.api.utils.Durations; import org.sonar.server.db.DbClient; +import org.sonar.server.rule.index.RuleIndex; import org.sonar.server.user.index.UserIndex; import static org.assertj.core.api.Assertions.assertThat; @@ -31,7 +32,7 @@ import static org.sonar.server.issue.notification.AbstractNewIssuesEmailTemplate public class MyNewIssuesNotificationTest { - MyNewIssuesNotification sut = new MyNewIssuesNotification(mock(UserIndex.class), mock(DbClient.class), mock(Durations.class)); + MyNewIssuesNotification sut = new MyNewIssuesNotification(mock(UserIndex.class), mock(RuleIndex.class), mock(DbClient.class), mock(Durations.class)); @Test public void set_assignee() throws Exception { diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesEmailTemplateTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesEmailTemplateTest.java index 4de5ac346a3..723f9f5ddbb 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesEmailTemplateTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesEmailTemplateTest.java @@ -38,7 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.*; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static org.sonar.server.issue.notification.NewIssuesStatistics.METRIC.*; +import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.*; public class NewIssuesEmailTemplateTest { @@ -97,6 +97,7 @@ public class NewIssuesEmailTemplateTest { public void format_email_with_all_fields_filled() throws Exception { Notification notification = newNotification(); addAssignees(notification); + addRules(notification); addTags(notification); addComponents(notification); @@ -154,10 +155,10 @@ public class NewIssuesEmailTemplateTest { private void addTags(Notification notification) { notification - .setFieldValue(TAGS + ".1.label", "oscar") - .setFieldValue(TAGS + ".1.count", "3") - .setFieldValue(TAGS + ".2.label", "cesar") - .setFieldValue(TAGS + ".2.count", "10"); + .setFieldValue(TAG + ".1.label", "oscar") + .setFieldValue(TAG + ".1.count", "3") + .setFieldValue(TAG + ".2.label", "cesar") + .setFieldValue(TAG + ".2.count", "10"); } private void addComponents(Notification notification) { @@ -167,4 +168,12 @@ public class NewIssuesEmailTemplateTest { .setFieldValue(COMPONENT + ".2.label", "/path/to/directory") .setFieldValue(COMPONENT + ".2.count", "7"); } + + private void addRules(Notification notification) { + notification + .setFieldValue(RULE + ".1.label", "Rule the Universe (Clojure)") + .setFieldValue(RULE + ".1.count", "42") + .setFieldValue(RULE + ".2.label", "Rule the World (Java)") + .setFieldValue(RULE + ".2.count", "5"); + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesNotificationTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesNotificationTest.java index 67338fbd425..ef9bf673dfa 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesNotificationTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesNotificationTest.java @@ -20,10 +20,12 @@ package org.sonar.server.issue.notification; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import org.junit.Test; import org.mockito.Mockito; import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.Severity; import org.sonar.api.utils.DateUtils; import org.sonar.api.utils.Duration; @@ -32,6 +34,10 @@ import org.sonar.core.component.ComponentDto; import org.sonar.core.persistence.DbSession; import org.sonar.server.component.ComponentTesting; import org.sonar.server.db.DbClient; +import org.sonar.server.rule.Rule; +import org.sonar.server.rule.index.RuleDoc; +import org.sonar.server.rule.index.RuleIndex; +import org.sonar.server.rule.index.RuleNormalizer; import org.sonar.server.user.index.UserIndex; import java.util.Date; @@ -42,15 +48,21 @@ import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static org.sonar.server.issue.notification.NewIssuesStatistics.METRIC.*; +import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.ASSIGNEE; +import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.COMPONENT; +import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.DEBT; +import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.RULE; +import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.SEVERITY; +import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.TAG; public class NewIssuesNotificationTest { NewIssuesStatistics.Stats stats = new NewIssuesStatistics.Stats(); UserIndex userIndex = mock(UserIndex.class); + RuleIndex ruleIndex = mock(RuleIndex.class); DbClient dbClient = mock(DbClient.class, Mockito.RETURNS_DEEP_STUBS); Durations durations = mock(Durations.class); - NewIssuesNotification sut = new NewIssuesNotification(userIndex, dbClient, durations); + NewIssuesNotification sut = new NewIssuesNotification(userIndex, ruleIndex, dbClient, durations); @Test public void set_project() throws Exception { @@ -83,6 +95,8 @@ public class NewIssuesNotificationTest { addIssueNTimes(newIssue2(), 3); when(dbClient.componentDao().getByUuid(any(DbSession.class), eq("file-uuid")).name()).thenReturn("file-name"); when(dbClient.componentDao().getByUuid(any(DbSession.class), eq("directory-uuid")).name()).thenReturn("directory-name"); + when(ruleIndex.getByKey(RuleKey.of("SonarQube", "rule-the-world"))).thenReturn(newRule("Rule the World", "Java")); + when(ruleIndex.getByKey(RuleKey.of("SonarQube", "rule-the-universe"))).thenReturn(newRule("Rule the Universe", "Clojure")); sut.setStatistics(component, stats); @@ -92,14 +106,18 @@ public class NewIssuesNotificationTest { assertThat(sut.getFieldValue(ASSIGNEE + ".1.count")).isEqualTo("5"); assertThat(sut.getFieldValue(ASSIGNEE + ".2.label")).isEqualTo("keenan"); assertThat(sut.getFieldValue(ASSIGNEE + ".2.count")).isEqualTo("3"); - assertThat(sut.getFieldValue(TAGS + ".1.label")).isEqualTo("owasp"); - assertThat(sut.getFieldValue(TAGS + ".1.count")).isEqualTo("8"); - assertThat(sut.getFieldValue(TAGS + ".2.label")).isEqualTo("bug"); - assertThat(sut.getFieldValue(TAGS + ".2.count")).isEqualTo("5"); + assertThat(sut.getFieldValue(TAG + ".1.label")).isEqualTo("owasp"); + assertThat(sut.getFieldValue(TAG + ".1.count")).isEqualTo("8"); + assertThat(sut.getFieldValue(TAG + ".2.label")).isEqualTo("bug"); + assertThat(sut.getFieldValue(TAG + ".2.count")).isEqualTo("5"); assertThat(sut.getFieldValue(COMPONENT + ".1.label")).isEqualTo("file-name"); assertThat(sut.getFieldValue(COMPONENT + ".1.count")).isEqualTo("5"); assertThat(sut.getFieldValue(COMPONENT + ".2.label")).isEqualTo("directory-name"); assertThat(sut.getFieldValue(COMPONENT + ".2.count")).isEqualTo("3"); + assertThat(sut.getFieldValue(RULE + ".1.label")).isEqualTo("Rule the World (Java)"); + assertThat(sut.getFieldValue(RULE + ".1.count")).isEqualTo("5"); + assertThat(sut.getFieldValue(RULE + ".2.label")).isEqualTo("Rule the Universe (Clojure)"); + assertThat(sut.getFieldValue(RULE + ".2.count")).isEqualTo("3"); assertThat(sut.getDefaultMessage()).startsWith("8 new issues on project-long-name"); } @@ -124,6 +142,7 @@ public class NewIssuesNotificationTest { .setComponentUuid("file-uuid") .setSeverity(Severity.INFO) .setTags(Lists.newArrayList("bug", "owasp")) + .setRuleKey(RuleKey.of("SonarQube", "rule-the-world")) .setDebt(Duration.create(5L)); } @@ -133,6 +152,14 @@ public class NewIssuesNotificationTest { .setComponentUuid("directory-uuid") .setSeverity(Severity.BLOCKER) .setTags(Lists.newArrayList("owasp")) + .setRuleKey(RuleKey.of("SonarQube", "rule-the-universe")) .setDebt(Duration.create(10L)); } + + private Rule newRule(String name, String language) { + return new RuleDoc(ImmutableMap.of( + RuleNormalizer.RuleField.NAME.field(), name, + RuleNormalizer.RuleField.LANGUAGE.field(), language + )); + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesStatisticsTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesStatisticsTest.java index a23f6570126..947e1741492 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesStatisticsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesStatisticsTest.java @@ -23,9 +23,10 @@ package org.sonar.server.issue.notification; import com.google.common.collect.Lists; import org.junit.Test; import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.Severity; import org.sonar.api.utils.Duration; -import org.sonar.server.issue.notification.NewIssuesStatistics.METRIC; +import org.sonar.server.issue.notification.NewIssuesStatistics.Metric; import static org.assertj.core.api.Assertions.assertThat; @@ -41,16 +42,18 @@ public class NewIssuesStatisticsTest { sut.add(issue.setAssignee("james")); sut.add(issue.setAssignee("keenan")); - assertThat(countDistribution(METRIC.ASSIGNEE, "maynard")).isEqualTo(1); - assertThat(countDistribution(METRIC.ASSIGNEE, "james")).isEqualTo(1); - assertThat(countDistribution(METRIC.ASSIGNEE, "keenan")).isEqualTo(1); - assertThat(countDistribution(METRIC.ASSIGNEE, "wrong.login")).isEqualTo(0); - assertThat(countDistribution(METRIC.COMPONENT, "file-uuid")).isEqualTo(3); - assertThat(countDistribution(METRIC.COMPONENT, "wrong-uuid")).isEqualTo(0); - assertThat(countDistribution(METRIC.SEVERITY, Severity.INFO)).isEqualTo(3); - assertThat(countDistribution(METRIC.SEVERITY, Severity.CRITICAL)).isEqualTo(0); - assertThat(countDistribution(METRIC.TAGS, "owasp")).isEqualTo(3); - assertThat(countDistribution(METRIC.TAGS, "wrong-tag")).isEqualTo(0); + assertThat(countDistribution(Metric.ASSIGNEE, "maynard")).isEqualTo(1); + assertThat(countDistribution(Metric.ASSIGNEE, "james")).isEqualTo(1); + assertThat(countDistribution(Metric.ASSIGNEE, "keenan")).isEqualTo(1); + assertThat(countDistribution(Metric.ASSIGNEE, "wrong.login")).isEqualTo(0); + assertThat(countDistribution(Metric.COMPONENT, "file-uuid")).isEqualTo(3); + assertThat(countDistribution(Metric.COMPONENT, "wrong-uuid")).isEqualTo(0); + assertThat(countDistribution(Metric.SEVERITY, Severity.INFO)).isEqualTo(3); + assertThat(countDistribution(Metric.SEVERITY, Severity.CRITICAL)).isEqualTo(0); + assertThat(countDistribution(Metric.TAG, "owasp")).isEqualTo(3); + assertThat(countDistribution(Metric.TAG, "wrong-tag")).isEqualTo(0); + assertThat(countDistribution(Metric.RULE, "SonarQube:rule-the-world")).isEqualTo(3); + assertThat(countDistribution(Metric.RULE, "SonarQube:has-a-fake-rule")).isEqualTo(0); assertThat(sut.globalStatistics().debt().toMinutes()).isEqualTo(15L); assertThat(sut.globalStatistics().hasIssues()).isTrue(); assertThat(sut.hasIssues()).isTrue(); @@ -62,7 +65,7 @@ public class NewIssuesStatisticsTest { assertThat(sut.globalStatistics().hasIssues()).isFalse(); } - private int countDistribution(METRIC metric, String label) { + private int countDistribution(Metric metric, String label) { return sut.globalStatistics().countForMetric(metric, label); } @@ -72,6 +75,7 @@ public class NewIssuesStatisticsTest { .setComponentUuid("file-uuid") .setNew(true) .setSeverity(Severity.INFO) + .setRuleKey(RuleKey.of("SonarQube", "rule-the-world")) .setTags(Lists.newArrayList("bug", "owasp")) .setDebt(Duration.create(5L)); } diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/notification/MyNewIssuesEmailTemplateTest/email_with_all_details.txt b/server/sonar-server/src/test/resources/org/sonar/server/issue/notification/MyNewIssuesEmailTemplateTest/email_with_all_details.txt index 39fa601f01d..c2e53d7a50f 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/notification/MyNewIssuesEmailTemplateTest/email_with_all_details.txt +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/notification/MyNewIssuesEmailTemplateTest/email_with_all_details.txt @@ -5,6 +5,10 @@ Project: Struts Severity Blocker: 0 Critical: 5 Major: 10 Minor: 3 Info: 1 + Rules + Rule the Universe (Clojure): 42 + Rule the World (Java): 5 + Tags oscar: 3 cesar: 10 diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/notification/NewIssuesEmailTemplateTest/email_with_all_details.txt b/server/sonar-server/src/test/resources/org/sonar/server/issue/notification/NewIssuesEmailTemplateTest/email_with_all_details.txt index bddf6f7309a..64d4aeb2f3f 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/notification/NewIssuesEmailTemplateTest/email_with_all_details.txt +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/notification/NewIssuesEmailTemplateTest/email_with_all_details.txt @@ -9,6 +9,10 @@ Project: Struts robin.williams: 5 al.pacino: 7 + Rules + Rule the Universe (Clojure): 42 + Rule the World (Java): 5 + Tags oscar: 3 cesar: 10