From fa500518ce3e43b2b4e5f42cee21a3946c119978 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Wed, 20 Mar 2013 18:36:17 +0100 Subject: [PATCH] SONAR-4163 Add "New false positive issue" notification --- .../org/sonar/plugins/core/CorePlugin.java | 9 +- .../reviews/NewFalsePositiveReview.java | 70 ++++++++++ .../resources/org/sonar/l10n/core.properties | 1 + .../notifications/alerts/NewAlertsTest.java | 4 +- ...InReviewAssignedToMeOrCreatedByMeTest.java | 12 +- .../reviews/NewFalsePositiveReviewTest.java | 120 ++++++++++++++++++ 6 files changed, 206 insertions(+), 10 deletions(-) create mode 100644 plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/notifications/reviews/NewFalsePositiveReview.java create mode 100644 plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/notifications/reviews/NewFalsePositiveReviewTest.java diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java index 2af797f7ff8..d12b2d7adde 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java @@ -44,6 +44,7 @@ import org.sonar.plugins.core.measurefilters.MyFavouritesFilter; import org.sonar.plugins.core.measurefilters.ProjectFilter; import org.sonar.plugins.core.notifications.alerts.NewAlerts; import org.sonar.plugins.core.notifications.reviews.ChangesInReviewAssignedToMeOrCreatedByMe; +import org.sonar.plugins.core.notifications.reviews.NewFalsePositiveReview; import org.sonar.plugins.core.notifications.violations.NewViolationsOnFirstDifferentialPeriod; import org.sonar.plugins.core.security.ApplyProjectRolesDecorator; import org.sonar.plugins.core.sensors.BranchCoverageDecorator; @@ -525,6 +526,12 @@ public final class CorePlugin extends SonarPlugin { ChangesInReviewAssignedToMeOrCreatedByMe.class, NotificationDispatcherMetadata.create("ChangesInReviewAssignedToMeOrCreatedByMe") .setProperty(NotificationDispatcherMetadata.GLOBAL_NOTIFICATION, String.valueOf(true)) - .setProperty(NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION, String.valueOf(true))); + .setProperty(NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION, String.valueOf(true)), + // Notify new false positive resolution + NewFalsePositiveReview.class, + NotificationDispatcherMetadata.create("NewFalsePositiveReview") + .setProperty(NotificationDispatcherMetadata.GLOBAL_NOTIFICATION, String.valueOf(true)) + .setProperty(NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION, String.valueOf(true)) + ); } } diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/notifications/reviews/NewFalsePositiveReview.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/notifications/reviews/NewFalsePositiveReview.java new file mode 100644 index 00000000000..9c7b60f6a83 --- /dev/null +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/notifications/reviews/NewFalsePositiveReview.java @@ -0,0 +1,70 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ + +package org.sonar.plugins.core.notifications.reviews; + +import com.google.common.collect.Multimap; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.notifications.Notification; +import org.sonar.api.notifications.NotificationChannel; +import org.sonar.api.notifications.NotificationDispatcher; +import org.sonar.api.notifications.NotificationManager; +import org.sonar.core.review.ReviewDto; + +import java.util.Collection; +import java.util.Map; + +/** + * This dispatcher means: "notify me when someone resolve a review as false positive". + * + * @since 3.6 + */ +public class NewFalsePositiveReview extends NotificationDispatcher { + + private NotificationManager notificationManager; + + public NewFalsePositiveReview(NotificationManager notificationManager) { + super("review-changed"); + this.notificationManager = notificationManager; + } + + @Override + public void dispatch(Notification notification, Context context) { + String newResolution = notification.getFieldValue("new.resolution"); + if (StringUtils.equals(newResolution, ReviewDto.RESOLUTION_FALSE_POSITIVE)) { + String author = notification.getFieldValue("author"); + int projectId = Integer.parseInt(notification.getFieldValue("projectId")); + Multimap subscribedRecipients = notificationManager.findSubscribedRecipientsForDispatcher(this, projectId); + notify(author, context, subscribedRecipients); + } + } + + private void notify(String author, Context context, Multimap subscribedRecipients) { + for (Map.Entry> channelsByRecipients : subscribedRecipients.asMap().entrySet()) { + String userLogin = channelsByRecipients.getKey(); + if (!StringUtils.equals(author, userLogin)) { + for (NotificationChannel channel : channelsByRecipients.getValue()) { + context.addUser(userLogin, channel); + } + } + } + } + +} diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties b/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties index 5738fb5dce2..91093364a3f 100644 --- a/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties +++ b/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties @@ -1537,6 +1537,7 @@ notification.channel.EmailNotificationChannel=Email notification.dispatcher.ChangesInReviewAssignedToMeOrCreatedByMe=Changes in reviews assigned to me or created by me notification.dispatcher.NewViolationsOnFirstDifferentialPeriod=New violations introduced during the first differential period notification.dispatcher.NewAlerts=New alerts +notification.dispatcher.NewFalsePositiveReview=New false positive issue #------------------------------------------------------------------------------ diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/notifications/alerts/NewAlertsTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/notifications/alerts/NewAlertsTest.java index c0d124e35c5..4279f9350d3 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/notifications/alerts/NewAlertsTest.java +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/notifications/alerts/NewAlertsTest.java @@ -59,7 +59,7 @@ public class NewAlertsTest { } @Test - public void shouldNotDispatchIfNotAlertsNotification() throws Exception { + public void should_not_dispatch_if_not_alerts_notification() throws Exception { Notification notification = new Notification("other-notif"); dispatcher.performDispatch(notification, context); @@ -67,7 +67,7 @@ public class NewAlertsTest { } @Test - public void shouldDispatchToUsersWhoHaveSubscribedAndFlaggedProjectAsFavourite() { + public void should_dispatch_to_users_who_have_subscribed() { Multimap recipients = HashMultimap.create(); recipients.put("user1", emailChannel); recipients.put("user2", twitterChannel); diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/notifications/reviews/ChangesInReviewAssignedToMeOrCreatedByMeTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/notifications/reviews/ChangesInReviewAssignedToMeOrCreatedByMeTest.java index 4840c7e0fe0..fcec42573c7 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/notifications/reviews/ChangesInReviewAssignedToMeOrCreatedByMeTest.java +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/notifications/reviews/ChangesInReviewAssignedToMeOrCreatedByMeTest.java @@ -19,8 +19,6 @@ */ package org.sonar.plugins.core.notifications.reviews; -import org.sonar.plugins.core.notifications.reviews.ChangesInReviewAssignedToMeOrCreatedByMe; - import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import org.junit.Before; @@ -55,14 +53,14 @@ public class ChangesInReviewAssignedToMeOrCreatedByMeTest { private ChangesInReviewAssignedToMeOrCreatedByMe dispatcher; @Before - public void setUp() { + public void before() { MockitoAnnotations.initMocks(this); dispatcher = new ChangesInReviewAssignedToMeOrCreatedByMe(notificationManager); } @Test - public void shouldNotDispatchIfNotNewViolationsNotification() throws Exception { + public void should_not_dispatch_if_not_new_violations_notification() throws Exception { Notification notification = new Notification("other-notif"); dispatcher.performDispatch(notification, context); @@ -70,7 +68,7 @@ public class ChangesInReviewAssignedToMeOrCreatedByMeTest { } @Test - public void dispatchToCreatorAndAssignee() { + public void should_dispatch_to_creator_and_assignee() { Multimap recipients = HashMultimap.create(); recipients.put("simon", emailChannel); recipients.put("freddy", twitterChannel); @@ -92,7 +90,7 @@ public class ChangesInReviewAssignedToMeOrCreatedByMeTest { } @Test - public void doNotDispatchToAuthorOfChanges() { + public void should_not_dispatch_to_author_of_changes() { Multimap recipients = HashMultimap.create(); recipients.put("simon", emailChannel); recipients.put("freddy", twitterChannel); @@ -110,7 +108,7 @@ public class ChangesInReviewAssignedToMeOrCreatedByMeTest { } @Test - public void shouldNotDispatch() { + public void should_not_dispatch_when_other_notification_type() { Notification notification = new Notification("other"); dispatcher.performDispatch(notification, context); diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/notifications/reviews/NewFalsePositiveReviewTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/notifications/reviews/NewFalsePositiveReviewTest.java new file mode 100644 index 00000000000..5c8e5414fcb --- /dev/null +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/notifications/reviews/NewFalsePositiveReviewTest.java @@ -0,0 +1,120 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ + +package org.sonar.plugins.core.notifications.reviews; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.sonar.api.notifications.Notification; +import org.sonar.api.notifications.NotificationChannel; +import org.sonar.api.notifications.NotificationDispatcher; +import org.sonar.api.notifications.NotificationManager; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +public class NewFalsePositiveReviewTest { + + @Mock + private NotificationManager notificationManager; + + @Mock + private NotificationDispatcher.Context context; + + @Mock + private NotificationChannel emailChannel; + + @Mock + private NotificationChannel twitterChannel; + + private NotificationDispatcher dispatcher; + + @Before + public void before() { + MockitoAnnotations.initMocks(this); + + dispatcher = new NewFalsePositiveReview(notificationManager); + } + + @Test + public void should_not_dispatch_if_not_reviews_notification() throws Exception { + Notification notification = new Notification("other-notif"); + dispatcher.performDispatch(notification, context); + + verify(context, never()).addUser(any(String.class), any(NotificationChannel.class)); + } + + @Test + public void should_dispatch_false_positive_resolution_to_every_subscribers() { + Multimap recipients = HashMultimap.create(); + recipients.put("user1", emailChannel); + recipients.put("user2", twitterChannel); + when(notificationManager.findSubscribedRecipientsForDispatcher(dispatcher, 42)).thenReturn(recipients); + + dispatcher.performDispatch(new Notification("review-changed") + .setFieldValue("projectId", "42") + .setFieldValue("author", "user3") + .setFieldValue("new.resolution", "FALSE-POSITIVE"), + context); + + verify(context).addUser("user1", emailChannel); + verify(context).addUser("user2", twitterChannel); + verifyNoMoreInteractions(context); + } + + @Test + public void should_not_dispatch_to_author_of_changes() { + Multimap recipients = HashMultimap.create(); + recipients.put("user1", emailChannel); + recipients.put("user2", twitterChannel); + when(notificationManager.findSubscribedRecipientsForDispatcher(dispatcher, 42)).thenReturn(recipients); + + dispatcher.performDispatch(new Notification("review-changed") + .setFieldValue("projectId", "42") + .setFieldValue("author", "user1") + .setFieldValue("new.resolution", "FALSE-POSITIVE"), + context); + + verify(context).addUser("user2", twitterChannel); + verify(context, never()).addUser("user1", emailChannel); + verifyNoMoreInteractions(context); + } + + @Test + public void should_not_dispatch_other_than_false_positive_resolution() { + Multimap recipients = HashMultimap.create(); + recipients.put("user", emailChannel); + when(notificationManager.findSubscribedRecipientsForDispatcher(dispatcher, 42)).thenReturn(recipients); + + dispatcher.performDispatch(new Notification("review-changed") + .setFieldValue("projectId", "42") + .setFieldValue("author", "user2") + .setFieldValue("new.assignee", "user"), context); + + verify(context, never()).addUser(any(String.class), any(NotificationChannel.class)); + } +} -- 2.39.5