// Copyright (C) 2016 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.server.query.account;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.common.truth.Truth8.assertThat;
import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static java.util.stream.Collectors.toList;
import static org.junit.Assert.fail;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Streams;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.api.GerritApi;
import com.google.gerrit.extensions.api.access.AccessSectionInfo;
import com.google.gerrit.extensions.api.access.PermissionInfo;
import com.google.gerrit.extensions.api.access.PermissionRuleInfo;
import com.google.gerrit.extensions.api.access.ProjectAccessInput;
import com.google.gerrit.extensions.api.accounts.Accounts.QueryRequest;
import com.google.gerrit.extensions.api.changes.ReviewerInput;
import com.google.gerrit.extensions.api.groups.GroupInput;
import com.google.gerrit.extensions.api.projects.ProjectInput;
import com.google.gerrit.extensions.client.ListAccountsOption;
import com.google.gerrit.extensions.client.ProjectWatchInfo;
import com.google.gerrit.extensions.client.ReviewerState;
import com.google.gerrit.extensions.common.AccountExternalIdInfo;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.ChangeInput;
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.index.QueryOptions;
import com.google.gerrit.index.Schema;
import com.google.gerrit.index.query.FieldBundle;
import com.google.gerrit.lifecycle.LifecycleManager;
import com.google.gerrit.server.AnonymousUser;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.ServerInitiated;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountConfig;
import com.google.gerrit.server.account.AccountDelta;
import com.google.gerrit.server.account.AccountManager;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.account.Accounts;
import com.google.gerrit.server.account.AccountsUpdate;
import com.google.gerrit.server.account.AuthRequest;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.account.externalids.ExternalIdKeyFactory;
import com.google.gerrit.server.account.externalids.ExternalIds;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.index.account.AccountField;
import com.google.gerrit.server.index.account.AccountIndex;
import com.google.gerrit.server.index.account.AccountIndexCollection;
import com.google.gerrit.server.index.account.AccountIndexer;
import com.google.gerrit.server.schema.SchemaCreator;
import com.google.gerrit.server.util.ManualRequestContext;
import com.google.gerrit.server.util.OneOffRequestContext;
import com.google.gerrit.server.util.RequestContext;
import com.google.gerrit.server.util.ThreadLocalRequestContext;
import com.google.gerrit.testing.GerritServerTests;
import com.google.gerrit.testing.GerritTestName;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Provider;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;

@Ignore
public abstract class AbstractQueryAccountsTest extends GerritServerTests {
  @Rule public final GerritTestName testName = new GerritTestName();

  @Inject protected Accounts accounts;

  @Inject @ServerInitiated protected Provider<AccountsUpdate> accountsUpdate;

  @Inject protected AccountCache accountCache;

  @Inject protected AccountIndexer accountIndexer;

  @Inject protected AccountManager accountManager;

  @Inject protected GerritApi gApi;

  @Inject @GerritPersonIdent Provider<PersonIdent> serverIdent;

  @Inject protected IdentifiedUser.GenericFactory userFactory;

  @Inject private Provider<AnonymousUser> anonymousUser;

  @Inject protected SchemaCreator schemaCreator;

  @Inject protected ThreadLocalRequestContext requestContext;

  @Inject protected OneOffRequestContext oneOffRequestContext;

  @Inject protected Provider<InternalAccountQuery> queryProvider;

  @Inject protected AllProjectsName allProjects;

  @Inject protected AllUsersName allUsers;

  @Inject protected GitRepositoryManager repoManager;

  @Inject protected AccountIndexCollection indexes;

  @Inject protected ExternalIds externalIds;

  @Inject private ExternalIdKeyFactory externalIdKeyFactory;

  @Inject protected AuthRequest.Factory authRequestFactory;

  protected LifecycleManager lifecycle;
  protected Injector injector;
  protected AccountInfo currentUserInfo;
  protected CurrentUser admin;

  protected abstract Injector createInjector();

  protected void validateAssumptions() {}

  @Before
  public void setUpInjector() throws Exception {
    lifecycle = new LifecycleManager();
    injector = createInjector();
    lifecycle.add(injector);
    injector.injectMembers(this);
    lifecycle.start();
    initAfterLifecycleStart();
    setUpDatabase();
    validateAssumptions();
  }

  @After
  public void cleanUp() {
    lifecycle.stop();
  }

