private void doExecute(Component project) {
long analysisDate = analysisMetadataHolder.getAnalysisDate();
- Predicate<Issue> isOnLeakPredicate = i -> i.isNew() && i.creationDate().getTime() >= truncateToSeconds(analysisDate);
+ Predicate<DefaultIssue> isOnLeakPredicate = i -> i.isNew() && i.creationDate().getTime() >= truncateToSeconds(analysisDate);
NewIssuesStatistics newIssuesStats = new NewIssuesStatistics(isOnLeakPredicate);
try (CloseableIterator<DefaultIssue> issues = issueCache.traverse()) {
processIssues(newIssuesStats, issues, project);
*/
package org.sonar.server.issue.notification;
-import com.google.common.collect.Lists;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
+import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.Locale;
import org.sonar.api.config.EmailSettings;
import org.sonar.api.i18n.I18n;
import org.sonar.api.notifications.Notification;
-import org.sonar.api.rule.Severity;
+import org.sonar.api.rules.RuleType;
import org.sonar.api.utils.DateUtils;
import org.sonar.plugins.emailnotifications.api.EmailMessage;
import org.sonar.plugins.emailnotifications.api.EmailTemplate;
StringBuilder message = new StringBuilder();
message.append("Project: ").append(projectName).append(NEW_LINE).append(NEW_LINE);
- appendSeverity(message, notification);
+ appendRuleType(message, notification);
appendAssignees(message, notification);
appendRules(message, notification);
appendTags(message, notification);
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.RULE_TYPE + COUNT),
notification.getFieldValue(Metric.EFFORT + COUNT));
}
genericAppendOfMetric(Metric.RULE, "Rules", message, notification);
}
- protected void appendSeverity(StringBuilder message, Notification notification) {
+ protected void appendRuleType(StringBuilder message, Notification notification) {
message
.append(String.format("%s new issues (new debt: %s)",
- notification.getFieldValue(Metric.SEVERITY + COUNT),
+ notification.getFieldValue(Metric.RULE_TYPE + COUNT),
notification.getFieldValue(Metric.EFFORT + COUNT)))
.append(NEW_LINE).append(NEW_LINE)
.append(TAB)
- .append("Severity")
+ .append("Type")
.append(NEW_LINE)
.append(TAB)
.append(TAB);
- for (Iterator<String> 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));
- if (severityIterator.hasNext()) {
+
+ for (Iterator<RuleType> ruleTypeIterator = Arrays.asList(RuleType.BUG, RuleType.VULNERABILITY, RuleType.CODE_SMELL).iterator(); ruleTypeIterator.hasNext();) {
+ RuleType ruleType = ruleTypeIterator.next();
+ String ruleTypeLabel = i18n.message(getLocale(), "rule_type." + ruleType, ruleType.name());
+ message.append(ruleTypeLabel).append(": ").append(notification.getFieldValue(Metric.RULE_TYPE + DOT + ruleType + COUNT));
+ if (ruleTypeIterator.hasNext()) {
message.append(TAB);
}
}
@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.RULE_TYPE + COUNT),
projectName);
}
*/
package org.sonar.server.issue.notification;
-import com.google.common.collect.ImmutableMap;
+import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import javax.annotation.Nullable;
import org.sonar.api.notifications.Notification;
import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rule.Severity;
+import org.sonar.api.rules.RuleType;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.Duration;
import org.sonar.api.utils.Durations;
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;
+import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.RULE_TYPE;
public class NewIssuesNotification extends Notification {
}
public NewIssuesNotification setStatistics(String projectName, NewIssuesStatistics.Stats stats) {
- setDefaultMessage(stats.getDistributedMetricStats(SEVERITY).getOnLeak() + " new issues on " + projectName + ".\n");
+ setDefaultMessage(stats.getDistributedMetricStats(RULE_TYPE).getOnLeak() + " new issues on " + projectName + ".\n");
try (DbSession dbSession = dbClient.openSession(false)) {
- setSeverityStatistics(stats);
+ setRuleTypeStatistics(stats);
setAssigneesStatistics(stats);
setTagsStatistics(stats);
setComponentsStatistics(dbSession, stats);
.map(Map.Entry::getKey)
.map(RuleKey::parse)
.collect(MoreCollectors.toSet(fiveBiggest.size()));
- ImmutableMap<String, RuleDefinitionDto> ruleByRuleKey = dbClient.ruleDao().selectDefinitionByKeys(dbSession, ruleKeys)
+ Map<String, RuleDefinitionDto> ruleByRuleKey = dbClient.ruleDao().selectDefinitionByKeys(dbSession, ruleKeys)
.stream()
.collect(MoreCollectors.uniqueIndex(s -> s.getKey().toString()));
int i = 1;
return this;
}
- private void setSeverityStatistics(NewIssuesStatistics.Stats stats) {
- DistributedMetricStatsInt distributedMetricStats = stats.getDistributedMetricStats(SEVERITY);
- setFieldValue(SEVERITY + COUNT, String.valueOf(distributedMetricStats.getOnLeak()));
- for (String severity : Severity.ALL) {
- setFieldValue(
- SEVERITY + DOT + severity + COUNT,
- String.valueOf(distributedMetricStats.getForLabel(severity).map(MetricStatsInt::getOnLeak).orElse(0)));
- }
+ private void setRuleTypeStatistics(NewIssuesStatistics.Stats stats) {
+ DistributedMetricStatsInt distributedMetricStats = stats.getDistributedMetricStats(RULE_TYPE);
+ setFieldValue(RULE_TYPE + COUNT, String.valueOf(distributedMetricStats.getOnLeak()));
+ Arrays.stream(RuleType.values())
+ .forEach(ruleType -> setFieldValue(
+ RULE_TYPE + DOT + ruleType + COUNT,
+ String.valueOf(distributedMetricStats.getForLabel(ruleType.name()).map(MetricStatsInt::getOnLeak).orElse(0))));
}
@Override
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Predicate;
-import org.sonar.api.issue.Issue;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.Duration;
+import org.sonar.core.issue.DefaultIssue;
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.RULE_TYPE;
import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.TAG;
public class NewIssuesStatistics {
- private final Predicate<Issue> onLeakPredicate;
+ private final Predicate<DefaultIssue> onLeakPredicate;
private final Map<String, Stats> assigneesStatistics = new LinkedHashMap<>();
private final Stats globalStatistics;
- public NewIssuesStatistics(Predicate<Issue> onLeakPredicate) {
+ public NewIssuesStatistics(Predicate<DefaultIssue> onLeakPredicate) {
this.onLeakPredicate = onLeakPredicate;
this.globalStatistics = new Stats(onLeakPredicate);
}
- public void add(Issue issue) {
+ public void add(DefaultIssue issue) {
globalStatistics.add(issue);
String login = issue.assignee();
if (login != null) {
}
public enum Metric {
- SEVERITY(true), TAG(true), COMPONENT(true), ASSIGNEE(true), EFFORT(false), RULE(true);
+ RULE_TYPE(true), TAG(true), COMPONENT(true), ASSIGNEE(true), EFFORT(false), RULE(true);
private final boolean isComputedByDistribution;
Metric(boolean isComputedByDistribution) {
}
public static class Stats {
- private final Predicate<Issue> onLeakPredicate;
+ private final Predicate<DefaultIssue> onLeakPredicate;
private final Map<Metric, DistributedMetricStatsInt> distributions = new EnumMap<>(Metric.class);
private MetricStatsLong effortStats = new MetricStatsLong();
- public Stats(Predicate<Issue> onLeakPredicate) {
+ public Stats(Predicate<DefaultIssue> onLeakPredicate) {
this.onLeakPredicate = onLeakPredicate;
for (Metric metric : Metric.values()) {
if (metric.isComputedByDistribution()) {
}
}
- public void add(Issue issue) {
+ public void add(DefaultIssue issue) {
boolean isOnLeak = onLeakPredicate.test(issue);
- distributions.get(SEVERITY).increment(issue.severity(), isOnLeak);
+ distributions.get(RULE_TYPE).increment(issue.type().name(), isOnLeak);
String componentUuid = issue.componentUuid();
if (componentUuid != null) {
distributions.get(COMPONENT).increment(componentUuid, isOnLeak);
}
public boolean hasIssues() {
- return getDistributedMetricStats(SEVERITY).getTotal() > 0;
+ return getDistributedMetricStats(RULE_TYPE).getTotal() > 0;
}
public boolean hasIssuesOnLeak() {
- return getDistributedMetricStats(SEVERITY).getOnLeak() > 0;
+ return getDistributedMetricStats(RULE_TYPE).getOnLeak() > 0;
}
public boolean hasIssuesOffLeak() {
- return getDistributedMetricStats(SEVERITY).getOffLeak() > 0;
+ return getDistributedMetricStats(RULE_TYPE).getOffLeak() > 0;
}
@Override
import org.mockito.ArgumentCaptor;
import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent;
import org.sonar.api.notifications.Notification;
-import org.sonar.api.rule.Severity;
+import org.sonar.api.rules.RuleType;
import org.sonar.api.utils.Duration;
import org.sonar.api.utils.System2;
import org.sonar.core.issue.DefaultIssue;
@Rule
public TemporaryFolder temp = new TemporaryFolder();
+ private final Random random = new Random();
+ private final RuleType randomRuleType = RuleType.values()[random.nextInt(RuleType.values().length)];
private NotificationService notificationService = mock(NotificationService.class);
private NewIssuesNotificationFactory newIssuesNotificationFactory = mock(NewIssuesNotificationFactory.class);
private NewIssuesNotification newIssuesNotificationMock = createNewIssuesNotificationMock();
@Test
public void send_global_new_issues_notification() throws Exception {
issueCache.newAppender().append(
- new DefaultIssue().setSeverity(Severity.BLOCKER).setEffort(ISSUE_DURATION)
+ new DefaultIssue().setType(randomRuleType).setEffort(ISSUE_DURATION)
.setCreationDate(new Date(ANALYSE_DATE)))
.close();
when(notificationService.hasProjectSubscribersForTypes(PROJECT.getUuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
Integer[] backDatedEfforts = IntStream.range(0, 1 + random.nextInt(10)).mapToObj(i -> 10 + random.nextInt(100)).toArray(Integer[]::new);
Duration expectedEffort = Duration.create(Arrays.stream(efforts).mapToInt(i -> i).sum());
List<DefaultIssue> issues = Stream.concat(Arrays.stream(efforts)
- .map(effort -> new DefaultIssue().setSeverity(Severity.BLOCKER).setEffort(Duration.create(effort))
+ .map(effort -> new DefaultIssue().setType(randomRuleType).setEffort(Duration.create(effort))
.setCreationDate(new Date(ANALYSE_DATE))),
Arrays.stream(backDatedEfforts)
- .map(effort -> new DefaultIssue().setSeverity(Severity.BLOCKER).setEffort(Duration.create(effort))
+ .map(effort -> new DefaultIssue().setType(randomRuleType).setEffort(Duration.create(effort))
.setCreationDate(new Date(ANALYSE_DATE - FIVE_MINUTES_IN_MS))))
.collect(Collectors.toList());
Collections.shuffle(issues);
NewIssuesStatistics.Stats stats = statsCaptor.getValue();
assertThat(stats.hasIssues()).isTrue();
// just checking all issues have been added to the stats
- DistributedMetricStatsInt severity = stats.getDistributedMetricStats(NewIssuesStatistics.Metric.SEVERITY);
+ DistributedMetricStatsInt severity = stats.getDistributedMetricStats(NewIssuesStatistics.Metric.RULE_TYPE);
assertThat(severity.getOnLeak()).isEqualTo(efforts.length);
assertThat(severity.getOffLeak()).isEqualTo(backDatedEfforts.length);
assertThat(severity.getTotal()).isEqualTo(backDatedEfforts.length + efforts.length);
@Test
public void do_not_send_global_new_issues_notification_if_issue_has_been_backdated() {
issueCache.newAppender().append(
- new DefaultIssue().setSeverity(Severity.BLOCKER).setEffort(ISSUE_DURATION)
+ new DefaultIssue().setType(randomRuleType).setEffort(ISSUE_DURATION)
.setCreationDate(new Date(ANALYSE_DATE - FIVE_MINUTES_IN_MS)))
.close();
when(notificationService.hasProjectSubscribersForTypes(PROJECT.getUuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
public void send_global_new_issues_notification_on_branch() throws Exception {
ComponentDto branch = setUpProjectWithBranch();
issueCache.newAppender().append(
- new DefaultIssue().setSeverity(Severity.BLOCKER).setEffort(ISSUE_DURATION).setCreationDate(new Date(ANALYSE_DATE))).close();
+ new DefaultIssue().setType(randomRuleType).setEffort(ISSUE_DURATION).setCreationDate(new Date(ANALYSE_DATE))).close();
when(notificationService.hasProjectSubscribersForTypes(branch.uuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
analysisMetadataHolder.setBranch(newBranch());
public void do_not_send_global_new_issues_notification_on_branch_if_issue_has_been_backdated() throws Exception {
ComponentDto branch = setUpProjectWithBranch();
issueCache.newAppender().append(
- new DefaultIssue().setSeverity(Severity.BLOCKER).setEffort(ISSUE_DURATION).setCreationDate(new Date(ANALYSE_DATE - FIVE_MINUTES_IN_MS))).close();
+ new DefaultIssue().setType(randomRuleType).setEffort(ISSUE_DURATION).setCreationDate(new Date(ANALYSE_DATE - FIVE_MINUTES_IN_MS))).close();
when(notificationService.hasProjectSubscribersForTypes(branch.uuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
analysisMetadataHolder.setBranch(newBranch());
@Test
public void send_new_issues_notification_to_user() throws Exception {
issueCache.newAppender().append(
- new DefaultIssue().setSeverity(Severity.BLOCKER).setEffort(ISSUE_DURATION).setAssignee(ISSUE_ASSIGNEE)
+ new DefaultIssue().setType(randomRuleType).setEffort(ISSUE_DURATION).setAssignee(ISSUE_ASSIGNEE)
.setCreationDate(new Date(ANALYSE_DATE)))
.close();
when(notificationService.hasProjectSubscribersForTypes(PROJECT.getUuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
String assignee = randomAlphanumeric(5);
String otherAssignee = randomAlphanumeric(5);
List<DefaultIssue> issues = Stream.concat(Arrays.stream(assigned)
- .map(effort -> new DefaultIssue().setSeverity(Severity.BLOCKER).setEffort(Duration.create(effort))
+ .map(effort -> new DefaultIssue().setType(randomRuleType).setEffort(Duration.create(effort))
.setAssignee(assignee)
.setCreationDate(new Date(ANALYSE_DATE))),
Arrays.stream(assignedToOther)
- .map(effort -> new DefaultIssue().setSeverity(Severity.BLOCKER).setEffort(Duration.create(effort))
+ .map(effort -> new DefaultIssue().setType(randomRuleType).setEffort(Duration.create(effort))
.setAssignee(otherAssignee)
.setCreationDate(new Date(ANALYSE_DATE))))
.collect(Collectors.toList());
NewIssuesStatistics.Stats stats = statsCaptor.getValue();
assertThat(stats.hasIssues()).isTrue();
// just checking all issues have been added to the stats
- DistributedMetricStatsInt severity = stats.getDistributedMetricStats(NewIssuesStatistics.Metric.SEVERITY);
+ DistributedMetricStatsInt severity = stats.getDistributedMetricStats(NewIssuesStatistics.Metric.RULE_TYPE);
assertThat(severity.getOnLeak()).isEqualTo(assigned.length);
assertThat(severity.getOffLeak()).isEqualTo(0);
assertThat(severity.getTotal()).isEqualTo(assigned.length);
Integer[] backDatedEfforts = IntStream.range(0, 1 + random.nextInt(10)).mapToObj(i -> 10 + random.nextInt(100)).toArray(Integer[]::new);
Duration expectedEffort = Duration.create(Arrays.stream(efforts).mapToInt(i -> i).sum());
List<DefaultIssue> issues = Stream.concat(Arrays.stream(efforts)
- .map(effort -> new DefaultIssue().setSeverity(Severity.BLOCKER).setEffort(Duration.create(effort))
+ .map(effort -> new DefaultIssue().setType(randomRuleType).setEffort(Duration.create(effort))
.setAssignee(ISSUE_ASSIGNEE)
.setCreationDate(new Date(ANALYSE_DATE))),
Arrays.stream(backDatedEfforts)
- .map(effort -> new DefaultIssue().setSeverity(Severity.BLOCKER).setEffort(Duration.create(effort))
+ .map(effort -> new DefaultIssue().setType(randomRuleType).setEffort(Duration.create(effort))
.setAssignee(ISSUE_ASSIGNEE)
.setCreationDate(new Date(ANALYSE_DATE - FIVE_MINUTES_IN_MS))))
.collect(Collectors.toList());
NewIssuesStatistics.Stats stats = statsCaptor.getValue();
assertThat(stats.hasIssues()).isTrue();
// just checking all issues have been added to the stats
- DistributedMetricStatsInt severity = stats.getDistributedMetricStats(NewIssuesStatistics.Metric.SEVERITY);
+ DistributedMetricStatsInt severity = stats.getDistributedMetricStats(NewIssuesStatistics.Metric.RULE_TYPE);
assertThat(severity.getOnLeak()).isEqualTo(efforts.length);
assertThat(severity.getOffLeak()).isEqualTo(backDatedEfforts.length);
assertThat(severity.getTotal()).isEqualTo(backDatedEfforts.length + efforts.length);
@Test
public void do_not_send_new_issues_notification_to_user_if_issue_is_backdated() throws Exception {
issueCache.newAppender().append(
- new DefaultIssue().setSeverity(Severity.BLOCKER).setEffort(ISSUE_DURATION).setAssignee(ISSUE_ASSIGNEE)
+ new DefaultIssue().setType(randomRuleType).setEffort(ISSUE_DURATION).setAssignee(ISSUE_ASSIGNEE)
.setCreationDate(new Date(ANALYSE_DATE - FIVE_MINUTES_IN_MS)))
.close();
when(notificationService.hasProjectSubscribersForTypes(PROJECT.getUuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
import org.apache.commons.io.IOUtils;
import org.junit.Before;
import org.junit.Test;
-import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.sonar.api.config.EmailSettings;
import org.sonar.api.notifications.Notification;
import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.COMPONENT;
import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.EFFORT;
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.RULE_TYPE;
import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.TAG;
public class MyNewIssuesEmailTemplateTest {
date = new Date();
userIndex = mock(UserIndex.class);
// returns the login passed in parameter
- when(userIndex.getNullableByLogin(anyString())).thenAnswer(new Answer<UserDoc>() {
- @Override
- public UserDoc answer(InvocationOnMock invocationOnMock) throws Throwable {
- return new UserDoc().setName((String) invocationOnMock.getArguments()[0]);
- }
- });
- when(i18n.message(any(Locale.class), eq("severity.BLOCKER"), anyString())).thenReturn("Blocker");
- when(i18n.message(any(Locale.class), eq("severity.CRITICAL"), anyString())).thenReturn("Critical");
- when(i18n.message(any(Locale.class), eq("severity.MAJOR"), anyString())).thenReturn("Major");
- when(i18n.message(any(Locale.class), eq("severity.MINOR"), anyString())).thenReturn("Minor");
- when(i18n.message(any(Locale.class), eq("severity.INFO"), anyString())).thenReturn("Info");
+ when(userIndex.getNullableByLogin(anyString()))
+ .thenAnswer((Answer<UserDoc>) invocationOnMock -> new UserDoc().setName((String) invocationOnMock.getArguments()[0]));
+ when(i18n.message(any(Locale.class), eq("rule_type.BUG"), anyString())).thenReturn("Bug");
+ when(i18n.message(any(Locale.class), eq("rule_type.CODE_SMELL"), anyString())).thenReturn("Code Smell");
+ when(i18n.message(any(Locale.class), eq("rule_type.VULNERABILITY"), anyString())).thenReturn("Vulnerability");
underTest = new MyNewIssuesEmailTemplate(settings, i18n);
}
EmailMessage message = underTest.format(notification);
// TODO datetime to be completed when test is isolated from JVM timezone
- assertStartsWithFile(message.getMessage(), "MyNewIssuesEmailTemplateTest/email_with_all_details.txt");
+ assertThat(message.getMessage()).startsWith(
+ "Project: Struts\n" +
+ "\n" +
+ "32 new issues (new debt: 1d3h)\n" +
+ "\n" +
+ " Type\n" +
+ " Bug: 1 Vulnerability: 3 Code Smell: 0\n" +
+ "\n" +
+ " Rules\n" +
+ " Rule the Universe (Clojure): 42\n" +
+ " Rule the World (Java): 5\n" +
+ "\n" +
+ " Tags\n" +
+ " oscar: 3\n" +
+ " cesar: 10\n" +
+ "\n" +
+ " Most impacted files\n" +
+ " /path/to/file: 3\n" +
+ " /path/to/directory: 7\n" +
+ "\n" +
+ "See it in SonarQube: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&assignees=lo.gin&createdAt=2010-05-18");
}
@Test
EmailMessage message = underTest.format(notification);
// TODO datetime to be completed when test is isolated from JVM timezone
- assertStartsWithFile(message.getMessage(), "MyNewIssuesEmailTemplateTest/email_with_no_assignee_tags_components.txt");
+ assertThat(message.getMessage())
+ .startsWith("Project: Struts\n" +
+ "\n" +
+ "32 new issues (new debt: 1d3h)\n" +
+ "\n" +
+ " Type\n" +
+ " Bug: 1 Vulnerability: 3 Code Smell: 0\n" +
+ "\n" +
+ "See it in SonarQube: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&assignees=lo.gin&createdAt=2010-05-18");
}
@Test
EmailMessage message = underTest.format(notification);
// TODO datetime to be completed when test is isolated from JVM timezone
- assertStartsWithFile(message.getMessage(), "MyNewIssuesEmailTemplateTest/email_with_issue_on_branch.txt");
+ assertThat(message.getMessage())
+ .startsWith("Project: Struts\n" +
+ "\n" +
+ "32 new issues (new debt: 1d3h)\n" +
+ "\n" +
+ " Type\n" +
+ " Bug: 1 Vulnerability: 3 Code Smell: 0\n" +
+ "\n" +
+ "See it in SonarQube: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&assignees=lo.gin&branch=feature1&createdAt=2010-05-18");
}
@Test
public void do_not_add_footer_when_properties_missing() {
Notification notification = new Notification(MyNewIssuesNotification.MY_NEW_ISSUES_NOTIF_TYPE)
- .setFieldValue(SEVERITY + ".count", "32")
+ .setFieldValue(RULE_TYPE + ".count", "32")
.setFieldValue("projectName", "Struts");
EmailMessage message = underTest.format(notification);
.setFieldValue("projectDate", "2010-05-18T14:50:45+0000")
.setFieldValue("assignee", "lo.gin")
.setFieldValue(EFFORT + ".count", "1d3h")
- .setFieldValue(SEVERITY + ".count", "32")
- .setFieldValue(SEVERITY + ".INFO.count", "1")
- .setFieldValue(SEVERITY + ".MINOR.count", "3")
- .setFieldValue(SEVERITY + ".MAJOR.count", "10")
- .setFieldValue(SEVERITY + ".CRITICAL.count", "5")
- .setFieldValue(SEVERITY + ".BLOCKER.count", "0");
+ .setFieldValue(RULE_TYPE + ".count", "32")
+ .setFieldValue(RULE_TYPE + ".BUG.count", "1")
+ .setFieldValue(RULE_TYPE + ".VULNERABILITY.count", "3")
+ .setFieldValue(RULE_TYPE + ".CODE_SMELL.count", "0");
}
private void addTags(Notification notification) {
package org.sonar.server.issue.notification;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Locale;
import org.apache.commons.io.IOUtils;
import org.junit.Before;
import org.junit.Test;
-import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.sonar.api.config.EmailSettings;
import org.sonar.api.notifications.Notification;
import org.sonar.server.user.index.UserDoc;
import org.sonar.server.user.index.UserIndex;
-import java.nio.charset.StandardCharsets;
-import java.util.Locale;
-
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.COMPONENT;
import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.EFFORT;
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.RULE_TYPE;
import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.TAG;
public class NewIssuesEmailTemplateTest {
i18n = mock(DefaultI18n.class);
userIndex = mock(UserIndex.class);
// returns the login passed in parameter
- when(userIndex.getNullableByLogin(anyString())).thenAnswer(new Answer<UserDoc>() {
- @Override
- public UserDoc answer(InvocationOnMock invocationOnMock) throws Throwable {
- return new UserDoc().setName((String) invocationOnMock.getArguments()[0]);
- }
- });
- when(i18n.message(any(Locale.class), eq("severity.BLOCKER"), anyString())).thenReturn("Blocker");
- when(i18n.message(any(Locale.class), eq("severity.CRITICAL"), anyString())).thenReturn("Critical");
- when(i18n.message(any(Locale.class), eq("severity.MAJOR"), anyString())).thenReturn("Major");
- when(i18n.message(any(Locale.class), eq("severity.MINOR"), anyString())).thenReturn("Minor");
- when(i18n.message(any(Locale.class), eq("severity.INFO"), anyString())).thenReturn("Info");
+ when(userIndex.getNullableByLogin(anyString()))
+ .thenAnswer((Answer<UserDoc>) invocationOnMock -> new UserDoc().setName((String) invocationOnMock.getArguments()[0]));
+ when(i18n.message(any(Locale.class), eq("rule_type.CODE_SMELL"), anyString())).thenReturn("Code Smell");
+ when(i18n.message(any(Locale.class), eq("rule_type.VULNERABILITY"), anyString())).thenReturn("Vulnerability");
+ when(i18n.message(any(Locale.class), eq("rule_type.BUG"), anyString())).thenReturn("Bug");
template = new NewIssuesEmailTemplate(settings, i18n);
}
EmailMessage message = template.format(notification);
// TODO datetime to be completed when test is isolated from JVM timezone
- assertStartsWithFile(message.getMessage(), "NewIssuesEmailTemplateTest/email_with_all_details.txt");
+ assertThat(message.getMessage())
+ .startsWith("Project: Struts\n" +
+ "\n" +
+ "32 new issues (new debt: 1d3h)\n" +
+ "\n" +
+ " Type\n" +
+ " Bug: 1 Vulnerability: 10 Code Smell: 3\n" +
+ "\n" +
+ " Assignees\n" +
+ " robin.williams: 5\n" +
+ " al.pacino: 7\n" +
+ "\n" +
+ " Rules\n" +
+ " Rule the Universe (Clojure): 42\n" +
+ " Rule the World (Java): 5\n" +
+ "\n" +
+ " Tags\n" +
+ " oscar: 3\n" +
+ " cesar: 10\n" +
+ "\n" +
+ " Most impacted files\n" +
+ " /path/to/file: 3\n" +
+ " /path/to/directory: 7\n" +
+ "\n" +
+ "See it in SonarQube: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&createdAt=2010-05-1");
}
@Test
EmailMessage message = template.format(notification);
// TODO datetime to be completed when test is isolated from JVM timezone
- assertStartsWithFile(message.getMessage(), "NewIssuesEmailTemplateTest/email_with_partial_details.txt");
+ assertThat(message.getMessage())
+ .startsWith("Project: Struts\n" +
+ "\n" +
+ "32 new issues (new debt: 1d3h)\n" +
+ "\n" +
+ " Type\n" +
+ " Bug: 1 Vulnerability: 10 Code Smell: 3\n" +
+ "\n" +
+ "See it in SonarQube: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&createdAt=2010-05-1");
}
@Test
EmailMessage message = template.format(notification);
// TODO datetime to be completed when test is isolated from JVM timezone
- assertStartsWithFile(message.getMessage(), "NewIssuesEmailTemplateTest/email_with_issue_on_branch.txt");
+ assertThat(message.getMessage())
+ .startsWith("Project: Struts\n" +
+ "\n" +
+ "32 new issues (new debt: 1d3h)\n" +
+ "\n" +
+ " Type\n" +
+ " Bug: 1 Vulnerability: 10 Code Smell: 3\n" +
+ "\n" +
+ "See it in SonarQube: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&branch=feature1&createdAt=2010-05-1");
}
@Test
public void do_not_add_footer_when_properties_missing() {
Notification notification = new Notification(NewIssuesNotification.TYPE)
- .setFieldValue(SEVERITY + ".count", "32")
+ .setFieldValue(RULE_TYPE + ".count", "32")
.setFieldValue("projectName", "Struts");
EmailMessage message = template.format(notification);
.setFieldValue("projectUuid", "ABCDE")
.setFieldValue("projectDate", "2010-05-18T14:50:45+0000")
.setFieldValue(EFFORT + ".count", "1d3h")
- .setFieldValue(SEVERITY + ".count", "32")
- .setFieldValue(SEVERITY + ".INFO.count", "1")
- .setFieldValue(SEVERITY + ".MINOR.count", "3")
- .setFieldValue(SEVERITY + ".MAJOR.count", "10")
- .setFieldValue(SEVERITY + ".CRITICAL.count", "5")
- .setFieldValue(SEVERITY + ".BLOCKER.count", "0");
+ .setFieldValue(RULE_TYPE + ".count", "32")
+ .setFieldValue(RULE_TYPE + ".BUG.count", "1")
+ .setFieldValue(RULE_TYPE + ".CODE_SMELL.count", "3")
+ .setFieldValue(RULE_TYPE + ".VULNERABILITY.count", "10");
}
private void addAssignees(Notification notification) {
import org.junit.Before;
import org.junit.Test;
import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rule.Severity;
+import org.sonar.api.rules.RuleType;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.Duration;
import org.sonar.api.utils.Durations;
import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.COMPONENT;
import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.EFFORT;
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.RULE_TYPE;
import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.TAG;
public class NewIssuesNotificationTest {
+ private final Random random = new Random();
+ private final RuleType randomRuleType = RuleType.values()[random.nextInt(RuleType.values().length)];
private NewIssuesStatistics.Stats stats = new NewIssuesStatistics.Stats(i -> true);
private UserIndex userIndex = mock(UserIndex.class);
private DbClient dbClient = mock(DbClient.class);
underTest.setStatistics("project-long-name", stats);
- assertThat(underTest.getFieldValue(SEVERITY + ".INFO.count")).isEqualTo("5");
- assertThat(underTest.getFieldValue(SEVERITY + ".BLOCKER.count")).isEqualTo("3");
+ assertThat(underTest.getFieldValue(RULE_TYPE + ".BUG.count")).isEqualTo("5");
+ assertThat(underTest.getFieldValue(RULE_TYPE + ".CODE_SMELL.count")).isEqualTo("3");
assertThat(underTest.getFieldValue(ASSIGNEE + ".1.label")).isEqualTo("maynard");
assertThat(underTest.getFieldValue(ASSIGNEE + ".1.count")).isEqualTo("5");
assertThat(underTest.getFieldValue(ASSIGNEE + ".2.label")).isEqualTo("keenan");
@Test
public void add_only_5_assignees_with_biggest_issue_counts() {
- Random random = new Random();
String[] assignees = IntStream.range(0, 6 + random.nextInt(10)).mapToObj(s -> "assignee" + s).toArray(String[]::new);
NewIssuesStatistics.Stats stats = new NewIssuesStatistics.Stats(i -> true);
int i = assignees.length;
for (String assignee : assignees) {
- IntStream.range(0, i).mapToObj(j -> new DefaultIssue().setAssignee(assignee)).forEach(stats::add);
+ IntStream.range(0, i).mapToObj(j -> new DefaultIssue().setType(randomRuleType).setAssignee(assignee)).forEach(stats::add);
i--;
}
@Test
public void add_only_5_components_with_biggest_issue_counts() {
- Random random = new Random();
String[] componentUuids = IntStream.range(0, 6 + random.nextInt(10)).mapToObj(s -> "component_uuid_" + s).toArray(String[]::new);
NewIssuesStatistics.Stats stats = new NewIssuesStatistics.Stats(i -> true);
int i = componentUuids.length;
for (String component : componentUuids) {
- IntStream.range(0, i).mapToObj(j -> new DefaultIssue().setComponentUuid(component)).forEach(stats::add);
+ IntStream.range(0, i).mapToObj(j -> new DefaultIssue().setType(randomRuleType).setComponentUuid(component)).forEach(stats::add);
i--;
}
when(componentDao.selectByUuids(dbSession, Arrays.stream(componentUuids).limit(5).collect(Collectors.toSet())))
@Test
public void add_only_5_rules_with_biggest_issue_counts() {
- Random random = new Random();
String repository = randomAlphanumeric(4);
String[] ruleKeys = IntStream.range(0, 6 + random.nextInt(10)).mapToObj(s -> "rule_" + s).toArray(String[]::new);
NewIssuesStatistics.Stats stats = new NewIssuesStatistics.Stats(i -> true);
int i = ruleKeys.length;
for (String ruleKey : ruleKeys) {
- IntStream.range(0, i).mapToObj(j -> new DefaultIssue().setRuleKey(RuleKey.of(repository, ruleKey))).forEach(stats::add);
+ IntStream.range(0, i).mapToObj(j -> new DefaultIssue().setType(randomRuleType).setRuleKey(RuleKey.of(repository, ruleKey))).forEach(stats::add);
i--;
}
when(ruleDao.selectDefinitionByKeys(dbSession, Arrays.stream(ruleKeys).limit(5).map(s -> RuleKey.of(repository, s)).collect(MoreCollectors.toSet(5))))
return new DefaultIssue()
.setAssignee("maynard")
.setComponentUuid("file-uuid")
- .setSeverity(Severity.INFO)
+ .setType(RuleType.BUG)
.setTags(Lists.newArrayList("bug", "owasp"))
.setRuleKey(RuleKey.of("SonarQube", "rule-the-world"))
.setEffort(Duration.create(5L));
return new DefaultIssue()
.setAssignee("keenan")
.setComponentUuid("directory-uuid")
- .setSeverity(Severity.BLOCKER)
+ .setType(RuleType.CODE_SMELL)
.setTags(Lists.newArrayList("owasp"))
.setRuleKey(RuleKey.of("SonarQube", "rule-the-universe"))
.setEffort(Duration.create(10L));
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import javax.annotation.CheckForNull;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.sonar.api.issue.Issue;
import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rule.Severity;
+import org.sonar.api.rules.RuleType;
import org.sonar.api.utils.Duration;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.server.issue.notification.NewIssuesStatistics.Metric;
import static org.assertj.core.api.Assertions.assertThat;
public class NewIssuesStatisticsTest {
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
- NewIssuesStatistics underTest = new NewIssuesStatistics(Issue::isNew);
+ private final Random random = new Random();
+ private RuleType randomRuleType = RuleType.values()[random.nextInt(RuleType.values().length)];
+ private NewIssuesStatistics underTest = new NewIssuesStatistics(Issue::isNew);
+
+ @Test
+ public void add_fails_with_NPE_if_RuleType_is_null() {
+ String assignee = randomAlphanumeric(10);
+ DefaultIssue issue = new DefaultIssue().setType(null).setAssignee(assignee).setNew(new Random().nextBoolean());
+
+ expectedException.expect(NullPointerException.class);
+
+ underTest.add(issue);
+ }
@Test
public void add_issues_with_correct_global_statistics() {
.setAssignee("maynard")
.setComponentUuid("file-uuid")
.setNew(true)
- .setSeverity(Severity.INFO)
+ .setType(RuleType.BUG)
.setRuleKey(RuleKey.of("SonarQube", "rule-the-world"))
.setTags(Lists.newArrayList("bug", "owasp"))
.setEffort(Duration.create(5L));
assertThat(countDistributionTotal(Metric.ASSIGNEE, "wrong.login")).isNull();
assertThat(countDistributionTotal(Metric.COMPONENT, "file-uuid")).isEqualTo(3);
assertThat(countDistributionTotal(Metric.COMPONENT, "wrong-uuid")).isNull();
- assertThat(countDistributionTotal(Metric.SEVERITY, Severity.INFO)).isEqualTo(3);
- assertThat(countDistributionTotal(Metric.SEVERITY, Severity.CRITICAL)).isNull();
+ assertThat(countDistributionTotal(Metric.RULE_TYPE, RuleType.BUG.name())).isEqualTo(3);
+ assertThat(countDistributionTotal(Metric.RULE_TYPE, RuleType.CODE_SMELL.name())).isNull();
assertThat(countDistributionTotal(Metric.TAG, "owasp")).isEqualTo(3);
assertThat(countDistributionTotal(Metric.TAG, "wrong-tag")).isNull();
assertThat(countDistributionTotal(Metric.RULE, "SonarQube:rule-the-world")).isEqualTo(3);
}
@Test
- public void add_counts_issue_per_severity_on_leak_globally_and_per_assignee() {
+ public void add_counts_issue_per_RuleType_on_leak_globally_and_per_assignee() {
String assignee = randomAlphanumeric(10);
- Severity.ALL.stream()
- .map(severity -> new DefaultIssue().setSeverity(severity).setAssignee(assignee).setNew(true))
+ Arrays.stream(RuleType.values())
+ .map(ruleType -> new DefaultIssue().setType(ruleType).setAssignee(assignee).setNew(true))
.forEach(underTest::add);
- DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.SEVERITY);
- DistributedMetricStatsInt assigneeDistribution = underTest.getAssigneesStatistics().get(assignee).getDistributedMetricStats(Metric.SEVERITY);
+ DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.RULE_TYPE);
+ DistributedMetricStatsInt assigneeDistribution = underTest.getAssigneesStatistics().get(assignee).getDistributedMetricStats(Metric.RULE_TYPE);
Stream.of(globalDistribution, assigneeDistribution)
- .forEach(distribution -> {
- assertStats(distribution, Severity.INFO, 1, 0, 1);
- assertStats(distribution, Severity.MAJOR, 1, 0, 1);
- assertStats(distribution, Severity.CRITICAL, 1, 0, 1);
- assertStats(distribution, Severity.MINOR, 1, 0, 1);
- assertStats(distribution, Severity.BLOCKER, 1, 0, 1);
- });
+ .forEach(distribution -> Arrays.stream(RuleType.values()).forEach(ruleType -> assertStats(distribution, ruleType.name(), 1, 0, 1)));
}
@Test
- public void add_counts_issue_per_severity_off_leak_globally_and_per_assignee() {
+ public void add_counts_issue_per_RuleType_off_leak_globally_and_per_assignee() {
String assignee = randomAlphanumeric(10);
- Severity.ALL.stream()
- .map(severity -> new DefaultIssue().setSeverity(severity).setAssignee(assignee).setNew(false))
+ Arrays.stream(RuleType.values())
+ .map(ruleType -> new DefaultIssue().setType(ruleType).setAssignee(assignee).setNew(false))
.forEach(underTest::add);
- DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.SEVERITY);
- DistributedMetricStatsInt assigneeDistribution = underTest.getAssigneesStatistics().get(assignee).getDistributedMetricStats(Metric.SEVERITY);
+ DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.RULE_TYPE);
+ DistributedMetricStatsInt assigneeDistribution = underTest.getAssigneesStatistics().get(assignee).getDistributedMetricStats(Metric.RULE_TYPE);
Stream.of(globalDistribution, assigneeDistribution)
- .forEach(distribution -> {
- assertStats(distribution, Severity.INFO, 0, 1, 1);
- assertStats(distribution, Severity.MAJOR, 0, 1, 1);
- assertStats(distribution, Severity.CRITICAL, 0, 1, 1);
- assertStats(distribution, Severity.MINOR, 0, 1, 1);
- assertStats(distribution, Severity.BLOCKER, 0, 1, 1);
- });
- }
-
- @Test
- public void add_counts_severity_if_null_globally_and_per_assignee_as_it_should_not_be_null() {
- String assignee = randomAlphanumeric(10);
- underTest.add(new DefaultIssue().setSeverity(null).setAssignee(assignee).setNew(new Random().nextBoolean()));
-
- DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.SEVERITY);
- DistributedMetricStatsInt assigneeDistribution = underTest.getAssigneesStatistics().get(assignee).getDistributedMetricStats(Metric.SEVERITY);
- Stream.of(globalDistribution, assigneeDistribution)
- .forEach(distribution -> {
- assertThat(distribution.getTotal()).isEqualTo(1);
- assertThat(distribution.getForLabel(null).isPresent()).isTrue();
- });
+ .forEach(distribution -> Arrays.stream(RuleType.values()).forEach(ruleType -> assertStats(distribution, ruleType.name(), 0, 1, 1)));
}
@Test
List<String> componentUuids = IntStream.range(0, 1 + new Random().nextInt(10)).mapToObj(i -> randomAlphabetic(3)).collect(Collectors.toList());
String assignee = randomAlphanumeric(10);
componentUuids.stream()
- .map(componentUuid -> new DefaultIssue().setComponentUuid(componentUuid).setAssignee(assignee).setNew(true))
+ .map(componentUuid -> new DefaultIssue().setType(randomRuleType).setComponentUuid(componentUuid).setAssignee(assignee).setNew(true))
.forEach(underTest::add);
DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.COMPONENT);
List<String> componentUuids = IntStream.range(0, 1 + new Random().nextInt(10)).mapToObj(i -> randomAlphabetic(3)).collect(Collectors.toList());
String assignee = randomAlphanumeric(10);
componentUuids.stream()
- .map(componentUuid -> new DefaultIssue().setComponentUuid(componentUuid).setAssignee(assignee).setNew(false))
+ .map(componentUuid -> new DefaultIssue().setType(randomRuleType).setComponentUuid(componentUuid).setAssignee(assignee).setNew(false))
.forEach(underTest::add);
DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.COMPONENT);
@Test
public void add_does_not_count_component_if_null_neither_globally_nor_per_assignee() {
String assignee = randomAlphanumeric(10);
- underTest.add(new DefaultIssue().setComponentUuid(null).setAssignee(assignee).setNew(new Random().nextBoolean()));
+ underTest.add(new DefaultIssue().setType(randomRuleType).setComponentUuid(null).setAssignee(assignee).setNew(new Random().nextBoolean()));
DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.COMPONENT);
DistributedMetricStatsInt assigneeDistribution = underTest.getAssigneesStatistics().get(assignee).getDistributedMetricStats(Metric.COMPONENT);
List<String> ruleKeys = IntStream.range(0, 1 + new Random().nextInt(10)).mapToObj(i -> randomAlphabetic(3)).collect(Collectors.toList());
String assignee = randomAlphanumeric(10);
ruleKeys.stream()
- .map(ruleKey -> new DefaultIssue().setRuleKey(RuleKey.of(repository, ruleKey)).setAssignee(assignee).setNew(true))
+ .map(ruleKey -> new DefaultIssue().setType(randomRuleType).setRuleKey(RuleKey.of(repository, ruleKey)).setAssignee(assignee).setNew(true))
.forEach(underTest::add);
DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.RULE);
List<String> ruleKeys = IntStream.range(0, 1 + new Random().nextInt(10)).mapToObj(i -> randomAlphabetic(3)).collect(Collectors.toList());
String assignee = randomAlphanumeric(10);
ruleKeys.stream()
- .map(ruleKey -> new DefaultIssue().setRuleKey(RuleKey.of(repository, ruleKey)).setAssignee(assignee).setNew(false))
+ .map(ruleKey -> new DefaultIssue().setType(randomRuleType).setRuleKey(RuleKey.of(repository, ruleKey)).setAssignee(assignee).setNew(false))
.forEach(underTest::add);
DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.RULE);
@Test
public void add_does_not_count_ruleKey_if_null_neither_globally_nor_per_assignee() {
String assignee = randomAlphanumeric(10);
- underTest.add(new DefaultIssue().setRuleKey(null).setAssignee(assignee).setNew(new Random().nextBoolean()));
+ underTest.add(new DefaultIssue().setType(randomRuleType).setRuleKey(null).setAssignee(assignee).setNew(new Random().nextBoolean()));
DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.RULE);
DistributedMetricStatsInt assigneeDistribution = underTest.getAssigneesStatistics().get(assignee).getDistributedMetricStats(Metric.RULE);
public void add_counts_issue_per_assignee_on_leak_globally_and_per_assignee() {
List<String> assignees = IntStream.range(0, 1 + new Random().nextInt(10)).mapToObj(i -> randomAlphabetic(3)).collect(Collectors.toList());
assignees.stream()
- .map(assignee -> new DefaultIssue().setAssignee(assignee).setNew(true))
+ .map(assignee -> new DefaultIssue().setType(randomRuleType).setAssignee(assignee).setNew(true))
.forEach(underTest::add);
DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.ASSIGNEE);
public void add_counts_issue_per_assignee_off_leak_globally_and_per_assignee() {
List<String> assignees = IntStream.range(0, 1 + new Random().nextInt(10)).mapToObj(i -> randomAlphabetic(3)).collect(Collectors.toList());
assignees.stream()
- .map(assignee -> new DefaultIssue().setAssignee(assignee).setNew(false))
+ .map(assignee -> new DefaultIssue().setType(randomRuleType).setAssignee(assignee).setNew(false))
.forEach(underTest::add);
DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.ASSIGNEE);
@Test
public void add_does_not_assignee_if_empty_neither_globally_nor_per_assignee() {
- underTest.add(new DefaultIssue().setAssignee(null).setNew(new Random().nextBoolean()));
+ underTest.add(new DefaultIssue().setType(randomRuleType).setAssignee(null).setNew(new Random().nextBoolean()));
DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.ASSIGNEE);
assertThat(globalDistribution.getTotal()).isEqualTo(0);
public void add_counts_issue_per_tags_on_leak_globally_and_per_assignee() {
List<String> tags = IntStream.range(0, 1 + new Random().nextInt(10)).mapToObj(i -> randomAlphabetic(3)).collect(Collectors.toList());
String assignee = randomAlphanumeric(10);
- underTest.add(new DefaultIssue().setTags(tags).setAssignee(assignee).setNew(true));
+ underTest.add(new DefaultIssue().setType(randomRuleType).setTags(tags).setAssignee(assignee).setNew(true));
DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.TAG);
DistributedMetricStatsInt assigneeDistribution = underTest.getAssigneesStatistics().get(assignee).getDistributedMetricStats(Metric.TAG);
public void add_counts_issue_per_tags_off_leak_globally_and_per_assignee() {
List<String> tags = IntStream.range(0, 1 + new Random().nextInt(10)).mapToObj(i -> randomAlphabetic(3)).collect(Collectors.toList());
String assignee = randomAlphanumeric(10);
- underTest.add(new DefaultIssue().setTags(tags).setAssignee(assignee).setNew(false));
+ underTest.add(new DefaultIssue().setType(randomRuleType).setTags(tags).setAssignee(assignee).setNew(false));
DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.TAG);
DistributedMetricStatsInt assigneeDistribution = underTest.getAssigneesStatistics().get(assignee).getDistributedMetricStats(Metric.TAG);
@Test
public void add_does_not_count_tags_if_empty_neither_globally_nor_per_assignee() {
String assignee = randomAlphanumeric(10);
- underTest.add(new DefaultIssue().setTags(Collections.emptyList()).setAssignee(assignee).setNew(new Random().nextBoolean()));
+ underTest.add(new DefaultIssue().setType(randomRuleType).setTags(Collections.emptyList()).setAssignee(assignee).setNew(new Random().nextBoolean()));
DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.TAG);
DistributedMetricStatsInt assigneeDistribution = underTest.getAssigneesStatistics().get(assignee).getDistributedMetricStats(Metric.TAG);
int expected = efforts.stream().mapToInt(s -> s).sum();
String assignee = randomAlphanumeric(10);
efforts.stream()
- .map(effort -> new DefaultIssue().setEffort(Duration.create(effort)).setAssignee(assignee).setNew(true))
+ .map(effort -> new DefaultIssue().setType(randomRuleType).setEffort(Duration.create(effort)).setAssignee(assignee).setNew(true))
.forEach(underTest::add);
MetricStatsLong globalDistribution = underTest.globalStatistics().effort();
int expected = efforts.stream().mapToInt(s -> s).sum();
String assignee = randomAlphanumeric(10);
efforts.stream()
- .map(effort -> new DefaultIssue().setEffort(Duration.create(effort)).setAssignee(assignee).setNew(false))
+ .map(effort -> new DefaultIssue().setType(randomRuleType).setEffort(Duration.create(effort)).setAssignee(assignee).setNew(false))
.forEach(underTest::add);
MetricStatsLong globalDistribution = underTest.globalStatistics().effort();
@Test
public void add_does_not_sum_effort_if_null_neither_globally_nor_per_assignee() {
String assignee = randomAlphanumeric(10);
- underTest.add(new DefaultIssue().setEffort(null).setAssignee(assignee).setNew(new Random().nextBoolean()));
+ underTest.add(new DefaultIssue().setType(randomRuleType).setEffort(null).setAssignee(assignee).setNew(new Random().nextBoolean()));
MetricStatsLong globalDistribution = underTest.globalStatistics().effort();
MetricStatsLong assigneeDistribution = underTest.getAssigneesStatistics().get(assignee).effort();
.forEach(distribution -> assertThat(distribution.getTotal()).isEqualTo(0));
}
- @Test
- public void add_counts_issue_per_severity_per_assignee() {
- String assignee = randomAlphanumeric(20);
- Severity.ALL.stream().map(severity -> new DefaultIssue()
- .setSeverity(severity)
- .setAssignee(assignee)).forEach(underTest::add);
-
- assertThat(underTest.globalStatistics()
- .getDistributedMetricStats(Metric.SEVERITY)
- .getForLabel(Severity.INFO)
- .map(MetricStatsInt::getTotal)
- .orElse(null)).isEqualTo(1);
- assertThat(countDistributionTotal(Metric.SEVERITY, Severity.MINOR)).isEqualTo(1);
- assertThat(countDistributionTotal(Metric.SEVERITY, Severity.CRITICAL)).isEqualTo(1);
- assertThat(countDistributionTotal(Metric.SEVERITY, Severity.BLOCKER)).isEqualTo(1);
- assertThat(countDistributionTotal(Metric.SEVERITY, Severity.MAJOR)).isEqualTo(1);
- }
-
@Test
public void do_not_have_issues_when_no_issue_added() {
assertThat(underTest.globalStatistics().hasIssues()).isFalse();
int effort = 10 + new Random().nextInt(5);
RuleKey ruleKey = RuleKey.of(randomAlphanumeric(5), randomAlphanumeric(6));
underTest.add(new DefaultIssue()
- .setSeverity(Severity.BLOCKER)
+ .setType(randomRuleType)
.setComponentUuid(componentUuid)
.setTags(ImmutableSet.of(tag))
.setAssignee(assignee)
.isEqualTo("NewIssuesStatistics{" +
"assigneesStatistics={" + assignee + "=" +
"Stats{distributions={" +
- "SEVERITY=DistributedMetricStatsInt{globalStats=MetricStatsInt{onLeak=1, offLeak=0}, " +
- "statsPerLabel={" + Severity.BLOCKER + "=MetricStatsInt{onLeak=1, offLeak=0}}}, " +
+ "RULE_TYPE=DistributedMetricStatsInt{globalStats=MetricStatsInt{onLeak=1, offLeak=0}, " +
+ "statsPerLabel={" + randomRuleType.name() + "=MetricStatsInt{onLeak=1, offLeak=0}}}, " +
"TAG=DistributedMetricStatsInt{globalStats=MetricStatsInt{onLeak=1, offLeak=0}, " +
"statsPerLabel={" + tag + "=MetricStatsInt{onLeak=1, offLeak=0}}}, " +
"COMPONENT=DistributedMetricStatsInt{globalStats=MetricStatsInt{onLeak=1, offLeak=0}, " +
"statsPerLabel={" + ruleKey.toString() + "=MetricStatsInt{onLeak=1, offLeak=0}}}}, " +
"effortStats=MetricStatsLong{onLeak=" + effort + ", offLeak=0}}}, " +
"globalStatistics=Stats{distributions={" +
- "SEVERITY=DistributedMetricStatsInt{globalStats=MetricStatsInt{onLeak=1, offLeak=0}, " +
- "statsPerLabel={" + Severity.BLOCKER + "=MetricStatsInt{onLeak=1, offLeak=0}}}, " +
+ "RULE_TYPE=DistributedMetricStatsInt{globalStats=MetricStatsInt{onLeak=1, offLeak=0}, " +
+ "statsPerLabel={" + randomRuleType.name() + "=MetricStatsInt{onLeak=1, offLeak=0}}}, " +
"TAG=DistributedMetricStatsInt{globalStats=MetricStatsInt{onLeak=1, offLeak=0}, " +
"statsPerLabel={" + tag + "=MetricStatsInt{onLeak=1, offLeak=0}}}, " +
"COMPONENT=DistributedMetricStatsInt{globalStats=MetricStatsInt{onLeak=1, offLeak=0}, " +
+++ /dev/null
-Project: Struts
-
-32 new issues (new debt: 1d3h)
-
- 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
-
- Most impacted files
- /path/to/file: 3
- /path/to/directory: 7
-
-See it in SonarQube: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&assignees=lo.gin&createdAt=2010-05-18
+++ /dev/null
-Project: Struts
-
-32 new issues (new debt: 1d3h)
-
- Severity
- Blocker: 0 Critical: 5 Major: 10 Minor: 3 Info: 1
-
-See it in SonarQube: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&assignees=lo.gin&branch=feature1&createdAt=2010-05-18
+++ /dev/null
-Project: Struts
-
-32 new issues (new debt: 1d3h)
-
- Severity
- Blocker: 0 Critical: 5 Major: 10 Minor: 3 Info: 1
-
-See it in SonarQube: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&assignees=lo.gin&createdAt=2010-05-18
+++ /dev/null
-Project: Struts
-
-32 new issues (new debt: 1d3h)
-
- Severity
- Blocker: 0 Critical: 5 Major: 10 Minor: 3 Info: 1
-
- Assignees
- robin.williams: 5
- al.pacino: 7
-
- Rules
- Rule the Universe (Clojure): 42
- Rule the World (Java): 5
-
- Tags
- oscar: 3
- cesar: 10
-
- Most impacted files
- /path/to/file: 3
- /path/to/directory: 7
-
-See it in SonarQube: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&createdAt=2010-05-1
\ No newline at end of file
+++ /dev/null
-Project: Struts
-
-32 new issues (new debt: 1d3h)
-
- Severity
- Blocker: 0 Critical: 5 Major: 10 Minor: 3 Info: 1
-
-See it in SonarQube: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&branch=feature1&createdAt=2010-05-1
+++ /dev/null
-Project: Struts
-
-32 new issues (new debt: 1d3h)
-
- Severity
- Blocker: 0 Critical: 5 Major: 10 Minor: 3 Info: 1
-
-See it in SonarQube: http://nemo.sonarsource.org/project/issues?id=org.apache%3Astruts&createdAt=2010-05-1
\ No newline at end of file
assertThat(message.getHeader("To", null)).isEqualTo("<tester@example.org>");
assertThat((String) message.getContent()).contains("Sample");
assertThat((String) message.getContent()).contains("17 new issues (new debt: 17min)");
- assertThat((String) message.getContent()).contains("Severity");
+ assertThat((String) message.getContent()).contains("Type");
assertThat((String) message.getContent()).contains("One Issue Per Line (xoo): 17");
assertThat((String) message.getContent()).contains(
"See it in SonarQube: http://localhost:9000/project/issues?id=sample&createdAt=2015-12-15T00%3A00%3A00%2B");