From 6e89bcaaba4fe3dc4e6145830250c920ed696059 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Tue, 9 Feb 2016 17:16:02 +0100 Subject: [PATCH] Move ManualIssueTest ITs --- .../src/test/java/it/Category2Suite.java | 2 + .../test/java/it/issue/AbstractIssueTest.java | 6 +- .../test/java/it/issue/IssueActionTest.java | 4 +- .../test/java/it/issue/ManualIssueTest.java | 355 ++++++++++++++++++ 4 files changed, 363 insertions(+), 4 deletions(-) create mode 100644 it/it-tests/src/test/java/it/issue/ManualIssueTest.java diff --git a/it/it-tests/src/test/java/it/Category2Suite.java b/it/it-tests/src/test/java/it/Category2Suite.java index 718b5313f26..77f17dd5e88 100644 --- a/it/it-tests/src/test/java/it/Category2Suite.java +++ b/it/it-tests/src/test/java/it/Category2Suite.java @@ -39,6 +39,7 @@ import it.issue.IssuePurgeTest; import it.issue.IssueSearchTest; import it.issue.IssueTrackingTest; import it.issue.IssueWorkflowTest; +import it.issue.ManualIssueTest; import it.issue.NewIssuesMeasureTest; import it.measure.NewDebtRatioMeasureTest; import it.measure.TechnicalDebtMeasureVariationTest; @@ -81,6 +82,7 @@ import static util.ItUtils.xooPlugin; IssueSearchTest.class, IssueTrackingTest.class, IssueWorkflowTest.class, + ManualIssueTest.class, NewIssuesMeasureTest.class, // rule ManualRulesTest.class, diff --git a/it/it-tests/src/test/java/it/issue/AbstractIssueTest.java b/it/it-tests/src/test/java/it/issue/AbstractIssueTest.java index eb6ac7dba1f..c2a858fddff 100644 --- a/it/it-tests/src/test/java/it/issue/AbstractIssueTest.java +++ b/it/it-tests/src/test/java/it/issue/AbstractIssueTest.java @@ -64,8 +64,10 @@ public abstract class AbstractIssueTest { return searchIssues(issueKeys, false); } - static List searchIssues(String issueKey, boolean withComments) { - return searchIssues(new String[] {issueKey}, withComments); + static Issue searchIssue(String issueKey, boolean withComments) { + List issues = searchIssues(new String[] {issueKey}, withComments); + assertThat(issues).hasSize(1); + return issues.iterator().next(); } static List searchIssues(String[] issueKeys, boolean withComments) { diff --git a/it/it-tests/src/test/java/it/issue/IssueActionTest.java b/it/it-tests/src/test/java/it/issue/IssueActionTest.java index 858ee73b513..495d8c41d31 100644 --- a/it/it-tests/src/test/java/it/issue/IssueActionTest.java +++ b/it/it-tests/src/test/java/it/issue/IssueActionTest.java @@ -72,7 +72,7 @@ public class IssueActionTest extends AbstractIssueTest { assertThat(comment.createdAt()).isNotNull(); // reload issue - Issue reloaded = searchIssues(issue.key(), true).iterator().next(); + Issue reloaded = searchIssue(issue.key(), true); assertThat(reloaded.comments()).hasSize(1); assertThat(reloaded.comments().get(0).key()).isEqualTo(comment.key()); @@ -229,7 +229,7 @@ public class IssueActionTest extends AbstractIssueTest { adminIssueClient().doAction(issue.key(), "fake"); // reload issue - Issue reloaded = searchIssues(issue.key(), true).iterator().next(); + Issue reloaded = searchIssue(issue.key(), true); assertThat(reloaded.comments()).hasSize(1); assertThat(reloaded.comments().get(0).htmlText()).isEqualTo("New Comment from fake action"); diff --git a/it/it-tests/src/test/java/it/issue/ManualIssueTest.java b/it/it-tests/src/test/java/it/issue/ManualIssueTest.java new file mode 100644 index 00000000000..f4e8c3be78e --- /dev/null +++ b/it/it-tests/src/test/java/it/issue/ManualIssueTest.java @@ -0,0 +1,355 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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 it.issue; + +import com.google.common.collect.ImmutableMap; +import java.util.List; +import org.junit.Before; +import org.junit.Test; +import org.sonar.wsclient.issue.Issue; +import org.sonar.wsclient.issue.IssueComment; +import org.sonar.wsclient.issue.IssueQuery; +import org.sonar.wsclient.issue.Issues; +import org.sonar.wsclient.issue.NewIssue; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; +import static util.ItUtils.runProjectAnalysis; +import static util.ItUtils.verifyHttpException; + +/** + * SONAR-4304 + */ +public class ManualIssueTest extends AbstractIssueTest { + + private final static String COMPONENT_KEY = "sample:src/main/xoo/sample/Sample.xoo"; + + @Before + public void before() { + ORCHESTRATOR.resetData(); + analyzeProject(); + createManualRule(); + } + + @Test + public void create_manual_issue_through_ws() throws Exception { + // Create the manual issue + Issue newIssue = adminIssueClient().create(NewIssue.create().component(COMPONENT_KEY) + .rule("manual:invalidclassname") + .line(3) + .severity("CRITICAL") + .message("The name 'Sample' is too generic")); + assertThat(newIssue.key()).isNotNull(); + assertThat(newIssue.creationDate()).isNotNull(); + assertThat(newIssue.updateDate()).isNotNull(); + assertThat(newIssue.ruleKey()).isEqualTo("manual:invalidclassname"); + assertThat(newIssue.line()).isEqualTo(3); + assertThat(newIssue.severity()).isEqualTo(("CRITICAL")); + assertThat(newIssue.message()).isEqualTo(("The name 'Sample' is too generic")); + assertThat(newIssue.status()).isEqualTo("OPEN"); + assertThat(newIssue.resolution()).isNull(); + assertThat(newIssue.reporter()).isEqualTo("admin"); + + Issues issues = search(IssueQuery.create().issues(newIssue.key())); + assertThat(issues.list().get(0).reporter()).isEqualTo("admin"); + + // get the detail of the reporter + assertThat(issues.user("admin").name()).isEqualTo("Administrator"); + } + + @Test + public void scan_should_keep_manual_issues_open() throws Exception { + // Create the manual issue + Issue newIssue = adminIssueClient().create(NewIssue.create().component(COMPONENT_KEY) + .rule("manual:invalidclassname") + .line(3) + .severity("CRITICAL") + .message("The name 'Sample' is too generic")); + assertThat(newIssue.key()).isNotNull(); + assertThat(newIssue.creationDate()).isNotNull(); + assertThat(newIssue.updateDate()).isNotNull(); + + // the metric 'issues' is not up-to-date yet + assertThat(searchIssuesByComponent(COMPONENT_KEY)).hasSize(1); + + // re-inspect the project : the issue still exists + analyzeProject(); + + Issue issue = searchIssueByKey(newIssue.key()); + assertThat(issue.ruleKey()).isEqualTo("manual:invalidclassname"); + assertThat(issue.line()).isEqualTo(3); + assertThat(issue.severity()).isEqualTo(("CRITICAL")); + assertThat(issue.message()).isEqualTo(("The name 'Sample' is too generic")); + assertThat(issue.status()).isEqualTo("OPEN"); + assertThat(issue.resolution()).isNull(); + assertThat(issue.reporter()).isEqualTo("admin"); + assertThat(issue.creationDate()).isEqualTo(newIssue.creationDate()); + assertThat(issue.updateDate()).isEqualTo(newIssue.updateDate()); + } + + @Test + public void scan_should_close_issues_on_deleted_manual_rules() throws Exception { + // Create another manual rule + ORCHESTRATOR.getServer().adminWsClient().post("/api/rules/create", ImmutableMap.of( + "manual_key", "ruletoberemoved", + "name", "RuleToBeRemoved", + "markdown_description", "Rule to be removed" + )); + + // Create the manual issue + Issue newIssue = adminIssueClient().create(NewIssue.create().component(COMPONENT_KEY) + .rule("manual:ruletoberemoved") + .line(3) + .severity("CRITICAL") + .message("The name 'Sample' is too generic")); + assertThat(newIssue.status()).isEqualTo("OPEN"); + + // Delete the manual rule (will be in fact disabled in the db, not removed) + ORCHESTRATOR.getServer().adminWsClient().post("/api/rules/delete", ImmutableMap.of("key", "manual:ruletoberemoved")); + + analyzeProject(); + Issue closedIssue = searchIssueByKey(newIssue.key()); + assertThat(closedIssue.status()).isEqualTo("CLOSED"); + assertThat(closedIssue.resolution()).isEqualTo("REMOVED"); + assertThat(closedIssue.creationDate()).isEqualTo(newIssue.creationDate()); + assertThat(closedIssue.updateDate().before(newIssue.updateDate())).isFalse(); + assertThat(closedIssue.closeDate().before(closedIssue.creationDate())).isFalse(); + } + + @Test + public void scan_should_close_manual_resolved_issues() throws Exception { + // Create the manual issue + Issue newIssue = adminIssueClient().create(NewIssue.create().component(COMPONENT_KEY) + .rule("manual:invalidclassname") + .line(3) + .severity("CRITICAL") + .message("The name 'Sample' is too generic")); + assertThat(newIssue.status()).isEqualTo("OPEN"); + + // mark issue as resolved + adminIssueClient().doTransition(newIssue.key(), "resolve"); + + analyzeProject(); + Issue closedIssue = searchIssueByKey(newIssue.key()); + assertThat(closedIssue.status()).isEqualTo("CLOSED"); + assertThat(closedIssue.resolution()).isEqualTo("FIXED"); + assertThat(closedIssue.creationDate()).isEqualTo(newIssue.creationDate()); + assertThat(closedIssue.updateDate().before(newIssue.updateDate())).isFalse(); + assertThat(closedIssue.closeDate().before(closedIssue.creationDate())).isFalse(); + } + + @Test + public void add_comment_to_manual_issue() throws Exception { + // Create the manual issue + Issue manualIssue = adminIssueClient().create(NewIssue.create().component(COMPONENT_KEY) + .rule("manual:invalidclassname") + .line(3) + .severity("CRITICAL") + .message("The name 'Sample' is too generic")); + + // Add a comment on the manual issue + IssueComment comment = adminIssueClient().addComment(manualIssue.key(), "this is my *comment*"); + + // Reload manual issue + Issue reloaded = searchIssueWithComments(manualIssue.key()); + + assertThat(reloaded.comments()).hasSize(1); + assertThat(reloaded.comments().get(0).key()).isEqualTo(comment.key()); + } + + @Test + public void resolve_manual_issue() throws Exception { + // Create the manual issue + Issue manualIssue = adminIssueClient().create(NewIssue.create().component(COMPONENT_KEY) + .rule("manual:invalidclassname") + .line(3) + .severity("CRITICAL") + .message("The name 'Sample' is too generic")); + + // Resolve the manual issue + adminIssueClient().doTransition(manualIssue.key(), "resolve"); + + // Check the manual issue is well resolved + Issue reloaded = searchIssueByKey(manualIssue.key()); + assertThat(reloaded.status()).isEqualTo("RESOLVED"); + assertThat(reloaded.resolution()).isEqualTo("FIXED"); + assertThat(reloaded.creationDate()).isEqualTo(manualIssue.creationDate()); + assertThat(reloaded.updateDate().before(manualIssue.updateDate())).isFalse(); + + analyzeProject(); + + // Reload after analyse -> manual issue should be closed + reloaded = searchIssueByKey(manualIssue.key()); + assertThat(reloaded.status()).isEqualTo("CLOSED"); + assertThat(reloaded.resolution()).isEqualTo("FIXED"); + assertThat(reloaded.creationDate()).isEqualTo(manualIssue.creationDate()); + assertThat(reloaded.updateDate().before(manualIssue.updateDate())).isFalse(); + assertThat(reloaded.closeDate()).isNotNull(); + assertThat(reloaded.closeDate().before(reloaded.creationDate())).isFalse(); + } + + @Test + public void resolve_and_reopen_manual_issue() throws Exception { + // Create the manual issue + Issue issue = adminIssueClient().create(NewIssue.create().component(COMPONENT_KEY) + .rule("manual:invalidclassname") + .line(3) + .severity("CRITICAL") + .message("The name 'Sample' is too generic")); + + // Resolve the manual issue + adminIssueClient().doTransition(issue.key(), "resolve"); + + // Check the manual issue is well resolved + assertThat(searchIssueByKey(issue.key()).status()).isEqualTo("RESOLVED"); + + analyzeProject(); + // Reload after analyse -> manual issue is closed + assertThat(searchIssueByKey(issue.key()).status()).isEqualTo("CLOSED"); + + // Reopen the manual issue + adminIssueClient().doTransition(issue.key(), "reopen"); + + analyzeProject(); + // Reload after analyse -> manual issue is reopened + Issue reloaded = searchIssueByKey(issue.key()); + assertThat(reloaded.status()).isEqualTo("REOPENED"); + assertThat(reloaded.resolution()).isNull(); + assertThat(reloaded.creationDate()).isEqualTo(issue.creationDate()); + assertThat(reloaded.updateDate().before(issue.updateDate())).isFalse(); + } + + @Test + public void fail_if_unknown_rule() throws Exception { + try { + adminIssueClient().create(NewIssue.create().component(COMPONENT_KEY) + // this rule does not exist + .rule("manual:unknown-rule") + .line(3) + .severity("CRITICAL") + .message("The name 'Sample' is too generic")); + fail(); + } catch (Exception e) { + verifyHttpException(e, 400); + } + } + + @Test + public void fail_if_missing_rule() throws Exception { + try { + adminIssueClient().create(NewIssue.create().component(COMPONENT_KEY) + .line(3) + .severity("CRITICAL") + .message("The name 'Sample' is too generic")); + fail(); + } catch (Exception e) { + verifyHttpException(e, 400); + } + } + + @Test + public void fail_if_not_a_manual_rule() throws Exception { + try { + adminIssueClient().create(NewIssue.create().component(COMPONENT_KEY) + // Not a manual rule + .rule("xoo:OneIssuePerLine") + .line(3) + .severity("CRITICAL") + .message("The name 'Sample' is too generic")); + fail(); + } catch (Exception e) { + verifyHttpException(e, 400); + } + } + + @Test + public void fail_if_rule_is_disabled() throws Exception { + // Create and delete a manual rule + ORCHESTRATOR.getServer().adminWsClient().post("/api/rules/create", ImmutableMap.of( + "manual_key", "anotherinvalidclassname", + "name", "AnotherInvalidClassName", + "markdown_description", "Another invalid class name" + )); + ORCHESTRATOR.getServer().adminWsClient().post("/api/rules/delete", ImmutableMap.of( + "key", "manual:anotherinvalidclassname" + )); + + try { + adminIssueClient().create(NewIssue.create().component(COMPONENT_KEY) + // This rule is disabled + .rule("manual:anotherinvalidclassname") + .line(3) + .severity("CRITICAL") + .message("The name 'Sample' is too generic")); + fail(); + } catch (Exception e) { + verifyHttpException(e, 400); + } + } + + @Test + public void fail_if_component_does_not_exist() throws Exception { + try { + adminIssueClient().create(NewIssue.create().component("unknown component") + .rule("manual:invalidclassname") + .line(3) + .severity("CRITICAL") + .message("The name 'Sample' is too generic")); + fail(); + } catch (Exception e) { + verifyHttpException(e, 400); + } + } + + @Test + public void fail_if_not_logged_in() throws Exception { + try { + issueClient().create(NewIssue.create().component("unknown component") + .rule("manual:invalidclassname") + .line(3) + .severity("CRITICAL") + .message("The name 'Sample' is too generic")); + fail(); + } catch (Exception e) { + verifyHttpException(e, 401); + } + } + + private static void analyzeProject() { + // no active rules + runProjectAnalysis(ORCHESTRATOR, "shared/xoo-sample"); + } + + private static void createManualRule() { + ORCHESTRATOR.getServer().adminWsClient().post("/api/rules/create", ImmutableMap.of( + "manual_key", "invalidclassname", + "name", "InvalidClassName", + "markdown_description", "Invalid class name" + )); + } + + private static List searchIssuesByComponent(String componentKey) { + return search(IssueQuery.create().components(componentKey)).list(); + } + + private static Issue searchIssueWithComments(String issueKey) { + return searchIssue(issueKey, true); + } +} -- 2.39.5