aboutsummaryrefslogtreecommitdiffstats
path: root/it/it-tests/src
diff options
context:
space:
mode:
authorDuarte Meneses <duarte.meneses@sonarsource.com>2015-08-14 14:49:49 +0200
committerDuarte Meneses <duarte.meneses@sonarsource.com>2015-08-18 09:36:10 +0200
commit2a5eea17c29c46566a13f84eead54b202a9bae83 (patch)
tree6e360aeea61672f86d090e52f281f6319953d4e2 /it/it-tests/src
parent48bb07308a21354e7f904a03b0c593158bde82b5 (diff)
downloadsonarqube-2a5eea17c29c46566a13f84eead54b202a9bae83.tar.gz
sonarqube-2a5eea17c29c46566a13f84eead54b202a9bae83.zip
Migrate batch ITs
Diffstat (limited to 'it/it-tests/src')
-rw-r--r--it/it-tests/src/test/java/batch/BatchTest.java460
-rw-r--r--it/it-tests/src/test/java/batch/IssuesModeTest.java345
-rw-r--r--it/it-tests/src/test/java/batch/SettingsEncryptionTest.java71
-rw-r--r--it/it-tests/src/test/java/batch/suite/BatchTestSuite.java41
-rw-r--r--it/it-tests/src/test/java/batch/suite/ExtensionLifecycleTest.java37
-rw-r--r--it/it-tests/src/test/java/batch/suite/IssueJsonReportTest.java212
-rw-r--r--it/it-tests/src/test/java/batch/suite/LinksTest.java82
-rw-r--r--it/it-tests/src/test/java/batch/suite/MavenTest.java241
-rw-r--r--it/it-tests/src/test/java/batch/suite/MultiLanguageTest.java67
-rw-r--r--it/it-tests/src/test/java/batch/suite/ProjectBuilderTest.java74
-rw-r--r--it/it-tests/src/test/java/batch/suite/ProjectExclusionsTest.java121
-rw-r--r--it/it-tests/src/test/java/batch/suite/ProjectProvisioningTest.java147
-rw-r--r--it/it-tests/src/test/java/batch/suite/TempFolderTest.java93
-rw-r--r--it/it-tests/src/test/java/duplications/suite/CrossProjectDuplicationsTest.java72
-rw-r--r--it/it-tests/src/test/java/duplications/suite/DuplicationsTest.java171
-rw-r--r--it/it-tests/src/test/java/duplications/suite/DuplicationsTestSuite.java23
-rw-r--r--it/it-tests/src/test/java/exclusions/suite/ExclusionsTestSuite.java25
-rw-r--r--it/it-tests/src/test/java/exclusions/suite/FileExclusionsTest.java129
-rw-r--r--it/it-tests/src/test/java/exclusions/suite/IssueExclusionsTest.java251
-rw-r--r--it/it-tests/src/test/java/plugins/PluginsTest.java2
-rw-r--r--it/it-tests/src/test/java/util/ItUtils.java59
-rw-r--r--it/it-tests/src/test/resources/batch/BatchTest/one-issue-per-line.xml12
-rw-r--r--it/it-tests/src/test/resources/batch/IssueJsonReportTest/no-server-analysis.json174
-rw-r--r--it/it-tests/src/test/resources/batch/IssueJsonReportTest/one-issue-per-line.xml12
-rw-r--r--it/it-tests/src/test/resources/batch/IssueJsonReportTest/report-on-root-module.json1
-rw-r--r--it/it-tests/src/test/resources/batch/IssueJsonReportTest/report-on-single-module-branch.json196
-rw-r--r--it/it-tests/src/test/resources/batch/IssueJsonReportTest/report-on-single-module.json196
-rw-r--r--it/it-tests/src/test/resources/batch/IssueJsonReportTest/report-on-sub-module.json208
-rw-r--r--it/it-tests/src/test/resources/batch/IssuesModeTest/empty.xml7
-rw-r--r--it/it-tests/src/test/resources/batch/IssuesModeTest/one-issue-per-line-empty.xml7
-rw-r--r--it/it-tests/src/test/resources/batch/IssuesModeTest/one-issue-per-line.xml12
-rw-r--r--it/it-tests/src/test/resources/batch/IssuesModeTest/with-many-rules.xml32
-rw-r--r--it/it-tests/src/test/resources/batch/MultiLanguageTest/one-issue-per-line-xoo2.xml12
-rw-r--r--it/it-tests/src/test/resources/batch/MultiLanguageTest/one-issue-per-line.xml12
-rw-r--r--it/it-tests/src/test/resources/batch/SettingsEncryptionTest/sonar-secret.txt1
-rw-r--r--it/it-tests/src/test/resources/batch/TempFolderTest/one-issue-per-line.xml12
-rw-r--r--it/it-tests/src/test/resources/exclusions/IssueExclusionsTest/with-many-rules.xml32
37 files changed, 3648 insertions, 1 deletions
diff --git a/it/it-tests/src/test/java/batch/BatchTest.java b/it/it-tests/src/test/java/batch/BatchTest.java
new file mode 100644
index 00000000000..e0e03509df1
--- /dev/null
+++ b/it/it-tests/src/test/java/batch/BatchTest.java
@@ -0,0 +1,460 @@
+/*
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package batch;
+
+import util.ItUtils;
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.BuildFailureException;
+import com.sonar.orchestrator.build.BuildResult;
+import com.sonar.orchestrator.build.SonarRunner;
+import com.sonar.orchestrator.locator.FileLocation;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Date;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.wsclient.Sonar;
+import org.sonar.wsclient.services.PropertyDeleteQuery;
+import org.sonar.wsclient.services.PropertyUpdateQuery;
+import org.sonar.wsclient.services.Resource;
+import org.sonar.wsclient.services.ResourceQuery;
+
+public class BatchTest {
+
+ @ClassRule
+ public static Orchestrator orchestrator = Orchestrator.builderEnv()
+ .addPlugin(ItUtils.xooPlugin())
+ .setContext("/")
+
+ .addPlugin(ItUtils.pluginArtifact("batch-plugin"))
+ // Java is only used in convert_library_into_module test
+ .setOrchestratorProperty("javaVersion", "LATEST_RELEASE").addPlugin("java")
+
+ .build();
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ @Before
+ public void deleteData() {
+ orchestrator.resetData();
+ orchestrator.getServer().restoreProfile(FileLocation.ofClasspath("/batch/BatchTest/one-issue-per-line.xml"));
+ }
+
+ /**
+ * SONAR-3718
+ */
+ @Test
+ public void should_scan_branch_with_forward_slash() {
+ scan("shared/xoo-multi-modules-sample");
+ scan("shared/xoo-multi-modules-sample", "sonar.branch", "branch/0.x");
+
+ Sonar sonar = orchestrator.getServer().getWsClient();
+ assertThat(sonar.findAll(new ResourceQuery().setQualifiers("TRK"))).hasSize(2);
+
+ Resource master = sonar.find(new ResourceQuery("com.sonarsource.it.samples:multi-modules-sample"));
+ assertThat(master.getName()).isEqualTo("Sonar :: Integration Tests :: Multi-modules Sample");
+
+ Resource branch = sonar.find(new ResourceQuery("com.sonarsource.it.samples:multi-modules-sample:branch/0.x"));
+ assertThat(branch.getName()).isEqualTo("Sonar :: Integration Tests :: Multi-modules Sample branch/0.x");
+ }
+
+ /**
+ * SONAR-2907
+ */
+ @Test
+ public void branch_should_load_own_settings_from_database() {
+ orchestrator.getServer().provisionProject("com.sonarsource.it.samples:multi-modules-sample", "Sonar :: Integration Tests :: Multi-modules Sample");
+ orchestrator.getServer().associateProjectToQualityProfile("com.sonarsource.it.samples:multi-modules-sample", "xoo", "one-issue-per-line");
+ scan("shared/xoo-multi-modules-sample");
+ assertThat(getResource("com.sonarsource.it.samples:multi-modules-sample:module_b")).isNotNull();
+
+ Sonar sonar = orchestrator.getServer().getAdminWsClient();
+ // The parameter skippedModule considers key after first colon
+ sonar.update(new PropertyUpdateQuery("sonar.skippedModules", "multi-modules-sample:module_b",
+ "com.sonarsource.it.samples:multi-modules-sample"));
+
+ try {
+ scan("shared/xoo-multi-modules-sample");
+ assertThat(getResource("com.sonarsource.it.samples:multi-modules-sample:module_b")).isNull();
+
+ scan("shared/xoo-multi-modules-sample",
+ "sonar.branch", "mybranch");
+
+ assertThat(getResource("com.sonarsource.it.samples:multi-modules-sample:module_b:mybranch")).isNotNull();
+ } finally {
+ sonar.delete(new PropertyDeleteQuery("sonar.skippedModules", "com.sonarsource.it.samples:multi-modules-sample"));
+ }
+ }
+
+ // SONAR-4680
+ @Test
+ public void module_should_load_own_settings_from_database() {
+ orchestrator.getServer().provisionProject("com.sonarsource.it.samples:multi-modules-sample", "Sonar :: Integration Tests :: Multi-modules Sample");
+ orchestrator.getServer().associateProjectToQualityProfile("com.sonarsource.it.samples:multi-modules-sample", "xoo", "one-issue-per-line");
+
+ Sonar sonar = orchestrator.getServer().getAdminWsClient();
+ String propKey = "myFakeProperty";
+ String rootModuleKey = "com.sonarsource.it.samples:multi-modules-sample";
+ String moduleBKey = rootModuleKey + ":module_b";
+ sonar.delete(new PropertyDeleteQuery(propKey, rootModuleKey));
+ sonar.delete(new PropertyDeleteQuery(propKey, moduleBKey));
+
+ BuildResult result = scan("shared/xoo-multi-modules-sample", "sonar.showSettings", "true");
+
+ assertThat(result.getLogs()).doesNotContain(rootModuleKey + ":" + propKey);
+ assertThat(result.getLogs()).doesNotContain(moduleBKey + ":" + propKey);
+
+ // Set property only on root project
+ sonar.update(new PropertyUpdateQuery(propKey, "project", rootModuleKey));
+
+ result = scan("shared/xoo-multi-modules-sample", "sonar.showSettings", "true");
+
+ assertThat(result.getLogs()).contains(rootModuleKey + ":" + propKey + " = project");
+ assertThat(result.getLogs()).contains(moduleBKey + ":" + propKey + " = project");
+
+ // Override property on moduleB
+ sonar.update(new PropertyUpdateQuery(propKey, "moduleB", moduleBKey));
+
+ result = scan("shared/xoo-multi-modules-sample", "sonar.showSettings", "true");
+
+ assertThat(result.getLogs()).contains(rootModuleKey + ":" + propKey + " = project");
+ assertThat(result.getLogs()).contains(moduleBKey + ":" + propKey + " = moduleB");
+ }
+
+ /**
+ * SONAR-3116
+ */
+ @Test
+ public void should_not_exclude_root_module() {
+ orchestrator.getServer().provisionProject("com.sonarsource.it.samples:multi-modules-sample", "Sonar :: Integration Tests :: Multi-modules Sample");
+ orchestrator.getServer().associateProjectToQualityProfile("com.sonarsource.it.samples:multi-modules-sample", "xoo", "one-issue-per-line");
+
+ thrown.expect(BuildFailureException.class);
+ scan("shared/xoo-multi-modules-sample",
+ "sonar.skippedModules", "multi-modules-sample");
+ }
+
+ /**
+ * SONAR-3024
+ */
+ @Test
+ public void should_support_source_files_with_same_deprecated_key() {
+ orchestrator.getServer().provisionProject("com.sonarsource.it.projects.batch:duplicate-source", "exclusions");
+ orchestrator.getServer().associateProjectToQualityProfile("com.sonarsource.it.projects.batch:duplicate-source", "xoo", "one-issue-per-line");
+ scan("batch/duplicate-source");
+
+ Sonar sonar = orchestrator.getServer().getAdminWsClient();
+ Resource project = sonar.find(new ResourceQuery("com.sonarsource.it.projects.batch:duplicate-source").setMetrics("files", "directories"));
+ // 2 main files and 1 test file all with same deprecated key
+ assertThat(project.getMeasureIntValue("files")).isEqualTo(2);
+ assertThat(project.getMeasureIntValue("directories")).isEqualTo(3);
+ }
+
+ /**
+ * SONAR-3125
+ */
+ @Test
+ public void should_display_explicit_message_when_no_plugin_language_available() {
+ orchestrator.getServer().provisionProject("sample", "xoo-sample");
+ orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
+
+ BuildResult buildResult = scanQuietly("shared/xoo-sample",
+ "sonar.language", "foo",
+ "sonar.profile", "");
+ assertThat(buildResult.getStatus()).isEqualTo(1);
+ assertThat(buildResult.getLogs()).contains(
+ "You must install a plugin that supports the language 'foo'");
+ }
+
+ @Test
+ public void should_display_explicit_message_when_wrong_profile() {
+ orchestrator.getServer().provisionProject("sample", "xoo-sample");
+ orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
+
+ BuildResult buildResult = scanQuietly("shared/xoo-sample",
+ "sonar.profile", "unknow");
+ assertThat(buildResult.getStatus()).isEqualTo(1);
+ assertThat(buildResult.getLogs()).contains(
+ "sonar.profile was set to 'unknow' but didn't match any profile for any language. Please check your configuration.");
+ }
+
+ @Test
+ public void should_authenticate_when_needed() {
+ try {
+ orchestrator.getServer().provisionProject("sample", "xoo-sample");
+ orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
+
+ orchestrator.getServer().getAdminWsClient().update(new PropertyUpdateQuery("sonar.forceAuthentication", "true"));
+
+ BuildResult buildResult = scanQuietly("shared/xoo-sample",
+ "sonar.login", "",
+ "sonar.password", "");
+ assertThat(buildResult.getStatus()).isEqualTo(1);
+ assertThat(buildResult.getLogs()).contains(
+ "Not authorized. Analyzing this project requires to be authenticated. Please provide the values of the properties sonar.login and sonar.password.");
+
+ // SONAR-4048
+ buildResult = scanQuietly("shared/xoo-sample",
+ "sonar.login", "wrong_login",
+ "sonar.password", "wrong_password");
+ assertThat(buildResult.getStatus()).isEqualTo(1);
+ assertThat(buildResult.getLogs()).contains(
+ "Not authorized. Please check the properties sonar.login and sonar.password.");
+
+ buildResult = scan("shared/xoo-sample",
+ "sonar.login", "admin",
+ "sonar.password", "admin");
+ assertThat(buildResult.getStatus()).isEqualTo(0);
+
+ } finally {
+ orchestrator.getServer().getAdminWsClient().update(new PropertyUpdateQuery("sonar.forceAuthentication", "false"));
+ }
+ }
+
+ /**
+ * SONAR-4211 Test Sonar Runner when server requires authentication
+ */
+ @Test
+ public void sonar_runner_with_secured_server() {
+ try {
+ orchestrator.getServer().provisionProject("sample", "xoo-sample");
+ orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
+
+ orchestrator.getServer().getAdminWsClient().update(new PropertyUpdateQuery("sonar.forceAuthentication", "true"));
+
+ BuildResult buildResult = scanQuietly("shared/xoo-sample");
+ assertThat(buildResult.getStatus()).isEqualTo(1);
+ assertThat(buildResult.getLogs()).contains(
+ "Not authorized. Analyzing this project requires to be authenticated. Please provide the values of the properties sonar.login and sonar.password.");
+
+ buildResult = scanQuietly("shared/xoo-sample",
+ "sonar.login", "wrong_login",
+ "sonar.password", "wrong_password");
+ assertThat(buildResult.getStatus()).isEqualTo(1);
+ assertThat(buildResult.getLogs()).contains(
+ "Not authorized. Please check the properties sonar.login and sonar.password.");
+
+ buildResult = scan("shared/xoo-sample",
+ "sonar.login", "admin",
+ "sonar.password", "admin");
+ assertThat(buildResult.getStatus()).isEqualTo(0);
+
+ } finally {
+ orchestrator.getServer().getAdminWsClient().update(new PropertyUpdateQuery("sonar.forceAuthentication", "false"));
+ }
+ }
+
+ /**
+ * SONAR-2291
+ */
+ @Test
+ public void batch_should_cache_plugin_jars() throws IOException {
+ File userHome = temp.newFolder();
+
+ BuildResult result = scan("shared/xoo-sample",
+ "sonar.userHome", userHome.getAbsolutePath());
+
+ File cache = new File(userHome, "cache");
+ assertThat(cache).exists().isDirectory();
+ int cachedFiles = FileUtils.listFiles(cache, new String[] {"jar"}, true).size();
+ assertThat(cachedFiles).isGreaterThan(5);
+ assertThat(result.getLogs()).contains("User cache: " + cache.getAbsolutePath());
+ assertThat(result.getLogs()).contains("Download sonar-xoo-plugin-");
+
+ result = scan("shared/xoo-sample",
+ "sonar.userHome", userHome.getAbsolutePath());
+ assertThat(cachedFiles).isEqualTo(cachedFiles);
+ assertThat(result.getLogs()).contains("User cache: " + cache.getAbsolutePath());
+ assertThat(result.getLogs()).doesNotContain("Download sonar-xoo-plugin-");
+ }
+
+ /**
+ * SONAR-4239
+ */
+ @Test
+ public void should_display_project_url_after_analysis() throws IOException {
+ orchestrator.getServer().provisionProject("com.sonarsource.it.samples:multi-modules-sample", "Sonar :: Integration Tests :: Multi-modules Sample");
+ orchestrator.getServer().associateProjectToQualityProfile("com.sonarsource.it.samples:multi-modules-sample", "xoo", "one-issue-per-line");
+ Assume.assumeTrue(orchestrator.getServer().version().isGreaterThanOrEquals("3.6"));
+
+ BuildResult result = scan("shared/xoo-multi-modules-sample");
+
+ assertThat(result.getLogs()).contains("/dashboard/index/com.sonarsource.it.samples:multi-modules-sample");
+
+ result = scan("shared/xoo-multi-modules-sample",
+ "sonar.branch", "mybranch");
+
+ assertThat(result.getLogs()).contains("/dashboard/index/com.sonarsource.it.samples:multi-modules-sample:mybranch");
+
+ orchestrator.getServer().getAdminWsClient().update(new PropertyUpdateQuery("sonar.core.serverBaseURL", "http://foo:123/sonar"));
+
+ result = scan("shared/xoo-multi-modules-sample");
+
+ assertThat(result.getLogs()).contains("http://foo:123/sonar/dashboard/index/com.sonarsource.it.samples:multi-modules-sample");
+ }
+
+ /**
+ * SONAR-4188, SONAR-5178, SONAR-5915
+ */
+ @Test
+ public void should_display_explicit_message_when_invalid_project_key_or_branch() {
+ orchestrator.getServer().provisionProject("sample", "xoo-sample");
+ orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
+
+ BuildResult buildResult = scanQuietly("shared/xoo-sample",
+ "sonar.projectKey", "ar g$l:");
+ assertThat(buildResult.getStatus()).isEqualTo(1);
+ assertThat(buildResult.getLogs()).contains("\"ar g$l:\" is not a valid project or module key")
+ .contains("Allowed characters");
+
+ // SONAR-4629
+ buildResult = scanQuietly("shared/xoo-sample",
+ "sonar.projectKey", "12345");
+ assertThat(buildResult.getStatus()).isEqualTo(1);
+ assertThat(buildResult.getLogs()).contains("\"12345\" is not a valid project or module key")
+ .contains("Allowed characters");
+
+ buildResult = scanQuietly("shared/xoo-sample",
+ "sonar.branch", "ar g$l:");
+ assertThat(buildResult.getStatus()).isEqualTo(1);
+ assertThat(buildResult.getLogs()).contains("\"ar g$l:\" is not a valid branch")
+ .contains("Allowed characters");
+ }
+
+ /**
+ * SONAR-4547
+ */
+ @Test
+ public void display_MessageException_without_stacktrace() throws Exception {
+ orchestrator.getServer().provisionProject("sample", "xoo-sample");
+ orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
+ BuildResult result = scanQuietly("shared/xoo-sample", "raiseMessageException", "true");
+ assertThat(result.getStatus()).isNotEqualTo(0);
+ assertThat(result.getLogs())
+ // message
+ .contains("Error message from plugin")
+
+ // but not stacktrace
+ .doesNotContain("at com.sonarsource.RaiseMessageException");
+ }
+
+ /**
+ * SONAR-4751
+ */
+ @Test
+ public void file_extensions_are_case_insensitive() throws Exception {
+ orchestrator.getServer().provisionProject("case-sensitive-file-extensions", "Case Sensitive");
+ orchestrator.getServer().associateProjectToQualityProfile("case-sensitive-file-extensions", "xoo", "one-issue-per-line");
+ scan("batch/case-sensitive-file-extensions");
+
+ Resource project = orchestrator.getServer().getWsClient().find(ResourceQuery.createForMetrics("case-sensitive-file-extensions", "files", "ncloc"));
+ assertThat(project.getMeasureIntValue("files")).isEqualTo(2);
+ assertThat(project.getMeasureIntValue("ncloc")).isEqualTo(5 + 2);
+ }
+
+ /**
+ * SONAR-4876
+ */
+ @Test
+ public void custom_module_key() {
+ orchestrator.getServer().provisionProject("com.sonarsource.it.samples:multi-modules-sample", "Sonar :: Integration Tests :: Multi-modules Sample");
+ orchestrator.getServer().associateProjectToQualityProfile("com.sonarsource.it.samples:multi-modules-sample", "xoo", "one-issue-per-line");
+ scan("batch/custom-module-key");
+ assertThat(getResource("com.sonarsource.it.samples:moduleA")).isNotNull();
+ assertThat(getResource("com.sonarsource.it.samples:moduleB")).isNotNull();
+ }
+
+ /**
+ * SONAR-4692
+ */
+ @Test
+ @Ignore("This test should be moved to a Medium test of the Compute Engine")
+ public void prevent_same_module_key_in_two_projects() {
+ orchestrator.getServer().provisionProject("projectAB", "project AB");
+ orchestrator.getServer().associateProjectToQualityProfile("projectAB", "xoo", "one-issue-per-line");
+ scan("batch/prevent-common-module/projectAB");
+ assertThat(getResource("com.sonarsource.it.samples:moduleA")).isNotNull();
+ assertThat(getResource("com.sonarsource.it.samples:moduleB")).isNotNull();
+
+ orchestrator.getServer().provisionProject("projectAC", "project AC");
+ orchestrator.getServer().associateProjectToQualityProfile("projectAC", "xoo", "one-issue-per-line");
+
+ BuildResult result = scanQuietly("batch/prevent-common-module/projectAC");
+ assertThat(result.getStatus()).isNotEqualTo(0);
+ assertThat(result.getLogs()).contains("Module \"com.sonarsource.it.samples:moduleA\" is already part of project \"projectAB\"");
+ }
+
+ /**
+ * SONAR-4235
+ */
+ @Test
+ public void test_project_creation_date() {
+ long before = new Date().getTime()-2000l;
+ orchestrator.getServer().provisionProject("sample", "xoo-sample");
+ orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
+ orchestrator.executeBuild(SonarRunner.create(ItUtils.projectDir("shared/xoo-sample")));
+ long after = new Date().getTime()+2000l;
+ Resource xooSample = orchestrator.getServer().getWsClient().find(new ResourceQuery().setResourceKeyOrId("sample"));
+ assertThat(xooSample.getCreationDate().getTime()).isGreaterThan(before).isLessThan(after);
+ }
+
+ /**
+ * SONAR-4334
+ */
+ @Test
+ @Ignore("Should be move to CE IT/MT")
+ public void fail_if_project_date_is_older_than_latest_snapshot() {
+ orchestrator.getServer().provisionProject("sample", "xoo-sample");
+ orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
+ SonarRunner analysis = SonarRunner.create(ItUtils.projectDir("shared/xoo-sample"));
+ analysis.setProperty("sonar.projectDate", "2014-01-01");
+ orchestrator.executeBuild(analysis);
+
+ analysis.setProperty("sonar.projectDate", "2000-10-19");
+ BuildResult result = orchestrator.executeBuildQuietly(analysis);
+
+ assertThat(result.getStatus()).isNotEqualTo(0);
+ assertThat(result.getLogs()).contains("'sonar.projectDate' property cannot be older than the date of the last known quality snapshot on this project. Value: '2000-10-19'. " +
+ "Latest quality snapshot: ");
+ assertThat(result.getLogs()).contains("This property may only be used to rebuild the past in a chronological order.");
+ }
+
+ private Resource getResource(String key) {
+ return orchestrator.getServer().getWsClient().find(ResourceQuery.createForMetrics(key, "lines"));
+ }
+
+ private BuildResult scan(String projectPath, String... props) {
+ SonarRunner runner = configureRunner(projectPath, props);
+ return orchestrator.executeBuild(runner);
+ }
+
+ private BuildResult scanQuietly(String projectPath, String... props) {
+ SonarRunner runner = configureRunner(projectPath, props);
+ return orchestrator.executeBuildQuietly(runner);
+ }
+
+ private SonarRunner configureRunner(String projectPath, String... props) {
+ SonarRunner runner = SonarRunner.create(ItUtils.projectDir(projectPath))
+ .setProperties(props);
+ return runner;
+ }
+
+}
diff --git a/it/it-tests/src/test/java/batch/IssuesModeTest.java b/it/it-tests/src/test/java/batch/IssuesModeTest.java
new file mode 100644
index 00000000000..bfd5e33d7ff
--- /dev/null
+++ b/it/it-tests/src/test/java/batch/IssuesModeTest.java
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package batch;
+
+import util.ItUtils;
+import com.google.common.collect.Maps;
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.BuildResult;
+import com.sonar.orchestrator.build.SonarRunner;
+import com.sonar.orchestrator.build.SonarRunnerInstaller;
+import com.sonar.orchestrator.config.FileSystem;
+import com.sonar.orchestrator.locator.FileLocation;
+import com.sonar.orchestrator.version.Version;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import static org.junit.Assert.*;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import org.apache.commons.lang.ObjectUtils;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.wsclient.SonarClient;
+import org.sonar.wsclient.issue.Issue;
+import org.sonar.wsclient.issue.IssueQuery;
+import org.sonar.wsclient.issue.Issues;
+import org.sonar.wsclient.services.Resource;
+import org.sonar.wsclient.services.ResourceQuery;
+import org.sonar.wsclient.user.UserParameters;
+
+public class IssuesModeTest {
+
+ @ClassRule
+ public static Orchestrator orchestrator = Orchestrator.builderEnv()
+ .addPlugin(ItUtils.xooPlugin())
+ .setContext("/")
+ .addPlugin(ItUtils.pluginArtifact("access-secured-props-plugin"))
+ .build();
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ @Before
+ public void deleteData() throws IOException {
+ orchestrator.resetData();
+ }
+
+ @Test
+ public void issuesAnalysisOnNewProject() throws IOException {
+ restoreProfile("one-issue-per-line.xml");
+ orchestrator.getServer().provisionProject("sample", "xoo-sample");
+ orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
+ SonarRunner runner = configureRunnerIssues("shared/xoo-sample");
+ orchestrator.executeBuild(runner);
+ }
+
+ // SONAR-5715
+ @Test
+ public void test_issues_mode_on_project_with_space_in_filename() throws IOException {
+ restoreProfile("with-many-rules.xml");
+ orchestrator.getServer().provisionProject("sample", "xoo-sample-with-spaces");
+ orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "with-many-rules");
+
+ SonarRunner runner = configureRunner("batch/xoo-sample-with-spaces/v2");
+ BuildResult result = orchestrator.executeBuild(runner);
+ assertThat(getResource("sample:my sources/main/xoo/sample/My Sample.xoo")).isNotNull();
+
+ runner = configureRunnerIssues("batch/xoo-sample-with-spaces/v2");
+ result = orchestrator.executeBuild(runner);
+ // Analysis is not persisted in database
+ Resource project = getResource("com.sonarsource.it.samples:simple-sample");
+ assertThat(project).isNull();
+ assertThat(result.getLogs()).contains("Issues");
+ assertThat(result.getLogs()).contains("ANALYSIS SUCCESSFUL");
+ }
+
+ @Test
+ public void should_not_fail_on_resources_that_have_existed_before() throws IOException {
+ restoreProfile("with-many-rules.xml");
+ orchestrator.getServer().provisionProject("sample", "xoo-history");
+ orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "with-many-rules");
+
+ // First real scan with source
+ SonarRunner runner = configureRunner("shared/xoo-history-v2");
+ BuildResult result = orchestrator.executeBuild(runner);
+ assertThat(getResource("sample:src/main/xoo/sample/ClassAdded.xoo")).isNotNull();
+
+ // Second scan should remove ClassAdded.xoo
+ runner = configureRunner("shared/xoo-history-v1");
+ result = orchestrator.executeBuild(runner);
+ assertThat(getResource("sample:src/main/xoo/sample/ClassAdded.xoo")).isNull();
+
+ // Re-add ClassAdded.xoo in local workspace
+ runner = configureRunnerIssues("shared/xoo-history-v2");
+ result = orchestrator.executeBuild(runner);
+
+ assertThat(getResource("sample:src/main/xoo/sample/ClassAdded.xoo")).isNull();
+ assertThat(result.getLogs()).contains("Issues");
+ assertThat(result.getLogs()).contains("ANALYSIS SUCCESSFUL");
+ }
+
+ @Test
+ public void should_fail_if_plugin_access_secured_properties() throws IOException {
+ // Test access from task (ie BatchSettings)
+ SonarRunner runner = configureRunnerIssues("shared/xoo-sample",
+ "accessSecuredFromTask", "true");
+ BuildResult result = orchestrator.executeBuildQuietly(runner);
+
+ assertThat(result.getLogs()).contains("Access to the secured property 'foo.bar.secured' is not possible in issues mode. "
+ + "The SonarQube plugin which requires this property must be deactivated in issues mode.");
+
+ // Test access from sensor (ie ModuleSettings)
+ runner = configureRunnerIssues("shared/xoo-sample",
+ "accessSecuredFromSensor", "true");
+ result = orchestrator.executeBuildQuietly(runner);
+
+ assertThat(result.getLogs()).contains("Access to the secured property 'foo.bar.secured' is not possible in issues mode. "
+ + "The SonarQube plugin which requires this property must be deactivated in issues mode.");
+ }
+
+ // SONAR-4602
+ @Test
+ public void no_issues_mode_cache_after_new_analysis() throws Exception {
+ restoreProfile("one-issue-per-line.xml");
+ restoreProfile("empty.xml");
+ orchestrator.getServer().provisionProject("sample", "xoo-sample");
+
+ // First run (publish mode)
+ orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "empty");
+ SonarRunner runner = configureRunner("shared/xoo-sample");
+ orchestrator.executeBuild(runner);
+
+ // First run issues mode
+ orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
+ runner = configureRunnerIssues("shared/xoo-sample");
+ BuildResult result = orchestrator.executeBuild(runner);
+
+ // As many new issue as lines
+ assertThat(ItUtils.countIssuesInJsonReport(result, true)).isEqualTo(17);
+
+ // Second run (publish mode) should invalidate cache
+ runner = configureRunner("shared/xoo-sample");
+ orchestrator.executeBuild(runner);
+
+ // Second run issues mode
+ runner = configureRunnerIssues("shared/xoo-sample", "sonar.report.export.path", "sonar-report.json");
+ result = orchestrator.executeBuild(runner);
+
+ // No new issue this time
+ assertThat(ItUtils.countIssuesInJsonReport(result, true)).isEqualTo(0);
+ }
+
+ // SONAR-4602
+ @Test
+ public void no_issues_mode_cache_after_profile_change() throws Exception {
+ restoreProfile("one-issue-per-line-empty.xml");
+ orchestrator.getServer().provisionProject("sample", "xoo-sample");
+ orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
+
+ // First run (publish mode)
+ SonarRunner runner = configureRunner("shared/xoo-sample");
+ orchestrator.executeBuild(runner);
+
+ // First issues mode
+ runner = configureRunnerIssues("shared/xoo-sample");
+ BuildResult result = orchestrator.executeBuild(runner);
+
+ // No new issues
+ assertThat(ItUtils.countIssuesInJsonReport(result, true)).isEqualTo(0);
+
+ // Modification of QP should invalidate cache
+ restoreProfile("/one-issue-per-line.xml");
+
+ // Second issues mode
+ runner = configureRunnerIssues("shared/xoo-sample", "sonar.report.export.path", "sonar-report.json");
+ result = orchestrator.executeBuild(runner);
+
+ // As many new issue as lines
+ assertThat(ItUtils.countIssuesInJsonReport(result, true)).isEqualTo(17);
+ }
+
+ // SONAR-4602
+ @Test
+ public void no_issues_mode_cache_after_issue_change() throws Exception {
+ restoreProfile("one-issue-per-line.xml");
+ orchestrator.getServer().provisionProject("sample", "xoo-sample");
+ orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
+
+ // First run (publish mode)
+ SonarRunner runner = configureRunner("shared/xoo-sample");
+ orchestrator.executeBuild(runner);
+
+ // First issues mode
+ runner = configureRunnerIssues("shared/xoo-sample");
+ BuildResult result = orchestrator.executeBuild(runner);
+
+ // 17 issues
+ assertThat(ItUtils.countIssuesInJsonReport(result, false)).isEqualTo(17);
+
+ // Flag one issue as false positive
+ JSONObject obj = ItUtils.getJSONReport(result);
+ String key = ((JSONObject) ((JSONArray) obj.get("issues")).get(0)).get("key").toString();
+ orchestrator.getServer().adminWsClient().issueClient().doTransition(key, "falsepositive");
+
+ // Second issues mode
+ runner = configureRunnerIssues("shared/xoo-sample");
+ result = orchestrator.executeBuild(runner);
+
+ // False positive is not returned
+ assertThat(ItUtils.countIssuesInJsonReport(result, false)).isEqualTo(16);
+ }
+
+ // SONAR-6522
+ @Test
+ public void load_user_name_in_json_report() throws Exception {
+ restoreProfile("one-issue-per-line.xml");
+ orchestrator.getServer().provisionProject("sample", "xoo-sample");
+ orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
+
+ // First run (publish mode)
+ SonarRunner runner = configureRunner("shared/xoo-sample");
+ orchestrator.executeBuild(runner);
+
+ SonarClient client = orchestrator.getServer().adminWsClient();
+
+ Issues issues = client.issueClient().find(IssueQuery.create());
+ Issue issue = issues.list().get(0);
+
+ UserParameters creationParameters = UserParameters.create().login("julien").name("Julien H")
+ .password("password").passwordConfirmation("password");
+ client.userClient().create(creationParameters);
+
+ // Assign issue
+ client.issueClient().assign(issue.key(), "julien");
+
+ // Issues
+ runner = configureRunnerIssues("shared/xoo-sample");
+ BuildResult result = orchestrator.executeBuild(runner);
+
+ JSONObject obj = ItUtils.getJSONReport(result);
+
+ Map<String, String> userNameByLogin = Maps.newHashMap();
+ final JSONArray users = (JSONArray) obj.get("users");
+ if (users != null) {
+ for (Object user : users) {
+ String login = ObjectUtils.toString(((JSONObject) user).get("login"));
+ String name = ObjectUtils.toString(((JSONObject) user).get("name"));
+ userNameByLogin.put(login, name);
+ }
+ }
+ assertThat(userNameByLogin.get("julien")).isEqualTo("Julien H");
+
+ for (Object issueJson : (JSONArray) obj.get("issues")) {
+ JSONObject jsonObject = (JSONObject) issueJson;
+ if (issue.key().equals(jsonObject.get("key"))) {
+ assertThat(jsonObject.get("assignee")).isEqualTo("julien");
+ return;
+ }
+ }
+ fail("Issue not found");
+ }
+
+ // SONAR-4602
+ @Test
+ public void concurrent_issue_mode_on_existing_project() throws Exception {
+ restoreProfile("one-issue-per-line.xml");
+ orchestrator.getServer().provisionProject("sample", "xoo-sample");
+ orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
+
+ SonarRunner runner = configureRunner("shared/xoo-sample");
+ orchestrator.executeBuild(runner);
+
+ runConcurrentIssues();
+ }
+
+ private void runConcurrentIssues() throws InterruptedException, ExecutionException {
+ // Install sonar-runner in advance to avoid concurrent unzip issues
+ FileSystem fileSystem = orchestrator.getConfiguration().fileSystem();
+ new SonarRunnerInstaller(fileSystem).install(Version.create(SonarRunner.DEFAULT_RUNNER_VERSION), fileSystem.workspace());
+ final int nThreads = 5;
+ ExecutorService executorService = Executors.newFixedThreadPool(nThreads);
+ List<Callable<BuildResult>> tasks = new ArrayList<>();
+ for (int i = 0; i < nThreads; i++) {
+ tasks.add(new Callable<BuildResult>() {
+
+ public BuildResult call() throws Exception {
+ SonarRunner runner = configureRunnerIssues("shared/xoo-sample");
+ return orchestrator.executeBuild(runner);
+ }
+ });
+ }
+
+ for (Future<BuildResult> result : executorService.invokeAll(tasks)) {
+ result.get();
+ }
+ }
+
+ private void restoreProfile(String fileName) {
+ orchestrator.getServer().restoreProfile(FileLocation.ofClasspath("/batch/IssuesModeTest/" + fileName));
+ }
+
+ private Resource getResource(String key) {
+ return orchestrator.getServer().getWsClient().find(ResourceQuery.createForMetrics(key, "lines"));
+ }
+
+ private SonarRunner configureRunnerIssues(String projectDir, String... props) throws IOException {
+ SonarRunner runner = SonarRunner.create(ItUtils.projectDir(projectDir),
+ "sonar.working.directory", temp.newFolder().getAbsolutePath(),
+ "sonar.analysis.mode", "issues",
+ "sonar.report.export.path", "sonar-report.json",
+ "sonar.userHome", temp.newFolder().getAbsolutePath());
+ runner.setProperties(props);
+ return runner;
+ }
+
+ private SonarRunner configureRunner(String projectDir, String... props) throws IOException {
+ SonarRunner runner = SonarRunner.create(ItUtils.projectDir(projectDir),
+ "sonar.working.directory", temp.newFolder().getAbsolutePath(),
+ "sonar.report.export.path", "sonar-report.json",
+ "sonar.userHome", temp.newFolder().getAbsolutePath());
+ runner.setProperties(props);
+ return runner;
+ }
+
+}
diff --git a/it/it-tests/src/test/java/batch/SettingsEncryptionTest.java b/it/it-tests/src/test/java/batch/SettingsEncryptionTest.java
new file mode 100644
index 00000000000..b415e496be4
--- /dev/null
+++ b/it/it-tests/src/test/java/batch/SettingsEncryptionTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package batch;
+
+import util.ItUtils;
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.BuildFailureException;
+import com.sonar.orchestrator.build.BuildResult;
+import com.sonar.orchestrator.build.SonarRunner;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+import java.io.File;
+import java.net.URL;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class SettingsEncryptionTest {
+ @ClassRule
+ public static Orchestrator orchestrator = Orchestrator.builderEnv()
+ .addPlugin(ItUtils.pluginArtifact("settings-encryption-plugin"))
+ .addPlugin(ItUtils.xooPlugin())
+ .build();
+
+ /**
+ * SONAR-2084
+ * SONAR-4061
+ */
+ @Test
+ public void testEncryptedProperty() throws Exception {
+ SonarRunner build = SonarRunner.create(ItUtils.projectDir("shared/xoo-sample"))
+ .setProperty("sonar.secretKeyPath", pathToValidSecretKey())
+ .setProperty("sonar.login", "admin")
+ // wrong password
+ .setProperty("sonar.password", "{aes}wrongencryption==")// wrong password
+ // "this is a secret" encrypted with the above secret key
+ .setProperty("encryptedProperty", "{aes}9mx5Zq4JVyjeChTcVjEide4kWCwusFl7P2dSVXtg9IY=");
+ BuildResult result = orchestrator.executeBuildQuietly(build);
+ assertThat(result.getStatus()).isNotEqualTo(0);
+ assertThat(result.getLogs()).contains("Fail to decrypt the property sonar.password. Please check your secret key");
+
+ build = SonarRunner.create(ItUtils.projectDir("shared/xoo-sample"))
+ .setProperty("sonar.secretKeyPath", pathToValidSecretKey())
+ // "admin" encrypted with the above secret key
+ .setProperty("sonar.login", "{aes}evRHXHsEyPr5RjEuxUJcHA==")
+ .setProperty("sonar.password", "{aes}evRHXHsEyPr5RjEuxUJcHA==")
+ // "this is a secret" encrypted with the above secret key
+ .setProperty("encryptedProperty", "{aes}9mx5Zq4JVyjeChTcVjEide4kWCwusFl7P2dSVXtg9IY=");
+ // no error
+ orchestrator.executeBuild(build);
+ }
+
+ /**
+ * SONAR-2084
+ */
+ @Test(expected = BuildFailureException.class)
+ public void failIfEncryptedPropertyButNoSecretKey() throws Exception {
+ // path to secret key is missing
+ SonarRunner build = SonarRunner.create(ItUtils.projectDir("shared/xoo-sample"))
+ .setProperty("encryptedProperty", "{aes}9mx5Zq4JVyjeChTcVjEide4kWCwusFl7P2dSVXtg9IY=");
+ orchestrator.executeBuild(build);
+ }
+
+ private String pathToValidSecretKey() throws Exception {
+ URL resource = getClass().getResource("/batch/SettingsEncryptionTest/sonar-secret.txt");
+ return new File(resource.toURI()).getCanonicalPath();
+ }
+}
diff --git a/it/it-tests/src/test/java/batch/suite/BatchTestSuite.java b/it/it-tests/src/test/java/batch/suite/BatchTestSuite.java
new file mode 100644
index 00000000000..4e77fd34e44
--- /dev/null
+++ b/it/it-tests/src/test/java/batch/suite/BatchTestSuite.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package batch.suite;
+
+import util.ItUtils;
+
+import com.sonar.orchestrator.Orchestrator;
+import org.junit.ClassRule;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ ExtensionLifecycleTest.class, LinksTest.class, MavenTest.class, ProjectBuilderTest.class, ProjectExclusionsTest.class,
+ TempFolderTest.class, MultiLanguageTest.class, IssueJsonReportTest.class, ProjectProvisioningTest.class
+})
+public class BatchTestSuite {
+
+ @ClassRule
+ public static final Orchestrator ORCHESTRATOR = Orchestrator.builderEnv()
+ .addPlugin(ItUtils.xooPlugin())
+ .setOrchestratorProperty("javaVersion", "LATEST_RELEASE").addPlugin("java")
+ .setContext("/")
+
+ // used by TempFolderTest
+ .addPlugin(ItUtils.pluginArtifact("batch-plugin"))
+
+ // used by ExtensionLifecycleTest
+ .addPlugin(ItUtils.pluginArtifact("extension-lifecycle-plugin"))
+
+ // used by ProjectBuilderTest
+ .addPlugin(ItUtils.pluginArtifact("project-builder-plugin"))
+
+ // used by SemaphoreTest
+ .addPlugin(ItUtils.pluginArtifact("crash-plugin"))
+
+ .build();
+}
diff --git a/it/it-tests/src/test/java/batch/suite/ExtensionLifecycleTest.java b/it/it-tests/src/test/java/batch/suite/ExtensionLifecycleTest.java
new file mode 100644
index 00000000000..ff8fe05118e
--- /dev/null
+++ b/it/it-tests/src/test/java/batch/suite/ExtensionLifecycleTest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package batch.suite;
+
+import util.ItUtils;
+
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.MavenBuild;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+public class ExtensionLifecycleTest {
+
+ @ClassRule
+ public static Orchestrator orchestrator = BatchTestSuite.ORCHESTRATOR;
+
+ @Before
+ public void cleanup() {
+ orchestrator.resetData();
+ }
+
+ @Test
+ public void testInstantiationStrategyAndLifecycleOfBatchExtensions() {
+ MavenBuild build = MavenBuild.create(ItUtils.projectPom("batch/extension-lifecycle"))
+ .setCleanSonarGoals()
+ .setProperty("extension.lifecycle", "true")
+ .setProperty("sonar.dynamicAnalysis", "false");
+
+ // Build fails if the extensions provided in the extension-lifecycle-plugin are not correctly
+ // managed.
+ orchestrator.executeBuild(build);
+ }
+}
diff --git a/it/it-tests/src/test/java/batch/suite/IssueJsonReportTest.java b/it/it-tests/src/test/java/batch/suite/IssueJsonReportTest.java
new file mode 100644
index 00000000000..7bc7b1c87aa
--- /dev/null
+++ b/it/it-tests/src/test/java/batch/suite/IssueJsonReportTest.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package batch.suite;
+
+import com.sonar.orchestrator.locator.ResourceLocation;
+import util.ItUtils;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.SonarRunner;
+import com.sonar.orchestrator.locator.FileLocation;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.skyscreamer.jsonassert.JSONAssert;
+
+public class IssueJsonReportTest {
+
+ @ClassRule
+ public static Orchestrator orchestrator = BatchTestSuite.ORCHESTRATOR;
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ @Before
+ public void resetData() {
+ orchestrator.resetData();
+ }
+
+ @Test
+ public void test_json_report_no_server_analysis() throws Exception {
+ orchestrator.getServer().restoreProfile(getResource("one-issue-per-line.xml"));
+ orchestrator.getServer().provisionProject("sample", "tracking");
+ orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
+
+ File projectDir = ItUtils.projectDir("batch/tracking/v1");
+ SonarRunner issuesModeScan = SonarRunner.create(projectDir)
+ .setProperty("sonar.analysis.mode", "issues")
+ .setProperty("sonar.userHome", temp.newFolder().getAbsolutePath())
+ .setProperty("sonar.report.export.path", "sonar-report.json")
+ .setProperty("sonar.projectDate", "2013-05-02");
+ orchestrator.executeBuild(issuesModeScan);
+
+ File report = new File(projectDir, ".sonar/sonar-report.json");
+ assertThat(report).isFile().exists();
+
+ String json = sanitize(FileUtils.readFileToString(report));
+ String expectedJson = sanitize(IOUtils.toString(getResourceInputStream("no-server-analysis.json")));
+ JSONAssert.assertEquals(expectedJson, json, false);
+ }
+
+ @Test
+ public void test_json_report() throws Exception {
+ orchestrator.getServer().restoreProfile(getResource("one-issue-per-line.xml"));
+ orchestrator.getServer().provisionProject("sample", "tracking");
+ orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
+
+ SonarRunner scan = SonarRunner.create(ItUtils.projectDir("batch/tracking/v1"))
+ .setProperty("sonar.projectDate", "2013-05-01");
+ orchestrator.executeBuild(scan);
+
+ // Issues mode scan -> 2 new issues and 13 existing issues
+ File projectDir = ItUtils.projectDir("batch/tracking/v2");
+ SonarRunner issuesModeScan = SonarRunner.create(projectDir)
+ .setProperty("sonar.analysis.mode", "issues")
+ .setProperty("sonar.userHome", temp.newFolder().getAbsolutePath())
+ .setProperty("sonar.report.export.path", "sonar-report.json")
+ .setProperty("sonar.projectDate", "2013-05-02");
+ orchestrator.executeBuild(issuesModeScan);
+
+ File report = new File(projectDir, ".sonar/sonar-report.json");
+ assertThat(report).isFile().exists();
+
+ String json = sanitize(FileUtils.readFileToString(report));
+ String expectedJson = sanitize(IOUtils.toString(getResourceInputStream("report-on-single-module.json")));
+ JSONAssert.assertEquals(expectedJson, json, false);
+ }
+
+ @Test
+ public void test_json_report_on_branch() throws Exception {
+ orchestrator.getServer().restoreProfile(getResource("one-issue-per-line.xml"));
+ orchestrator.getServer().provisionProject("sample:mybranch", "Sample");
+ orchestrator.getServer().associateProjectToQualityProfile("sample:mybranch", "xoo", "one-issue-per-line");
+
+ SonarRunner scan = SonarRunner.create(ItUtils.projectDir("batch/tracking/v1"))
+ .setProperty("sonar.projectDate", "2013-05-01")
+ .setProperty("sonar.branch", "mybranch");
+ orchestrator.executeBuild(scan);
+
+ // issues mode scan -> 2 new issues and 13 existing issues
+ File projectDir = ItUtils.projectDir("batch/tracking/v2");
+ SonarRunner issuesModeScan = SonarRunner.create(projectDir)
+ .setProperty("sonar.analysis.mode", "issues")
+ .setProperty("sonar.userHome", temp.newFolder().getAbsolutePath())
+ .setProperty("sonar.report.export.path", "sonar-report.json")
+ .setProperty("sonar.issuesReport.console.enable", "true")
+ .setProperty("sonar.projectDate", "2013-05-02")
+ .setProperty("sonar.verbose", "true")
+ .setProperty("sonar.branch", "mybranch");
+ orchestrator.executeBuild(issuesModeScan);
+
+ File report = new File(projectDir, ".sonar/sonar-report.json");
+ assertThat(report).isFile().exists();
+
+ String json = sanitize(FileUtils.readFileToString(report));
+ String expectedJson = sanitize(IOUtils.toString(getResourceInputStream("report-on-single-module-branch.json")));
+ JSONAssert.assertEquals(expectedJson, json, false);
+ }
+
+ /**
+ * Multi-modules project but Eclipse scans only a single module
+ */
+ @Test
+ public void test_json_report_on_sub_module() throws Exception {
+ orchestrator.getServer().restoreProfile(getResource("one-issue-per-line.xml"));
+ orchestrator.getServer().provisionProject("com.sonarsource.it.samples:multi-modules-sample", "Multi-module sample");
+ orchestrator.getServer().associateProjectToQualityProfile("com.sonarsource.it.samples:multi-modules-sample", "xoo", "one-issue-per-line");
+
+ File rootDir = ItUtils.projectDir("shared/xoo-multi-modules-sample");
+ SonarRunner scan = SonarRunner.create(rootDir)
+ .setProperty("sonar.projectDate", "2013-05-01");
+ orchestrator.executeBuild(scan);
+
+ // Issues mode scan on a module -> no new issues
+ File moduleDir = ItUtils.projectDir("shared/xoo-multi-modules-sample/module_a/module_a1");
+ SonarRunner issuesModeScan = SonarRunner.create(moduleDir)
+ .setProperty("sonar.projectKey", "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1")
+ .setProperty("sonar.projectVersion", "1.0-SNAPSHOT")
+ .setProperty("sonar.projectName", "ModuleA1")
+ .setProperty("sonar.sources", "src/main/xoo")
+ .setProperty("sonar.language", "xoo")
+ .setProperty("sonar.analysis.mode", "issues")
+ .setProperty("sonar.userHome", temp.newFolder().getAbsolutePath())
+ .setProperty("sonar.report.export.path", "sonar-report.json")
+ .setProperty("sonar.projectDate", "2013-05-02");
+ orchestrator.executeBuild(issuesModeScan);
+
+ File report = new File(moduleDir, ".sonar/sonar-report.json");
+ assertThat(report).isFile().exists();
+
+ String json = sanitize(FileUtils.readFileToString(report));
+ // SONAR-5218 All issues are updated as their root project id has changed (it's now the sub module)
+ String expectedJson = sanitize(IOUtils.toString(getResourceInputStream("report-on-sub-module.json")));
+ JSONAssert.assertEquals(expectedJson, json, false);
+ }
+
+ /**
+ * Multi-modules project
+ */
+ @Test
+ public void test_json_report_on_root_module() throws Exception {
+ orchestrator.getServer().restoreProfile(getResource("/one-issue-per-line.xml"));
+ orchestrator.getServer().provisionProject("com.sonarsource.it.samples:multi-modules-sample", "Sonar :: Integration Tests :: Multi-modules Sample");
+ orchestrator.getServer().associateProjectToQualityProfile("com.sonarsource.it.samples:multi-modules-sample", "xoo", "one-issue-per-line");
+
+ File rootDir = ItUtils.projectDir("shared/xoo-multi-modules-sample");
+ SonarRunner scan = SonarRunner.create(rootDir)
+ .setProperty("sonar.projectDate", "2013-05-01");
+ orchestrator.executeBuild(scan);
+
+ // issues mode scan -> no new issues
+ SonarRunner issuesModeScan = SonarRunner.create(rootDir)
+ .setProperty("sonar.analysis.mode", "issues")
+ .setProperty("sonar.userHome", temp.newFolder().getAbsolutePath())
+ .setProperty("sonar.report.export.path", "sonar-report.json")
+ .setProperty("sonar.projectDate", "2013-05-02");
+ orchestrator.executeBuild(issuesModeScan);
+
+ File report = new File(rootDir, ".sonar/sonar-report.json");
+ assertThat(report).isFile().exists();
+
+ String json = sanitize(FileUtils.readFileToString(report));
+ String expectedJson = sanitize(IOUtils.toString(getResourceInputStream("report-on-root-module.json")));
+ JSONAssert.assertEquals(expectedJson, json, false);
+ }
+
+ @Test
+ public void sanityCheck() {
+ assertThat(sanitize("5.0.0-5868-SILVER-SNAPSHOT")).isEqualTo("<SONAR_VERSION>");
+ }
+
+ private static String sanitize(String s) {
+ // sanitize issue uuid keys
+ s = s.replaceAll("\\w\\w\\w\\w\\w\\w\\w\\w\\-\\w\\w\\w\\w\\-\\w\\w\\w\\w\\-\\w\\w\\w\\w\\-\\w\\w\\w\\w\\w\\w\\w\\w\\w\\w\\w\\w", "abcde");
+
+ // sanitize sonar version. Note that "-SILVER-SNAPSHOT" is used by Goldeneye jobs
+ s = s.replaceAll("\\d\\.\\d(.\\d)?(\\-.*)?\\-SNAPSHOT", "<SONAR_VERSION>");
+
+ return ItUtils.sanitizeTimezones(s);
+ }
+
+ private InputStream getResourceInputStream(String resource) throws FileNotFoundException {
+ ResourceLocation res = getResource(resource);
+ return getClass().getResourceAsStream(res.getPath());
+ }
+
+ private ResourceLocation getResource(String resource) {
+ return FileLocation.ofClasspath("/batch/IssueJsonReportTest/" + resource);
+ }
+
+}
diff --git a/it/it-tests/src/test/java/batch/suite/LinksTest.java b/it/it-tests/src/test/java/batch/suite/LinksTest.java
new file mode 100644
index 00000000000..3c670a53c82
--- /dev/null
+++ b/it/it-tests/src/test/java/batch/suite/LinksTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package batch.suite;
+
+import util.ItUtils;
+import com.google.common.collect.Lists;
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.MavenBuild;
+import com.sonar.orchestrator.build.SonarRunner;
+import com.sonar.orchestrator.db.Database;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class LinksTest {
+
+ @ClassRule
+ public static Orchestrator orchestrator = BatchTestSuite.ORCHESTRATOR;
+
+ private static String[] expectedLinks = new String[] {
+ "homepage=http://www.simplesample.org_OVERRIDDEN",
+ "ci=http://bamboo.ci.codehaus.org/browse/SIMPLESAMPLE",
+ "issue=http://jira.codehaus.org/browse/SIMPLESAMPLE",
+ "scm=https://github.com/SonarSource/simplesample",
+ "scm_dev=scm:git:git@github.com:SonarSource/simplesample.git"
+ };
+
+ @Before
+ @After
+ public void cleanProjectLinksTable() {
+ // TODO should not do this and find another way without using direct db connection
+ orchestrator.getDatabase().truncate("project_links");
+ }
+
+ /**
+ * SONAR-3676
+ */
+ @Test
+ public void shouldUseLinkProperties() {
+ SonarRunner runner = SonarRunner.create(ItUtils.projectDir("batch/links-project"))
+ .setProperty("sonar.scm.disabled", "true");
+ orchestrator.executeBuild(runner);
+
+ checkLinks();
+ }
+
+ /**
+ * SONAR-3676
+ */
+ @Test
+ public void shouldUseLinkPropertiesOverPomLinksInMaven() {
+ MavenBuild build = MavenBuild.create(ItUtils.projectPom("batch/links-project"))
+ .setCleanPackageSonarGoals()
+ .setProperty("sonar.scm.disabled", "true");
+ orchestrator.executeBuild(build);
+
+ checkLinks();
+ }
+
+ private void checkLinks() {
+ Database db = orchestrator.getDatabase();
+ List<Map<String, String>> links = db.executeSql("select * from project_links");
+
+ assertThat(links.size()).isEqualTo(5);
+ Collection<String> linksToCheck = Lists.newArrayList();
+ for (Map<String, String> linkRow : links) {
+ linksToCheck.add(linkRow.get("LINK_TYPE") + "=" + linkRow.get("HREF"));
+ }
+ assertThat(linksToCheck).contains(expectedLinks);
+ }
+
+}
diff --git a/it/it-tests/src/test/java/batch/suite/MavenTest.java b/it/it-tests/src/test/java/batch/suite/MavenTest.java
new file mode 100644
index 00000000000..3d3855b106b
--- /dev/null
+++ b/it/it-tests/src/test/java/batch/suite/MavenTest.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package batch.suite;
+
+import util.ItUtils;
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.BuildResult;
+import com.sonar.orchestrator.build.MavenBuild;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.sonar.wsclient.Sonar;
+import org.sonar.wsclient.services.Resource;
+import org.sonar.wsclient.services.ResourceQuery;
+
+public class MavenTest {
+
+ @ClassRule
+ public static Orchestrator orchestrator = BatchTestSuite.ORCHESTRATOR;
+
+ @Before
+ public void deleteData() {
+ orchestrator.resetData();
+ }
+
+ @Test
+ public void shouldSupportJarWithoutSources() {
+ MavenBuild build = MavenBuild.create(ItUtils.projectPom("maven/project-with-module-without-sources"))
+ .setCleanSonarGoals();
+ orchestrator.executeBuild(build);
+
+ Resource project = orchestrator.getServer().getWsClient()
+ .find(ResourceQuery.createForMetrics("com.sonarsource.it.samples.project-with-module-without-sources:parent", "files"));
+ assertThat(project.getMeasureIntValue("files")).isEqualTo(1);
+
+ Resource subProject = orchestrator.getServer().getWsClient().find(ResourceQuery.create("com.sonarsource.it.samples.project-with-module-without-sources:without-sources"));
+ assertThat(subProject).isNotNull();
+ }
+
+ /**
+ * See SONAR-594
+ */
+ @Test
+ public void shouldSupportJeeProjects() {
+ MavenBuild build = MavenBuild.create(ItUtils.projectPom("maven/jee"))
+ .setGoals("clean install", "sonar:sonar");
+ orchestrator.executeBuild(build);
+
+ Resource project = orchestrator.getServer().getWsClient().find(ResourceQuery.createForMetrics("com.sonarsource.it.samples.jee:parent", "files"));
+ assertThat(project.getMeasureIntValue("files")).isEqualTo(2);
+
+ List<Resource> modules = orchestrator.getServer().getWsClient().findAll(ResourceQuery.create("com.sonarsource.it.samples.jee:parent").setDepth(-1).setQualifiers("BRC"));
+ assertThat(modules).hasSize(4);
+ }
+
+ /**
+ * See SONAR-222
+ */
+ @Test
+ public void shouldSupportMavenExtensions() {
+ MavenBuild build = MavenBuild.create(ItUtils.projectPom("maven/maven-extensions"))
+ .setCleanSonarGoals();
+ orchestrator.executeBuild(build);
+
+ Resource project = orchestrator.getServer().getWsClient().find(ResourceQuery.createForMetrics("com.sonarsource.it.samples:maven-extensions", "files"));
+ assertThat(project.getMeasureIntValue("files")).isEqualTo(1);
+ }
+
+ /**
+ * This test should be splitted. It checks multiple use-cases at the same time : SONAR-518, SONAR-519 and SONAR-593
+ */
+ @Test
+ public void testBadMavenParameters() {
+ // should not fail
+ MavenBuild build = MavenBuild.create(ItUtils.projectPom("maven/maven-bad-parameters"))
+ .setCleanSonarGoals();
+ orchestrator.executeBuild(build);
+
+ Resource project = orchestrator.getServer().getWsClient().find(ResourceQuery.createForMetrics("com.sonarsource.it.samples.maven-bad-parameters:parent", "files"));
+ assertThat(project.getMeasureIntValue("files")).isGreaterThan(0);
+ }
+
+ @Test
+ public void shouldAnalyzeMultiModules() {
+ MavenBuild build = MavenBuild.create(ItUtils.projectPom("maven/modules-order"))
+ .setCleanSonarGoals()
+ .setProperty("sonar.dynamicAnalysis", "false");
+ orchestrator.executeBuild(build);
+
+ Sonar sonar = orchestrator.getServer().getWsClient();
+ assertThat(sonar.find(new ResourceQuery("org.sonar.tests.modules-order:root")).getName()).isEqualTo("Sonar tests - modules order");
+
+ assertThat(sonar.find(new ResourceQuery("org.sonar.tests.modules-order:parent")).getName()).isEqualTo("Parent");
+
+ assertThat(sonar.find(new ResourceQuery("org.sonar.tests.modules-order:module_a")).getName()).isEqualTo("Module A");
+ assertThat(sonar.find(new ResourceQuery("org.sonar.tests.modules-order:module_a:src/main/java/HelloA.java")).getName()).isEqualTo("HelloA.java");
+
+ assertThat(sonar.find(new ResourceQuery("org.sonar.tests.modules-order:module_b")).getName()).isEqualTo("Module B");
+ assertThat(sonar.find(new ResourceQuery("org.sonar.tests.modules-order:module_b:src/main/java/HelloB.java")).getName()).isEqualTo("HelloB.java");
+ }
+
+ /**
+ * See SONAR-2735
+ */
+ @Test
+ public void shouldSupportDifferentDeclarationsForModules() {
+ MavenBuild build = MavenBuild.create(ItUtils.projectPom("maven/modules-declaration"))
+ .setCleanSonarGoals()
+ .setProperty("sonar.dynamicAnalysis", "false");
+ orchestrator.executeBuild(build);
+ Sonar sonar = orchestrator.getServer().getWsClient();
+
+ assertThat(sonar.find(new ResourceQuery("org.sonar.tests.modules-declaration:root")).getName()).isEqualTo("Root");
+
+ assertThat(sonar.find(new ResourceQuery("org.sonar.tests.modules-declaration:module_a")).getName()).isEqualTo("Module A");
+ assertThat(sonar.find(new ResourceQuery("org.sonar.tests.modules-declaration:module_a:src/main/java/HelloA.java")).getName()).isEqualTo("HelloA.java");
+
+ assertThat(sonar.find(new ResourceQuery("org.sonar.tests.modules-declaration:module_b")).getName()).isEqualTo("Module B");
+ assertThat(sonar.find(new ResourceQuery("org.sonar.tests.modules-declaration:module_b:src/main/java/HelloB.java")).getName()).isEqualTo("HelloB.java");
+
+ assertThat(sonar.find(new ResourceQuery("org.sonar.tests.modules-declaration:module_c")).getName()).isEqualTo("Module C");
+ assertThat(sonar.find(new ResourceQuery("org.sonar.tests.modules-declaration:module_c:src/main/java/HelloC.java")).getName()).isEqualTo("HelloC.java");
+
+ assertThat(sonar.find(new ResourceQuery("org.sonar.tests.modules-declaration:module_d")).getName()).isEqualTo("Module D");
+ assertThat(sonar.find(new ResourceQuery("org.sonar.tests.modules-declaration:module_d:src/main/java/HelloD.java")).getName()).isEqualTo("HelloD.java");
+
+ assertThat(sonar.find(new ResourceQuery("org.sonar.tests.modules-declaration:module_e")).getName()).isEqualTo("Module E");
+ assertThat(sonar.find(new ResourceQuery("org.sonar.tests.modules-declaration:module_e:src/main/java/HelloE.java")).getName()).isEqualTo("HelloE.java");
+ }
+
+ /**
+ * See SONAR-3843
+ */
+ @Test
+ public void should_support_shade_with_dependency_reduced_pom_with_clean_install_sonar_goals() {
+ MavenBuild build = MavenBuild.create(ItUtils.projectPom("maven/shade-with-dependency-reduced-pom"))
+ .setProperty("sonar.dynamicAnalysis", "false")
+ .setGoals("clean", "install", "sonar:sonar");
+
+ orchestrator.executeBuild(build);
+ }
+
+ /**
+ * SONAR-4245
+ */
+ @Test
+ @Ignore("This test should be moved to a Medium test of the Compute Engine")
+ public void should_prevent_analysis_of_module_then_project() {
+ MavenBuild scan = MavenBuild.create(ItUtils.projectPom("shared/multi-modules-sample/module_a"))
+ .setProperty("sonar.dynamicAnalysis", "false")
+ .setCleanSonarGoals();
+ orchestrator.executeBuild(scan);
+
+ scan = MavenBuild.create(ItUtils.projectPom("shared/multi-modules-sample"))
+ .setProperty("sonar.dynamicAnalysis", "false")
+ .setCleanSonarGoals();
+ BuildResult result = orchestrator.executeBuildQuietly(scan);
+ assertThat(result.getStatus()).isNotEqualTo(0);
+ assertThat(result.getLogs()).contains("The project 'com.sonarsource.it.samples:module_a' is already defined in SonarQube "
+ + "but not as a module of project 'com.sonarsource.it.samples:multi-modules-sample'. "
+ + "If you really want to stop directly analysing project 'com.sonarsource.it.samples:module_a', "
+ + "please first delete it from SonarQube and then relaunch the analysis of project 'com.sonarsource.it.samples:multi-modules-sample'.");
+ }
+
+ /**
+ * src/main/java is missing
+ */
+ @Test
+ public void maven_project_with_only_test_dir() {
+ MavenBuild build = MavenBuild.create(ItUtils.projectPom("maven/maven-only-test-dir")).setCleanPackageSonarGoals();
+ orchestrator.executeBuild(build);
+
+ Resource project = orchestrator.getServer().getWsClient().find(ResourceQuery.createForMetrics("com.sonarsource.it.samples:maven-only-test-dir", "tests", "files"));
+ assertThat(project.getMeasureIntValue("tests")).isEqualTo(1);
+ assertThat(project.getMeasure("files")).isNull();
+ }
+
+ /**
+ * The property sonar.sources overrides the source dirs as declared in Maven
+ */
+ @Test
+ public void override_sources() {
+ MavenBuild build = MavenBuild.create(ItUtils.projectPom("maven/maven-override-sources")).setGoals("sonar:sonar");
+ orchestrator.executeBuild(build);
+
+ Resource project = orchestrator.getServer().getWsClient().find(ResourceQuery.createForMetrics("com.sonarsource.it.samples:maven-override-sources", "files"));
+ assertThat(project.getMeasureIntValue("files")).isEqualTo(1);
+
+ Resource file = orchestrator.getServer().getWsClient().find(ResourceQuery.create("com.sonarsource.it.samples:maven-override-sources:src/main/java2/Hello2.java"));
+ assertThat(file).isNotNull();
+ }
+
+ /**
+ * The property sonar.inclusions overrides the property sonar.sources
+ */
+ @Test
+ public void inclusions_apply_to_source_dirs() {
+ MavenBuild build = MavenBuild.create(ItUtils.projectPom("maven/inclusions_apply_to_source_dirs")).setGoals("sonar:sonar");
+ orchestrator.executeBuild(build);
+
+ Resource project = orchestrator.getServer().getWsClient().find(ResourceQuery.createForMetrics("com.sonarsource.it.samples:inclusions_apply_to_source_dirs", "files"));
+ assertThat(project.getMeasureIntValue("files")).isEqualTo(1);
+
+ Resource file = orchestrator.getServer().getWsClient().find(ResourceQuery.create("com.sonarsource.it.samples:inclusions_apply_to_source_dirs:src/main/java/Hello2.java"));
+ assertThat(file).isNotNull();
+ }
+
+ /**
+ * The property sonar.sources has a typo -> fail, like in sonar-runner
+ */
+ @Test
+ public void fail_if_bad_value_of_sonar_sources_property() {
+ MavenBuild build = MavenBuild.create(ItUtils.projectPom("maven/maven-bad-sources-property")).setGoals("sonar:sonar");
+ BuildResult result = orchestrator.executeBuildQuietly(build);
+ assertThat(result.getStatus()).isNotEqualTo(0);
+ assertThat(result.getLogs()).contains(
+ "java2' does not exist for Maven module com.sonarsource.it.samples:maven-bad-sources-property:jar:1.0-SNAPSHOT. Please check the property sonar.sources");
+ }
+
+ /**
+ * The property sonar.sources has a typo -> fail, like in sonar-runner
+ */
+ @Test
+ public void fail_if_bad_value_of_sonar_tests_property() {
+ MavenBuild build = MavenBuild.create(ItUtils.projectPom("maven/maven-bad-tests-property")).setGoals("sonar:sonar");
+ BuildResult result = orchestrator.executeBuildQuietly(build);
+ assertThat(result.getStatus()).isNotEqualTo(0);
+ assertThat(result.getLogs()).contains(
+ "java2' does not exist for Maven module com.sonarsource.it.samples:maven-bad-tests-property:jar:1.0-SNAPSHOT. Please check the property sonar.tests");
+ }
+
+}
diff --git a/it/it-tests/src/test/java/batch/suite/MultiLanguageTest.java b/it/it-tests/src/test/java/batch/suite/MultiLanguageTest.java
new file mode 100644
index 00000000000..ef5f394c79a
--- /dev/null
+++ b/it/it-tests/src/test/java/batch/suite/MultiLanguageTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package batch.suite;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import util.ItUtils;
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.BuildResult;
+import com.sonar.orchestrator.build.SonarRunner;
+import com.sonar.orchestrator.locator.FileLocation;
+import org.junit.After;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.wsclient.services.Resource;
+import org.sonar.wsclient.services.ResourceQuery;
+
+public class MultiLanguageTest {
+
+ @ClassRule
+ public static Orchestrator orchestrator = BatchTestSuite.ORCHESTRATOR;
+
+ @After
+ public void cleanDatabase() {
+ orchestrator.resetData();
+ }
+
+ /**
+ * SONAR-926
+ * SONAR-5069
+ */
+ @Test
+ public void test_sonar_runner_inspection() {
+ orchestrator.getServer().restoreProfile(FileLocation.ofClasspath("/batch/MultiLanguageTest/one-issue-per-line.xml"));
+ orchestrator.getServer().restoreProfile(FileLocation.ofClasspath("/batch/MultiLanguageTest/one-issue-per-line-xoo2.xml"));
+
+ orchestrator.getServer().provisionProject("multi-language-sample", "multi-language-sample");
+
+ orchestrator.getServer().associateProjectToQualityProfile("multi-language-sample", "xoo", "one-issue-per-line");
+ orchestrator.getServer().associateProjectToQualityProfile("multi-language-sample","xoo2", "one-issue-per-line-xoo2");
+
+ SonarRunner build = SonarRunner.create().setProjectDir(ItUtils.projectDir("batch/xoo-multi-languages"));
+ BuildResult result = orchestrator.executeBuild(build);
+
+ assertThat(result.getLogs()).contains("2 files indexed");
+ assertThat(result.getLogs()).contains("Quality profile for xoo: one-issue-per-line");
+ assertThat(result.getLogs()).contains("Quality profile for xoo2: one-issue-per-line-xoo2");
+
+ // modules
+ Resource project = getResource("multi-language-sample", "files", "violations");
+ assertThat(project.getMeasureIntValue("files")).isEqualTo(2);
+ assertThat(project.getMeasureIntValue("violations")).isEqualTo(26);
+
+ Resource xooFile = getResource("multi-language-sample:src/sample/Sample.xoo", "violations");
+ assertThat(xooFile.getMeasureIntValue("violations")).isEqualTo(13);
+
+ Resource xoo2File = getResource("multi-language-sample:src/sample/Sample.xoo2", "violations");
+ assertThat(xoo2File.getMeasureIntValue("violations")).isEqualTo(13);
+ }
+
+ private Resource getResource(String resourceKey, String... metricKeys) {
+ return orchestrator.getServer().getWsClient().find(ResourceQuery.createForMetrics(resourceKey, metricKeys));
+ }
+}
diff --git a/it/it-tests/src/test/java/batch/suite/ProjectBuilderTest.java b/it/it-tests/src/test/java/batch/suite/ProjectBuilderTest.java
new file mode 100644
index 00000000000..d0e9bad2dc9
--- /dev/null
+++ b/it/it-tests/src/test/java/batch/suite/ProjectBuilderTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package batch.suite;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import util.ItUtils;
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.MavenBuild;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.wsclient.services.Resource;
+import org.sonar.wsclient.services.ResourceQuery;
+
+/**
+ * Test the extension point org.sonar.api.batch.bootstrap.ProjectBuilder
+ * <p/>
+ * A Sonar plugin can override the project definition injected by build-tool.
+ * Example: C# plugin loads project structure and modules from Visual Studio metadata file.
+ *
+ * @since 2.9
+ */
+public class ProjectBuilderTest {
+
+ @ClassRule
+ public static Orchestrator orchestrator = BatchTestSuite.ORCHESTRATOR;
+
+ @Test
+ public void shouldDefineProjectFromPlugin() {
+ MavenBuild build = MavenBuild.create(ItUtils.projectPom("batch/project-builder"))
+ .setCleanSonarGoals()
+ .setProperty("sonar.enableProjectBuilder", "true")
+ .setProperty("sonar.dynamicAnalysis", "false");
+ orchestrator.executeBuild(build);
+
+ checkProject();
+ checkSubProject("project-builder-module-a");
+ checkSubProject("project-builder-module-b");
+ checkFile("project-builder-module-a", "src/HelloA.java");
+ checkFile("project-builder-module-b", "src/HelloB.java");
+ assertThat(getResource("com.sonarsource.it.projects.batch:project-builder-module-b:src/IgnoredFile.java")).isNull();
+ }
+
+ private void checkProject() {
+ Resource project = getResource("com.sonarsource.it.projects.batch:project-builder");
+
+ // name has been changed by plugin
+ assertThat(project.getName()).isEqualTo("Name changed by plugin");
+
+ assertThat(project).isNotNull();
+ assertThat(project.getMeasureIntValue("files")).isEqualTo(2);
+ assertThat(project.getMeasureIntValue("lines")).isGreaterThan(10);
+ }
+
+ private void checkSubProject(String subProjectKey) {
+ Resource subProject = getResource("com.sonarsource.it.projects.batch:" + subProjectKey);
+ assertThat(subProject).isNotNull();
+ assertThat(subProject.getMeasureIntValue("files")).isEqualTo(1);
+ assertThat(subProject.getMeasureIntValue("lines")).isGreaterThan(5);
+ }
+
+ private void checkFile(String subProjectKey, String fileKey) {
+ Resource file = getResource("com.sonarsource.it.projects.batch:" + subProjectKey + ":" + fileKey);
+ assertThat(file).isNotNull();
+ assertThat(file.getMeasureIntValue("lines")).isGreaterThan(5);
+ }
+
+ private Resource getResource(String key) {
+ return orchestrator.getServer().getWsClient().find(ResourceQuery.createForMetrics(key, "lines", "files"));
+ }
+}
diff --git a/it/it-tests/src/test/java/batch/suite/ProjectExclusionsTest.java b/it/it-tests/src/test/java/batch/suite/ProjectExclusionsTest.java
new file mode 100644
index 00000000000..cd9e83ae4fb
--- /dev/null
+++ b/it/it-tests/src/test/java/batch/suite/ProjectExclusionsTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package batch.suite;
+
+import util.ItUtils;
+
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.MavenBuild;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.wsclient.services.Resource;
+import org.sonar.wsclient.services.ResourceQuery;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+public class ProjectExclusionsTest {
+ @ClassRule
+ public static Orchestrator orchestrator = BatchTestSuite.ORCHESTRATOR;
+
+ @Before
+ public void deleteProjectData() {
+ orchestrator.resetData();
+ }
+
+ /**
+ * This use-case was a bug in 2.8-RC2. It failed when both the properties sonar.branch and sonar.skippedModules
+ * were set on the same multi-modules project.
+ */
+ @Test
+ public void shouldSupportMixOfBranchAndSkippedModules() {
+ MavenBuild build = MavenBuild.create(ItUtils.projectPom("shared/multi-modules-sample"))
+ .setGoals("clean verify", "sonar:sonar")
+ .setProperty("sonar.dynamicAnalysis", "false")
+ .setProperty("sonar.branch", "mybranch")
+ .setProperty("sonar.skippedModules", "module_b");
+
+ orchestrator.executeBuild(build);
+
+ assertNotNull(getResource("com.sonarsource.it.samples:multi-modules-sample:mybranch"));
+ assertNotNull(getResource("com.sonarsource.it.samples:module_a:mybranch").getId());
+ assertNotNull(getResource("com.sonarsource.it.samples:module_a1:mybranch").getId());
+ assertNotNull(getResource("com.sonarsource.it.samples:module_a2:mybranch").getId());
+
+ assertNull(getResource("com.sonarsource.it.samples:module_b:mybranch"));
+ assertNull(getResource("com.sonarsource.it.samples:module_b1:mybranch"));
+ assertNull(getResource("com.sonarsource.it.samples:module_b2:mybranch"));
+ }
+
+ /**
+ * Black list
+ */
+ @Test
+ public void shouldExcludeModuleAndItsChildren() {
+ MavenBuild build = MavenBuild.create(ItUtils.projectPom("shared/multi-modules-sample"))
+ .setGoals("clean verify", "sonar:sonar")
+ .setProperty("sonar.dynamicAnalysis", "false")
+ .setProperty("sonar.skippedModules", "module_b");
+
+ orchestrator.executeBuild(build);
+
+ assertNotNull(getResource("com.sonarsource.it.samples:multi-modules-sample"));
+ assertNotNull(getResource("com.sonarsource.it.samples:module_a"));
+ assertNotNull(getResource("com.sonarsource.it.samples:module_a1"));
+ assertNotNull(getResource("com.sonarsource.it.samples:module_a2"));
+
+ // excluded project and its children
+ assertNull(getResource("com.sonarsource.it.samples:module_b"));
+ assertNull(getResource("com.sonarsource.it.samples:module_b1"));
+ assertNull(getResource("com.sonarsource.it.samples:module_b2"));
+ }
+
+ /**
+ * Exhaustive white list
+ */
+ @Test
+ public void shouldIncludeModules() {
+ MavenBuild build = MavenBuild.create(ItUtils.projectPom("shared/multi-modules-sample"))
+ .setGoals("clean verify", "sonar:sonar")
+ .setProperty("sonar.dynamicAnalysis", "false")
+ .setProperty("sonar.includedModules", "multi-modules-sample,module_a,module_a1");
+
+ orchestrator.executeBuild(build);
+
+ assertNotNull(getResource("com.sonarsource.it.samples:multi-modules-sample"));
+ assertNotNull(getResource("com.sonarsource.it.samples:module_a"));
+ assertNotNull(getResource("com.sonarsource.it.samples:module_a1"));
+
+ assertNull(getResource("com.sonarsource.it.samples:module_a2"));
+ assertNull(getResource("com.sonarsource.it.samples:module_b"));
+ assertNull(getResource("com.sonarsource.it.samples:module_b1"));
+ assertNull(getResource("com.sonarsource.it.samples:module_b2"));
+ }
+
+ @Test
+ public void rootModuleShouldBeOptionalInListOfIncludedModules() {
+ MavenBuild build = MavenBuild.create(ItUtils.projectPom("shared/multi-modules-sample"))
+ .setCleanSonarGoals()
+ .setProperty("sonar.dynamicAnalysis", "false")
+ // the root module 'multi-modules-sample' is not declared
+ .setProperty("sonar.includedModules", "module_a,module_a1");
+
+ orchestrator.executeBuild(build);
+
+ assertNotNull(getResource("com.sonarsource.it.samples:multi-modules-sample"));
+ assertNotNull(getResource("com.sonarsource.it.samples:module_a"));
+ assertNotNull(getResource("com.sonarsource.it.samples:module_a1"));
+
+ assertNull(getResource("com.sonarsource.it.samples:module_a2"));
+ assertNull(getResource("com.sonarsource.it.samples:module_b"));
+ assertNull(getResource("com.sonarsource.it.samples:module_b1"));
+ assertNull(getResource("com.sonarsource.it.samples:module_b2"));
+ }
+
+ private Resource getResource(String key) {
+ return orchestrator.getServer().getWsClient().find(ResourceQuery.create(key));
+ }
+}
diff --git a/it/it-tests/src/test/java/batch/suite/ProjectProvisioningTest.java b/it/it-tests/src/test/java/batch/suite/ProjectProvisioningTest.java
new file mode 100644
index 00000000000..e4212590134
--- /dev/null
+++ b/it/it-tests/src/test/java/batch/suite/ProjectProvisioningTest.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package batch.suite;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import util.ItUtils;
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.BuildResult;
+import com.sonar.orchestrator.build.SonarRunner;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.sonar.wsclient.SonarClient;
+import org.sonar.wsclient.project.NewProject;
+import org.sonar.wsclient.services.PropertyUpdateQuery;
+
+public class ProjectProvisioningTest {
+
+ @ClassRule
+ public static Orchestrator orchestrator = BatchTestSuite.ORCHESTRATOR;
+
+ @BeforeClass
+ public static void init() {
+ orchestrator.resetData();
+ orchestrator.executeBuild(
+ SonarRunner.create(ItUtils.projectDir("shared/xoo-sample"))
+ );
+ }
+
+ @AfterClass
+ public static void resetAutoProjectCreation() {
+ setProperty("sonar.preventAutoProjectCreation", "false");
+ }
+
+ private SonarClient client;
+
+ @Before
+ public void initClient() {
+ client = orchestrator.getServer().adminWsClient();
+ }
+
+ /**
+ * SONAR-3871
+ * SONAR-4713
+ */
+ @Test
+ public void should_allow_existing_project_scan() {
+ setProperty("sonar.preventAutoProjectCreation", "true");
+
+ // xoo-sample already exists => pass
+ checkBuildSuccess("shared/xoo-sample");
+ }
+
+ /**
+ * SONAR-3871
+ * SONAR-4713
+ */
+ @Test
+ @Ignore("This test should be moved to a Medium test of the Compute Engine")
+ public void should_prevent_project_creation() {
+ setProperty("sonar.preventAutoProjectCreation", "true");
+
+ // xoo-sample-with-tests does not exist => fail
+ checkBuildFailed("shared/xoo-sample-with-tests");
+
+ // provision xoo-sample-with-tests and retry
+ client.projectClient().create(
+ NewProject.create()
+ .key("sample-with-tests")
+ .name("Sample With Tests"));
+ checkBuildSuccess("shared/xoo-sample-with-tests");
+ }
+
+ /**
+ * SONAR-3871
+ * SONAR-4713
+ */
+ @Test
+ public void should_allow_provisioned_project() {
+ setProperty("sonar.preventAutoProjectCreation", "true");
+
+ // provision xoo-multi-modules-sample before 1st scan and check build OK
+ client.projectClient().create(
+ NewProject.create()
+ .key("com.sonarsource.it.samples:multi-modules-sample")
+ .name("Xoo Multi Modules Sample"));
+ checkBuildSuccess("shared/xoo-multi-modules-sample");
+ }
+
+ /**
+ * SONAR-5547
+ */
+ @Test
+ public void should_allow_provisioned_project_with_branch() {
+ setProperty("sonar.preventAutoProjectCreation", "true");
+
+ // provision xoo-multi-modules-sample before 1st scan and check build OK
+ client.projectClient().create(
+ NewProject.create()
+ .key("com.sonarsource.it.samples:multi-modules-sample:branch")
+ .name("Xoo Multi Modules Sample - Branch"));
+ checkBuildSuccess("shared/xoo-multi-modules-sample", "sonar.branch", "branch");
+ }
+
+ /**
+ * SONAR-3871
+ * SONAR-4713
+ */
+ @Test
+ public void should_allow_provisioned_project_even_when_provisioning_not_enforced() {
+ setProperty("sonar.preventAutoProjectCreation", "false");
+
+ client.projectClient().create(
+ NewProject.create()
+ .key("xo")
+ .name("xo"));
+ checkBuildSuccess("shared/xoo-two-letters-named");
+ }
+
+ private static BuildResult checkBuildSuccess(String projectPath, String... propertiesKeyValues) {
+ BuildResult result = scan(projectPath, propertiesKeyValues);
+ assertThat(result.getStatus()).isZero();
+ return result;
+ }
+
+ private static BuildResult checkBuildFailed(String projectPath) {
+ BuildResult result = scan(projectPath);
+ assertThat(result.getStatus()).isNotEqualTo(0);
+ return result;
+ }
+
+ private static BuildResult scan(String projectPath, String... propertiesKeyValues) {
+ return orchestrator.executeBuildQuietly(
+ SonarRunner.create(ItUtils.projectDir(projectPath)).setProperties(propertiesKeyValues));
+ }
+
+ private static void setProperty(String key, String value) {
+ orchestrator.getServer().getAdminWsClient().update(new PropertyUpdateQuery(key, value));
+ }
+}
diff --git a/it/it-tests/src/test/java/batch/suite/TempFolderTest.java b/it/it-tests/src/test/java/batch/suite/TempFolderTest.java
new file mode 100644
index 00000000000..c422eb9d987
--- /dev/null
+++ b/it/it-tests/src/test/java/batch/suite/TempFolderTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package batch.suite;
+
+import util.ItUtils;
+
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.BuildResult;
+import com.sonar.orchestrator.build.SonarRunner;
+import com.sonar.orchestrator.locator.FileLocation;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+
+import java.io.File;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class TempFolderTest {
+
+ @ClassRule
+ public static Orchestrator orchestrator = BatchTestSuite.ORCHESTRATOR;
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ @Before
+ public void deleteData() {
+ orchestrator.resetData();
+ orchestrator.getServer().restoreProfile(FileLocation.ofClasspath("/batch/TempFolderTest/one-issue-per-line.xml"));
+ orchestrator.getServer().provisionProject("sample", "Sample");
+ orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
+ }
+
+ // SONAR-4748
+ @Test
+ public void should_create_in_temp_folder() {
+ File projectDir = ItUtils.projectDir("shared/xoo-sample");
+ BuildResult result = scan();
+
+ assertThat(result.getLogs()).doesNotContain("Creating temp directory:");
+ assertThat(result.getLogs()).doesNotContain("Creating temp file:");
+
+ result = scan("sonar.createTempFiles", "true");
+ assertThat(result.getLogs()).contains(
+ "Creating temp directory: " + projectDir.getAbsolutePath() + File.separator + ".sonar" + File.separator + ".sonartmp" + File.separator + "sonar-it");
+ assertThat(result.getLogs()).contains(
+ "Creating temp file: " + projectDir.getAbsolutePath() + File.separator + ".sonar" + File.separator + ".sonartmp" + File.separator + "sonar-it");
+
+ // Verify temp folder is deleted after analysis
+ assertThat(new File(projectDir, ".sonar/.sonartmp/sonar-it")).doesNotExist();
+ }
+
+ // SONAR-4748
+ @Test
+ public void should_not_use_system_tmp_dir() throws Exception {
+ String oldTmp = System.getProperty("java.io.tmpdir");
+ try {
+ File tmp = temp.newFolder();
+ assertThat(tmp.list()).isEmpty();
+
+ SonarRunner runner = configureRunner()
+ .setEnvironmentVariable("SONAR_RUNNER_OPTS", "-Djava.io.tmpdir=" + tmp.getAbsolutePath());
+ orchestrator.executeBuild(runner);
+
+ // TODO There is one remaining file waiting for SONARPLUGINS-3185
+ assertThat(tmp.list()).hasSize(1);
+ assertThat(tmp.list()[0]).matches("sonar-runner-batch(.*).jar");
+ } finally {
+ System.setProperty("java.io.tmpdir", oldTmp);
+ }
+ }
+
+ private BuildResult scan(String... props) {
+ SonarRunner runner = configureRunner(props);
+ return orchestrator.executeBuild(runner);
+ }
+
+ private SonarRunner configureRunner(String... props) {
+ return SonarRunner.create(ItUtils.projectDir("shared/xoo-sample"))
+ .setProperties(props);
+ }
+
+}
diff --git a/it/it-tests/src/test/java/duplications/suite/CrossProjectDuplicationsTest.java b/it/it-tests/src/test/java/duplications/suite/CrossProjectDuplicationsTest.java
new file mode 100644
index 00000000000..b4505ab1359
--- /dev/null
+++ b/it/it-tests/src/test/java/duplications/suite/CrossProjectDuplicationsTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package duplications.suite;
+
+import util.ItUtils;
+
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.MavenBuild;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.sonar.wsclient.services.Resource;
+import org.sonar.wsclient.services.ResourceQuery;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+
+@Ignore("Cross project duplications are temporary disabled, waiting to be reimplemented in CE or correctly implemented in the batch")
+public class CrossProjectDuplicationsTest {
+
+ @ClassRule
+ public static Orchestrator orchestrator = DuplicationsTestSuite.ORCHESTRATOR;
+
+ @Before
+ public void analyzeProjects() {
+ orchestrator.resetData();
+
+ MavenBuild build = MavenBuild.create(ItUtils.projectPom("duplications/cross-project/a"))
+ .setCleanSonarGoals()
+ .setProperty("sonar.cpd.cross_project", "true")
+ .setProperty("sonar.dynamicAnalysis", "false");
+ orchestrator.executeBuild(build);
+
+ build = MavenBuild.create(ItUtils.projectPom("duplications/cross-project/b"))
+ .setCleanSonarGoals()
+ .setProperty("sonar.cpd.cross_project", "true")
+ .setProperty("sonar.dynamicAnalysis", "false");
+ orchestrator.executeBuild(build);
+
+ build = MavenBuild.create(ItUtils.projectPom("duplications/cross-project/b"))
+ .setCleanSonarGoals()
+ .setProperty("sonar.cpd.cross_project", "true")
+ .setProperty("sonar.branch", "branch")
+ .setProperty("sonar.dynamicAnalysis", "false");
+ orchestrator.executeBuild(build);
+ }
+
+ @Test
+ public void testMeasures() throws Exception {
+
+ Resource project = getResource("com.sonarsource.it.samples.duplications:a");
+ assertThat(project, notNullValue());
+ assertThat(project.getMeasureIntValue("duplicated_lines"), is(0));
+
+ project = getResource("com.sonarsource.it.samples.duplications:b");
+ assertThat(project, notNullValue());
+ assertThat(project.getMeasureIntValue("duplicated_lines"), is(10));
+
+ project = getResource("com.sonarsource.it.samples.duplications:b:branch");
+ assertThat(project, notNullValue());
+ assertThat(project.getMeasureIntValue("duplicated_lines"), is(0));
+ }
+
+ private Resource getResource(String key) {
+ return orchestrator.getServer().getWsClient().find(ResourceQuery.createForMetrics(key, "duplicated_lines"));
+ }
+
+}
diff --git a/it/it-tests/src/test/java/duplications/suite/DuplicationsTest.java b/it/it-tests/src/test/java/duplications/suite/DuplicationsTest.java
new file mode 100644
index 00000000000..9f71da26a03
--- /dev/null
+++ b/it/it-tests/src/test/java/duplications/suite/DuplicationsTest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package duplications.suite;
+
+import util.ItUtils;
+
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.MavenBuild;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.wsclient.services.Resource;
+import org.sonar.wsclient.services.ResourceQuery;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.junit.Assert.assertThat;
+
+public class DuplicationsTest {
+
+ private static final String DUPLICATIONS = "com.sonarsource.it.samples:duplications";
+ private static final String DUPLICATIONS_WITH_EXCLUSIONS = "com.sonarsource.it.samples:duplications-with-exclusions";
+ @ClassRule
+ public static Orchestrator orchestrator = DuplicationsTestSuite.ORCHESTRATOR;
+
+ @BeforeClass
+ public static void init() {
+ orchestrator.resetData();
+
+ MavenBuild build = MavenBuild.create(ItUtils.projectPom("duplications/file-duplications"))
+ .setCleanPackageSonarGoals();
+ orchestrator.executeBuild(build);
+
+ // Use a new project key to avoid conflict with other tests
+ String projectKey = DUPLICATIONS_WITH_EXCLUSIONS;
+ build = MavenBuild.create(ItUtils.projectPom("duplications/file-duplications"))
+ .setCleanPackageSonarGoals()
+ .setProperties("sonar.projectKey", projectKey,
+ "sonar.cpd.exclusions", "**/Class*");
+ orchestrator.executeBuild(build);
+
+ }
+
+ @Test
+ public void duplicated_lines_within_same_class() {
+ Resource file = getResource(DUPLICATIONS + ":src/main/java/duplicated_lines_within_same_class/DuplicatedLinesInSameClass.java");
+ assertThat(file, not(nullValue()));
+ assertThat(file.getMeasureValue("duplicated_blocks"), is(2.0));
+ assertThat(file.getMeasureValue("duplicated_lines"), is(27.0 * 2)); // 2 blocks with 27 lines
+ assertThat(file.getMeasureValue("duplicated_files"), is(1.0));
+ assertThat(file.getMeasureValue("duplicated_lines_density"), is(60.0));
+ }
+
+ @Test
+ public void duplicated_same_lines_within_3_classes() {
+ Resource file1 = getResource(DUPLICATIONS + ":src/main/java/duplicated_same_lines_within_3_classes/Class1.java");
+ assertThat(file1, not(nullValue()));
+ assertThat(file1.getMeasureValue("duplicated_blocks"), is(1.0));
+ assertThat(file1.getMeasureValue("duplicated_lines"), is(29.0));
+ assertThat(file1.getMeasureValue("duplicated_files"), is(1.0));
+ assertThat(file1.getMeasureValue("duplicated_lines_density"), is(47.5));
+
+ Resource file2 = getResource(DUPLICATIONS + ":src/main/java/duplicated_same_lines_within_3_classes/Class2.java");
+ assertThat(file2, not(nullValue()));
+ assertThat(file2.getMeasureValue("duplicated_blocks"), is(1.0));
+ assertThat(file2.getMeasureValue("duplicated_lines"), is(29.0));
+ assertThat(file2.getMeasureValue("duplicated_files"), is(1.0));
+ assertThat(file2.getMeasureValue("duplicated_lines_density"), is(48.3));
+
+ Resource file3 = getResource(DUPLICATIONS + ":src/main/java/duplicated_same_lines_within_3_classes/Class3.java");
+ assertThat(file3, not(nullValue()));
+ assertThat(file3.getMeasureValue("duplicated_blocks"), is(1.0));
+ assertThat(file3.getMeasureValue("duplicated_lines"), is(29.0));
+ assertThat(file3.getMeasureValue("duplicated_files"), is(1.0));
+ assertThat(file3.getMeasureValue("duplicated_lines_density"), is(46.0));
+
+ Resource pkg = getResource(DUPLICATIONS + ":src/main/java/duplicated_same_lines_within_3_classes");
+ assertThat(pkg, not(nullValue()));
+ assertThat(pkg.getMeasureValue("duplicated_blocks"), is(3.0));
+ assertThat(pkg.getMeasureValue("duplicated_lines"), is(29.0 * 3)); // 3 blocks with 29 lines
+ assertThat(pkg.getMeasureValue("duplicated_files"), is(3.0));
+ assertThat(pkg.getMeasureValue("duplicated_lines_density"), is(47.3));
+ }
+
+ @Test
+ public void duplicated_lines_within_package() {
+ Resource file1 = getResource(DUPLICATIONS + ":src/main/java/duplicated_lines_within_package/DuplicatedLinesInSamePackage1.java");
+ assertThat(file1, not(nullValue()));
+ assertThat(file1.getMeasureValue("duplicated_blocks"), is(4.0));
+ assertThat(file1.getMeasureValue("duplicated_lines"), is(72.0));
+ assertThat(file1.getMeasureValue("duplicated_files"), is(1.0));
+ assertThat(file1.getMeasureValue("duplicated_lines_density"), is(58.1));
+
+ Resource file2 = getResource(DUPLICATIONS + ":src/main/java/duplicated_lines_within_package/DuplicatedLinesInSamePackage2.java");
+ assertThat(file2, not(nullValue()));
+ assertThat(file2.getMeasureValue("duplicated_blocks"), is(3.0));
+ assertThat(file2.getMeasureValue("duplicated_lines"), is(58.0));
+ assertThat(file2.getMeasureValue("duplicated_files"), is(1.0));
+ assertThat(file2.getMeasureValue("duplicated_lines_density"), is(64.4));
+
+ Resource pkg = getResource(DUPLICATIONS + ":src/main/java/duplicated_lines_within_package");
+ assertThat(pkg, not(nullValue()));
+ assertThat(pkg.getMeasureValue("duplicated_blocks"), is(4.0 + 3.0));
+ assertThat(pkg.getMeasureValue("duplicated_lines"), is(72.0 + 58.0));
+ assertThat(pkg.getMeasureValue("duplicated_files"), is(2.0));
+ assertThat(pkg.getMeasureValue("duplicated_lines_density"), is(60.7));
+ }
+
+ @Test
+ public void duplicated_lines_with_other_package() {
+ Resource file1 = getResource(DUPLICATIONS + ":src/main/java/duplicated_lines_with_other_package1/DuplicatedLinesWithOtherPackage.java");
+ assertThat(file1, not(nullValue()));
+ assertThat(file1.getMeasureValue("duplicated_blocks"), is(1.0));
+ assertThat(file1.getMeasureValue("duplicated_lines"), is(36.0));
+ assertThat(file1.getMeasureValue("duplicated_files"), is(1.0));
+ assertThat(file1.getMeasureValue("duplicated_lines_density"), is(60.0));
+
+ Resource pkg1 = getResource(DUPLICATIONS + ":src/main/java/duplicated_lines_with_other_package1");
+ assertThat(pkg1, not(nullValue()));
+ assertThat(pkg1.getMeasureValue("duplicated_blocks"), is(1.0));
+ assertThat(pkg1.getMeasureValue("duplicated_lines"), is(36.0));
+ assertThat(pkg1.getMeasureValue("duplicated_files"), is(1.0));
+ assertThat(pkg1.getMeasureValue("duplicated_lines_density"), is(60.0));
+
+ Resource file2 = getResource(DUPLICATIONS + ":src/main/java/duplicated_lines_with_other_package2/DuplicatedLinesWithOtherPackage.java");
+ assertThat(file2, not(nullValue()));
+ assertThat(file2.getMeasureValue("duplicated_blocks"), is(1.0));
+ assertThat(file2.getMeasureValue("duplicated_lines"), is(36.0));
+ assertThat(file2.getMeasureValue("duplicated_files"), is(1.0));
+ assertThat(file2.getMeasureValue("duplicated_lines_density"), is(60.0));
+
+ Resource pkg2 = getResource(DUPLICATIONS + ":src/main/java/duplicated_lines_with_other_package2");
+ assertThat(pkg2, not(nullValue()));
+ assertThat(pkg2.getMeasureValue("duplicated_blocks"), is(1.0));
+ assertThat(pkg2.getMeasureValue("duplicated_lines"), is(36.0));
+ assertThat(pkg2.getMeasureValue("duplicated_files"), is(1.0));
+ assertThat(pkg2.getMeasureValue("duplicated_lines_density"), is(60.0));
+ }
+
+ @Test
+ public void consolidation() {
+ Resource project = getResource(DUPLICATIONS);
+ assertThat(project, not(nullValue()));
+ assertThat(project.getMeasureValue("duplicated_blocks"), is(14.0));
+ assertThat(project.getMeasureValue("duplicated_lines"), is(343.0));
+ assertThat(project.getMeasureValue("duplicated_files"), is(8.0));
+ assertThat(project.getMeasureValue("duplicated_lines_density"), is(56.4));
+ }
+
+ /**
+ * SONAR-3108
+ */
+ @Test
+ public void use_duplication_exclusions() {
+ Resource project = getResource(DUPLICATIONS_WITH_EXCLUSIONS);
+ assertThat(project, not(nullValue()));
+ assertThat(project.getMeasureValue("duplicated_blocks"), is(11.0));
+ assertThat(project.getMeasureValue("duplicated_lines"), is(256.0));
+ assertThat(project.getMeasureValue("duplicated_files"), is(5.0));
+ assertThat(project.getMeasureValue("duplicated_lines_density"), is(42.1));
+ }
+
+ private Resource getResource(String key) {
+ return orchestrator.getServer().getWsClient()
+ .find(ResourceQuery.createForMetrics(key, "duplicated_lines", "duplicated_blocks", "duplicated_files", "duplicated_lines_density"));
+ }
+
+}
diff --git a/it/it-tests/src/test/java/duplications/suite/DuplicationsTestSuite.java b/it/it-tests/src/test/java/duplications/suite/DuplicationsTestSuite.java
new file mode 100644
index 00000000000..4cffa398e97
--- /dev/null
+++ b/it/it-tests/src/test/java/duplications/suite/DuplicationsTestSuite.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package duplications.suite;
+
+import com.sonar.orchestrator.Orchestrator;
+import org.junit.ClassRule;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ CrossProjectDuplicationsTest.class, DuplicationsTest.class
+})
+public class DuplicationsTestSuite {
+
+ @ClassRule
+ public static final Orchestrator ORCHESTRATOR = Orchestrator.builderEnv()
+ .setOrchestratorProperty("javaVersion", "LATEST_RELEASE").addPlugin("java")
+ .build();
+}
diff --git a/it/it-tests/src/test/java/exclusions/suite/ExclusionsTestSuite.java b/it/it-tests/src/test/java/exclusions/suite/ExclusionsTestSuite.java
new file mode 100644
index 00000000000..ff89627c2c9
--- /dev/null
+++ b/it/it-tests/src/test/java/exclusions/suite/ExclusionsTestSuite.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package exclusions.suite;
+
+import util.ItUtils;
+
+import com.sonar.orchestrator.Orchestrator;
+import org.junit.ClassRule;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ FileExclusionsTest.class, IssueExclusionsTest.class
+})
+public class ExclusionsTestSuite {
+
+ @ClassRule
+ public static final Orchestrator ORCHESTRATOR = Orchestrator.builderEnv()
+ .addPlugin(ItUtils.xooPlugin())
+ .build();
+}
diff --git a/it/it-tests/src/test/java/exclusions/suite/FileExclusionsTest.java b/it/it-tests/src/test/java/exclusions/suite/FileExclusionsTest.java
new file mode 100644
index 00000000000..191adcab25d
--- /dev/null
+++ b/it/it-tests/src/test/java/exclusions/suite/FileExclusionsTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package exclusions.suite;
+
+import util.ItUtils;
+
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.SonarRunner;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.wsclient.services.Resource;
+import org.sonar.wsclient.services.ResourceQuery;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class FileExclusionsTest {
+ static final String PROJECT = "exclusions";
+
+ @ClassRule
+ public static Orchestrator orchestrator = ExclusionsTestSuite.ORCHESTRATOR;
+
+ @Before
+ public void resetData() {
+ orchestrator.resetData();
+ }
+
+ @Test
+ public void exclude_source_files() {
+ scan(
+ "sonar.global.exclusions", "**/*Ignore*.xoo",
+ "sonar.exclusions", "**/*Exclude*.xoo,src/main/xoo/org/sonar/tests/packageToExclude/**",
+ "sonar.test.exclusions", "**/ClassTwoTest.xoo");
+
+ Resource project = projectWithMetrics("ncloc", "files", "directories");
+
+ assertThat(project.getMeasureIntValue("files")).isEqualTo(4);
+ assertThat(project.getMeasureIntValue("ncloc")).isEqualTo(60);
+ assertThat(project.getMeasureIntValue("directories")).isEqualTo(3);
+ }
+
+ /**
+ * SONAR-2444 / SONAR-3758
+ */
+ @Test
+ public void exclude_test_files() {
+ scan(
+ "sonar.global.exclusions", "**/*Ignore*.xoo",
+ "sonar.exclusions", "**/*Exclude*.xoo,org/sonar/tests/packageToExclude/**",
+ "sonar.test.exclusions", "**/ClassTwoTest.xoo");
+
+ List<Resource> testFiles = orchestrator.getServer().getWsClient()
+ .findAll(new ResourceQuery(PROJECT).setQualifiers("UTS").setDepth(-1));
+
+ assertThat(testFiles).hasSize(2);
+ assertThat(testFiles).extracting("name").doesNotContain("ClassTwoTest.xoo");
+ }
+
+ /**
+ * SONAR-1896
+ */
+ @Test
+ public void include_source_files() {
+ scan(
+ "sonar.dynamicAnalysis", "false",
+ "sonar.inclusions", "**/*One.xoo,**/*Two.xoo");
+
+ Resource project = projectWithMetrics("files");
+ assertThat(project.getMeasureIntValue("files")).isEqualTo(2);
+
+ List<Resource> sourceFiles = orchestrator.getServer().getWsClient()
+ .findAll(new ResourceQuery(PROJECT).setQualifiers("FIL").setDepth(-1));
+
+ assertThat(sourceFiles).hasSize(2);
+ assertThat(sourceFiles).extracting("name").containsOnly("ClassOne.xoo", "ClassTwo.xoo");
+ }
+
+ /**
+ * SONAR-1896
+ */
+ @Test
+ public void include_test_files() {
+ scan("sonar.test.inclusions", "src/test/xoo/**/*One*.xoo,src/test/xoo/**/*Two*.xoo");
+
+ Resource project = projectWithMetrics("tests");
+ assertThat(project.getMeasureIntValue("tests")).isEqualTo(2);
+
+ List<Resource> testFiles = orchestrator.getServer().getWsClient()
+ .findAll(new ResourceQuery(PROJECT).setQualifiers("UTS").setDepth(-1));
+
+ assertThat(testFiles).hasSize(2);
+ assertThat(testFiles).extracting("name").containsOnly("ClassOneTest.xoo", "ClassTwoTest.xoo");
+ }
+
+ /**
+ * SONAR-2760
+ */
+ @Test
+ public void include_and_exclude_files_by_absolute_path() {
+ scan(
+ // includes everything except ClassOnDefaultPackage
+ "sonar.inclusions", "file:**/src/main/xoo/org/**/*.xoo",
+
+ // exclude ClassThree and ClassToExclude
+ "sonar.exclusions", "file:**/src/main/xoo/org/**/packageToExclude/*.xoo,file:**/src/main/xoo/org/**/*Exclude.xoo");
+
+ List<Resource> sourceFiles = orchestrator.getServer().getWsClient()
+ .findAll(new ResourceQuery(PROJECT).setQualifiers("FIL").setDepth(-1));
+
+ assertThat(sourceFiles).hasSize(4);
+ assertThat(sourceFiles).extracting("name").containsOnly("ClassOne.xoo", "ClassToIgnoreGlobally.xoo", "ClassTwo.xoo", "NoSonarComment.xoo");
+ }
+
+ static Resource projectWithMetrics(String... metricKeys) {
+ return orchestrator.getServer().getWsClient().find(ResourceQuery.createForMetrics(PROJECT, metricKeys));
+ }
+
+ private void scan(String... properties) {
+ SonarRunner build = SonarRunner
+ .create(ItUtils.projectDir("exclusions/exclusions"))
+ .setProperties(properties);
+ orchestrator.executeBuild(build);
+ }
+}
diff --git a/it/it-tests/src/test/java/exclusions/suite/IssueExclusionsTest.java b/it/it-tests/src/test/java/exclusions/suite/IssueExclusionsTest.java
new file mode 100644
index 00000000000..12bbfa23707
--- /dev/null
+++ b/it/it-tests/src/test/java/exclusions/suite/IssueExclusionsTest.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package exclusions.suite;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import util.ItUtils;
+
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.BuildResult;
+import com.sonar.orchestrator.build.SonarRunner;
+import com.sonar.orchestrator.locator.FileLocation;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.wsclient.services.Resource;
+import org.sonar.wsclient.services.ResourceQuery;
+
+public class IssueExclusionsTest {
+
+ private static final String PROJECT_KEY = "com.sonarsource.it.samples:multi-modules-exclusions";
+ private static final String PROJECT_DIR = "exclusions/xoo-multi-modules";
+
+ @ClassRule
+ public static Orchestrator orchestrator = ExclusionsTestSuite.ORCHESTRATOR;
+
+ @Before
+ public void resetData() {
+ orchestrator.resetData();
+ }
+
+ @Test
+ public void should_not_exclude_anything() {
+ scan();
+
+ checkIssueCountBySeverity(67, 2, 57, 4, 0, 4);
+ }
+
+ @Test
+ public void should_ignore_all_files() {
+ scan(
+ "sonar.issue.ignore.multicriteria", "1",
+ "sonar.issue.ignore.multicriteria.1.resourceKey", "**/*.xoo",
+ "sonar.issue.ignore.multicriteria.1.ruleKey", "*");
+
+ checkIssueCountBySeverity(4, 0, 0, 0, 0, 4);
+ }
+
+ @Test
+ public void should_enforce_only_on_one_file() {
+ scan(
+ "sonar.issue.enforce.multicriteria", "1",
+ "sonar.issue.enforce.multicriteria.1.resourceKey", "**/HelloA1.xoo",
+ "sonar.issue.enforce.multicriteria.1.ruleKey", "*");
+
+ checkIssueCountBySeverity(
+ 1 /* tag */+ 18 /* lines in HelloA1.xoo */+ 1 /* file */,
+ 0 + 1,
+ 0 + 18,
+ 0 + 1,
+ 0,
+ 0);
+ }
+
+ @Test
+ public void should_enforce_on_two_files_with_same_rule() {
+ scan(
+ "sonar.issue.enforce.multicriteria", "1,2",
+ "sonar.issue.enforce.multicriteria.1.resourceKey", "**/HelloA1.xoo",
+ "sonar.issue.enforce.multicriteria.1.ruleKey", "*",
+ "sonar.issue.enforce.multicriteria.2.resourceKey", "**/HelloA2.xoo",
+ "sonar.issue.enforce.multicriteria.2.ruleKey", "*");
+
+ checkIssueCountBySeverity(
+ 2 /* tags */+ 18 /* lines in HelloA1.xoo */+ 15 /* lines in HelloA2.xoo */+ 2 /* files */,
+ 0 + 2,
+ 0 + 18 + 15,
+ 0 + 2,
+ 0,
+ 0);
+ }
+
+ @Test
+ public void should_enforce_on_two_files_with_different_rule() {
+ scan(
+ "sonar.issue.enforce.multicriteria", "1,2",
+ "sonar.issue.enforce.multicriteria.1.resourceKey", "**/HelloA1.xoo",
+ "sonar.issue.enforce.multicriteria.1.ruleKey", "xoo:OneIssuePerLine",
+ "sonar.issue.enforce.multicriteria.2.resourceKey", "**/HelloA2.xoo",
+ "sonar.issue.enforce.multicriteria.2.ruleKey", "xoo:HasTag");
+
+ checkIssueCountBySeverity(
+ 1 /* tag in HelloA2 */+ 18 /* lines in HelloA1.xoo */+ 4 /* files */+ 4 /* modules */,
+ 0 + 1,
+ 0 + 18,
+ 4,
+ 0,
+ 4);
+ }
+
+ @Test
+ public void should_ignore_files_with_regexp() {
+ scan(
+ "sonar.issue.ignore.allfile", "1",
+ "sonar.issue.ignore.allfile.1.fileRegexp", "EXTERMINATE-ALL-ISSUES");
+
+ checkIssueCountBySeverity(
+ 67 - 1 /* tag */- 18 /* lines in HelloA1.xoo */- 1 /* file */,
+ 2 - 1,
+ 57 - 18,
+ 4 - 1,
+ 0,
+ 4);
+ }
+
+ @Test
+ public void should_ignore_block_with_regexp() {
+ scan(
+ "sonar.issue.ignore.block", "1",
+ "sonar.issue.ignore.block.1.beginBlockRegexp", "MUTE-SONAR",
+ "sonar.issue.ignore.block.1.endBlockRegexp", "UNMUTE-SONAR");
+
+ checkIssueCountBySeverity(
+ 67 - 1 /* tag */- 5 /* lines in HelloA2.xoo */,
+ 2 - 1,
+ 57 - 5,
+ 4,
+ 0,
+ 4);
+ }
+
+ @Test
+ public void should_ignore_to_end_of_file() {
+ scan(
+ "sonar.issue.ignore.block", "1",
+ "sonar.issue.ignore.block.1.beginBlockRegexp", "MUTE-SONAR",
+ "sonar.issue.ignore.block.1.endBlockRegexp", "");
+
+ checkIssueCountBySeverity(
+ 67 - 1 /* tag */- 7 /* remaining lines in HelloA2.xoo */,
+ 2 - 1,
+ 57 - 7,
+ 4,
+ 0,
+ 4);
+ }
+
+ @Test
+ public void should_ignore_one_per_line_on_single_package() {
+ scan(
+ "sonar.issue.ignore.multicriteria", "1",
+ "sonar.issue.ignore.multicriteria.1.resourceKey", "**/com/sonar/it/samples/modules/a1/*",
+ "sonar.issue.ignore.multicriteria.1.ruleKey", "xoo:OneIssuePerLine");
+
+ checkIssueCountBySeverity(
+ 67 - 18 /* lines in HelloA1.xoo */,
+ 2,
+ 57 - 18,
+ 4,
+ 0,
+ 4);
+ }
+
+ @Test
+ public void should_apply_exclusions_from_multiple_sources() {
+ scan(
+ "sonar.issue.ignore.allfile", "1",
+ "sonar.issue.ignore.allfile.1.fileRegexp", "EXTERMINATE-ALL-ISSUES",
+ "sonar.issue.ignore.block", "1",
+ "sonar.issue.ignore.block.1.beginBlockRegexp", "MUTE-SONAR",
+ "sonar.issue.ignore.block.1.endBlockRegexp", "UNMUTE-SONAR",
+ "sonar.issue.ignore.multicriteria", "1",
+ "sonar.issue.ignore.multicriteria.1.resourceKey", "**/com/sonar/it/samples/modules/b1/*",
+ "sonar.issue.ignore.multicriteria.1.ruleKey", "xoo:OneIssuePerLine");
+
+ checkIssueCountBySeverity(
+ 67 - 1 /* tag in HelloA1.xoo */- 1 /* tag in HelloA2.xoo */
+ - 18 /* lines in HelloA1.xoo */- 5 /* lines in HelloA2.xoo */- 12 /* lines in HelloB1.xoo */
+ - 1 /* HelloA1.xoo file */,
+ 0,
+ 57 - 18 - 5 - 12,
+ 4 - 1,
+ 0,
+ 4);
+ }
+
+ @Test
+ public void should_log_missing_resource_key() {
+ checkAnalysisFails(
+ "sonar.issue.ignore.multicriteria", "1",
+ "sonar.issue.ignore.multicriteria.1.resourceKey", "",
+ "sonar.issue.ignore.multicriteria.1.ruleKey", "*");
+ }
+
+ @Test
+ public void should_log_missing_rule_key() {
+ checkAnalysisFails(
+ "sonar.issue.ignore.multicriteria", "1",
+ "sonar.issue.ignore.multicriteria.1.resourceKey", "*",
+ "sonar.issue.ignore.multicriteria.1.ruleKey", "");
+ }
+
+ @Test
+ public void should_log_missing_block_start() {
+ checkAnalysisFails(
+ "sonar.issue.ignore.block", "1",
+ "sonar.issue.ignore.block.1.beginBlockRegexp", "",
+ "sonar.issue.ignore.block.1.endBlockRegexp", "UNMUTE-SONAR");
+ }
+
+ @Test
+ public void should_log_missing_whole_file_regexp() {
+ checkAnalysisFails(
+ "sonar.issue.ignore.allfile", "1",
+ "sonar.issue.ignore.allfile.1.fileRegexp", "");
+ }
+
+ protected BuildResult scan(String... properties) {
+ orchestrator.getServer().restoreProfile(FileLocation.ofClasspath("/exclusions/IssueExclusionsTest/with-many-rules.xml"));
+ orchestrator.getServer().provisionProject("com.sonarsource.it.samples:multi-modules-exclusions",
+ "Sonar :: Integration Tests :: Multi-modules With Exclusions");
+ orchestrator.getServer().associateProjectToQualityProfile("com.sonarsource.it.samples:multi-modules-exclusions", "xoo", "with-many-rules");
+
+ SonarRunner scan = SonarRunner.create(ItUtils.projectDir(PROJECT_DIR))
+ .setProperties("sonar.cpd.skip", "true")
+ .setProperties(properties)
+ .setProperties("sonar.verbose", "true");
+ return orchestrator.executeBuildQuietly(scan);
+ }
+
+ private void checkIssueCountBySeverity(int total, int taggedXoo, int perLine, int perFile, int blocker, int perModule) {
+ Resource project = orchestrator.getServer().getWsClient()
+ .find(ResourceQuery.createForMetrics(PROJECT_KEY, "violations", "info_violations", "minor_violations", "major_violations",
+ "blocker_violations", "critical_violations"));
+ assertThat(project.getMeasureIntValue("violations")).isEqualTo(total);
+ assertThat(project.getMeasureIntValue("info_violations")).isEqualTo(taggedXoo); // Has tag 'xoo'
+ assertThat(project.getMeasureIntValue("minor_violations")).isEqualTo(perLine); // One per line
+ assertThat(project.getMeasureIntValue("major_violations")).isEqualTo(perFile); // One per file
+ assertThat(project.getMeasureIntValue("blocker_violations")).isEqualTo(blocker);
+ assertThat(project.getMeasureIntValue("critical_violations")).isEqualTo(perModule); // One per module
+ }
+
+ private void checkAnalysisFails(String... properties) {
+ BuildResult buildResult = scan(properties);
+ assertThat(buildResult.getStatus()).isNotEqualTo(0);
+ assertThat(buildResult.getLogs().indexOf("SonarException")).isGreaterThan(0);
+ }
+}
diff --git a/it/it-tests/src/test/java/plugins/PluginsTest.java b/it/it-tests/src/test/java/plugins/PluginsTest.java
index fb0c57b403b..f0cf76e83ea 100644
--- a/it/it-tests/src/test/java/plugins/PluginsTest.java
+++ b/it/it-tests/src/test/java/plugins/PluginsTest.java
@@ -107,7 +107,7 @@ public class PluginsTest {
@Test
public void preview_analysis_of_project_with_all_supported_languages() {
SonarRunner analysis = newAnalysis();
- analysis.setProperty("sonar.analysis.mode", "preview");
+ analysis.setProperty("sonar.analysis.mode", "issues");
analysis.setProperty("sonar.preview.excludePlugins", Joiner.on(",").join(DISABLED_PLUGINS_FOR_PREVIEW_MODE));
BuildResult result = orchestrator.executeBuildQuietly(analysis);
if (result.getStatus() != 0) {
diff --git a/it/it-tests/src/test/java/util/ItUtils.java b/it/it-tests/src/test/java/util/ItUtils.java
index f0392cf732c..322fabb9117 100644
--- a/it/it-tests/src/test/java/util/ItUtils.java
+++ b/it/it-tests/src/test/java/util/ItUtils.java
@@ -4,10 +4,22 @@ package util;/*
* mailto:contact AT sonarsource DOT com
*/
+import com.sonar.orchestrator.build.BuildResult;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.sonar.orchestrator.locator.FileLocation;
+
import java.io.File;
+import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static org.assertj.core.api.Assertions.fail;
+
+import static org.assertj.core.api.Assertions.assertThat;
import org.apache.commons.io.FileUtils;
public class ItUtils {
@@ -66,4 +78,51 @@ public class ItUtils {
}
return FileLocation.of(file);
}
+
+ /**
+ * Locate the pom file of a sample project
+ *
+ * @param relativePath project path related to the directory it/it-projects, for example "qualitygate/xoo-sample"
+ */
+ public static File projectPom(String projectName) {
+ File pom = new File(projectDir(projectName), "pom.xml");
+ if (!pom.exists() || !pom.isFile()) {
+ throw new IllegalStateException("pom file does not exist: " + pom.getAbsolutePath());
+ }
+ return pom;
+ }
+
+ public static String sanitizeTimezones(String s) {
+ return s.replaceAll("[\\+\\-]\\d\\d\\d\\d", "+0000");
+ }
+
+ public static JSONObject getJSONReport(BuildResult result) {
+ Pattern pattern = Pattern.compile("Export issues to (.*?).json");
+ Matcher m = pattern.matcher(result.getLogs());
+ if (m.find()) {
+ String s = m.group(1);
+ File path = new File(s + ".json");
+ assertThat(path).exists();
+ try {
+ return (JSONObject) JSONValue.parse(FileUtils.readFileToString(path));
+ } catch (IOException e) {
+ throw new RuntimeException("Unable to read JSON report", e);
+ }
+ }
+ fail("Unable to locate json report");
+ return null;
+ }
+
+ public static int countIssuesInJsonReport(BuildResult result, boolean onlyNews) {
+ JSONObject obj = getJSONReport(result);
+ JSONArray issues = (JSONArray) obj.get("issues");
+ int count = 0;
+ for (Object issue : issues) {
+ JSONObject jsonIssue = (JSONObject) issue;
+ if (!onlyNews || (Boolean) jsonIssue.get("isNew")) {
+ count++;
+ }
+ }
+ return count;
+ }
}
diff --git a/it/it-tests/src/test/resources/batch/BatchTest/one-issue-per-line.xml b/it/it-tests/src/test/resources/batch/BatchTest/one-issue-per-line.xml
new file mode 100644
index 00000000000..7bb4ed5593a
--- /dev/null
+++ b/it/it-tests/src/test/resources/batch/BatchTest/one-issue-per-line.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- Generated by Sonar -->
+<profile>
+ <name>one-issue-per-line</name>
+ <language>xoo</language>
+ <rules>
+ <rule>
+ <repositoryKey>xoo</repositoryKey>
+ <key>OneIssuePerLine</key>
+ <priority>MAJOR</priority>
+ </rule>
+ </rules>
+</profile> \ No newline at end of file
diff --git a/it/it-tests/src/test/resources/batch/IssueJsonReportTest/no-server-analysis.json b/it/it-tests/src/test/resources/batch/IssueJsonReportTest/no-server-analysis.json
new file mode 100644
index 00000000000..353b352f203
--- /dev/null
+++ b/it/it-tests/src/test/resources/batch/IssueJsonReportTest/no-server-analysis.json
@@ -0,0 +1,174 @@
+{
+ "version": "<SONAR_VERSION>",
+ "issues": [
+ {
+ "key": "05652201-6f89-4f07-ba03-1df08eae0d55",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 6,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": true,
+ "creationDate": "2013-05-02T00:00:00+0200"
+ },
+ {
+ "key": "0746cf8f-0b67-4da8-82fc-36a6717c1f81",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 5,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": true,
+ "creationDate": "2013-05-02T00:00:00+0200"
+ },
+ {
+ "key": "0e9c20e2-567b-4c7a-b1e7-b9e5648dbfc5",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 13,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": true,
+ "creationDate": "2013-05-02T00:00:00+0200"
+ },
+ {
+ "key": "107fb325-ddda-43c6-9fde-1e7250571ef8",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 1,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": true,
+ "creationDate": "2013-05-02T00:00:00+0200"
+ },
+ {
+ "key": "226c71cf-0a86-43af-8281-6df0308eac92",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 3,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": true,
+ "creationDate": "2013-05-02T00:00:00+0200"
+ },
+ {
+ "key": "55c9705c-6509-48c6-9773-0437ab60be42",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 4,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": true,
+ "creationDate": "2013-05-02T00:00:00+0200"
+ },
+ {
+ "key": "5d653e95-16e2-4ee7-aac5-91ab8c3aebd6",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 12,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": true,
+ "creationDate": "2013-05-02T00:00:00+0200"
+ },
+ {
+ "key": "86056a4b-1813-4a10-937f-082e3f810152",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 10,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": true,
+ "creationDate": "2013-05-02T00:00:00+0200"
+ },
+ {
+ "key": "906f38ad-ada7-4088-80fe-3fc3b8532ad6",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 2,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": true,
+ "creationDate": "2013-05-02T00:00:00+0200"
+ },
+ {
+ "key": "9328fb3c-6fab-489f-a8ad-eb8277dd7bf7",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 9,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": true,
+ "creationDate": "2013-05-02T00:00:00+0200"
+ },
+ {
+ "key": "9980ca57-dfc4-431c-9a45-7ee9d397078a",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 11,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": true,
+ "creationDate": "2013-05-02T00:00:00+0200"
+ },
+ {
+ "key": "ccf5a264-bbe0-4459-97dc-acc0e323c4bb",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 7,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": true,
+ "creationDate": "2013-05-02T00:00:00+0200"
+ },
+ {
+ "key": "ead82961-2724-4d85-b2af-f810206b0ab1",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 8,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": true,
+ "creationDate": "2013-05-02T00:00:00+0200"
+ }
+ ],
+ "components": [
+ {
+ "key": "sample"
+ },
+ {
+ "key": "sample:src/main/xoo/sample",
+ "path": "src/main/xoo/sample",
+ "moduleKey": "sample"
+ },
+ {
+ "key": "sample:src/main/xoo/sample/Sample.xoo",
+ "path": "src/main/xoo/sample/Sample.xoo",
+ "moduleKey": "sample",
+ "status": "ADDED"
+ }
+ ],
+ "rules": [
+ {
+ "key": "xoo:OneIssuePerLine",
+ "rule": "OneIssuePerLine",
+ "repository": "xoo",
+ "name": "One Issue Per Line"
+ }
+ ],
+ "users": [ ]
+
+} \ No newline at end of file
diff --git a/it/it-tests/src/test/resources/batch/IssueJsonReportTest/one-issue-per-line.xml b/it/it-tests/src/test/resources/batch/IssueJsonReportTest/one-issue-per-line.xml
new file mode 100644
index 00000000000..7bb4ed5593a
--- /dev/null
+++ b/it/it-tests/src/test/resources/batch/IssueJsonReportTest/one-issue-per-line.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- Generated by Sonar -->
+<profile>
+ <name>one-issue-per-line</name>
+ <language>xoo</language>
+ <rules>
+ <rule>
+ <repositoryKey>xoo</repositoryKey>
+ <key>OneIssuePerLine</key>
+ <priority>MAJOR</priority>
+ </rule>
+ </rules>
+</profile> \ No newline at end of file
diff --git a/it/it-tests/src/test/resources/batch/IssueJsonReportTest/report-on-root-module.json b/it/it-tests/src/test/resources/batch/IssueJsonReportTest/report-on-root-module.json
new file mode 100644
index 00000000000..41a22d1a963
--- /dev/null
+++ b/it/it-tests/src/test/resources/batch/IssueJsonReportTest/report-on-root-module.json
@@ -0,0 +1 @@
+{"version":"5.2-SNAPSHOT","issues":[{"key":"02863c43-1063-4f1c-9a5f-90f96a3b73a2","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo","line":4,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"1f7826f2-c615-462b-90ef-a597482a1954","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo","line":11,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"3a55c080-5358-4f38-9764-15f253092db9","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo","line":2,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"4960db5a-0a63-4555-9e54-1555ae59bef6","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo","line":5,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"497c4cb1-51d1-4114-b27d-648160179617","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo","line":1,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"4fac27de-afa9-4eca-beba-c3ca6c562a03","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo","line":15,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"5f772c56-75d0-4c53-b016-d998df46b02c","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo","line":16,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"83767a3b-9819-4450-a512-9313c1b11522","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo","line":13,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"93dc780d-6a6c-4bb1-a6c1-729eb3fe3d1c","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo","line":9,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"a236746f-12d1-4a17-becb-af6fb0b34d76","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo","line":12,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"a4953d8c-3f25-4bb8-8d62-64e9fc73c74c","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo","line":3,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"bd610f56-7977-437e-a6ac-199db4da738b","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo","line":8,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"d997cfbe-d6c7-42a5-bc09-a02374d017f1","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo","line":14,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"e4fa51d5-5c10-4b91-bc46-eaf22e10d8b3","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo","line":6,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"e58db2c5-7055-4d86-b866-74bca942d09e","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo","line":10,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"fb4aaeeb-50e0-4b92-966a-f90c06982070","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo","line":7,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"08efacb9-ea82-49aa-b909-3e2535be57bb","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2:src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo","line":2,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"0d1425a6-ea1a-4599-b6e4-cb3351a27225","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2:src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo","line":12,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"0e9aab93-300b-492c-a28f-e0d3d3e02319","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2:src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo","line":8,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"10f34bbd-1d60-4003-83b0-84f6ff723f68","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2:src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo","line":17,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"123a65dc-a3d7-4697-8dbc-6c9f8fef7988","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2:src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo","line":19,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"177e847b-240d-447e-aa72-490ffe57e748","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2:src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo","line":4,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"2d013a53-04c1-4651-8b2a-b0e3cd24bd1a","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2:src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo","line":3,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"57f25741-fea5-431b-aed9-d74737ec5f57","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2:src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo","line":21,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"5f7a4542-bfc2-4a33-9ce4-2411a145a395","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2:src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo","line":6,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"6017ed94-6eae-4ee8-8009-19915b84d831","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2:src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo","line":9,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"65490cd1-969b-4ef3-91f8-ad48133f4645","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2:src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo","line":18,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"7dd791fc-30b3-43a4-8368-98b7ec3c2c44","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2:src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo","line":5,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"88e45274-26e1-43d2-b88c-a4f0de40b340","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2:src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo","line":20,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"adc1eb27-4165-43be-96a0-ad8ad4aa5cc6","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2:src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo","line":15,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"af3b1b21-afdb-46db-b320-7eb0186c76b4","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2:src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo","line":7,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"b9bc99f9-df91-402c-b01c-c79804fdfafa","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2:src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo","line":16,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"c3eef6a7-fa0f-4281-b0c4-c3cc62c28ee6","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2:src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo","line":13,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"c40a9a79-7c42-4a78-9c0a-941493760d80","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2:src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo","line":10,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"d4dfe839-5516-43d3-8708-630b9922c92d","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2:src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo","line":1,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"e7c78357-32b7-4a97-9ea6-bd324911c94d","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2:src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo","line":14,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"e8ddc175-52f7-4e9b-a73f-6b57b0925bdf","component":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2:src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo","line":11,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"1b6829f9-d3a7-4224-8dd9-cf7e3db827c5","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b1:src/main/xoo/com/sonar/it/samples/modules/b1/HelloB1.xoo","line":9,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"9540459b-fd9f-48af-9311-a88f62deb244","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b1:src/main/xoo/com/sonar/it/samples/modules/b1/HelloB1.xoo","line":10,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"9a5ed7e3-dd85-484e-999e-0435b2f75253","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b1:src/main/xoo/com/sonar/it/samples/modules/b1/HelloB1.xoo","line":2,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"9bfa3e15-8268-4361-9b59-456746841716","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b1:src/main/xoo/com/sonar/it/samples/modules/b1/HelloB1.xoo","line":1,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"a77e07a5-c572-4953-8f68-7190ada0a72a","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b1:src/main/xoo/com/sonar/it/samples/modules/b1/HelloB1.xoo","line":8,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"bb9ea74c-31da-4f45-9a30-770758d6fb91","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b1:src/main/xoo/com/sonar/it/samples/modules/b1/HelloB1.xoo","line":5,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"bed123b2-6ce1-4f48-bcd6-8449bed843e6","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b1:src/main/xoo/com/sonar/it/samples/modules/b1/HelloB1.xoo","line":7,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"c65358e1-71de-4a41-b666-56f98f5b142b","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b1:src/main/xoo/com/sonar/it/samples/modules/b1/HelloB1.xoo","line":3,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"c8545226-991f-402a-a9ab-ed7366965cbd","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b1:src/main/xoo/com/sonar/it/samples/modules/b1/HelloB1.xoo","line":4,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"d46f8a3b-9dfe-4f46-b073-5247ee2dc7fb","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b1:src/main/xoo/com/sonar/it/samples/modules/b1/HelloB1.xoo","line":6,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"d51307c8-f22e-4a35-9eac-9159472034bd","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b1:src/main/xoo/com/sonar/it/samples/modules/b1/HelloB1.xoo","line":12,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"de0f6728-99cb-4642-9538-dce255680ed5","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b1:src/main/xoo/com/sonar/it/samples/modules/b1/HelloB1.xoo","line":11,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"19b42c33-784d-411d-8ba1-f6da0b81a8ec","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b2:src/main/xoo/com/sonar/it/samples/modules/b2/HelloB2.xoo","line":12,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"1f5bacb3-d3e5-4e0e-aa22-07bc906ff171","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b2:src/main/xoo/com/sonar/it/samples/modules/b2/HelloB2.xoo","line":5,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"240fc9e6-4f86-4cba-87b6-0bc658f0bb2a","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b2:src/main/xoo/com/sonar/it/samples/modules/b2/HelloB2.xoo","line":4,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"38a5a22c-28a5-47a9-b803-45533d1981b5","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b2:src/main/xoo/com/sonar/it/samples/modules/b2/HelloB2.xoo","line":1,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"3a8d14db-c977-4945-8723-e568725ca60b","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b2:src/main/xoo/com/sonar/it/samples/modules/b2/HelloB2.xoo","line":8,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"55b33cc6-ee3d-46e3-b5fc-68efe42c7a2e","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b2:src/main/xoo/com/sonar/it/samples/modules/b2/HelloB2.xoo","line":3,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"abaa37b3-7af3-4fd0-bd5a-494406f5fff9","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b2:src/main/xoo/com/sonar/it/samples/modules/b2/HelloB2.xoo","line":10,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"abb9c19c-6780-40b9-aed0-04538b30940f","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b2:src/main/xoo/com/sonar/it/samples/modules/b2/HelloB2.xoo","line":6,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"b7e9fcdd-3035-4947-9b47-053261edd1ef","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b2:src/main/xoo/com/sonar/it/samples/modules/b2/HelloB2.xoo","line":7,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"c378be23-d7d3-4244-bab3-b5bfa5967af1","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b2:src/main/xoo/com/sonar/it/samples/modules/b2/HelloB2.xoo","line":11,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"cf2a2623-675a-4220-ae1c-50296c8c3b2a","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b2:src/main/xoo/com/sonar/it/samples/modules/b2/HelloB2.xoo","line":2,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"},{"key":"fbdfdbc9-31ec-4821-af23-e7e77ffe4f2d","component":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b2:src/main/xoo/com/sonar/it/samples/modules/b2/HelloB2.xoo","line":9,"message":"This issue is generated on each line","severity":"MAJOR","rule":"xoo:OneIssuePerLine","status":"OPEN","isNew":false,"creationDate":"2013-05-01T00:00:00+0200"}],"components":[{"key":"com.sonarsource.it.samples:multi-modules-sample"},{"key":"com.sonarsource.it.samples:multi-modules-sample:module_a","path":"module_a"},{"key":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1","path":"module_a1"},{"key":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2","path":"module_a2"},{"key":"com.sonarsource.it.samples:multi-modules-sample:module_b","path":"module_b"},{"key":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b1","path":"module_b1"},{"key":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b2","path":"module_b2"},{"key":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo","path":"src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo","moduleKey":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1","status":"SAME"},{"key":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2:src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo","path":"src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo","moduleKey":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2","status":"SAME"},{"key":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b1:src/main/xoo/com/sonar/it/samples/modules/b1/HelloB1.xoo","path":"src/main/xoo/com/sonar/it/samples/modules/b1/HelloB1.xoo","moduleKey":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b1","status":"SAME"},{"key":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b2:src/main/xoo/com/sonar/it/samples/modules/b2/HelloB2.xoo","path":"src/main/xoo/com/sonar/it/samples/modules/b2/HelloB2.xoo","moduleKey":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b2","status":"SAME"},{"key":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1","path":"src/main/xoo/com/sonar/it/samples/modules/a1","moduleKey":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1"},{"key":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2:src/main/xoo/com/sonar/it/samples/modules/a2","path":"src/main/xoo/com/sonar/it/samples/modules/a2","moduleKey":"com.sonarsource.it.samples:multi-modules-sample:module_a:module_a2"},{"key":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b1:src/main/xoo/com/sonar/it/samples/modules/b1","path":"src/main/xoo/com/sonar/it/samples/modules/b1","moduleKey":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b1"},{"key":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b2:src/main/xoo/com/sonar/it/samples/modules/b2","path":"src/main/xoo/com/sonar/it/samples/modules/b2","moduleKey":"com.sonarsource.it.samples:multi-modules-sample:module_b:module_b2"}],"rules":[{"key":"xoo:OneIssuePerLine","rule":"OneIssuePerLine","repository":"xoo","name":"One Issue Per Line"}],"users":[]} \ No newline at end of file
diff --git a/it/it-tests/src/test/resources/batch/IssueJsonReportTest/report-on-single-module-branch.json b/it/it-tests/src/test/resources/batch/IssueJsonReportTest/report-on-single-module-branch.json
new file mode 100644
index 00000000000..a440c8c00ba
--- /dev/null
+++ b/it/it-tests/src/test/resources/batch/IssueJsonReportTest/report-on-single-module-branch.json
@@ -0,0 +1,196 @@
+{
+ "version": "<SONAR_VERSION>",
+ "issues": [
+ {
+ "key": "042f73b0-61e5-43df-b3c3-9d5f1e43dffd",
+ "component": "sample:mybranch:src/main/xoo/sample/Sample.xoo",
+ "line": 2,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "0f1f71b3-4949-406b-abe8-3f61ee5df8e2",
+ "component": "sample:mybranch:src/main/xoo/sample/Sample.xoo",
+ "line": 10,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "45518777-ed03-4282-915f-60cc09ff6c5d",
+ "component": "sample:mybranch:src/main/xoo/sample/Sample.xoo",
+ "line": 13,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "501ee82e-898c-4b88-9975-68655607da8f",
+ "component": "sample:mybranch:src/main/xoo/sample/Sample.xoo",
+ "line": 15,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "55799ca7-85f0-4003-a657-361532b9ad9e",
+ "component": "sample:mybranch:src/main/xoo/sample/Sample.xoo",
+ "line": 4,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "57ba7f32-ac32-4d18-b3cc-61042e59b9aa",
+ "component": "sample:mybranch:src/main/xoo/sample/Sample.xoo",
+ "line": 3,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "5885445b-5f76-45da-8ae4-5b31f145cc68",
+ "component": "sample:mybranch:src/main/xoo/sample/Sample.xoo",
+ "line": 12,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "71be8e1c-3d3b-4704-b86f-efb3de0cc17f",
+ "component": "sample:mybranch:src/main/xoo/sample/Sample.xoo",
+ "line": 11,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": true,
+ "creationDate": "2013-05-02T00:00:00+0200"
+ },
+ {
+ "key": "81669e04-75ae-4eb6-8a13-90b7ea0adcf0",
+ "component": "sample:mybranch:src/main/xoo/sample/Sample.xoo",
+ "line": 5,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "939c914b-a899-429e-a98a-73cc5ff7d1f7",
+ "component": "sample:mybranch:src/main/xoo/sample/Sample.xoo",
+ "line": 7,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": true,
+ "creationDate": "2013-05-02T00:00:00+0200"
+ },
+ {
+ "key": "b3c66ea0-9d80-4159-868f-05d6fcbbc551",
+ "component": "sample:mybranch:src/main/xoo/sample/Sample.xoo",
+ "line": 9,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "c9a17e92-b355-4c19-9b11-24c006a55a4d",
+ "component": "sample:mybranch:src/main/xoo/sample/Sample.xoo",
+ "line": 6,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "dddba55e-44fa-47b8-bcfc-b88f40659e56",
+ "component": "sample:mybranch:src/main/xoo/sample/Sample.xoo",
+ "line": 8,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "e390f328-f59a-4a9a-9421-f5d0e13a3f4e",
+ "component": "sample:mybranch:src/main/xoo/sample/Sample.xoo",
+ "line": 1,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "fdff9685-de6d-4862-adbd-0d6059da5180",
+ "component": "sample:mybranch:src/main/xoo/sample/Sample.xoo",
+ "line": 14,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ }
+ ],
+ "components": [
+ {
+ "key": "sample:mybranch"
+ },
+ {
+ "key": "sample:mybranch:src/main/xoo/sample",
+ "path": "src/main/xoo/sample",
+ "moduleKey": "sample:mybranch"
+ },
+ {
+ "key": "sample:mybranch:src/main/xoo/sample/Sample.xoo",
+ "path": "src/main/xoo/sample/Sample.xoo",
+ "moduleKey": "sample:mybranch",
+ "status": "CHANGED"
+ }
+ ],
+ "rules": [
+ {
+ "key": "xoo:OneIssuePerLine",
+ "rule": "OneIssuePerLine",
+ "repository": "xoo",
+ "name": "One Issue Per Line"
+ }
+ ],
+ "users": [ ]
+
+} \ No newline at end of file
diff --git a/it/it-tests/src/test/resources/batch/IssueJsonReportTest/report-on-single-module.json b/it/it-tests/src/test/resources/batch/IssueJsonReportTest/report-on-single-module.json
new file mode 100644
index 00000000000..99898937f69
--- /dev/null
+++ b/it/it-tests/src/test/resources/batch/IssueJsonReportTest/report-on-single-module.json
@@ -0,0 +1,196 @@
+{
+ "version": "<SONAR_VERSION>",
+ "issues": [
+ {
+ "key": "05652201-6f89-4f07-ba03-1df08eae0d55",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 6,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "0746cf8f-0b67-4da8-82fc-36a6717c1f81",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 5,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "0e9c20e2-567b-4c7a-b1e7-b9e5648dbfc5",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 13,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "107fb325-ddda-43c6-9fde-1e7250571ef8",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 1,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "226c71cf-0a86-43af-8281-6df0308eac92",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 3,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "55c9705c-6509-48c6-9773-0437ab60be42",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 4,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "5d653e95-16e2-4ee7-aac5-91ab8c3aebd6",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 12,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "86056a4b-1813-4a10-937f-082e3f810152",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 10,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "906f38ad-ada7-4088-80fe-3fc3b8532ad6",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 2,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "9328fb3c-6fab-489f-a8ad-eb8277dd7bf7",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 9,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "9980ca57-dfc4-431c-9a45-7ee9d397078a",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 11,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": true,
+ "creationDate": "2013-05-02T00:00:00+0200"
+ },
+ {
+ "key": "ccf5a264-bbe0-4459-97dc-acc0e323c4bb",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 7,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": true,
+ "creationDate": "2013-05-02T00:00:00+0200"
+ },
+ {
+ "key": "ead82961-2724-4d85-b2af-f810206b0ab1",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 8,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "ef617afe-b453-46a2-b004-8f7418059ebc",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 14,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "f7d19927-2d2f-453c-aa45-1e315e5bfbe6",
+ "component": "sample:src/main/xoo/sample/Sample.xoo",
+ "line": 15,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ }
+ ],
+ "components": [
+ {
+ "key": "sample"
+ },
+ {
+ "key": "sample:src/main/xoo/sample",
+ "path": "src/main/xoo/sample",
+ "moduleKey": "sample"
+ },
+ {
+ "key": "sample:src/main/xoo/sample/Sample.xoo",
+ "path": "src/main/xoo/sample/Sample.xoo",
+ "moduleKey": "sample",
+ "status": "CHANGED"
+ }
+ ],
+ "rules": [
+ {
+ "key": "xoo:OneIssuePerLine",
+ "rule": "OneIssuePerLine",
+ "repository": "xoo",
+ "name": "One Issue Per Line"
+ }
+ ],
+ "users": [ ]
+
+} \ No newline at end of file
diff --git a/it/it-tests/src/test/resources/batch/IssueJsonReportTest/report-on-sub-module.json b/it/it-tests/src/test/resources/batch/IssueJsonReportTest/report-on-sub-module.json
new file mode 100644
index 00000000000..c86edf9dd32
--- /dev/null
+++ b/it/it-tests/src/test/resources/batch/IssueJsonReportTest/report-on-sub-module.json
@@ -0,0 +1,208 @@
+{
+
+ "version": "<SONAR_VERSION>",
+ "issues": [
+ {
+ "key": "040a1d39-472b-4cfa-a75d-0547dd21b3c4",
+ "component": "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo",
+ "line": 4,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "0934e722-8456-465d-bb85-adbcd632d3df",
+ "component": "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo",
+ "line": 7,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "3992207a-f3a3-4c3c-a369-28a893e17c60",
+ "component": "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo",
+ "line": 6,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "4b38f729-17f3-4628-b5e1-f6795a6c49c7",
+ "component": "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo",
+ "line": 1,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "50541707-ab11-469d-9ace-b4753ffb84b8",
+ "component": "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo",
+ "line": 8,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "88ddda56-ae14-4121-9dbd-fefc5cc8c86b",
+ "component": "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo",
+ "line": 15,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "a246f099-c97f-4c7e-b1f4-cc3389f3dced",
+ "component": "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo",
+ "line": 14,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "aa2f4b1d-724d-4e2d-85cd-39a86006e2e9",
+ "component": "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo",
+ "line": 10,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "ac908fcc-e533-4229-9a04-3a89d13537e4",
+ "component": "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo",
+ "line": 3,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "c4604a54-5df8-4db7-8670-df6e4932246b",
+ "component": "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo",
+ "line": 2,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "c99f57ec-98e4-464c-8fa5-adbb27a3a81c",
+ "component": "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo",
+ "line": 16,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "d491b9c4-9217-4285-aabd-44d079b1d46a",
+ "component": "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo",
+ "line": 9,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "d4ae59a5-1ece-4735-8142-ac884bdad17a",
+ "component": "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo",
+ "line": 5,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "d832eb5d-5ff1-4095-b9bc-c5b948e74d5f",
+ "component": "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo",
+ "line": 12,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "e4e76304-7920-4a2f-8deb-fe5a7f21d085",
+ "component": "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo",
+ "line": 13,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ },
+ {
+ "key": "fb923e8f-c336-49c0-8884-4529ff8af6e4",
+ "component": "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo",
+ "line": 11,
+ "message": "This issue is generated on each line",
+ "severity": "MAJOR",
+ "rule": "xoo:OneIssuePerLine",
+ "status": "OPEN",
+ "isNew": false,
+ "creationDate": "2013-05-01T00:00:00+0200"
+ }
+ ],
+ "components": [
+ {
+ "key": "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1"
+ },
+ {
+ "key": "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1",
+ "path": "src/main/xoo/com/sonar/it/samples/modules/a1",
+ "moduleKey": "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1"
+ },
+ {
+ "key": "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1:src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo",
+ "path": "src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo",
+ "moduleKey": "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1",
+ "status": "SAME"
+ }
+ ],
+ "rules": [
+ {
+ "key": "xoo:OneIssuePerLine",
+ "rule": "OneIssuePerLine",
+ "repository": "xoo",
+ "name": "One Issue Per Line"
+ }
+ ],
+ "users": [ ]
+
+} \ No newline at end of file
diff --git a/it/it-tests/src/test/resources/batch/IssuesModeTest/empty.xml b/it/it-tests/src/test/resources/batch/IssuesModeTest/empty.xml
new file mode 100644
index 00000000000..8bab61d6c85
--- /dev/null
+++ b/it/it-tests/src/test/resources/batch/IssuesModeTest/empty.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- Generated by Sonar -->
+<profile>
+ <name>empty</name>
+ <language>xoo</language>
+ <rules>
+ </rules>
+</profile> \ No newline at end of file
diff --git a/it/it-tests/src/test/resources/batch/IssuesModeTest/one-issue-per-line-empty.xml b/it/it-tests/src/test/resources/batch/IssuesModeTest/one-issue-per-line-empty.xml
new file mode 100644
index 00000000000..0ba34f10dbd
--- /dev/null
+++ b/it/it-tests/src/test/resources/batch/IssuesModeTest/one-issue-per-line-empty.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- Generated by Sonar -->
+<profile>
+ <name>one-issue-per-line</name>
+ <language>xoo</language>
+ <rules>
+ </rules>
+</profile>
diff --git a/it/it-tests/src/test/resources/batch/IssuesModeTest/one-issue-per-line.xml b/it/it-tests/src/test/resources/batch/IssuesModeTest/one-issue-per-line.xml
new file mode 100644
index 00000000000..7bb4ed5593a
--- /dev/null
+++ b/it/it-tests/src/test/resources/batch/IssuesModeTest/one-issue-per-line.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- Generated by Sonar -->
+<profile>
+ <name>one-issue-per-line</name>
+ <language>xoo</language>
+ <rules>
+ <rule>
+ <repositoryKey>xoo</repositoryKey>
+ <key>OneIssuePerLine</key>
+ <priority>MAJOR</priority>
+ </rule>
+ </rules>
+</profile> \ No newline at end of file
diff --git a/it/it-tests/src/test/resources/batch/IssuesModeTest/with-many-rules.xml b/it/it-tests/src/test/resources/batch/IssuesModeTest/with-many-rules.xml
new file mode 100644
index 00000000000..f3d0baf0616
--- /dev/null
+++ b/it/it-tests/src/test/resources/batch/IssuesModeTest/with-many-rules.xml
@@ -0,0 +1,32 @@
+<profile>
+ <name>with-many-rules</name>
+ <language>xoo</language>
+ <rules>
+ <rule>
+ <repositoryKey>xoo</repositoryKey>
+ <key>OneIssuePerLine</key>
+ <priority>MINOR</priority>
+ </rule>
+ <rule>
+ <repositoryKey>xoo</repositoryKey>
+ <key>OneIssuePerFile</key>
+ <priority>MAJOR</priority>
+ </rule>
+ <rule>
+ <repositoryKey>xoo</repositoryKey>
+ <key>OneIssuePerModule</key>
+ <priority>CRITICAL</priority>
+ </rule>
+ <rule>
+ <repositoryKey>xoo</repositoryKey>
+ <key>HasTag</key>
+ <priority>INFO</priority>
+ <parameters>
+ <parameter>
+ <key>tag</key>
+ <value>xoo</value>
+ </parameter>
+ </parameters>
+ </rule>
+ </rules>
+</profile> \ No newline at end of file
diff --git a/it/it-tests/src/test/resources/batch/MultiLanguageTest/one-issue-per-line-xoo2.xml b/it/it-tests/src/test/resources/batch/MultiLanguageTest/one-issue-per-line-xoo2.xml
new file mode 100644
index 00000000000..67215f91a52
--- /dev/null
+++ b/it/it-tests/src/test/resources/batch/MultiLanguageTest/one-issue-per-line-xoo2.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- Generated by Sonar -->
+<profile>
+ <name>one-issue-per-line-xoo2</name>
+ <language>xoo2</language>
+ <rules>
+ <rule>
+ <repositoryKey>xoo2</repositoryKey>
+ <key>OneIssuePerLine</key>
+ <priority>MAJOR</priority>
+ </rule>
+ </rules>
+</profile>
diff --git a/it/it-tests/src/test/resources/batch/MultiLanguageTest/one-issue-per-line.xml b/it/it-tests/src/test/resources/batch/MultiLanguageTest/one-issue-per-line.xml
new file mode 100644
index 00000000000..7bb4ed5593a
--- /dev/null
+++ b/it/it-tests/src/test/resources/batch/MultiLanguageTest/one-issue-per-line.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- Generated by Sonar -->
+<profile>
+ <name>one-issue-per-line</name>
+ <language>xoo</language>
+ <rules>
+ <rule>
+ <repositoryKey>xoo</repositoryKey>
+ <key>OneIssuePerLine</key>
+ <priority>MAJOR</priority>
+ </rule>
+ </rules>
+</profile> \ No newline at end of file
diff --git a/it/it-tests/src/test/resources/batch/SettingsEncryptionTest/sonar-secret.txt b/it/it-tests/src/test/resources/batch/SettingsEncryptionTest/sonar-secret.txt
new file mode 100644
index 00000000000..65b98c522da
--- /dev/null
+++ b/it/it-tests/src/test/resources/batch/SettingsEncryptionTest/sonar-secret.txt
@@ -0,0 +1 @@
+0PZz+G+f8mjr3sPn4+AhHg== \ No newline at end of file
diff --git a/it/it-tests/src/test/resources/batch/TempFolderTest/one-issue-per-line.xml b/it/it-tests/src/test/resources/batch/TempFolderTest/one-issue-per-line.xml
new file mode 100644
index 00000000000..7bb4ed5593a
--- /dev/null
+++ b/it/it-tests/src/test/resources/batch/TempFolderTest/one-issue-per-line.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- Generated by Sonar -->
+<profile>
+ <name>one-issue-per-line</name>
+ <language>xoo</language>
+ <rules>
+ <rule>
+ <repositoryKey>xoo</repositoryKey>
+ <key>OneIssuePerLine</key>
+ <priority>MAJOR</priority>
+ </rule>
+ </rules>
+</profile> \ No newline at end of file
diff --git a/it/it-tests/src/test/resources/exclusions/IssueExclusionsTest/with-many-rules.xml b/it/it-tests/src/test/resources/exclusions/IssueExclusionsTest/with-many-rules.xml
new file mode 100644
index 00000000000..f3d0baf0616
--- /dev/null
+++ b/it/it-tests/src/test/resources/exclusions/IssueExclusionsTest/with-many-rules.xml
@@ -0,0 +1,32 @@
+<profile>
+ <name>with-many-rules</name>
+ <language>xoo</language>
+ <rules>
+ <rule>
+ <repositoryKey>xoo</repositoryKey>
+ <key>OneIssuePerLine</key>
+ <priority>MINOR</priority>
+ </rule>
+ <rule>
+ <repositoryKey>xoo</repositoryKey>
+ <key>OneIssuePerFile</key>
+ <priority>MAJOR</priority>
+ </rule>
+ <rule>
+ <repositoryKey>xoo</repositoryKey>
+ <key>OneIssuePerModule</key>
+ <priority>CRITICAL</priority>
+ </rule>
+ <rule>
+ <repositoryKey>xoo</repositoryKey>
+ <key>HasTag</key>
+ <priority>INFO</priority>
+ <parameters>
+ <parameter>
+ <key>tag</key>
+ <value>xoo</value>
+ </parameter>
+ </parameters>
+ </rule>
+ </rules>
+</profile> \ No newline at end of file