issue.setStatus(ref.getStatus());
issue.setAssignee(ref.getAssignee());
issue.setAuthorLogin(ref.getAuthorLogin());
-
if (ref.getIssueAttributes() != null) {
issue.setAttributes(KeyValueFormat.parse(ref.getIssueAttributes()));
}
Long debtInMinutes = ref.getDebt();
Duration previousTechnicalDebt = debtInMinutes != null ? Duration.create(debtInMinutes) : null;
updater.setPastTechnicalDebt(issue, previousTechnicalDebt, changeContext);
- updater.setPastProject(issue, ref.getRootComponentKey(), changeContext);
}
}
@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);
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
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;
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
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;
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
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;
}
}
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())
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;
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();
}
@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;
}
}
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;
ModuleIssues moduleIssues = mock(ModuleIssues.class);
IssueCache cache = mock(IssueCache.class);
- Project project = mock(Project.class);
Component component = mock(Component.class);
@Test
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<Issue> issues = perspective.issues();
assertThat(issues).containsOnly(unresolved);
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<Issue> issues = perspective.resolvedIssues();
assertThat(issues).containsOnly(resolved);
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;
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);
@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);
public void setUp() {
when(project.getAnalysisDate()).thenReturn(new Date());
when(project.getEffectiveKey()).thenReturn("org.apache:struts-core");
- when(project.getRoot()).thenReturn(project);
}
@Test
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
*/
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;
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);
@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);
@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();
@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
public class DefaultIssueBuilder implements Issuable.IssueBuilder {
private String componentKey;
- private String projectKey;
private RuleKey ruleKey;
private Integer line;
private String message;
return this;
}
-
- public DefaultIssueBuilder projectKey(String projectKey) {
- this.projectKey = projectKey;
- return this;
- }
-
@Override
public Issuable.IssueBuilder ruleKey(RuleKey ruleKey) {
this.ruleKey = ruleKey;
@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");
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);
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);
- }
-
}
.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())
.setActionPlanKey(issue.actionPlanKey())
.setIssueAttributes(KeyValueFormat.format(issue.attributes()))
.setAuthorLogin(issue.authorLogin())
- .setRootComponentId(rootComponentId)
.setIssueCreationDate(issue.creationDate())
.setIssueCloseDate(issue.closeDate())
.setIssueUpdateDate(issue.updateDate())
IssueDto selectByKey(String key);
+ List<IssueDto> 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.
}
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);
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()));
}
}
reporter=#{reporter},
assignee=#{assignee},
author_login=#{authorLogin},
- root_component_id=#{rootComponentId},
issue_attributes=#{issueAttributes},
issue_creation_date=#{issueCreationDate},
issue_update_date=#{issueUpdateDate},
reporter=#{reporter},
assignee=#{assignee},
author_login=#{authorLogin},
- root_component_id=#{rootComponentId},
issue_attributes=#{issueAttributes},
issue_creation_date=#{issueCreationDate},
issue_update_date=#{issueUpdateDate},
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
<where>
and i.status <> 'CLOSED'
</where>
@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)
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");
public void not_set_default_severity() {
DefaultIssue issue = (DefaultIssue) new DefaultIssueBuilder()
.componentKey("Action.java")
- .projectKey("org.apache.struts")
.ruleKey(RuleKey.of("squid", "NullDereference"))
.build();
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");
- }
-
}
}
@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
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
IssueDto dto = new IssueDto();
dto.setComponentId(123l);
- dto.setRootComponentId(101l);
+ dto.setRootComponentId(100l);
dto.setRuleId(200);
dto.setKee("ABCDE");
dto.setLine(500);
IssueDto dto = new IssueDto();
dto.setComponentId(123l);
- dto.setRootComponentId(101l);
+ dto.setRootComponentId(100l);
dto.setRuleId(200);
dto.setKee("ABCDE");
dto.setLine(500);
IssueDto dto = new IssueDto();
dto.setComponentId(123l);
- dto.setRootComponentId(101l);
+ dto.setRootComponentId(100l);
dto.setRuleId(200);
dto.setKee("ABCDE");
dto.setLine(500);
+++ /dev/null
-<!--
- ~ Sonar, open source software quality management tool.
- ~ Copyright (C) 2008-2012 SonarSource
- ~ mailto:contact AT sonarsource DOT com
- ~
- ~ Sonar 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.
- ~
- ~ Sonar 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 Sonar; if not, write to the Free Software
- ~ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- -->
-
-<dataset>
-
- <!-- Open Issue on a file -->
- <issues
- id="100"
- kee="100"
- component_id="401"
- root_component_id="111"
- rule_id="500"
- severity="BLOCKER"
- manual_severity="[false]"
- message="[null]"
- line="200"
- effort_to_fix="[null]"
- status="OPEN"
- resolution="[null]"
- checksum="[null]"
- reporter="user"
- assignee="user"
- author_login="[null]"
- issue_attributes="[null]"
- issue_creation_date="2013-04-16"
- issue_update_date="2013-04-16"
- issue_close_date="2013-04-16"
- created_at="2013-04-16"
- updated_at="[null]"
- />
-
- <!-- Open Issue on a file -->
- <issues
- id="101"
- kee="101"
- component_id="402"
- root_component_id="111"
- rule_id="501"
- severity="MAJOR"
- manual_severity="[false]"
- message="[null]"
- line="120"
- effort_to_fix="[null]"
- status="OPEN"
- resolution="[null]"
- checksum="[null]"
- reporter="[null]"
- assignee="user"
- author_login="[null]"
- issue_attributes="[null]"
- issue_creation_date="2013-04-16"
- issue_update_date="2013-04-16"
- issue_close_date="2013-04-16"
- created_at="2013-04-10"
- updated_at="[null]"
- />
-
- <!-- Closed Issue on a file -->
- <issues
- id="102"
- kee="102"
- component_id="402"
- root_component_id="111"
- rule_id="501"
- severity="MAJOR"
- manual_severity="[false]"
- message="[null]"
- line="120"
- effort_to_fix="[null]"
- status="CLOSED"
- resolution="FIXED"
- checksum="[null]"
- reporter="[null]"
- assignee="user"
- author_login="[null]"
- issue_attributes="[null]"
- issue_creation_date="2013-04-16"
- issue_update_date="2013-04-16"
- issue_close_date="2013-04-16"
- created_at="2013-04-10"
- updated_at="[null]"
- />
-
- <!-- Open Issue on a sub module -->
- <issues
- id="103"
- kee="103"
- component_id="400"
- root_component_id="111"
- rule_id="501"
- severity="MAJOR"
- manual_severity="[false]"
- message="[null]"
- line="[null]"
- effort_to_fix="[null]"
- status="OPEN"
- resolution="[null]"
- checksum="[null]"
- reporter="[null]"
- assignee="user"
- author_login="[null]"
- issue_attributes="[null]"
- issue_creation_date="2013-04-16"
- issue_update_date="2013-04-16"
- issue_close_date="2013-04-16"
- created_at="2013-04-10"
- updated_at="[null]"
- />
-
-</dataset>
id="100"
kee="ABCDE"
component_id="123"
- root_component_id="101"
+ root_component_id="100"
rule_id="200"
severity="BLOCKER"
manual_severity="[false]"
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;
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;
}
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);
}
*/
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;
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;
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");
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;
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() {
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.<Issue>emptyList());
when(finder.find(any(IssueQuery.class))).thenReturn(issueQueryResult);
}
@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<Transition> transitions = newArrayList(transition);
when(workflow.outTransitions(issue)).thenReturn(transitions);
}
@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()));
}
@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);
}
@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);
}
@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);
}
@Test
- public void assign() {
+ public void should_assign() {
String assignee = "perceval";
User user = new DefaultUser();
}
@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);
}
@Test
- public void not_assign() {
+ public void should_not_assign() {
String assignee = "perceval";
User user = new DefaultUser();
}
@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);
}
@Test
- public void plan() {
+ public void should_plan() {
String actionPlanKey = "EFGH";
ActionPlan actionPlan = new DefaultActionPlan();
}
@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);
}
@Test
- public void not_plan() {
+ public void should_not_plan() {
String actionPlanKey = "EFGH";
ActionPlan actionPlan = new DefaultActionPlan();
}
@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);
}
@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);
}
@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);
@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");
}
@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");
}
@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");
}
@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");