@Test 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().setType(randomRuleTypeExceptHotspot).setTags(tags).setAssigneeUuid(assignee).setNew(true)); DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.TAG); DistributedMetricStatsInt assigneeDistribution = underTest.getAssigneesStatistics().get(assignee).getDistributedMetricStats(Metric.TAG); Stream.of(globalDistribution, assigneeDistribution) .forEach(distribution -> tags.forEach(tag -> assertStats(distribution, tag, 1, 0, 1))); }
private void doExecute(NotificationStatistics notificationStatistics, Component project) { long analysisDate = analysisMetadataHolder.getAnalysisDate(); Predicate<DefaultIssue> isOnLeakPredicate = i -> i.isNew() && i.creationDate().getTime() >= truncateToSeconds(analysisDate); NewIssuesStatistics newIssuesStats = new NewIssuesStatistics(isOnLeakPredicate); Map<String, UserDto> usersDtoByUuids; try (DbSession dbSession = dbClient.openSession(false)) { Iterable<DefaultIssue> iterable = issueCache::traverse; List<String> assigneeUuids = stream(iterable.spliterator(), false).map(DefaultIssue::assignee).filter(Objects::nonNull).collect(toList()); usersDtoByUuids = dbClient.userDao().selectByUuids(dbSession, assigneeUuids).stream().collect(toMap(UserDto::getUuid, dto -> dto)); } try (CloseableIterator<DefaultIssue> issues = issueCache.traverse()) { processIssues(newIssuesStats, issues, project, usersDtoByUuids, notificationStatistics); } if (newIssuesStats.hasIssuesOnLeak()) { sendNewIssuesNotification(newIssuesStats, project, analysisDate, notificationStatistics); sendMyNewIssuesNotification(newIssuesStats, project, analysisDate, notificationStatistics); } }
@Test public void add_counts_issue_per_component_off_leak_globally_and_per_assignee() { 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().setType(randomRuleTypeExceptHotspot).setComponentUuid(componentUuid).setAssigneeUuid(assignee).setNew(false)) .forEach(underTest::add); DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.COMPONENT); NewIssuesStatistics.Stats stats = underTest.getAssigneesStatistics().get(assignee); DistributedMetricStatsInt assigneeDistribution = stats.getDistributedMetricStats(Metric.COMPONENT); Stream.of(globalDistribution, assigneeDistribution) .forEach(distribution -> componentUuids.forEach(componentUuid -> assertStats(distribution, componentUuid, 0, 1, 1))); }
@Test public void add_issues_with_correct_global_statistics() { DefaultIssue issue = new DefaultIssue() .setAssigneeUuid("maynard") .setComponentUuid("file-uuid") .setNew(true) .setType(RuleType.BUG) .setRuleKey(RuleKey.of("SonarQube", "rule-the-world")) .setTags(Lists.newArrayList("bug", "owasp")) .setEffort(Duration.create(5L)); underTest.add(issue); underTest.add(issue.setAssigneeUuid("james")); underTest.add(issue.setAssigneeUuid("keenan")); assertThat(countDistributionTotal(Metric.ASSIGNEE, "maynard")).isEqualTo(1); assertThat(countDistributionTotal(Metric.ASSIGNEE, "james")).isEqualTo(1); assertThat(countDistributionTotal(Metric.ASSIGNEE, "keenan")).isEqualTo(1); 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.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); assertThat(countDistributionTotal(Metric.RULE, "SonarQube:has-a-fake-rule")).isNull(); assertThat(underTest.globalStatistics().effort().getTotal()).isEqualTo(15L); assertThat(underTest.globalStatistics().hasIssues()).isTrue(); assertThat(underTest.hasIssues()).isTrue(); assertThat(underTest.getAssigneesStatistics().get("maynard").hasIssues()).isTrue(); }
@CheckForNull private Integer countDistributionTotal(Metric metric, String label) { return underTest.globalStatistics() .getDistributedMetricStats(metric) .getForLabel(label) .map(MetricStatsInt::getTotal) .orElse(null); }
private Map<String, UserDto> loadUserDtoByUuid(NewIssuesStatistics statistics) { List<Map.Entry<String, NewIssuesStatistics.Stats>> entriesWithIssuesOnLeak = statistics.getAssigneesStatistics().entrySet() .stream().filter(e -> e.getValue().hasIssuesOnLeak()).collect(toList()); List<String> assigneeUuids = entriesWithIssuesOnLeak.stream().map(Map.Entry::getKey).collect(toList()); try (DbSession dbSession = dbClient.openSession(false)) { return dbClient.userDao().selectByUuids(dbSession, assigneeUuids).stream().collect(toMap(UserDto::getUuid, u -> u)); } }
private void processIssues(NewIssuesStatistics newIssuesStats, CloseableIterator<DefaultIssue> issues, Component project, Map<String, UserDto> usersDtoByUuids, NotificationStatistics notificationStatistics) { while (issues.hasNext()) { DefaultIssue issue = issues.next(); if (issue.type() != RuleType.SECURITY_HOTSPOT) { if (issue.isNew() && issue.resolution() == null) { newIssuesStats.add(issue); } else if (issue.isChanged() && issue.mustSendNotifications()) { sendIssueChangeNotification(issue, project, usersDtoByUuids, notificationStatistics); } } } }
int effort = 10 + new Random().nextInt(5); RuleKey ruleKey = RuleKey.of(randomAlphanumeric(5), randomAlphanumeric(6)); underTest.add(new DefaultIssue() .setType(randomRuleTypeExceptHotspot) .setComponentUuid(componentUuid) .setEffort(Duration.create(effort))); assertThat(underTest.toString()) .isEqualTo("NewIssuesStatistics{" + "assigneesStatistics={" + assignee + "=" +
@Test public void add_counts_issue_per_component_on_leak_globally_and_per_assignee() { 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().setType(randomRuleTypeExceptHotspot).setComponentUuid(componentUuid).setAssigneeUuid(assignee).setNew(true)) .forEach(underTest::add); DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.COMPONENT); DistributedMetricStatsInt assigneeDistribution = underTest.getAssigneesStatistics().get(assignee).getDistributedMetricStats(Metric.COMPONENT); Stream.of(globalDistribution, assigneeDistribution) .forEach(distribution -> componentUuids.forEach(componentUuid -> assertStats(distribution, componentUuid, 1, 0, 1))); }
@Test public void do_not_have_issues_when_no_issue_added() { assertThat(underTest.globalStatistics().hasIssues()).isFalse(); }
private void sendMyNewIssuesNotification(NewIssuesStatistics statistics, Component project, long analysisDate, NotificationStatistics notificationStatistics) { Map<String, UserDto> userDtoByUuid = loadUserDtoByUuid(statistics); statistics.getAssigneesStatistics().entrySet() .stream() .filter(e -> e.getValue().hasIssuesOnLeak()) .forEach(e -> { String assigneeUuid = e.getKey(); NewIssuesStatistics.Stats assigneeStatistics = e.getValue(); MyNewIssuesNotification myNewIssuesNotification = newIssuesNotificationFactory .newMyNewIssuesNotification() .setAssignee(userDtoByUuid.get(assigneeUuid)); myNewIssuesNotification .setProject(project.getKey(), project.getName(), getBranchName(), getPullRequest()) .setProjectVersion(project.getProjectAttributes().getVersion()) .setAnalysisDate(new Date(analysisDate)) .setStatistics(project.getName(), assigneeStatistics) .setDebt(Duration.create(assigneeStatistics.effort().getOnLeak())); notificationStatistics.myNewIssuesDeliveries += service.deliver(myNewIssuesNotification); notificationStatistics.myNewIssues++; }); }
@Test public void add_fails_with_NPE_if_RuleType_is_null() { String assignee = randomAlphanumeric(10); DefaultIssue issue = new DefaultIssue().setType(null).setAssigneeUuid(assignee).setNew(new Random().nextBoolean()); expectedException.expect(NullPointerException.class); underTest.add(issue); }
@Test public void add_does_not_count_ruleKey_if_null_neither_globally_nor_per_assignee() { String assignee = randomAlphanumeric(10); underTest.add(new DefaultIssue().setType(randomRuleTypeExceptHotspot).setRuleKey(null).setAssigneeUuid(assignee).setNew(new Random().nextBoolean())); DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.RULE); DistributedMetricStatsInt assigneeDistribution = underTest.getAssigneesStatistics().get(assignee).getDistributedMetricStats(Metric.RULE); Stream.of(globalDistribution, assigneeDistribution) .forEach(distribution -> { assertThat(distribution.getTotal()).isEqualTo(0); assertThat(distribution.getForLabel(null).isPresent()).isFalse(); }); }
@Test 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().setType(randomRuleTypeExceptHotspot).setAssigneeUuid(assignee).setNew(false)) .forEach(underTest::add); DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.ASSIGNEE); assignees.forEach(assignee -> assertStats(globalDistribution, assignee, 0, 1, 1)); assignees.forEach(assignee -> { NewIssuesStatistics.Stats stats = underTest.getAssigneesStatistics().get(assignee); DistributedMetricStatsInt assigneeStats = stats.getDistributedMetricStats(Metric.ASSIGNEE); assertThat(assigneeStats.getOnLeak()).isEqualTo(0); assertThat(assigneeStats.getTotal()).isEqualTo(1); assignees.forEach(s -> { Optional<MetricStatsInt> forLabelOpts = assigneeStats.getForLabel(s); if (s.equals(assignee)) { assertThat(forLabelOpts.isPresent()).isTrue(); MetricStatsInt forLabel = forLabelOpts.get(); assertThat(forLabel.getOnLeak()).isEqualTo(0); assertThat(forLabel.getTotal()).isEqualTo(1); } else { assertThat(forLabelOpts.isPresent()).isFalse(); } }); }); }
private void sendNewIssuesNotification(NewIssuesStatistics statistics, Component project, long analysisDate, NotificationStatistics notificationStatistics) { NewIssuesStatistics.Stats globalStatistics = statistics.globalStatistics(); NewIssuesNotification notification = newIssuesNotificationFactory .newNewIssuesNotification() .setProject(project.getKey(), project.getName(), getBranchName(), getPullRequest()) .setProjectVersion(project.getProjectAttributes().getVersion()) .setAnalysisDate(new Date(analysisDate)) .setStatistics(project.getName(), globalStatistics) .setDebt(Duration.create(globalStatistics.effort().getOnLeak())); notificationStatistics.newIssuesDeliveries += service.deliver(notification); notificationStatistics.newIssues++; }
private Map<String, UserDto> loadUserDtoByUuid(NewIssuesStatistics statistics) { List<Map.Entry<String, NewIssuesStatistics.Stats>> entriesWithIssuesOnLeak = statistics.getAssigneesStatistics().entrySet() .stream().filter(e -> e.getValue().hasIssuesOnLeak()).collect(toList()); List<String> assigneeUuids = entriesWithIssuesOnLeak.stream().map(Map.Entry::getKey).collect(toList()); try (DbSession dbSession = dbClient.openSession(false)) { return dbClient.userDao().selectByUuids(dbSession, assigneeUuids).stream().collect(toMap(UserDto::getUuid, u -> u)); } }
private void doExecute(Component project) { long analysisDate = analysisMetadataHolder.getAnalysisDate(); Predicate<DefaultIssue> isOnLeakPredicate = i -> i.isNew() && i.creationDate().getTime() >= truncateToSeconds(analysisDate); NewIssuesStatistics newIssuesStats = new NewIssuesStatistics(isOnLeakPredicate); Map<String, UserDto> usersDtoByUuids; try (DbSession dbSession = dbClient.openSession(false)) { Iterable<DefaultIssue> iterable = issueCache::traverse; List<String> assigneeUuids = stream(iterable.spliterator(), false).map(DefaultIssue::assignee).filter(Objects::nonNull).collect(toList()); usersDtoByUuids = dbClient.userDao().selectByUuids(dbSession, assigneeUuids).stream().collect(toMap(UserDto::getUuid, dto -> dto)); } try (CloseableIterator<DefaultIssue> issues = issueCache.traverse()) { processIssues(newIssuesStats, issues, project, usersDtoByUuids); } if (newIssuesStats.hasIssuesOnLeak()) { sendNewIssuesNotification(newIssuesStats, project, analysisDate); sendNewIssuesNotificationToAssignees(newIssuesStats, project, analysisDate); } }
private void processIssues(NewIssuesStatistics newIssuesStats, CloseableIterator<DefaultIssue> issues, Component project, Map<String, UserDto> usersDtoByUuids) { while (issues.hasNext()) { DefaultIssue issue = issues.next(); if (issue.isNew() && issue.resolution() == null) { newIssuesStats.add(issue); } else if (issue.isChanged() && issue.mustSendNotifications()) { sendIssueChangeNotification(issue, project, usersDtoByUuids); } } }
@Test public void add_does_not_assignee_if_empty_neither_globally_nor_per_assignee() { underTest.add(new DefaultIssue().setType(randomRuleTypeExceptHotspot).setAssigneeUuid(null).setNew(new Random().nextBoolean())); DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.ASSIGNEE); assertThat(globalDistribution.getTotal()).isEqualTo(0); assertThat(globalDistribution.getForLabel(null).isPresent()).isFalse(); assertThat(underTest.getAssigneesStatistics()).isEmpty(); }
@Test public void add_counts_issue_per_ruleKey_off_leak_globally_and_per_assignee() { String repository = randomAlphanumeric(3); 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().setType(randomRuleTypeExceptHotspot).setRuleKey(RuleKey.of(repository, ruleKey)).setAssigneeUuid(assignee).setNew(false)) .forEach(underTest::add); DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.RULE); DistributedMetricStatsInt assigneeDistribution = underTest.getAssigneesStatistics().get(assignee).getDistributedMetricStats(Metric.RULE); Stream.of(globalDistribution, assigneeDistribution) .forEach(distribution -> ruleKeys.forEach(ruleKey -> assertStats(distribution, RuleKey.of(repository, ruleKey).toString(), 0, 1, 1))); }