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