From: Julien Lancelot Date: Fri, 18 Apr 2014 12:07:18 +0000 (+0200) Subject: Revert "SONAR-5218 Once a module has been turned into a project, its issues are no... X-Git-Tag: 4.3~5 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=f9f85043a17edeb69f3ea5a93e56b4d60e3a22ae;p=sonarqube.git Revert "SONAR-5218 Once a module has been turned into a project, its issues are no more visible in the UI" This reverts commit 6334cb7d7397e1455099611b3b1259ad050706e6. --- diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java index 1838dc5311e..65b2a5a31a6 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java @@ -157,7 +157,6 @@ public class IssueTrackingDecorator implements Decorator { issue.setStatus(ref.getStatus()); issue.setAssignee(ref.getAssignee()); issue.setAuthorLogin(ref.getAuthorLogin()); - if (ref.getIssueAttributes() != null) { issue.setAttributes(KeyValueFormat.parse(ref.getIssueAttributes())); } @@ -181,7 +180,6 @@ public class IssueTrackingDecorator implements Decorator { Long debtInMinutes = ref.getDebt(); Duration previousTechnicalDebt = debtInMinutes != null ? Duration.create(debtInMinutes) : null; updater.setPastTechnicalDebt(issue, previousTechnicalDebt, changeContext); - updater.setPastProject(issue, ref.getRootComponentKey(), changeContext); } } diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueTrackingDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueTrackingDecoratorTest.java index 121b473d2d8..05aa5bdb2d7 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueTrackingDecoratorTest.java +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueTrackingDecoratorTest.java @@ -508,7 +508,7 @@ public class IssueTrackingDecoratorTest extends AbstractDaoTestCase { @Test public void merge_matched_issue() throws Exception { IssueDto previousIssue = new IssueDto().setKee("ABCDE").setResolution(null).setStatus("OPEN").setRuleKey_unit_test_only("squid", "AvoidCycle") - .setLine(10).setSeverity("MAJOR").setMessage("Message").setEffortToFix(1.5).setDebt(1L).setRootComponentKey_unit_test_only("sample"); + .setLine(10).setSeverity("MAJOR").setMessage("Message").setEffortToFix(1.5).setDebt(1L); DefaultIssue issue = new DefaultIssue(); IssueTrackingResult trackingResult = mock(IssueTrackingResult.class); @@ -521,7 +521,6 @@ public class IssueTrackingDecoratorTest extends AbstractDaoTestCase { verify(updater).setPastMessage(eq(issue), eq("Message"), any(IssueChangeContext.class)); verify(updater).setPastEffortToFix(eq(issue), eq(1.5), any(IssueChangeContext.class)); verify(updater).setPastTechnicalDebt(eq(issue), eq(Duration.create(1L)), any(IssueChangeContext.class)); - verify(updater).setPastProject(eq(issue), eq("sample"), any(IssueChangeContext.class)); } @Test diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/DefaultIssuable.java b/sonar-batch/src/main/java/org/sonar/batch/issue/DefaultIssuable.java index 578bb2bb49e..62b44e7d69e 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/DefaultIssuable.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/DefaultIssuable.java @@ -24,7 +24,6 @@ import org.sonar.api.component.Component; import org.sonar.api.issue.Issuable; import org.sonar.api.issue.Issue; import org.sonar.api.issue.internal.DefaultIssue; -import org.sonar.api.resources.Project; import org.sonar.core.issue.DefaultIssueBuilder; import java.util.List; @@ -37,18 +36,16 @@ public class DefaultIssuable implements Issuable { private final ModuleIssues moduleIssues; private final IssueCache cache; private final Component component; - private final Project project; - DefaultIssuable(Component component, Project project, ModuleIssues moduleIssues, IssueCache cache) { + DefaultIssuable(Component component, ModuleIssues moduleIssues, IssueCache cache) { this.component = component; - this.project = project; this.moduleIssues = moduleIssues; this.cache = cache; } @Override public IssueBuilder newIssueBuilder() { - return new DefaultIssueBuilder().componentKey(component.key()).projectKey(project.getKey()); + return new DefaultIssueBuilder().componentKey(component.key()); } @Override diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/IssuableFactory.java b/sonar-batch/src/main/java/org/sonar/batch/issue/IssuableFactory.java index 7491bbb7814..147ab7c7c15 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/IssuableFactory.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/IssuableFactory.java @@ -22,7 +22,6 @@ package org.sonar.batch.issue; import org.sonar.api.component.Component; import org.sonar.api.issue.Issuable; import org.sonar.api.resources.Scopes; -import org.sonar.batch.ProjectTree; import org.sonar.core.component.PerspectiveBuilder; import org.sonar.core.component.ResourceComponent; @@ -36,13 +35,11 @@ public class IssuableFactory extends PerspectiveBuilder { private final ModuleIssues moduleIssues; private final IssueCache cache; - private final ProjectTree projectTree; - public IssuableFactory(ModuleIssues moduleIssues, IssueCache cache, ProjectTree projectTree) { + public IssuableFactory(ModuleIssues moduleIssues, IssueCache cache) { super(Issuable.class); this.moduleIssues = moduleIssues; this.cache = cache; - this.projectTree = projectTree; } @CheckForNull @@ -52,6 +49,6 @@ public class IssuableFactory extends PerspectiveBuilder { if (component instanceof ResourceComponent) { supported = Scopes.isHigherThanOrEquals(((ResourceComponent) component).scope(), Scopes.FILE); } - return supported ? new DefaultIssuable(component, projectTree.getRootProject(), moduleIssues, cache) : null; + return supported ? new DefaultIssuable(component, moduleIssues, cache) : null; } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/ModuleIssues.java b/sonar-batch/src/main/java/org/sonar/batch/issue/ModuleIssues.java index 6f46e2cc7a9..c0a49d68671 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/ModuleIssues.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ModuleIssues.java @@ -67,7 +67,6 @@ public class ModuleIssues { private DefaultIssue newIssue(Violation violation) { return (DefaultIssue) new DefaultIssueBuilder() .componentKey(violation.getResource().getEffectiveKey()) - .projectKey(project.getRoot().getEffectiveKey()) .ruleKey(RuleKey.of(violation.getRule().getRepositoryKey(), violation.getRule().getKey())) .effortToFix(violation.getCost()) .line(violation.getLineId()) diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/ScanIssueStorage.java b/sonar-batch/src/main/java/org/sonar/batch/issue/ScanIssueStorage.java index 723082eb335..23dab80cde1 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/ScanIssueStorage.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ScanIssueStorage.java @@ -23,7 +23,6 @@ import org.sonar.api.BatchComponent; import org.sonar.api.database.model.Snapshot; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.rules.RuleFinder; -import org.sonar.batch.ProjectTree; import org.sonar.batch.index.SnapshotCache; import org.sonar.core.issue.db.IssueStorage; import org.sonar.core.persistence.MyBatis; @@ -35,18 +34,16 @@ public class ScanIssueStorage extends IssueStorage implements BatchComponent { private final SnapshotCache snapshotCache; private final ResourceDao resourceDao; - private final ProjectTree projectTree; - public ScanIssueStorage(MyBatis mybatis, RuleFinder ruleFinder, SnapshotCache snapshotCache, ResourceDao resourceDao, ProjectTree projectTree) { + public ScanIssueStorage(MyBatis mybatis, RuleFinder ruleFinder, SnapshotCache snapshotCache, ResourceDao resourceDao) { super(mybatis, ruleFinder); this.snapshotCache = snapshotCache; this.resourceDao = resourceDao; - this.projectTree = projectTree; } @Override protected long componentId(DefaultIssue issue) { - Snapshot snapshot = snapshotCache.get(issue.componentKey()); + Snapshot snapshot = getSnapshot(issue); if (snapshot != null) { return snapshot.getResourceId(); } @@ -61,7 +58,19 @@ public class ScanIssueStorage extends IssueStorage implements BatchComponent { @Override protected long projectId(DefaultIssue issue) { - return projectTree.getRootProject().getId(); + Snapshot snapshot = getSnapshot(issue); + if (snapshot != null) { + return snapshot.getRootProjectId(); + } + throw new IllegalStateException("Project id not found for: " + issue.componentKey()); + } + + private Snapshot getSnapshot(DefaultIssue issue) { + Snapshot snapshot = snapshotCache.get(issue.componentKey()); + if (snapshot != null) { + return snapshot; + } + return null; } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/DefaultIssuableTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/DefaultIssuableTest.java index 90721058222..1f557c64ad1 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/DefaultIssuableTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/DefaultIssuableTest.java @@ -23,7 +23,6 @@ import org.junit.Test; import org.sonar.api.component.Component; import org.sonar.api.issue.Issue; import org.sonar.api.issue.internal.DefaultIssue; -import org.sonar.api.resources.Project; import java.util.Arrays; import java.util.List; @@ -36,7 +35,6 @@ public class DefaultIssuableTest { ModuleIssues moduleIssues = mock(ModuleIssues.class); IssueCache cache = mock(IssueCache.class); - Project project = mock(Project.class); Component component = mock(Component.class); @Test @@ -46,7 +44,7 @@ public class DefaultIssuableTest { DefaultIssue unresolved = new DefaultIssue(); when(cache.byComponent("struts:org.apache.Action")).thenReturn(Arrays.asList(resolved, unresolved)); - DefaultIssuable perspective = new DefaultIssuable(component, project, moduleIssues, cache); + DefaultIssuable perspective = new DefaultIssuable(component, moduleIssues, cache); List issues = perspective.issues(); assertThat(issues).containsOnly(unresolved); @@ -59,7 +57,7 @@ public class DefaultIssuableTest { DefaultIssue unresolved = new DefaultIssue(); when(cache.byComponent("struts:org.apache.Action")).thenReturn(Arrays.asList(resolved, unresolved)); - DefaultIssuable perspective = new DefaultIssuable(component, project, moduleIssues, cache); + DefaultIssuable perspective = new DefaultIssuable(component, moduleIssues, cache); List issues = perspective.resolvedIssues(); assertThat(issues).containsOnly(resolved); diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/IssuableFactoryTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/IssuableFactoryTest.java index 4753023ccbc..d11d0a72111 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/IssuableFactoryTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/IssuableFactoryTest.java @@ -25,7 +25,6 @@ import org.sonar.api.component.Component; import org.sonar.api.issue.Issuable; import org.sonar.api.resources.File; import org.sonar.api.resources.Project; -import org.sonar.batch.ProjectTree; import org.sonar.core.component.ResourceComponent; import static org.fest.assertions.Assertions.assertThat; @@ -35,11 +34,10 @@ public class IssuableFactoryTest { ModuleIssues moduleIssues = mock(ModuleIssues.class); IssueCache cache = mock(IssueCache.class, Mockito.RETURNS_MOCKS); - ProjectTree projectTree = mock(ProjectTree.class); @Test public void file_should_be_issuable() throws Exception { - IssuableFactory factory = new IssuableFactory(moduleIssues, cache, projectTree); + IssuableFactory factory = new IssuableFactory(moduleIssues, cache); Component component = new ResourceComponent(new File("foo/bar.c").setEffectiveKey("foo/bar.c")); Issuable issuable = factory.loadPerspective(Issuable.class, component); @@ -50,7 +48,7 @@ public class IssuableFactoryTest { @Test public void project_should_be_issuable() throws Exception { - IssuableFactory factory = new IssuableFactory(moduleIssues, cache, projectTree); + IssuableFactory factory = new IssuableFactory(moduleIssues, cache); Component component = new ResourceComponent(new Project("Foo").setEffectiveKey("foo")); Issuable issuable = factory.loadPerspective(Issuable.class, component); diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ModuleIssuesTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ModuleIssuesTest.java index bacfe55be16..3df87485b74 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/ModuleIssuesTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ModuleIssuesTest.java @@ -73,7 +73,6 @@ public class ModuleIssuesTest { public void setUp() { when(project.getAnalysisDate()).thenReturn(new Date()); when(project.getEffectiveKey()).thenReturn("org.apache:struts-core"); - when(project.getRoot()).thenReturn(project); } @Test @@ -226,7 +225,6 @@ public class ModuleIssuesTest { assertThat(issue.key()).isNotEmpty(); assertThat(issue.ruleKey().toString()).isEqualTo("squid:AvoidCycle"); assertThat(issue.componentKey()).isEqualTo("struts:src/org/struts/Action.java"); - assertThat(issue.projectKey()).isEqualTo("org.apache:struts-core"); } @Test diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ScanIssueStorageTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ScanIssueStorageTest.java index 8866851b3da..7875ae97f25 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/ScanIssueStorageTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ScanIssueStorageTest.java @@ -19,19 +19,13 @@ */ package org.sonar.batch.issue; -import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; import org.sonar.api.database.model.Snapshot; import org.sonar.api.issue.internal.DefaultIssue; -import org.sonar.api.resources.Project; import org.sonar.api.rule.RuleKey; import org.sonar.api.rules.Rule; import org.sonar.api.rules.RuleFinder; import org.sonar.api.rules.RuleQuery; -import org.sonar.batch.ProjectTree; import org.sonar.batch.index.SnapshotCache; import org.sonar.core.persistence.AbstractDaoTestCase; import org.sonar.core.resource.ResourceDao; @@ -40,28 +34,16 @@ import java.util.Collection; import static org.fest.assertions.Assertions.assertThat; import static org.fest.assertions.Fail.fail; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -@RunWith(MockitoJUnitRunner.class) public class ScanIssueStorageTest extends AbstractDaoTestCase { - - @Mock - SnapshotCache snapshotCache; - - @Mock - ProjectTree projectTree; - - ScanIssueStorage storage; - - @Before - public void setUp() throws Exception { - storage = new ScanIssueStorage(getMyBatis(), new FakeRuleFinder(), snapshotCache, new ResourceDao(getMyBatis()), projectTree); - } - @Test public void should_load_component_id_from_cache() throws Exception { + SnapshotCache snapshotCache = mock(SnapshotCache.class); when(snapshotCache.get("struts:Action.java")).thenReturn(new Snapshot().setResourceId(123)); + ScanIssueStorage storage = new ScanIssueStorage(getMyBatis(), new FakeRuleFinder(), snapshotCache, new ResourceDao(getMyBatis())); long componentId = storage.componentId(new DefaultIssue().setComponentKey("struts:Action.java")); assertThat(componentId).isEqualTo(123); @@ -70,8 +52,10 @@ public class ScanIssueStorageTest extends AbstractDaoTestCase { @Test public void should_load_component_id_from_db() throws Exception { setupData("should_load_component_id_from_db"); + SnapshotCache snapshotCache = mock(SnapshotCache.class); when(snapshotCache.get("struts:Action.java")).thenReturn(null); + ScanIssueStorage storage = new ScanIssueStorage(getMyBatis(), new FakeRuleFinder(), snapshotCache, new ResourceDao(getMyBatis())); long componentId = storage.componentId(new DefaultIssue().setComponentKey("struts:Action.java")); assertThat(componentId).isEqualTo(123); @@ -80,8 +64,10 @@ public class ScanIssueStorageTest extends AbstractDaoTestCase { @Test public void should_fail_to_load_component_id_if_unknown_component() throws Exception { setupData("should_fail_to_load_component_id_if_unknown_component"); + SnapshotCache snapshotCache = mock(SnapshotCache.class); when(snapshotCache.get("struts:Action.java")).thenReturn(null); + ScanIssueStorage storage = new ScanIssueStorage(getMyBatis(), new FakeRuleFinder(), snapshotCache, new ResourceDao(getMyBatis())); try { storage.componentId(new DefaultIssue().setComponentKey("struts:Action.java")); fail(); @@ -92,13 +78,29 @@ public class ScanIssueStorageTest extends AbstractDaoTestCase { @Test public void should_load_project_id() throws Exception { - when(projectTree.getRootProject()).thenReturn((Project) new Project("struts").setId(100)); + SnapshotCache snapshotCache = mock(SnapshotCache.class); + when(snapshotCache.get("struts:Action.java")).thenReturn(new Snapshot().setResourceId(123).setRootProjectId(100)); + ScanIssueStorage storage = new ScanIssueStorage(getMyBatis(), new FakeRuleFinder(), snapshotCache, new ResourceDao(getMyBatis())); long projectId = storage.projectId(new DefaultIssue().setComponentKey("struts:Action.java")); assertThat(projectId).isEqualTo(100); } + @Test + public void should_fail_to_load_project_id_if_unknown_component() throws Exception { + SnapshotCache snapshotCache = mock(SnapshotCache.class); + when(snapshotCache.get("struts:Action.java")).thenReturn(null); + + ScanIssueStorage storage = new ScanIssueStorage(getMyBatis(), new FakeRuleFinder(), snapshotCache, new ResourceDao(getMyBatis())); + try { + storage.projectId(new DefaultIssue().setComponentKey("struts:Action.java")); + fail(); + } catch (Exception e) { + assertThat(e).hasMessage("Project id not found for: struts:Action.java"); + } + } + static class FakeRuleFinder implements RuleFinder { @Override diff --git a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueBuilder.java b/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueBuilder.java index 859ad804ad2..68284cb07ce 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueBuilder.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueBuilder.java @@ -35,7 +35,6 @@ import java.util.UUID; public class DefaultIssueBuilder implements Issuable.IssueBuilder { private String componentKey; - private String projectKey; private RuleKey ruleKey; private Integer line; private String message; @@ -53,12 +52,6 @@ public class DefaultIssueBuilder implements Issuable.IssueBuilder { return this; } - - public DefaultIssueBuilder projectKey(String projectKey) { - this.projectKey = projectKey; - return this; - } - @Override public Issuable.IssueBuilder ruleKey(RuleKey ruleKey) { this.ruleKey = ruleKey; @@ -106,7 +99,6 @@ public class DefaultIssueBuilder implements Issuable.IssueBuilder { @Override public DefaultIssue build() { - Preconditions.checkNotNull(projectKey, "Project key must be set"); Preconditions.checkNotNull(componentKey, "Component key must be set"); Preconditions.checkNotNull(ruleKey, "Rule key must be set"); @@ -115,7 +107,6 @@ public class DefaultIssueBuilder implements Issuable.IssueBuilder { Preconditions.checkState(!Strings.isNullOrEmpty(key), "Fail to generate issue key"); issue.setKey(key); issue.setComponentKey(componentKey); - issue.setProjectKey(projectKey); issue.setRuleKey(ruleKey); issue.setMessage(message); issue.setSeverity(severity); diff --git a/sonar-core/src/main/java/org/sonar/core/issue/IssueUpdater.java b/sonar-core/src/main/java/org/sonar/core/issue/IssueUpdater.java index 9ac381eeffd..cdd3717f699 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/IssueUpdater.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/IssueUpdater.java @@ -247,20 +247,4 @@ public class IssueUpdater implements BatchComponent, ServerComponent { return false; } - public boolean setProject(DefaultIssue issue, String key, IssueChangeContext context) { - if (!Objects.equal(key, issue.projectKey())) { - issue.setProjectKey(key); - issue.setUpdateDate(context.date()); - issue.setChanged(true); - return true; - } - return false; - } - - public boolean setPastProject(DefaultIssue issue, String previousKey, IssueChangeContext context) { - String currentProjectKey = issue.projectKey(); - issue.setProjectKey(previousKey); - return setProject(issue, currentProjectKey, context); - } - } diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java index be0d275f1cd..3b7aa30ccc4 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java @@ -390,7 +390,7 @@ public final class IssueDto implements Serializable { .setUpdatedAt(now); } - public static IssueDto toDtoForUpdate(DefaultIssue issue, Long rootComponentId, Date now) { + public static IssueDto toDtoForUpdate(DefaultIssue issue, Date now) { // Invariant fields, like key and rule, can't be updated return new IssueDto() .setKee(issue.key()) @@ -408,7 +408,6 @@ public final class IssueDto implements Serializable { .setActionPlanKey(issue.actionPlanKey()) .setIssueAttributes(KeyValueFormat.format(issue.attributes())) .setAuthorLogin(issue.authorLogin()) - .setRootComponentId(rootComponentId) .setIssueCreationDate(issue.creationDate()) .setIssueCloseDate(issue.closeDate()) .setIssueUpdateDate(issue.updateDate()) diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueMapper.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueMapper.java index 600b5e4f8c2..3c3a8784891 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueMapper.java @@ -31,6 +31,8 @@ public interface IssueMapper { IssueDto selectByKey(String key); + List selectNonClosedIssuesByModule(int rootComponentId); + /** * Return a paginated list of authorized issue ids for a user. * If the role is null, then the authorisation check is disabled. diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueStorage.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueStorage.java index a52f728a5df..fad9862d7be 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueStorage.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueStorage.java @@ -119,7 +119,7 @@ public abstract class IssueStorage { } private void update(IssueMapper issueMapper, Date now, DefaultIssue issue) { - IssueDto dto = IssueDto.toDtoForUpdate(issue, projectId(issue), now); + IssueDto dto = IssueDto.toDtoForUpdate(issue, now); if (Issue.STATUS_CLOSED.equals(issue.status()) || issue.selectedAt() == null) { // Issue is closed by scan or changed by end-user issueMapper.update(dto); diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/UpdateConflictResolver.java b/sonar-core/src/main/java/org/sonar/core/issue/db/UpdateConflictResolver.java index 73370a7face..536667cae3f 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/db/UpdateConflictResolver.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/UpdateConflictResolver.java @@ -41,7 +41,7 @@ class UpdateConflictResolver { IssueDto dbIssue = mapper.selectByKey(issue.key()); if (dbIssue != null) { mergeFields(dbIssue, issue); - mapper.update(IssueDto.toDtoForUpdate(issue, dbIssue.getRootComponentId(), new Date())); + mapper.update(IssueDto.toDtoForUpdate(issue, new Date())); } } diff --git a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml index bd85afc9313..a3e15378041 100644 --- a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml @@ -89,7 +89,6 @@ reporter=#{reporter}, assignee=#{assignee}, author_login=#{authorLogin}, - root_component_id=#{rootComponentId}, issue_attributes=#{issueAttributes}, issue_creation_date=#{issueCreationDate}, issue_update_date=#{issueUpdateDate}, @@ -116,7 +115,6 @@ reporter=#{reporter}, assignee=#{assignee}, author_login=#{authorLogin}, - root_component_id=#{rootComponentId}, issue_attributes=#{issueAttributes}, issue_creation_date=#{issueCreationDate}, issue_update_date=#{issueUpdateDate}, @@ -165,12 +163,10 @@ i.updated_at as updatedAt, r.plugin_rule_key as ruleKey, r.plugin_name as ruleRepo, - p.kee as componentKey, - root.kee as rootComponentKey + p.kee as componentKey from issues i - inner join (select p.id,p.kee from projects p where (p.root_id=#{id} and p.qualifier <> 'BRC') or (p.id=#{id})) p on p.id=i.component_id inner join rules r on r.id=i.rule_id - left outer join projects root on root.id=i.root_component_id + inner join (select p.id,p.kee from projects p where (p.root_id=#{id} and p.qualifier <> 'BRC') or (p.id=#{id})) p on p.id=i.component_id and i.status <> 'CLOSED' diff --git a/sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueBuilderTest.java b/sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueBuilderTest.java index 30b34609c00..916be3ea6e1 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueBuilderTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueBuilderTest.java @@ -32,10 +32,8 @@ public class DefaultIssueBuilderTest { @Test public void build_new_issue() throws Exception { String componentKey = "org.apache.struts:struts-core:Action.java"; - String projectKey = "org.apache.struts"; DefaultIssue issue = (DefaultIssue) new DefaultIssueBuilder() .componentKey(componentKey) - .projectKey(projectKey) .message("the message") .line(123) .effortToFix(10000.0) @@ -49,7 +47,6 @@ public class DefaultIssueBuilderTest { assertThat(issue.key()).isNotNull(); assertThat(issue.effortToFix()).isEqualTo(10000.0); assertThat(issue.componentKey()).isEqualTo(componentKey); - assertThat(issue.projectKey()).isEqualTo(projectKey); assertThat(issue.message()).isEqualTo("the message"); assertThat(issue.line()).isEqualTo(123); assertThat(issue.ruleKey().repository()).isEqualTo("squid"); @@ -68,7 +65,6 @@ public class DefaultIssueBuilderTest { public void not_set_default_severity() { DefaultIssue issue = (DefaultIssue) new DefaultIssueBuilder() .componentKey("Action.java") - .projectKey("org.apache.struts") .ruleKey(RuleKey.of("squid", "NullDereference")) .build(); diff --git a/sonar-core/src/test/java/org/sonar/core/issue/IssueUpdaterTest.java b/sonar-core/src/test/java/org/sonar/core/issue/IssueUpdaterTest.java index 5373ebef6eb..c0dfa62ec32 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/IssueUpdaterTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/IssueUpdaterTest.java @@ -447,35 +447,4 @@ public class IssueUpdaterTest { assertThat(issue.mustSendNotifications()).isFalse(); } - @Test - public void set_project() throws Exception { - boolean updated = updater.setProject(issue, "sample", context); - assertThat(updated).isTrue(); - assertThat(issue.projectKey()).isEqualTo("sample"); - - // do not save change - assertThat(issue.currentChange()).isNull(); - assertThat(issue.mustSendNotifications()).isFalse(); - } - - @Test - public void set_past_project() throws Exception { - issue.setProjectKey("new project key"); - boolean updated = updater.setPastProject(issue, "past project key", context); - assertThat(updated).isTrue(); - assertThat(issue.projectKey()).isEqualTo("new project key"); - - // do not save change - assertThat(issue.currentChange()).isNull(); - assertThat(issue.mustSendNotifications()).isFalse(); - } - - @Test - public void not_set_past_project_if_no_change() throws Exception { - issue.setProjectKey("key"); - boolean updated = updater.setPastProject(issue, "key", context); - assertThat(updated).isFalse(); - assertThat(issue.projectKey()).isEqualTo("key"); - } - } diff --git a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java index 45790762a26..a8087a3d4d8 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java @@ -310,7 +310,7 @@ public class IssueDaoTest extends AbstractDaoTestCase { } @Test - public void select_non_closed_issues_by_module() { + public void should_select_non_closed_issues_by_module() { setupData("shared", "should_select_non_closed_issues_by_module"); // 400 is a non-root module, we should find 2 issues from classes and one on itself @@ -322,37 +322,11 @@ public class IssueDaoTest extends AbstractDaoTestCase { assertThat(issue.getRuleRepo()).isNotNull(); assertThat(issue.getRule()).isNotNull(); assertThat(issue.getComponentKey()).isNotNull(); - assertThat(issue.getRootComponentKey()).isEqualTo("struts"); // 399 is the root module, we should only find 1 issue on itself handler = new DefaultResultHandler(); dao.selectNonClosedIssuesByModule(399, handler); assertThat(handler.getResultList()).hasSize(1); - - issue = (IssueDto) handler.getResultList().get(0); - assertThat(issue.getComponentKey()).isEqualTo("struts"); - assertThat(issue.getRootComponentKey()).isEqualTo("struts"); - } - - /** - * SONAR-5218 - */ - @Test - public void select_non_closed_issues_by_module_on_removed_project() { - // All issues are linked on a project that is not existing anymore - - setupData("shared", "should_select_non_closed_issues_by_module_on_removed_project"); - - // 400 is a non-root module, we should find 2 issues from classes and one on itself - DefaultResultHandler handler = new DefaultResultHandler(); - dao.selectNonClosedIssuesByModule(400, handler); - assertThat(handler.getResultList()).hasSize(3); - - IssueDto issue = (IssueDto) handler.getResultList().get(0); - assertThat(issue.getRuleRepo()).isNotNull(); - assertThat(issue.getRule()).isNotNull(); - assertThat(issue.getComponentKey()).isNotNull(); - assertThat(issue.getRootComponentKey()).isNull(); } @Test diff --git a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueMapperTest.java b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueMapperTest.java index 705c5358ea8..e3e074562ee 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueMapperTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueMapperTest.java @@ -84,7 +84,7 @@ public class IssueMapperTest extends AbstractDaoTestCase { IssueDto dto = new IssueDto(); dto.setComponentId(123l); - dto.setRootComponentId(101l); + dto.setRootComponentId(100l); dto.setRuleId(200); dto.setKee("ABCDE"); dto.setLine(500); @@ -119,7 +119,7 @@ public class IssueMapperTest extends AbstractDaoTestCase { IssueDto dto = new IssueDto(); dto.setComponentId(123l); - dto.setRootComponentId(101l); + dto.setRootComponentId(100l); dto.setRuleId(200); dto.setKee("ABCDE"); dto.setLine(500); @@ -157,7 +157,7 @@ public class IssueMapperTest extends AbstractDaoTestCase { IssueDto dto = new IssueDto(); dto.setComponentId(123l); - dto.setRootComponentId(101l); + dto.setRootComponentId(100l); dto.setRuleId(200); dto.setKee("ABCDE"); dto.setLine(500); diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/should_select_non_closed_issues_by_module_on_removed_project.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/should_select_non_closed_issues_by_module_on_removed_project.xml deleted file mode 100644 index bb4aaf5abbf..00000000000 --- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/should_select_non_closed_issues_by_module_on_removed_project.xml +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/testUpdate-result.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/testUpdate-result.xml index a923dfa54e0..8016cfac576 100644 --- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/testUpdate-result.xml +++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/testUpdate-result.xml @@ -3,7 +3,7 @@ id="100" kee="ABCDE" component_id="123" - root_component_id="101" + root_component_id="100" rule_id="200" severity="BLOCKER" manual_severity="[false]" diff --git a/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java b/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java index d0362da17d0..bef324ee95f 100644 --- a/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java @@ -21,6 +21,7 @@ package org.sonar.server.issue; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; +import com.google.common.base.Objects; import com.google.common.base.Predicate; import com.google.common.base.Strings; import com.google.common.collect.Iterables; @@ -35,9 +36,11 @@ import org.sonar.api.issue.action.Action; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.issue.internal.FieldDiffs; import org.sonar.api.rule.RuleKey; +import org.sonar.api.rule.Severity; import org.sonar.api.utils.SonarException; import org.sonar.core.issue.ActionPlanStats; import org.sonar.core.issue.DefaultActionPlan; +import org.sonar.core.issue.DefaultIssueBuilder; import org.sonar.core.issue.DefaultIssueFilter; import org.sonar.core.issue.workflow.Transition; import org.sonar.core.resource.ResourceDao; @@ -233,8 +236,16 @@ public class InternalRubyIssueService implements ServerComponent { } if (result.ok()) { - DefaultIssue issue = issueService.createManualIssue(componentKey, ruleKey, RubyUtils.toInteger(params.get("line")), params.get("message"), params.get("severity"), - RubyUtils.toDouble(params.get("effortToFix")), UserSession.get()); + DefaultIssue issue = (DefaultIssue) new DefaultIssueBuilder() + .componentKey(componentKey) + .line(RubyUtils.toInteger(params.get("line"))) + .message(params.get("message")) + .severity(Objects.firstNonNull(params.get("severity"), Severity.MAJOR)) + .effortToFix(RubyUtils.toDouble(params.get("effortToFix"))) + .ruleKey(ruleKey) + .reporter(UserSession.get().login()) + .build(); + issue = issueService.createManualIssue(issue, UserSession.get()); result.set(issue); } diff --git a/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java b/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java index 7db9d49daca..db1664a919c 100644 --- a/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java @@ -19,7 +19,6 @@ */ package org.sonar.server.issue; -import com.google.common.base.Objects; import com.google.common.base.Strings; import org.apache.commons.lang.StringUtils; import org.sonar.api.ServerComponent; @@ -29,14 +28,11 @@ import org.sonar.api.issue.IssueQuery; import org.sonar.api.issue.IssueQueryResult; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.issue.internal.IssueChangeContext; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.rule.Severity; import org.sonar.api.rules.Rule; import org.sonar.api.rules.RuleFinder; import org.sonar.api.user.User; import org.sonar.api.user.UserFinder; import org.sonar.api.web.UserRole; -import org.sonar.core.issue.DefaultIssueBuilder; import org.sonar.core.issue.IssueNotifications; import org.sonar.core.issue.IssueUpdater; import org.sonar.core.issue.db.IssueStorage; @@ -206,26 +202,15 @@ public class IssueService implements ServerComponent { return issue; } - public DefaultIssue createManualIssue(String componentKey, RuleKey ruleKey, @Nullable Integer line, @Nullable String message, @Nullable String severity, - @Nullable Double effortToFix, UserSession userSession) { + public DefaultIssue createManualIssue(DefaultIssue issue, UserSession userSession) { verifyLoggedIn(userSession); - ResourceDto resourceDto = resourceDao.getResource(ResourceQuery.create().setKey(componentKey)); - ResourceDto project = resourceDao.getRootProjectByComponentKey(componentKey); - if (resourceDto == null || project == null) { - throw new IllegalArgumentException("Unknown component: " + componentKey); + ResourceDto resourceDto = resourceDao.getResource(ResourceQuery.create().setKey(issue.componentKey())); + if (resourceDto == null) { + throw new IllegalArgumentException("Unknown component: " + issue.componentKey()); } - - DefaultIssue issue = (DefaultIssue) new DefaultIssueBuilder() - .componentKey(resourceDto.getKey()) - .projectKey(project.getKey()) - .line(line) - .message(message) - .severity(Objects.firstNonNull(severity, Severity.MAJOR)) - .effortToFix(effortToFix) - .ruleKey(ruleKey) - .reporter(UserSession.get().login()) - .build(); - + // Force use of correct key in case deprecated key is used + issue.setComponentKey(resourceDto.getKey()); + issue.setComponentId(resourceDto.getId()); if (!authorizationDao.isAuthorizedComponentKey(resourceDto.getKey(), userSession.userId(), UserRole.USER)) { // TODO throw unauthorized throw new IllegalStateException("User does not have the required role"); diff --git a/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceTest.java b/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceTest.java index 3f842e788f4..7d27a4bb842 100644 --- a/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceTest.java +++ b/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceTest.java @@ -22,10 +22,7 @@ package org.sonar.server.issue; import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; import org.sonar.api.issue.ActionPlan; import org.sonar.api.issue.Issue; import org.sonar.api.issue.IssueQuery; @@ -64,56 +61,23 @@ import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.*; -@RunWith(MockitoJUnitRunner.class) public class IssueServiceTest { - @Mock - DefaultIssueFinder finder; - - @Mock - IssueWorkflow workflow; - - @Mock - IssueUpdater issueUpdater; - - @Mock - IssueStorage issueStorage; - - @Mock - IssueNotifications issueNotifications; - - @Mock - ActionPlanService actionPlanService; - - @Mock - RuleFinder ruleFinder; - - @Mock - ResourceDao resourceDao; - - @Mock - AuthorizationDao authorizationDao; - - @Mock - UserFinder userFinder; - - @Mock - UserSession userSession; - - @Mock - IssueQueryResult issueQueryResult; - - @Mock - ResourceDto resource; - - @Mock - ResourceDto project; - - Transition transition = Transition.create("reopen", Issue.STATUS_RESOLVED, Issue.STATUS_REOPENED); - - DefaultIssue issue = new DefaultIssue().setKey("ABCD"); - - IssueService issueService; + private DefaultIssueFinder finder = mock(DefaultIssueFinder.class); + private IssueWorkflow workflow = mock(IssueWorkflow.class); + private IssueUpdater issueUpdater = mock(IssueUpdater.class); + private IssueStorage issueStorage = mock(IssueStorage.class); + private IssueNotifications issueNotifications = mock(IssueNotifications.class); + private ActionPlanService actionPlanService = mock(ActionPlanService.class); + private RuleFinder ruleFinder = mock(RuleFinder.class); + private ResourceDao resourceDao = mock(ResourceDao.class); + private AuthorizationDao authorizationDao = mock(AuthorizationDao.class); + private UserFinder userFinder = mock(UserFinder.class); + private UserSession userSession = mock(UserSession.class); + private Transition transition = Transition.create("reopen", Issue.STATUS_RESOLVED, Issue.STATUS_REOPENED); + private IssueQueryResult issueQueryResult = mock(IssueQueryResult.class); + private DefaultIssue issue = new DefaultIssue().setKey("ABCD"); + private IssueService issueService; @Before public void before() { @@ -126,21 +90,18 @@ public class IssueServiceTest { when(issueQueryResult.issues()).thenReturn(newArrayList((Issue) issue)); when(issueQueryResult.first()).thenReturn(issue); - when(resource.getKey()).thenReturn("org.sonar.Sample"); - when(project.getKey()).thenReturn("Sample"); - issueService = new IssueService(finder, workflow, issueStorage, issueUpdater, issueNotifications, actionPlanService, ruleFinder, resourceDao, authorizationDao, userFinder, mock(PreviewCache.class)); } @Test - public void load_issue() { + public void should_load_issue() { IssueQueryResult result = issueService.loadIssue("ABCD"); assertThat(result).isEqualTo(issueQueryResult); } @Test - public void fail_to_load_issue() { + public void should_fail_to_load_issue() { when(issueQueryResult.issues()).thenReturn(Collections.emptyList()); when(finder.find(any(IssueQuery.class))).thenReturn(issueQueryResult); @@ -153,13 +114,13 @@ public class IssueServiceTest { } @Test - public void list_status() { + public void should_list_status() { issueService.listStatus(); verify(workflow).statusKeys(); } @Test - public void list_transitions() { + public void should_list_transitions() { List transitions = newArrayList(transition); when(workflow.outTransitions(issue)).thenReturn(transitions); @@ -169,7 +130,7 @@ public class IssueServiceTest { } @Test - public void return_no_transition() { + public void should_return_no_transition() { when(issueQueryResult.first()).thenReturn(null); when(issueQueryResult.issues()).thenReturn(newArrayList((Issue) new DefaultIssue())); @@ -178,7 +139,7 @@ public class IssueServiceTest { } @Test - public void do_transition() { + public void should_do_transition() { when(workflow.doTransition(eq(issue), eq(transition.key()), any(IssueChangeContext.class))).thenReturn(true); Issue result = issueService.doTransition("ABCD", transition.key(), userSession); @@ -196,7 +157,7 @@ public class IssueServiceTest { } @Test - public void not_do_transition() { + public void should_not_do_transition() { when(workflow.doTransition(eq(issue), eq(transition.key()), any(IssueChangeContext.class))).thenReturn(false); Issue result = issueService.doTransition("ABCD", transition.key(), userSession); @@ -207,7 +168,7 @@ public class IssueServiceTest { } @Test - public void fail_do_transition_if_not_logged() { + public void should_fail_do_transition_if_not_logged() { when(userSession.isLoggedIn()).thenReturn(false); try { issueService.doTransition("ABCD", transition.key(), userSession); @@ -219,7 +180,7 @@ public class IssueServiceTest { } @Test - public void assign() { + public void should_assign() { String assignee = "perceval"; User user = new DefaultUser(); @@ -241,7 +202,7 @@ public class IssueServiceTest { } @Test - public void unassign() { + public void should_unassign() { when(issueUpdater.assign(eq(issue), eq((User) null), any(IssueChangeContext.class))).thenReturn(true); Issue result = issueService.assign("ABCD", null, userSession); @@ -260,7 +221,7 @@ public class IssueServiceTest { } @Test - public void not_assign() { + public void should_not_assign() { String assignee = "perceval"; User user = new DefaultUser(); @@ -276,7 +237,7 @@ public class IssueServiceTest { } @Test - public void fail_assign_if_assignee_not_found() { + public void should_fail_assign_if_assignee_not_found() { String assignee = "perceval"; when(userFinder.findByLogin(assignee)).thenReturn(null); @@ -294,7 +255,7 @@ public class IssueServiceTest { } @Test - public void plan() { + public void should_plan() { String actionPlanKey = "EFGH"; ActionPlan actionPlan = new DefaultActionPlan(); @@ -317,7 +278,7 @@ public class IssueServiceTest { } @Test - public void unplan() { + public void should_unplan() { when(issueUpdater.plan(eq(issue), eq((ActionPlan) null), any(IssueChangeContext.class))).thenReturn(true); Issue result = issueService.plan("ABCD", null, userSession); @@ -336,7 +297,7 @@ public class IssueServiceTest { } @Test - public void not_plan() { + public void should_not_plan() { String actionPlanKey = "EFGH"; ActionPlan actionPlan = new DefaultActionPlan(); @@ -352,7 +313,7 @@ public class IssueServiceTest { } @Test - public void fail_plan_if_action_plan_not_found() { + public void should_fail_plan_if_action_plan_not_found() { String actionPlanKey = "EFGH"; when(actionPlanService.findByKey(actionPlanKey, userSession)).thenReturn(null); @@ -369,7 +330,7 @@ public class IssueServiceTest { } @Test - public void set_severity() { + public void should_set_severity() { String severity = "MINOR"; when(issueUpdater.setManualSeverity(eq(issue), eq(severity), any(IssueChangeContext.class))).thenReturn(true); @@ -388,7 +349,7 @@ public class IssueServiceTest { } @Test - public void not_set_severity() { + public void should_not_set_severity() { String severity = "MINOR"; when(issueUpdater.setManualSeverity(eq(issue), eq(severity), any(IssueChangeContext.class))).thenReturn(false); @@ -402,47 +363,47 @@ public class IssueServiceTest { @Test public void create_manual_issue() { RuleKey ruleKey = RuleKey.of("manual", "manualRuleKey"); + DefaultIssue manualIssue = new DefaultIssue().setKey("GHIJ").setRuleKey(RuleKey.of("manual", "manualRuleKey")).setComponentKey("org.sonar.Sample").setMessage("Fix it"); when(ruleFinder.findByKey(ruleKey)).thenReturn(Rule.create("manual", "manualRuleKey")); - when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(resource); - when(resourceDao.getRootProjectByComponentKey(anyString())).thenReturn(project); + when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(mock(ResourceDto.class)); - Issue result = issueService.createManualIssue("org.sonar.Sample", RuleKey.of("manual", "manualRuleKey"), null, "Fix it", null, null, userSession); + Issue result = issueService.createManualIssue(manualIssue, userSession); assertThat(result).isNotNull(); assertThat(result.message()).isEqualTo("Fix it"); assertThat(result.creationDate()).isNotNull(); assertThat(result.updateDate()).isNotNull(); - verify(issueStorage).save(any(DefaultIssue.class)); + verify(issueStorage).save(manualIssue); verify(authorizationDao).isAuthorizedComponentKey(anyString(), anyInt(), eq(UserRole.USER)); } @Test public void create_manual_issue_use_rule_name_if_no_message() { RuleKey ruleKey = RuleKey.of("manual", "manualRuleKey"); + DefaultIssue manualIssue = new DefaultIssue().setKey("GHIJ").setRuleKey(RuleKey.of("manual", "manualRuleKey")).setComponentKey("org.sonar.Sample").setMessage(""); when(ruleFinder.findByKey(ruleKey)).thenReturn(Rule.create("manual", "manualRuleKey").setName("Manual Rule")); - when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(resource); - when(resourceDao.getRootProjectByComponentKey(anyString())).thenReturn(project); + when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(mock(ResourceDto.class)); - Issue result = issueService.createManualIssue("org.sonar.Sample", RuleKey.of("manual", "manualRuleKey"), null, "", null, null, userSession); + Issue result = issueService.createManualIssue(manualIssue, userSession); assertThat(result).isNotNull(); assertThat(result.message()).isEqualTo("Manual Rule"); assertThat(result.creationDate()).isNotNull(); assertThat(result.updateDate()).isNotNull(); - verify(issueStorage).save(any(DefaultIssue.class)); + verify(issueStorage).save(manualIssue); verify(authorizationDao).isAuthorizedComponentKey(anyString(), anyInt(), eq(UserRole.USER)); } @Test - public void fail_create_manual_issue_if_not_having_required_role() { + public void should_fail_create_manual_issue_if_not_having_required_role() { RuleKey ruleKey = RuleKey.of("manual", "manualRuleKey"); - when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(resource); - when(resourceDao.getRootProjectByComponentKey(anyString())).thenReturn(project); + when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(mock(ResourceDto.class)); when(ruleFinder.findByKey(ruleKey)).thenReturn(Rule.create("manual", "manualRuleKey")); when(authorizationDao.isAuthorizedComponentKey(anyString(), eq(10), anyString())).thenReturn(false); + DefaultIssue manualIssue = new DefaultIssue().setKey("GHIJ").setRuleKey(ruleKey).setComponentKey("org.sonar.Sample"); try { - issueService.createManualIssue("org.sonar.Sample", ruleKey, null, null, null, null, userSession); + issueService.createManualIssue(manualIssue, userSession); fail(); } catch (Exception e) { assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("User does not have the required role"); @@ -450,13 +411,13 @@ public class IssueServiceTest { } @Test - public void fail_create_manual_issue_if_not_manual_rule() { - when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(resource); - when(resourceDao.getRootProjectByComponentKey(anyString())).thenReturn(project); + public void should_fail_create_manual_issue_if_not_manual_rule() { + when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(mock(ResourceDto.class)); RuleKey ruleKey = RuleKey.of("squid", "s100"); + DefaultIssue manualIssue = new DefaultIssue().setKey("GHIJ").setRuleKey(ruleKey).setComponentKey("org.sonar.Sample"); try { - issueService.createManualIssue("org.sonar.Sample", ruleKey, null, null, null, null, userSession); + issueService.createManualIssue(manualIssue, userSession); fail(); } catch (Exception e) { assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Issues can be created only on rules marked as 'manual': squid:s100"); @@ -465,14 +426,14 @@ public class IssueServiceTest { } @Test - public void fail_create_manual_issue_if_rule_not_found() { - when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(resource); - when(resourceDao.getRootProjectByComponentKey(anyString())).thenReturn(project); + public void should_fail_create_manual_issue_if_rule_not_found() { + when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(mock(ResourceDto.class)); RuleKey ruleKey = RuleKey.of("manual", "manualRuleKey"); + DefaultIssue manualIssue = new DefaultIssue().setKey("GHIJ").setRuleKey(RuleKey.of("manual", "manualRuleKey")).setComponentKey("org.sonar.Sample"); when(ruleFinder.findByKey(ruleKey)).thenReturn(null); try { - issueService.createManualIssue("org.sonar.Sample", RuleKey.of("manual", "manualRuleKey"), null, null, null, null, userSession); + issueService.createManualIssue(manualIssue, userSession); fail(); } catch (Exception e) { assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Unknown rule: manual:manualRuleKey"); @@ -481,12 +442,13 @@ public class IssueServiceTest { } @Test - public void fail_create_manual_issue_if_component_not_found() { + public void should_fail_create_manual_issue_if_component_not_found() { RuleKey ruleKey = RuleKey.of("manual", "manualRuleKey"); + DefaultIssue manualIssue = new DefaultIssue().setKey("GHIJ").setRuleKey(RuleKey.of("manual", "manualRuleKey")).setComponentKey("org.sonar.Sample"); when(ruleFinder.findByKey(ruleKey)).thenReturn(Rule.create("manual", "manualRuleKey")); when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(null); try { - issueService.createManualIssue("org.sonar.Sample", RuleKey.of("manual", "manualRuleKey"), null, null, null, null, userSession); + issueService.createManualIssue(manualIssue, userSession); fail(); } catch (Exception e) { assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Unknown component: org.sonar.Sample");