rule avoid code factoring by static code + remove code duplication + add auto reset features
also fixed licence headers in issues package
/*
- * Copyright (C) 2009-2014 SonarSource SA
- * All rights reserved
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package issue.suite;
orchestrator.getServer().provisionProject("common-rules-project", "Sample");
orchestrator.getServer().associateProjectToQualityProfile("common-rules-project", "xoo", "xoo-common-rules");
runProjectAnalysis(orchestrator, "issue/common-rules",
- "sonar.cpd.xoo.minimumTokens", "2",
- "sonar.cpd.xoo.minimumLines", "2");
+ "sonar.cpd.xoo.minimumTokens", "2",
+ "sonar.cpd.xoo.minimumLines", "2");
}
@Test
/*
- * Copyright (C) 2009-2014 SonarSource SA
- * All rights reserved
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package issue.suite;
import com.sonar.orchestrator.Orchestrator;
-import com.sonar.orchestrator.locator.FileLocation;
import java.util.List;
import org.junit.Before;
import org.junit.ClassRule;
+import org.junit.Rule;
import org.junit.Test;
import org.sonar.wsclient.issue.Issue;
+import util.ProjectAnalysis;
+import util.ProjectAnalysisRule;
import static issue.suite.IssueTestSuite.searchIssues;
import static org.assertj.core.api.Assertions.assertThat;
-import static util.ItUtils.runProjectAnalysis;
public class CustomRulesTest {
@ClassRule
public static Orchestrator orchestrator = IssueTestSuite.ORCHESTRATOR;
+ @Rule
+ public final ProjectAnalysisRule projectAnalysisRule = ProjectAnalysisRule.from(orchestrator);
+
+ private ProjectAnalysis xooSampleAnalysis;
@Before
- public void deleteData() {
- orchestrator.resetData();
+ public void setup() {
+ String profileKey = projectAnalysisRule.registerProfile("/issue/suite/CustomRulesTest/custom.xml");
+ String projectKey = projectAnalysisRule.registerProject("shared/xoo-sample");
+ this.xooSampleAnalysis = projectAnalysisRule.newProjectAnalysis(projectKey)
+ .withQualityProfile(profileKey);
}
@Test
public void analyzeProjectWithCustomRules() throws Exception {
-
orchestrator.getServer().adminWsClient().post("api/rules/create",
"template_key", "xoo:TemplateRule",
"custom_key", "MyCustomRule",
"severity", "BLOCKER",
"params", "line=2");
- orchestrator.getServer().restoreProfile(FileLocation.ofClasspath("/issue/suite/CustomRulesTest/custom.xml"));
-
- orchestrator.getServer().provisionProject("sample", "Sample");
- orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "Custom");
-
- runProjectAnalysis(orchestrator, "shared/xoo-sample");
+ xooSampleAnalysis.run();
List<Issue> issues = searchIssues();
assertThat(issues).hasSize(1);
package issue.suite;
import com.sonar.orchestrator.Orchestrator;
-import com.sonar.orchestrator.build.SonarRunner;
-import com.sonar.orchestrator.locator.FileLocation;
import java.util.List;
import org.junit.Before;
import org.junit.ClassRule;
+import org.junit.Rule;
import org.junit.Test;
import org.sonar.wsclient.base.HttpException;
import org.sonar.wsclient.issue.ActionPlan;
import org.sonar.wsclient.issue.IssueQuery;
import org.sonar.wsclient.issue.Issues;
import org.sonar.wsclient.issue.NewActionPlan;
+import util.ProjectAnalysis;
+import util.ProjectAnalysisRule;
import static issue.suite.IssueTestSuite.ORCHESTRATOR;
import static issue.suite.IssueTestSuite.adminIssueClient;
import static issue.suite.IssueTestSuite.searchRandomIssue;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
-import static util.ItUtils.runProjectAnalysis;
import static util.ItUtils.toDate;
import static util.ItUtils.verifyHttpException;
@ClassRule
public static Orchestrator orchestrator = ORCHESTRATOR;
+ @Rule
+ public final ProjectAnalysisRule projectAnalysisRule = ProjectAnalysisRule.from(orchestrator);
Issue issue;
- SonarRunner scan;
-
- private static List<Issue> searchIssuesBySeverities(String componentKey, String... severities) {
- return searchIssues(IssueQuery.create().componentRoots(componentKey).severities(severities));
- }
-
- private static ActionPlanClient adminActionPlanClient() {
- return orchestrator.getServer().adminWsClient().actionPlanClient();
- }
+ ProjectAnalysis projectAnalysis;
@Before
- public void resetData() {
- orchestrator.resetData();
- orchestrator.getServer().restoreProfile(FileLocation.ofClasspath("/issue/suite/IssueActionTest/xoo-one-issue-per-line-profile.xml"));
- orchestrator.getServer().provisionProject("sample", "Sample");
- orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "xoo-one-issue-per-line-profile");
-
- scan = runProjectAnalysis(orchestrator, "shared/xoo-sample");
- issue = searchRandomIssue();
+ public void setup() {
+ String qualityProfileKey = projectAnalysisRule.registerProfile("/issue/suite/IssueActionTest/xoo-one-issue-per-line-profile.xml");
+ String projectKey = projectAnalysisRule.registerProject("shared/xoo-sample");
+
+ this.projectAnalysis = projectAnalysisRule.newProjectAnalysis(projectKey).withQualityProfile(qualityProfileKey);
+ this.projectAnalysis.run();
+ this.issue = searchRandomIssue();
}
@Test
assertThat(searchIssuesBySeverities(componentKey, "BLOCKER")).hasSize(1);
- orchestrator.executeBuild(scan);
+ projectAnalysis.run();
Issue reloaded = searchIssueByKey(issue.key());
assertThat(reloaded.severity()).isEqualTo("BLOCKER");
assertThat(reloaded.status()).isEqualTo("OPEN");
adminIssueClient().assign(issue.key(), "admin");
assertThat(searchIssues(IssueQuery.create().assignees("admin"))).hasSize(1);
- orchestrator.executeBuild(scan);
+ projectAnalysis.run();
Issue reloaded = searchIssueByKey(issue.key());
assertThat(reloaded.assignee()).isEqualTo("admin");
assertThat(reloaded.creationDate()).isEqualTo(issue.creationDate());
adminIssueClient().plan(issue.key(), newActionPlan.key());
assertThat(search(IssueQuery.create().actionPlans(newActionPlan.key())).list()).hasSize(1);
- orchestrator.executeBuild(scan);
+ projectAnalysis.run();
Issue reloaded = searchIssueByKey(issue.key());
assertThat(reloaded.actionPlan()).isEqualTo(newActionPlan.key());
assertThat(reloaded.creationDate()).isEqualTo(issue.creationDate());
adminIssueClient().plan(issue.key(), null);
assertThat(search(IssueQuery.create().actionPlans(newActionPlan.key())).list()).hasSize(0);
- orchestrator.executeBuild(scan);
+ projectAnalysis.run();
Issue reloaded = searchIssueByKey(issue.key());
assertThat(reloaded.actionPlan()).isNull();
assertThat(reloaded.creationDate()).isEqualTo(issue.creationDate());
adminIssueClient().doAction(issue.key(), "fake");
assertThat(adminIssueClient().actions(issue.key())).doesNotContain("fake");
- orchestrator.executeBuild(scan);
+ projectAnalysis.run();
// Fake action is no more available if the issue attribute is still there
assertThat(adminIssueClient().actions(issue.key())).doesNotContain("fake");
}
+ private static List<Issue> searchIssuesBySeverities(String componentKey, String... severities) {
+ return searchIssues(IssueQuery.create().componentRoots(componentKey).severities(severities));
+ }
+
+ private static ActionPlanClient adminActionPlanClient() {
+ return orchestrator.getServer().adminWsClient().actionPlanClient();
+ }
+
}
import com.google.common.base.Function;
import com.google.common.collect.FluentIterable;
import com.sonar.orchestrator.Orchestrator;
-import com.sonar.orchestrator.locator.FileLocation;
import java.util.List;
import org.junit.Before;
import org.junit.ClassRule;
+import org.junit.Rule;
import org.junit.Test;
import org.sonar.wsclient.base.HttpException;
import org.sonar.wsclient.issue.ActionPlan;
import org.sonar.wsclient.issue.Issue;
import org.sonar.wsclient.issue.NewActionPlan;
import util.ItUtils;
+import util.ProjectAnalysis;
+import util.ProjectAnalysisRule;
import static issue.suite.IssueTestSuite.ORCHESTRATOR;
import static issue.suite.IssueTestSuite.adminIssueClient;
import static issue.suite.IssueTestSuite.issueClient;
import static org.assertj.core.api.Assertions.assertThat;
-import static util.ItUtils.runProjectAnalysis;
/**
* SONAR-4421
@ClassRule
public static Orchestrator orchestrator = ORCHESTRATOR;
+ @Rule
+ public final ProjectAnalysisRule projectAnalysisRule = ProjectAnalysisRule.from(orchestrator);
+
+ private ProjectAnalysis xooSampleLittleIssuesAnalysis;
@Before
- public void resetData() {
- orchestrator.resetData();
+ public void setUp() throws Exception {
+ String qualityProfileKey = projectAnalysisRule.registerProfile("/issue/suite/IssueBulkChangeTest/one-issue-per-line-profile.xml");
+ String projectKey = projectAnalysisRule.registerProject("shared/xoo-sample");
+ this.xooSampleLittleIssuesAnalysis = projectAnalysisRule.newProjectAnalysis(projectKey)
+ .withQualityProfile(qualityProfileKey);
}
@Test
public void should_change_severity() {
- analyzeSampleProjectWillSmallNumberOfIssues();
+ xooSampleLittleIssuesAnalysis.run();
String newSeverity = "BLOCKER";
String[] issueKeys = searchIssueKeys(BULK_EDITED_ISSUE_COUNT);
@Test
public void should_do_transition() {
- analyzeSampleProjectWillSmallNumberOfIssues();
+ xooSampleLittleIssuesAnalysis.run();
String[] issueKeys = searchIssueKeys(BULK_EDITED_ISSUE_COUNT);
BulkChange bulkChange = bulkTransitionStatusOfIssues(issueKeys, "confirm");
@Test
public void should_assign() {
- analyzeSampleProjectWillSmallNumberOfIssues();
+ xooSampleLittleIssuesAnalysis.run();
String[] issueKeys = searchIssueKeys(BULK_EDITED_ISSUE_COUNT);
BulkChange bulkChange = buldChangeAssigneeOfIssues(issueKeys, "admin");
@Test
public void should_plan() {
- analyzeSampleProjectWillSmallNumberOfIssues();
+ xooSampleLittleIssuesAnalysis.run();
// Create action plan
ActionPlan newActionPlan = adminActionPlanClient().create(
@Test
public void should_setSeverity_add_comment_in_single_WS_call() {
- analyzeSampleProjectWillSmallNumberOfIssues();
+ xooSampleLittleIssuesAnalysis.run();
String newSeverity = "BLOCKER";
String[] issueKeys = searchIssueKeys(BULK_EDITED_ISSUE_COUNT);
@Test
public void should_apply_bulk_change_on_many_actions() {
- analyzeSampleProjectWillSmallNumberOfIssues();
+ xooSampleLittleIssuesAnalysis.run();
String newSeverity = "BLOCKER";
String[] issueKeys = searchIssueKeys(BULK_EDITED_ISSUE_COUNT);
@Test
public void should_not_apply_bulk_change_if_not_logged() {
- analyzeSampleProjectWillSmallNumberOfIssues();
+ xooSampleLittleIssuesAnalysis.run();
String newSeverity = "BLOCKER";
String[] issueKeys = searchIssueKeys(BULK_EDITED_ISSUE_COUNT);
@Test
public void should_not_apply_bulk_change_if_no_change_to_do() {
- analyzeSampleProjectWillSmallNumberOfIssues();
+ xooSampleLittleIssuesAnalysis.run();
String newSeverity = "BLOCKER";
String[] issueKeys = searchIssueKeys(BULK_EDITED_ISSUE_COUNT);
@Test
public void should_not_apply_bulk_change_if_action_is_invalid() {
- analyzeSampleProjectWillSmallNumberOfIssues();
+ xooSampleLittleIssuesAnalysis.run();
int limit = BULK_EDITED_ISSUE_COUNT;
String[] issueKeys = searchIssueKeys(limit);
@Test
public void should_add_comment_only_on_issues_that_will_be_changed() {
- analyzeSampleProjectWillSmallNumberOfIssues();
+ xooSampleLittleIssuesAnalysis.run();
int nbIssues = BULK_EDITED_ISSUE_COUNT;
String[] issueKeys = searchIssueKeys(nbIssues);
assertThat(nbIssuesWithComment).isEqualTo(1);
}
- private void analyzeSampleProjectWillSmallNumberOfIssues() {
- orchestrator.getServer().restoreProfile(FileLocation.ofClasspath("/issue/suite/IssueBulkChangeTest/one-issue-per-line-profile.xml"));
- orchestrator.getServer().provisionProject("sample", "Sample");
- orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
- runProjectAnalysis(orchestrator, "shared/xoo-sample");
- }
-
private static void assertIssueSeverity(String[] issueKeys, String expectedSeverity) {
for (Issue issue : IssueTestSuite.searchIssues(issueKeys)) {
assertThat(issue.severity()).isEqualTo(expectedSeverity);
package issue.suite;
import com.sonar.orchestrator.Orchestrator;
-import com.sonar.orchestrator.build.SonarRunner;
-import com.sonar.orchestrator.locator.FileLocation;
import java.util.List;
import org.junit.Before;
import org.junit.ClassRule;
+import org.junit.Rule;
import org.junit.Test;
import org.sonar.wsclient.issue.Issue;
import org.sonar.wsclient.issue.IssueChange;
import org.sonar.wsclient.issue.IssueChangeDiff;
import org.sonar.wsclient.issue.IssueQuery;
+import util.ProjectAnalysis;
+import util.ProjectAnalysisRule;
import static issue.suite.IssueTestSuite.ORCHESTRATOR;
import static issue.suite.IssueTestSuite.adminIssueClient;
import static issue.suite.IssueTestSuite.issueClient;
import static org.assertj.core.api.Assertions.assertThat;
-import static util.ItUtils.runProjectAnalysis;
public class IssueChangelogTest {
@ClassRule
public static Orchestrator orchestrator = ORCHESTRATOR;
+ @Rule
+ public final ProjectAnalysisRule projectAnalysisRule = ProjectAnalysisRule.from(orchestrator);
Issue issue;
- SonarRunner scan;
+ ProjectAnalysis xooSampleAnalysis;
@Before
public void resetData() {
- orchestrator.resetData();
- orchestrator.getServer().restoreProfile(FileLocation.ofClasspath("/issue/suite/IssueChangelogTest/one-issue-per-line-profile.xml"));
- orchestrator.getServer().provisionProject("sample", "Sample");
- orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
- scan = runProjectAnalysis(orchestrator, "shared/xoo-sample");
+ xooSampleAnalysis = projectAnalysisRule
+ .newProjectAnalysis(projectAnalysisRule.registerProject("shared/xoo-sample"))
+ .withQualityProfile(projectAnalysisRule.registerProfile("/issue/suite/IssueChangelogTest/one-issue-per-line-profile.xml"));
+ xooSampleAnalysis.run();
issue = searchRandomIssue();
}
// re analyse the project after resolving an issue in order to reopen it
adminIssueClient().doTransition(issue.key(), "resolve");
- orchestrator.executeBuild(scan);
+ xooSampleAnalysis.run();
List<IssueChange> changes = retrieveChangeForIssue(issue.key());
assertThat(changes).hasSize(2);
package issue.suite;
import com.sonar.orchestrator.Orchestrator;
-import com.sonar.orchestrator.locator.FileLocation;
import java.util.List;
-import org.junit.Before;
import org.junit.ClassRule;
+import org.junit.Rule;
import org.junit.Test;
import org.sonar.wsclient.issue.Issue;
import org.sonar.wsclient.issue.IssueQuery;
import org.sonar.wsclient.services.Measure;
import org.sonar.wsclient.services.Resource;
import org.sonar.wsclient.services.ResourceQuery;
+import util.ProjectAnalysis;
+import util.ProjectAnalysisRule;
import static issue.suite.IssueTestSuite.ORCHESTRATOR;
import static issue.suite.IssueTestSuite.searchIssues;
import static org.assertj.core.api.Assertions.assertThat;
-import static util.ItUtils.runProjectAnalysis;
/**
* Tests the extension point IssueFilter
*/
public class IssueFilterExtensionTest {
- private static final String MULTI_MODULES_SAMPLE_PROJECT_NAME = "com.sonarsource.it.samples:multi-modules-sample";
-
@ClassRule
public static Orchestrator orchestrator = ORCHESTRATOR;
+ @Rule
+ public final ProjectAnalysisRule projectAnalysisRule = ProjectAnalysisRule.from(orchestrator);
- @Before
- public void resetData() {
- orchestrator.resetData();
- orchestrator.getServer().restoreProfile(FileLocation.ofClasspath("/issue/suite/IssueFilterExtensionTest/xoo-with-many-rules.xml"));
- }
+ private final String manyRuleProfileKey = projectAnalysisRule.registerProfile("/issue/suite/IssueFilterExtensionTest/xoo-with-many-rules.xml");
+ private final String xooMultiModuleProjectKey = projectAnalysisRule.registerProject("shared/xoo-multi-modules-sample");
+ private final ProjectAnalysis analysis = projectAnalysisRule.newProjectAnalysis(xooMultiModuleProjectKey)
+ .withQualityProfile(manyRuleProfileKey);
@Test
public void should_filter_files() throws Exception {
- orchestrator.getServer().provisionProject(MULTI_MODULES_SAMPLE_PROJECT_NAME, "Sonar :: Integration Tests :: Multi-modules Sample");
- orchestrator.getServer().associateProjectToQualityProfile(MULTI_MODULES_SAMPLE_PROJECT_NAME, "xoo", "with-many-rules");
- runProjectAnalysis(orchestrator, "shared/xoo-multi-modules-sample",
- "sonar.exclusions", "**/HelloA1.xoo");
+ analysis.withProperties("sonar.exclusions", "**/HelloA1.xoo").run();
List<Issue> issues = searchIssues();
assertThat(issues).isNotEmpty();
assertThat(issue.componentKey()).doesNotContain("HelloA1");
}
- assertThat(getMeasure(MULTI_MODULES_SAMPLE_PROJECT_NAME, "violations").getIntValue()).isEqualTo(issues.size());
+ assertThat(getMeasure(xooMultiModuleProjectKey, "violations").getIntValue()).isEqualTo(issues.size());
}
@Test
public void should_filter_issues() {
- // first analysis without isssue-filter
- orchestrator.getServer().provisionProject(MULTI_MODULES_SAMPLE_PROJECT_NAME, "Sonar :: Integration Tests :: Multi-modules Sample");
- orchestrator.getServer().associateProjectToQualityProfile(MULTI_MODULES_SAMPLE_PROJECT_NAME, "xoo", "with-many-rules");
- runProjectAnalysis(orchestrator, "shared/xoo-multi-modules-sample");
+ // first analysis without issue-filter
+ analysis.run();
// Issue filter removes issues on lines < 5
// Deprecated violation filter removes issues detected by PMD
- List<Issue> unresolvedIssues = searchResolvedIssues(MULTI_MODULES_SAMPLE_PROJECT_NAME);
+ List<Issue> unresolvedIssues = searchResolvedIssues(xooMultiModuleProjectKey);
int issuesBeforeLine5 = countIssuesBeforeLine5(unresolvedIssues);
int pmdIssues = countModuleIssues(unresolvedIssues);
assertThat(issuesBeforeLine5).isGreaterThan(0);
assertThat(pmdIssues).isGreaterThan(0);
// Enable issue filters
- runProjectAnalysis(orchestrator, "shared/xoo-multi-modules-sample",
- "enableIssueFilters", "true");
+ analysis.withProperties("enableIssueFilters", "true").run();
- unresolvedIssues = searchResolvedIssues(MULTI_MODULES_SAMPLE_PROJECT_NAME);
- List<Issue> resolvedIssues = searchUnresolvedIssues(MULTI_MODULES_SAMPLE_PROJECT_NAME);
+ unresolvedIssues = searchResolvedIssues(xooMultiModuleProjectKey);
+ List<Issue> resolvedIssues = searchUnresolvedIssues(xooMultiModuleProjectKey);
assertThat(countIssuesBeforeLine5(unresolvedIssues)).isZero();
assertThat(countModuleIssues(unresolvedIssues)).isZero();
assertThat(countModuleIssues(resolvedIssues)).isGreaterThan(0);
package issue.suite;
import com.sonar.orchestrator.Orchestrator;
-import com.sonar.orchestrator.locator.FileLocation;
import java.util.List;
import org.junit.Before;
import org.junit.ClassRule;
+import org.junit.Rule;
import org.junit.Test;
import org.sonar.wsclient.issue.Issue;
import org.sonar.wsclient.issue.IssueQuery;
+import util.ProjectAnalysis;
+import util.ProjectAnalysisRule;
import static issue.suite.IssueTestSuite.ORCHESTRATOR;
import static issue.suite.IssueTestSuite.searchIssues;
import static org.assertj.core.api.Assertions.assertThat;
-import static util.ItUtils.runProjectAnalysis;
-import static util.ItUtils.setServerProperty;
public class IssuePurgeTest {
@ClassRule
public static Orchestrator orchestrator = ORCHESTRATOR;
+ @Rule
+ public final ProjectAnalysisRule projectAnalysisRule = ProjectAnalysisRule.from(orchestrator);
+
+ private ProjectAnalysis xooSampleAnalysis;
+ private ProjectAnalysis xooMultiModuleAnalysis;
@Before
- public void deleteAnalysisData() {
- orchestrator.resetData();
- // reset settings before test
- setServerProperty(orchestrator, "sonar.dbcleaner.daysBeforeDeletingClosedIssues", null);
- orchestrator.getServer().restoreProfile(FileLocation.ofClasspath("/issue/suite/IssuePurgeTest/with-many-rules.xml"));
+ public void setUp() throws Exception {
+ String manyRulesProfile = projectAnalysisRule.registerProfile("/issue/suite/IssuePurgeTest/with-many-rules.xml");
+ String xooSampleProjectKey = projectAnalysisRule.registerProject("shared/xoo-sample");
+ this.xooSampleAnalysis = projectAnalysisRule.newProjectAnalysis(xooSampleProjectKey)
+ .withQualityProfile(manyRulesProfile);
+ String xooMultiModuleProjectKey = projectAnalysisRule.registerProject("shared/xoo-multi-modules-sample");
+ this.xooMultiModuleAnalysis = projectAnalysisRule.newProjectAnalysis(xooMultiModuleProjectKey)
+ .withQualityProfile(manyRulesProfile);
}
/**
*/
@Test
public void purge_old_closed_issues() throws Exception {
- setServerProperty(orchestrator, "sonar.dbcleaner.daysBeforeDeletingClosedIssues", "5000");
+ projectAnalysisRule.setServerProperty("sonar.dbcleaner.daysBeforeDeletingClosedIssues", "5000");
// Generate some issues
- orchestrator.getServer().provisionProject("sample", "Sample");
- orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "with-many-rules");
- runProjectAnalysis(orchestrator, "shared/xoo-sample",
+ xooSampleAnalysis.withProperties(
"sonar.dynamicAnalysis", "false",
- "sonar.projectDate", "2014-10-01");
+ "sonar.projectDate", "2014-10-01")
+ .run();
// All the issues are open
List<Issue> issues = searchIssues();
// Second scan with empty profile -> all issues are resolved and closed
// -> Not deleted because less than 5000 days long
- orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "empty");
- runProjectAnalysis(orchestrator, "shared/xoo-sample",
- "sonar.dynamicAnalysis", "false",
- "sonar.projectDate", "2014-10-15");
+ xooSampleAnalysis
+ .withXooEmptyProfile()
+ .withProperties(
+ "sonar.dynamicAnalysis", "false",
+ "sonar.projectDate", "2014-10-15")
+ .run();
issues = searchIssues();
assertThat(issues).isNotEmpty();
for (Issue issue : issues) {
}
// Third scan -> closed issues are deleted
- setServerProperty(orchestrator, "sonar.dbcleaner.daysBeforeDeletingClosedIssues", "1");
+ projectAnalysisRule.setServerProperty("sonar.dbcleaner.daysBeforeDeletingClosedIssues", "1");
- runProjectAnalysis(orchestrator, "shared/xoo-sample",
- "sonar.dynamicAnalysis", "false",
- "sonar.projectDate", "2014-10-20");
+ xooSampleAnalysis.withXooEmptyProfile()
+ .withProperties(
+ "sonar.dynamicAnalysis", "false",
+ "sonar.projectDate", "2014-10-20")
+ .run();
assertThat(searchIssues(IssueQuery.create())).isEmpty();
}
*/
@Test
public void resolve_issues_when_removing_module() throws Exception {
- 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", "with-many-rules");
-
// Generate some issues
- runProjectAnalysis(orchestrator, "shared/xoo-multi-modules-sample",
- "sonar.dynamicAnalysis", "false");
+ xooMultiModuleAnalysis
+ .withProperties("sonar.dynamicAnalysis", "false")
+ .run();
// All the issues are open
List<Issue> issues = searchIssues();
assertThat(issuesOnModuleB).isEqualTo(28);
// Second scan without module B -> issues on module B are resolved as removed and closed
- runProjectAnalysis(orchestrator, "shared/xoo-multi-modules-sample",
- "sonar.dynamicAnalysis", "false",
- "sonar.modules", "module_a");
+ xooMultiModuleAnalysis
+ .withProperties(
+ "sonar.dynamicAnalysis", "false",
+ "sonar.modules", "module_a")
+ .run();
// Resolved should should all be mark as REMOVED and affect to module b
List<Issue> reloadedIssues = searchIssues(IssueQuery.create().resolved(true));
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
package issue.suite;
import com.sonar.orchestrator.Orchestrator;
-import com.sonar.orchestrator.build.SonarRunner;
-import com.sonar.orchestrator.locator.FileLocation;
import java.util.List;
import org.junit.Before;
import org.junit.ClassRule;
+import org.junit.Rule;
import org.junit.Test;
import org.sonar.wsclient.issue.Issue;
import org.sonar.wsclient.issue.IssueQuery;
+import util.ProjectAnalysis;
+import util.ProjectAnalysisRule;
import static issue.suite.IssueTestSuite.adminIssueClient;
import static issue.suite.IssueTestSuite.searchIssueByKey;
import static issue.suite.IssueTestSuite.searchIssues;
import static issue.suite.IssueTestSuite.searchRandomIssue;
import static org.assertj.core.api.Assertions.assertThat;
-import static util.ItUtils.projectDir;
public class IssueWorkflowTest {
@ClassRule
public static Orchestrator orchestrator = IssueTestSuite.ORCHESTRATOR;
- Issue issue;
- SonarRunner scan;
+ @Rule
+ public final ProjectAnalysisRule projectAnalysisRule = ProjectAnalysisRule.from(orchestrator);
- @Before
- public void resetData() {
- orchestrator.resetData();
-
- orchestrator.getServer().restoreProfile(FileLocation.ofClasspath("/issue/suite/IssueWorkflowTest/xoo-one-issue-per-line-profile.xml"));
- orchestrator.getServer().provisionProject("workflow", "Workflow");
- orchestrator.getServer().associateProjectToQualityProfile("workflow", "xoo", "xoo-one-issue-per-line-profile");
+ private ProjectAnalysis analysisWithIssues;
+ private ProjectAnalysis analysisWithoutIssues;
+ private Issue issue;
- scan = SonarRunner.create(projectDir("issue/workflow"));
- orchestrator.executeBuild(scan);
+ @Before
+ public void before() {
+ String oneIssuePerFileProfileKey = projectAnalysisRule.registerProfile("/issue/suite/IssueWorkflowTest/xoo-one-issue-per-line-profile.xml");
+ String analyzedProjectKey = projectAnalysisRule.registerProject("issue/workflow");
+ analysisWithIssues = projectAnalysisRule.newProjectAnalysis(analyzedProjectKey).withQualityProfile(oneIssuePerFileProfileKey);
+ analysisWithoutIssues = analysisWithIssues.withXooEmptyProfile();
+ analysisWithIssues.run();
issue = searchRandomIssue();
}
assertThat(issues).isNotEmpty();
// re-analyze with profile "empty". The rule is disabled so the issues must be closed
- orchestrator.getServer().associateProjectToQualityProfile("workflow", "xoo", "empty");
- orchestrator.executeBuild(scan);
+ analysisWithoutIssues.run();
issues = searchIssues(IssueQuery.create().rules("xoo:OneIssuePerLine"));
assertThat(issues).isNotEmpty();
for (Issue issue : issues) {
assertThat(falsePositive.creationDate()).isEqualTo(issue.creationDate());
// scan without any rules -> confirmed is closed
- orchestrator.getServer().associateProjectToQualityProfile("workflow", "xoo", "empty");
- orchestrator.executeBuild(scan);
+ analysisWithoutIssues.run();
Issue closed = searchIssueByKey(issue.key());
assertThat(closed.status()).isEqualTo("CLOSED");
assertThat(closed.resolution()).isEqualTo("REMOVED");
assertThat(resolvedIssue.updateDate().before(issue.updateDate())).isFalse();
// re-execute scan, with the same Q profile -> the issue has not been fixed
- orchestrator.executeBuild(scan);
+ analysisWithIssues.run();
// reload issue
Issue reopenedIssue = searchIssueByKey(issue.key());
assertThat(resolvedIssue.closeDate()).isNull();
// re-execute scan without rules -> the issue is removed with resolution "REMOVED"
- orchestrator.getServer().associateProjectToQualityProfile("workflow", "xoo", "empty");
- orchestrator.executeBuild(scan);
+ analysisWithoutIssues.run();
// reload issue
Issue closedIssue = searchIssueByKey(issue.key());
assertThat(falsePositive.creationDate()).isEqualTo(issue.creationDate());
// re-execute the same scan
- orchestrator.executeBuild(scan);
+ analysisWithIssues.run();
// refresh
Issue reloaded = searchIssueByKey(falsePositive.key());
assertThat(falsePositive.creationDate()).isEqualTo(issue.creationDate());
// scan without any rules -> false-positive is closed
- orchestrator.getServer().associateProjectToQualityProfile("workflow", "xoo", "empty");
- orchestrator.executeBuild(scan);
+ analysisWithoutIssues.run();
Issue closed = searchIssueByKey(issue.key());
assertThat(closed.status()).isEqualTo("CLOSED");
assertThat(closed.resolution()).isEqualTo("REMOVED");
adminIssueClient().doTransition(issue.key(), "resolve");
// re-execute scan without rules -> the issue is closed
- orchestrator.getServer().associateProjectToQualityProfile("workflow", "xoo", "empty");
- orchestrator.executeBuild(scan);
+ analysisWithoutIssues.run();
// user try to reopen the issue
assertThat(adminIssueClient().transitions(issue.key())).isEmpty();
/*
- * Copyright (C) 2009-2014 SonarSource SA
- * All rights reserved
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package issue.suite;
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package util;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+final class LoadedProfiles {
+ private final Map<String, Profile> profileStatesPerProfileKey = new HashMap<>();
+
+ public LoadedProfiles() {
+ init();
+ }
+
+ public String loadProfile(String relativePathToProfile) {
+ try {
+ URL resource = getClass().getResource(relativePathToProfile);
+ Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(resource.openStream());
+
+ String profileKey = null;
+ String languageKey = null;
+
+ Element documentElement = document.getDocumentElement();
+ checkArgument("profile".equals(documentElement.getNodeName()), "%s is not a quality profile file. Root node is not %s", resource.toURI().toString());
+ NodeList childNodes = documentElement.getChildNodes();
+ for (int i = 0; i < childNodes.getLength(); i++) {
+ Node childNode = childNodes.item(i);
+ if ("name".equals(childNode.getNodeName())) {
+ profileKey = childNode.getChildNodes().item(0).getNodeValue();
+ } else if ("language".equals(childNode.getNodeName())) {
+ languageKey = childNode.getChildNodes().item(0).getNodeValue();
+ }
+ }
+ checkArgument(profileKey != null, "Quality profile file %s is missing profile key", resource.toURI().toString());
+ checkArgument(languageKey != null, "Quality profile file %s is missing language key", resource.toURI().toString());
+ this.profileStatesPerProfileKey.put(profileKey, new Profile(profileKey, languageKey, relativePathToProfile));
+
+ return profileKey;
+ } catch (URISyntaxException | SAXException | IOException | ParserConfigurationException e) {
+ throw new RuntimeException("Can not load quality profile " + relativePathToProfile, e);
+ }
+ }
+
+ public Profile getState(String qualityProfileKey) {
+ Profile profile = this.profileStatesPerProfileKey.get(qualityProfileKey);
+ checkArgument(profile != null, "Quality Profile with key %s is unknown to %s", qualityProfileKey, ProjectAnalysisRule.class.getSimpleName());
+ return profile;
+ }
+
+ public void reset() {
+ this.profileStatesPerProfileKey.clear();
+ init();
+ }
+
+ private void init() {
+ this.profileStatesPerProfileKey.put(Profile.XOO_EMPTY_PROFILE.getProfileKey(), Profile.XOO_EMPTY_PROFILE);
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package util;
+
+import com.google.common.base.Throwables;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+
+final class LoadedProjects {
+
+ static final String SONAR_PROJECT_PROPERTIES_FILE_NAME = "sonar-project.properties";
+
+ private final Map<String, ProjectState> projectStatePerProjectKey = new HashMap<>();
+ private final Set<String> knownProjects = new HashSet<>();
+
+ public void reset() {
+ this.projectStatePerProjectKey.clear();
+ this.knownProjects.clear();
+ }
+
+ public String load(String projectRelativePath) {
+ checkState(!knownProjects.contains(projectRelativePath), "Project at location %s already loaded", projectRelativePath);
+
+ File projectDir = ItUtils.projectDir(projectRelativePath);
+ Properties sonarProjectProperties = loadProjectProperties(projectDir);
+ ProjectState projectState = new ProjectState(projectDir, sonarProjectProperties);
+
+ register(projectRelativePath, projectState);
+
+ return projectState.getProjectKey();
+ }
+
+ public ProjectState getProjectState(String projectKey) {
+ ProjectState projectState = this.projectStatePerProjectKey.get(projectKey);
+ checkArgument(projectState != null, "Project with key %s is unknown to %s", projectKey, ProjectAnalysisRule.class.getSimpleName());
+ return projectState;
+ }
+
+ private void register(String projectRelativePath, ProjectState projectState) {
+ this.projectStatePerProjectKey.put(projectState.getProjectKey(), projectState);
+ this.knownProjects.add(projectRelativePath);
+ }
+
+ private static Properties loadProjectProperties(File projectDir) {
+ File sonarPropertiesFile = new File(projectDir, SONAR_PROJECT_PROPERTIES_FILE_NAME);
+ checkArgument(sonarPropertiesFile.exists(), "Can not locate %s in project %s", SONAR_PROJECT_PROPERTIES_FILE_NAME, projectDir.getAbsolutePath());
+
+ Properties properties = new Properties();
+ try {
+ properties.load(new FileReader(sonarPropertiesFile));
+ } catch (IOException e) {
+ Throwables.propagate(e);
+ }
+ return properties;
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package util;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+final class Profile {
+ static final Profile XOO_EMPTY_PROFILE = new Profile("empty", "xoo", "n/a");
+
+ private final String profileKey;
+ private final String languageKey;
+ private final String relativePath;
+
+ Profile(String profileKey, String languageKey, String relativePath) {
+ this.profileKey = profileKey;
+ this.languageKey = languageKey;
+ this.relativePath = relativePath;
+ }
+
+ public String getProfileKey() {
+ return profileKey;
+ }
+
+ public String getLanguageKey() {
+ return languageKey;
+ }
+
+ public String getRelativePath() {
+ return relativePath;
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package util;
+
+public interface ProjectAnalysis {
+ /**
+ * Creates a new ProjectAnalysis which will use the specified quality profile.
+ *
+ * @throws IllegalArgumentException if the quality profile with the specified key has not been loaded into the Rule
+ * @see {@link ProjectAnalysisRule#registerProfile(String)}
+ */
+ ProjectAnalysis withQualityProfile(String qualityProfileKey);
+
+ /**
+ * Creates a new ProjectAnalysis which will use the built-in Xoo empty profile.
+ */
+ ProjectAnalysis withXooEmptyProfile();
+
+ /**
+ * Creates a new ProjectAnalysis which will have debug logs enabled (or not).
+ */
+ ProjectAnalysis withDebugLogs(boolean enabled);
+
+ /**
+ * Creates a new ProjectAnalysis which will have the specified properties.
+ */
+ ProjectAnalysis withProperties(String... properties);
+
+ /**
+ * Execute the current ProjectAnalysis.
+ * This method can be called any number of time and will run the same analysis again and again.
+ */
+ void run();
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package util;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableMap;
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.SonarRunner;
+import com.sonar.orchestrator.locator.FileLocation;
+import java.util.HashSet;
+import java.util.Set;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+import org.junit.rules.ExternalResource;
+import org.sonar.wsclient.services.PropertyDeleteQuery;
+import org.sonar.wsclient.services.PropertyUpdateQuery;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Rule wrapping around an {@link Orchestrator} instance which handle:
+ * <ul>
+ * <li>automatic reset of Orchestrator data after each method when used as a {@link org.junit.Rule},
+ * after each class when used as a {@link org.junit.ClassRule}</li>
+ * <li>automatic reset of server properties after each method when used as a {@link org.junit.Rule},
+ * after each class when used as a {@link org.junit.ClassRule}</li>
+ * <li>associating project with a specific Quality Profile before running an analysis</li>
+ * <li>provisioning a project before its first analysis so that a Quality Profile can be associated to it</li>
+ * <li>"restoring" a Quality Profile before an analysis with a specific Quality Profile</li>
+ * </ul>
+ *
+ * This Rule has preparatory methods ({@link #registerProfile(String)} and {@link #registerProject(String)}) which
+ * will allow consequent calls to the rule methods to be based solely on Quality Profile and Project keys. In addition,
+ * these methods returns the Quality Profile and Project key to avoid information duplication (the only magic string
+ * the IT developer has to know is the relative path of the Project or the Quality Profile).
+ *
+ * To run an analysis, use method {@link #newProjectAnalysis(String)} to create a {@link ProjectAnalysis}
+ * object. This object has a {@link ProjectAnalysis#run()} method which will start the analysis.
+ * {@link ProjectAnalysis} can safely be reused to run the same analysis multiple times. In addition, these objects are
+ * immutable. Any call to one of their method which would modify their state will create a new instance which can also
+ * be reused at will.
+ */
+public class ProjectAnalysisRule extends ExternalResource {
+
+ private final Orchestrator orchestrator;
+ private final LoadedProfiles loadedProfiles = new LoadedProfiles();
+ private final LoadedProjects loadedProjects = new LoadedProjects();
+ private final Set<String> serverProperties = new HashSet<>();
+
+ private ProjectAnalysisRule(Orchestrator orchestrator) {
+ this.orchestrator = orchestrator;
+ }
+
+ public static ProjectAnalysisRule from(Orchestrator orchestrator) {
+ return new ProjectAnalysisRule(requireNonNull(orchestrator, "Orchestrator instance can not be null"));
+ }
+
+ /**
+ * @param relativePathToProfile eg.: "/issue/suite/IssueFilterExtensionTest/xoo-with-many-rules.xml"
+ *
+ * @return the quality profile key
+ */
+ public String registerProfile(String relativePathToProfile) {
+ return this.loadedProfiles.loadProfile(relativePathToProfile);
+ }
+
+ /**
+ * @param projectRelativePath path relative to it/it-projects, eg. "shared/xoo-multi-modules-sample"
+ *
+ * @return the project key
+ */
+ public String registerProject(String projectRelativePath) {
+ return this.loadedProjects.load(projectRelativePath);
+ }
+
+ public ProjectAnalysis newProjectAnalysis(String projectKey) {
+ ProjectState projectState = this.loadedProjects.getProjectState(projectKey);
+
+ return new ProjectAnalysisImpl(projectState, null, false);
+ }
+
+ @Override
+ protected void before() throws Throwable {
+ orchestrator.resetData();
+ }
+
+ @Override
+ protected void after() {
+ resetServerProperties();
+ resetRuleState();
+ }
+
+ private void resetServerProperties() {
+ for (String serverProperty : serverProperties) {
+ setServerPropertyImpl(serverProperty, null);
+ }
+ }
+
+ public void setServerPropertyImpl(String key, @Nullable String value) {
+ if (value == null) {
+ orchestrator.getServer().getAdminWsClient().delete(new PropertyDeleteQuery(key));
+ } else {
+ orchestrator.getServer().getAdminWsClient().update(new PropertyUpdateQuery().setKey(key).setValue(value));
+ }
+ }
+
+ public ProjectAnalysisRule setServerProperty(String key, String value) {
+ setServerPropertyImpl(key, value);
+ this.serverProperties.add(key);
+ return this;
+ }
+
+ @Immutable
+ private final class ProjectAnalysisImpl implements ProjectAnalysis {
+ private final ProjectState projectState;
+ @CheckForNull
+ private final Profile qualityProfile;
+ private final boolean debugLogs;
+ @CheckForNull
+ private final String[] properties;
+
+ private ProjectAnalysisImpl(ProjectState projectState, @Nullable Profile qualityProfile, boolean debugLogs, String... properties) {
+ this.projectState = projectState;
+ this.qualityProfile = qualityProfile;
+ this.debugLogs = debugLogs;
+ this.properties = properties;
+ }
+
+ @Override
+ public ProjectAnalysis withQualityProfile(String qualityProfileKey) {
+ checkNotNull(qualityProfileKey, "Specified Quality Profile Key can not be null");
+ if (this.qualityProfile != null && this.qualityProfile.getProfileKey().equals(qualityProfileKey)) {
+ return this;
+ }
+
+ return new ProjectAnalysisImpl(this.projectState, loadedProfiles.getState(qualityProfileKey), this.debugLogs, this.properties);
+ }
+
+ @Override
+ public ProjectAnalysis withXooEmptyProfile() {
+ if (this.qualityProfile == Profile.XOO_EMPTY_PROFILE) {
+ return this;
+ }
+ return new ProjectAnalysisImpl(this.projectState, Profile.XOO_EMPTY_PROFILE, this.debugLogs, this.properties);
+ }
+
+ @Override
+ public ProjectAnalysis withDebugLogs(boolean enabled) {
+ if (this.debugLogs == enabled) {
+ return this;
+ }
+ return new ProjectAnalysisImpl(this.projectState, this.qualityProfile, enabled, this.properties);
+ }
+
+ @Override
+ public ProjectAnalysis withProperties(String... properties) {
+ checkArgument(
+ properties == null || properties.length % 2 == 0,
+ "there must be an even number of String parameters (got %s): key/value pairs must be complete", properties == null ? 0 : properties.length);
+ return new ProjectAnalysisImpl(this.projectState, this.qualityProfile, this.debugLogs, properties);
+ }
+
+ @Override
+ public void run() {
+ provisionIfNecessary();
+ setQualityProfileIfNecessary();
+ runAnalysis();
+ }
+
+ private void setQualityProfileIfNecessary() {
+ if (this.qualityProfile != null) {
+ if (this.qualityProfile != Profile.XOO_EMPTY_PROFILE) {
+ orchestrator.getServer().restoreProfile(FileLocation.ofClasspath(this.qualityProfile.getRelativePath()));
+ }
+ orchestrator.getServer().associateProjectToQualityProfile(
+ this.projectState.getProjectKey(),
+ this.qualityProfile.getLanguageKey(),
+ this.qualityProfile.getProfileKey());
+ }
+ }
+
+ private void provisionIfNecessary() {
+ if (this.qualityProfile != null && !projectState.isProvisioned()) {
+ String projectKey = projectState.getProjectKey();
+ orchestrator.getServer().provisionProject(projectKey, MoreObjects.firstNonNull(projectState.getProjectName(), projectKey));
+ projectState.setProvisioned(true);
+ }
+ }
+
+ private SonarRunner runAnalysis() {
+ SonarRunner sonarRunner = SonarRunner.create(projectState.getProjectDir());
+ ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
+ for (int i = 0; i < this.properties.length; i += 2) {
+ builder.put(this.properties[i], this.properties[i + 1]);
+ }
+ SonarRunner scan = sonarRunner.setDebugLogs(this.debugLogs).setProperties(builder.build());
+ orchestrator.executeBuild(scan);
+ return scan;
+ }
+ }
+
+ private void resetRuleState() {
+ this.loadedProjects.reset();
+ this.loadedProfiles.reset();
+ this.serverProperties.clear();
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package util;
+
+import java.io.File;
+import java.util.Properties;
+
+import static com.google.common.base.Preconditions.checkState;
+import static util.LoadedProjects.SONAR_PROJECT_PROPERTIES_FILE_NAME;
+
+final class ProjectState {
+ private static final String SONAR_PROJECT_KEY_PROPERTY_NAME = "sonar.projectKey";
+ private static final String SONAR_PROJECT_NAME_PROPERTY_NAME = "sonar.projectName";
+
+ private final File projectDir;
+ private final Properties properties;
+ private boolean provisioned = false;
+
+ ProjectState(File projectDir, Properties properties) {
+ this.projectDir = projectDir;
+ this.properties = properties;
+ }
+
+ public File getProjectDir() {
+ return projectDir;
+ }
+
+ public Properties getProperties() {
+ return properties;
+ }
+
+ public String getProjectKey() {
+ return getProperty(SONAR_PROJECT_KEY_PROPERTY_NAME);
+ }
+
+ public String getProjectName() {
+ return getProperty(SONAR_PROJECT_NAME_PROPERTY_NAME);
+ }
+
+ private String getProperty(String propertyName) {
+ String value = this.properties.getProperty(propertyName);
+ checkState(value != null, "Property %s is missing in %s file in project directory %s",
+ propertyName, SONAR_PROJECT_PROPERTIES_FILE_NAME, projectDir.getAbsolutePath());
+ return value;
+ }
+
+ public boolean isProvisioned() {
+ return provisioned;
+ }
+
+ public void setProvisioned(boolean provisioned) {
+ this.provisioned = provisioned;
+ }
+}