  protected void setUpDatabase() throws Exception {
    schemaCreator.create();

    Account.Id adminId = createAccount("admin", "Administrator", "admin@example.com", true);
    admin = userFactory.create(adminId);
    requestContext.setContext(newRequestContext(adminId));
    currentUserInfo = gApi.accounts().id(adminId.get()).get();
  }

  protected void initAfterLifecycleStart() throws Exception {}

  protected RequestContext newRequestContext(Account.Id requestUserId) {
    final CurrentUser requestUser = userFactory.create(requestUserId);
    return () -> requestUser;
  }

  protected void setAnonymous() {
    requestContext.setContext(anonymousUser::get);
  }

  @After
  public void tearDownInjector() {
    if (lifecycle != null) {
      lifecycle.stop();
    }
    requestContext.setContext(null);
  }

  @Test
  public void byId() throws Exception {
    AccountInfo user = newAccount("user");

    assertQuery("9999999");
    assertQuery(currentUserInfo._accountId, currentUserInfo);
    assertQuery(user._accountId, user);
  }

  @Test
  public void bySelf() throws Exception {
    assertQuery("self", currentUserInfo);
  }

  @Test
  public void byEmail() throws Exception {
    AccountInfo user1 = newAccountWithEmail("user1", name("user1@example.com"));

    String domain = name("test.com");
    AccountInfo user2 = newAccountWithEmail("user2", "user2@" + domain);
    AccountInfo user3 = newAccountWithEmail("user3", "user3@" + domain);

    String prefix = name("prefix");
    AccountInfo user4 = newAccountWithEmail("user4", prefix + "user4@example.com");

    AccountInfo user5 = newAccountWithEmail("user5", name("user5MixedCase@example.com"));

    assertQuery("notexisting@example.com");

    assertQuery(currentUserInfo.email, currentUserInfo);
    assertQuery("email:" + currentUserInfo.email, currentUserInfo);

    assertQuery(user1.email, user1);
    assertQuery("email:" + user1.email, user1);

    assertQuery(domain, user2, user3);

    assertQuery("email:" + prefix, user4);

    assertQuery(user5.email, user5);
    assertQuery("email:" + user5.email, user5);
    assertQuery("email:" + user5.email.toUpperCase(Locale.US), user5);
  }

  @Test
  public void bySecondaryEmail() throws Exception {
    String prefix = name("secondary");
    String domain = name("test.com");
    String secondaryEmail = prefix + "@" + domain;
    AccountInfo user1 = newAccountWithEmail("user1", name("user1@example.com"));
    addEmails(user1, secondaryEmail);

    AccountInfo user2 = newAccountWithEmail("user2", name("user2@example.com"));
    addEmails(user2, name("other@" + domain));

    assertQuery(secondaryEmail, user1);
    assertQuery("email:" + secondaryEmail, user1);
    assertQuery("email:" + prefix, user1);
    assertQuery(domain, user1, user2);
  }

  @Test
  public void byEmailWithoutModifyAccountCapability() throws Exception {
    String preferredEmail = name("primary@example.com");
    String secondaryEmail = name("secondary@example.com");
    AccountInfo user1 = newAccountWithEmail("user1", preferredEmail);
    addEmails(user1, secondaryEmail);

    AccountInfo user2 = newAccount("user");
    requestContext.setContext(newRequestContext(Account.id(user2._accountId)));

    assertQuery(preferredEmail, user1);
    assertQuery(secondaryEmail);

    assertQuery("email:" + preferredEmail, user1);
    assertQuery("email:" + secondaryEmail);
  }

  @Test
  public void byUsername() throws Exception {
    assume().that(hasIndexByUsername()).isTrue();
    AccountInfo user1 = newAccount("myuser");

    assertQuery("notexisting");
    assertQuery("Not Existing");

    assertQuery(user1.username, user1);
    assertQuery("username:" + user1.username, user1);
    assertQuery("username:" + user1.username.toUpperCase(Locale.US), user1);
  }

  @Test
  public void isActive() throws Exception {
    String domain = name("test.com");
    AccountInfo user1 = newAccountWithEmail("user1", "user1@" + domain);
    AccountInfo user2 = newAccountWithEmail("user2", "user2@" + domain);
    AccountInfo user3 = newAccount("user3", "user3@" + domain, false);
    AccountInfo user4 = newAccount("user4", "user4@" + domain, false);

    // by default only active accounts are returned
    assertQuery(domain, user1, user2);
    assertQuery("name:" + domain, user1, user2);

    assertQuery("is:active name:" + domain, user1, user2);

    assertQuery("is:inactive name:" + domain, user3, user4);
  }

