--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.issue;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Strings;
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.issue.ActionPlan;
+import org.sonar.api.issue.Issue;
+import org.sonar.api.issue.IssueQuery;
+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.component.ComponentDto;
+import org.sonar.core.issue.DefaultIssueBuilder;
+import org.sonar.core.issue.IssueNotifications;
+import org.sonar.core.issue.IssueUpdater;
+import org.sonar.core.issue.db.IssueDao;
+import org.sonar.core.issue.db.IssueDto;
+import org.sonar.core.issue.db.IssueStorage;
+import org.sonar.core.issue.workflow.IssueWorkflow;
+import org.sonar.core.issue.workflow.Transition;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.preview.PreviewCache;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.issue.actionplan.ActionPlanService;
+import org.sonar.server.issue.index.IssueIndex;
+import org.sonar.server.search.IndexClient;
+import org.sonar.server.search.QueryContext;
+import org.sonar.server.user.UserSession;
+
+import javax.annotation.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+public class DefaultIssueService implements IssueService {
+
+ private final DbClient dbClient;
+ private final IndexClient indexClient;
+
+ private final IssueWorkflow workflow;
+ private final IssueUpdater issueUpdater;
+ private final IssueStorage issueStorage;
+ private final IssueNotifications issueNotifications;
+ private final ActionPlanService actionPlanService;
+ private final RuleFinder ruleFinder;
+ private final IssueDao issueDao;
+ private final UserFinder userFinder;
+ private final PreviewCache dryRunCache;
+
+ public DefaultIssueService(DbClient dbClient, IndexClient indexClient,
+ IssueWorkflow workflow,
+ IssueStorage issueStorage,
+ IssueUpdater issueUpdater,
+ IssueNotifications issueNotifications,
+ ActionPlanService actionPlanService,
+ RuleFinder ruleFinder,
+ IssueDao issueDao,
+ UserFinder userFinder,
+ PreviewCache dryRunCache) {
+ this.dbClient = dbClient;
+ this.indexClient = indexClient;
+ this.workflow = workflow;
+ this.issueStorage = issueStorage;
+ this.issueUpdater = issueUpdater;
+ this.actionPlanService = actionPlanService;
+ this.ruleFinder = ruleFinder;
+ this.issueNotifications = issueNotifications;
+ this.issueDao = issueDao;
+ this.userFinder = userFinder;
+ this.dryRunCache = dryRunCache;
+ }
+
+ @Override
+ public List<String> listStatus() {
+ return workflow.statusKeys();
+ }
+
+ /**
+ * List of available transitions.
+ * <p/>
+ * Never return null, but return an empty list if the issue does not exist.
+ */
+ @Override
+ public List<Transition> listTransitions(String issueKey) {
+ DbSession session = dbClient.openSession(false);
+ try {
+ IssueDto issueDto = getByKey(session, issueKey);
+ return listTransitions(issueDto.toDefaultIssue());
+ } finally {
+ session.close();
+ }
+ }
+
+ /**
+ * Never return null, but an empty list if the issue does not exist.
+ * No security check is done since it should already have been done to get the issue
+ */
+ @Override
+ public List<Transition> listTransitions(@Nullable Issue issue) {
+ if (issue == null) {
+ return Collections.emptyList();
+ }
+ List<Transition> outTransitions = workflow.outTransitions(issue);
+ List<Transition> allowedTransitions = new ArrayList<Transition>();
+ for (Transition transition : outTransitions) {
+ DefaultIssue defaultIssue = (DefaultIssue) issue;
+ String projectKey = defaultIssue.projectKey();
+ if (StringUtils.isBlank(transition.requiredProjectPermission()) ||
+ (projectKey != null && UserSession.get().hasProjectPermission(transition.requiredProjectPermission(), projectKey))) {
+ allowedTransitions.add(transition);
+ }
+ }
+ return allowedTransitions;
+ }
+
+ @Override
+ public Issue doTransition(String issueKey, String transitionKey) {
+ verifyLoggedIn();
+
+ DbSession session = dbClient.openSession(false);
+ try {
+ IssueDto issueDto = getByKey(session, issueKey);
+ DefaultIssue defaultIssue = issueDto.toDefaultIssue();
+ IssueChangeContext context = IssueChangeContext.createUser(new Date(), UserSession.get().login());
+ checkTransitionPermission(transitionKey, UserSession.get(), defaultIssue);
+ if (workflow.doTransition(defaultIssue, transitionKey, context)) {
+ saveIssue(session, defaultIssue, context);
+ }
+ return defaultIssue;
+
+ } finally {
+ session.close();
+ }
+ }
+
+ private void checkTransitionPermission(String transitionKey, UserSession userSession, DefaultIssue defaultIssue) {
+ List<Transition> outTransitions = workflow.outTransitions(defaultIssue);
+ for (Transition transition : outTransitions) {
+ String projectKey = defaultIssue.projectKey();
+ if (transition.key().equals(transitionKey) && StringUtils.isNotBlank(transition.requiredProjectPermission()) && projectKey != null) {
+ userSession.checkProjectPermission(transition.requiredProjectPermission(), projectKey);
+ }
+ }
+ }
+
+ @Override
+ public Issue assign(String issueKey, @Nullable String assignee) {
+ verifyLoggedIn();
+
+ DbSession session = dbClient.openSession(false);
+ try {
+ IssueDto issueDto = getByKey(session, issueKey);
+ DefaultIssue issue = issueDto.toDefaultIssue();
+ User user = null;
+ if (!Strings.isNullOrEmpty(assignee)) {
+ user = userFinder.findByLogin(assignee);
+ if (user == null) {
+ throw new NotFoundException("Unknown user: " + assignee);
+ }
+ }
+ IssueChangeContext context = IssueChangeContext.createUser(new Date(), UserSession.get().login());
+ if (issueUpdater.assign(issue, user, context)) {
+ saveIssue(session, issue, context);
+ }
+ return issue;
+
+ } finally {
+ session.close();
+ }
+ }
+
+ @Override
+ public Issue plan(String issueKey, @Nullable String actionPlanKey) {
+ verifyLoggedIn();
+
+ DbSession session = dbClient.openSession(false);
+ try {
+ ActionPlan actionPlan = null;
+ if (!Strings.isNullOrEmpty(actionPlanKey)) {
+ actionPlan = actionPlanService.findByKey(actionPlanKey, UserSession.get());
+ if (actionPlan == null) {
+ throw new NotFoundException("Unknown action plan: " + actionPlanKey);
+ }
+ }
+ IssueDto issueDto = getByKey(session, issueKey);
+ DefaultIssue issue = issueDto.toDefaultIssue();
+
+ IssueChangeContext context = IssueChangeContext.createUser(new Date(), UserSession.get().login());
+ if (issueUpdater.plan(issue, actionPlan, context)) {
+ saveIssue(session, issue, context);
+ }
+ return issue;
+
+ } finally {
+ session.close();
+ }
+ }
+
+ @Override
+ public Issue setSeverity(String issueKey, String severity) {
+ verifyLoggedIn();
+
+ DbSession session = dbClient.openSession(false);
+ try {
+ IssueDto issueDto = getByKey(session, issueKey);
+ DefaultIssue issue = issueDto.toDefaultIssue();
+ UserSession.get().checkProjectPermission(UserRole.ISSUE_ADMIN, issue.projectKey());
+
+ IssueChangeContext context = IssueChangeContext.createUser(new Date(), UserSession.get().login());
+ if (issueUpdater.setManualSeverity(issue, severity, context)) {
+ saveIssue(session, issue, context);
+ }
+ return issue;
+ } finally {
+ session.close();
+ }
+ }
+
+ @Override
+ public DefaultIssue createManualIssue(String componentKey, RuleKey ruleKey, @Nullable Integer line, @Nullable String message, @Nullable String severity,
+ @Nullable Double effortToFix) {
+ verifyLoggedIn();
+
+ DbSession session = dbClient.openSession(false);
+ try {
+ ComponentDto component = dbClient.componentDao().getByKey(session, componentKey);
+ ComponentDto project = dbClient.componentDao().getRootProjectByKey(componentKey, session);
+
+ UserSession.get().checkProjectPermission(UserRole.USER, project.getKey());
+ if (!ruleKey.isManual()) {
+ throw new IllegalArgumentException("Issues can be created only on rules marked as 'manual': " + ruleKey);
+ }
+ Rule rule = getRuleByKey(ruleKey);
+
+ DefaultIssue issue = new DefaultIssueBuilder()
+ .componentKey(component.getKey())
+ .projectKey(project.getKey())
+ .line(line)
+ .message(!Strings.isNullOrEmpty(message) ? message : rule.getName())
+ .severity(Objects.firstNonNull(severity, Severity.MAJOR))
+ .effortToFix(effortToFix)
+ .ruleKey(ruleKey)
+ .reporter(UserSession.get().login())
+ .build();
+
+ Date now = new Date();
+ issue.setCreationDate(now);
+ issue.setUpdateDate(now);
+ issueStorage.save(issue);
+ dryRunCache.reportResourceModification(component.getKey());
+ return issue;
+ } finally {
+ session.close();
+ }
+ }
+
+ // TODO result should be replaced by an aggregation object in IssueIndex
+ @Override
+ public RulesAggregation findRulesByComponent(String componentKey, @Nullable Date periodDate, DbSession session) {
+ RulesAggregation rulesAggregation = new RulesAggregation();
+ for (RuleDto ruleDto : issueDao.findRulesByComponent(componentKey, periodDate, session)) {
+ rulesAggregation.add(ruleDto);
+ }
+ return rulesAggregation;
+ }
+
+ // TODO result should be replaced by an aggregation object in IssueIndex
+ @Override
+ public Multiset<String> findSeveritiesByComponent(String componentKey, @Nullable Date periodDate, DbSession session) {
+ Multiset<String> aggregation = HashMultiset.create();
+ for (String severity : issueDao.findSeveritiesByComponent(componentKey, periodDate, session)) {
+ aggregation.add(severity);
+ }
+ return aggregation;
+ }
+
+ public IssueDto getByKey(DbSession session, String key) {
+ // Load with index to check permission
+ indexClient.get(IssueIndex.class).getByKey(key);
+ return dbClient.issueDao().getByKey(session, key);
+ }
+
+ private void saveIssue(DbSession session, DefaultIssue issue, IssueChangeContext context) {
+ issueStorage.save(issue);
+ issueNotifications.sendChanges(issue, context,
+ getRuleByKey(issue.ruleKey()),
+ dbClient.componentDao().getByKey(session, issue.projectKey()),
+ dbClient.componentDao().getNullableByKey(session, issue.componentKey()));
+ dryRunCache.reportResourceModification(issue.componentKey());
+ }
+
+ private Rule getRuleByKey(RuleKey ruleKey) {
+ Rule rule = ruleFinder.findByKey(ruleKey);
+ if (rule == null) {
+ throw new IllegalArgumentException("Unknown rule: " + ruleKey);
+ }
+ return rule;
+ }
+
+ public org.sonar.server.search.Result<Issue> search(IssueQuery query, QueryContext options) {
+ IssueIndex issueIndex = indexClient.get(IssueIndex.class);
+ return issueIndex.search(query, options);
+ }
+
+ private void verifyLoggedIn() {
+ UserSession.get().checkLoggedIn();
+ }
+}
}
public List<Transition> listTransitions(String issueKey) {
- return issueService.listTransitions(issueKey, UserSession.get());
+ return issueService.listTransitions(issueKey);
}
public List<Transition> listTransitions(Issue issue) {
- return issueService.listTransitions(issue, UserSession.get());
+ return issueService.listTransitions(issue);
}
public List<String> listStatus() {
public Result<Issue> doTransition(String issueKey, String transitionKey) {
Result<Issue> result = Result.of();
try {
- result.set(issueService.doTransition(issueKey, transitionKey, UserSession.get()));
+ result.set(issueService.doTransition(issueKey, transitionKey));
} catch (Exception e) {
result.addError(e.getMessage());
}
public Result<Issue> assign(String issueKey, @Nullable String assignee) {
Result<Issue> result = Result.of();
try {
- result.set(issueService.assign(issueKey, StringUtils.defaultIfBlank(assignee, null), UserSession.get()));
+ result.set(issueService.assign(issueKey, StringUtils.defaultIfBlank(assignee, null)));
} catch (Exception e) {
result.addError(e.getMessage());
}
public Result<Issue> setSeverity(String issueKey, String severity) {
Result<Issue> result = Result.of();
try {
- result.set(issueService.setSeverity(issueKey, severity, UserSession.get()));
+ result.set(issueService.setSeverity(issueKey, severity));
} catch (Exception e) {
result.addError(e.getMessage());
}
public Result<Issue> plan(String issueKey, @Nullable String actionPlanKey) {
Result<Issue> result = Result.of();
try {
- result.set(issueService.plan(issueKey, actionPlanKey, UserSession.get()));
+ result.set(issueService.plan(issueKey, actionPlanKey));
} catch (Exception e) {
result.addError(e.getMessage());
}
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());
+ RubyUtils.toDouble(params.get("effortToFix")));
result.set(issue);
}
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+
package org.sonar.server.issue;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Objects;
-import com.google.common.base.Strings;
-import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
-import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.sonar.api.ServerComponent;
-import org.sonar.api.issue.ActionPlan;
import org.sonar.api.issue.Issue;
-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.IssueDao;
-import org.sonar.core.issue.db.IssueStorage;
-import org.sonar.core.issue.workflow.IssueWorkflow;
import org.sonar.core.issue.workflow.Transition;
import org.sonar.core.persistence.DbSession;
-import org.sonar.core.preview.PreviewCache;
-import org.sonar.core.resource.ResourceDao;
-import org.sonar.core.resource.ResourceDto;
-import org.sonar.core.resource.ResourceQuery;
-import org.sonar.core.rule.RuleDto;
-import org.sonar.core.user.AuthorizationDao;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.issue.actionplan.ActionPlanService;
-import org.sonar.server.issue.index.IssueIndex;
-import org.sonar.server.search.IndexClient;
-import org.sonar.server.search.QueryContext;
-import org.sonar.server.user.UserSession;
import javax.annotation.Nullable;
-import java.util.*;
-
-/**
- * @since 3.6
- */
-public class IssueService implements ServerComponent {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(IssueService.class);
-
- private final DbClient dbClient;
- private final IndexClient indexClient;
-
- private final DefaultIssueFinder finder;
- private final IssueWorkflow workflow;
- private final IssueUpdater issueUpdater;
- private final IssueStorage issueStorage;
- private final IssueNotifications issueNotifications;
- private final ActionPlanService actionPlanService;
- private final RuleFinder ruleFinder;
- private final ResourceDao resourceDao;
- private final IssueDao issueDao;
- private final AuthorizationDao authorizationDao;
- private final UserFinder userFinder;
- private final PreviewCache dryRunCache;
-
- @Deprecated
- @VisibleForTesting
- public IssueService(DefaultIssueFinder finder,
- IssueWorkflow workflow,
- IssueStorage issueStorage,
- IssueUpdater issueUpdater,
- IssueNotifications issueNotifications,
- ActionPlanService actionPlanService,
- RuleFinder ruleFinder,
- ResourceDao resourceDao,
- IssueDao issueDao,
- AuthorizationDao authorizationDao,
- UserFinder userFinder,
- PreviewCache dryRunCache) {
- this(null, null, finder, workflow, issueStorage, issueUpdater, issueNotifications, actionPlanService,
- ruleFinder, resourceDao, issueDao, authorizationDao, userFinder, dryRunCache);
- }
-
- public IssueService(DbClient dbClient, IndexClient indexClient,
- DefaultIssueFinder finder,
- IssueWorkflow workflow,
- IssueStorage issueStorage,
- IssueUpdater issueUpdater,
- IssueNotifications issueNotifications,
- ActionPlanService actionPlanService,
- RuleFinder ruleFinder,
- ResourceDao resourceDao,
- IssueDao issueDao,
- AuthorizationDao authorizationDao,
- UserFinder userFinder,
- PreviewCache dryRunCache) {
- this.dbClient = dbClient;
- this.indexClient = indexClient;
- this.finder = finder;
- this.workflow = workflow;
- this.issueStorage = issueStorage;
- this.issueUpdater = issueUpdater;
- this.actionPlanService = actionPlanService;
- this.ruleFinder = ruleFinder;
- this.issueNotifications = issueNotifications;
- this.resourceDao = resourceDao;
- this.issueDao = issueDao;
- this.authorizationDao = authorizationDao;
- this.userFinder = userFinder;
- this.dryRunCache = dryRunCache;
- }
-
- /**
- * List of available transitions.
- * <p/>
- * Never return null, but return an empty list if the issue does not exist.
- */
- public List<Transition> listTransitions(String issueKey, UserSession userSession) {
- Issue issue = loadIssue(issueKey).first();
- return listTransitions(issue, userSession);
- }
+import java.util.Date;
+import java.util.List;
- /**
- * Never return null, but an empty list if the issue does not exist.
- * No security check is done since it should already have been done to get the issue
- */
- public List<Transition> listTransitions(@Nullable Issue issue, UserSession userSession) {
- if (issue == null) {
- return Collections.emptyList();
- }
- List<Transition> outTransitions = workflow.outTransitions(issue);
- List<Transition> allowedTransitions = new ArrayList<Transition>();
- for (Transition transition : outTransitions) {
- DefaultIssue defaultIssue = (DefaultIssue) issue;
- String projectKey = defaultIssue.projectKey();
- if (StringUtils.isBlank(transition.requiredProjectPermission()) ||
- (projectKey != null && userSession.hasProjectPermission(transition.requiredProjectPermission(), projectKey))) {
- allowedTransitions.add(transition);
- }
- }
- return allowedTransitions;
- }
+public interface IssueService extends ServerComponent {
+ List<String> listStatus();
- public Issue doTransition(String issueKey, String transitionKey, UserSession userSession) {
- verifyLoggedIn(userSession);
- IssueQueryResult queryResult = loadIssue(issueKey);
- DefaultIssue defaultIssue = (DefaultIssue) queryResult.first();
- IssueChangeContext context = IssueChangeContext.createUser(new Date(), userSession.login());
- checkTransitionPermission(transitionKey, userSession, defaultIssue);
- if (workflow.doTransition(defaultIssue, transitionKey, context)) {
- issueStorage.save(defaultIssue);
- issueNotifications.sendChanges(defaultIssue, context, queryResult);
- dryRunCache.reportResourceModification(defaultIssue.componentKey());
- }
- return defaultIssue;
- }
+ List<Transition> listTransitions(String issueKey);
- private void checkTransitionPermission(String transitionKey, UserSession userSession, DefaultIssue defaultIssue) {
- List<Transition> outTransitions = workflow.outTransitions(defaultIssue);
- for (Transition transition : outTransitions) {
- String projectKey = defaultIssue.projectKey();
- if (transition.key().equals(transitionKey) && StringUtils.isNotBlank(transition.requiredProjectPermission()) && projectKey != null) {
- userSession.checkProjectPermission(transition.requiredProjectPermission(), projectKey);
- }
- }
- }
+ List<Transition> listTransitions(@Nullable Issue issue);
- public Issue assign(String issueKey, @Nullable String assignee, UserSession userSession) {
- verifyLoggedIn(userSession);
- IssueQueryResult queryResult = loadIssue(issueKey);
- DefaultIssue issue = (DefaultIssue) queryResult.first();
- User user = null;
- if (!Strings.isNullOrEmpty(assignee)) {
- user = userFinder.findByLogin(assignee);
- if (user == null) {
- throw new IllegalArgumentException("Unknown user: " + assignee);
- }
- }
- IssueChangeContext context = IssueChangeContext.createUser(new Date(), userSession.login());
- if (issueUpdater.assign(issue, user, context)) {
- issueStorage.save(issue);
- issueNotifications.sendChanges(issue, context, queryResult);
- dryRunCache.reportResourceModification(issue.componentKey());
- }
- return issue;
- }
+ Issue doTransition(String issueKey, String transitionKey);
- public Issue plan(String issueKey, @Nullable String actionPlanKey, UserSession userSession) {
- verifyLoggedIn(userSession);
- ActionPlan actionPlan = null;
- if (!Strings.isNullOrEmpty(actionPlanKey)) {
- actionPlan = actionPlanService.findByKey(actionPlanKey, userSession);
- if (actionPlan == null) {
- throw new IllegalArgumentException("Unknown action plan: " + actionPlanKey);
- }
- }
- IssueQueryResult queryResult = loadIssue(issueKey);
- DefaultIssue issue = (DefaultIssue) queryResult.first();
+ Issue assign(String issueKey, @Nullable String assignee);
- IssueChangeContext context = IssueChangeContext.createUser(new Date(), userSession.login());
- if (issueUpdater.plan(issue, actionPlan, context)) {
- issueStorage.save(issue);
- issueNotifications.sendChanges(issue, context, queryResult);
- dryRunCache.reportResourceModification(issue.componentKey());
- }
- return issue;
- }
+ Issue plan(String issueKey, @Nullable String actionPlanKey);
- public Issue setSeverity(String issueKey, String severity, UserSession userSession) {
- verifyLoggedIn(userSession);
- IssueQueryResult queryResult = loadIssue(issueKey);
- DefaultIssue issue = (DefaultIssue) queryResult.first();
- userSession.checkProjectPermission(UserRole.ISSUE_ADMIN, issue.projectKey());
+ Issue setSeverity(String issueKey, String severity);
- IssueChangeContext context = IssueChangeContext.createUser(new Date(), userSession.login());
- if (issueUpdater.setManualSeverity(issue, severity, context)) {
- issueStorage.save(issue);
- issueNotifications.sendChanges(issue, context, queryResult);
- dryRunCache.reportResourceModification(issue.componentKey());
- }
- return issue;
- }
-
- public DefaultIssue createManualIssue(String componentKey, RuleKey ruleKey, @Nullable Integer line, @Nullable String message, @Nullable String severity,
- @Nullable Double effortToFix, UserSession userSession) {
- verifyLoggedIn(userSession);
- ResourceDto component = resourceDao.getResource(ResourceQuery.create().setKey(componentKey));
- ResourceDto project = resourceDao.getRootProjectByComponentKey(componentKey);
- if (component == null || project == null) {
- throw new IllegalArgumentException("Unknown component: " + componentKey);
- }
- if (!authorizationDao.isAuthorizedComponentKey(component.getKey(), userSession.userId(), UserRole.USER)) {
- // TODO throw unauthorized
- throw new IllegalStateException("User does not have the required role");
- }
- if (!ruleKey.isManual()) {
- throw new IllegalArgumentException("Issues can be created only on rules marked as 'manual': " + ruleKey);
- }
- Rule rule = findRule(ruleKey);
-
- DefaultIssue issue = (DefaultIssue) new DefaultIssueBuilder()
- .componentKey(component.getKey())
- .projectKey(project.getKey())
- .line(line)
- .message(!Strings.isNullOrEmpty(message) ? message : rule.getName())
- .severity(Objects.firstNonNull(severity, Severity.MAJOR))
- .effortToFix(effortToFix)
- .ruleKey(ruleKey)
- .reporter(UserSession.get().login())
- .build();
-
- Date now = new Date();
- issue.setCreationDate(now);
- issue.setUpdateDate(now);
- issueStorage.save(issue);
- dryRunCache.reportResourceModification(component.getKey());
- return issue;
- }
-
- private Rule findRule(RuleKey ruleKey) {
- Rule rule = ruleFinder.findByKey(ruleKey);
- if (rule == null) {
- throw new IllegalArgumentException("Unknown rule: " + ruleKey);
- }
- return rule;
- }
-
- public IssueQueryResult loadIssue(String issueKey) {
- // TODO use IssueIndex for ACL
- // TODO load DTO
- IssueQueryResult result = finder.find(IssueQuery.builder().issueKeys(Arrays.asList(issueKey)).requiredRole(UserRole.USER).build());
- if (result.issues().size() != 1) {
- // TODO throw 404
- throw new IllegalArgumentException("Issue not found: " + issueKey);
- }
- return result;
- }
-
- public List<String> listStatus() {
- return workflow.statusKeys();
- }
-
- private void verifyLoggedIn(UserSession userSession) {
- if (!userSession.isLoggedIn()) {
- // must be logged
- throw new IllegalStateException("User is not logged in");
- }
- }
+ DefaultIssue createManualIssue(String componentKey, RuleKey ruleKey, @Nullable Integer line, @Nullable String message, @Nullable String severity,
+ @Nullable Double effortToFix);
// TODO result should be replaced by an aggregation object in IssueIndex
- public RulesAggregation findRulesByComponent(String componentKey, @Nullable Date periodDate, DbSession session) {
- RulesAggregation rulesAggregation = new RulesAggregation();
- for (RuleDto ruleDto : issueDao.findRulesByComponent(componentKey, periodDate, session)) {
- rulesAggregation.add(ruleDto);
- }
- return rulesAggregation;
- }
+ RulesAggregation findRulesByComponent(String componentKey, @Nullable Date periodDate, DbSession session);
// TODO result should be replaced by an aggregation object in IssueIndex
- public Multiset<String> findSeveritiesByComponent(String componentKey, @Nullable Date periodDate, DbSession session) {
- Multiset<String> aggregation = HashMultiset.create();
- for (String severity : issueDao.findSeveritiesByComponent(componentKey, periodDate, session)) {
- aggregation.add(severity);
- }
- return aggregation;
- }
-
- public Issue getByKey(String key) {
- return indexClient.get(IssueIndex.class).getByKey(key);
- }
+ Multiset<String> findSeveritiesByComponent(String componentKey, @Nullable Date periodDate, DbSession session);
- public org.sonar.server.search.Result<Issue> search(IssueQuery query, QueryContext options) {
- IssueIndex issueIndex = indexClient.get(IssueIndex.class);
- return issueIndex.search(query, options);
- }
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.issue;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Strings;
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.issue.ActionPlan;
+import org.sonar.api.issue.Issue;
+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.IssueDao;
+import org.sonar.core.issue.db.IssueStorage;
+import org.sonar.core.issue.workflow.IssueWorkflow;
+import org.sonar.core.issue.workflow.Transition;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.preview.PreviewCache;
+import org.sonar.core.resource.ResourceDao;
+import org.sonar.core.resource.ResourceDto;
+import org.sonar.core.resource.ResourceQuery;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.core.user.AuthorizationDao;
+import org.sonar.server.issue.actionplan.ActionPlanService;
+import org.sonar.server.user.UserSession;
+
+import javax.annotation.Nullable;
+
+import java.util.*;
+
+/**
+ * @since 3.6
+ */
+public class OldIssueService implements IssueService {
+
+ private final DefaultIssueFinder finder;
+ private final IssueWorkflow workflow;
+ private final IssueUpdater issueUpdater;
+ private final IssueStorage issueStorage;
+ private final IssueNotifications issueNotifications;
+ private final ActionPlanService actionPlanService;
+ private final RuleFinder ruleFinder;
+ private final ResourceDao resourceDao;
+ private final IssueDao issueDao;
+ private final AuthorizationDao authorizationDao;
+ private final UserFinder userFinder;
+ private final PreviewCache dryRunCache;
+
+ public OldIssueService(
+ DefaultIssueFinder finder,
+ IssueWorkflow workflow,
+ IssueStorage issueStorage,
+ IssueUpdater issueUpdater,
+ IssueNotifications issueNotifications,
+ ActionPlanService actionPlanService,
+ RuleFinder ruleFinder,
+ ResourceDao resourceDao,
+ IssueDao issueDao,
+ AuthorizationDao authorizationDao,
+ UserFinder userFinder,
+ PreviewCache dryRunCache) {
+ this.finder = finder;
+ this.workflow = workflow;
+ this.issueStorage = issueStorage;
+ this.issueUpdater = issueUpdater;
+ this.actionPlanService = actionPlanService;
+ this.ruleFinder = ruleFinder;
+ this.issueNotifications = issueNotifications;
+ this.resourceDao = resourceDao;
+ this.issueDao = issueDao;
+ this.authorizationDao = authorizationDao;
+ this.userFinder = userFinder;
+ this.dryRunCache = dryRunCache;
+ }
+
+ /**
+ * List of available transitions.
+ * <p/>
+ * Never return null, but return an empty list if the issue does not exist.
+ */
+ public List<Transition> listTransitions(String issueKey) {
+ Issue issue = loadIssue(issueKey).first();
+ return listTransitions(issue);
+ }
+
+ /**
+ * Never return null, but an empty list if the issue does not exist.
+ * No security check is done since it should already have been done to get the issue
+ */
+ public List<Transition> listTransitions(@Nullable Issue issue) {
+ if (issue == null) {
+ return Collections.emptyList();
+ }
+ List<Transition> outTransitions = workflow.outTransitions(issue);
+ List<Transition> allowedTransitions = new ArrayList<Transition>();
+ for (Transition transition : outTransitions) {
+ DefaultIssue defaultIssue = (DefaultIssue) issue;
+ String projectKey = defaultIssue.projectKey();
+ if (StringUtils.isBlank(transition.requiredProjectPermission()) ||
+ (projectKey != null && UserSession.get().hasProjectPermission(transition.requiredProjectPermission(), projectKey))) {
+ allowedTransitions.add(transition);
+ }
+ }
+ return allowedTransitions;
+ }
+
+ public Issue doTransition(String issueKey, String transitionKey) {
+ verifyLoggedIn();
+ IssueQueryResult queryResult = loadIssue(issueKey);
+ DefaultIssue defaultIssue = (DefaultIssue) queryResult.first();
+ IssueChangeContext context = IssueChangeContext.createUser(new Date(), UserSession.get().login());
+ checkTransitionPermission(transitionKey, UserSession.get(), defaultIssue);
+ if (workflow.doTransition(defaultIssue, transitionKey, context)) {
+ issueStorage.save(defaultIssue);
+ issueNotifications.sendChanges(defaultIssue, context, queryResult);
+ dryRunCache.reportResourceModification(defaultIssue.componentKey());
+ }
+ return defaultIssue;
+ }
+
+ private void checkTransitionPermission(String transitionKey, UserSession userSession, DefaultIssue defaultIssue) {
+ List<Transition> outTransitions = workflow.outTransitions(defaultIssue);
+ for (Transition transition : outTransitions) {
+ String projectKey = defaultIssue.projectKey();
+ if (transition.key().equals(transitionKey) && StringUtils.isNotBlank(transition.requiredProjectPermission()) && projectKey != null) {
+ userSession.checkProjectPermission(transition.requiredProjectPermission(), projectKey);
+ }
+ }
+ }
+
+ public Issue assign(String issueKey, @Nullable String assignee) {
+ verifyLoggedIn();
+ IssueQueryResult queryResult = loadIssue(issueKey);
+ DefaultIssue issue = (DefaultIssue) queryResult.first();
+ User user = null;
+ if (!Strings.isNullOrEmpty(assignee)) {
+ user = userFinder.findByLogin(assignee);
+ if (user == null) {
+ throw new IllegalArgumentException("Unknown user: " + assignee);
+ }
+ }
+ IssueChangeContext context = IssueChangeContext.createUser(new Date(), UserSession.get().login());
+ if (issueUpdater.assign(issue, user, context)) {
+ issueStorage.save(issue);
+ issueNotifications.sendChanges(issue, context, queryResult);
+ dryRunCache.reportResourceModification(issue.componentKey());
+ }
+ return issue;
+ }
+
+ public Issue plan(String issueKey, @Nullable String actionPlanKey) {
+ verifyLoggedIn();
+ ActionPlan actionPlan = null;
+ if (!Strings.isNullOrEmpty(actionPlanKey)) {
+ actionPlan = actionPlanService.findByKey(actionPlanKey, UserSession.get());
+ if (actionPlan == null) {
+ throw new IllegalArgumentException("Unknown action plan: " + actionPlanKey);
+ }
+ }
+ IssueQueryResult queryResult = loadIssue(issueKey);
+ DefaultIssue issue = (DefaultIssue) queryResult.first();
+
+ IssueChangeContext context = IssueChangeContext.createUser(new Date(), UserSession.get().login());
+ if (issueUpdater.plan(issue, actionPlan, context)) {
+ issueStorage.save(issue);
+ issueNotifications.sendChanges(issue, context, queryResult);
+ dryRunCache.reportResourceModification(issue.componentKey());
+ }
+ return issue;
+ }
+
+ public Issue setSeverity(String issueKey, String severity) {
+ verifyLoggedIn();
+ IssueQueryResult queryResult = loadIssue(issueKey);
+ DefaultIssue issue = (DefaultIssue) queryResult.first();
+ UserSession.get().checkProjectPermission(UserRole.ISSUE_ADMIN, issue.projectKey());
+
+ IssueChangeContext context = IssueChangeContext.createUser(new Date(), UserSession.get().login());
+ if (issueUpdater.setManualSeverity(issue, severity, context)) {
+ issueStorage.save(issue);
+ issueNotifications.sendChanges(issue, context, queryResult);
+ dryRunCache.reportResourceModification(issue.componentKey());
+ }
+ return issue;
+ }
+
+ public DefaultIssue createManualIssue(String componentKey, RuleKey ruleKey, @Nullable Integer line, @Nullable String message, @Nullable String severity,
+ @Nullable Double effortToFix) {
+ verifyLoggedIn();
+ ResourceDto component = resourceDao.getResource(ResourceQuery.create().setKey(componentKey));
+ ResourceDto project = resourceDao.getRootProjectByComponentKey(componentKey);
+ if (component == null || project == null) {
+ throw new IllegalArgumentException("Unknown component: " + componentKey);
+ }
+ if (!authorizationDao.isAuthorizedComponentKey(component.getKey(), UserSession.get().userId(), UserRole.USER)) {
+ // TODO throw unauthorized
+ throw new IllegalStateException("User does not have the required role");
+ }
+ if (!ruleKey.isManual()) {
+ throw new IllegalArgumentException("Issues can be created only on rules marked as 'manual': " + ruleKey);
+ }
+ Rule rule = findRule(ruleKey);
+
+ DefaultIssue issue = (DefaultIssue) new DefaultIssueBuilder()
+ .componentKey(component.getKey())
+ .projectKey(project.getKey())
+ .line(line)
+ .message(!Strings.isNullOrEmpty(message) ? message : rule.getName())
+ .severity(Objects.firstNonNull(severity, Severity.MAJOR))
+ .effortToFix(effortToFix)
+ .ruleKey(ruleKey)
+ .reporter(UserSession.get().login())
+ .build();
+
+ Date now = new Date();
+ issue.setCreationDate(now);
+ issue.setUpdateDate(now);
+ issueStorage.save(issue);
+ dryRunCache.reportResourceModification(component.getKey());
+ return issue;
+ }
+
+ private Rule findRule(RuleKey ruleKey) {
+ Rule rule = ruleFinder.findByKey(ruleKey);
+ if (rule == null) {
+ throw new IllegalArgumentException("Unknown rule: " + ruleKey);
+ }
+ return rule;
+ }
+
+ public IssueQueryResult loadIssue(String issueKey) {
+ // TODO use IssueIndex for ACL
+ // TODO load DTO
+ IssueQueryResult result = finder.find(IssueQuery.builder().issueKeys(Arrays.asList(issueKey)).requiredRole(UserRole.USER).build());
+ if (result.issues().size() != 1) {
+ // TODO throw 404
+ throw new IllegalArgumentException("Issue not found: " + issueKey);
+ }
+ return result;
+ }
+
+ public List<String> listStatus() {
+ return workflow.statusKeys();
+ }
+
+ private void verifyLoggedIn() {
+ if (!UserSession.get().isLoggedIn()) {
+ // must be logged
+ throw new IllegalStateException("User is not logged in");
+ }
+ }
+
+ // TODO result should be replaced by an aggregation object in IssueIndex
+ public RulesAggregation findRulesByComponent(String componentKey, @Nullable Date periodDate, DbSession session) {
+ RulesAggregation rulesAggregation = new RulesAggregation();
+ for (RuleDto ruleDto : issueDao.findRulesByComponent(componentKey, periodDate, session)) {
+ rulesAggregation.add(ruleDto);
+ }
+ return rulesAggregation;
+ }
+
+ // TODO result should be replaced by an aggregation object in IssueIndex
+ public Multiset<String> findSeveritiesByComponent(String componentKey, @Nullable Date periodDate, DbSession session) {
+ Multiset<String> aggregation = HashMultiset.create();
+ for (String severity : issueDao.findSeveritiesByComponent(componentKey, periodDate, session)) {
+ aggregation.add(severity);
+ }
+ return aggregation;
+ }
+
+}
public void writeTransitions(Issue issue, JsonWriter json) {
json.name("transitions").beginArray();
if (UserSession.get().isLoggedIn()) {
- List<Transition> transitions = issueService.listTransitions(issue, UserSession.get());
+ List<Transition> transitions = issueService.listTransitions(issue);
for (Transition transition : transitions) {
json.value(transition.key());
}
import com.google.common.collect.Iterables;
import com.google.common.io.Resources;
import org.sonar.api.i18n.I18n;
-import org.sonar.api.issue.ActionPlan;
-import org.sonar.api.issue.Issue;
-import org.sonar.api.issue.IssueComment;
-import org.sonar.api.issue.IssueQuery;
-import org.sonar.api.issue.IssueQueryResult;
+import org.sonar.api.issue.*;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.Severity;
import org.sonar.api.server.ws.Request;
import org.sonar.markdown.Markdown;
import org.sonar.server.component.DefaultComponentFinder;
import org.sonar.server.db.DbClient;
+import org.sonar.server.issue.DefaultIssueService;
import org.sonar.server.issue.IssueService;
import org.sonar.server.issue.actionplan.ActionPlanService;
import org.sonar.server.issue.filter.IssueFilterParameters;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import static com.google.common.collect.Lists.newArrayList;
@Override
protected Result<Issue> doSearch(IssueQuery query, QueryContext context) {
- return service.search(query, context);
+ return ((DefaultIssueService)service).search(query, context);
}
@Override
import org.sonar.core.metric.DefaultMetricFinder;
import org.sonar.core.notification.DefaultNotificationManager;
import org.sonar.core.permission.PermissionFacade;
-import org.sonar.core.persistence.DaoUtils;
-import org.sonar.core.persistence.DatabaseVersion;
-import org.sonar.core.persistence.DefaultDatabase;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.core.persistence.PreviewDatabaseFactory;
-import org.sonar.core.persistence.SemaphoreUpdater;
-import org.sonar.core.persistence.SemaphoresImpl;
+import org.sonar.core.persistence.*;
import org.sonar.core.preview.PreviewCache;
import org.sonar.core.profiling.Profiling;
import org.sonar.core.purge.PurgeProfiler;
import org.sonar.server.activity.ws.ActivitiesWebService;
import org.sonar.server.activity.ws.ActivityMapping;
import org.sonar.server.authentication.ws.AuthenticationWs;
-import org.sonar.server.batch.BatchIndex;
-import org.sonar.server.batch.BatchWs;
-import org.sonar.server.batch.GlobalReferentialsAction;
-import org.sonar.server.batch.ProjectReferentialsAction;
-import org.sonar.server.batch.UploadReportAction;
+import org.sonar.server.batch.*;
import org.sonar.server.charts.ChartFactory;
import org.sonar.server.component.ComponentCleanerService;
import org.sonar.server.component.DefaultComponentFinder;
import org.sonar.server.component.DefaultRubyComponentService;
import org.sonar.server.component.db.ComponentDao;
import org.sonar.server.component.db.SnapshotDao;
-import org.sonar.server.component.ws.ComponentAppAction;
-import org.sonar.server.component.ws.ComponentsWs;
-import org.sonar.server.component.ws.EventsWs;
-import org.sonar.server.component.ws.ProjectsWs;
-import org.sonar.server.component.ws.ResourcesWs;
+import org.sonar.server.component.ws.*;
import org.sonar.server.config.ws.PropertiesWs;
import org.sonar.server.db.DatabaseChecker;
import org.sonar.server.db.DbClient;
import org.sonar.server.db.EmbeddedDatabaseFactory;
import org.sonar.server.db.migrations.DatabaseMigrations;
import org.sonar.server.db.migrations.DatabaseMigrator;
-import org.sonar.server.debt.DebtCharacteristicsXMLImporter;
-import org.sonar.server.debt.DebtModelBackup;
-import org.sonar.server.debt.DebtModelLookup;
-import org.sonar.server.debt.DebtModelOperations;
-import org.sonar.server.debt.DebtModelPluginRepository;
-import org.sonar.server.debt.DebtModelService;
-import org.sonar.server.debt.DebtModelXMLExporter;
-import org.sonar.server.debt.DebtRulesXMLImporter;
+import org.sonar.server.debt.*;
import org.sonar.server.design.FileDesignWidget;
import org.sonar.server.design.PackageDesignWidget;
import org.sonar.server.duplication.ws.DuplicationsJsonWriter;
import org.sonar.server.duplication.ws.DuplicationsParser;
import org.sonar.server.duplication.ws.DuplicationsWs;
-import org.sonar.server.issue.ActionService;
-import org.sonar.server.issue.AssignAction;
-import org.sonar.server.issue.CommentAction;
-import org.sonar.server.issue.DefaultIssueFinder;
-import org.sonar.server.issue.InternalRubyIssueService;
-import org.sonar.server.issue.IssueBulkChangeService;
-import org.sonar.server.issue.IssueChangelogFormatter;
-import org.sonar.server.issue.IssueChangelogService;
-import org.sonar.server.issue.IssueCommentService;
-import org.sonar.server.issue.IssueService;
-import org.sonar.server.issue.IssueStatsFinder;
-import org.sonar.server.issue.PlanAction;
-import org.sonar.server.issue.PublicRubyIssueService;
-import org.sonar.server.issue.ServerIssueStorage;
-import org.sonar.server.issue.SetSeverityAction;
-import org.sonar.server.issue.TransitionAction;
+import org.sonar.server.issue.*;
import org.sonar.server.issue.actionplan.ActionPlanService;
import org.sonar.server.issue.actionplan.ActionPlanWs;
import org.sonar.server.issue.db.IssueAuthorizationDao;
import org.sonar.server.platform.ws.RestartHandler;
import org.sonar.server.platform.ws.ServerWs;
import org.sonar.server.platform.ws.SystemWs;
-import org.sonar.server.plugins.InstalledPluginReferentialFactory;
-import org.sonar.server.plugins.PluginDownloader;
-import org.sonar.server.plugins.ServerExtensionInstaller;
-import org.sonar.server.plugins.ServerPluginJarInstaller;
-import org.sonar.server.plugins.ServerPluginJarsInstaller;
-import org.sonar.server.plugins.ServerPluginRepository;
-import org.sonar.server.plugins.UpdateCenterClient;
-import org.sonar.server.plugins.UpdateCenterMatrixFactory;
+import org.sonar.server.plugins.*;
import org.sonar.server.qualitygate.QgateProjectFinder;
import org.sonar.server.qualitygate.QualityGates;
import org.sonar.server.qualitygate.RegisterQualityGates;
-import org.sonar.server.qualitygate.ws.QGatesAppAction;
-import org.sonar.server.qualitygate.ws.QGatesCopyAction;
-import org.sonar.server.qualitygate.ws.QGatesCreateAction;
-import org.sonar.server.qualitygate.ws.QGatesCreateConditionAction;
-import org.sonar.server.qualitygate.ws.QGatesDeleteConditionAction;
-import org.sonar.server.qualitygate.ws.QGatesDeselectAction;
-import org.sonar.server.qualitygate.ws.QGatesDestroyAction;
-import org.sonar.server.qualitygate.ws.QGatesListAction;
-import org.sonar.server.qualitygate.ws.QGatesRenameAction;
-import org.sonar.server.qualitygate.ws.QGatesSearchAction;
-import org.sonar.server.qualitygate.ws.QGatesSelectAction;
-import org.sonar.server.qualitygate.ws.QGatesSetAsDefaultAction;
-import org.sonar.server.qualitygate.ws.QGatesShowAction;
-import org.sonar.server.qualitygate.ws.QGatesUnsetDefaultAction;
-import org.sonar.server.qualitygate.ws.QGatesUpdateConditionAction;
-import org.sonar.server.qualitygate.ws.QGatesWs;
-import org.sonar.server.qualityprofile.BuiltInProfiles;
-import org.sonar.server.qualityprofile.QProfileBackuper;
-import org.sonar.server.qualityprofile.QProfileCopier;
-import org.sonar.server.qualityprofile.QProfileExporters;
-import org.sonar.server.qualityprofile.QProfileFactory;
-import org.sonar.server.qualityprofile.QProfileLoader;
-import org.sonar.server.qualityprofile.QProfileLookup;
-import org.sonar.server.qualityprofile.QProfileProjectLookup;
-import org.sonar.server.qualityprofile.QProfileProjectOperations;
-import org.sonar.server.qualityprofile.QProfileRepositoryExporter;
-import org.sonar.server.qualityprofile.QProfileReset;
-import org.sonar.server.qualityprofile.QProfileService;
-import org.sonar.server.qualityprofile.QProfiles;
-import org.sonar.server.qualityprofile.RegisterQualityProfiles;
-import org.sonar.server.qualityprofile.RuleActivator;
-import org.sonar.server.qualityprofile.RuleActivatorContextFactory;
+import org.sonar.server.qualitygate.ws.*;
+import org.sonar.server.qualityprofile.*;
import org.sonar.server.qualityprofile.db.ActiveRuleDao;
import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
import org.sonar.server.qualityprofile.index.ActiveRuleNormalizer;
-import org.sonar.server.qualityprofile.ws.BulkRuleActivationActions;
-import org.sonar.server.qualityprofile.ws.ProfilesWs;
-import org.sonar.server.qualityprofile.ws.QProfileRestoreBuiltInAction;
-import org.sonar.server.qualityprofile.ws.QProfilesWs;
-import org.sonar.server.qualityprofile.ws.RuleActivationActions;
-import org.sonar.server.rule.DefaultRuleFinder;
-import org.sonar.server.rule.DeprecatedRulesDefinition;
-import org.sonar.server.rule.RegisterRules;
-import org.sonar.server.rule.RubyRuleService;
-import org.sonar.server.rule.RuleCreator;
-import org.sonar.server.rule.RuleDefinitionsLoader;
-import org.sonar.server.rule.RuleDeleter;
-import org.sonar.server.rule.RuleOperations;
-import org.sonar.server.rule.RuleRepositories;
-import org.sonar.server.rule.RuleService;
-import org.sonar.server.rule.RuleUpdater;
+import org.sonar.server.qualityprofile.ws.*;
+import org.sonar.server.rule.*;
import org.sonar.server.rule.db.RuleDao;
import org.sonar.server.rule.index.RuleIndex;
import org.sonar.server.rule.index.RuleNormalizer;
-import org.sonar.server.rule.ws.ActiveRuleCompleter;
-import org.sonar.server.rule.ws.AppAction;
-import org.sonar.server.rule.ws.DeleteAction;
-import org.sonar.server.rule.ws.RuleMapping;
-import org.sonar.server.rule.ws.RulesWebService;
-import org.sonar.server.rule.ws.SearchAction;
-import org.sonar.server.rule.ws.TagsAction;
-import org.sonar.server.rule.ws.UpdateAction;
-import org.sonar.server.search.IndexClient;
-import org.sonar.server.search.IndexQueue;
-import org.sonar.server.search.IndexSynchronizer;
-import org.sonar.server.search.SearchClient;
-import org.sonar.server.search.SearchHealth;
+import org.sonar.server.rule.ws.*;
+import org.sonar.server.search.*;
import org.sonar.server.source.CodeColorizers;
import org.sonar.server.source.DeprecatedSourceDecorator;
import org.sonar.server.source.HtmlSourceDecorator;
import org.sonar.server.source.ws.ScmWriter;
import org.sonar.server.source.ws.ShowAction;
import org.sonar.server.source.ws.SourcesWs;
-import org.sonar.server.startup.CleanPreviewAnalysisCache;
-import org.sonar.server.startup.CopyRequirementsFromCharacteristicsToRules;
-import org.sonar.server.startup.GeneratePluginIndex;
-import org.sonar.server.startup.GwtPublisher;
-import org.sonar.server.startup.JdbcDriverDeployer;
-import org.sonar.server.startup.LogServerId;
-import org.sonar.server.startup.RegisterDashboards;
-import org.sonar.server.startup.RegisterDebtModel;
-import org.sonar.server.startup.RegisterMetrics;
-import org.sonar.server.startup.RegisterNewMeasureFilters;
-import org.sonar.server.startup.RegisterPermissionTemplates;
-import org.sonar.server.startup.RegisterServletFilters;
-import org.sonar.server.startup.RenameDeprecatedPropertyKeys;
-import org.sonar.server.startup.ServerMetadataPersister;
+import org.sonar.server.startup.*;
import org.sonar.server.test.CoverageService;
-import org.sonar.server.test.ws.CoverageShowAction;
-import org.sonar.server.test.ws.CoverageWs;
-import org.sonar.server.test.ws.TestsCoveredFilesAction;
-import org.sonar.server.test.ws.TestsShowAction;
-import org.sonar.server.test.ws.TestsTestCasesAction;
-import org.sonar.server.test.ws.TestsWs;
+import org.sonar.server.test.ws.*;
import org.sonar.server.text.MacroInterpreter;
import org.sonar.server.text.RubyTextService;
import org.sonar.server.ui.JRubyI18n;
import org.sonar.server.ui.PageDecorations;
import org.sonar.server.ui.Views;
import org.sonar.server.updatecenter.ws.UpdateCenterWs;
-import org.sonar.server.user.DefaultUserService;
-import org.sonar.server.user.DoPrivileged;
-import org.sonar.server.user.GroupMembershipFinder;
-import org.sonar.server.user.GroupMembershipService;
-import org.sonar.server.user.NewUserNotifier;
-import org.sonar.server.user.SecurityRealmFactory;
+import org.sonar.server.user.*;
import org.sonar.server.user.db.GroupDao;
import org.sonar.server.user.ws.FavoritesWs;
import org.sonar.server.user.ws.UserPropertiesWs;
import org.sonar.server.user.ws.UsersWs;
-import org.sonar.server.util.BooleanTypeValidation;
-import org.sonar.server.util.FloatTypeValidation;
-import org.sonar.server.util.IntegerTypeValidation;
-import org.sonar.server.util.StringListTypeValidation;
-import org.sonar.server.util.StringTypeValidation;
-import org.sonar.server.util.TextTypeValidation;
-import org.sonar.server.util.TypeValidations;
+import org.sonar.server.util.*;
import org.sonar.server.ws.ListingWs;
import org.sonar.server.ws.WebServiceEngine;
pico.addSingleton(IssueUpdater.class);
pico.addSingleton(FunctionExecutor.class);
pico.addSingleton(IssueWorkflow.class);
- pico.addSingleton(IssueService.class);
pico.addSingleton(IssueCommentService.class);
pico.addSingleton(DefaultIssueFinder.class);
pico.addSingleton(IssueStatsFinder.class);
// Switch Issue search
if (properties.getProperty("sonar.issues.use_es_backend", null) != null) {
pico.addSingleton(org.sonar.server.issue.ws.SearchAction.class);
+ pico.addSingleton(DefaultIssueService.class);
} else {
pico.addSingleton(IssueSearchAction.class);
+ pico.addSingleton(OldIssueService.class);
}
pico.addSingleton(IssueActionsWriter.class);
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.sonar.api.config.Settings;
import org.sonar.core.persistence.DbSession;
import org.sonar.server.activity.index.ActivityIndex;
import org.sonar.server.db.Dao;
private final DbClient db;
private final IndexClient index;
+ private final Settings settings;
- public IndexSynchronizer(DbClient db, IndexClient index) {
+ public IndexSynchronizer(DbClient db, IndexClient index, Settings settings) {
this.db = db;
this.index = index;
+ this.settings = settings;
}
public void execute() {
LOG.info("Starting DB to Index synchronization");
long start = System.currentTimeMillis();
synchronize(session, db.ruleDao(), index.get(RuleIndex.class));
- synchronize(session, db.issueDao(), index.get(IssueIndex.class));
- synchronize(session, db.issueAuthorizationDao(), index.get(IssueAuthorizationIndex.class));
+
+ // Switch Issue search
+ if (settings.getString("sonar.issues.use_es_backend") != null) {
+ synchronize(session, db.issueDao(), index.get(IssueIndex.class));
+ synchronize(session, db.issueAuthorizationDao(), index.get(IssueAuthorizationIndex.class));
+ }
+
synchronize(session, db.activeRuleDao(), index.get(ActiveRuleIndex.class));
synchronize(session, db.activityDao(), index.get(ActivityIndex.class));
session.commit();
MockUserSession.set().addComponentPermission(UserRole.USER, SUB_PROJECT_KEY, COMPONENT_KEY);
addComponent();
-
addMeasure(CoreMetrics.IT_COVERAGE_KEY, 85.2);
WsTester.TestRequest request = tester.newGetRequest("api/components", "app").setParam("key", COMPONENT_KEY);
when(resourceDao.getLastSnapshotByResourceId(eq(1L), eq(session))).thenReturn(
new SnapshotDto().setPeriodMode(1, "previous_analysis").setPeriodDate(1, DateUtils.parseDate("2014-05-08"))
- );
+ );
when(periods.label(anyString(), anyString(), any(Date.class))).thenReturn("since previous analysis (May 08 2014)");
WsTester.TestRequest request = tester.newGetRequest("api/components", "app").setParam("key", COMPONENT_KEY);
addComponent();
when(issueService.findRulesByComponent(COMPONENT_KEY, null, session)).thenReturn(
new RulesAggregation().add(new RuleDto().setRuleKey("AvoidCycle").setRepositoryKey("squid").setName("Avoid Cycle"))
- );
+ );
WsTester.TestRequest request = tester.newGetRequest("api/components", "app").setParam("key", COMPONENT_KEY);
request.execute().assertJson(getClass(), "app_with_rules.json");
Date periodDate = DateUtils.parseDate("2014-05-08");
when(resourceDao.getLastSnapshotByResourceId(eq(1L), eq(session))).thenReturn(
new SnapshotDto().setPeriodMode(1, "previous_analysis").setPeriodDate(1, periodDate)
- );
+ );
when(periods.label(anyString(), anyString(), any(Date.class))).thenReturn("since previous analysis (May 08 2014)");
when(issueService.findRulesByComponent(COMPONENT_KEY, periodDate, session)).thenReturn(
new RulesAggregation().add(new RuleDto().setRuleKey("AvoidCycle").setRepositoryKey("squid").setName("Avoid Cycle"))
- );
+ );
WsTester.TestRequest request = tester.newGetRequest("api/components", "app").setParam("key", COMPONENT_KEY).setParam("period", "1");
request.execute().assertJson(getClass(), "app_with_rules_when_period_is_set.json");
when(componentDao.getById(1L, session)).thenReturn(new ComponentDto().setId(1L).setLongName("SonarQube").setKey("org.codehaus.sonar:sonar"));
}
- private void addPeriod(){
+ private void addPeriod() {
Date periodDate = DateUtils.parseDate("2014-05-08");
when(resourceDao.getLastSnapshotByResourceId(eq(1L), eq(session))).thenReturn(
new SnapshotDto().setPeriodMode(1, "previous_analysis").setPeriodDate(1, periodDate)
- );
+ );
when(periods.label(anyString(), anyString(), any(Date.class))).thenReturn("since previous analysis (May 08 2014)");
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.issue;
+
+import com.google.common.collect.Multiset;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.issue.DefaultTransitions;
+import org.sonar.api.issue.Issue;
+import org.sonar.api.issue.IssueQuery;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.Scopes;
+import org.sonar.api.rule.Severity;
+import org.sonar.api.security.DefaultGroups;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.issue.db.ActionPlanDto;
+import org.sonar.core.issue.db.IssueDto;
+import org.sonar.core.issue.workflow.Transition;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.permission.PermissionFacade;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.core.user.UserDto;
+import org.sonar.server.component.SnapshotTesting;
+import org.sonar.server.component.db.ComponentDao;
+import org.sonar.server.component.db.SnapshotDao;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.issue.db.IssueDao;
+import org.sonar.server.issue.index.IssueIndex;
+import org.sonar.server.rule.RuleTesting;
+import org.sonar.server.rule.db.RuleDao;
+import org.sonar.server.search.IndexClient;
+import org.sonar.server.search.QueryContext;
+import org.sonar.server.tester.ServerTester;
+import org.sonar.server.user.MockUserSession;
+
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class DefaultIssueServiceMediumTest {
+
+ @ClassRule
+ public static ServerTester tester = new ServerTester()
+ .setProperty("sonar.issues.use_es_backend", "true");
+
+ DbClient db;
+ IndexClient indexClient;
+ DbSession session;
+ IssueService service;
+
+ RuleDto rule;
+ ComponentDto project;
+ ComponentDto file;
+ UserDto connectedUser;
+
+ @Before
+ public void setUp() throws Exception {
+ tester.clearDbAndIndexes();
+ db = tester.get(DbClient.class);
+ indexClient = tester.get(IndexClient.class);
+ session = db.openSession(false);
+ service = tester.get(IssueService.class);
+
+ rule = RuleTesting.newXooX1();
+ tester.get(RuleDao.class).insert(session, rule);
+
+ project = new ComponentDto()
+ .setKey("MyProject")
+ .setLongName("My Project")
+ .setQualifier(Qualifiers.PROJECT)
+ .setScope(Scopes.PROJECT);
+ tester.get(ComponentDao.class).insert(session, project);
+ tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForComponent(project));
+
+ file = new ComponentDto()
+ .setProjectId(project.getId())
+ .setSubProjectId(project.getId())
+ .setKey("MyComponent")
+ .setLongName("My Component");
+ tester.get(ComponentDao.class).insert(session, file);
+ tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForComponent(file));
+
+ // project can be seen by anyone
+ tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session);
+ db.issueAuthorizationDao().synchronizeAfter(session, new Date(0));
+
+ connectedUser = new UserDto().setLogin("gandalf").setName("Gandalf");
+ db.userDao().insert(session, connectedUser);
+ tester.get(PermissionFacade.class).insertUserPermission(project.getId(), connectedUser.getId(), UserRole.USER, session);
+
+ MockUserSession.set()
+ .setLogin(connectedUser.getLogin())
+ .setUserId(connectedUser.getId().intValue())
+ .setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN)
+ .addProjectPermissions(UserRole.USER, project.key())
+ .addProjectPermissions(UserRole.ISSUE_ADMIN, project.key());
+
+ session.commit();
+ }
+
+ @After
+ public void after() {
+ session.close();
+ }
+
+ @Test
+ public void can_facet() throws Exception {
+ IssueDto issue1 = newIssue().setActionPlanKey("P1");
+ IssueDto issue2 = newIssue().setActionPlanKey("P2").setResolution("NONE");
+ tester.get(IssueDao.class).insert(session, issue1, issue2);
+ session.commit();
+
+ org.sonar.server.search.Result<Issue> result = ((DefaultIssueService) service).search(IssueQuery.builder().build(), new QueryContext());
+ assertThat(result.getHits()).hasSize(2);
+ assertThat(result.getFacets()).isEmpty();
+
+ result = ((DefaultIssueService) service).search(IssueQuery.builder().build(), new QueryContext().setFacet(true));
+ assertThat(result.getFacets().keySet()).hasSize(4);
+ assertThat(result.getFacetKeys("actionPlan")).hasSize(2);
+ }
+
+ @Test
+ public void list_status() {
+ assertThat(service.listStatus()).containsExactly("OPEN", "CONFIRMED", "REOPENED", "RESOLVED", "CLOSED");
+ }
+
+ @Test
+ public void list_transitions() {
+ IssueDto issue = newIssue().setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_FALSE_POSITIVE);
+ tester.get(IssueDao.class).insert(session, issue);
+ session.commit();
+
+ List<Transition> result = service.listTransitions(issue.getKey());
+ assertThat(result).hasSize(1);
+ assertThat(result.get(0).key()).isEqualTo("reopen");
+ }
+
+ @Test
+ public void do_transition() {
+ IssueDto issue = newIssue().setStatus(Issue.STATUS_OPEN);
+ tester.get(IssueDao.class).insert(session, issue);
+ session.commit();
+
+ assertThat(db.issueDao().getByKey(session, issue.getKey())).isNotNull();
+ IssueTesting.assertIsEquivalent(issue, indexClient.get(IssueIndex.class).getByKey(issue.getKey()));
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).status()).isEqualTo(Issue.STATUS_OPEN);
+
+ service.doTransition(issue.getKey(), DefaultTransitions.CONFIRM);
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).status()).isEqualTo(Issue.STATUS_CONFIRMED);
+ }
+
+ @Test
+ public void assign() {
+ IssueDto issue = newIssue();
+ tester.get(IssueDao.class).insert(session, issue);
+
+ UserDto user = new UserDto().setLogin("perceval").setName("Perceval");
+ db.userDao().insert(session, user);
+ session.commit();
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).assignee()).isNull();
+
+ service.assign(issue.getKey(), user.getLogin());
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).assignee()).isEqualTo("perceval");
+ }
+
+ @Test
+ public void un_assign() {
+ IssueDto issue = newIssue().setAssignee("perceval");
+ tester.get(IssueDao.class).insert(session, issue);
+
+ UserDto user = new UserDto().setLogin("perceval").setName("Perceval");
+ db.userDao().insert(session, user);
+ session.commit();
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).assignee()).isEqualTo("perceval");
+
+ service.assign(issue.getKey(), "");
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).assignee()).isNull();
+ }
+
+ @Test
+ public void fail_to_assign_on_unknown_user() {
+ IssueDto issue = newIssue();
+ tester.get(IssueDao.class).insert(session, issue);
+ session.commit();
+
+ try {
+ service.assign(issue.getKey(), "unknown");
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(NotFoundException.class).hasMessage("Unknown user: unknown");
+ }
+ }
+
+ @Test
+ public void plan() {
+ IssueDto issue = newIssue();
+ tester.get(IssueDao.class).insert(session, issue);
+
+ String actionPlanKey = "EFGH";
+ db.actionPlanDao().save(new ActionPlanDto().setKey(actionPlanKey).setProjectId(project.getId()));
+ session.commit();
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).actionPlanKey()).isNull();
+
+ service.plan(issue.getKey(), actionPlanKey);
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).actionPlanKey()).isEqualTo(actionPlanKey);
+ }
+
+ @Test
+ public void un_plan() {
+ String actionPlanKey = "EFGH";
+ db.actionPlanDao().save(new ActionPlanDto().setKey(actionPlanKey).setProjectId(project.getId()));
+
+ IssueDto issue = newIssue().setActionPlanKey(actionPlanKey);
+ tester.get(IssueDao.class).insert(session, issue);
+ session.commit();
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).actionPlanKey()).isEqualTo(actionPlanKey);
+
+ service.plan(issue.getKey(), null);
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).actionPlanKey()).isNull();
+ }
+
+ @Test
+ public void fail_plan_if_action_plan_not_found() {
+ tester.get(IssueDao.class).insert(session, newIssue());
+ session.commit();
+
+ try {
+ service.plan("ABCD", "unknown");
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(NotFoundException.class).hasMessage("Unknown action plan: unknown");
+ }
+ }
+
+ @Test
+ public void set_severity() {
+ IssueDto issue = newIssue().setSeverity(Severity.BLOCKER);
+ tester.get(IssueDao.class).insert(session, issue);
+ session.commit();
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).severity()).isEqualTo(Severity.BLOCKER);
+
+ service.setSeverity(issue.getKey(), Severity.MINOR);
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).severity()).isEqualTo(Severity.MINOR);
+ }
+
+ @Test
+ public void create_manual_issue() {
+ RuleDto manualRule = RuleTesting.newManualRule("manualRuleKey");
+ tester.get(RuleDao.class).insert(session, manualRule);
+ session.commit();
+
+ Issue result = service.createManualIssue(file.key(), manualRule.getKey(), 10, "Fix it", Severity.MINOR, 2d);
+
+ Issue manualIssue = indexClient.get(IssueIndex.class).getByKey(result.key());
+ assertThat(manualIssue.componentKey()).isEqualTo(file.key());
+ assertThat(manualIssue.projectKey()).isEqualTo(project.key());
+ assertThat(manualIssue.ruleKey()).isEqualTo(manualRule.getKey());
+ assertThat(manualIssue.message()).isEqualTo("Fix it");
+ assertThat(manualIssue.line()).isEqualTo(10);
+ assertThat(manualIssue.severity()).isEqualTo(Severity.MINOR);
+ assertThat(manualIssue.effortToFix()).isEqualTo(2d);
+ assertThat(manualIssue.reporter()).isEqualTo(connectedUser.getLogin());
+ }
+
+ @Test
+ public void create_manual_issue_with_major_severity_when_no_severity() {
+ RuleDto manualRule = RuleTesting.newManualRule("manualRuleKey");
+ tester.get(RuleDao.class).insert(session, manualRule);
+ session.commit();
+
+ Issue result = service.createManualIssue(file.key(), manualRule.getKey(), 10, "Fix it", null, 2d);
+
+ Issue manualIssue = indexClient.get(IssueIndex.class).getByKey(result.key());
+ assertThat(manualIssue.severity()).isEqualTo(Severity.MAJOR);
+ }
+
+ @Test
+ public void create_manual_issue_with_rule_name_when_no_message() {
+ RuleDto manualRule = RuleTesting.newManualRule("manualRuleKey").setName("Manual rule name");
+ tester.get(RuleDao.class).insert(session, manualRule);
+ session.commit();
+
+ Issue result = service.createManualIssue(file.key(), manualRule.getKey(), 10, null, null, 2d);
+
+ Issue manualIssue = indexClient.get(IssueIndex.class).getByKey(result.key());
+ assertThat(manualIssue.message()).isEqualTo("Manual rule name");
+ }
+
+ @Test
+ public void fail_create_manual_issue_on_not_manual_rule() {
+ try {
+ service.createManualIssue(file.key(), rule.getKey(), 10, "Fix it", null, 2d);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Issues can be created only on rules marked as 'manual': xoo:x1");
+ }
+ }
+
+ @Test(expected = ForbiddenException.class)
+ public void fail_create_manual_issue_if_not_having_required_role() {
+ // User has not the 'user' role on the project
+ MockUserSession.set()
+ .setLogin(connectedUser.getLogin())
+ .setUserId(connectedUser.getId().intValue())
+ .setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN)
+ .addProjectPermissions(UserRole.CODEVIEWER, project.key());
+
+ RuleDto manualRule = RuleTesting.newManualRule("manualRuleKey");
+ tester.get(RuleDao.class).insert(session, manualRule);
+ session.commit();
+
+ service.createManualIssue(file.key(), rule.getKey(), 10, "Fix it", null, 2d);
+ }
+
+ @Test
+ public void find_rules_by_component() throws Exception {
+ // 2 issues on the same rule
+ tester.get(IssueDao.class).insert(session, newIssue().setRule(rule));
+ tester.get(IssueDao.class).insert(session, newIssue().setRule(rule));
+ session.commit();
+
+ RulesAggregation result = service.findRulesByComponent(file.key(), null, session);
+ assertThat(result.rules()).hasSize(1);
+ }
+
+ @Test
+ public void find_rules_by_severity() throws Exception {
+ tester.get(IssueDao.class).insert(session, newIssue().setSeverity(Severity.MAJOR));
+ tester.get(IssueDao.class).insert(session, newIssue().setSeverity(Severity.MAJOR));
+ tester.get(IssueDao.class).insert(session, newIssue().setSeverity(Severity.INFO));
+ session.commit();
+
+ Multiset<String> result = service.findSeveritiesByComponent(file.key(), null, session);
+ assertThat(result.count("MAJOR")).isEqualTo(2);
+ assertThat(result.count("INFO")).isEqualTo(1);
+ assertThat(result.count("UNKNOWN")).isEqualTo(0);
+ }
+
+ private IssueDto newIssue() {
+ return new IssueDto()
+ .setIssueCreationDate(DateUtils.parseDate("2014-09-04"))
+ .setIssueUpdateDate(DateUtils.parseDate("2014-12-04"))
+ .setRule(rule)
+ .setDebt(10L)
+ .setRootComponent(project)
+ .setComponent(file)
+ .setStatus(Issue.STATUS_OPEN)
+ .setResolution(null)
+ .setSeverity(Severity.MAJOR)
+ .setKee(UUID.randomUUID().toString());
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.issue;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+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 org.sonar.api.issue.action.Action;
+import org.sonar.api.issue.internal.DefaultIssue;
+import org.sonar.api.issue.internal.FieldDiffs;
+import org.sonar.api.user.User;
+import org.sonar.core.issue.DefaultActionPlan;
+import org.sonar.core.issue.DefaultIssueFilter;
+import org.sonar.core.resource.ResourceDao;
+import org.sonar.core.resource.ResourceDto;
+import org.sonar.core.resource.ResourceQuery;
+import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.exceptions.Message;
+import org.sonar.server.issue.actionplan.ActionPlanService;
+import org.sonar.server.issue.filter.IssueFilterService;
+import org.sonar.server.user.UserSession;
+
+import java.util.Collections;
+import java.util.Map;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.collect.Maps.newHashMap;
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class InternalRubyDefaultIssueServiceTest {
+
+ @Mock
+ IssueService issueService;
+
+ @Mock
+ IssueCommentService commentService;
+
+ @Mock
+ IssueChangelogService changelogService;
+
+ @Mock
+ ActionPlanService actionPlanService;
+
+ @Mock
+ ResourceDao resourceDao;
+
+ @Mock
+ IssueStatsFinder issueStatsFinder;
+
+ @Mock
+ ActionService actionService;
+
+ @Mock
+ IssueFilterService issueFilterService;
+
+ @Mock
+ IssueBulkChangeService issueBulkChangeService;
+
+ InternalRubyIssueService service;
+
+ @Before
+ public void setUp() {
+ ResourceDto project = new ResourceDto().setKey("org.sonar.Sample");
+ when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(project);
+ service = new InternalRubyIssueService(issueService, commentService, changelogService, actionPlanService, issueStatsFinder, resourceDao, actionService,
+ issueFilterService, issueBulkChangeService);
+ }
+
+ @Test
+ public void find_issue_assignees() throws Exception {
+ service.findIssueAssignees(ImmutableMap.<String, Object>of("issues", "ABCD"));
+ verify(issueStatsFinder).findIssueAssignees(any(IssueQuery.class));
+ }
+
+ @Test
+ public void list_transitions_by_issue_key() throws Exception {
+ service.listTransitions("ABCD");
+ verify(issueService).listTransitions(eq("ABCD"));
+ }
+
+ @Test
+ public void list_transitions_by_issue() throws Exception {
+ Issue issue = new DefaultIssue().setKey("ABCD");
+ service.listTransitions(issue);
+ verify(issueService).listTransitions(eq(issue));
+ }
+
+ @Test
+ public void list_status() throws Exception {
+ service.listStatus();
+ verify(issueService).listStatus();
+ }
+
+ @Test
+ public void list_resolutions() throws Exception {
+ assertThat(service.listResolutions()).isEqualTo(Issue.RESOLUTIONS);
+ }
+
+ @Test
+ public void list_plugin_actions() {
+ Action action = mock(Action.class);
+ when(action.key()).thenReturn("link-to-jira");
+
+ when(actionService.listAllActions()).thenReturn(newArrayList(action));
+
+ assertThat(service.listPluginActions()).containsOnly("link-to-jira");
+ }
+
+ @Test
+ public void do_transition() throws Exception {
+ service.doTransition("ABCD", Issue.STATUS_RESOLVED);
+ verify(issueService).doTransition(eq("ABCD"), eq(Issue.STATUS_RESOLVED));
+ }
+
+ @Test
+ public void create_action_plan() {
+ Map<String, String> parameters = newHashMap();
+ parameters.put("name", "Long term");
+ parameters.put("description", "Long term issues");
+ parameters.put("project", "org.sonar.Sample");
+ parameters.put("deadLine", "2113-05-13");
+
+ Result result = service.createActionPlan(parameters);
+ assertThat(result.ok()).isTrue();
+
+ ArgumentCaptor<ActionPlan> actionPlanCaptor = ArgumentCaptor.forClass(ActionPlan.class);
+ verify(actionPlanService).create(actionPlanCaptor.capture(), any(UserSession.class));
+ ActionPlan actionPlan = actionPlanCaptor.getValue();
+
+ assertThat(actionPlan).isNotNull();
+ assertThat(actionPlan.key()).isNotNull();
+ assertThat(actionPlan.name()).isEqualTo("Long term");
+ assertThat(actionPlan.description()).isEqualTo("Long term issues");
+ assertThat(actionPlan.deadLine()).isNotNull();
+ }
+
+ @Test
+ public void update_action_plan() {
+ when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(DefaultActionPlan.create("Long term"));
+
+ Map<String, String> parameters = newHashMap();
+ parameters.put("name", "New Long term");
+ parameters.put("description", "New Long term issues");
+ parameters.put("deadLine", "2113-05-13");
+ parameters.put("project", "org.sonar.MultiSample");
+
+ Result result = service.updateActionPlan("ABCD", parameters);
+ assertThat(result.ok()).isTrue();
+
+ ArgumentCaptor<ActionPlan> actionPlanCaptor = ArgumentCaptor.forClass(ActionPlan.class);
+ verify(actionPlanService).update(actionPlanCaptor.capture(), any(UserSession.class));
+ ActionPlan actionPlan = actionPlanCaptor.getValue();
+
+ assertThat(actionPlan).isNotNull();
+ assertThat(actionPlan.key()).isNotNull();
+ assertThat(actionPlan.name()).isEqualTo("New Long term");
+ assertThat(actionPlan.description()).isEqualTo("New Long term issues");
+ assertThat(actionPlan.deadLine()).isNotNull();
+ }
+
+ @Test
+ public void update_action_plan_with_new_project() {
+ when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(DefaultActionPlan.create("Long term").setProjectKey("org.sonar.MultiSample"));
+
+ Map<String, String> parameters = newHashMap();
+ parameters.put("name", "New Long term");
+ parameters.put("description", "New Long term issues");
+ parameters.put("deadLine", "2113-05-13");
+
+ ArgumentCaptor<ActionPlan> actionPlanCaptor = ArgumentCaptor.forClass(ActionPlan.class);
+ Result result = service.updateActionPlan("ABCD", parameters);
+ assertThat(result.ok()).isTrue();
+
+ verify(actionPlanService).update(actionPlanCaptor.capture(), any(UserSession.class));
+ ActionPlan actionPlan = actionPlanCaptor.getValue();
+
+ assertThat(actionPlan).isNotNull();
+ assertThat(actionPlan.key()).isNotNull();
+ assertThat(actionPlan.name()).isEqualTo("New Long term");
+ assertThat(actionPlan.description()).isEqualTo("New Long term issues");
+ assertThat(actionPlan.deadLine()).isNotNull();
+ assertThat(actionPlan.projectKey()).isEqualTo("org.sonar.MultiSample");
+ }
+
+ @Test
+ public void not_update_action_plan_when_action_plan_is_not_found() {
+ when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(null);
+
+ Result result = service.updateActionPlan("ABCD", null);
+ assertThat(result.ok()).isFalse();
+ assertThat(result.errors()).contains(Result.Message.ofL10n("action_plans.errors.action_plan_does_not_exist", "ABCD"));
+ }
+
+ @Test
+ public void delete_action_plan() {
+ when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(DefaultActionPlan.create("Long term"));
+
+ Result result = service.deleteActionPlan("ABCD");
+ verify(actionPlanService).delete(eq("ABCD"), any(UserSession.class));
+ assertThat(result.ok()).isTrue();
+ }
+
+ @Test
+ public void not_delete_action_plan_if_action_plan_not_found() {
+ when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(null);
+
+ Result result = service.deleteActionPlan("ABCD");
+ verify(actionPlanService, never()).delete(eq("ABCD"), any(UserSession.class));
+ assertThat(result.ok()).isFalse();
+ assertThat(result.errors()).contains(Result.Message.ofL10n("action_plans.errors.action_plan_does_not_exist", "ABCD"));
+ }
+
+ @Test
+ public void close_action_plan() {
+ when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(DefaultActionPlan.create("Long term"));
+
+ Result result = service.closeActionPlan("ABCD");
+ verify(actionPlanService).setStatus(eq("ABCD"), eq("CLOSED"), any(UserSession.class));
+ assertThat(result.ok()).isTrue();
+ }
+
+ @Test
+ public void open_action_plan() {
+ when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(DefaultActionPlan.create("Long term"));
+
+ Result result = service.openActionPlan("ABCD");
+ verify(actionPlanService).setStatus(eq("ABCD"), eq("OPEN"), any(UserSession.class));
+ assertThat(result.ok()).isTrue();
+ }
+
+ @Test
+ public void get_error_on_action_plan_result_when_no_project() {
+ Map<String, String> parameters = newHashMap();
+ parameters.put("name", "Long term");
+ parameters.put("description", "Long term issues");
+
+ Result result = service.createActionPlanResult(parameters);
+ assertThat(result.ok()).isFalse();
+ assertThat(result.errors()).contains(Result.Message.ofL10n("errors.cant_be_empty", "project"));
+ }
+
+ @Test
+ public void get_error_on_action_plan_result_when_no_name() {
+ Map<String, String> parameters = newHashMap();
+ parameters.put("name", null);
+ parameters.put("description", "Long term issues");
+ parameters.put("project", "org.sonar.Sample");
+
+ Result result = service.createActionPlanResult(parameters);
+ assertThat(result.ok()).isFalse();
+ assertThat(result.errors()).contains(Result.Message.ofL10n("errors.cant_be_empty", "name"));
+ }
+
+ @Test
+ public void get_error_on_action_plan_result_when_name_is_too_long() {
+ Map<String, String> parameters = newHashMap();
+ parameters.put("name", createLongString(201));
+ parameters.put("description", "Long term issues");
+ parameters.put("project", "org.sonar.Sample");
+
+ Result result = service.createActionPlanResult(parameters);
+ assertThat(result.ok()).isFalse();
+ assertThat(result.errors()).contains(Result.Message.ofL10n("errors.is_too_long", "name", 200));
+ }
+
+ @Test
+ public void get_error_on_action_plan_result_when_description_is_too_long() {
+ Map<String, String> parameters = newHashMap();
+ parameters.put("name", "Long term");
+ parameters.put("description", createLongString(1001));
+ parameters.put("project", "org.sonar.Sample");
+
+ Result result = service.createActionPlanResult(parameters);
+ assertThat(result.ok()).isFalse();
+ assertThat(result.errors()).contains(Result.Message.ofL10n("errors.is_too_long", "description", 1000));
+ }
+
+ @Test
+ public void get_error_on_action_plan_result_when_dead_line_use_wrong_format() {
+ Map<String, String> parameters = newHashMap();
+ parameters.put("name", "Long term");
+ parameters.put("description", "Long term issues");
+ parameters.put("project", "org.sonar.Sample");
+ parameters.put("deadLine", "18/05/2013");
+
+ Result result = service.createActionPlanResult(parameters);
+ assertThat(result.ok()).isFalse();
+ assertThat(result.errors()).contains(Result.Message.ofL10n("errors.is_not_valid", "date"));
+ }
+
+ @Test
+ public void get_error_on_action_plan_result_when_dead_line_is_in_the_past() {
+ Map<String, String> parameters = newHashMap();
+ parameters.put("name", "Long term");
+ parameters.put("description", "Long term issues");
+ parameters.put("project", "org.sonar.Sample");
+ parameters.put("deadLine", "2000-01-01");
+
+ Result result = service.createActionPlanResult(parameters);
+ assertThat(result.ok()).isFalse();
+ assertThat(result.errors()).contains(Result.Message.ofL10n("action_plans.date_cant_be_in_past"));
+ }
+
+ @Test
+ public void get_error_on_action_plan_result_when_name_is_already_used_for_project() {
+ Map<String, String> parameters = newHashMap();
+ parameters.put("name", "Long term");
+ parameters.put("description", "Long term issues");
+ parameters.put("project", "org.sonar.Sample");
+
+ when(actionPlanService.isNameAlreadyUsedForProject(anyString(), anyString())).thenReturn(true);
+
+ Result result = service.createActionPlanResult(parameters, DefaultActionPlan.create("Short term"));
+ assertThat(result.ok()).isFalse();
+ assertThat(result.errors()).contains(Result.Message.ofL10n("action_plans.same_name_in_same_project"));
+ }
+
+ @Test
+ public void get_error_on_action_plan_result_when_project_not_found() {
+ Map<String, String> parameters = newHashMap();
+ parameters.put("name", "Long term");
+ parameters.put("description", "Long term issues");
+ parameters.put("project", "org.sonar.Sample");
+
+ when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(null);
+
+ Result result = service.createActionPlanResult(parameters);
+ assertThat(result.ok()).isFalse();
+ assertThat(result.errors()).contains(Result.Message.ofL10n("action_plans.errors.project_does_not_exist", "org.sonar.Sample"));
+ }
+
+ @Test
+ public void test_changelog_from_issue_key() throws Exception {
+ IssueChangelog changelog = new IssueChangelog(Collections.<FieldDiffs>emptyList(), Collections.<User>emptyList());
+ when(changelogService.changelog(eq("ABCDE"))).thenReturn(changelog);
+
+ IssueChangelog result = service.changelog("ABCDE");
+
+ assertThat(result).isSameAs(changelog);
+ }
+
+ @Test
+ public void test_changelog_from_issue() throws Exception {
+ Issue issue = new DefaultIssue().setKey("ABCDE");
+
+ IssueChangelog changelog = new IssueChangelog(Collections.<FieldDiffs>emptyList(), Collections.<User>emptyList());
+ when(changelogService.changelog(eq(issue))).thenReturn(changelog);
+
+ IssueChangelog result = service.changelog(issue);
+
+ assertThat(result).isSameAs(changelog);
+ }
+
+ @Test
+ public void create_issue_filter() {
+ Map<String, String> parameters = newHashMap();
+ parameters.put("name", "Long term");
+ parameters.put("description", "Long term issues");
+
+ service.createIssueFilter(parameters);
+
+ ArgumentCaptor<DefaultIssueFilter> issueFilterCaptor = ArgumentCaptor.forClass(DefaultIssueFilter.class);
+ verify(issueFilterService).save(issueFilterCaptor.capture(), any(UserSession.class));
+ DefaultIssueFilter issueFilter = issueFilterCaptor.getValue();
+ assertThat(issueFilter.name()).isEqualTo("Long term");
+ assertThat(issueFilter.description()).isEqualTo("Long term issues");
+ }
+
+ @Test
+ public void update_issue_filter() {
+ Map<String, String> parameters = newHashMap();
+ parameters.put("id", "10");
+ parameters.put("name", "Long term");
+ parameters.put("description", "Long term issues");
+ parameters.put("user", "John");
+
+ service.updateIssueFilter(parameters);
+
+ ArgumentCaptor<DefaultIssueFilter> issueFilterCaptor = ArgumentCaptor.forClass(DefaultIssueFilter.class);
+ verify(issueFilterService).update(issueFilterCaptor.capture(), any(UserSession.class));
+ DefaultIssueFilter issueFilter = issueFilterCaptor.getValue();
+ assertThat(issueFilter.id()).isEqualTo(10L);
+ assertThat(issueFilter.name()).isEqualTo("Long term");
+ assertThat(issueFilter.description()).isEqualTo("Long term issues");
+ }
+
+ @Test
+ public void update_data() {
+ Map<String, Object> data = newHashMap();
+ service.updateIssueFilterQuery(10L, data);
+ verify(issueFilterService).updateFilterQuery(eq(10L), eq(data), any(UserSession.class));
+ }
+
+ @Test
+ public void delete_issue_filter() {
+ service.deleteIssueFilter(1L);
+ verify(issueFilterService).delete(eq(1L), any(UserSession.class));
+ }
+
+ @Test
+ public void copy_issue_filter() {
+ Map<String, String> parameters = newHashMap();
+ parameters.put("name", "Copy of Long term");
+ parameters.put("description", "Copy of Long term issues");
+
+ service.copyIssueFilter(1L, parameters);
+
+ ArgumentCaptor<DefaultIssueFilter> issueFilterCaptor = ArgumentCaptor.forClass(DefaultIssueFilter.class);
+ verify(issueFilterService).copy(eq(1L), issueFilterCaptor.capture(), any(UserSession.class));
+ DefaultIssueFilter issueFilter = issueFilterCaptor.getValue();
+ assertThat(issueFilter.name()).isEqualTo("Copy of Long term");
+ assertThat(issueFilter.description()).isEqualTo("Copy of Long term issues");
+ }
+
+ @Test
+ public void get_error_on_create_issue_filter_result_when_no_name() {
+ Map<String, String> parameters = newHashMap();
+ parameters.put("name", "");
+ parameters.put("description", "Long term issues");
+ parameters.put("user", "John");
+
+ try {
+ service.createIssueFilterResultForNew(parameters);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(BadRequestException.class);
+ checkBadRequestException(e, "errors.cant_be_empty", "name");
+ }
+ }
+
+ @Test
+ public void get_error_on_create_issue_filter_result_when_name_is_too_long() {
+ Map<String, String> parameters = newHashMap();
+ parameters.put("name", createLongString(101));
+ parameters.put("description", "Long term issues");
+ parameters.put("user", "John");
+
+ try {
+ service.createIssueFilterResultForNew(parameters);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(BadRequestException.class);
+ checkBadRequestException(e, "errors.is_too_long", "name", 100);
+ }
+ }
+
+ @Test
+ public void get_error_on_create_issue_filter_result_when_description_is_too_long() {
+ Map<String, String> parameters = newHashMap();
+ parameters.put("name", "Long term");
+ parameters.put("description", createLongString(4001));
+ parameters.put("user", "John");
+
+ try {
+ service.createIssueFilterResultForNew(parameters);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(BadRequestException.class);
+ checkBadRequestException(e, "errors.is_too_long", "description", 4000);
+ }
+ }
+
+ @Test
+ public void get_error_on_create_issue_filter_result_when_id_is_null_on_update() {
+ Map<String, String> parameters = newHashMap();
+ parameters.put("id", null);
+ parameters.put("name", "Long term");
+ parameters.put("description", "Long term issues");
+ parameters.put("user", "John");
+
+ try {
+ service.createIssueFilterResultForUpdate(parameters);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(BadRequestException.class);
+ checkBadRequestException(e, "errors.cant_be_empty", "id");
+ }
+ }
+
+ @Test
+ public void get_error_on_create_issue_filter_result_when_user_is_null_on_update() {
+ Map<String, String> parameters = newHashMap();
+ parameters.put("id", "10");
+ parameters.put("name", "All Open Issues");
+ parameters.put("description", "Long term issues");
+ parameters.put("user", null);
+
+ try {
+ service.createIssueFilterResultForUpdate(parameters);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(BadRequestException.class);
+ checkBadRequestException(e, "errors.cant_be_empty", "user");
+ }
+ }
+
+ @Test
+ public void get_no_error_on_issue_filter_result_when_id_and_user_are_null_on_copy() {
+ Map<String, String> parameters = newHashMap();
+ parameters.put("id", null);
+ parameters.put("name", "Long term");
+ parameters.put("description", "Long term issues");
+ parameters.put("user", null);
+
+ DefaultIssueFilter result = service.createIssueFilterResultForCopy(parameters);
+ assertThat(result).isNotNull();
+ }
+
+ @Test
+ public void execute_issue_filter_from_issue_query() {
+ service.execute(Maps.<String, Object>newHashMap());
+ verify(issueFilterService).execute(any(IssueQuery.class));
+ }
+
+ @Test
+ public void execute_issue_filter_from_existing_filter() {
+ Map<String, Object> props = newHashMap();
+ props.put("componentRoots", "struts");
+ props.put("statuses", "OPEN");
+ when(issueFilterService.deserializeIssueFilterQuery(any(DefaultIssueFilter.class))).thenReturn(props);
+
+ Map<String, Object> overrideProps = newHashMap();
+ overrideProps.put("statuses", "CLOSED");
+ overrideProps.put("resolved", true);
+ overrideProps.put("pageSize", 20);
+ overrideProps.put("pageIndex", 2);
+ service.execute(10L, overrideProps);
+ ArgumentCaptor<IssueQuery> captor = ArgumentCaptor.forClass(IssueQuery.class);
+ verify(issueFilterService).execute(captor.capture());
+ verify(issueFilterService).find(eq(10L), any(UserSession.class));
+
+ IssueQuery issueQuery = captor.getValue();
+ assertThat(issueQuery.componentRoots()).contains("struts");
+ assertThat(issueQuery.statuses()).contains("CLOSED");
+ assertThat(issueQuery.resolved()).isTrue();
+ assertThat(issueQuery.pageSize()).isEqualTo(20);
+ assertThat(issueQuery.pageIndex()).isEqualTo(2);
+ }
+
+ @Test
+ public void serialize_filter_query() {
+ Map<String, Object> props = newHashMap();
+ props.put("componentRoots", "struts");
+ service.serializeFilterQuery(props);
+ verify(issueFilterService).serializeFilterQuery(props);
+ }
+
+ @Test
+ public void deserialize_filter_query() {
+ DefaultIssueFilter issueFilter = new DefaultIssueFilter();
+ service.deserializeFilterQuery(issueFilter);
+ verify(issueFilterService).deserializeIssueFilterQuery(issueFilter);
+ }
+
+ @Test
+ public void sanitize_filter_query() {
+ Map<String, Object> query = newHashMap();
+ query.put("statuses", "CLOSED");
+ query.put("resolved", true);
+ query.put("unknown", "john");
+ Map<String, Object> result = service.sanitizeFilterQuery(query);
+ assertThat(result.keySet()).containsOnly("statuses", "resolved");
+ }
+
+ @Test
+ public void find_user_issue_filters() {
+ service.findIssueFiltersForCurrentUser();
+ verify(issueFilterService).findByUser(any(UserSession.class));
+ }
+
+ @Test
+ public void find_shared_issue_filters() {
+ service.findSharedFiltersForCurrentUser();
+ verify(issueFilterService).findSharedFiltersWithoutUserFilters(any(UserSession.class));
+ }
+
+ @Test
+ public void find_favourite_issue_filters() {
+ service.findFavouriteIssueFiltersForCurrentUser();
+ verify(issueFilterService).findFavoriteFilters(any(UserSession.class));
+ }
+
+ @Test
+ public void toggle_favourite_issue_filter() {
+ service.toggleFavouriteIssueFilter(10L);
+ verify(issueFilterService).toggleFavouriteIssueFilter(eq(10L), any(UserSession.class));
+ }
+
+ @Test
+ public void check_if_user_is_authorized_to_see_issue_filter() {
+ DefaultIssueFilter issueFilter = new DefaultIssueFilter();
+ service.isUserAuthorized(issueFilter);
+ verify(issueFilterService).getLoggedLogin(any(UserSession.class));
+ verify(issueFilterService).verifyCurrentUserCanReadFilter(eq(issueFilter), anyString());
+ }
+
+ @Test
+ public void check_if_user_can_share_issue_filter() {
+ service.canUserShareIssueFilter();
+ verify(issueFilterService).canShareFilter(any(UserSession.class));
+ }
+
+ @Test
+ public void execute_bulk_change() {
+ Map<String, Object> params = newHashMap();
+ params.put("issues", newArrayList("ABCD", "EFGH"));
+ params.put("actions", newArrayList("do_transition", "assign", "set_severity", "plan"));
+ params.put("do_transition.transition", "confirm");
+ params.put("assign.assignee", "arthur");
+ params.put("set_severity.severity", "MINOR");
+ params.put("plan.plan", "3.7");
+ service.bulkChange(params, "My comment", true);
+ verify(issueBulkChangeService).execute(any(IssueBulkChangeQuery.class), any(UserSession.class));
+ }
+
+ @Test
+ public void format_changelog() {
+ FieldDiffs fieldDiffs = new FieldDiffs();
+ service.formatChangelog(fieldDiffs);
+ verify(changelogService).formatDiffs(eq(fieldDiffs));
+ }
+
+ private void checkBadRequestException(Exception e, String key, Object... params) {
+ BadRequestException exception = (BadRequestException) e;
+ Message msg = exception.errors().messages().get(0);
+ assertThat(msg.getKey()).isEqualTo(key);
+ assertThat(msg.getParams()).containsOnly(params);
+ }
+
+ private String createLongString(int size) {
+ String result = "";
+ for (int i = 0; i < size; i++) {
+ result += "c";
+ }
+ return result;
+ }
+
+}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.issue;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-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 org.sonar.api.issue.action.Action;
-import org.sonar.api.issue.internal.DefaultIssue;
-import org.sonar.api.issue.internal.FieldDiffs;
-import org.sonar.api.user.User;
-import org.sonar.core.issue.DefaultActionPlan;
-import org.sonar.core.issue.DefaultIssueFilter;
-import org.sonar.core.resource.ResourceDao;
-import org.sonar.core.resource.ResourceDto;
-import org.sonar.core.resource.ResourceQuery;
-import org.sonar.server.exceptions.BadRequestException;
-import org.sonar.server.exceptions.Message;
-import org.sonar.server.issue.actionplan.ActionPlanService;
-import org.sonar.server.issue.filter.IssueFilterService;
-import org.sonar.server.user.UserSession;
-
-import java.util.Collections;
-import java.util.Map;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static com.google.common.collect.Maps.newHashMap;
-import static org.fest.assertions.Assertions.assertThat;
-import static org.fest.assertions.Fail.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.*;
-
-@RunWith(MockitoJUnitRunner.class)
-public class InternalRubyIssueServiceTest {
-
- @Mock
- IssueService issueService;
-
- @Mock
- IssueCommentService commentService = mock(IssueCommentService.class);
-
- @Mock
- IssueChangelogService changelogService = mock(IssueChangelogService.class);
-
- @Mock
- ActionPlanService actionPlanService = mock(ActionPlanService.class);
-
- @Mock
- ResourceDao resourceDao = mock(ResourceDao.class);
-
- @Mock
- IssueStatsFinder issueStatsFinder = mock(IssueStatsFinder.class);
-
- @Mock
- ActionService actionService = mock(ActionService.class);
-
- @Mock
- IssueFilterService issueFilterService = mock(IssueFilterService.class);
-
- @Mock
- IssueBulkChangeService issueBulkChangeService = mock(IssueBulkChangeService.class);
-
- InternalRubyIssueService service;
-
- @Before
- public void setUp() {
- ResourceDto project = new ResourceDto().setKey("org.sonar.Sample");
- when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(project);
- service = new InternalRubyIssueService(issueService, commentService, changelogService, actionPlanService, issueStatsFinder, resourceDao, actionService,
- issueFilterService, issueBulkChangeService);
- }
-
- @Test
- public void find_issue_assignees() throws Exception {
- service.findIssueAssignees(ImmutableMap.<String, Object>of("issues", "ABCD"));
- verify(issueStatsFinder).findIssueAssignees(any(IssueQuery.class));
- }
-
- @Test
- public void list_transitions_by_issue_key() throws Exception {
- service.listTransitions("ABCD");
- verify(issueService).listTransitions(eq("ABCD"), any(UserSession.class));
- }
-
- @Test
- public void list_transitions_by_issue() throws Exception {
- Issue issue = new DefaultIssue().setKey("ABCD");
- service.listTransitions(issue);
- verify(issueService).listTransitions(eq(issue), any(UserSession.class));
- }
-
- @Test
- public void list_status() throws Exception {
- service.listStatus();
- verify(issueService).listStatus();
- }
-
- @Test
- public void list_resolutions() throws Exception {
- assertThat(service.listResolutions()).isEqualTo(Issue.RESOLUTIONS);
- }
-
- @Test
- public void list_plugin_actions() {
- Action action = mock(Action.class);
- when(action.key()).thenReturn("link-to-jira");
-
- when(actionService.listAllActions()).thenReturn(newArrayList(action));
-
- assertThat(service.listPluginActions()).containsOnly("link-to-jira");
- }
-
- @Test
- public void do_transition() throws Exception {
- service.doTransition("ABCD", Issue.STATUS_RESOLVED);
- verify(issueService).doTransition(eq("ABCD"), eq(Issue.STATUS_RESOLVED), any(UserSession.class));
- }
-
- @Test
- public void create_action_plan() {
- Map<String, String> parameters = newHashMap();
- parameters.put("name", "Long term");
- parameters.put("description", "Long term issues");
- parameters.put("project", "org.sonar.Sample");
- parameters.put("deadLine", "2113-05-13");
-
- Result result = service.createActionPlan(parameters);
- assertThat(result.ok()).isTrue();
-
- ArgumentCaptor<ActionPlan> actionPlanCaptor = ArgumentCaptor.forClass(ActionPlan.class);
- verify(actionPlanService).create(actionPlanCaptor.capture(), any(UserSession.class));
- ActionPlan actionPlan = actionPlanCaptor.getValue();
-
- assertThat(actionPlan).isNotNull();
- assertThat(actionPlan.key()).isNotNull();
- assertThat(actionPlan.name()).isEqualTo("Long term");
- assertThat(actionPlan.description()).isEqualTo("Long term issues");
- assertThat(actionPlan.deadLine()).isNotNull();
- }
-
- @Test
- public void update_action_plan() {
- when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(DefaultActionPlan.create("Long term"));
-
- Map<String, String> parameters = newHashMap();
- parameters.put("name", "New Long term");
- parameters.put("description", "New Long term issues");
- parameters.put("deadLine", "2113-05-13");
- parameters.put("project", "org.sonar.MultiSample");
-
- Result result = service.updateActionPlan("ABCD", parameters);
- assertThat(result.ok()).isTrue();
-
- ArgumentCaptor<ActionPlan> actionPlanCaptor = ArgumentCaptor.forClass(ActionPlan.class);
- verify(actionPlanService).update(actionPlanCaptor.capture(), any(UserSession.class));
- ActionPlan actionPlan = actionPlanCaptor.getValue();
-
- assertThat(actionPlan).isNotNull();
- assertThat(actionPlan.key()).isNotNull();
- assertThat(actionPlan.name()).isEqualTo("New Long term");
- assertThat(actionPlan.description()).isEqualTo("New Long term issues");
- assertThat(actionPlan.deadLine()).isNotNull();
- }
-
- @Test
- public void update_action_plan_with_new_project() {
- when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(DefaultActionPlan.create("Long term").setProjectKey("org.sonar.MultiSample"));
-
- Map<String, String> parameters = newHashMap();
- parameters.put("name", "New Long term");
- parameters.put("description", "New Long term issues");
- parameters.put("deadLine", "2113-05-13");
-
- ArgumentCaptor<ActionPlan> actionPlanCaptor = ArgumentCaptor.forClass(ActionPlan.class);
- Result result = service.updateActionPlan("ABCD", parameters);
- assertThat(result.ok()).isTrue();
-
- verify(actionPlanService).update(actionPlanCaptor.capture(), any(UserSession.class));
- ActionPlan actionPlan = actionPlanCaptor.getValue();
-
- assertThat(actionPlan).isNotNull();
- assertThat(actionPlan.key()).isNotNull();
- assertThat(actionPlan.name()).isEqualTo("New Long term");
- assertThat(actionPlan.description()).isEqualTo("New Long term issues");
- assertThat(actionPlan.deadLine()).isNotNull();
- assertThat(actionPlan.projectKey()).isEqualTo("org.sonar.MultiSample");
- }
-
- @Test
- public void not_update_action_plan_when_action_plan_is_not_found() {
- when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(null);
-
- Result result = service.updateActionPlan("ABCD", null);
- assertThat(result.ok()).isFalse();
- assertThat(result.errors()).contains(Result.Message.ofL10n("action_plans.errors.action_plan_does_not_exist", "ABCD"));
- }
-
- @Test
- public void delete_action_plan() {
- when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(DefaultActionPlan.create("Long term"));
-
- Result result = service.deleteActionPlan("ABCD");
- verify(actionPlanService).delete(eq("ABCD"), any(UserSession.class));
- assertThat(result.ok()).isTrue();
- }
-
- @Test
- public void not_delete_action_plan_if_action_plan_not_found() {
- when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(null);
-
- Result result = service.deleteActionPlan("ABCD");
- verify(actionPlanService, never()).delete(eq("ABCD"), any(UserSession.class));
- assertThat(result.ok()).isFalse();
- assertThat(result.errors()).contains(Result.Message.ofL10n("action_plans.errors.action_plan_does_not_exist", "ABCD"));
- }
-
- @Test
- public void close_action_plan() {
- when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(DefaultActionPlan.create("Long term"));
-
- Result result = service.closeActionPlan("ABCD");
- verify(actionPlanService).setStatus(eq("ABCD"), eq("CLOSED"), any(UserSession.class));
- assertThat(result.ok()).isTrue();
- }
-
- @Test
- public void open_action_plan() {
- when(actionPlanService.findByKey(eq("ABCD"), any(UserSession.class))).thenReturn(DefaultActionPlan.create("Long term"));
-
- Result result = service.openActionPlan("ABCD");
- verify(actionPlanService).setStatus(eq("ABCD"), eq("OPEN"), any(UserSession.class));
- assertThat(result.ok()).isTrue();
- }
-
- @Test
- public void get_error_on_action_plan_result_when_no_project() {
- Map<String, String> parameters = newHashMap();
- parameters.put("name", "Long term");
- parameters.put("description", "Long term issues");
-
- Result result = service.createActionPlanResult(parameters);
- assertThat(result.ok()).isFalse();
- assertThat(result.errors()).contains(Result.Message.ofL10n("errors.cant_be_empty", "project"));
- }
-
- @Test
- public void get_error_on_action_plan_result_when_no_name() {
- Map<String, String> parameters = newHashMap();
- parameters.put("name", null);
- parameters.put("description", "Long term issues");
- parameters.put("project", "org.sonar.Sample");
-
- Result result = service.createActionPlanResult(parameters);
- assertThat(result.ok()).isFalse();
- assertThat(result.errors()).contains(Result.Message.ofL10n("errors.cant_be_empty", "name"));
- }
-
- @Test
- public void get_error_on_action_plan_result_when_name_is_too_long() {
- Map<String, String> parameters = newHashMap();
- parameters.put("name", createLongString(201));
- parameters.put("description", "Long term issues");
- parameters.put("project", "org.sonar.Sample");
-
- Result result = service.createActionPlanResult(parameters);
- assertThat(result.ok()).isFalse();
- assertThat(result.errors()).contains(Result.Message.ofL10n("errors.is_too_long", "name", 200));
- }
-
- @Test
- public void get_error_on_action_plan_result_when_description_is_too_long() {
- Map<String, String> parameters = newHashMap();
- parameters.put("name", "Long term");
- parameters.put("description", createLongString(1001));
- parameters.put("project", "org.sonar.Sample");
-
- Result result = service.createActionPlanResult(parameters);
- assertThat(result.ok()).isFalse();
- assertThat(result.errors()).contains(Result.Message.ofL10n("errors.is_too_long", "description", 1000));
- }
-
- @Test
- public void get_error_on_action_plan_result_when_dead_line_use_wrong_format() {
- Map<String, String> parameters = newHashMap();
- parameters.put("name", "Long term");
- parameters.put("description", "Long term issues");
- parameters.put("project", "org.sonar.Sample");
- parameters.put("deadLine", "18/05/2013");
-
- Result result = service.createActionPlanResult(parameters);
- assertThat(result.ok()).isFalse();
- assertThat(result.errors()).contains(Result.Message.ofL10n("errors.is_not_valid", "date"));
- }
-
- @Test
- public void get_error_on_action_plan_result_when_dead_line_is_in_the_past() {
- Map<String, String> parameters = newHashMap();
- parameters.put("name", "Long term");
- parameters.put("description", "Long term issues");
- parameters.put("project", "org.sonar.Sample");
- parameters.put("deadLine", "2000-01-01");
-
- Result result = service.createActionPlanResult(parameters);
- assertThat(result.ok()).isFalse();
- assertThat(result.errors()).contains(Result.Message.ofL10n("action_plans.date_cant_be_in_past"));
- }
-
- @Test
- public void get_error_on_action_plan_result_when_name_is_already_used_for_project() {
- Map<String, String> parameters = newHashMap();
- parameters.put("name", "Long term");
- parameters.put("description", "Long term issues");
- parameters.put("project", "org.sonar.Sample");
-
- when(actionPlanService.isNameAlreadyUsedForProject(anyString(), anyString())).thenReturn(true);
-
- Result result = service.createActionPlanResult(parameters, DefaultActionPlan.create("Short term"));
- assertThat(result.ok()).isFalse();
- assertThat(result.errors()).contains(Result.Message.ofL10n("action_plans.same_name_in_same_project"));
- }
-
- @Test
- public void get_error_on_action_plan_result_when_project_not_found() {
- Map<String, String> parameters = newHashMap();
- parameters.put("name", "Long term");
- parameters.put("description", "Long term issues");
- parameters.put("project", "org.sonar.Sample");
-
- when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(null);
-
- Result result = service.createActionPlanResult(parameters);
- assertThat(result.ok()).isFalse();
- assertThat(result.errors()).contains(Result.Message.ofL10n("action_plans.errors.project_does_not_exist", "org.sonar.Sample"));
- }
-
- @Test
- public void test_changelog_from_issue_key() throws Exception {
- IssueChangelog changelog = new IssueChangelog(Collections.<FieldDiffs>emptyList(), Collections.<User>emptyList());
- when(changelogService.changelog(eq("ABCDE"))).thenReturn(changelog);
-
- IssueChangelog result = service.changelog("ABCDE");
-
- assertThat(result).isSameAs(changelog);
- }
-
- @Test
- public void test_changelog_from_issue() throws Exception {
- Issue issue = new DefaultIssue().setKey("ABCDE");
-
- IssueChangelog changelog = new IssueChangelog(Collections.<FieldDiffs>emptyList(), Collections.<User>emptyList());
- when(changelogService.changelog(eq(issue))).thenReturn(changelog);
-
- IssueChangelog result = service.changelog(issue);
-
- assertThat(result).isSameAs(changelog);
- }
-
- @Test
- public void create_issue_filter() {
- Map<String, String> parameters = newHashMap();
- parameters.put("name", "Long term");
- parameters.put("description", "Long term issues");
-
- service.createIssueFilter(parameters);
-
- ArgumentCaptor<DefaultIssueFilter> issueFilterCaptor = ArgumentCaptor.forClass(DefaultIssueFilter.class);
- verify(issueFilterService).save(issueFilterCaptor.capture(), any(UserSession.class));
- DefaultIssueFilter issueFilter = issueFilterCaptor.getValue();
- assertThat(issueFilter.name()).isEqualTo("Long term");
- assertThat(issueFilter.description()).isEqualTo("Long term issues");
- }
-
- @Test
- public void update_issue_filter() {
- Map<String, String> parameters = newHashMap();
- parameters.put("id", "10");
- parameters.put("name", "Long term");
- parameters.put("description", "Long term issues");
- parameters.put("user", "John");
-
- service.updateIssueFilter(parameters);
-
- ArgumentCaptor<DefaultIssueFilter> issueFilterCaptor = ArgumentCaptor.forClass(DefaultIssueFilter.class);
- verify(issueFilterService).update(issueFilterCaptor.capture(), any(UserSession.class));
- DefaultIssueFilter issueFilter = issueFilterCaptor.getValue();
- assertThat(issueFilter.id()).isEqualTo(10L);
- assertThat(issueFilter.name()).isEqualTo("Long term");
- assertThat(issueFilter.description()).isEqualTo("Long term issues");
- }
-
- @Test
- public void update_data() {
- Map<String, Object> data = newHashMap();
- service.updateIssueFilterQuery(10L, data);
- verify(issueFilterService).updateFilterQuery(eq(10L), eq(data), any(UserSession.class));
- }
-
- @Test
- public void delete_issue_filter() {
- service.deleteIssueFilter(1L);
- verify(issueFilterService).delete(eq(1L), any(UserSession.class));
- }
-
- @Test
- public void copy_issue_filter() {
- Map<String, String> parameters = newHashMap();
- parameters.put("name", "Copy of Long term");
- parameters.put("description", "Copy of Long term issues");
-
- service.copyIssueFilter(1L, parameters);
-
- ArgumentCaptor<DefaultIssueFilter> issueFilterCaptor = ArgumentCaptor.forClass(DefaultIssueFilter.class);
- verify(issueFilterService).copy(eq(1L), issueFilterCaptor.capture(), any(UserSession.class));
- DefaultIssueFilter issueFilter = issueFilterCaptor.getValue();
- assertThat(issueFilter.name()).isEqualTo("Copy of Long term");
- assertThat(issueFilter.description()).isEqualTo("Copy of Long term issues");
- }
-
- @Test
- public void get_error_on_create_issue_filter_result_when_no_name() {
- Map<String, String> parameters = newHashMap();
- parameters.put("name", "");
- parameters.put("description", "Long term issues");
- parameters.put("user", "John");
-
- try {
- service.createIssueFilterResultForNew(parameters);
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(BadRequestException.class);
- checkBadRequestException(e, "errors.cant_be_empty", "name");
- }
- }
-
- @Test
- public void get_error_on_create_issue_filter_result_when_name_is_too_long() {
- Map<String, String> parameters = newHashMap();
- parameters.put("name", createLongString(101));
- parameters.put("description", "Long term issues");
- parameters.put("user", "John");
-
- try {
- service.createIssueFilterResultForNew(parameters);
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(BadRequestException.class);
- checkBadRequestException(e, "errors.is_too_long", "name", 100);
- }
- }
-
- @Test
- public void get_error_on_create_issue_filter_result_when_description_is_too_long() {
- Map<String, String> parameters = newHashMap();
- parameters.put("name", "Long term");
- parameters.put("description", createLongString(4001));
- parameters.put("user", "John");
-
- try {
- service.createIssueFilterResultForNew(parameters);
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(BadRequestException.class);
- checkBadRequestException(e, "errors.is_too_long", "description", 4000);
- }
- }
-
- @Test
- public void get_error_on_create_issue_filter_result_when_id_is_null_on_update() {
- Map<String, String> parameters = newHashMap();
- parameters.put("id", null);
- parameters.put("name", "Long term");
- parameters.put("description", "Long term issues");
- parameters.put("user", "John");
-
- try {
- service.createIssueFilterResultForUpdate(parameters);
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(BadRequestException.class);
- checkBadRequestException(e, "errors.cant_be_empty", "id");
- }
- }
-
- @Test
- public void get_error_on_create_issue_filter_result_when_user_is_null_on_update() {
- Map<String, String> parameters = newHashMap();
- parameters.put("id", "10");
- parameters.put("name", "All Open Issues");
- parameters.put("description", "Long term issues");
- parameters.put("user", null);
-
- try {
- service.createIssueFilterResultForUpdate(parameters);
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(BadRequestException.class);
- checkBadRequestException(e, "errors.cant_be_empty", "user");
- }
- }
-
- @Test
- public void get_no_error_on_issue_filter_result_when_id_and_user_are_null_on_copy() {
- Map<String, String> parameters = newHashMap();
- parameters.put("id", null);
- parameters.put("name", "Long term");
- parameters.put("description", "Long term issues");
- parameters.put("user", null);
-
- DefaultIssueFilter result = service.createIssueFilterResultForCopy(parameters);
- assertThat(result).isNotNull();
- }
-
- @Test
- public void execute_issue_filter_from_issue_query() {
- service.execute(Maps.<String, Object>newHashMap());
- verify(issueFilterService).execute(any(IssueQuery.class));
- }
-
- @Test
- public void execute_issue_filter_from_existing_filter() {
- Map<String, Object> props = newHashMap();
- props.put("componentRoots", "struts");
- props.put("statuses", "OPEN");
- when(issueFilterService.deserializeIssueFilterQuery(any(DefaultIssueFilter.class))).thenReturn(props);
-
- Map<String, Object> overrideProps = newHashMap();
- overrideProps.put("statuses", "CLOSED");
- overrideProps.put("resolved", true);
- overrideProps.put("pageSize", 20);
- overrideProps.put("pageIndex", 2);
- service.execute(10L, overrideProps);
- ArgumentCaptor<IssueQuery> captor = ArgumentCaptor.forClass(IssueQuery.class);
- verify(issueFilterService).execute(captor.capture());
- verify(issueFilterService).find(eq(10L), any(UserSession.class));
-
- IssueQuery issueQuery = captor.getValue();
- assertThat(issueQuery.componentRoots()).contains("struts");
- assertThat(issueQuery.statuses()).contains("CLOSED");
- assertThat(issueQuery.resolved()).isTrue();
- assertThat(issueQuery.pageSize()).isEqualTo(20);
- assertThat(issueQuery.pageIndex()).isEqualTo(2);
- }
-
- @Test
- public void serialize_filter_query() {
- Map<String, Object> props = newHashMap();
- props.put("componentRoots", "struts");
- service.serializeFilterQuery(props);
- verify(issueFilterService).serializeFilterQuery(props);
- }
-
- @Test
- public void deserialize_filter_query() {
- DefaultIssueFilter issueFilter = new DefaultIssueFilter();
- service.deserializeFilterQuery(issueFilter);
- verify(issueFilterService).deserializeIssueFilterQuery(issueFilter);
- }
-
- @Test
- public void sanitize_filter_query() {
- Map<String, Object> query = newHashMap();
- query.put("statuses", "CLOSED");
- query.put("resolved", true);
- query.put("unknown", "john");
- Map<String, Object> result = service.sanitizeFilterQuery(query);
- assertThat(result.keySet()).containsOnly("statuses", "resolved");
- }
-
- @Test
- public void find_user_issue_filters() {
- service.findIssueFiltersForCurrentUser();
- verify(issueFilterService).findByUser(any(UserSession.class));
- }
-
- @Test
- public void find_shared_issue_filters() {
- service.findSharedFiltersForCurrentUser();
- verify(issueFilterService).findSharedFiltersWithoutUserFilters(any(UserSession.class));
- }
-
- @Test
- public void find_favourite_issue_filters() {
- service.findFavouriteIssueFiltersForCurrentUser();
- verify(issueFilterService).findFavoriteFilters(any(UserSession.class));
- }
-
- @Test
- public void toggle_favourite_issue_filter() {
- service.toggleFavouriteIssueFilter(10L);
- verify(issueFilterService).toggleFavouriteIssueFilter(eq(10L), any(UserSession.class));
- }
-
- @Test
- public void check_if_user_is_authorized_to_see_issue_filter() {
- DefaultIssueFilter issueFilter = new DefaultIssueFilter();
- service.isUserAuthorized(issueFilter);
- verify(issueFilterService).getLoggedLogin(any(UserSession.class));
- verify(issueFilterService).verifyCurrentUserCanReadFilter(eq(issueFilter), anyString());
- }
-
- @Test
- public void check_if_user_can_share_issue_filter() {
- service.canUserShareIssueFilter();
- verify(issueFilterService).canShareFilter(any(UserSession.class));
- }
-
- @Test
- public void execute_bulk_change() {
- Map<String, Object> params = newHashMap();
- params.put("issues", newArrayList("ABCD", "EFGH"));
- params.put("actions", newArrayList("do_transition", "assign", "set_severity", "plan"));
- params.put("do_transition.transition", "confirm");
- params.put("assign.assignee", "arthur");
- params.put("set_severity.severity", "MINOR");
- params.put("plan.plan", "3.7");
- service.bulkChange(params, "My comment", true);
- verify(issueBulkChangeService).execute(any(IssueBulkChangeQuery.class), any(UserSession.class));
- }
-
- @Test
- public void format_changelog() {
- FieldDiffs fieldDiffs = new FieldDiffs();
- service.formatChangelog(fieldDiffs);
- verify(changelogService).formatDiffs(eq(fieldDiffs));
- }
-
- private void checkBadRequestException(Exception e, String key, Object... params) {
- BadRequestException exception = (BadRequestException) e;
- Message msg = exception.errors().messages().get(0);
- assertThat(msg.getKey()).isEqualTo(key);
- assertThat(msg.getParams()).containsOnly(params);
- }
-
- private String createLongString(int size) {
- String result = "";
- for (int i = 0; i < size; i++) {
- result += "c";
- }
- return result;
- }
-
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.issue;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.sonar.api.issue.DefaultTransitions;
-import org.sonar.api.issue.Issue;
-import org.sonar.api.issue.IssueQuery;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.Scopes;
-import org.sonar.api.rule.Severity;
-import org.sonar.api.security.DefaultGroups;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.issue.db.IssueDto;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.permission.PermissionFacade;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.rule.RuleDto;
-import org.sonar.core.user.UserDto;
-import org.sonar.server.component.SnapshotTesting;
-import org.sonar.server.component.db.ComponentDao;
-import org.sonar.server.component.db.SnapshotDao;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.issue.db.IssueDao;
-import org.sonar.server.issue.index.IssueIndex;
-import org.sonar.server.rule.RuleTesting;
-import org.sonar.server.rule.db.RuleDao;
-import org.sonar.server.search.IndexClient;
-import org.sonar.server.search.QueryContext;
-import org.sonar.server.tester.ServerTester;
-import org.sonar.server.user.MockUserSession;
-import org.sonar.server.user.UserSession;
-
-import java.util.Date;
-import java.util.UUID;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class IssueServiceMediumTest {
-
- @ClassRule
- public static ServerTester tester = new ServerTester();
-
- DbClient db;
- IndexClient indexClient;
- DbSession session;
- IssueService service;
- UserSession userSession;
-
- RuleDto rule;
- ComponentDto project;
- ComponentDto resource;
-
- @Before
- public void setUp() throws Exception {
- tester.clearDbAndIndexes();
- db = tester.get(DbClient.class);
- indexClient = tester.get(IndexClient.class);
- session = db.openSession(false);
- service = tester.get(IssueService.class);
-
- rule = RuleTesting.newXooX1();
- tester.get(RuleDao.class).insert(session, rule);
-
- project = new ComponentDto()
- .setKey("MyProject")
- .setLongName("My Project")
- .setQualifier(Qualifiers.PROJECT)
- .setScope(Scopes.PROJECT);
- tester.get(ComponentDao.class).insert(session, project);
- tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForComponent(project));
-
- resource = new ComponentDto()
- .setProjectId(project.getId())
- .setKey("MyComponent")
- .setLongName("My Component");
- tester.get(ComponentDao.class).insert(session, resource);
- tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForComponent(resource));
-
- // project can be seen by anyone
- tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session);
- db.issueAuthorizationDao().synchronizeAfter(session, new Date(0));
-
- UserDto user = new UserDto().setLogin("gandalf").setName("Gandalf");
- db.userDao().insert(session, user);
- tester.get(PermissionFacade.class).insertUserPermission(project.getId(), user.getId(), UserRole.USER, session);
-
- userSession = MockUserSession.create().setLogin(user.getLogin()).setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN)
- .addProjectPermissions(UserRole.USER, project.key());
-
- session.commit();
- }
-
- @After
- public void after() {
- session.close();
- }
-
- @Test
- public void can_facet() throws Exception {
- IssueDto issue1 = getIssue().setActionPlanKey("P1");
- IssueDto issue2 = getIssue().setActionPlanKey("P2").setResolution("NONE");
- tester.get(IssueDao.class).insert(session, issue1, issue2);
- session.commit();
-
- org.sonar.server.search.Result<Issue> result = service.search(IssueQuery.builder().build(), new QueryContext());
- assertThat(result.getHits()).hasSize(2);
- assertThat(result.getFacets()).isEmpty();
-
- result = service.search(IssueQuery.builder().build(), new QueryContext().setFacet(true));
- assertThat(result.getFacets().keySet()).hasSize(4);
- assertThat(result.getFacetKeys("actionPlan")).hasSize(2);
- }
-
- @Test
- public void do_transition() {
- IssueDto issue = getIssue();
- tester.get(IssueDao.class).insert(session, issue);
- session.commit();
-
- assertThat(db.issueDao().getByKey(session, issue.getKey())).isNotNull();
-
- IssueTesting.assertIsEquivalent(issue, indexClient.get(IssueIndex.class).getByKey(issue.getKey()));
-
- service.doTransition(issue.getKey(), DefaultTransitions.CONFIRM, userSession);
- Issue issueDoc = indexClient.get(IssueIndex.class).getByKey(issue.getKey());
- assertThat(issueDoc.status()).isEqualTo(Issue.STATUS_CONFIRMED);
- }
-
- private IssueDto getIssue() {
- return new IssueDto()
- .setIssueCreationDate(DateUtils.parseDate("2014-09-04"))
- .setIssueUpdateDate(DateUtils.parseDate("2014-12-04"))
- .setRule(rule)
- .setDebt(10L)
- .setRootComponent(project)
- .setComponent(resource)
- .setStatus(Issue.STATUS_OPEN)
- .setResolution(null)
- .setSeverity(Severity.MAJOR)
- .setKee(UUID.randomUUID().toString());
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.issue;
-
-import com.google.common.collect.Multiset;
-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 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.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.DefaultActionPlan;
-import org.sonar.core.issue.IssueNotifications;
-import org.sonar.core.issue.IssueUpdater;
-import org.sonar.core.issue.db.IssueDao;
-import org.sonar.core.issue.db.IssueStorage;
-import org.sonar.core.issue.workflow.IssueWorkflow;
-import org.sonar.core.issue.workflow.Transition;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.preview.PreviewCache;
-import org.sonar.core.resource.ResourceDao;
-import org.sonar.core.resource.ResourceDto;
-import org.sonar.core.resource.ResourceQuery;
-import org.sonar.core.rule.RuleDto;
-import org.sonar.core.user.AuthorizationDao;
-import org.sonar.core.user.DefaultUser;
-import org.sonar.server.issue.actionplan.ActionPlanService;
-import org.sonar.server.user.UserSession;
-
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static org.fest.assertions.Assertions.assertThat;
-import static org.fest.assertions.Fail.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-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
- IssueDao issueDao;
-
- @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;
-
- @Before
- public void before() {
- when(userSession.isLoggedIn()).thenReturn(true);
- when(userSession.userId()).thenReturn(10);
- when(userSession.login()).thenReturn("arthur");
-
- when(authorizationDao.isAuthorizedComponentKey(anyString(), eq(10), anyString())).thenReturn(true);
- when(finder.find(any(IssueQuery.class))).thenReturn(issueQueryResult);
- 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, issueDao,
- authorizationDao, userFinder, mock(PreviewCache.class));
- }
-
- @Test
- public void load_issue() {
- IssueQueryResult result = issueService.loadIssue("ABCD");
- assertThat(result).isEqualTo(issueQueryResult);
- }
-
- @Test
- public void fail_to_load_issue() {
- when(issueQueryResult.issues()).thenReturn(Collections.<Issue>emptyList());
- when(finder.find(any(IssueQuery.class))).thenReturn(issueQueryResult);
-
- try {
- issueService.loadIssue("ABCD");
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Issue not found: ABCD");
- }
- }
-
- @Test
- public void list_status() {
- issueService.listStatus();
- verify(workflow).statusKeys();
- }
-
- @Test
- public void list_transitions() {
- List<Transition> transitions = newArrayList(transition);
- when(workflow.outTransitions(issue)).thenReturn(transitions);
-
- List<Transition> result = issueService.listTransitions("ABCD", userSession);
- assertThat(result).hasSize(1);
- assertThat(result.get(0)).isEqualTo(transition);
- }
-
- @Test
- public void return_no_transition() {
- when(issueQueryResult.first()).thenReturn(null);
- when(issueQueryResult.issues()).thenReturn(newArrayList((Issue) new DefaultIssue()));
-
- assertThat(issueService.listTransitions("ABCD", userSession)).isEmpty();
- verifyZeroInteractions(workflow);
- }
-
- @Test
- public void do_transition() {
- when(workflow.doTransition(eq(issue), eq(transition.key()), any(IssueChangeContext.class))).thenReturn(true);
-
- Issue result = issueService.doTransition("ABCD", transition.key(), userSession);
- assertThat(result).isNotNull();
-
- ArgumentCaptor<IssueChangeContext> measureCaptor = ArgumentCaptor.forClass(IssueChangeContext.class);
- verify(workflow).doTransition(eq(issue), eq(transition.key()), measureCaptor.capture());
- verify(issueStorage).save(issue);
-
- IssueChangeContext issueChangeContext = measureCaptor.getValue();
- assertThat(issueChangeContext.login()).isEqualTo("arthur");
- assertThat(issueChangeContext.date()).isNotNull();
-
- verify(issueNotifications).sendChanges(eq(issue), eq(issueChangeContext), eq(issueQueryResult));
- }
-
- @Test
- public void not_do_transition() {
- when(workflow.doTransition(eq(issue), eq(transition.key()), any(IssueChangeContext.class))).thenReturn(false);
-
- Issue result = issueService.doTransition("ABCD", transition.key(), userSession);
- assertThat(result).isNotNull();
- verify(workflow).doTransition(eq(issue), eq(transition.key()), any(IssueChangeContext.class));
- verifyZeroInteractions(issueStorage);
- verifyZeroInteractions(issueNotifications);
- }
-
- @Test
- public void fail_do_transition_if_not_logged() {
- when(userSession.isLoggedIn()).thenReturn(false);
- try {
- issueService.doTransition("ABCD", transition.key(), userSession);
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("User is not logged in");
- }
- verifyZeroInteractions(authorizationDao);
- }
-
- @Test
- public void assign() {
- String assignee = "perceval";
- User user = new DefaultUser();
-
- when(userFinder.findByLogin(assignee)).thenReturn(user);
- when(issueUpdater.assign(eq(issue), eq(user), any(IssueChangeContext.class))).thenReturn(true);
-
- Issue result = issueService.assign("ABCD", assignee, userSession);
- assertThat(result).isNotNull();
-
- ArgumentCaptor<IssueChangeContext> measureCaptor = ArgumentCaptor.forClass(IssueChangeContext.class);
- verify(issueUpdater).assign(eq(issue), eq(user), measureCaptor.capture());
- verify(issueStorage).save(issue);
-
- IssueChangeContext issueChangeContext = measureCaptor.getValue();
- assertThat(issueChangeContext.login()).isEqualTo("arthur");
- assertThat(issueChangeContext.date()).isNotNull();
-
- verify(issueNotifications).sendChanges(eq(issue), eq(issueChangeContext), eq(issueQueryResult));
- }
-
- @Test
- public void unassign() {
- when(issueUpdater.assign(eq(issue), eq((User) null), any(IssueChangeContext.class))).thenReturn(true);
-
- Issue result = issueService.assign("ABCD", null, userSession);
- assertThat(result).isNotNull();
-
- ArgumentCaptor<IssueChangeContext> measureCaptor = ArgumentCaptor.forClass(IssueChangeContext.class);
- verify(issueUpdater).assign(eq(issue), eq((User) null), measureCaptor.capture());
- verify(issueStorage).save(issue);
-
- IssueChangeContext issueChangeContext = measureCaptor.getValue();
- assertThat(issueChangeContext.login()).isEqualTo("arthur");
- assertThat(issueChangeContext.date()).isNotNull();
-
- verify(issueNotifications).sendChanges(eq(issue), eq(issueChangeContext), eq(issueQueryResult));
- verify(userFinder, never()).findByLogin(anyString());
- }
-
- @Test
- public void not_assign() {
- String assignee = "perceval";
- User user = new DefaultUser();
-
- when(userFinder.findByLogin(assignee)).thenReturn(user);
- when(issueUpdater.assign(eq(issue), eq(user), any(IssueChangeContext.class))).thenReturn(false);
-
- Issue result = issueService.assign("ABCD", assignee, userSession);
- assertThat(result).isNotNull();
-
- verify(issueUpdater).assign(eq(issue), eq(user), any(IssueChangeContext.class));
- verifyZeroInteractions(issueStorage);
- verifyZeroInteractions(issueNotifications);
- }
-
- @Test
- public void fail_assign_if_assignee_not_found() {
- String assignee = "perceval";
-
- when(userFinder.findByLogin(assignee)).thenReturn(null);
-
- try {
- issueService.assign("ABCD", assignee, userSession);
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Unknown user: perceval");
- }
-
- verifyZeroInteractions(issueUpdater);
- verifyZeroInteractions(issueStorage);
- verifyZeroInteractions(issueNotifications);
- }
-
- @Test
- public void plan() {
- String actionPlanKey = "EFGH";
-
- ActionPlan actionPlan = new DefaultActionPlan();
-
- when(actionPlanService.findByKey(actionPlanKey, userSession)).thenReturn(actionPlan);
- when(issueUpdater.plan(eq(issue), eq(actionPlan), any(IssueChangeContext.class))).thenReturn(true);
-
- Issue result = issueService.plan("ABCD", actionPlanKey, userSession);
- assertThat(result).isNotNull();
-
- ArgumentCaptor<IssueChangeContext> measureCaptor = ArgumentCaptor.forClass(IssueChangeContext.class);
- verify(issueUpdater).plan(eq(issue), eq(actionPlan), measureCaptor.capture());
- verify(issueStorage).save(issue);
-
- IssueChangeContext issueChangeContext = measureCaptor.getValue();
- assertThat(issueChangeContext.login()).isEqualTo("arthur");
- assertThat(issueChangeContext.date()).isNotNull();
-
- verify(issueNotifications).sendChanges(eq(issue), eq(issueChangeContext), eq(issueQueryResult));
- }
-
- @Test
- public void unplan() {
- when(issueUpdater.plan(eq(issue), eq((ActionPlan) null), any(IssueChangeContext.class))).thenReturn(true);
-
- Issue result = issueService.plan("ABCD", null, userSession);
- assertThat(result).isNotNull();
-
- ArgumentCaptor<IssueChangeContext> measureCaptor = ArgumentCaptor.forClass(IssueChangeContext.class);
- verify(issueUpdater).plan(eq(issue), eq((ActionPlan) null), measureCaptor.capture());
- verify(issueStorage).save(issue);
-
- IssueChangeContext issueChangeContext = measureCaptor.getValue();
- assertThat(issueChangeContext.login()).isEqualTo("arthur");
- assertThat(issueChangeContext.date()).isNotNull();
-
- verify(issueNotifications).sendChanges(eq(issue), eq(issueChangeContext), eq(issueQueryResult));
- verify(actionPlanService, never()).findByKey(anyString(), any(UserSession.class));
- }
-
- @Test
- public void not_plan() {
- String actionPlanKey = "EFGH";
-
- ActionPlan actionPlan = new DefaultActionPlan();
-
- when(actionPlanService.findByKey(actionPlanKey, userSession)).thenReturn(actionPlan);
- when(issueUpdater.plan(eq(issue), eq(actionPlan), any(IssueChangeContext.class))).thenReturn(false);
-
- Issue result = issueService.plan("ABCD", actionPlanKey, userSession);
- assertThat(result).isNotNull();
- verify(issueUpdater).plan(eq(issue), eq(actionPlan), any(IssueChangeContext.class));
- verifyZeroInteractions(issueStorage);
- verifyZeroInteractions(issueNotifications);
- }
-
- @Test
- public void fail_plan_if_action_plan_not_found() {
- String actionPlanKey = "EFGH";
-
- when(actionPlanService.findByKey(actionPlanKey, userSession)).thenReturn(null);
- try {
- issueService.plan("ABCD", actionPlanKey, userSession);
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Unknown action plan: EFGH");
- }
-
- verifyZeroInteractions(issueUpdater);
- verifyZeroInteractions(issueStorage);
- verifyZeroInteractions(issueNotifications);
- }
-
- @Test
- public void set_severity() {
- String severity = "MINOR";
- when(issueUpdater.setManualSeverity(eq(issue), eq(severity), any(IssueChangeContext.class))).thenReturn(true);
-
- Issue result = issueService.setSeverity("ABCD", severity, userSession);
- assertThat(result).isNotNull();
-
- ArgumentCaptor<IssueChangeContext> measureCaptor = ArgumentCaptor.forClass(IssueChangeContext.class);
- verify(issueUpdater).setManualSeverity(eq(issue), eq(severity), measureCaptor.capture());
- verify(issueStorage).save(issue);
-
- IssueChangeContext issueChangeContext = measureCaptor.getValue();
- assertThat(issueChangeContext.login()).isEqualTo("arthur");
- assertThat(issueChangeContext.date()).isNotNull();
-
- verify(issueNotifications).sendChanges(eq(issue), eq(issueChangeContext), eq(issueQueryResult));
- }
-
- @Test
- public void not_set_severity() {
- String severity = "MINOR";
- when(issueUpdater.setManualSeverity(eq(issue), eq(severity), any(IssueChangeContext.class))).thenReturn(false);
-
- Issue result = issueService.setSeverity("ABCD", severity, userSession);
- assertThat(result).isNotNull();
- verify(issueUpdater).setManualSeverity(eq(issue), eq(severity), any(IssueChangeContext.class));
- verifyZeroInteractions(issueStorage);
- verifyZeroInteractions(issueNotifications);
- }
-
- @Test
- public void create_manual_issue() {
- RuleKey ruleKey = RuleKey.of("manual", "manualRuleKey");
- when(ruleFinder.findByKey(ruleKey)).thenReturn(Rule.create("manual", "manualRuleKey"));
- when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(resource);
- when(resourceDao.getRootProjectByComponentKey(anyString())).thenReturn(project);
-
- Issue result = issueService.createManualIssue("org.sonar.Sample", RuleKey.of("manual", "manualRuleKey"), null, "Fix it", null, null, 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(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");
- 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);
-
- Issue result = issueService.createManualIssue("org.sonar.Sample", RuleKey.of("manual", "manualRuleKey"), null, "", null, null, 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(authorizationDao).isAuthorizedComponentKey(anyString(), anyInt(), eq(UserRole.USER));
- }
-
- @Test
- public void 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(ruleFinder.findByKey(ruleKey)).thenReturn(Rule.create("manual", "manualRuleKey"));
- when(authorizationDao.isAuthorizedComponentKey(anyString(), eq(10), anyString())).thenReturn(false);
-
- try {
- issueService.createManualIssue("org.sonar.Sample", ruleKey, null, null, null, null, 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);
-
- RuleKey ruleKey = RuleKey.of("squid", "s100");
- try {
- issueService.createManualIssue("org.sonar.Sample", ruleKey, null, null, null, null, userSession);
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Issues can be created only on rules marked as 'manual': squid:s100");
- }
- verifyZeroInteractions(issueStorage);
- }
-
- @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);
-
- RuleKey ruleKey = RuleKey.of("manual", "manualRuleKey");
- when(ruleFinder.findByKey(ruleKey)).thenReturn(null);
- try {
- issueService.createManualIssue("org.sonar.Sample", RuleKey.of("manual", "manualRuleKey"), null, null, null, null, userSession);
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Unknown rule: manual:manualRuleKey");
- }
- verifyZeroInteractions(issueStorage);
- }
-
- @Test
- public void fail_create_manual_issue_if_component_not_found() {
- RuleKey ruleKey = RuleKey.of("manual", "manualRuleKey");
- 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);
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Unknown component: org.sonar.Sample");
- }
- verifyZeroInteractions(issueStorage);
- }
-
- @Test
- public void find_rules_by_component() throws Exception {
- DbSession session = mock(DbSession.class);
- String componentKey = "org.sonar.Sample";
-
- Date date = new Date();
- when(issueDao.findRulesByComponent(componentKey, date, session)).thenReturn(newArrayList(
- RuleDto.createFor(RuleKey.of("repo", "rule")).setName("Rule name"),
- RuleDto.createFor(RuleKey.of("repo", "rule")).setName("Rule name")
- ));
-
- RulesAggregation result = issueService.findRulesByComponent(componentKey, date, session);
- assertThat(result.rules()).hasSize(1);
- }
-
- @Test
- public void find_rules_by_severity() throws Exception {
- DbSession session = mock(DbSession.class);
- String componentKey = "org.sonar.Sample";
-
- Date date = new Date();
- when(issueDao.findSeveritiesByComponent(componentKey, date, session)).thenReturn(newArrayList("MAJOR", "MAJOR", "INFO"));
-
- Multiset<String> result = issueService.findSeveritiesByComponent(componentKey, date, session);
- assertThat(result.count("MAJOR")).isEqualTo(2);
- assertThat(result.count("INFO")).isEqualTo(1);
- assertThat(result.count("UNKNOWN")).isEqualTo(0);
- }
-}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.issue;
+
+import com.google.common.collect.Multiset;
+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 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.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.DefaultActionPlan;
+import org.sonar.core.issue.IssueNotifications;
+import org.sonar.core.issue.IssueUpdater;
+import org.sonar.core.issue.db.IssueDao;
+import org.sonar.core.issue.db.IssueStorage;
+import org.sonar.core.issue.workflow.IssueWorkflow;
+import org.sonar.core.issue.workflow.Transition;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.preview.PreviewCache;
+import org.sonar.core.resource.ResourceDao;
+import org.sonar.core.resource.ResourceDto;
+import org.sonar.core.resource.ResourceQuery;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.core.user.AuthorizationDao;
+import org.sonar.core.user.DefaultUser;
+import org.sonar.server.issue.actionplan.ActionPlanService;
+import org.sonar.server.user.MockUserSession;
+import org.sonar.server.user.UserSession;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class OldDefaultIssueServiceTest {
+
+ @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
+ IssueDao issueDao;
+
+ @Mock
+ AuthorizationDao authorizationDao;
+
+ @Mock
+ UserFinder userFinder;
+
+ 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");
+
+ OldIssueService issueService;
+
+ @Before
+ public void before() {
+ userSession = MockUserSession.set()
+ .setLogin("arthur")
+ .setUserId(10)
+ .setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN)
+ .addProjectPermissions(UserRole.USER, project.getKey())
+ .addProjectPermissions(UserRole.ISSUE_ADMIN, project.getKey());
+
+ when(authorizationDao.isAuthorizedComponentKey(anyString(), eq(10), anyString())).thenReturn(true);
+ when(finder.find(any(IssueQuery.class))).thenReturn(issueQueryResult);
+ 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 OldIssueService(finder, workflow, issueStorage, issueUpdater, issueNotifications, actionPlanService, ruleFinder, resourceDao, issueDao,
+ authorizationDao, userFinder, mock(PreviewCache.class));
+ }
+
+ @Test
+ public void load_issue() {
+ IssueQueryResult result = issueService.loadIssue("ABCD");
+ assertThat(result).isEqualTo(issueQueryResult);
+ }
+
+ @Test
+ public void fail_to_load_issue() {
+ when(issueQueryResult.issues()).thenReturn(Collections.<Issue>emptyList());
+ when(finder.find(any(IssueQuery.class))).thenReturn(issueQueryResult);
+
+ try {
+ issueService.loadIssue("ABCD");
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Issue not found: ABCD");
+ }
+ }
+
+ @Test
+ public void list_status() {
+ issueService.listStatus();
+ verify(workflow).statusKeys();
+ }
+
+ @Test
+ public void list_transitions() {
+ List<Transition> transitions = newArrayList(transition);
+ when(workflow.outTransitions(issue)).thenReturn(transitions);
+
+ List<Transition> result = issueService.listTransitions("ABCD");
+ assertThat(result).hasSize(1);
+ assertThat(result.get(0)).isEqualTo(transition);
+ }
+
+ @Test
+ public void return_no_transition() {
+ when(issueQueryResult.first()).thenReturn(null);
+ when(issueQueryResult.issues()).thenReturn(newArrayList((Issue) new DefaultIssue()));
+
+ assertThat(issueService.listTransitions("ABCD")).isEmpty();
+ verifyZeroInteractions(workflow);
+ }
+
+ @Test
+ public void do_transition() {
+ when(workflow.doTransition(eq(issue), eq(transition.key()), any(IssueChangeContext.class))).thenReturn(true);
+
+ Issue result = issueService.doTransition("ABCD", transition.key());
+ assertThat(result).isNotNull();
+
+ ArgumentCaptor<IssueChangeContext> measureCaptor = ArgumentCaptor.forClass(IssueChangeContext.class);
+ verify(workflow).doTransition(eq(issue), eq(transition.key()), measureCaptor.capture());
+ verify(issueStorage).save(issue);
+
+ IssueChangeContext issueChangeContext = measureCaptor.getValue();
+ assertThat(issueChangeContext.login()).isEqualTo("arthur");
+ assertThat(issueChangeContext.date()).isNotNull();
+
+ verify(issueNotifications).sendChanges(eq(issue), eq(issueChangeContext), eq(issueQueryResult));
+ }
+
+ @Test
+ public void not_do_transition() {
+ when(workflow.doTransition(eq(issue), eq(transition.key()), any(IssueChangeContext.class))).thenReturn(false);
+
+ Issue result = issueService.doTransition("ABCD", transition.key());
+ assertThat(result).isNotNull();
+ verify(workflow).doTransition(eq(issue), eq(transition.key()), any(IssueChangeContext.class));
+ verifyZeroInteractions(issueStorage);
+ verifyZeroInteractions(issueNotifications);
+ }
+
+ @Test
+ public void fail_do_transition_if_not_logged() {
+ MockUserSession.set();
+ try {
+ issueService.doTransition("ABCD", transition.key());
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("User is not logged in");
+ }
+ verifyZeroInteractions(authorizationDao);
+ }
+
+ @Test
+ public void assign() {
+ String assignee = "perceval";
+ User user = new DefaultUser();
+
+ when(userFinder.findByLogin(assignee)).thenReturn(user);
+ when(issueUpdater.assign(eq(issue), eq(user), any(IssueChangeContext.class))).thenReturn(true);
+
+ Issue result = issueService.assign("ABCD", assignee);
+ assertThat(result).isNotNull();
+
+ ArgumentCaptor<IssueChangeContext> measureCaptor = ArgumentCaptor.forClass(IssueChangeContext.class);
+ verify(issueUpdater).assign(eq(issue), eq(user), measureCaptor.capture());
+ verify(issueStorage).save(issue);
+
+ IssueChangeContext issueChangeContext = measureCaptor.getValue();
+ assertThat(issueChangeContext.login()).isEqualTo("arthur");
+ assertThat(issueChangeContext.date()).isNotNull();
+
+ verify(issueNotifications).sendChanges(eq(issue), eq(issueChangeContext), eq(issueQueryResult));
+ }
+
+ @Test
+ public void unassign() {
+ when(issueUpdater.assign(eq(issue), eq((User) null), any(IssueChangeContext.class))).thenReturn(true);
+
+ Issue result = issueService.assign("ABCD", null);
+ assertThat(result).isNotNull();
+
+ ArgumentCaptor<IssueChangeContext> measureCaptor = ArgumentCaptor.forClass(IssueChangeContext.class);
+ verify(issueUpdater).assign(eq(issue), eq((User) null), measureCaptor.capture());
+ verify(issueStorage).save(issue);
+
+ IssueChangeContext issueChangeContext = measureCaptor.getValue();
+ assertThat(issueChangeContext.login()).isEqualTo("arthur");
+ assertThat(issueChangeContext.date()).isNotNull();
+
+ verify(issueNotifications).sendChanges(eq(issue), eq(issueChangeContext), eq(issueQueryResult));
+ verify(userFinder, never()).findByLogin(anyString());
+ }
+
+ @Test
+ public void not_assign() {
+ String assignee = "perceval";
+ User user = new DefaultUser();
+
+ when(userFinder.findByLogin(assignee)).thenReturn(user);
+ when(issueUpdater.assign(eq(issue), eq(user), any(IssueChangeContext.class))).thenReturn(false);
+
+ Issue result = issueService.assign("ABCD", assignee);
+ assertThat(result).isNotNull();
+
+ verify(issueUpdater).assign(eq(issue), eq(user), any(IssueChangeContext.class));
+ verifyZeroInteractions(issueStorage);
+ verifyZeroInteractions(issueNotifications);
+ }
+
+ @Test
+ public void fail_assign_if_assignee_not_found() {
+ String assignee = "perceval";
+
+ when(userFinder.findByLogin(assignee)).thenReturn(null);
+
+ try {
+ issueService.assign("ABCD", assignee);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Unknown user: perceval");
+ }
+
+ verifyZeroInteractions(issueUpdater);
+ verifyZeroInteractions(issueStorage);
+ verifyZeroInteractions(issueNotifications);
+ }
+
+ @Test
+ public void plan() {
+ String actionPlanKey = "EFGH";
+
+ ActionPlan actionPlan = new DefaultActionPlan();
+
+ when(actionPlanService.findByKey(actionPlanKey, userSession)).thenReturn(actionPlan);
+ when(issueUpdater.plan(eq(issue), eq(actionPlan), any(IssueChangeContext.class))).thenReturn(true);
+
+ Issue result = issueService.plan("ABCD", actionPlanKey);
+ assertThat(result).isNotNull();
+
+ ArgumentCaptor<IssueChangeContext> measureCaptor = ArgumentCaptor.forClass(IssueChangeContext.class);
+ verify(issueUpdater).plan(eq(issue), eq(actionPlan), measureCaptor.capture());
+ verify(issueStorage).save(issue);
+
+ IssueChangeContext issueChangeContext = measureCaptor.getValue();
+ assertThat(issueChangeContext.login()).isEqualTo("arthur");
+ assertThat(issueChangeContext.date()).isNotNull();
+
+ verify(issueNotifications).sendChanges(eq(issue), eq(issueChangeContext), eq(issueQueryResult));
+ }
+
+ @Test
+ public void unplan() {
+ when(issueUpdater.plan(eq(issue), eq((ActionPlan) null), any(IssueChangeContext.class))).thenReturn(true);
+
+ Issue result = issueService.plan("ABCD", null);
+ assertThat(result).isNotNull();
+
+ ArgumentCaptor<IssueChangeContext> measureCaptor = ArgumentCaptor.forClass(IssueChangeContext.class);
+ verify(issueUpdater).plan(eq(issue), eq((ActionPlan) null), measureCaptor.capture());
+ verify(issueStorage).save(issue);
+
+ IssueChangeContext issueChangeContext = measureCaptor.getValue();
+ assertThat(issueChangeContext.login()).isEqualTo("arthur");
+ assertThat(issueChangeContext.date()).isNotNull();
+
+ verify(issueNotifications).sendChanges(eq(issue), eq(issueChangeContext), eq(issueQueryResult));
+ verify(actionPlanService, never()).findByKey(anyString(), any(UserSession.class));
+ }
+
+ @Test
+ public void not_plan() {
+ String actionPlanKey = "EFGH";
+
+ ActionPlan actionPlan = new DefaultActionPlan();
+
+ when(actionPlanService.findByKey(actionPlanKey, userSession)).thenReturn(actionPlan);
+ when(issueUpdater.plan(eq(issue), eq(actionPlan), any(IssueChangeContext.class))).thenReturn(false);
+
+ Issue result = issueService.plan("ABCD", actionPlanKey);
+ assertThat(result).isNotNull();
+ verify(issueUpdater).plan(eq(issue), eq(actionPlan), any(IssueChangeContext.class));
+ verifyZeroInteractions(issueStorage);
+ verifyZeroInteractions(issueNotifications);
+ }
+
+ @Test
+ public void fail_plan_if_action_plan_not_found() {
+ String actionPlanKey = "EFGH";
+
+ when(actionPlanService.findByKey(actionPlanKey, userSession)).thenReturn(null);
+ try {
+ issueService.plan("ABCD", actionPlanKey);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Unknown action plan: EFGH");
+ }
+
+ verifyZeroInteractions(issueUpdater);
+ verifyZeroInteractions(issueStorage);
+ verifyZeroInteractions(issueNotifications);
+ }
+
+ @Test
+ public void set_severity() {
+ String severity = "MINOR";
+ when(issueUpdater.setManualSeverity(eq(issue), eq(severity), any(IssueChangeContext.class))).thenReturn(true);
+
+ Issue result = issueService.setSeverity("ABCD", severity);
+ assertThat(result).isNotNull();
+
+ ArgumentCaptor<IssueChangeContext> measureCaptor = ArgumentCaptor.forClass(IssueChangeContext.class);
+ verify(issueUpdater).setManualSeverity(eq(issue), eq(severity), measureCaptor.capture());
+ verify(issueStorage).save(issue);
+
+ IssueChangeContext issueChangeContext = measureCaptor.getValue();
+ assertThat(issueChangeContext.login()).isEqualTo("arthur");
+ assertThat(issueChangeContext.date()).isNotNull();
+
+ verify(issueNotifications).sendChanges(eq(issue), eq(issueChangeContext), eq(issueQueryResult));
+ }
+
+ @Test
+ public void not_set_severity() {
+ String severity = "MINOR";
+ when(issueUpdater.setManualSeverity(eq(issue), eq(severity), any(IssueChangeContext.class))).thenReturn(false);
+
+ Issue result = issueService.setSeverity("ABCD", severity);
+ assertThat(result).isNotNull();
+ verify(issueUpdater).setManualSeverity(eq(issue), eq(severity), any(IssueChangeContext.class));
+ verifyZeroInteractions(issueStorage);
+ verifyZeroInteractions(issueNotifications);
+ }
+
+ @Test
+ public void create_manual_issue() {
+ RuleKey ruleKey = RuleKey.of("manual", "manualRuleKey");
+ when(ruleFinder.findByKey(ruleKey)).thenReturn(Rule.create("manual", "manualRuleKey"));
+ when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(resource);
+ when(resourceDao.getRootProjectByComponentKey(anyString())).thenReturn(project);
+
+ Issue result = issueService.createManualIssue("org.sonar.Sample", RuleKey.of("manual", "manualRuleKey"), null, "Fix it", null, null);
+ assertThat(result).isNotNull();
+ assertThat(result.message()).isEqualTo("Fix it");
+ assertThat(result.creationDate()).isNotNull();
+ assertThat(result.updateDate()).isNotNull();
+
+ verify(issueStorage).save(any(DefaultIssue.class));
+ 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");
+ 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);
+
+ Issue result = issueService.createManualIssue("org.sonar.Sample", RuleKey.of("manual", "manualRuleKey"), null, "", null, null);
+ assertThat(result).isNotNull();
+ assertThat(result.message()).isEqualTo("Manual Rule");
+ assertThat(result.creationDate()).isNotNull();
+ assertThat(result.updateDate()).isNotNull();
+
+ verify(issueStorage).save(any(DefaultIssue.class));
+ verify(authorizationDao).isAuthorizedComponentKey(anyString(), anyInt(), eq(UserRole.USER));
+ }
+
+ @Test
+ public void 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(ruleFinder.findByKey(ruleKey)).thenReturn(Rule.create("manual", "manualRuleKey"));
+ when(authorizationDao.isAuthorizedComponentKey(anyString(), eq(10), anyString())).thenReturn(false);
+
+ try {
+ issueService.createManualIssue("org.sonar.Sample", ruleKey, null, null, null, null);
+ 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);
+
+ RuleKey ruleKey = RuleKey.of("squid", "s100");
+ try {
+ issueService.createManualIssue("org.sonar.Sample", ruleKey, null, null, null, null);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Issues can be created only on rules marked as 'manual': squid:s100");
+ }
+ verifyZeroInteractions(issueStorage);
+ }
+
+ @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);
+
+ RuleKey ruleKey = RuleKey.of("manual", "manualRuleKey");
+ when(ruleFinder.findByKey(ruleKey)).thenReturn(null);
+ try {
+ issueService.createManualIssue("org.sonar.Sample", RuleKey.of("manual", "manualRuleKey"), null, null, null, null);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Unknown rule: manual:manualRuleKey");
+ }
+ verifyZeroInteractions(issueStorage);
+ }
+
+ @Test
+ public void fail_create_manual_issue_if_component_not_found() {
+ RuleKey ruleKey = RuleKey.of("manual", "manualRuleKey");
+ 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);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Unknown component: org.sonar.Sample");
+ }
+ verifyZeroInteractions(issueStorage);
+ }
+
+ @Test
+ public void find_rules_by_component() throws Exception {
+ DbSession session = mock(DbSession.class);
+ String componentKey = "org.sonar.Sample";
+
+ Date date = new Date();
+ when(issueDao.findRulesByComponent(componentKey, date, session)).thenReturn(newArrayList(
+ RuleDto.createFor(RuleKey.of("repo", "rule")).setName("Rule name"),
+ RuleDto.createFor(RuleKey.of("repo", "rule")).setName("Rule name")
+ ));
+
+ RulesAggregation result = issueService.findRulesByComponent(componentKey, date, session);
+ assertThat(result.rules()).hasSize(1);
+ }
+
+ @Test
+ public void find_rules_by_severity() throws Exception {
+ DbSession session = mock(DbSession.class);
+ String componentKey = "org.sonar.Sample";
+
+ Date date = new Date();
+ when(issueDao.findSeveritiesByComponent(componentKey, date, session)).thenReturn(newArrayList("MAJOR", "MAJOR", "INFO"));
+
+ Multiset<String> result = issueService.findSeveritiesByComponent(componentKey, date, session);
+ assertThat(result.count("MAJOR")).isEqualTo(2);
+ assertThat(result.count("INFO")).isEqualTo(1);
+ assertThat(result.count("UNKNOWN")).isEqualTo(0);
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.issue;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+import org.sonar.api.issue.IssueFinder;
+import org.sonar.api.issue.IssueQuery;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.web.UserRole;
+
+import java.util.Map;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.collect.Maps.newHashMap;
+import static java.util.Arrays.asList;
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.*;
+
+public class PublicRubyDefaultIssueServiceTest {
+
+ IssueFinder finder = mock(IssueFinder.class);
+ PublicRubyIssueService facade = new PublicRubyIssueService(finder);
+
+ @Test
+ public void find_by_issue_keys() throws Exception {
+ facade.find("ABCDE");
+ verify(finder).find(argThat(new ArgumentMatcher<IssueQuery>() {
+ @Override
+ public boolean matches(Object o) {
+ IssueQuery query = (IssueQuery) o;
+ return query.issueKeys().contains("ABCDE") && UserRole.USER.equals(query.requiredRole());
+ }
+ }));
+ }
+
+ @Test
+ public void find_by_params() throws Exception {
+ facade.find(ImmutableMap.<String, Object>of("issues", Lists.newArrayList("ABCDE")));
+ verify(finder).find(argThat(new ArgumentMatcher<IssueQuery>() {
+ @Override
+ public boolean matches(Object o) {
+ IssueQuery query = (IssueQuery) o;
+ return query.issueKeys().contains("ABCDE") && UserRole.USER.equals(query.requiredRole());
+ }
+ }));
+ }
+
+ @Test
+ public void create_query_from_parameters() {
+ Map<String, Object> map = newHashMap();
+ map.put("issues", newArrayList("ABCDE1234"));
+ map.put("severities", newArrayList("MAJOR", "MINOR"));
+ map.put("statuses", newArrayList("CLOSED"));
+ map.put("resolutions", newArrayList("FALSE-POSITIVE"));
+ map.put("resolved", true);
+ map.put("components", newArrayList("org.apache"));
+ map.put("componentRoots", newArrayList("org.sonar"));
+ map.put("reporters", newArrayList("marilyn"));
+ map.put("assignees", newArrayList("joanna"));
+ map.put("languages", newArrayList("xoo"));
+ map.put("assigned", true);
+ map.put("planned", true);
+ map.put("hideRules", true);
+ map.put("createdAfter", "2013-04-16T09:08:24+0200");
+ map.put("createdBefore", "2013-04-17T09:08:24+0200");
+ map.put("rules", "squid:AvoidCycle,findbugs:NullReference");
+ map.put("pageSize", 10l);
+ map.put("pageIndex", 50);
+ map.put("sort", "CREATION_DATE");
+ map.put("asc", true);
+
+ IssueQuery query = new PublicRubyIssueService(finder).toQuery(map);
+ assertThat(query.issueKeys()).containsOnly("ABCDE1234");
+ assertThat(query.severities()).containsOnly("MAJOR", "MINOR");
+ assertThat(query.statuses()).containsOnly("CLOSED");
+ assertThat(query.resolutions()).containsOnly("FALSE-POSITIVE");
+ assertThat(query.resolved()).isTrue();
+ assertThat(query.components()).containsOnly("org.apache");
+ assertThat(query.componentRoots()).containsOnly("org.sonar");
+ assertThat(query.reporters()).containsOnly("marilyn");
+ assertThat(query.assignees()).containsOnly("joanna");
+ assertThat(query.languages()).containsOnly("xoo");
+ assertThat(query.assigned()).isTrue();
+ assertThat(query.planned()).isTrue();
+ assertThat(query.hideRules()).isTrue();
+ assertThat(query.rules()).hasSize(2);
+ assertThat(query.createdAfter()).isEqualTo(DateUtils.parseDateTime("2013-04-16T09:08:24+0200"));
+ assertThat(query.createdBefore()).isEqualTo(DateUtils.parseDateTime("2013-04-17T09:08:24+0200"));
+ assertThat(query.pageSize()).isEqualTo(10);
+ assertThat(query.pageIndex()).isEqualTo(50);
+ assertThat(query.sort()).isEqualTo(IssueQuery.SORT_BY_CREATION_DATE);
+ assertThat(query.asc()).isTrue();
+ }
+
+ @Test
+ public void parse_list_of_rules() {
+ assertThat(PublicRubyIssueService.toRules(null)).isNull();
+ assertThat(PublicRubyIssueService.toRules("")).isEmpty();
+ assertThat(PublicRubyIssueService.toRules("squid:AvoidCycle")).containsOnly(RuleKey.of("squid", "AvoidCycle"));
+ assertThat(PublicRubyIssueService.toRules("squid:AvoidCycle,findbugs:NullRef")).containsOnly(RuleKey.of("squid", "AvoidCycle"), RuleKey.of("findbugs", "NullRef"));
+ assertThat(PublicRubyIssueService.toRules(asList("squid:AvoidCycle", "findbugs:NullRef"))).containsOnly(RuleKey.of("squid", "AvoidCycle"), RuleKey.of("findbugs", "NullRef"));
+ }
+
+ @Test
+ public void start() throws Exception {
+ facade.start();
+ // nothing is done
+ verifyZeroInteractions(finder);
+ }
+}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.issue;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-import org.junit.Test;
-import org.mockito.ArgumentMatcher;
-import org.sonar.api.issue.IssueFinder;
-import org.sonar.api.issue.IssueQuery;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.api.web.UserRole;
-
-import java.util.Map;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static com.google.common.collect.Maps.newHashMap;
-import static java.util.Arrays.asList;
-import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Mockito.*;
-
-public class PublicRubyIssueServiceTest {
-
- IssueFinder finder = mock(IssueFinder.class);
- PublicRubyIssueService facade = new PublicRubyIssueService(finder);
-
- @Test
- public void find_by_issue_keys() throws Exception {
- facade.find("ABCDE");
- verify(finder).find(argThat(new ArgumentMatcher<IssueQuery>() {
- @Override
- public boolean matches(Object o) {
- IssueQuery query = (IssueQuery) o;
- return query.issueKeys().contains("ABCDE") && UserRole.USER.equals(query.requiredRole());
- }
- }));
- }
-
- @Test
- public void find_by_params() throws Exception {
- facade.find(ImmutableMap.<String, Object>of("issues", Lists.newArrayList("ABCDE")));
- verify(finder).find(argThat(new ArgumentMatcher<IssueQuery>() {
- @Override
- public boolean matches(Object o) {
- IssueQuery query = (IssueQuery) o;
- return query.issueKeys().contains("ABCDE") && UserRole.USER.equals(query.requiredRole());
- }
- }));
- }
-
- @Test
- public void create_query_from_parameters() {
- Map<String, Object> map = newHashMap();
- map.put("issues", newArrayList("ABCDE1234"));
- map.put("severities", newArrayList("MAJOR", "MINOR"));
- map.put("statuses", newArrayList("CLOSED"));
- map.put("resolutions", newArrayList("FALSE-POSITIVE"));
- map.put("resolved", true);
- map.put("components", newArrayList("org.apache"));
- map.put("componentRoots", newArrayList("org.sonar"));
- map.put("reporters", newArrayList("marilyn"));
- map.put("assignees", newArrayList("joanna"));
- map.put("languages", newArrayList("xoo"));
- map.put("assigned", true);
- map.put("planned", true);
- map.put("hideRules", true);
- map.put("createdAfter", "2013-04-16T09:08:24+0200");
- map.put("createdBefore", "2013-04-17T09:08:24+0200");
- map.put("rules", "squid:AvoidCycle,findbugs:NullReference");
- map.put("pageSize", 10l);
- map.put("pageIndex", 50);
- map.put("sort", "CREATION_DATE");
- map.put("asc", true);
-
- IssueQuery query = new PublicRubyIssueService(finder).toQuery(map);
- assertThat(query.issueKeys()).containsOnly("ABCDE1234");
- assertThat(query.severities()).containsOnly("MAJOR", "MINOR");
- assertThat(query.statuses()).containsOnly("CLOSED");
- assertThat(query.resolutions()).containsOnly("FALSE-POSITIVE");
- assertThat(query.resolved()).isTrue();
- assertThat(query.components()).containsOnly("org.apache");
- assertThat(query.componentRoots()).containsOnly("org.sonar");
- assertThat(query.reporters()).containsOnly("marilyn");
- assertThat(query.assignees()).containsOnly("joanna");
- assertThat(query.languages()).containsOnly("xoo");
- assertThat(query.assigned()).isTrue();
- assertThat(query.planned()).isTrue();
- assertThat(query.hideRules()).isTrue();
- assertThat(query.rules()).hasSize(2);
- assertThat(query.createdAfter()).isEqualTo(DateUtils.parseDateTime("2013-04-16T09:08:24+0200"));
- assertThat(query.createdBefore()).isEqualTo(DateUtils.parseDateTime("2013-04-17T09:08:24+0200"));
- assertThat(query.pageSize()).isEqualTo(10);
- assertThat(query.pageIndex()).isEqualTo(50);
- assertThat(query.sort()).isEqualTo(IssueQuery.SORT_BY_CREATION_DATE);
- assertThat(query.asc()).isTrue();
- }
-
- @Test
- public void parse_list_of_rules() {
- assertThat(PublicRubyIssueService.toRules(null)).isNull();
- assertThat(PublicRubyIssueService.toRules("")).isEmpty();
- assertThat(PublicRubyIssueService.toRules("squid:AvoidCycle")).containsOnly(RuleKey.of("squid", "AvoidCycle"));
- assertThat(PublicRubyIssueService.toRules("squid:AvoidCycle,findbugs:NullRef")).containsOnly(RuleKey.of("squid", "AvoidCycle"), RuleKey.of("findbugs", "NullRef"));
- assertThat(PublicRubyIssueService.toRules(asList("squid:AvoidCycle", "findbugs:NullRef"))).containsOnly(RuleKey.of("squid", "AvoidCycle"), RuleKey.of("findbugs", "NullRef"));
- }
-
- @Test
- public void start() throws Exception {
- facade.start();
- // nothing is done
- verifyZeroInteractions(finder);
- }
-}
public class IssueBackendMediumTest {
@ClassRule
- public static ServerTester tester = new ServerTester();
+ public static ServerTester tester = new ServerTester()
+ .setProperty("sonar.issues.use_es_backend", "true");
DbClient dbClient;
IndexClient indexClient;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.System2;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.issue.db.IssueDto;
import org.sonar.core.persistence.AbstractDaoTestCase;
import org.sonar.core.persistence.DbSession;
+import org.sonar.server.rule.RuleTesting;
import java.util.Date;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class IssueDaoTest extends AbstractDaoTestCase {
this.session.close();
}
+ @Test
+ public void get_by_key() {
+ setupData("shared", "get_by_key");
+
+ IssueDto issue = dao.getByKey(session, "ABCDE");
+ assertThat(issue.getKee()).isEqualTo("ABCDE");
+ assertThat(issue.getId()).isEqualTo(100L);
+ assertThat(issue.getComponentId()).isEqualTo(401);
+ assertThat(issue.getRootComponentId()).isEqualTo(399);
+ assertThat(issue.getRuleId()).isEqualTo(500);
+ assertThat(issue.getSeverity()).isEqualTo("BLOCKER");
+ assertThat(issue.isManualSeverity()).isFalse();
+ assertThat(issue.getMessage()).isNull();
+ assertThat(issue.getLine()).isEqualTo(200);
+ assertThat(issue.getEffortToFix()).isEqualTo(4.2);
+ assertThat(issue.getStatus()).isEqualTo("OPEN");
+ assertThat(issue.getResolution()).isEqualTo("FIXED");
+ assertThat(issue.getChecksum()).isEqualTo("XXX");
+ assertThat(issue.getAuthorLogin()).isEqualTo("karadoc");
+ assertThat(issue.getReporter()).isEqualTo("arthur");
+ assertThat(issue.getAssignee()).isEqualTo("perceval");
+ assertThat(issue.getIssueAttributes()).isEqualTo("JIRA=FOO-1234");
+ assertThat(issue.getIssueCreationDate()).isNotNull();
+ assertThat(issue.getIssueUpdateDate()).isNotNull();
+ assertThat(issue.getIssueCloseDate()).isNotNull();
+ assertThat(issue.getCreatedAt()).isNotNull();
+ assertThat(issue.getUpdatedAt()).isNotNull();
+ assertThat(issue.getRuleRepo()).isEqualTo("squid");
+ assertThat(issue.getRule()).isEqualTo("AvoidCycle");
+ assertThat(issue.getComponentKey()).isEqualTo("Action.java");
+ assertThat(issue.getRootComponentKey()).isEqualTo("struts");
+ }
+
@Test
public void find_after_dates() throws Exception {
- setupData("shared", "should_select_all");
+ setupData("shared", "some_issues");
Date t0 = new Date(0);
assertThat(dao.findAfterDate(session, t0)).hasSize(3);
assertThat(dao.findAfterDate(session, DateUtils.parseDate("2014-01-01"), ImmutableMap.of("project", "struts"))).hasSize(1);
}
+
+ @Test
+ public void insert() throws Exception {
+ when(system2.now()).thenReturn(DateUtils.parseDate("2013-05-22").getTime());
+
+ IssueDto dto = new IssueDto();
+ dto.setComponent(new ComponentDto().setKey("struts:Action").setId(123L));
+ dto.setRootComponent(new ComponentDto().setKey("struts").setId(100L));
+ dto.setRule(RuleTesting.newDto(RuleKey.of("squid", "S001")).setId(200));
+ dto.setKee("ABCDE");
+ dto.setLine(500);
+ dto.setEffortToFix(3.14);
+ dto.setDebt(10L);
+ dto.setResolution("FIXED");
+ dto.setStatus("RESOLVED");
+ dto.setSeverity("BLOCKER");
+ dto.setReporter("emmerik");
+ dto.setAuthorLogin("morgan");
+ dto.setAssignee("karadoc");
+ dto.setActionPlanKey("current_sprint");
+ dto.setIssueAttributes("JIRA=FOO-1234");
+ dto.setChecksum("123456789");
+ dto.setMessage("the message");
+
+ dto.setIssueCreationDate(DateUtils.parseDate("2013-05-18"));
+ dto.setIssueUpdateDate(DateUtils.parseDate("2013-05-19"));
+ dto.setIssueCloseDate(DateUtils.parseDate("2013-05-20"));
+ dto.setCreatedAt(DateUtils.parseDate("2013-05-21"));
+ dto.setUpdatedAt(DateUtils.parseDate("2013-05-22"));
+
+ dao.insert(session, dto);
+ session.commit();
+
+ checkTables("insert", new String[]{"id"}, "issues");
+ }
+
+ @Test
+ public void update() throws Exception {
+ when(system2.now()).thenReturn(DateUtils.parseDate("2013-05-22").getTime());
+
+ setupData("update");
+
+ IssueDto dto = new IssueDto();
+ dto.setComponent(new ComponentDto().setKey("struts:Action").setId(123L));
+ dto.setRootComponent(new ComponentDto().setKey("struts").setId(101L));
+ dto.setRule(RuleTesting.newDto(RuleKey.of("squid", "S001")).setId(200));
+ dto.setKee("ABCDE");
+ dto.setLine(500);
+ dto.setEffortToFix(3.14);
+ dto.setDebt(10L);
+ dto.setResolution("FIXED");
+ dto.setStatus("RESOLVED");
+ dto.setSeverity("BLOCKER");
+ dto.setReporter("emmerik");
+ dto.setAuthorLogin("morgan");
+ dto.setAssignee("karadoc");
+ dto.setActionPlanKey("current_sprint");
+ dto.setIssueAttributes("JIRA=FOO-1234");
+ dto.setChecksum("123456789");
+ dto.setMessage("the message");
+
+ dto.setIssueCreationDate(DateUtils.parseDate("2013-05-18"));
+ dto.setIssueUpdateDate(DateUtils.parseDate("2013-05-19"));
+ dto.setIssueCloseDate(DateUtils.parseDate("2013-05-20"));
+ dto.setCreatedAt(DateUtils.parseDate("2013-05-21"));
+ dto.setUpdatedAt(DateUtils.parseDate("2013-05-22"));
+
+ dao.update(session, dto);
+ session.commit();
+
+ checkTables("update", new String[]{"id"}, "issues");
+ }
}
public class IssueAuthorizationIndexMediumTest {
@ClassRule
- public static ServerTester tester = new ServerTester();
+ public static ServerTester tester = new ServerTester()
+ .setProperty("sonar.issues.use_es_backend", "true");
DbClient db;
DbSession session;
public class IssueIndexMediumTest {
@ClassRule
- public static ServerTester tester = new ServerTester();
+ public static ServerTester tester = new ServerTester()
+ .setProperty("sonar.issues.use_es_backend", "true");
DbClient db;
DbSession session;
import org.sonar.server.issue.ActionService;
import org.sonar.server.issue.IssueService;
import org.sonar.server.user.MockUserSession;
-import org.sonar.server.user.UserSession;
import java.io.StringWriter;
import static com.google.common.collect.Lists.newArrayList;
-import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
"{\"actions\": " +
"[" +
"\"comment\", \"assign\", \"assign_to_me\", \"plan\", \"set_severity\"\n" +
- "]}"
- );
+ "]}");
}
@Test
"{\"actions\": " +
"[" +
"\"comment\", \"assign\", \"assign_to_me\", \"plan\", \"link-to-jira\"\n" +
- "]}"
- );
+ "]}");
}
@Test
"{\"actions\": " +
"[" +
"\"comment\"" +
- "]}"
- );
+ "]}");
}
@Test
MockUserSession.set();
testActions(issue,
- "{\"actions\": []}"
- );
+ "{\"actions\": []}");
}
@Test
"{\"actions\": " +
"[" +
"\"comment\", \"assign\", \"plan\"\n" +
- "]}"
- );
+ "]}");
}
@Test
.setProjectKey("sample")
.setRuleKey(RuleKey.of("squid", "AvoidCycle"));
- when(issueService.listTransitions(eq(issue), any(UserSession.class))).thenReturn(newArrayList(Transition.create("reopen", "RESOLVED", "REOPEN")));
+ when(issueService.listTransitions(eq(issue))).thenReturn(newArrayList(Transition.create("reopen", "RESOLVED", "REOPEN")));
MockUserSession.set().setLogin("john");
testTransitions(issue,
"{\"transitions\": [\n" +
" \"reopen\"\n" +
- " ]}"
- );
+ " ]}");
}
@Test
MockUserSession.set().setLogin("john");
testTransitions(issue,
- "{\"transitions\": []}"
- );
+ "{\"transitions\": []}");
}
private void testActions(Issue issue, String expected) throws JSONException {
import org.sonar.server.issue.ActionService;
import org.sonar.server.issue.IssueService;
import org.sonar.server.user.MockUserSession;
-import org.sonar.server.user.UserSession;
import org.sonar.server.ws.WsTester;
import java.util.*;
issues.add(issue);
MockUserSession.set().setLogin("john");
- when(issueService.listTransitions(eq(issue), any(UserSession.class))).thenReturn(newArrayList(Transition.create("reopen", "RESOLVED", "REOPEN")));
+ when(issueService.listTransitions(eq(issue))).thenReturn(newArrayList(Transition.create("reopen", "RESOLVED", "REOPEN")));
result.addActionPlans(newArrayList((ActionPlan) new DefaultActionPlan().setKey("AP-ABCD").setName("1.0")));
import org.sonar.server.issue.IssueChangelogService;
import org.sonar.server.issue.IssueService;
import org.sonar.server.user.MockUserSession;
-import org.sonar.server.user.UserSession;
import org.sonar.server.ws.WsTester;
import java.util.ArrayList;
.setResolution("FIXED");
issues.add(issue);
- when(issueService.listTransitions(eq(issue), any(UserSession.class))).thenReturn(newArrayList(Transition.create("reopen", "RESOLVED", "REOPEN")));
+ when(issueService.listTransitions(eq(issue))).thenReturn(newArrayList(Transition.create("reopen", "RESOLVED", "REOPEN")));
MockUserSession.set().setLogin("john");
WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issue.key());
public static RuleDto newManualRule(String manualKey){
return new RuleDto().setRuleKey(manualKey)
+ .setName("Name " + manualKey)
.setRepositoryKey("manual")
.setDescription("Description " + manualKey)
.setStatus(RuleStatus.READY);
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
+import org.sonar.api.config.Settings;
import org.sonar.api.rule.RuleKey;
import org.sonar.core.persistence.DbSession;
import org.sonar.server.db.DbClient;
public class IndexSynchronizerMediumTest {
@ClassRule
- public static ServerTester tester = new ServerTester();
+ public static ServerTester tester = new ServerTester()
+ .setProperty("sonar.issues.use_es_backend", "true");
IndexSynchronizer synchronizer;
DbClient dbClient;
indexClient = tester.get(IndexClient.class);
platform = tester.get(Platform.class);
dbSession = dbClient.openSession(false);
- synchronizer = new IndexSynchronizer(dbClient, indexClient);
+ synchronizer = new IndexSynchronizer(dbClient, indexClient, tester.get(Settings.class));
tester.clearDbAndIndexes();
}
--- /dev/null
+<dataset>
+
+ <issues
+ id="100"
+ kee="ABCDE"
+ component_id="401"
+ root_component_id="399"
+ rule_id="500"
+ severity="BLOCKER"
+ manual_severity="[false]"
+ message="[null]"
+ line="200"
+ effort_to_fix="4.2"
+ status="OPEN"
+ resolution="FIXED"
+ checksum="XXX"
+ reporter="arthur"
+ assignee="perceval"
+ author_login="karadoc"
+ issue_attributes="JIRA=FOO-1234"
+ 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="2013-04-16"
+ />
+
+</dataset>
--- /dev/null
+<dataset>
+ <issues
+ id="100"
+ kee="ABCDE"
+ component_id="123"
+ root_component_id="100"
+ rule_id="200"
+ severity="BLOCKER"
+ manual_severity="[false]"
+ message="the message"
+ line="500"
+ effort_to_fix="3.14"
+ technical_debt="10"
+ status="RESOLVED"
+ resolution="FIXED"
+ checksum="123456789"
+ reporter="emmerik"
+ author_login="morgan"
+ assignee="karadoc"
+ issue_attributes="JIRA=FOO-1234"
+ issue_creation_date="2013-05-18"
+ issue_update_date="2013-05-19"
+ issue_close_date="2013-05-20"
+ created_at="2013-05-21"
+ updated_at="2013-05-22"
+ action_plan_key="current_sprint"
+ />
+</dataset>
+++ /dev/null
-<dataset>
-
- <!-- rule 500 -->
- <issues
- id="100"
- kee="ABCDE-1"
- component_id="401"
- root_component_id="399"
- rule_id="500"
- severity="BLOCKER"
- manual_severity="[false]"
- message="[null]"
- line="200"
- effort_to_fix="4.2"
- status="OPEN"
- resolution="FIXED"
- checksum="XXX"
- reporter="arthur"
- assignee="perceval"
- author_login="[null]"
- issue_attributes="JIRA=FOO-1234"
- 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="2013-04-16"
- />
-
- <issues
- id="101"
- kee="ABCDE-2"
- component_id="401"
- root_component_id="399"
- rule_id="500"
- severity="BLOCKER"
- manual_severity="[false]"
- message="[null]"
- line="200"
- effort_to_fix="4.2"
- status="OPEN"
- resolution="FIXED"
- checksum="XXX"
- reporter="arthur"
- assignee="perceval"
- author_login="[null]"
- issue_attributes="JIRA=FOO-1234"
- 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="2013-04-16"
- />
-
-
- <!-- rule 501 -->
- <issues
- id="102"
- kee="ABCDE-3"
- component_id="401"
- root_component_id="399"
- rule_id="501"
- severity="BLOCKER"
- manual_severity="[false]"
- message="[null]"
- line="200"
- effort_to_fix="4.2"
- status="OPEN"
- resolution="FIXED"
- checksum="XXX"
- reporter="arthur"
- assignee="perceval"
- author_login="[null]"
- issue_attributes="JIRA=FOO-1234"
- issue_creation_date="2014-04-16"
- issue_update_date="2014-04-16"
- issue_close_date="2014-04-16"
- created_at="2014-04-16"
- updated_at="2014-04-16"
- />
-</dataset>
--- /dev/null
+<dataset>
+
+ <!-- rule 500 -->
+ <issues
+ id="100"
+ kee="ABCDE-1"
+ component_id="401"
+ root_component_id="399"
+ rule_id="500"
+ severity="BLOCKER"
+ manual_severity="[false]"
+ message="[null]"
+ line="200"
+ effort_to_fix="4.2"
+ status="OPEN"
+ resolution="FIXED"
+ checksum="XXX"
+ reporter="arthur"
+ assignee="perceval"
+ author_login="[null]"
+ issue_attributes="JIRA=FOO-1234"
+ 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="2013-04-16"
+ />
+
+ <issues
+ id="101"
+ kee="ABCDE-2"
+ component_id="401"
+ root_component_id="399"
+ rule_id="500"
+ severity="BLOCKER"
+ manual_severity="[false]"
+ message="[null]"
+ line="200"
+ effort_to_fix="4.2"
+ status="OPEN"
+ resolution="FIXED"
+ checksum="XXX"
+ reporter="arthur"
+ assignee="perceval"
+ author_login="[null]"
+ issue_attributes="JIRA=FOO-1234"
+ 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="2013-04-16"
+ />
+
+
+ <!-- rule 501 -->
+ <issues
+ id="102"
+ kee="ABCDE-3"
+ component_id="401"
+ root_component_id="399"
+ rule_id="501"
+ severity="BLOCKER"
+ manual_severity="[false]"
+ message="[null]"
+ line="200"
+ effort_to_fix="4.2"
+ status="OPEN"
+ resolution="FIXED"
+ checksum="XXX"
+ reporter="arthur"
+ assignee="perceval"
+ author_login="[null]"
+ issue_attributes="JIRA=FOO-1234"
+ issue_creation_date="2014-04-16"
+ issue_update_date="2014-04-16"
+ issue_close_date="2014-04-16"
+ created_at="2014-04-16"
+ updated_at="2014-04-16"
+ />
+</dataset>
--- /dev/null
+<dataset>
+ <issues
+ id="100"
+ kee="ABCDE"
+ component_id="123"
+ root_component_id="101"
+ rule_id="200"
+ severity="BLOCKER"
+ manual_severity="[false]"
+ message="the message"
+ line="500"
+ effort_to_fix="3.14"
+ technical_debt="10"
+ status="RESOLVED"
+ resolution="FIXED"
+ checksum="123456789"
+ reporter="emmerik"
+ author_login="morgan"
+ assignee="karadoc"
+ issue_attributes="JIRA=FOO-1234"
+ issue_creation_date="2013-05-18"
+ issue_update_date="2013-05-19"
+ issue_close_date="2013-05-20"
+ created_at="[null]"
+ updated_at="2013-05-22"
+ action_plan_key="current_sprint"
+ />
+</dataset>
--- /dev/null
+<dataset>
+ <issues
+ id="100"
+ kee="ABCDE"
+ component_id="123"
+ root_component_id="100"
+ rule_id="200"
+ severity="INFO"
+ manual_severity="[false]"
+ message="old"
+ line="[null]"
+ effort_to_fix="[null]"
+ technical_debt="[null]"
+ status="OPEN"
+ resolution="[null]"
+ checksum="[null]"
+ reporter="[null]"
+ author_login="[null]"
+ assignee="[null]"
+ issue_attributes="[null]"
+ issue_creation_date="[null]"
+ issue_update_date="[null]"
+ issue_close_date="[null]"
+ created_at="[null]"
+ updated_at="2009-01-01"
+ action_plan_key="[null]"
+ />
+</dataset>
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
+
import java.io.Serializable;
import java.util.List;
import java.util.Map;
public List<Notification> sendChanges(DefaultIssue issue, IssueChangeContext context, IssueQueryResult queryResult) {
Map<DefaultIssue, Rule> issues = Maps.newHashMap();
issues.put(issue, queryResult.rule(issue));
- return sendChanges(issues, context, queryResult.project(issue), queryResult.component(issue));
+ return sendChanges(issue, context, queryResult.rule(issue), queryResult.project(issue), queryResult.component(issue));
+ }
+
+ @CheckForNull
+ public List<Notification> sendChanges(DefaultIssue issue, IssueChangeContext context, Rule rule, Component project, @Nullable Component component) {
+ Map<DefaultIssue, Rule> issues = Maps.newHashMap();
+ issues.put(issue, rule);
+ return sendChanges(issues, context, project, component);
}
@CheckForNull
return notification;
}
+ @CheckForNull
private String ruleName(@Nullable Rule rule) {
// this code should definitely be shared in api
if (rule == null) {
}
/**
- * @deprecated please use setRootComponent;
+ * @deprecated please use setRootComponent
*/
@Deprecated
public IssueDto setRootComponentId(Long rootComponentId) {
return ruleRepo;
}
+ public RuleKey getRuleKey(){
+ return RuleKey.of(ruleRepo, ruleKey);
+ }
+
public String getComponentKey() {
return componentKey;
}
/**
* Should only be used to persist in E/S
+ *
+ * Please use {@link #setRule(org.sonar.core.rule.RuleDto)} instead
*/
public IssueDto setRuleKey(String repo, String rule) {
this.ruleRepo = repo;
/**
* Should only be used to persist in E/S
+ *
+ * Please use {@link #setComponent(org.sonar.core.component.ComponentDto)} instead
*/
public IssueDto setComponentKey(String componentKey) {
this.componentKey = componentKey;
/**
* Should only be used to persist in E/S
+ *
+ * Please use {@link #setRootComponent(org.sonar.core.component.ComponentDto)} instead
*/
public IssueDto setRootComponentKey(String rootComponentKey) {
this.rootComponentKey = rootComponentKey;
issue.setComponentId(componentId);
issue.setProjectKey(rootComponentKey);
issue.setManualSeverity(manualSeverity);
- issue.setRuleKey(RuleKey.of(ruleRepo, ruleKey));
+ issue.setRuleKey(getRuleKey());
issue.setActionPlanKey(actionPlanKey);
issue.setAuthorLogin(authorLogin);
issue.setNew(false);
* This facade wraps db operations related to permissions
*
* Should be removed when batch will no more create permission, and be replaced by a new PermissionService in module server (probably be a merge with InternalPermissionService)
+ *
+ * WARNING, this class is called by Views to apply default permission template on new views
*/
public class PermissionFacade implements TaskComponent, ServerComponent {
/**
* @since 3.6
+ * @deprecated since 5.0
*/
+@Deprecated
public interface IssueQueryResult {
/**
* Non-null paginated list of issues.