]> source.dussan.org Git - sonarqube.git/blob
824c72a912926eaad9a4e2081a7685f8e3cfcdbb
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2017 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 3 of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20 package org.sonar.server.computation.task.projectanalysis.step;
21
22 import java.util.Date;
23 import org.junit.Before;
24 import org.junit.Rule;
25 import org.junit.Test;
26 import org.junit.rules.TemporaryFolder;
27 import org.mockito.ArgumentCaptor;
28 import org.sonar.api.notifications.Notification;
29 import org.sonar.api.rule.Severity;
30 import org.sonar.api.utils.Duration;
31 import org.sonar.api.utils.System2;
32 import org.sonar.core.issue.DefaultIssue;
33 import org.sonar.db.component.ComponentDto;
34 import org.sonar.db.rule.RuleDefinitionDto;
35 import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
36 import org.sonar.server.computation.task.projectanalysis.analysis.Branch;
37 import org.sonar.server.computation.task.projectanalysis.component.Component;
38 import org.sonar.server.computation.task.projectanalysis.component.Component.Type;
39 import org.sonar.server.computation.task.projectanalysis.component.DefaultBranchImpl;
40 import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
41 import org.sonar.server.computation.task.projectanalysis.issue.IssueCache;
42 import org.sonar.server.computation.task.projectanalysis.issue.RuleRepositoryRule;
43 import org.sonar.server.computation.task.step.ComputationStep;
44 import org.sonar.server.issue.notification.IssueChangeNotification;
45 import org.sonar.server.issue.notification.MyNewIssuesNotification;
46 import org.sonar.server.issue.notification.NewIssuesNotification;
47 import org.sonar.server.issue.notification.NewIssuesNotificationFactory;
48 import org.sonar.server.issue.notification.NewIssuesStatistics;
49 import org.sonar.server.notification.NotificationService;
50
51 import static org.assertj.core.api.Java6Assertions.assertThat;
52 import static org.mockito.Matchers.anyString;
53 import static org.mockito.Matchers.eq;
54 import static org.mockito.Mockito.any;
55 import static org.mockito.Mockito.mock;
56 import static org.mockito.Mockito.never;
57 import static org.mockito.Mockito.times;
58 import static org.mockito.Mockito.verify;
59 import static org.mockito.Mockito.when;
60 import static org.sonar.db.component.ComponentTesting.newBranchDto;
61 import static org.sonar.db.component.ComponentTesting.newFileDto;
62 import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
63 import static org.sonar.db.component.ComponentTesting.newProjectBranch;
64 import static org.sonar.db.issue.IssueTesting.newIssue;
65 import static org.sonar.db.organization.OrganizationTesting.newOrganizationDto;
66 import static org.sonar.db.rule.RuleTesting.newRule;
67 import static org.sonar.server.computation.task.projectanalysis.component.ReportComponent.builder;
68
69 public class SendIssueNotificationsStepTest extends BaseStepTest {
70
71   private static final String BRANCH_NAME = "feature";
72
73   private static final long ANALYSE_DATE = 123L;
74
75   private static final Duration ISSUE_DURATION = Duration.create(100L);
76   private static final String ISSUE_ASSIGNEE = "John";
77
78   private static final Component FILE = builder(Component.Type.FILE, 11).build();
79   private static final Component PROJECT = builder(Type.PROJECT, 1).addChildren(FILE).build();
80
81   @Rule
82   public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule()
83     .setRoot(PROJECT);
84
85   @Rule
86   public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule()
87     .setBranch(new DefaultBranchImpl())
88     .setAnalysisDate(new Date(ANALYSE_DATE));
89
90   @Rule
91   public RuleRepositoryRule ruleRepository = new RuleRepositoryRule();
92
93   @Rule
94   public TemporaryFolder temp = new TemporaryFolder();
95
96   private NotificationService notificationService = mock(NotificationService.class);
97   private NewIssuesNotificationFactory newIssuesNotificationFactory = mock(NewIssuesNotificationFactory.class);
98   private NewIssuesNotification newIssuesNotificationMock = createNewIssuesNotificationMock();
99   private MyNewIssuesNotification myNewIssuesNotificationMock = createMyNewIssuesNotificationMock();
100
101   private IssueCache issueCache;
102   private SendIssueNotificationsStep underTest;
103
104   @Before
105   public void setUp() throws Exception {
106     issueCache = new IssueCache(temp.newFile(), System2.INSTANCE);
107     underTest = new SendIssueNotificationsStep(issueCache, ruleRepository, treeRootHolder, notificationService, analysisMetadataHolder,
108       newIssuesNotificationFactory);
109
110     when(newIssuesNotificationFactory.newNewIssuesNotication()).thenReturn(newIssuesNotificationMock);
111     when(newIssuesNotificationFactory.newMyNewIssuesNotification()).thenReturn(myNewIssuesNotificationMock);
112   }
113
114   @Test
115   public void do_not_send_notifications_if_no_subscribers() {
116     when(notificationService.hasProjectSubscribersForTypes(PROJECT.getUuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(false);
117
118     underTest.execute();
119
120     verify(notificationService, never()).deliver(any(Notification.class));
121   }
122
123   @Test
124   public void send_global_new_issues_notification() throws Exception {
125     issueCache.newAppender().append(
126       new DefaultIssue().setSeverity(Severity.BLOCKER).setEffort(ISSUE_DURATION)).close();
127
128     when(notificationService.hasProjectSubscribersForTypes(PROJECT.getUuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
129
130     underTest.execute();
131
132     verify(notificationService).deliver(any(NewIssuesNotification.class));
133     verify(newIssuesNotificationMock).setProject(PROJECT.getPublicKey(), PROJECT.getUuid(), PROJECT.getName(), null);
134     verify(newIssuesNotificationMock).setAnalysisDate(new Date(ANALYSE_DATE));
135     verify(newIssuesNotificationMock).setStatistics(eq(PROJECT.getName()), any(NewIssuesStatistics.Stats.class));
136     verify(newIssuesNotificationMock).setDebt(ISSUE_DURATION);
137   }
138
139   @Test
140   public void send_global_new_issues_notification_on_branch() throws Exception {
141     ComponentDto project = newPrivateProjectDto(newOrganizationDto());
142     ComponentDto branch = newProjectBranch(project, newBranchDto(project).setKey(BRANCH_NAME));
143     ComponentDto file = newFileDto(branch);
144     treeRootHolder.setRoot(builder(Type.PROJECT, 2).setKey(branch.getDbKey()).setPublicKey(branch.getKey()).setName(branch.longName()).setUuid(branch.uuid()).addChildren(
145       builder(Component.Type.FILE, 11).setKey(file.getDbKey()).setPublicKey(file.getKey()).setName(file.longName()).build()
146     ).build());
147     issueCache.newAppender().append(
148       new DefaultIssue().setSeverity(Severity.BLOCKER).setEffort(ISSUE_DURATION)).close();
149
150     when(notificationService.hasProjectSubscribersForTypes(branch.uuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
151     analysisMetadataHolder.setBranch(newBranch());
152
153     underTest.execute();
154
155     verify(notificationService).deliver(any(NewIssuesNotification.class));
156     verify(newIssuesNotificationMock).setProject(branch.getKey(), branch.uuid(), branch.longName(), BRANCH_NAME);
157     verify(newIssuesNotificationMock).setAnalysisDate(new Date(ANALYSE_DATE));
158     verify(newIssuesNotificationMock).setStatistics(eq(branch.longName()), any(NewIssuesStatistics.Stats.class));
159     verify(newIssuesNotificationMock).setDebt(ISSUE_DURATION);
160   }
161
162   @Test
163   public void send_new_issues_notification_to_user() throws Exception {
164     issueCache.newAppender().append(
165       new DefaultIssue().setSeverity(Severity.BLOCKER).setEffort(ISSUE_DURATION).setAssignee(ISSUE_ASSIGNEE)).close();
166
167     when(notificationService.hasProjectSubscribersForTypes(PROJECT.getUuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
168
169     underTest.execute();
170
171     verify(notificationService, times(2)).deliver(any(Notification.class));
172     verify(myNewIssuesNotificationMock).setAssignee(ISSUE_ASSIGNEE);
173     verify(myNewIssuesNotificationMock).setProject(PROJECT.getPublicKey(), PROJECT.getUuid(), PROJECT.getName(), null);
174     verify(myNewIssuesNotificationMock).setAnalysisDate(new Date(ANALYSE_DATE));
175     verify(myNewIssuesNotificationMock).setStatistics(eq(PROJECT.getName()), any(NewIssuesStatistics.Stats.class));
176     verify(myNewIssuesNotificationMock).setDebt(ISSUE_DURATION);
177   }
178
179   @Test
180   public void send_issues_change_notification() throws Exception {
181     ComponentDto project = newPrivateProjectDto(newOrganizationDto()).setDbKey(PROJECT.getKey()).setLongName(PROJECT.getName());
182     ComponentDto file = newFileDto(project).setDbKey(FILE.getKey()).setLongName(FILE.getName());
183     RuleDefinitionDto ruleDefinitionDto = newRule();
184     DefaultIssue issue = newIssue(ruleDefinitionDto, project, file).toDefaultIssue()
185       .setNew(false)
186       .setChanged(true)
187       .setSendNotifications(true);
188     ruleRepository.add(ruleDefinitionDto.getKey()).setName(ruleDefinitionDto.getName());
189     issueCache.newAppender().append(issue).close();
190     when(notificationService.hasProjectSubscribersForTypes(PROJECT.getUuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
191
192     underTest.execute();
193
194     ArgumentCaptor<IssueChangeNotification> issueChangeNotificationCaptor = ArgumentCaptor.forClass(IssueChangeNotification.class);
195     verify(notificationService).deliver(issueChangeNotificationCaptor.capture());
196     assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("key")).isEqualTo(issue.key());
197     assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("assignee")).isEqualTo(issue.assignee());
198     assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("message")).isEqualTo(issue.message());
199     assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("ruleName")).isEqualTo(ruleDefinitionDto.getName());
200     assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("projectName")).isEqualTo(project.longName());
201     assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("projectKey")).isEqualTo(project.getKey());
202     assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("componentKey")).isEqualTo(file.getKey());
203     assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("componentName")).isEqualTo(file.longName());
204   }
205
206   @Test
207   public void send_issues_change_notification_on_branch() throws Exception {
208     ComponentDto project = newPrivateProjectDto(newOrganizationDto());
209     ComponentDto branch = newProjectBranch(project, newBranchDto(project).setKey(BRANCH_NAME));
210     ComponentDto file = newFileDto(branch);
211     treeRootHolder.setRoot(builder(Type.PROJECT, 2).setKey(branch.getDbKey()).setPublicKey(branch.getKey()).setName(branch.longName()).setUuid(branch.uuid()).addChildren(
212       builder(Component.Type.FILE, 11).setKey(file.getDbKey()).setPublicKey(file.getKey()).setName(file.longName()).build()
213     ).build());
214     RuleDefinitionDto ruleDefinitionDto = newRule();
215     DefaultIssue issue = newIssue(ruleDefinitionDto, branch, file).toDefaultIssue()
216       .setNew(false)
217       .setChanged(true)
218       .setSendNotifications(true);
219     ruleRepository.add(ruleDefinitionDto.getKey()).setName(ruleDefinitionDto.getName());
220     issueCache.newAppender().append(issue).close();
221     when(notificationService.hasProjectSubscribersForTypes(branch.uuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
222     analysisMetadataHolder.setBranch(newBranch());
223
224     underTest.execute();
225
226     ArgumentCaptor<IssueChangeNotification> issueChangeNotificationCaptor = ArgumentCaptor.forClass(IssueChangeNotification.class);
227     verify(notificationService).deliver(issueChangeNotificationCaptor.capture());
228     assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("projectName")).isEqualTo(branch.longName());
229     assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("projectKey")).isEqualTo(branch.getKey());
230     assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("branch")).isEqualTo(BRANCH_NAME);
231     assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("componentKey")).isEqualTo(file.getKey());
232     assertThat(issueChangeNotificationCaptor.getValue().getFieldValue("componentName")).isEqualTo(file.longName());
233   }
234
235   private NewIssuesNotification createNewIssuesNotificationMock() {
236     NewIssuesNotification notification = mock(NewIssuesNotification.class);
237     when(notification.setProject(anyString(), anyString(), anyString(), anyString())).thenReturn(notification);
238     when(notification.setAnalysisDate(any(Date.class))).thenReturn(notification);
239     when(notification.setStatistics(anyString(), any(NewIssuesStatistics.Stats.class))).thenReturn(notification);
240     when(notification.setDebt(any(Duration.class))).thenReturn(notification);
241     return notification;
242   }
243
244   private MyNewIssuesNotification createMyNewIssuesNotificationMock() {
245     MyNewIssuesNotification notification = mock(MyNewIssuesNotification.class);
246     when(notification.setAssignee(anyString())).thenReturn(notification);
247     when(notification.setProject(anyString(), anyString(), anyString(), anyString())).thenReturn(notification);
248     when(notification.setAnalysisDate(any(Date.class))).thenReturn(notification);
249     when(notification.setStatistics(anyString(), any(NewIssuesStatistics.Stats.class))).thenReturn(notification);
250     when(notification.setDebt(any(Duration.class))).thenReturn(notification);
251     return notification;
252   }
253
254   private static Branch newBranch() {
255     Branch branch = mock(Branch.class);
256     when(branch.isMain()).thenReturn(false);
257     when(branch.getName()).thenReturn(BRANCH_NAME);
258     return branch;
259   }
260
261   @Override
262   protected ComputationStep step() {
263     return underTest;
264   }
265 }