  @Test
  public void byName() throws Exception {
    AccountInfo user1 = newAccountWithFullName("jdoe", "John Doe");
    AccountInfo user2 = newAccountWithFullName("jroe", "Jane Roe");
    AccountInfo user3 = newAccountWithFullName("user3", "Mr Selfish");

    assertQuery("notexisting");
    assertQuery("Not Existing");

    assertQuery(quote(user1.name), user1);
    assertQuery("name:" + quote(user1.name), user1);
    assertQuery("John", user1);
    assertQuery("john", user1);
    assertQuery("Doe", user1);
    assertQuery("doe", user1);
    assertQuery("DOE", user1);
    assertQuery("Jo Do", user1);
    assertQuery("jo do", user1);
    assertQuery("self", currentUserInfo, user3);
    assertQuery("me", currentUserInfo);
    assertQuery("name:John", user1);
    assertQuery("name:john", user1);
    assertQuery("name:Doe", user1);
    assertQuery("name:doe", user1);
    assertQuery("name:DOE", user1);
    assertQuery("name:self", user3);

    assertQuery(quote(user2.name), user2);
    assertQuery("name:" + quote(user2.name), user2);
  }

  @Test
  public void byNameWithoutModifyAccountCapability() throws Exception {
    AccountInfo user1 = newAccountWithFullName("jdoe", "John Doe");
    AccountInfo user2 = newAccountWithFullName("jroe", "Jane Roe");

    AccountInfo user3 = newAccount("user");
    requestContext.setContext(newRequestContext(Account.id(user3._accountId)));

    assertQuery("notexisting");
    assertQuery("Not Existing");

    // by full name works with any index version
    assertQuery(quote(user1.name), user1);
    assertQuery("name:" + quote(user1.name), user1);
    assertQuery(quote(user2.name), user2);
    assertQuery("name:" + quote(user2.name), user2);

    // by self/me works with any index version
    assertQuery("self", user3);
    assertQuery("me", user3);

    assertQuery("John", user1);
    assertQuery("john", user1);
    assertQuery("Doe", user1);
    assertQuery("doe", user1);
    assertQuery("DOE", user1);
    assertQuery("Jo Do", user1);
    assertQuery("jo do", user1);
    assertQuery("name:John", user1);
    assertQuery("name:john", user1);
    assertQuery("name:Doe", user1);
    assertQuery("name:doe", user1);
    assertQuery("name:DOE", user1);
  }

  @Test
  public void byCansee() throws Exception {
    String domain = name("test.com");
    AccountInfo user1 = newAccountWithEmail("account1", "account1@" + domain);
    AccountInfo user2 = newAccountWithEmail("account2", "account2@" + domain);
    AccountInfo user3 = newAccountWithEmail("account3", "account3@" + domain);

    Project.NameKey p = createProject(name("p"));
    ChangeInfo c = createChange(p);
    assertQuery("name:" + domain + " cansee:" + c.changeId, user1, user2, user3);

    GroupInfo group = createGroup(name("group"), user1, user2);
    blockRead(p, group);
    assertQuery("name:" + domain + " cansee:" + c.changeId, user3);
  }

  @Test
  public void byCanSee_privateChange() throws Exception {
    String domain = name("test.com");
    AccountInfo user1 = newAccountWithEmail("account1", "account1@" + domain);
    AccountInfo user2 = newAccountWithEmail("account2", "account2@" + domain);
    AccountInfo user3 = newAccountWithEmail("account3", "account3@" + domain);
    AccountInfo user4 = newAccountWithEmail("account4", "account4@" + domain);

    Project.NameKey p = createProject(name("p"));

    // Create the change as User1
    requestContext.setContext(newRequestContext(Account.id(user1._accountId)));
    ChangeInfo c = createPrivateChange(p);
    assertThat(c.owner).isEqualTo(user1);

    // Add user2 as a reviewer, user3 as a CC, and leave user4 dangling.
    addReviewer(c.changeId, user2.email, ReviewerState.REVIEWER);
    addReviewer(c.changeId, user3.email, ReviewerState.CC);

    // Request as the owner
    requestContext.setContext(newRequestContext(Account.id(user1._accountId)));
    assertQuery("cansee:" + c.changeId, user1, user2, user3);

    // Request as the reviewer
    requestContext.setContext(newRequestContext(Account.id(user2._accountId)));
    assertQuery("cansee:" + c.changeId, user1, user2, user3);

    // Request as the CC
    requestContext.setContext(newRequestContext(Account.id(user3._accountId)));
    assertQuery("cansee:" + c.changeId, user1, user2, user3);

    // Request as an account not in {owner, reviewer, CC}
    requestContext.setContext(newRequestContext(Account.id(user4._accountId)));
    BadRequestException exception =
        assertThrows(BadRequestException.class, () -> newQuery("cansee:" + c.changeId).get());
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(String.format("change %s not found", c.changeId));
  }

