3 * Copyright (C) 2009-2017 SonarSource SA
4 * mailto:info AT sonarsource DOT com
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.
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.
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.
20 package org.sonar.scanner.mediumtest.issuesmode;
22 import com.google.common.collect.ImmutableMap;
24 import java.io.IOException;
25 import java.text.ParseException;
26 import java.text.SimpleDateFormat;
27 import java.util.Date;
28 import org.apache.commons.codec.digest.DigestUtils;
29 import org.apache.commons.io.FileUtils;
30 import org.apache.commons.io.filefilter.FileFilterUtils;
31 import org.apache.commons.lang.StringUtils;
32 import org.assertj.core.api.Condition;
33 import org.junit.Rule;
34 import org.junit.Test;
35 import org.junit.rules.TemporaryFolder;
36 import org.sonar.api.CoreProperties;
37 import org.sonar.api.utils.log.LogTester;
38 import org.sonar.api.utils.log.LoggerLevel;
39 import org.sonar.scanner.issue.tracking.TrackedIssue;
40 import org.sonar.scanner.mediumtest.ScannerMediumTester;
41 import org.sonar.scanner.mediumtest.TaskResult;
42 import org.sonar.scanner.protocol.Constants.Severity;
43 import org.sonar.scanner.protocol.input.ScannerInput.ServerIssue;
44 import org.sonar.scanner.scan.report.ConsoleReport;
45 import org.sonar.xoo.XooPlugin;
46 import org.sonar.xoo.rule.XooRulesDefinition;
48 import static org.assertj.core.api.Assertions.assertThat;
50 public class IssueModeAndReportsMediumTest {
53 public TemporaryFolder temp = new TemporaryFolder();
56 public LogTester logTester = new LogTester();
58 private static SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
60 private static Long date(String date) {
62 return sdf.parse(date).getTime();
63 } catch (ParseException e) {
64 throw new IllegalStateException(e);
69 public ScannerMediumTester tester = new ScannerMediumTester()
70 .bootstrapProperties(ImmutableMap.of(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_ISSUES))
71 .registerPlugin("xoo", new XooPlugin())
72 .addDefaultQProfile("xoo", "Sonar Way")
73 .addRules(new XooRulesDefinition())
74 .addActiveRule("xoo", "OneIssuePerLine", null, "One issue per line", "MAJOR", null, "xoo")
75 .addActiveRule("xoo", "OneIssueOnDirPerFile", null, "OneIssueOnDirPerFile", "MAJOR", null, "xoo")
76 .addActiveRule("xoo", "OneIssuePerModule", null, "OneIssuePerModule", "MAJOR", null, "xoo")
77 .setPreviousAnalysisDate(new Date())
78 // Existing issue that is still detected
79 .mockServerIssue(ServerIssue.newBuilder().setKey("xyz")
80 .setModuleKey("sample")
81 .setPath("xources/hello/HelloJava.xoo")
82 .setRuleRepository("xoo")
83 .setRuleKey("OneIssuePerLine")
85 .setSeverity(Severity.MAJOR)
86 .setCreationDate(date("14/03/2004"))
87 .setChecksum(DigestUtils.md5Hex("packagehello;"))
90 // Existing issue that is no more detected (will be closed)
91 .mockServerIssue(ServerIssue.newBuilder().setKey("resolved")
92 .setModuleKey("sample")
93 .setPath("xources/hello/HelloJava.xoo")
94 .setRuleRepository("xoo")
95 .setRuleKey("OneIssuePerLine")
97 .setSeverity(Severity.MAJOR)
98 .setCreationDate(date("14/03/2004"))
99 .setChecksum(DigestUtils.md5Hex("dontexist"))
102 // Existing issue on project that is still detected
103 .mockServerIssue(ServerIssue.newBuilder().setKey("resolved-on-project")
104 .setModuleKey("sample")
105 .setRuleRepository("xoo")
106 .setRuleKey("OneIssuePerModule")
107 .setSeverity(Severity.CRITICAL)
108 .setCreationDate(date("14/03/2004"))
112 private File copyProject(String path) throws Exception {
113 File projectDir = temp.newFolder();
114 File originalProjectDir = new File(IssueModeAndReportsMediumTest.class.getResource(path).toURI());
115 FileUtils.copyDirectory(originalProjectDir, projectDir, FileFilterUtils.notFileFilter(FileFilterUtils.nameFileFilter(".sonar")));
120 public void testIssueTracking() throws Exception {
121 File projectDir = copyProject("/mediumtest/xoo/sample");
123 TaskResult result = tester
124 .newScanTask(new File(projectDir, "sonar-project.properties"))
129 int resolvedIssue = 0;
130 for (TrackedIssue issue : result.trackedIssues()) {
132 .println(issue.getMessage() + " " + issue.key() + " " + issue.getRuleKey() + " " + issue.isNew() + " " + issue.resolution() + " " + issue.componentKey() + " "
133 + issue.startLine());
136 } else if (issue.resolution() != null) {
142 System.out.println("new: " + newIssues + " open: " + openIssues + " resolved " + resolvedIssue);
143 assertThat(newIssues).isEqualTo(16);
144 assertThat(openIssues).isEqualTo(2);
145 assertThat(resolvedIssue).isEqualTo(1);
148 String logs = StringUtils.join(logTester.logs(LoggerLevel.INFO), "\n");
150 assertThat(logs).contains("Performing issue tracking");
151 assertThat(logs).contains("6/6 components tracked");
153 // assert that original fields of a matched issue are kept
154 assertThat(result.trackedIssues()).haveExactly(1, new Condition<TrackedIssue>() {
156 public boolean matches(TrackedIssue value) {
157 return value.isNew() == false
158 && "resolved-on-project".equals(value.key())
159 && "OPEN".equals(value.status())
160 && new Date(date("14/03/2004")).equals(value.creationDate());
166 public void testConsoleReport() throws Exception {
167 File projectDir = copyProject("/mediumtest/xoo/sample");
170 .newScanTask(new File(projectDir, "sonar-project.properties"))
171 .property("sonar.issuesReport.console.enable", "true")
174 assertThat(getReportLog()).contains("+16 issues", "+16 major");
178 public void testPostJob() throws Exception {
179 File projectDir = copyProject("/mediumtest/xoo/sample");
182 .newScanTask(new File(projectDir, "sonar-project.properties"))
183 .property("sonar.xoo.enablePostJob", "true")
186 assertThat(logTester.logs()).contains("Resolved issues: 1", "Open issues: 18");
189 private String getReportLog() {
190 for (String log : logTester.logs()) {
191 if (log.contains(ConsoleReport.HEADER)) {
195 throw new IllegalStateException("No console report");
199 public void testHtmlReport() throws Exception {
200 File projectDir = copyProject("/mediumtest/xoo/sample");
203 .newScanTask(new File(projectDir, "sonar-project.properties"))
204 .property("sonar.issuesReport.html.enable", "true")
207 assertThat(new File(projectDir, ".sonar/issues-report/issues-report.html")).exists();
208 assertThat(new File(projectDir, ".sonar/issues-report/issues-report-light.html")).exists();
212 public void testHtmlReportNoFile() throws Exception {
213 File baseDir = temp.newFolder();
214 File srcDir = new File(baseDir, "src");
218 .properties(ImmutableMap.<String, String>builder()
219 .put("sonar.task", "scan")
220 .put("sonar.projectBaseDir", baseDir.getAbsolutePath())
221 .put("sonar.projectKey", "sample")
222 .put("sonar.projectName", "Foo Project")
223 .put("sonar.projectVersion", "1.0-SNAPSHOT")
224 .put("sonar.projectDescription", "Description of Foo Project")
225 .put("sonar.sources", "src")
226 .put("sonar.issuesReport.html.enable", "true")
230 assertThat(FileUtils.readFileToString(new File(baseDir, ".sonar/issues-report/issues-report.html"))).contains("No file analyzed");
231 assertThat(FileUtils.readFileToString(new File(baseDir, ".sonar/issues-report/issues-report-light.html"))).contains("No file analyzed");
235 public void noSyntaxHighlightingInIssuesMode() throws IOException {
237 File baseDir = temp.newFolder();
238 File srcDir = new File(baseDir, "src");
241 File xooFile = new File(srcDir, "sample.xoo");
242 File xoohighlightingFile = new File(srcDir, "sample.xoo.highlighting");
243 FileUtils.write(xooFile, "Sample xoo\ncontent plop");
244 FileUtils.write(xoohighlightingFile, "0:10:s\n11:18:k");
246 TaskResult result = tester.newTask()
247 .properties(ImmutableMap.<String, String>builder()
248 .put("sonar.projectBaseDir", baseDir.getAbsolutePath())
249 .put("sonar.projectKey", "com.foo.project")
250 .put("sonar.projectName", "Foo Project")
251 .put("sonar.projectVersion", "1.0-SNAPSHOT")
252 .put("sonar.projectDescription", "Description of Foo Project")
253 .put("sonar.sources", "src")
257 assertThat(result.getReportReader().hasSyntaxHighlighting(1)).isFalse();
258 assertThat(result.getReportReader().hasSyntaxHighlighting(2)).isFalse();
259 assertThat(result.getReportReader().hasSyntaxHighlighting(3)).isFalse();