]> source.dussan.org Git - sonarqube.git/blob
bb60b3cf32aa1f1d18fec0e626b11c36e8337f6e
[sonarqube.git] /
1 /*
2  * Sonar, open source software quality management tool.
3  * Copyright (C) 2008-2012 SonarSource
4  * mailto:contact AT sonarsource DOT com
5  *
6  * Sonar 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  * Sonar 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
17  * License along with Sonar; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
19  */
20 package org.sonar.plugins.core.timemachine;
21
22 import static org.hamcrest.Matchers.is;
23 import static org.junit.Assert.assertThat;
24 import static org.mockito.Matchers.any;
25 import static org.mockito.Matchers.argThat;
26 import static org.mockito.Matchers.eq;
27 import static org.mockito.Mockito.mock;
28 import static org.mockito.Mockito.never;
29 import static org.mockito.Mockito.times;
30 import static org.mockito.Mockito.verify;
31 import static org.mockito.Mockito.when;
32
33 import java.text.DateFormat;
34 import java.text.SimpleDateFormat;
35 import java.util.Arrays;
36 import java.util.Calendar;
37 import java.util.Date;
38 import java.util.GregorianCalendar;
39 import java.util.List;
40
41 import org.apache.commons.lang.ObjectUtils;
42 import org.apache.commons.lang.time.DateUtils;
43 import org.hamcrest.BaseMatcher;
44 import org.hamcrest.Description;
45 import org.junit.Before;
46 import org.junit.Test;
47 import org.sonar.api.batch.DecoratorContext;
48 import org.sonar.api.measures.CoreMetrics;
49 import org.sonar.api.measures.Measure;
50 import org.sonar.api.measures.Metric;
51 import org.sonar.api.measures.RuleMeasure;
52 import org.sonar.api.notifications.Notification;
53 import org.sonar.api.notifications.NotificationManager;
54 import org.sonar.api.resources.File;
55 import org.sonar.api.resources.Project;
56 import org.sonar.api.resources.Qualifiers;
57 import org.sonar.api.resources.Resource;
58 import org.sonar.api.rules.Rule;
59 import org.sonar.api.rules.RulePriority;
60 import org.sonar.api.rules.Violation;
61 import org.sonar.batch.components.PastSnapshot;
62 import org.sonar.batch.components.TimeMachineConfiguration;
63
64 import com.google.common.collect.Lists;
65
66 public class NewViolationsDecoratorTest {
67   private Rule rule1;
68   private Rule rule2;
69   private Rule rule3;
70
71   private NewViolationsDecorator decorator;
72   private DecoratorContext context;
73   private Resource resource;
74   private NotificationManager notificationManager;
75
76   private Date rightNow;
77   private Date tenDaysAgo;
78   private Date fiveDaysAgo;
79   private TimeMachineConfiguration timeMachineConfiguration;
80
81   @Before
82   public void setUp() {
83     rightNow = new Date();
84     tenDaysAgo = DateUtils.addDays(rightNow, -10);
85     fiveDaysAgo = DateUtils.addDays(rightNow, -5);
86
87     PastSnapshot pastSnapshot = mock(PastSnapshot.class);
88     when(pastSnapshot.getIndex()).thenReturn(1);
89     when(pastSnapshot.getTargetDate()).thenReturn(fiveDaysAgo);
90
91     PastSnapshot pastSnapshot2 = mock(PastSnapshot.class);
92     when(pastSnapshot2.getIndex()).thenReturn(2);
93     when(pastSnapshot2.getTargetDate()).thenReturn(tenDaysAgo);
94
95     timeMachineConfiguration = mock(TimeMachineConfiguration.class);
96     when(timeMachineConfiguration.getProjectPastSnapshots()).thenReturn(Arrays.asList(pastSnapshot, pastSnapshot2));
97
98     context = mock(DecoratorContext.class);
99     resource = new File("com/foo/bar");
100     when(context.getResource()).thenReturn(resource);
101
102     notificationManager = mock(NotificationManager.class);
103     decorator = new NewViolationsDecorator(timeMachineConfiguration, notificationManager);
104
105     rule1 = Rule.create().setRepositoryKey("rule1").setKey("rule1").setName("name1");
106     rule2 = Rule.create().setRepositoryKey("rule2").setKey("rule2").setName("name2");
107     rule3 = Rule.create().setRepositoryKey("rule3").setKey("rule3").setName("name3");
108   }
109
110   @Test
111   public void shouldExecuteIfLastAnalysis() {
112     Project project = mock(Project.class);
113
114     when(project.isLatestAnalysis()).thenReturn(false);
115     assertThat(decorator.shouldExecuteOnProject(project), is(false));
116
117     when(project.isLatestAnalysis()).thenReturn(true);
118     assertThat(decorator.shouldExecuteOnProject(project), is(true));
119   }
120
121   @Test
122   public void shouldBeDependedUponMetric() {
123     assertThat(decorator.generatesMetric().size(), is(6));
124   }
125
126   @Test
127   public void shouldCountViolationsAfterDate() {
128     List<Violation> violations = createViolations();
129
130     assertThat(decorator.countViolations(null, fiveDaysAgo), is(0));
131     assertThat(decorator.countViolations(violations, fiveDaysAgo), is(1)); // 1 rightNow
132     assertThat(decorator.countViolations(violations, tenDaysAgo), is(3)); // 1 rightNow + 2 fiveDaysAgo
133   }
134
135   @Test
136   public void shouldClearCacheAfterExecution() {
137     Violation violation1 = Violation.create(rule1, resource).setSeverity(RulePriority.CRITICAL).setCreatedAt(rightNow);
138     Violation violation2 = Violation.create(rule2, resource).setSeverity(RulePriority.CRITICAL).setCreatedAt(rightNow);
139     when(context.getViolations()).thenReturn(Arrays.asList(violation1)).thenReturn(Arrays.asList(violation2));
140
141     decorator.decorate(resource, context);
142     decorator.decorate(resource, context);
143
144     verify(context, times(2)).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS, 1.0, 1.0)));
145     verify(context, never()).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS, 2.0, 2.0)));
146   }
147
148   @Test
149   public void severityViolations() {
150     when(context.getViolations()).thenReturn(createViolations());
151
152     decorator.decorate(resource, context);
153
154     // remember : period1 is 5daysAgo, period2 is 10daysAgo
155     verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_BLOCKER_VIOLATIONS, 0.0, 0.0)));
156     verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS, 1.0, 1.0)));
157     verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_MAJOR_VIOLATIONS, 0.0, 1.0)));
158     verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_MINOR_VIOLATIONS, 0.0, 1.0)));
159     verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_INFO_VIOLATIONS, 0.0, 0.0)));
160   }
161
162   @Test
163   public void ruleViolations() {
164     when(context.getViolations()).thenReturn(createViolations());
165
166     decorator.decorate(resource, context);
167
168     // remember : period1 is 5daysAgo, period2 is 10daysAgo
169     verify(context).saveMeasure(argThat(new IsVariationRuleMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS, rule1, 1.0, 1.0)));
170     verify(context).saveMeasure(argThat(new IsVariationRuleMeasure(CoreMetrics.NEW_MAJOR_VIOLATIONS, rule2, 0.0, 1.0)));
171     verify(context).saveMeasure(argThat(new IsVariationRuleMeasure(CoreMetrics.NEW_MINOR_VIOLATIONS, rule3, 0.0, 1.0)));
172   }
173
174   @Test
175   public void shouldNotNotifyIfNotLastestAnalysis() {
176     Project project = mock(Project.class);
177     when(project.isLatestAnalysis()).thenReturn(false);
178     assertThat(decorator.shouldExecuteOnProject(project), is(false));
179   }
180
181   @Test
182   public void shouldNotNotifyIfNotRootProject() throws Exception {
183     Project project = mock(Project.class);
184     when(project.getQualifier()).thenReturn(Qualifiers.MODULE);
185
186     decorator.decorate(project, context);
187
188     verify(notificationManager, never()).scheduleForSending(any(Notification.class));
189   }
190
191   @Test
192   public void shouldNotNotifyIfNoPeriodForLastAnalysis() throws Exception {
193     Project project = new Project("key");
194     when(timeMachineConfiguration.getLastAnalysisPeriodIndex()).thenReturn(null);
195
196     decorator.notifyNewViolations(project, context);
197
198     verify(notificationManager, never()).scheduleForSending(any(Notification.class));
199   }
200
201   @Test
202   public void shouldNotNotifyIfNoNewViolations() throws Exception {
203     Project project = new Project("key");
204     when(timeMachineConfiguration.getLastAnalysisPeriodIndex()).thenReturn(1);
205     Measure m = new Measure(CoreMetrics.NEW_VIOLATIONS);
206     when(context.getMeasure(CoreMetrics.NEW_VIOLATIONS)).thenReturn(m);
207
208     // NULL is returned here
209     decorator.notifyNewViolations(project, context);
210     verify(notificationManager, never()).scheduleForSending(any(Notification.class));
211
212     // 0 will be returned now
213     m.setVariation1(0.0);
214     decorator.notifyNewViolations(project, context);
215     verify(notificationManager, never()).scheduleForSending(any(Notification.class));
216   }
217
218   @Test
219   public void shouldNotifyUserAboutNewViolations() throws Exception {
220     Project project = new Project("key").setName("LongName");
221     project.setId(45);
222     when(timeMachineConfiguration.getLastAnalysisPeriodIndex()).thenReturn(2);
223     Calendar pastDate = new GregorianCalendar(2011, 10, 25);
224     PastSnapshot pastSnapshot = new PastSnapshot("", pastDate.getTime());
225     when(timeMachineConfiguration.getProjectPastSnapshots()).thenReturn(Lists.newArrayList(pastSnapshot, pastSnapshot));
226     Measure m = new Measure(CoreMetrics.NEW_VIOLATIONS).setVariation2(32.0);
227     when(context.getMeasure(CoreMetrics.NEW_VIOLATIONS)).thenReturn(m);
228
229     decorator.decorate(project, context);
230
231     DateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd");
232     Notification notification = new Notification("new-violations")
233         .setFieldValue("count", "32")
234         .setFieldValue("projectName", "LongName")
235         .setFieldValue("projectKey", "key")
236         .setFieldValue("projectId", "45")
237         .setFieldValue("period", "2")
238         .setFieldValue("fromDate", dateformat.format(pastDate.getTime()))
239         .setFieldValue("toDate", dateformat.format(new Date()));
240     verify(notificationManager, times(1)).scheduleForSending(eq(notification));
241   }
242
243   private List<Violation> createViolations() {
244     List<Violation> violations = Lists.newLinkedList();
245     violations.add(Violation.create(rule1, resource).setSeverity(RulePriority.CRITICAL).setCreatedAt(rightNow));
246     violations.add(Violation.create(rule1, resource).setSeverity(RulePriority.CRITICAL).setCreatedAt(tenDaysAgo));
247     violations.add(Violation.create(rule2, resource).setSeverity(RulePriority.MAJOR).setCreatedAt(fiveDaysAgo));
248     violations.add(Violation.create(rule2, resource).setSeverity(RulePriority.MAJOR).setCreatedAt(tenDaysAgo));
249     violations.add(Violation.create(rule3, resource).setSeverity(RulePriority.MINOR).setCreatedAt(fiveDaysAgo));
250     violations.add(Violation.create(rule3, resource).setSeverity(RulePriority.MINOR).setCreatedAt(tenDaysAgo));
251     return violations;
252   }
253
254   private class IsVariationRuleMeasure extends BaseMatcher<Measure> {
255     private Metric metric = null;
256     private Rule rule = null;
257     private Double var1 = null;
258     private Double var2 = null;
259
260     public IsVariationRuleMeasure(Metric metric, Rule rule, Double var1, Double var2) {
261       this.metric = metric;
262       this.rule = rule;
263       this.var1 = var1;
264       this.var2 = var2;
265     }
266
267     public boolean matches(Object o) {
268       if (!(o instanceof RuleMeasure)) {
269         return false;
270       }
271       RuleMeasure m = (RuleMeasure) o;
272       return ObjectUtils.equals(metric, m.getMetric()) &&
273         ObjectUtils.equals(rule, m.getRule()) &&
274         ObjectUtils.equals(var1, m.getVariation1()) &&
275         ObjectUtils.equals(var2, m.getVariation2());
276     }
277
278     public void describeTo(Description arg0) {
279     }
280   }
281
282   private class IsVariationMeasure extends BaseMatcher<Measure> {
283     private Metric metric = null;
284     private Double var1 = null;
285     private Double var2 = null;
286
287     public IsVariationMeasure(Metric metric, Double var1, Double var2) {
288       this.metric = metric;
289       this.var1 = var1;
290       this.var2 = var2;
291     }
292
293     public boolean matches(Object o) {
294       if (!(o instanceof Measure)) {
295         return false;
296       }
297       Measure m = (Measure) o;
298       return ObjectUtils.equals(metric, m.getMetric()) &&
299         ObjectUtils.equals(var1, m.getVariation1()) &&
300         ObjectUtils.equals(var2, m.getVariation2()) &&
301         !(m instanceof RuleMeasure);
302     }
303
304     public void describeTo(Description o) {
305     }
306   }
307 }