  @Test
  public void byWatchedProject() throws Exception {
    Project.NameKey p = createProject(name("p"));
    Project.NameKey p2 = createProject(name("p2"));
    AccountInfo user1 = newAccountWithFullName("jdoe", "John Doe");
    AccountInfo user2 = newAccountWithFullName("jroe", "Jane Roe");
    AccountInfo user3 = newAccountWithFullName("user3", "Mr Selfish");

    assertThat(queryProvider.get().byWatchedProject(p)).isEmpty();

    watch(user1, p, null);
    assertAccounts(queryProvider.get().byWatchedProject(p), user1);

    watch(user2, p, "keyword");
    assertAccounts(queryProvider.get().byWatchedProject(p), user1, user2);

    watch(user3, p2, "keyword");
    watch(user3, allProjects, "keyword");
    assertAccounts(queryProvider.get().byWatchedProject(p), user1, user2);
    assertAccounts(queryProvider.get().byWatchedProject(p2), user3);
    assertAccounts(queryProvider.get().byWatchedProject(allProjects), user3);
  }

  @Test
  public void byDeletedAccount() throws Exception {
    AccountInfo user = newAccountWithFullName("jdoe", "John Doe");
    Account.Id userId = Account.Id.tryParse(user._accountId.toString()).get();
    assertQuery("John", user);

    for (AccountIndex index : indexes.getWriteIndexes()) {
      index.delete(userId);
    }
    assertQuery("John");
  }

  @Test
  public void withLimit() throws Exception {
    String domain = name("test.com");
    AccountInfo user1 = newAccountWithEmail("user1", "user1@" + domain);
    AccountInfo user2 = newAccountWithEmail("user2", "user2@" + domain);
    AccountInfo user3 = newAccountWithEmail("user3", "user3@" + domain);

    List<AccountInfo> result = assertQuery(domain, user1, user2, user3);
    assertThat(Iterables.getLast(result)._moreAccounts).isNull();

    result = assertQuery(newQuery(domain).withLimit(2), result.subList(0, 2));
    assertThat(Iterables.getLast(result)._moreAccounts).isTrue();
  }

  @Test
  public void withStart() throws Exception {
    String domain = name("test.com");
    AccountInfo user1 = newAccountWithEmail("user1", "user1@" + domain);
    AccountInfo user2 = newAccountWithEmail("user2", "user2@" + domain);
    AccountInfo user3 = newAccountWithEmail("user3", "user3@" + domain);

    List<AccountInfo> result = assertQuery(domain, user1, user2, user3);
    assertQuery(newQuery(domain).withStart(1), result.subList(1, 3));
  }

  @Test
  public void withStartCannotBeLessThanZero() throws Exception {
    assertFailingQuery(
        newQuery("self").withStart(-1), "'start' parameter cannot be less than zero");
  }

  @Test
  public void sortedByFullname() throws Exception {
    String appendix = name("name");

    // Use an account creation order that ensures that sorting by fullname differs from sorting by
    // account ID.
    AccountInfo userFoo = newAccountWithFullName("user1", "foo-" + appendix);
    AccountInfo userBar = newAccountWithFullName("user2", "bar-" + appendix);
    AccountInfo userBaz = newAccountWithFullName("user3", "baz-" + appendix);
    assertThat(userFoo._accountId).isLessThan(userBar._accountId);
    assertThat(userBar._accountId).isLessThan(userBaz._accountId);

    String query = "name:" + userFoo.name + " OR name:" + userBar.name + " OR name:" + userBaz.name;
    // Must request details to populate fullname in the results. If fullname is not set sorting by
    // fullname is not possible.
    assertQuery(newQuery(query).withOption(ListAccountsOption.DETAILS), userBar, userBaz, userFoo);
  }

