]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5908 When creating a manual issue, assign it to the author of the line
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 12 Jan 2015 11:13:03 +0000 (12:13 +0100)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 12 Jan 2015 11:48:31 +0000 (12:48 +0100)
15 files changed:
server/sonar-server/src/main/java/org/sonar/server/exceptions/Message.java
server/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java
server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineIndex.java
server/sonar-server/src/main/java/org/sonar/server/user/UserService.java
server/sonar-server/src/main/java/org/sonar/server/user/index/UserDoc.java
server/sonar-server/src/main/java/org/sonar/server/user/index/UserIndex.java
server/sonar-server/src/main/java/org/sonar/server/user/index/UserIndexDefinition.java
server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/source/index/SourceLineIndexTest.java
server/sonar-server/src/test/java/org/sonar/server/user/UserServiceMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/user/index/UserIndexTest.java
server/sonar-server/src/test/resources/org/sonar/server/user/index/UserIndexTest/get_nullable_by_login.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/user/index/UserIndexTest/user1.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/user/index/UserIndexTest/user2.json [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueBuilder.java

index 38e6a6379f4ee305a8e79c4204ff4ac25e6d432b..80aa6ac7e6b361ab7cf4cba9e78424d2594278e2 100644 (file)
@@ -79,7 +79,7 @@ public class Message {
   public String toString() {
     return Objects.toStringHelper(this)
       .add("key", key)
-      .add("params", params)
+      .add("params", params != null ? Arrays.toString(params) : null)
       .toString();
   }
 }
index 2974678533ae3bf572dccf204570e5ac18fef3a4..6c83da09dde85d215ef5bad64f93b74cbdb0e25a 100644 (file)
@@ -55,16 +55,16 @@ import org.sonar.server.issue.index.IssueIndex;
 import org.sonar.server.search.FacetValue;
 import org.sonar.server.search.IndexClient;
 import org.sonar.server.search.QueryContext;
+import org.sonar.server.source.index.SourceLineDoc;
+import org.sonar.server.source.index.SourceLineIndex;
 import org.sonar.server.user.UserSession;
+import org.sonar.server.user.index.UserDoc;
+import org.sonar.server.user.index.UserIndex;
 
+import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 import static com.google.common.collect.Maps.newLinkedHashMap;
 
@@ -82,6 +82,8 @@ public class IssueService implements ServerComponent {
   private final IssueDao deprecatedIssueDao;
   private final UserFinder userFinder;
   private final PreviewCache dryRunCache;
+  private final UserIndex userIndex;
+  private final SourceLineIndex sourceLineIndex;
 
   public IssueService(DbClient dbClient, IndexClient indexClient,
     IssueWorkflow workflow,
@@ -92,7 +94,8 @@ public class IssueService implements ServerComponent {
     RuleFinder ruleFinder,
     IssueDao deprecatedIssueDao,
     UserFinder userFinder,
-    PreviewCache dryRunCache) {
+    PreviewCache dryRunCache,
+    UserIndex userIndex, SourceLineIndex sourceLineIndex) {
     this.dbClient = dbClient;
     this.indexClient = indexClient;
     this.workflow = workflow;
@@ -104,6 +107,8 @@ public class IssueService implements ServerComponent {
     this.deprecatedIssueDao = deprecatedIssueDao;
     this.userFinder = userFinder;
     this.dryRunCache = dryRunCache;
+    this.userIndex = userIndex;
+    this.sourceLineIndex = sourceLineIndex;
   }
 
   public List<String> listStatus() {
@@ -266,6 +271,7 @@ public class IssueService implements ServerComponent {
         .effortToFix(effortToFix)
         .ruleKey(ruleKey)
         .reporter(UserSession.get().login())
+        .assignee(findSourceLineUser(component.uuid(), line))
         .build();
 
       Date now = new Date();
@@ -374,4 +380,19 @@ public class IssueService implements ServerComponent {
   public Map<String, Long> listTagsForComponent(String componentUuid, int pageSize) {
     return indexClient.get(IssueIndex.class).listTagsForComponent(componentUuid, pageSize);
   }
+
+  @CheckForNull
+  private String findSourceLineUser(String fileUuid, @Nullable Integer line) {
+    if (line != null) {
+      SourceLineDoc sourceLine = sourceLineIndex.getLine(fileUuid, line);
+      String scmAuthor = sourceLine.scmAuthor();
+      if (!Strings.isNullOrEmpty(scmAuthor)) {
+        UserDoc userDoc = userIndex.getNullableByScmAccount(scmAuthor);
+        if (userDoc != null) {
+          return userDoc.login();
+        }
+      }
+    }
+    return null;
+  }
 }
index f3c84bb650ca9b1b8c5c6f477a4b96a411e8085b..0cbf88ebb1d5a9016286a030a2a018a161ee1834 100644 (file)
@@ -21,11 +21,13 @@ package org.sonar.server.source.index;
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
+import org.elasticsearch.action.search.SearchRequestBuilder;
 import org.elasticsearch.index.query.QueryBuilders;
 import org.elasticsearch.search.SearchHit;
 import org.elasticsearch.search.sort.SortOrder;
 import org.sonar.api.ServerComponent;
 import org.sonar.server.es.EsClient;
+import org.sonar.server.exceptions.NotFoundException;
 
 import java.util.List;
 
@@ -59,7 +61,7 @@ public class SourceLineIndex implements ServerComponent {
     }
     int toLimited = size + from - 1;
 
-    for (SearchHit hit: esClient.prepareSearch(SourceLineIndexDefinition.INDEX)
+    for (SearchHit hit : esClient.prepareSearch(SourceLineIndexDefinition.INDEX)
       .setTypes(SourceLineIndexDefinition.TYPE)
       .setSize(size)
       .setQuery(QueryBuilders.boolQuery()
@@ -74,4 +76,23 @@ public class SourceLineIndex implements ServerComponent {
 
     return lines;
   }
+
+  public SourceLineDoc getLine(String fileUuid, int line) {
+    Preconditions.checkArgument(line > 0, "Line should be greater than 0");
+    SearchRequestBuilder request = esClient.prepareSearch(SourceLineIndexDefinition.INDEX)
+      .setTypes(SourceLineIndexDefinition.TYPE)
+      .setSize(1)
+      .setQuery(QueryBuilders.boolQuery()
+        .must(QueryBuilders.termQuery(SourceLineIndexDefinition.FIELD_FILE_UUID, fileUuid))
+        .must(QueryBuilders.rangeQuery(SourceLineIndexDefinition.FIELD_LINE)
+          .gte(line)
+          .lte(line)))
+      .addSort(SourceLineIndexDefinition.FIELD_LINE, SortOrder.ASC);
+
+    SearchHit[] result = request.get().getHits().getHits();
+    if (result.length == 1) {
+      return new SourceLineDoc(result[0].sourceAsMap());
+    }
+    throw new NotFoundException(String.format("No source found on line %s for file '%s'", line, fileUuid));
+  }
 }
index e69d8c3e0d25f025b47ed04ef7e084894dbf6dce..11ccd0246d0f7ca9802c9a310c7c5260b7e50bfb 100644 (file)
@@ -62,6 +62,11 @@ public class UserService implements ServerComponent {
     return userIndex.getNullableByLogin(login);
   }
 
+  @CheckForNull
+  public UserDoc getNullableByScmAccount(String scmAccount) {
+    return userIndex.getNullableByScmAccount(scmAccount);
+  }
+
   public void index() {
     userIndexer.index();
   }
index d74f28bf1f8eacd362453048331a9bd9a1d89b44..84c98236a882bdef8157768430084144125ffe35 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.server.user.index;
 
+import org.sonar.api.user.User;
 import org.sonar.server.search.BaseDoc;
 
 import javax.annotation.Nullable;
@@ -26,7 +27,7 @@ import javax.annotation.Nullable;
 import java.util.List;
 import java.util.Map;
 
-public class UserDoc extends BaseDoc {
+public class UserDoc extends BaseDoc implements User {
 
   public UserDoc(Map<String, Object> fields) {
     super(fields);
index c9beb4b210c3e3ed6d7e667305554914e3c69e88..63ce49d84688afe2ac3faed5485b2506acabfdb5 100644 (file)
@@ -22,6 +22,9 @@ package org.sonar.server.user.index;
 
 import org.elasticsearch.action.get.GetRequestBuilder;
 import org.elasticsearch.action.get.GetResponse;
+import org.elasticsearch.action.search.SearchRequestBuilder;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.search.SearchHit;
 import org.sonar.api.ServerComponent;
 import org.sonar.server.es.EsClient;
 import org.sonar.server.exceptions.NotFoundException;
@@ -48,6 +51,22 @@ public class UserIndex implements ServerComponent {
     return null;
   }
 
+  @CheckForNull
+  public UserDoc getNullableByScmAccount(String scmAccount) {
+    SearchRequestBuilder request = esClient.prepareSearch(UserIndexDefinition.INDEX)
+      .setTypes(UserIndexDefinition.TYPE_USER)
+      .setQuery(QueryBuilders.boolQuery()
+        .should(QueryBuilders.termQuery(UserIndexDefinition.FIELD_LOGIN, scmAccount))
+        .should(QueryBuilders.termQuery(UserIndexDefinition.FIELD_EMAIL, scmAccount))
+        .should(QueryBuilders.termQuery(UserIndexDefinition.FIELD_SCM_ACCOUNTS, scmAccount)))
+      .setSize(1);
+    SearchHit[] result = request.get().getHits().getHits();
+    if (result.length == 1) {
+      return new UserDoc(result[0].sourceAsMap());
+    }
+    return null;
+  }
+
   public UserDoc getByLogin(String login) {
     UserDoc userDoc = getNullableByLogin(login);
     if (userDoc == null) {
index 1f87ef04133948618c0b2f9d18bfdbeeb78e3579..b988dd3143203b87bd3c239455a8e7f77c097d50 100644 (file)
@@ -62,13 +62,14 @@ public class UserIndexDefinition implements IndexDefinition {
     }
 
     // type "users"
-    NewIndex.NewIndexType issueMapping = index.createType(TYPE_USER);
-    issueMapping.setAttribute("_id", ImmutableMap.of("path", FIELD_LOGIN));
-    issueMapping.stringFieldBuilder(FIELD_NAME).build();
-    issueMapping.stringFieldBuilder(FIELD_EMAIL).enableSorting().build();
-    issueMapping.createDateTimeField(FIELD_CREATED_AT);
-    issueMapping.createDateTimeField(FIELD_UPDATED_AT);
-    issueMapping.createBooleanField(FIELD_ACTIVE);
-    issueMapping.stringFieldBuilder(FIELD_SCM_ACCOUNTS).build();
+    NewIndex.NewIndexType mapping = index.createType(TYPE_USER);
+    mapping.setAttribute("_id", ImmutableMap.of("path", FIELD_LOGIN));
+    mapping.stringFieldBuilder(FIELD_LOGIN).build();
+    mapping.stringFieldBuilder(FIELD_NAME).build();
+    mapping.stringFieldBuilder(FIELD_EMAIL).enableSorting().build();
+    mapping.createDateTimeField(FIELD_CREATED_AT);
+    mapping.createDateTimeField(FIELD_UPDATED_AT);
+    mapping.createBooleanField(FIELD_ACTIVE);
+    mapping.stringFieldBuilder(FIELD_SCM_ACCOUNTS).build();
   }
 }
index 405e97b9a7e430fbce4979064271818c82954a3a..cc3ffa6f4783c85e1437be6923877899b7ffeae3 100644 (file)
  */
 package org.sonar.server.issue;
 
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Multiset;
-import com.google.common.collect.Sets;
+import com.google.common.collect.*;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Test;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
 import org.sonar.api.issue.DefaultTransitions;
 import org.sonar.api.issue.Issue;
 import org.sonar.api.rule.RuleKey;
@@ -33,19 +33,16 @@ import org.sonar.api.rule.Severity;
 import org.sonar.api.security.DefaultGroups;
 import org.sonar.api.web.UserRole;
 import org.sonar.core.component.ComponentDto;
-import org.sonar.core.component.SnapshotDto;
 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.GroupDto;
 import org.sonar.core.user.UserDto;
 import org.sonar.server.component.ComponentTesting;
-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;
@@ -57,19 +54,27 @@ import org.sonar.server.permission.InternalPermissionService;
 import org.sonar.server.permission.PermissionChange;
 import org.sonar.server.rule.RuleTesting;
 import org.sonar.server.rule.db.RuleDao;
+import org.sonar.server.search.BaseNormalizer;
 import org.sonar.server.search.IndexClient;
 import org.sonar.server.search.QueryContext;
+import org.sonar.server.source.index.SourceLineDoc;
+import org.sonar.server.source.index.SourceLineIndexer;
+import org.sonar.server.source.index.SourceLineResultSetIterator;
 import org.sonar.server.tester.ServerTester;
 import org.sonar.server.user.MockUserSession;
+import org.sonar.server.user.NewUser;
+import org.sonar.server.user.UserService;
+import org.sonar.server.user.db.GroupDao;
 
 import java.util.Arrays;
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.entry;
 import static org.junit.Assert.fail;
-
+import static org.sonar.server.source.index.SourceLineIndexDefinition.*;
 
 public class IssueServiceMediumTest {
 
@@ -81,11 +86,6 @@ public class IssueServiceMediumTest {
   DbSession session;
   IssueService service;
 
-  RuleDto rule;
-  ComponentDto project;
-  ComponentDto file;
-  UserDto connectedUser;
-
   @Before
   public void setUp() throws Exception {
     tester.clearDbAndIndexes();
@@ -93,34 +93,6 @@ public class IssueServiceMediumTest {
     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 = ComponentTesting.newProjectDto();
-    tester.get(ComponentDao.class).insert(session, project);
-    SnapshotDto projectSnapshot = SnapshotTesting.createForProject(project);
-    tester.get(SnapshotDao.class).insert(session, projectSnapshot);
-
-    file = ComponentTesting.newFileDto(project);
-    tester.get(ComponentDao.class).insert(session, file);
-    tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForComponent(file, projectSnapshot));
-
-
-    // workaround for the test to have sufficient privileges
-    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();
-
-    // project can be seen by group "anyone"
-    tester.get(InternalPermissionService.class).addPermission(new PermissionChange().setComponentKey(project.getKey()).setGroup(DefaultGroups.ANYONE).setPermission(UserRole.USER));
   }
 
   @After
@@ -134,21 +106,22 @@ public class IssueServiceMediumTest {
 
   @Test
   public void get_by_key() throws Exception {
-    IssueDto issue = newIssue();
-    tester.get(IssueDao.class).insert(session, issue);
-    session.commit();
-    index();
+    RuleDto rule = newRule();
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+    IssueDto issue = saveIssue(IssueTesting.newDto(rule, file, project));
 
     assertThat(service.getByKey(issue.getKey())).isNotNull();
   }
 
   @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();
-    index();
+    RuleDto rule = newRule();
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+
+    saveIssue(IssueTesting.newDto(rule, file, project).setActionPlanKey("P1"));
+    saveIssue(IssueTesting.newDto(rule, file, project).setActionPlanKey("P2").setResolution("NONE"));
 
     org.sonar.server.search.Result<Issue> result = service.search(IssueQuery.builder().build(), new QueryContext());
     assertThat(result.getHits()).hasSize(2);
@@ -167,10 +140,10 @@ public class IssueServiceMediumTest {
 
   @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();
-    index();
+    RuleDto rule = newRule();
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+    IssueDto issue = saveIssue(IssueTesting.newDto(rule, file, project).setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_FALSE_POSITIVE));
 
     List<Transition> result = service.listTransitions(issue.getKey());
     assertThat(result).hasSize(1);
@@ -179,13 +152,12 @@ public class IssueServiceMediumTest {
 
   @Test
   public void do_transition() {
-    IssueDto issue = newIssue().setStatus(Issue.STATUS_OPEN);
-    tester.get(IssueDao.class).insert(session, issue);
-    session.commit();
-    index();
+    RuleDto rule = newRule();
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+    MockUserSession.set().setLogin("john");
 
-    assertThat(db.issueDao().selectByKey(session, issue.getKey())).isNotNull();
-    IssueTesting.assertIsEquivalent(issue, (IssueDoc) indexClient.get(IssueIndex.class).getByKey(issue.getKey()));
+    IssueDto issue = saveIssue(IssueTesting.newDto(rule, file, project).setStatus(Issue.STATUS_OPEN));
 
     assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).status()).isEqualTo(Issue.STATUS_OPEN);
 
@@ -196,8 +168,12 @@ public class IssueServiceMediumTest {
 
   @Test
   public void assign() {
-    IssueDto issue = newIssue();
-    tester.get(IssueDao.class).insert(session, issue);
+    RuleDto rule = newRule();
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+    MockUserSession.set().setLogin("john");
+
+    IssueDto issue = saveIssue(IssueTesting.newDto(rule, file, project));
 
     UserDto user = new UserDto().setLogin("perceval").setName("Perceval");
     db.userDao().insert(session, user);
@@ -213,8 +189,12 @@ public class IssueServiceMediumTest {
 
   @Test
   public void unassign() {
-    IssueDto issue = newIssue().setAssignee("perceval");
-    tester.get(IssueDao.class).insert(session, issue);
+    RuleDto rule = newRule();
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+    MockUserSession.set().setLogin("john");
+
+    IssueDto issue = saveIssue(IssueTesting.newDto(rule, file, project).setAssignee("perceval"));
 
     UserDto user = new UserDto().setLogin("perceval").setName("Perceval");
     db.userDao().insert(session, user);
@@ -230,10 +210,12 @@ public class IssueServiceMediumTest {
 
   @Test
   public void fail_to_assign_on_unknown_user() {
-    IssueDto issue = newIssue();
-    tester.get(IssueDao.class).insert(session, issue);
-    session.commit();
-    index();
+    RuleDto rule = newRule();
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+    MockUserSession.set().setLogin("john");
+
+    IssueDto issue = saveIssue(IssueTesting.newDto(rule, file, project));
 
     try {
       service.assign(issue.getKey(), "unknown");
@@ -245,8 +227,12 @@ public class IssueServiceMediumTest {
 
   @Test
   public void plan() {
-    IssueDto issue = newIssue();
-    tester.get(IssueDao.class).insert(session, issue);
+    RuleDto rule = newRule();
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+    MockUserSession.set().setLogin("john").addProjectPermissions(UserRole.USER, project.key());
+
+    IssueDto issue = saveIssue(IssueTesting.newDto(rule, file, project));
 
     String actionPlanKey = "EFGH";
     db.actionPlanDao().save(new ActionPlanDto().setKey(actionPlanKey).setProjectId(project.getId()));
@@ -262,13 +248,14 @@ public class IssueServiceMediumTest {
 
   @Test
   public void un_plan() {
+    RuleDto rule = newRule();
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+    MockUserSession.set().setLogin("john");
+
     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();
-    index();
+    IssueDto issue = saveIssue(IssueTesting.newDto(rule, file, project).setActionPlanKey(actionPlanKey));
 
     assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).actionPlanKey()).isEqualTo(actionPlanKey);
 
@@ -279,12 +266,14 @@ public class IssueServiceMediumTest {
 
   @Test
   public void fail_plan_if_action_plan_not_found() {
-    tester.get(IssueDao.class).insert(session, newIssue());
-    session.commit();
-    index();
+    RuleDto rule = newRule();
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+    MockUserSession.set().setLogin("john");
 
+    IssueDto issue = saveIssue(IssueTesting.newDto(rule, file, project));
     try {
-      service.plan("ABCD", "unknown");
+      service.plan(issue.getKey(), "unknown");
       fail();
     } catch (Exception e) {
       assertThat(e).isInstanceOf(NotFoundException.class).hasMessage("Unknown action plan: unknown");
@@ -293,10 +282,12 @@ public class IssueServiceMediumTest {
 
   @Test
   public void set_severity() {
-    IssueDto issue = newIssue().setSeverity(Severity.BLOCKER);
-    tester.get(IssueDao.class).insert(session, issue);
-    session.commit();
-    index();
+    RuleDto rule = newRule();
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+    MockUserSession.set().setLogin("john").addProjectPermissions(UserRole.ISSUE_ADMIN, project.key());
+
+    IssueDto issue = saveIssue(IssueTesting.newDto(rule, file, project).setSeverity(Severity.BLOCKER));
 
     assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).severity()).isEqualTo(Severity.BLOCKER);
 
@@ -307,30 +298,65 @@ public class IssueServiceMediumTest {
 
   @Test
   public void create_manual_issue() {
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+    MockUserSession.set().setLogin("john").addProjectPermissions(UserRole.USER, project.key());
+
+    RuleDto manualRule = RuleTesting.newManualRule("manualRuleKey");
+    tester.get(RuleDao.class).insert(session, manualRule);
+    session.commit();
+
+    Issue result = service.createManualIssue(file.key(), manualRule.getKey(), null, "Fix it", Severity.MINOR, 2d);
+
+    IssueDoc manualIssue = (IssueDoc) indexClient.get(IssueIndex.class).getByKey(result.key());
+    assertThat(manualIssue.componentUuid()).isEqualTo(file.uuid());
+    assertThat(manualIssue.projectUuid()).isEqualTo(project.uuid());
+    assertThat(manualIssue.ruleKey()).isEqualTo(manualRule.getKey());
+    assertThat(manualIssue.message()).isEqualTo("Fix it");
+    assertThat(manualIssue.line()).isNull();
+    assertThat(manualIssue.severity()).isEqualTo(Severity.MINOR);
+    assertThat(manualIssue.effortToFix()).isEqualTo(2d);
+    assertThat(manualIssue.reporter()).isEqualTo("john");
+  }
+
+  @Test
+  public void create_manual_issue_on_line() {
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+    newSourceLine(file, 1, "arthur");
+    createDefaultGroup();
+    newUser("arthur");
+    MockUserSession.set().setLogin("john").addProjectPermissions(UserRole.USER, project.key());
+
     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 result = service.createManualIssue(file.key(), manualRule.getKey(), 1, "Fix it", Severity.MINOR, 2d);
 
     IssueDoc manualIssue = (IssueDoc) indexClient.get(IssueIndex.class).getByKey(result.key());
     assertThat(manualIssue.componentUuid()).isEqualTo(file.uuid());
     assertThat(manualIssue.projectUuid()).isEqualTo(project.uuid());
     assertThat(manualIssue.ruleKey()).isEqualTo(manualRule.getKey());
     assertThat(manualIssue.message()).isEqualTo("Fix it");
-    assertThat(manualIssue.line()).isEqualTo(10);
+    assertThat(manualIssue.line()).isEqualTo(1);
     assertThat(manualIssue.severity()).isEqualTo(Severity.MINOR);
     assertThat(manualIssue.effortToFix()).isEqualTo(2d);
-    assertThat(manualIssue.reporter()).isEqualTo(connectedUser.getLogin());
+    assertThat(manualIssue.reporter()).isEqualTo("john");
+    assertThat(manualIssue.assignee()).isEqualTo("arthur");
   }
 
   @Test
   public void create_manual_issue_with_major_severity_when_no_severity() {
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+    MockUserSession.set().setLogin("john").addProjectPermissions(UserRole.USER, project.key());
+
     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 result = service.createManualIssue(file.key(), manualRule.getKey(), null, "Fix it", null, 2d);
 
     Issue manualIssue = indexClient.get(IssueIndex.class).getByKey(result.key());
     assertThat(manualIssue.severity()).isEqualTo(Severity.MAJOR);
@@ -338,20 +364,67 @@ public class IssueServiceMediumTest {
 
   @Test
   public void create_manual_issue_with_rule_name_when_no_message() {
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+    MockUserSession.set().setLogin("john").addProjectPermissions(UserRole.USER, project.key());
+
     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 result = service.createManualIssue(file.key(), manualRule.getKey(), null, null, null, 2d);
 
     Issue manualIssue = indexClient.get(IssueIndex.class).getByKey(result.key());
     assertThat(manualIssue.message()).isEqualTo("Manual rule name");
   }
 
+  @Test
+  public void create_manual_issue_without_assignee_when_scm_author_do_not_match_user() {
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+    // Unknown SCM account
+    newSourceLine(file, 1, "unknown");
+    createDefaultGroup();
+    newUser("arthur");
+    MockUserSession.set().setLogin("john").addProjectPermissions(UserRole.USER, project.key());
+
+    RuleDto manualRule = RuleTesting.newManualRule("manualRuleKey");
+    tester.get(RuleDao.class).insert(session, manualRule);
+    session.commit();
+
+    Issue result = service.createManualIssue(file.key(), manualRule.getKey(), 1, "Fix it", Severity.MINOR, 2d);
+
+    IssueDoc manualIssue = (IssueDoc) indexClient.get(IssueIndex.class).getByKey(result.key());
+    assertThat(manualIssue.assignee()).isNull();
+  }
+
+  @Test
+  public void create_manual_issue_without_assignee_when_no_scm_author_on_line() {
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+    // No author on line 1
+    newSourceLine(file, 1, "");
+    MockUserSession.set().setLogin("john").addProjectPermissions(UserRole.USER, project.key());
+
+    RuleDto manualRule = RuleTesting.newManualRule("manualRuleKey");
+    tester.get(RuleDao.class).insert(session, manualRule);
+    session.commit();
+
+    Issue result = service.createManualIssue(file.key(), manualRule.getKey(), 1, "Fix it", Severity.MINOR, 2d);
+
+    IssueDoc manualIssue = (IssueDoc) indexClient.get(IssueIndex.class).getByKey(result.key());
+    assertThat(manualIssue.assignee()).isNull();
+  }
+
   @Test
   public void fail_create_manual_issue_on_not_manual_rule() {
+    RuleDto rule = newRule();
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+    MockUserSession.set().setLogin("john").addProjectPermissions(UserRole.USER, project.key());
+
     try {
-      service.createManualIssue(file.key(), rule.getKey(), 10, "Fix it", null, 2d);
+      service.createManualIssue(file.key(), rule.getKey(), null, "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");
@@ -360,17 +433,21 @@ public class IssueServiceMediumTest {
 
   @Test(expected = IllegalArgumentException.class)
   public void fail_create_manual_issue_if_rule_does_not_exists() {
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+    MockUserSession.set().setLogin("john").addProjectPermissions(UserRole.USER, project.key());
+
     service.createManualIssue(file.key(), RuleKey.of("rule", "unknown"), 10, "Fix it", null, 2d);
   }
 
   @Test(expected = ForbiddenException.class)
   public void fail_create_manual_issue_if_not_having_required_role() {
+    RuleDto rule = newRule();
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+
     // 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());
+    MockUserSession.set().setLogin("john").addProjectPermissions(UserRole.CODEVIEWER, project.key());
 
     RuleDto manualRule = RuleTesting.newManualRule("manualRuleKey");
     tester.get(RuleDao.class).insert(session, manualRule);
@@ -381,10 +458,13 @@ public class IssueServiceMediumTest {
 
   @Test
   public void find_rules_by_component() throws Exception {
+    RuleDto rule = newRule();
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+
     // 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();
+    saveIssue(IssueTesting.newDto(rule, file, project));
+    saveIssue(IssueTesting.newDto(rule, file, project));
 
     RulesAggregation result = service.findRulesByComponent(file.key(), null, session);
     assertThat(result.rules()).hasSize(1);
@@ -392,10 +472,13 @@ public class IssueServiceMediumTest {
 
   @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();
+    RuleDto rule = newRule();
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+
+    saveIssue(IssueTesting.newDto(rule, file, project).setSeverity(Severity.MAJOR));
+    saveIssue(IssueTesting.newDto(rule, file, project).setSeverity(Severity.MAJOR));
+    saveIssue(IssueTesting.newDto(rule, file, project).setSeverity(Severity.INFO));
 
     Multiset<String> result = service.findSeveritiesByComponent(file.key(), null, session);
     assertThat(result.count("MAJOR")).isEqualTo(2);
@@ -405,10 +488,10 @@ public class IssueServiceMediumTest {
 
   @Test
   public void search_issues() {
-    IssueDto issue = newIssue();
-    tester.get(IssueDao.class).insert(session, issue);
-    session.commit();
-    index();
+    RuleDto rule = newRule();
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+    saveIssue(IssueTesting.newDto(rule, file, project));
 
     List<Issue> result = service.search(IssueQuery.builder().build(), new QueryContext()).getHits();
     assertThat(result).hasSize(1);
@@ -416,13 +499,13 @@ public class IssueServiceMediumTest {
 
   @Test
   public void find_issue_assignees() throws Exception {
-    db.issueDao().insert(session,
-      IssueTesting.newDto(rule, file, project).setAssignee("steph"),
-      IssueTesting.newDto(rule, file, project).setAssignee("simon"),
-      IssueTesting.newDto(rule, file, project),
-      IssueTesting.newDto(rule, file, project).setAssignee("steph"));
-    session.commit();
-    index();
+    RuleDto rule = newRule();
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+    saveIssue(IssueTesting.newDto(rule, file, project).setAssignee("steph"));
+    saveIssue(IssueTesting.newDto(rule, file, project).setAssignee("simon"));
+    saveIssue(IssueTesting.newDto(rule, file, project));
+    saveIssue(IssueTesting.newDto(rule, file, project).setAssignee("steph"));
 
     Map<String, Long> results = service.findIssueAssignees(IssueQuery.builder().build());
 
@@ -436,19 +519,15 @@ public class IssueServiceMediumTest {
     assertThat(results.keySet().toArray()[2]).isNull();
   }
 
-  private IssueDto newIssue() {
-    return IssueTesting.newDto(rule, file, project);
-  }
-
   @Test
   public void list_tags() {
-    db.issueDao().insert(session,
-      IssueTesting.newDto(rule, file, project).setTags(ImmutableSet.of("convention", "java8", "bug")),
-      IssueTesting.newDto(rule, file, project).setTags(ImmutableSet.of("convention", "bug")),
-      IssueTesting.newDto(rule, file, project),
-      IssueTesting.newDto(rule, file, project).setTags(ImmutableSet.of("convention")));
-    session.commit();
-    index();
+    RuleDto rule = newRule();
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+    saveIssue(IssueTesting.newDto(rule, file, project).setTags(ImmutableSet.of("convention", "java8", "bug")));
+    saveIssue(IssueTesting.newDto(rule, file, project).setTags(ImmutableSet.of("convention", "bug")));
+    saveIssue(IssueTesting.newDto(rule, file, project));
+    saveIssue(IssueTesting.newDto(rule, file, project).setTags(ImmutableSet.of("convention")));
 
     assertThat(service.listTags(null, 5)).containsOnly("convention", "java8", "bug");
     assertThat(service.listTags(null, 2)).containsOnly("bug", "convention");
@@ -459,11 +538,12 @@ public class IssueServiceMediumTest {
 
   @Test
   public void set_tags() {
-    IssueDto issue = newIssue();
-    tester.get(IssueDao.class).insert(session, issue);
+    RuleDto rule = newRule();
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+    MockUserSession.set().setLogin("john");
 
-    session.commit();
-    index();
+    IssueDto issue = saveIssue(IssueTesting.newDto(rule, file, project));
 
     assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).tags()).isEmpty();
 
@@ -493,18 +573,77 @@ public class IssueServiceMediumTest {
 
   @Test
   public void list_component_tags() {
-    db.issueDao().insert(session,
-      IssueTesting.newDto(rule, file, project).setTags(ImmutableSet.of("convention", "java8", "bug")),
-      IssueTesting.newDto(rule, file, project).setTags(ImmutableSet.of("convention", "bug")),
-      IssueTesting.newDto(rule, file, project),
-      IssueTesting.newDto(rule, file, project).setTags(ImmutableSet.of("convention", "java8", "bug")).setResolution(Issue.RESOLUTION_FIXED),
-      IssueTesting.newDto(rule, file, project).setTags(ImmutableSet.of("convention")));
-
-    session.commit();
-    index();
+    RuleDto rule = newRule();
+    ComponentDto project = newProject();
+    ComponentDto file = newFile(project);
+    saveIssue(IssueTesting.newDto(rule, file, project).setTags(ImmutableSet.of("convention", "java8", "bug")));
+    saveIssue(IssueTesting.newDto(rule, file, project).setTags(ImmutableSet.of("convention", "bug")));
+    saveIssue(IssueTesting.newDto(rule, file, project));
+    saveIssue(IssueTesting.newDto(rule, file, project).setTags(ImmutableSet.of("convention", "java8", "bug")).setResolution(Issue.RESOLUTION_FIXED));
+    saveIssue(IssueTesting.newDto(rule, file, project).setTags(ImmutableSet.of("convention")));
 
     assertThat(service.listTagsForComponent(project.uuid(), 5)).contains(entry("convention", 3L), entry("bug", 2L), entry("java8", 1L));
     assertThat(service.listTagsForComponent(project.uuid(), 2)).contains(entry("convention", 3L), entry("bug", 2L)).doesNotContainEntry("java8", 1L);
     assertThat(service.listTagsForComponent("other", 10)).isEmpty();
   }
+
+  private RuleDto newRule() {
+    RuleDto rule = RuleTesting.newXooX1();
+    tester.get(RuleDao.class).insert(session, rule);
+    session.commit();
+    return rule;
+  }
+
+  private ComponentDto newProject() {
+    ComponentDto project = ComponentTesting.newProjectDto();
+    tester.get(ComponentDao.class).insert(session, project);
+
+    MockUserSession.set().setLogin("admin").addProjectPermissions(UserRole.USER, project.key()).setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+    session.commit();
+
+    // project can be seen by group "anyone"
+    tester.get(InternalPermissionService.class).addPermission(new PermissionChange().setComponentKey(project.getKey()).setGroup(DefaultGroups.ANYONE).setPermission(UserRole.USER));
+    MockUserSession.set();
+
+    return project;
+  }
+
+  private ComponentDto newFile(ComponentDto project) {
+    ComponentDto file = ComponentTesting.newFileDto(project);
+    tester.get(ComponentDao.class).insert(session, file);
+    session.commit();
+    return file;
+  }
+
+  private IssueDto saveIssue(IssueDto issue) {
+    tester.get(IssueDao.class).insert(session, issue);
+    session.commit();
+    tester.get(IssueIndexer.class).indexAll();
+    return issue;
+  }
+
+  private void newSourceLine(ComponentDto file, int line, String scmAuthor) {
+    SourceLineDoc line1 = new SourceLineDoc(ImmutableMap.<String, Object>builder()
+      .put(FIELD_PROJECT_UUID, file.projectUuid())
+      .put(FIELD_FILE_UUID, file.uuid())
+      .put(FIELD_LINE, line)
+      .put(BaseNormalizer.UPDATED_AT_FIELD, new Date())
+      .put(FIELD_SCM_AUTHOR, scmAuthor)
+      .build());
+    SourceLineResultSetIterator.SourceFile sourceFile = new SourceLineResultSetIterator.SourceFile(file.uuid(), System.currentTimeMillis());
+    sourceFile.addLine(line1);
+    tester.get(SourceLineIndexer.class).index(Iterators.singletonIterator(sourceFile));
+  }
+
+  private void newUser(String login) {
+    MockUserSession.set().setLogin("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+    tester.get(UserService.class).create(NewUser.create().setLogin(login).setName(login).setPassword("test").setPasswordConfirmation("test"));
+    MockUserSession.set();
+  }
+
+  private void createDefaultGroup() {
+    tester.get(Settings.class).setProperty(CoreProperties.CORE_DEFAULT_GROUP, "sonar-users");
+    tester.get(GroupDao.class).insert(session, new GroupDto().setName("sonar-users").setDescription("Sonar Users"));
+    session.commit();
+  }
 }
index 71044d301ed12ded1390272a85cb4e9fdb020a8c..74dd63e4f748d2b3912de999833b939183cea1fe 100644 (file)
@@ -24,6 +24,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.config.Settings;
 import org.sonar.server.es.EsTester;
+import org.sonar.server.exceptions.NotFoundException;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -63,4 +64,47 @@ public class SourceLineIndexTest {
   public void should_reject_to_less_than_from() {
     index.getLines("polop", 2, 1);
   }
+
+  @Test
+  public void get_line() throws Exception {
+    es.putDocuments(SourceLineIndexDefinition.INDEX, SourceLineIndexDefinition.TYPE,
+      this.getClass(),
+      "file1_line1.json",
+      "file1_line2.json"
+      );
+    assertThat(index.getLine("file1", 1)).isNotNull();
+    assertThat(index.getLine("file1", 2)).isNotNull();
+  }
+
+  @Test
+  public void fail_to_get_line_when_line_is_not_greater_than_0() throws Exception {
+    try {
+      index.getLine("file1", 0);
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Line should be greater than 0");
+    }
+  }
+
+  @Test
+  public void fail_to_get_line_on_unknown_line() throws Exception {
+    es.putDocuments(SourceLineIndexDefinition.INDEX, SourceLineIndexDefinition.TYPE,
+      this.getClass(),
+      "file1_line1.json",
+      "file1_line2.json"
+      );
+    try {
+      index.getLine("file1", 1);
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(NotFoundException.class).hasMessage("No source found on line 5 for file 'file1'");
+    }
+  }
+
+  @Test
+  public void fail_to_get_line_on_unknown_file() throws Exception {
+    try {
+      index.getLine("file1", 1);
+    } catch (Exception e) {
+      assertThat(e).isInstanceOf(NotFoundException.class).hasMessage("No source found on line 1 for file 'file1'");
+    }
+  }
 }
index 578bf64518d9fb1c21ec30dfe53821dbc5961517..58b84c8ef386aa009f6131833253b4759b6f13c6 100644 (file)
@@ -155,40 +155,25 @@ public class UserServiceMediumTest {
 
   @Test
   public void get_nullable_by_login() throws Exception {
-    MockUserSession.set().setLogin("john").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-    GroupDto userGroup = new GroupDto().setName(CoreProperties.CORE_DEFAULT_GROUP_DEFAULT_VALUE);
-    dbClient.groupDao().insert(session, userGroup);
-    session.commit();
-
-    service.create(NewUser.create()
-      .setLogin("user")
-      .setName("User")
-      .setEmail("user@mail.com")
-      .setPassword("password")
-      .setPasswordConfirmation("password")
-      .setScmAccounts(newArrayList("u1", "u_1")));
+    createSampleUser();
 
     assertThat(service.getNullableByLogin("user")).isNotNull();
   }
 
   @Test
   public void get_by_login() throws Exception {
-    MockUserSession.set().setLogin("john").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-    GroupDto userGroup = new GroupDto().setName(CoreProperties.CORE_DEFAULT_GROUP_DEFAULT_VALUE);
-    dbClient.groupDao().insert(session, userGroup);
-    session.commit();
-
-    service.create(NewUser.create()
-      .setLogin("user")
-      .setName("User")
-      .setEmail("user@mail.com")
-      .setPassword("password")
-      .setPasswordConfirmation("password")
-      .setScmAccounts(newArrayList("u1", "u_1")));
+    createSampleUser();
 
     assertThat(service.getByLogin("user")).isNotNull();
   }
 
+  @Test
+  public void get_nullable_by_scm_account() throws Exception {
+    createSampleUser();
+
+    assertThat(service.getNullableByScmAccount("u1")).isNotNull();
+  }
+
   @Test
   public void index() throws Exception {
     UserDto userDto = new UserDto().setLogin("user").setEmail("user@mail.com").setCreatedAt(System.currentTimeMillis()).setUpdatedAt(System.currentTimeMillis());
@@ -200,4 +185,21 @@ public class UserServiceMediumTest {
     assertThat(esClient.prepareGet(UserIndexDefinition.INDEX, UserIndexDefinition.TYPE_USER, "user").get().isExists()).isTrue();
   }
 
+  private void createSampleUser() {
+    MockUserSession.set().setLogin("john").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+    GroupDto userGroup = new GroupDto().setName(CoreProperties.CORE_DEFAULT_GROUP_DEFAULT_VALUE);
+    dbClient.groupDao().insert(session, userGroup);
+    session.commit();
+
+    service.create(NewUser.create()
+      .setLogin("user")
+      .setName("User")
+      .setEmail("user@mail.com")
+      .setPassword("password")
+      .setPasswordConfirmation("password")
+      .setScmAccounts(newArrayList("u1", "u_1")));
+
+    MockUserSession.set().setLogin("john");
+  }
+
 }
index 096e4076bae94576eb75d512a265eb17a9c4444a..f795df89b0a4341e17e8ae19ad2a8e23829c725e 100644 (file)
@@ -44,7 +44,7 @@ public class UserIndexTest {
 
   @Test
   public void get_nullable_by_login() throws Exception {
-    esTester.putDocuments(UserIndexDefinition.INDEX, UserIndexDefinition.TYPE_USER, this.getClass(), "get_nullable_by_login.json");
+    esTester.putDocuments(UserIndexDefinition.INDEX, UserIndexDefinition.TYPE_USER, this.getClass(), "user1.json", "user2.json");
 
     UserDoc userDoc = index.getNullableByLogin("user1");
     assertThat(userDoc).isNotNull();
@@ -61,7 +61,7 @@ public class UserIndexTest {
 
   @Test
   public void get_nullable_by_login_should_be_case_sensitive() throws Exception {
-    esTester.putDocuments(UserIndexDefinition.INDEX, UserIndexDefinition.TYPE_USER, this.getClass(), "get_nullable_by_login.json");
+    esTester.putDocuments(UserIndexDefinition.INDEX, UserIndexDefinition.TYPE_USER, this.getClass(), "user1.json");
 
     assertThat(index.getNullableByLogin("user1")).isNotNull();
     assertThat(index.getNullableByLogin("User1")).isNull();
@@ -69,7 +69,7 @@ public class UserIndexTest {
 
   @Test
   public void get_by_login() throws Exception {
-    esTester.putDocuments(UserIndexDefinition.INDEX, UserIndexDefinition.TYPE_USER, this.getClass(), "get_nullable_by_login.json");
+    esTester.putDocuments(UserIndexDefinition.INDEX, UserIndexDefinition.TYPE_USER, this.getClass(), "user1.json", "user2.json");
 
     UserDoc userDoc = index.getByLogin("user1");
     assertThat(userDoc).isNotNull();
@@ -92,4 +92,15 @@ public class UserIndexTest {
     }
   }
 
+  @Test
+  public void get_nullable_by_scm_account() throws Exception {
+    esTester.putDocuments(UserIndexDefinition.INDEX, UserIndexDefinition.TYPE_USER, this.getClass(), "user1.json", "user2.json");
+
+    assertThat(index.getNullableByScmAccount("user_1").login()).isEqualTo("user1");
+    assertThat(index.getNullableByScmAccount("user1@mail.com").login()).isEqualTo("user1");
+    assertThat(index.getNullableByScmAccount("user1").login()).isEqualTo("user1");
+
+    assertThat(index.getNullableByScmAccount("unknown")).isNull();
+  }
+
 }
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/user/index/UserIndexTest/get_nullable_by_login.json b/server/sonar-server/src/test/resources/org/sonar/server/user/index/UserIndexTest/get_nullable_by_login.json
deleted file mode 100644 (file)
index 7c29066..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "login": "user1",
-  "name": "User1",
-  "email": "user1@mail.com",
-  "active": true,
-  "scmAccounts": ["user_1", "u1"],
-  "createdAt": 1500000000000,
-  "updatedAt": 1500000000000
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/user/index/UserIndexTest/user1.json b/server/sonar-server/src/test/resources/org/sonar/server/user/index/UserIndexTest/user1.json
new file mode 100644 (file)
index 0000000..7c29066
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "login": "user1",
+  "name": "User1",
+  "email": "user1@mail.com",
+  "active": true,
+  "scmAccounts": ["user_1", "u1"],
+  "createdAt": 1500000000000,
+  "updatedAt": 1500000000000
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/user/index/UserIndexTest/user2.json b/server/sonar-server/src/test/resources/org/sonar/server/user/index/UserIndexTest/user2.json
new file mode 100644 (file)
index 0000000..bfac5d4
--- /dev/null
@@ -0,0 +1,10 @@
+{
+  "login": "user2",
+  "name": "User2",
+  "email": "user2@mail.com",
+  "active": true,
+  "scmAccounts": ["u2"],
+  "createdAt": 1500000000000,
+  "updatedAt": 1500000000000
+}
+
index e81ae5448b6938dfc905e85ad66ccbd13952d586..3c39b5daddefc4097cf5145091e8d006f58feae6 100644 (file)
@@ -28,6 +28,7 @@ import org.sonar.api.rule.RuleKey;
 import org.sonar.api.utils.internal.Uuids;
 
 import javax.annotation.Nullable;
+
 import java.util.Map;
 
 public class DefaultIssueBuilder implements Issuable.IssueBuilder {
@@ -40,6 +41,7 @@ public class DefaultIssueBuilder implements Issuable.IssueBuilder {
   private String severity;
   private Double effortToFix;
   private String reporter;
+  private String assignee;
   private Map<String, String> attributes;
 
   public DefaultIssueBuilder() {
@@ -92,6 +94,11 @@ public class DefaultIssueBuilder implements Issuable.IssueBuilder {
     return this;
   }
 
+  public DefaultIssueBuilder assignee(@Nullable String s) {
+    this.assignee = s;
+    return this;
+  }
+
   @Override
   public DefaultIssueBuilder attribute(String key, @Nullable String value) {
     if (attributes == null) {
@@ -119,6 +126,7 @@ public class DefaultIssueBuilder implements Issuable.IssueBuilder {
     issue.setEffortToFix(effortToFix);
     issue.setLine(line);
     issue.setReporter(reporter);
+    issue.setAssignee(assignee);
     issue.setAttributes(attributes);
     issue.setResolution(null);
     issue.setStatus(Issue.STATUS_OPEN);