blob: 80bedcdd6bdf7eb6e012c1eb4fe46b5ea7d4106e [file] [log] [blame]
// Copyright (C) 2013 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.acceptance.rest.change;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allow;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowCapability;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.block;
import static com.google.gerrit.entities.Permission.READ;
import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static java.util.stream.Collectors.toList;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.config.GerritConfig;
import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.api.accounts.EmailInput;
import com.google.gerrit.extensions.api.changes.ReviewerInput;
import com.google.gerrit.extensions.client.ReviewerState;
import com.google.gerrit.extensions.common.ChangeInput;
import com.google.gerrit.extensions.common.SuggestedReviewerInfo;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.inject.Inject;
import java.util.List;
import java.util.Set;
import java.util.stream.IntStream;
import org.junit.Before;
import org.junit.Test;
public class SuggestReviewersIT extends AbstractDaemonTest {
@Inject private AccountOperations accountOperations;
@Inject private GroupOperations groupOperations;
@Inject private ProjectOperations projectOperations;
@Inject private RequestScopeOperations requestScopeOperations;
private AccountGroup.UUID group1;
private AccountGroup.UUID group2;
private AccountGroup.UUID group3;
private TestAccount user1;
private TestAccount user2;
private TestAccount user3;
private TestAccount user4;
@Before
public void setUp() throws Exception {
user1 = user("user1", "First1 Last1");
user2 = user("user2", "First2 Last2");
user3 = user("user3", "First3 Last3");
user4 = user("jdoe", "John Doe", "JDOE");
group1 =
groupOperations.newGroup().name(name("users1")).members(user1.id(), user3.id()).create();
group2 =
groupOperations.newGroup().name(name("users2")).members(user2.id(), user3.id()).create();
group3 = groupOperations.newGroup().name(name("users3")).members(user1.id()).create();
}
@Test
@GerritConfig(name = "suggest.accounts", value = "false")
public void suggestReviewers_withSuggestDisabled() throws Exception {
String changeId = createChange().getChangeId();
List<SuggestedReviewerInfo> reviewers = suggestReviewers(changeId, name("u"), 6);
assertThat(reviewers).isEmpty();
}
@Test
@GerritConfig(name = "accounts.visibility", value = "NONE")
public void suggestReviewers_accountVisibilityNone_noAccountsSuggested() throws Exception {
// Change is created by admin
String changeId = createChange().getChangeId();
requestScopeOperations.setApiUser(user2.id());
List<SuggestedReviewerInfo> reviewers = suggestReviewers(changeId, name("u"), 6);
assertThat(reviewers).isEmpty();
}
@Test
@GerritConfig(name = "suggest.from", value = "1")
@GerritConfig(name = "accounts.visibility", value = "NONE")
public void suggestReviewers_accountVisibilityNone_withSuggestFrom_noAccountsSuggested()
throws Exception {
// Change is created by admin
String changeId = createChange().getChangeId();
requestScopeOperations.setApiUser(user2.id());
List<SuggestedReviewerInfo> reviewers = suggestReviewers(changeId, name("u"), 6);
assertThat(reviewers).isEmpty();
}
@Test
@GerritConfig(name = "accounts.visibility", value = "NONE")
public void suggestReviewers_accountVisibilityNone_withGlobalCapability_allAccountsSuggested()
throws Exception {
projectOperations
.allProjectsForUpdate()
.add(allowCapability(GlobalCapability.VIEW_ALL_ACCOUNTS).group(REGISTERED_USERS))
.update();
String changeId = createChange().getChangeId();
requestScopeOperations.setApiUser(user2.id());
List<SuggestedReviewerInfo> reviewers = suggestReviewers(changeId, name("u"), 6);
assertReviewers(reviewers, ImmutableList.of(user1, user2, user3), ImmutableList.of(group2));
}
@Test
public void suggestReviewersChange() throws Exception {
String changeId = createChange().getChangeId();
testSuggestReviewersChange(changeId);
}
@Test
public void suggestReviewersPrivateChange() throws Exception {
String changeId = createChange().getChangeId();
gApi.changes().id(changeId).setPrivate(true, null);
testSuggestReviewersChange(changeId);
}
public void testSuggestReviewersChange(String changeId) throws Exception {
List<SuggestedReviewerInfo> reviewers = suggestReviewers(changeId, name("u"), 6);
assertReviewers(
reviewers, ImmutableList.of(user1, user2, user3), ImmutableList.of(group1, group2, group3));
reviewers = suggestReviewers(changeId, name("u"), 5);
assertReviewers(
reviewers, ImmutableList.of(user1, user2, user3), ImmutableList.of(group1, group2));
String group3Name = groupOperations.group(group3).get().name();
reviewers = suggestReviewers(changeId, group3Name, 10);
assertReviewers(reviewers, ImmutableList.of(), ImmutableList.of(group3));
// Suggested accounts are ordered by activity. All users have no activity,
// hence we don't know which of the matching accounts we get when the query
// is limited to 1.
reviewers = suggestReviewers(changeId, name("u"), 1);
assertThat(reviewers).hasSize(1);
assertThat(reviewers.get(0).account).isNotNull();
assertThat(ImmutableList.of(reviewers.get(0).account._accountId))
.containsAnyIn(
ImmutableList.of(user1, user2, user3).stream()
.map(u -> u.id().get())
.collect(toList()));
}
@Test
@GerritConfig(name = "index.maxTerms", value = "20")
public void suggestReviewersTooManyQueryTerms() throws Exception {
String changeId = createChange().getChangeId();
// Do a query which doesn't exceed index.maxTerms succeeds (add only 9 terms, since on
// 'inactive:1' term is implicitly added) and assert that a result is returned
StringBuilder query = new StringBuilder();
for (int i = 1; i <= 9; i++) {
query.append(name("u")).append(" ");
}
// The query expands to (2 * predicates + 1) terms = 2 * 9 + 1 = 19:
// (2 * predicates) since the default predicate expands to two "name" OR "username" predicates.
// + 1 since the query processor appends a predicate to search for active accounts only.
assertThat(suggestReviewers(changeId, query.toString())).isNotEmpty();
// Do a query which exceed index.maxTerms succeeds (10 * 2 terms plus 'inactive:1' term which is
// implicitly added).
query.append(name("u"));
BadRequestException exception =
assertThrows(BadRequestException.class, () -> suggestReviewers(changeId, query.toString()));
assertThat(exception)
.hasMessageThat()
.isEqualTo("too many terms in query: 21 terms (max = 20)");
}
@Test
public void suggestReviewersWithExcludeGroups() throws Exception {
String changeId = createChange().getChangeId();
// by default groups are included
List<SuggestedReviewerInfo> reviewers = suggestReviewers(changeId, name("user"));
assertReviewers(
reviewers, ImmutableList.of(user1, user2, user3), ImmutableList.of(group1, group2, group3));
// exclude groups
reviewers =
gApi.changes().id(changeId).suggestReviewers(name("user")).excludeGroups(true).get();
assertReviewers(reviewers, ImmutableList.of(user1, user2, user3), ImmutableList.of());
// explicitly include groups
reviewers =
gApi.changes().id(changeId).suggestReviewers(name("user")).excludeGroups(false).get();
assertReviewers(
reviewers, ImmutableList.of(user1, user2, user3), ImmutableList.of(group1, group2, group3));
}
@Test
@GerritConfig(name = "accounts.visibility", value = "SAME_GROUP")
public void suggestReviewersSameGroupVisibility() throws Exception {
String changeId = createChange().getChangeId();
List<SuggestedReviewerInfo> reviewers;
reviewers = suggestReviewers(changeId, user2.username(), 2);
assertThat(reviewers).hasSize(1);
assertThat(Iterables.getOnlyElement(reviewers).account.name).isEqualTo(user2.fullName());
requestScopeOperations.setApiUser(user1.id());
reviewers = suggestReviewers(changeId, user2.fullName(), 2);
assertThat(reviewers).isEmpty();
requestScopeOperations.setApiUser(user2.id());
reviewers = suggestReviewers(changeId, user2.username(), 2);
assertThat(reviewers).hasSize(1);
assertThat(Iterables.getOnlyElement(reviewers).account.name).isEqualTo(user2.fullName());
requestScopeOperations.setApiUser(user3.id());
reviewers = suggestReviewers(changeId, user2.username(), 2);
assertThat(reviewers).hasSize(1);
assertThat(Iterables.getOnlyElement(reviewers).account.name).isEqualTo(user2.fullName());
}
@Test
public void suggestReviewersPrivateProjectVisibility() throws Exception {
String changeId = createChange().getChangeId();
List<SuggestedReviewerInfo> reviewers;
requestScopeOperations.setApiUser(user3.id());
projectOperations
.project(project)
.forUpdate()
.add(block(READ).ref("refs/*").group(ANONYMOUS_USERS))
.add(allow(READ).ref("refs/*").group(group1))
.update();
reviewers = suggestReviewers(changeId, user2.username(), 2);
assertThat(reviewers).isEmpty();
}
@Test
@GerritConfig(name = "accounts.visibility", value = "SAME_GROUP")
public void suggestReviewersViewAllAccounts() throws Exception {
String changeId = createChange().getChangeId();
List<SuggestedReviewerInfo> reviewers;
requestScopeOperations.setApiUser(user1.id());
reviewers = suggestReviewers(changeId, user2.username(), 2);
assertThat(reviewers).isEmpty();
// Clear cached group info.
requestScopeOperations.setApiUser(user1.id());
projectOperations
.allProjectsForUpdate()
.add(allowCapability(GlobalCapability.VIEW_ALL_ACCOUNTS).group(group1))
.update();
reviewers = suggestReviewers(changeId, user2.username(), 2);
assertThat(reviewers).hasSize(1);
assertThat(Iterables.getOnlyElement(reviewers).account.name).isEqualTo(user2.fullName());
}
@Test
@GerritConfig(name = "suggest.maxSuggestedReviewers", value = "2")
public void suggestReviewersMaxNbrSuggestions() throws Exception {
String changeId = createChange().getChangeId();
List<SuggestedReviewerInfo> reviewers = suggestReviewers(changeId, name("user"), 5);
assertThat(reviewers).hasSize(2);
}
@Test
public void suggestReviewersFullTextSearch() throws Exception {
String changeId = createChange().getChangeId();
List<SuggestedReviewerInfo> reviewers;
reviewers = suggestReviewers(changeId, "first");
assertThat(reviewers).hasSize(3);
reviewers = suggestReviewers(changeId, "first1");
assertThat(reviewers).hasSize(1);
reviewers = suggestReviewers(changeId, "last");
assertThat(reviewers).hasSize(3);
reviewers = suggestReviewers(changeId, "last1");
assertThat(reviewers).hasSize(1);
reviewers = suggestReviewers(changeId, "fi la");
assertThat(reviewers).hasSize(3);
reviewers = suggestReviewers(changeId, "la fi");
assertThat(reviewers).hasSize(3);
reviewers = suggestReviewers(changeId, "first1 la");
assertThat(reviewers).hasSize(1);
reviewers = suggestReviewers(changeId, "fi last1");
assertThat(reviewers).hasSize(1);
reviewers = suggestReviewers(changeId, "first1 last2");
assertThat(reviewers).isEmpty();
reviewers = suggestReviewers(changeId, name("user"));
assertThat(reviewers).hasSize(6);
reviewers = suggestReviewers(changeId, user1.username());
assertThat(reviewers).hasSize(1);
reviewers = suggestReviewers(changeId, "example.com");
assertThat(reviewers).hasSize(5);
reviewers = suggestReviewers(changeId, user1.email());
assertThat(reviewers).hasSize(1);
reviewers = suggestReviewers(changeId, user1.username() + " example");
assertThat(reviewers).hasSize(1);
reviewers = suggestReviewers(changeId, user4.email().toLowerCase());
assertThat(reviewers).hasSize(1);
assertThat(reviewers.get(0).account.email).isEqualTo(user4.email());
}
@Test
public void suggestReviewersWithoutLimitOptionSpecified() throws Exception {
String changeId = createChange().getChangeId();
String query = user3.username();
List<SuggestedReviewerInfo> suggestedReviewerInfos =
gApi.changes().id(changeId).suggestReviewers(query).get();
assertThat(suggestedReviewerInfos).hasSize(1);
}
@Test
@GerritConfig(name = "addreviewer.maxAllowed", value = "1")
@GerritConfig(name = "addreviewer.maxWithoutConfirmation", value = "1")
public void confirmationIsNeverRequestedForAccounts() throws Exception {
user("individual 0", "Test0 Last0");
user("individual 1", "Test1 Last1");
String changeId = createChange().getChangeId();
List<SuggestedReviewerInfo> reviewers;
SuggestedReviewerInfo reviewer;
// Individual account suggestions have count of 1 and no confirm.
reviewers = suggestReviewers(changeId, "test", 10);
assertThat(reviewers).hasSize(2);
reviewer = reviewers.get(0);
assertThat(reviewer.count).isEqualTo(1);
assertThat(reviewer.confirm).isNull();
}
@Test
@GerritConfig(name = "addreviewer.maxAllowed", value = "2")
@GerritConfig(name = "addreviewer.maxWithoutConfirmation", value = "1")
public void suggestReviewersGroupSizeConsiderations() throws Exception {
AccountGroup.UUID largeGroup = createGroupWithArbitraryMembers(3);
String largeGroupName = groupOperations.group(largeGroup).get().name();
AccountGroup.UUID mediumGroup = createGroupWithArbitraryMembers(2);
String mediumGroupName = groupOperations.group(mediumGroup).get().name();
String changeId = createChange().getChangeId();
List<SuggestedReviewerInfo> reviewers;
SuggestedReviewerInfo reviewer;
// Large group should never be suggested.
reviewers = suggestReviewers(changeId, largeGroupName, 10);
assertThat(reviewers).isEmpty();
// Medium group should be suggested with appropriate count and confirm.
reviewers = suggestReviewers(changeId, mediumGroupName, 10);
assertThat(reviewers).hasSize(1);
reviewer = reviewers.get(0);
assertThat(reviewer.group.id).isEqualTo(mediumGroup.get());
assertThat(reviewer.count).isEqualTo(2);
assertThat(reviewer.confirm).isTrue();
}
@Test
@GerritConfig(name = "addreviewer.maxAllowed", value = "20")
@GerritConfig(name = "addreviewer.maxWithoutConfirmation", value = "0")
public void confirmationIsNotNecessaryForLargeGroupWhenLimitIsRemoved() throws Exception {
String changeId = createChange().getChangeId();
int numMembers = 15;
AccountGroup.UUID largeGroup = createGroupWithArbitraryMembers(numMembers);
String groupName = groupOperations.group(largeGroup).get().name();
List<SuggestedReviewerInfo> reviewers = suggestReviewers(changeId, groupName, 10);
assertThat(reviewers).hasSize(1);
SuggestedReviewerInfo reviewer = Iterables.getOnlyElement(reviewers);
assertThat(reviewer.group.id).isEqualTo(largeGroup.get());
// Confirmation should not be necessary.
assertThat(reviewer.confirm).isNull();
}
@Test
@GerritConfig(name = "addreviewer.maxAllowed", value = "0")
public void largeGroupIsSuggestedWhenLimitIsRemoved() throws Exception {
String changeId = createChange().getChangeId();
int numMembers = 30;
AccountGroup.UUID largeGroup = createGroupWithArbitraryMembers(numMembers);
String groupName = groupOperations.group(largeGroup).get().name();
List<SuggestedReviewerInfo> reviewers = suggestReviewers(changeId, groupName, 10);
assertThat(reviewers).hasSize(1);
SuggestedReviewerInfo reviewer = Iterables.getOnlyElement(reviewers);
assertThat(reviewer.group.id).isEqualTo(largeGroup.get());
}
@Test
public void defaultReviewerSuggestion() throws Exception {
TestAccount user1 = user("customuser1", "User1");
TestAccount reviewer1 = user("customuser2", "User2");
TestAccount reviewer2 = user("customuser3", "User3");
requestScopeOperations.setApiUser(user1.id());
String changeId1 = createChangeFromApi();
reviewChange(changeId1, reviewer1);
String changeId2 = createChangeFromApi();
reviewChange(changeId2, reviewer1);
reviewChange(changeId2, reviewer2);
String changeId3 = createChangeFromApi();
List<SuggestedReviewerInfo> reviewers = suggestReviewers(changeId3, null, 4);
assertThat(reviewers.stream().map(r -> r.account._accountId).collect(toList()))
.containsExactly(reviewer1.id().get(), reviewer2.id().get())
.inOrder();
// check that existing reviewers are filtered out
gApi.changes().id(changeId3).addReviewer(reviewer1.email());
reviewers = suggestReviewers(changeId3, null, 4);
assertThat(reviewers.stream().map(r -> r.account._accountId).collect(toList()))
.containsExactly(reviewer2.id().get())
.inOrder();
}
@Test
public void defaultReviewerSuggestionOnFirstChange() throws Exception {
TestAccount user1 = user("customuser1", "User1");
requestScopeOperations.setApiUser(user1.id());
List<SuggestedReviewerInfo> reviewers = suggestReviewers(createChange().getChangeId(), "", 4);
assertThat(reviewers).isEmpty();
}
@Test
public void suggestNoInactiveAccounts() throws Exception {
requestScopeOperations.setApiUser(user.id());
String changeIdReviewed = createChangeFromApi();
String changeId = createChangeFromApi();
String name = name("foo");
TestAccount foo1 = accountCreator.create(name + "-1");
reviewChange(changeIdReviewed, foo1);
assertThat(gApi.accounts().id(foo1.username()).getActive()).isTrue();
TestAccount foo2 = accountCreator.create(name + "-2");
reviewChange(changeIdReviewed, foo2);
assertThat(gApi.accounts().id(foo2.username()).getActive()).isTrue();
assertReviewers(
suggestReviewers(changeId, name), ImmutableList.of(foo1, foo2), ImmutableList.of());
requestScopeOperations.setApiUser(user.id());
gApi.accounts().id(foo2.username()).setActive(false);
assertThat(gApi.accounts().id(foo2.id().get()).getActive()).isFalse();
assertReviewers(suggestReviewers(changeId, name), ImmutableList.of(foo1), ImmutableList.of());
assertReviewers(
suggestReviewers(changeId, /*query=*/ ""), ImmutableList.of(foo1), ImmutableList.of());
}
@Test
public void suggestNoServiceAccounts() throws Exception {
requestScopeOperations.setApiUser(user.id());
String changeIdReviewed = createChangeFromApi();
String changeId = createChangeFromApi();
String name = name("foo");
TestAccount foo = accountCreator.create(name);
reviewChange(changeIdReviewed, foo);
assertReviewers(suggestReviewers(changeId, name), ImmutableList.of(foo), ImmutableList.of());
groupOperations.group(serviceUsersUUID()).forUpdate().addMember(foo.id()).update();
assertReviewers(suggestReviewers(changeId, name), ImmutableList.of(), ImmutableList.of());
}
@Test
public void suggestNoExistingReviewers() throws Exception {
requestScopeOperations.setApiUser(user.id());
String changeId = createChangeFromApi();
String changeIdReviewed = createChangeFromApi();
String name = name("foo");
TestAccount foo1 = accountCreator.create(name + "-1");
reviewChange(changeIdReviewed, foo1);
TestAccount foo2 = accountCreator.create(name + "-2");
reviewChange(changeIdReviewed, foo2);
assertReviewers(
suggestReviewers(changeId, name), ImmutableList.of(foo1, foo2), ImmutableList.of());
gApi.changes().id(changeId).addReviewer(foo2.id().toString());
assertReviewers(suggestReviewers(changeId, name), ImmutableList.of(foo1), ImmutableList.of());
}
@Test
public void suggestCcAsReviewer() throws Exception {
requestScopeOperations.setApiUser(user.id());
String changeId = createChangeFromApi();
String changeIdReviewed = createChangeFromApi();
String name = name("foo");
TestAccount foo1 = accountCreator.create(name + "-1");
reviewChange(changeIdReviewed, foo1);
TestAccount foo2 = accountCreator.create(name + "-2");
reviewChange(changeIdReviewed, foo2);
assertReviewers(
suggestReviewers(changeId, name), ImmutableList.of(foo1, foo2), ImmutableList.of());
ReviewerInput reviewerInput = new ReviewerInput();
reviewerInput.reviewer = foo2.id().toString();
reviewerInput.state = ReviewerState.CC;
gApi.changes().id(changeId).addReviewer(reviewerInput);
assertReviewers(
suggestReviewers(changeId, name), ImmutableList.of(foo1, foo2), ImmutableList.of());
}
@Test
public void suggestReviewerAsCc() throws Exception {
requestScopeOperations.setApiUser(user.id());
String changeId = createChangeFromApi();
String changeIdReviewed = createChangeFromApi();
String name = name("foo");
TestAccount foo1 = accountCreator.create(name + "-1");
reviewChange(changeIdReviewed, foo1);
TestAccount foo2 = accountCreator.create(name + "-2");
reviewChange(changeIdReviewed, foo2);
assertReviewers(suggestCcs(changeId, name), ImmutableList.of(foo1, foo2), ImmutableList.of());
ReviewerInput reviewerInput = new ReviewerInput();
reviewerInput.reviewer = foo2.id().toString();
reviewerInput.state = ReviewerState.REVIEWER;
gApi.changes().id(changeId).addReviewer(reviewerInput);
assertReviewers(suggestCcs(changeId, name), ImmutableList.of(foo1, foo2), ImmutableList.of());
}
@Test
public void suggestBySecondaryEmailWithModifyAccount() throws Exception {
String secondaryEmail = "foo.secondary@example.com";
TestAccount foo = createAccountWithSecondaryEmail("foo", secondaryEmail);
List<SuggestedReviewerInfo> reviewers = suggestReviewers(createChangeFromApi(), "secondary", 4);
assertReviewers(reviewers, ImmutableList.of(foo), ImmutableList.of());
}
@Test
public void cannotSuggestBySecondaryEmailWithoutModifyAccount() throws Exception {
// Test that even if the account exists, the result is still empty since
// it shouldn't match to that account based only on the secondary email.
createAccountWithSecondaryEmail("foo", "foo.secondary@example.com");
requestScopeOperations.setApiUser(user.id());
List<SuggestedReviewerInfo> reviewers = suggestReviewers(createChangeFromApi(), "secondary", 4);
assertThat(reviewers).isEmpty();
}
@Test
public void secondaryEmailsInSuggestions() throws Exception {
String secondaryEmail = "foo.secondary@example.com";
TestAccount foo = createAccountWithSecondaryEmail("foo", secondaryEmail);
List<SuggestedReviewerInfo> reviewers =
suggestReviewers(createChange().getChangeId(), "foo", 4);
assertReviewers(reviewers, ImmutableList.of(foo), ImmutableList.of());
assertThat(Iterables.getOnlyElement(reviewers).account.secondaryEmails)
.containsExactly(secondaryEmail);
requestScopeOperations.setApiUser(user.id());
reviewers = suggestReviewers(createChange().getChangeId(), "foo", 4);
assertReviewers(reviewers, ImmutableList.of(foo), ImmutableList.of());
assertThat(Iterables.getOnlyElement(reviewers).account.secondaryEmails).isNull();
}
@Test
public void suggestsPeopleWithNoReviewsWhenExplicitlyQueried() throws Exception {
TestAccount newTeamMember = accountCreator.create("newTeamMember");
requestScopeOperations.setApiUser(user.id());
String changeId = createChangeFromApi();
String changeIdReviewed = createChangeFromApi();
TestAccount reviewer = accountCreator.create("newReviewer");
reviewChange(changeIdReviewed, reviewer);
List<SuggestedReviewerInfo> reviewers = suggestReviewers(changeId, "new", 4);
assertThat(reviewers.stream().map(r -> r.account._accountId).collect(toList()))
.containsExactly(reviewer.id().get(), newTeamMember.id().get())
.inOrder();
}
private TestAccount createAccountWithSecondaryEmail(String name, String secondaryEmail)
throws Exception {
TestAccount foo = accountCreator.create(name(name), "foo.primary@example.com", "Foo", null);
EmailInput input = new EmailInput();
input.email = secondaryEmail;
input.noConfirmation = true;
gApi.accounts().id(foo.id().get()).addEmail(input);
return foo;
}
private List<SuggestedReviewerInfo> suggestReviewers(String changeId, String query)
throws Exception {
return gApi.changes().id(changeId).suggestReviewers(query).get();
}
private List<SuggestedReviewerInfo> suggestReviewers(String changeId, String query, int n)
throws Exception {
return gApi.changes().id(changeId).suggestReviewers(query).withLimit(n).get();
}
private List<SuggestedReviewerInfo> suggestCcs(String changeId, String query) throws Exception {
return gApi.changes().id(changeId).suggestCcs(query).get();
}
private AccountGroup.UUID createGroupWithArbitraryMembers(int numMembers) {
Set<Account.Id> members =
IntStream.rangeClosed(1, numMembers)
.mapToObj(i -> accountOperations.newAccount().create())
.collect(toImmutableSet());
return groupOperations.newGroup().members(members).create();
}
private TestAccount user(String name, String fullName, String emailName) throws Exception {
return accountCreator.create(name(name), name(emailName) + "@example.com", fullName, null);
}
private TestAccount user(String name, String fullName) throws Exception {
return user(name, fullName, name);
}
private AccountGroup.UUID serviceUsersUUID() {
return groupCache
.get(AccountGroup.nameKey("Service Users"))
.orElseThrow(() -> new IllegalStateException("unable to find 'Service Users'"))
.getGroupUUID();
}
private void reviewChange(String changeId, TestAccount reviewer) throws RestApiException {
gApi.changes().id(changeId).addReviewer(reviewer.id().toString());
}
private String createChangeFromApi() throws RestApiException {
return createChangeFromApi(project);
}
private String createChangeFromApi(Project.NameKey project) throws RestApiException {
ChangeInput ci = new ChangeInput();
ci.project = project.get();
ci.subject = "Test change at" + System.nanoTime();
ci.branch = "master";
return gApi.changes().create(ci).get().changeId;
}
private static void assertReviewers(
List<SuggestedReviewerInfo> actual,
List<TestAccount> expectedUsers,
List<AccountGroup.UUID> expectedGroups) {
List<Integer> actualAccountIds =
actual.stream()
.filter(i -> i.account != null)
.map(i -> i.account._accountId)
.collect(toList());
assertThat(actualAccountIds)
.containsExactlyElementsIn(expectedUsers.stream().map(u -> u.id().get()).collect(toList()));
List<String> actualGroupIds =
actual.stream().filter(i -> i.group != null).map(i -> i.group.id).collect(toList());
assertThat(actualGroupIds)
.containsExactlyElementsIn(
expectedGroups.stream().map(AccountGroup.UUID::get).collect(toList()))
.inOrder();
}
}