  @Test
  public void sortedByPreferredEmail() throws Exception {
    String appendix = name("name");

    // Use an account creation order that ensures that sorting by preferred email differs from
    // sorting by account ID. Use the same fullname for all accounts so that sorting must be done by
    // preferred email.
    AccountInfo userFoo3 =
        newAccount("user3", "foo-" + appendix, "foo3-" + appendix + "@example.com", true);
    AccountInfo userFoo1 =
        newAccount("user1", "foo-" + appendix, "foo1-" + appendix + "@example.com", true);
    AccountInfo userFoo2 =
        newAccount("user2", "foo-" + appendix, "foo2-" + appendix + "@example.com", true);
    assertThat(userFoo3._accountId).isLessThan(userFoo1._accountId);
    assertThat(userFoo1._accountId).isLessThan(userFoo2._accountId);

    String query =
        "name:" + userFoo1.name + " OR name:" + userFoo2.name + " OR name:" + userFoo3.name;
    // Must request details to populate fullname and preferred email in the results. If fullname and
    // preferred email are not set sorting by fullname and preferred email is not possible. Since
    // all 3 accounts have the same fullname we expect sorting by preferred email.
    assertQuery(
        newQuery(query).withOption(ListAccountsOption.DETAILS), userFoo1, userFoo2, userFoo3);
  }

  @Test
  public void sortedById() throws Exception {
    String appendix = name("name");

    // Each new account gets a higher account ID. Create the accounts in an order that sorting by
    // fullname differs from sorting by accout ID.
    AccountInfo userFoo = newAccountWithFullName("user1", "foo-" + appendix);
    AccountInfo userBar = newAccountWithFullName("user2", "bar-" + appendix);
    AccountInfo userBaz = newAccountWithFullName("user3", "baz-" + appendix);
    assertThat(userFoo._accountId).isLessThan(userBar._accountId);
    assertThat(userBar._accountId).isLessThan(userBaz._accountId);

    String query = "name:" + userFoo.name + " OR name:" + userBar.name + " OR name:" + userBaz.name;
    // Normally sorting is done by fullname and preferred email, but if no details are requested
    // fullname and preferred email are not set and then sorting is done by account ID.
    assertQuery(newQuery(query), userFoo, userBar, userBaz);
  }

  @Test
  public void withDetails() throws Exception {
    AccountInfo user1 = newAccount("myuser", "My User", "my.user@example.com", true);

    List<AccountInfo> result = assertQuery(getDefaultSearch(user1), user1);
    AccountInfo ai = result.get(0);
    assertThat(ai._accountId).isEqualTo(user1._accountId);
    assertThat(ai.name).isNull();
    assertThat(ai.username).isNull();
    assertThat(ai.email).isNull();
    assertThat(ai.avatars).isNull();

    result =
        assertQuery(
            newQuery(getDefaultSearch(user1)).withOption(ListAccountsOption.DETAILS), user1);
    ai = result.get(0);
    assertThat(ai._accountId).isEqualTo(user1._accountId);
    assertThat(ai.name).isEqualTo(user1.name);
    assertThat(ai.username).isEqualTo(user1.username);
    assertThat(ai.email).isEqualTo(user1.email);
    assertThat(ai.avatars).isNull();
  }

  @Test
  public void withSecondaryEmails() throws Exception {
    AccountInfo user1 = newAccount("myuser", "My User", "my.user@example.com", true);
    String[] secondaryEmails = new String[] {"bar@example.com", "foo@example.com"};
    addEmails(user1, secondaryEmails);

    List<AccountInfo> result = assertQuery(getDefaultSearch(user1), user1);
    assertThat(result.get(0).secondaryEmails).isNull();

    result = assertQuery(newQuery(getDefaultSearch(user1)).withSuggest(true), user1);
    assertThat(result.get(0).secondaryEmails)
        .containsExactlyElementsIn(Arrays.asList(secondaryEmails))
        .inOrder();

    result =
        assertQuery(
            newQuery(getDefaultSearch(user1)).withOption(ListAccountsOption.DETAILS), user1);
    assertThat(result.get(0).secondaryEmails).isNull();

    result =
        assertQuery(
            newQuery(getDefaultSearch(user1)).withOption(ListAccountsOption.ALL_EMAILS), user1);
    assertThat(result.get(0).secondaryEmails)
        .containsExactlyElementsIn(Arrays.asList(secondaryEmails))
        .inOrder();

    result =
        assertQuery(
            newQuery(getDefaultSearch(user1))
                .withOptions(ListAccountsOption.DETAILS, ListAccountsOption.ALL_EMAILS),
            user1);
    assertThat(result.get(0).secondaryEmails)
        .containsExactlyElementsIn(Arrays.asList(secondaryEmails))
        .inOrder();
  }

