]> source.dussan.org Git - sonarqube.git/blob
e02c84ec71a73ce1dbeb8707d48311a65599e037
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2016 SonarSource SA
4  * mailto:contact 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.batch.mediumtest.issuesmode;
21
22 import org.apache.commons.lang.StringUtils;
23
24 import org.sonar.api.utils.log.LoggerLevel;
25 import org.assertj.core.api.Condition;
26 import org.sonar.batch.issue.tracking.TrackedIssue;
27 import com.google.common.collect.ImmutableMap;
28
29 import java.io.File;
30 import java.io.IOException;
31 import java.text.ParseException;
32 import java.text.SimpleDateFormat;
33 import java.util.Date;
34 import java.util.LinkedList;
35 import java.util.List;
36
37 import org.apache.commons.codec.digest.DigestUtils;
38 import org.apache.commons.io.FileUtils;
39 import org.apache.commons.io.filefilter.FileFilterUtils;
40 import org.junit.After;
41 import org.junit.Before;
42 import org.junit.Test;
43 import org.junit.rules.TemporaryFolder;
44 import org.sonar.api.CoreProperties;
45 import org.sonar.api.utils.log.LogTester;
46 import org.sonar.batch.bootstrapper.IssueListener;
47 import org.sonar.batch.mediumtest.BatchMediumTester;
48 import org.sonar.batch.mediumtest.TaskResult;
49 import org.sonar.batch.scan.report.ConsoleReport;
50 import org.sonar.scanner.protocol.Constants.Severity;
51 import org.sonar.scanner.protocol.input.ScannerInput.ServerIssue;
52 import org.sonar.xoo.XooPlugin;
53 import org.sonar.xoo.rule.XooRulesDefinition;
54 import static org.assertj.core.api.Assertions.assertThat;
55
56 public class IssueModeAndReportsMediumTest {
57
58   @org.junit.Rule
59   public TemporaryFolder temp = new TemporaryFolder();
60
61   @org.junit.Rule
62   public LogTester logTester = new LogTester();
63
64   private static SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
65
66   private static Long date(String date) {
67     try {
68       return sdf.parse(date).getTime();
69     } catch (ParseException e) {
70       throw new IllegalStateException(e);
71     }
72   }
73
74   public BatchMediumTester tester = BatchMediumTester.builder()
75     .bootstrapProperties(ImmutableMap.of(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_ISSUES))
76     .registerPlugin("xoo", new XooPlugin())
77     .addDefaultQProfile("xoo", "Sonar Way")
78     .addRules(new XooRulesDefinition())
79     .addRule("manual:MyManualIssue", "manual", "MyManualIssue", "My manual issue")
80     .addRule("manual:MyManualIssueDup", "manual", "MyManualIssue", "My manual issue")
81     .addActiveRule("xoo", "OneIssuePerLine", null, "One issue per line", "MAJOR", null, "xoo")
82     .addActiveRule("xoo", "OneIssueOnDirPerFile", null, "OneIssueOnDirPerFile", "MAJOR", null, "xoo")
83     .addActiveRule("xoo", "OneIssuePerModule", null, "OneIssuePerModule", "MAJOR", null, "xoo")
84     .addActiveRule("manual", "MyManualIssue", null, "My manual issue", "MAJOR", null, null)
85     .setPreviousAnalysisDate(new Date())
86     // Existing issue that is still detected
87     .mockServerIssue(ServerIssue.newBuilder().setKey("xyz")
88       .setModuleKey("sample")
89       .setPath("xources/hello/HelloJava.xoo")
90       .setRuleRepository("xoo")
91       .setRuleKey("OneIssuePerLine")
92       .setLine(1)
93       .setSeverity(Severity.MAJOR)
94       .setCreationDate(date("14/03/2004"))
95       .setChecksum(DigestUtils.md5Hex("packagehello;"))
96       .setStatus("OPEN")
97       .build())
98     // Existing issue that is no more detected (will be closed)
99     .mockServerIssue(ServerIssue.newBuilder().setKey("resolved")
100       .setModuleKey("sample")
101       .setPath("xources/hello/HelloJava.xoo")
102       .setRuleRepository("xoo")
103       .setRuleKey("OneIssuePerLine")
104       .setLine(1)
105       .setSeverity(Severity.MAJOR)
106       .setCreationDate(date("14/03/2004"))
107       .setChecksum(DigestUtils.md5Hex("dontexist"))
108       .setStatus("OPEN")
109       .build())
110     // Existing issue on project that is still detected
111     .mockServerIssue(ServerIssue.newBuilder().setKey("resolved-on-project")
112       .setModuleKey("sample")
113       .setRuleRepository("xoo")
114       .setRuleKey("OneIssuePerModule")
115       .setSeverity(Severity.CRITICAL)
116       .setCreationDate(date("14/03/2004"))
117       .setStatus("OPEN")
118       .build())
119     // Manual issue
120     .mockServerIssue(ServerIssue.newBuilder().setKey("manual")
121       .setModuleKey("sample")
122       .setPath("xources/hello/HelloJava.xoo")
123       .setRuleRepository("manual")
124       .setRuleKey("MyManualIssue")
125       .setLine(1)
126       .setSeverity(Severity.MAJOR)
127       .setCreationDate(date("14/03/2004"))
128       .setChecksum(DigestUtils.md5Hex("packagehello;"))
129       .setStatus("OPEN")
130       .build())
131     .build();
132
133   @Before
134   public void prepare() {
135     tester.start();
136   }
137
138   @After
139   public void stop() {
140     tester.stop();
141   }
142
143   private File copyProject(String path) throws Exception {
144     File projectDir = temp.newFolder();
145     File originalProjectDir = new File(IssueModeAndReportsMediumTest.class.getResource(path).toURI());
146     FileUtils.copyDirectory(originalProjectDir, projectDir, FileFilterUtils.notFileFilter(FileFilterUtils.nameFileFilter(".sonar")));
147     return projectDir;
148   }
149
150   @Test
151   public void testIssueTracking() throws Exception {
152     File projectDir = copyProject("/mediumtest/xoo/sample");
153
154     TaskResult result = tester
155       .newScanTask(new File(projectDir, "sonar-project.properties"))
156       .start();
157
158     int newIssues = 0;
159     int openIssues = 0;
160     int resolvedIssue = 0;
161     for (TrackedIssue issue : result.trackedIssues()) {
162       System.out
163         .println(issue.getMessage() + " " + issue.key() + " " + issue.getRuleKey() + " " + issue.isNew() + " " + issue.resolution() + " " + issue.componentKey() + " "
164           + issue.startLine());
165       if (issue.isNew()) {
166         newIssues++;
167       } else if (issue.resolution() != null) {
168         resolvedIssue++;
169       } else {
170         openIssues++;
171       }
172     }
173     System.out.println("new: " + newIssues + " open: " + openIssues + " resolved " + resolvedIssue);
174     assertThat(newIssues).isEqualTo(16);
175     assertThat(openIssues).isEqualTo(3);
176     assertThat(resolvedIssue).isEqualTo(1);
177     
178     // progress report
179     String logs = StringUtils.join(logTester.logs(LoggerLevel.INFO), "\n");
180     
181     assertThat(logs).contains("Performing issue tracking");
182     assertThat(logs).contains("6/6 components tracked");
183
184     // assert that original fields of a matched issue are kept
185     assertThat(result.trackedIssues()).haveExactly(1, new Condition<TrackedIssue>() {
186       @Override
187       public boolean matches(TrackedIssue value) {
188         return value.isNew() == false
189           && "resolved-on-project".equals(value.key())
190           && "OPEN".equals(value.status())
191           && new Date(date("14/03/2004")).equals(value.creationDate());
192       }
193     });
194   }
195
196   @Test
197   public void testConsoleReport() throws Exception {
198     File projectDir = copyProject("/mediumtest/xoo/sample");
199
200     tester
201       .newScanTask(new File(projectDir, "sonar-project.properties"))
202       .property("sonar.issuesReport.console.enable", "true")
203       .start();
204
205     assertThat(getReportLog()).contains("+16 issues", "+16 major");
206   }
207
208   @Test
209   public void testPostJob() throws Exception {
210     File projectDir = copyProject("/mediumtest/xoo/sample");
211
212     tester
213       .newScanTask(new File(projectDir, "sonar-project.properties"))
214       .property("sonar.xoo.enablePostJob", "true")
215       .start();
216
217     assertThat(logTester.logs()).contains("Resolved issues: 1", "Open issues: 19");
218   }
219
220   private String getReportLog() {
221     for (String log : logTester.logs()) {
222       if (log.contains(ConsoleReport.HEADER)) {
223         return log;
224       }
225     }
226     throw new IllegalStateException("No console report");
227   }
228
229   @Test
230   public void testHtmlReport() throws Exception {
231     File projectDir = copyProject("/mediumtest/xoo/sample");
232
233     tester
234       .newScanTask(new File(projectDir, "sonar-project.properties"))
235       .property("sonar.issuesReport.html.enable", "true")
236       .start();
237
238     assertThat(new File(projectDir, ".sonar/issues-report/issues-report.html")).exists();
239     assertThat(new File(projectDir, ".sonar/issues-report/issues-report-light.html")).exists();
240   }
241
242   @Test
243   public void testHtmlReportNoFile() throws Exception {
244     File baseDir = temp.newFolder();
245     File srcDir = new File(baseDir, "src");
246     srcDir.mkdir();
247
248     tester.newTask()
249       .properties(ImmutableMap.<String, String>builder()
250         .put("sonar.task", "scan")
251         .put("sonar.projectBaseDir", baseDir.getAbsolutePath())
252         .put("sonar.projectKey", "sample")
253         .put("sonar.projectName", "Foo Project")
254         .put("sonar.projectVersion", "1.0-SNAPSHOT")
255         .put("sonar.projectDescription", "Description of Foo Project")
256         .put("sonar.sources", "src")
257         .put("sonar.issuesReport.html.enable", "true")
258         .build())
259       .start();
260
261     assertThat(FileUtils.readFileToString(new File(baseDir, ".sonar/issues-report/issues-report.html"))).contains("No file analyzed");
262     assertThat(FileUtils.readFileToString(new File(baseDir, ".sonar/issues-report/issues-report-light.html"))).contains("No file analyzed");
263   }
264
265   @Test
266   public void testIssueCallback() throws Exception {
267     File projectDir = copyProject("/mediumtest/xoo/sample");
268     IssueRecorder issueListener = new IssueRecorder();
269
270     TaskResult result = tester
271       .newScanTask(new File(projectDir, "sonar-project.properties"))
272       .setIssueListener(issueListener)
273       .start();
274
275     assertThat(result.trackedIssues()).hasSize(20);
276     assertThat(issueListener.issueList).hasSize(20);
277   }
278
279   private class IssueRecorder implements IssueListener {
280     List<Issue> issueList = new LinkedList<>();
281
282     @Override
283     public void handle(Issue issue) {
284       issueList.add(issue);
285     }
286   }
287
288   @Test
289   public void noSyntaxHighlightingInIssuesMode() throws IOException {
290
291     File baseDir = temp.newFolder();
292     File srcDir = new File(baseDir, "src");
293     srcDir.mkdir();
294
295     File xooFile = new File(srcDir, "sample.xoo");
296     File xoohighlightingFile = new File(srcDir, "sample.xoo.highlighting");
297     FileUtils.write(xooFile, "Sample xoo\ncontent plop");
298     FileUtils.write(xoohighlightingFile, "0:10:s\n11:18:k");
299
300     TaskResult result = tester.newTask()
301       .properties(ImmutableMap.<String, String>builder()
302         .put("sonar.projectBaseDir", baseDir.getAbsolutePath())
303         .put("sonar.projectKey", "com.foo.project")
304         .put("sonar.projectName", "Foo Project")
305         .put("sonar.projectVersion", "1.0-SNAPSHOT")
306         .put("sonar.projectDescription", "Description of Foo Project")
307         .put("sonar.sources", "src")
308         .build())
309       .start();
310
311     assertThat(result.getReportReader().hasSyntaxHighlighting(1)).isFalse();
312     assertThat(result.getReportReader().hasSyntaxHighlighting(2)).isFalse();
313     assertThat(result.getReportReader().hasSyntaxHighlighting(3)).isFalse();
314   }
315
316 }