  @Test
  public void withSecondaryEmailsWithoutModifyAccountCapability() throws Exception {
    AccountInfo user = newAccount("myuser", "My User", "other@example.com", true);

    AccountInfo otherUser = newAccount("otheruser", "Other User", "abc@example.com", true);
    String[] secondaryEmails = new String[] {"dfg@example.com", "hij@example.com"};
    addEmails(otherUser, secondaryEmails);

    requestContext.setContext(newRequestContext(Account.id(user._accountId)));

    List<AccountInfo> result = newQuery(getDefaultSearch(otherUser)).withSuggest(true).get();
    assertThat(result.get(0).secondaryEmails).isNull();
    assertThrows(
        AuthException.class,
        () ->
            newQuery(getDefaultSearch(otherUser)).withOption(ListAccountsOption.ALL_EMAILS).get());
  }

  @Test
  public void asAnonymous() throws Exception {
    AccountInfo user1 = newAccount("user1", "user1@gerrit.com", /*active=*/ true);

    setAnonymous();
    assertQuery("9999999");
    assertQuery("self");
    assertQuery("email:" + user1.email, user1);
  }

  // reindex permissions are tested by {@link AccountIT#reindexPermissions}
  @Test
  public void reindex() throws Exception {
    AccountInfo user1 = newAccountWithFullName("tester", "Test Usre");
    // update account without reindex so that account index is stale
    Account.Id accountId = Account.id(user1._accountId);
    String newName = "Test User";
    try (Repository repo = repoManager.openRepository(allUsers)) {
      MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsers, repo);
      PersonIdent ident = serverIdent.get();
      md.getCommitBuilder().setAuthor(ident);
      md.getCommitBuilder().setCommitter(ident);
      new AccountConfig(accountId, allUsers, repo)
          .load()
          .setAccountDelta(AccountDelta.builder().setFullName(newName).build())
          .commit(md);
    }
    // Querying for the account here will not result in a stale document because
    // we load AccountStates from the cache after reading documents from the index
    // which means we always read fresh data when matching.
    //
    // Reindex document
    gApi.accounts().id(user1.username).index();
    assertQuery("name:" + quote(user1.name));
    assertQuery("name:" + quote(newName), user1);
  }

  @Test
  public void rawDocument() throws Exception {
    AccountInfo userInfo = gApi.accounts().id(admin.getAccountId().get()).get();

    Schema<AccountState> schema = indexes.getSearchIndex().getSchema();
    Optional<FieldBundle> rawFields =
        indexes
            .getSearchIndex()
            .getRaw(
                Account.id(userInfo._accountId),
                QueryOptions.create(
                    config != null
                        ? IndexConfig.fromConfig(config).build()
                        : IndexConfig.createDefault(),
                    0,
                    1,
                    schema.getStoredFields()));

    assertThat(rawFields).isPresent();
    if (schema.hasField(AccountField.ID_FIELD_SPEC)) {
      assertThat(rawFields.get().getValue(AccountField.ID_FIELD_SPEC))
          .isEqualTo(userInfo._accountId);
    } else {
      assertThat(Integer.valueOf(rawFields.get().<String>getValue(AccountField.ID_STR_FIELD_SPEC)))
          .isEqualTo(userInfo._accountId);
    }

    List<AccountExternalIdInfo> externalIdInfos = gApi.accounts().self().getExternalIds();
    List<ByteArrayWrapper> blobs = new ArrayList<>();
    for (AccountExternalIdInfo info : externalIdInfos) {
      Optional<ExternalId> extId = externalIds.get(externalIdKeyFactory.parse(info.identity));
      assertThat(extId).isPresent();
      blobs.add(new ByteArrayWrapper(AccountField.serializeExternalId(extId.get())));
    }

    // Some installations do not store EXTERNAL_ID_STATE_SPEC
    if (!schema.hasField(AccountField.EXTERNAL_ID_STATE_SPEC)) {
      return;
    }
    Iterable<byte[]> externalIdStates =
        rawFields.get().<Iterable<byte[]>>getValue(AccountField.EXTERNAL_ID_STATE_SPEC);
    assertThat(externalIdStates).hasSize(blobs.size());
    assertThat(Streams.stream(externalIdStates).map(b -> new ByteArrayWrapper(b)).collect(toList()))
        .containsExactlyElementsIn(blobs);
  }

  private String getDefaultSearch(AccountInfo user) {
    return hasIndexByUsername() ? user.username : user.name;
  }

  /**
   * Returns 'true' is {@link AccountField#USERNAME_FIELD} is indexed.
   *
   * <p>Some installations do not index {@link AccountField#USERNAME_FIELD}, since they do not use
   * {@link ExternalId#SCHEME_USERNAME}
   */
  private boolean hasIndexByUsername() {
    Schema<AccountState> schema = indexes.getSearchIndex().getSchema();
    return schema.hasField(AccountField.USERNAME_SPEC);
  }

  protected AccountInfo newAccount(String username) throws Exception {
    return newAccountWithEmail(username, null);
  }

  protected AccountInfo newAccountWithEmail(String username, String email) throws Exception {
    return newAccount(username, email, true);
  }

  protected AccountInfo newAccountWithFullName(String username, String fullName) throws Exception {
    return newAccount(username, fullName, null, true);
  }

  protected AccountInfo newAccount(String username, String email, boolean active) throws Exception {
    return newAccount(username, null, email, active);
  }

  protected AccountInfo newAccount(String username, String fullName, String email, boolean active)
      throws Exception {
    String uniqueName = name(username);

    try {
      gApi.accounts().id(uniqueName).get();
      fail("user " + uniqueName + " already exists");
    } catch (ResourceNotFoundException e) {
      // expected: user does not exist yet
    }

    Account.Id id = createAccount(uniqueName, fullName, email, active);
    return gApi.accounts().id(id.get()).get();
  }

  protected Project.NameKey createProject(String name) throws RestApiException {
    ProjectInput in = new ProjectInput();
    in.name = name;
    in.createEmptyCommit = true;
    gApi.projects().create(in);
    return Project.nameKey(name);
  }

  protected void blockRead(Project.NameKey project, GroupInfo group) throws RestApiException {
    ProjectAccessInput in = new ProjectAccessInput();
    in.add = new HashMap<>();

    AccessSectionInfo a = new AccessSectionInfo();
    PermissionInfo p = new PermissionInfo(null, null);
    p.rules =
        ImmutableMap.of(group.id, new PermissionRuleInfo(PermissionRuleInfo.Action.BLOCK, false));
    a.permissions = ImmutableMap.of("read", p);
    in.add = ImmutableMap.of("refs/*", a);

    gApi.projects().name(project.get()).access(in);
  }

  protected ChangeInfo createPrivateChange(Project.NameKey project) throws RestApiException {
    ChangeInput in = new ChangeInput();
    in.subject = "A change";
    in.project = project.get();
    in.branch = "master";
    in.isPrivate = true;
    return gApi.changes().create(in).get();
  }

  protected ChangeInfo createChange(Project.NameKey project) throws RestApiException {
    ChangeInput in = new ChangeInput();
    in.subject = "A change";
    in.project = project.get();
    in.branch = "master";
    return gApi.changes().create(in).get();
  }

  protected void addReviewer(String changeId, String email, ReviewerState state)
      throws RestApiException {
    ReviewerInput reviewerInput = new ReviewerInput();
    reviewerInput.reviewer = email;
    reviewerInput.state = state;
    gApi.changes().id(changeId).addReviewer(reviewerInput);
  }

  protected GroupInfo createGroup(String name, AccountInfo... members) throws RestApiException {
    GroupInput in = new GroupInput();
    in.name = name;
    in.members =
        Arrays.asList(members).stream().map(a -> String.valueOf(a._accountId)).collect(toList());
    return gApi.groups().create(in).get();
  }

  protected void watch(AccountInfo account, Project.NameKey project, String filter)
      throws RestApiException {
    List<ProjectWatchInfo> projectsToWatch = new ArrayList<>();
    ProjectWatchInfo pwi = new ProjectWatchInfo();
    pwi.project = project.get();
    pwi.filter = filter;
    pwi.notifyAbandonedChanges = true;
    pwi.notifyNewChanges = true;
    pwi.notifyAllComments = true;
    projectsToWatch.add(pwi);
    gApi.accounts().id(account._accountId).setWatchedProjects(projectsToWatch);
  }

  protected String quote(String s) {
    return "\"" + s + "\"";
  }

  @Nullable
  protected String name(String name) {
    if (name == null) {
      return null;
    }

    String suffix = testName.getSanitizedMethodName();
    if (name.contains("@")) {
      return name + "." + suffix;
    }
    return name + "_" + suffix;
  }

  private Account.Id createAccount(String username, String fullName, String email, boolean active)
      throws Exception {
    try (ManualRequestContext ctx = oneOffRequestContext.open()) {
      Account.Id id =
          accountManager.authenticate(authRequestFactory.createForUser(username)).getAccountId();
      if (email != null) {
        accountManager.link(id, authRequestFactory.createForEmail(email));
      }
      accountsUpdate
          .get()
          .update(
              "Update Test Account",
              id,
              u -> {
                u.setFullName(fullName).setPreferredEmail(email).setActive(active);
              });
      return id;
    }
  }

  private void addEmails(AccountInfo account, String... emails) throws Exception {
    Account.Id id = Account.id(account._accountId);
    for (String email : emails) {
      accountManager.link(id, authRequestFactory.createForEmail(email));
    }
    accountIndexer.index(id);
  }

  protected QueryRequest newQuery(Object query) throws RestApiException {
    return gApi.accounts().query(query.toString());
  }

  protected List<AccountInfo> assertQuery(Object query, AccountInfo... accounts) throws Exception {
    return assertQuery(newQuery(query), accounts);
  }

  protected List<AccountInfo> assertQuery(QueryRequest query, AccountInfo... accounts)
      throws Exception {
    return assertQuery(query, Arrays.asList(accounts));
  }

  protected List<AccountInfo> assertQuery(QueryRequest query, List<AccountInfo> accounts)
      throws Exception {
    List<AccountInfo> result = query.get();
    Iterable<Integer> ids = ids(result);
    assertWithMessage(format(query, result, accounts))
        .that(ids)
        .containsExactlyElementsIn(ids(accounts))
        .inOrder();
    return result;
  }

  protected void assertAccounts(List<AccountState> accounts, AccountInfo... expectedAccounts) {
    assertThat(accounts.stream().map(a -> a.account().id().get()).collect(toList()))
        .containsExactlyElementsIn(
            Arrays.asList(expectedAccounts).stream().map(a -> a._accountId).collect(toList()));
  }

  private String format(
      QueryRequest query, List<AccountInfo> actualIds, List<AccountInfo> expectedAccounts) {
    StringBuilder b = new StringBuilder();
    b.append("query '").append(query.getQuery()).append("' with expected accounts ");
    b.append(format(expectedAccounts));
    b.append(" and result ");
    b.append(format(actualIds));
    return b.toString();
  }

  private String format(Iterable<AccountInfo> accounts) {
    StringBuilder b = new StringBuilder();
    b.append("[");
    Iterator<AccountInfo> it = accounts.iterator();
    while (it.hasNext()) {
      AccountInfo a = it.next();
      b.append("{")
          .append(a._accountId)
          .append(", ")
          .append("name=")
          .append(a.name)
          .append(", ")
          .append("email=")
          .append(a.email)
          .append(", ")
          .append("username=")
          .append(a.username)
          .append("}");
      if (it.hasNext()) {
        b.append(", ");
      }
    }
    b.append("]");
    return b.toString();
  }

  protected static Iterable<Integer> ids(AccountInfo... accounts) {
    return ids(Arrays.asList(accounts));
  }

  protected static Iterable<Integer> ids(List<AccountInfo> accounts) {
    return accounts.stream().map(a -> a._accountId).collect(toList());
  }

  protected void assertFailingQuery(QueryRequest query, String expectedMessage) throws Exception {
    try {
      assertQuery(query);
      fail("expected BadRequestException for query '" + query + "'");
    } catch (BadRequestException e) {
      assertThat(e.getMessage()).isEqualTo(expectedMessage);
    }
  }

  /** Boiler plate code to check two byte arrays for equality */
  private static class ByteArrayWrapper {
    private byte[] arr;

    private ByteArrayWrapper(byte[] arr) {
      this.arr = arr;
    }

    @Override
    public boolean equals(Object other) {
      if (!(other instanceof ByteArrayWrapper)) {
        return false;
      }
      return Arrays.equals(arr, ((ByteArrayWrapper) other).arr);
    }

    @Override
    public int hashCode() {
      return Arrays.hashCode(arr);
    }
  }
}
