// Copyright (C) 2020 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.plugins.codeowners.acceptance.api;

import static com.google.common.truth.Truth.assertThat;
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.plugins.codeowners.testing.CodeOwnerInfoSubject.assertThatList;
import static com.google.gerrit.plugins.codeowners.testing.CodeOwnerInfoSubject.hasAccountId;
import static com.google.gerrit.plugins.codeowners.testing.CodeOwnerInfoSubject.hasAccountName;
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.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.Permission;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.client.ListAccountsOption;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.plugins.codeowners.acceptance.AbstractCodeOwnersIT;
import com.google.gerrit.plugins.codeowners.acceptance.testsuite.TestCodeOwnerConfigCreation;
import com.google.gerrit.plugins.codeowners.acceptance.testsuite.TestPathExpressions;
import com.google.gerrit.plugins.codeowners.api.CodeOwnerInfo;
import com.google.gerrit.plugins.codeowners.api.CodeOwners;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerSet;
import com.google.gerrit.plugins.codeowners.restapi.GetCodeOwnersForPathInBranch;
import com.google.inject.Inject;
import java.util.List;
import java.util.Random;
import org.junit.Before;
import org.junit.Test;

/**
 * Base class of acceptance tests for REST endpoints that extend {@link
 * com.google.gerrit.plugins.codeowners.restapi.AbstractGetCodeOwnersForPath}.
 */
public abstract class AbstractGetCodeOwnersForPathIT extends AbstractCodeOwnersIT {
  /**
   * List of all file paths that are used by the tests. Subclasses can use this list to create these
   * files in the test setup in case they test functionality that requires the files to exist.
   */
  protected static final ImmutableList<String> TEST_PATHS =
      ImmutableList.of(
          "/foo/bar.md", "/foo/bar/baz.md", "/foo/bar/config.txt", "/foo/bar/main.config");

  @Inject private RequestScopeOperations requestScopeOperations;
  @Inject private AccountOperations accountOperations;
  @Inject private GroupOperations groupOperations;
  @Inject private ProjectOperations projectOperations;

  private TestPathExpressions testPathExpressions;

  @Before
  public void setup() throws Exception {
    testPathExpressions = plugin.getSysInjector().getInstance(TestPathExpressions.class);
  }

  /** Must return the {@link CodeOwners} API against which the tests should be run. */
  protected abstract CodeOwners getCodeOwnersApi() throws RestApiException;

  protected List<CodeOwnerInfo> queryCodeOwners(String path) throws RestApiException {
    return queryCodeOwners(getCodeOwnersApi().query(), path);
  }

  protected List<CodeOwnerInfo> queryCodeOwners(CodeOwners.QueryRequest queryRequest, String path)
      throws RestApiException {
    return queryRequest.get(path);
  }

  @Test
  public void getCodeOwnersWhenNoCodeOwnerConfigsExist() throws Exception {
    assertThat(queryCodeOwners("/foo/bar/baz.md")).isEmpty();
  }

  @Test
  public void getCodeOwnersUnrelatedCodeOwnerConfigHasNoEffect() throws Exception {
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/abc/def/")
        .addCodeOwnerEmail(admin.email())
        .addCodeOwnerEmail(user.email())
        .create();
    assertThat(queryCodeOwners("/foo/bar/baz.md")).isEmpty();
  }

  @Test
  public void getCodeOwnersForAbsolutePath() throws Exception {
    testGetCodeOwners(true);
  }

  @Test
  public void getCodeOwnersForNonAbsolutePath() throws Exception {
    testGetCodeOwners(false);
  }

  private void testGetCodeOwners(boolean useAbsolutePath) throws Exception {
    TestAccount user2 = accountCreator.user2();

    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/")
        .addCodeOwnerEmail(admin.email())
        .create();

    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/foo/")
        .addCodeOwnerEmail(user.email())
        .create();

    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/foo/bar/")
        .addCodeOwnerEmail(user2.email())
        .create();

    List<CodeOwnerInfo> codeOwnerInfos =
        queryCodeOwners(useAbsolutePath ? "/foo/bar/baz.md" : "foo/bar/baz.md");
    assertThat(codeOwnerInfos)
        .comparingElementsUsing(hasAccountId())
        .containsExactly(user2.id(), user.id(), admin.id())
        .inOrder();
    assertThat(codeOwnerInfos)
        .comparingElementsUsing(hasAccountName())
        .containsExactly(null, null, null);
  }

  @Test
  public void getCodeOwnersWithIgnoreParentCodeOwners() throws Exception {
    TestAccount user2 = accountCreator.user2();

    // Create some code owner configs.
    // The order below reflects the order in which the code owner configs are evaluated.

    // 1. code owner config that makes "user2" a code owner, inheriting code owners from parent code
    // owner configs is enabled by default
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/foo/bar/")
        .addCodeOwnerEmail(user2.email())
        .create();

    // 2. code owner config that makes "user" a code owner, code owners from parent code owner
    // configs are ignored
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/foo/")
        .ignoreParentCodeOwners()
        .addCodeOwnerEmail(user.email())
        .create();

    // 3. code owner config that makes "admin" a code owner, but for this test this code owner
    // config is ignored, since the 2. code owner config ignores code owners from parent code owner
    // configs
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/")
        .addCodeOwnerEmail(admin.email())
        .create();

    // Assert the code owners for "/foo/bar/baz.md". This evaluates the code owner configs in the
    // order: 1., 2., 3.
    // The 3. code owner config is ignored since the 2. code owner config has set
    // 'ignoreParentCodeOwners=true'. Hence the expected code owners are only the users that are
    // code owner according to the 1. and 2. code owner config: user2 + user
    List<CodeOwnerInfo> codeOwnerInfos = queryCodeOwners("/foo/bar/baz.md");
    assertThat(codeOwnerInfos)
        .comparingElementsUsing(hasAccountId())
        .containsExactly(user2.id(), user.id())
        .inOrder();
  }

  @Test
  public void getPerFileCodeOwners() throws Exception {
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/foo/bar/")
        .addCodeOwnerSet(
            CodeOwnerSet.builder()
                .addPathExpression(testPathExpressions.matchFileTypeInCurrentFolder("txt"))
                .addCodeOwnerEmail(admin.email())
                .build())
        .addCodeOwnerSet(
            CodeOwnerSet.builder()
                .addPathExpression(testPathExpressions.matchFileTypeInCurrentFolder("md"))
                .addCodeOwnerEmail(user.email())
                .build())
        .create();

    assertThat(queryCodeOwners("/foo/bar/config.txt"))
        .comparingElementsUsing(hasAccountId())
        .containsExactly(admin.id());
    assertThat(queryCodeOwners("/foo/bar/baz.md"))
        .comparingElementsUsing(hasAccountId())
        .containsExactly(user.id());
    assertThat(queryCodeOwners("/foo/bar/main.config")).isEmpty();
  }

  @Test
  public void getCodeOwnersWithAccountDetails() throws Exception {
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/foo/bar/")
        .addCodeOwnerEmail(admin.email())
        .create();

    List<CodeOwnerInfo> codeOwnerInfos =
        queryCodeOwners(
            getCodeOwnersApi().query().withOptions(ListAccountsOption.DETAILS), "/foo/bar/baz.md");
    assertThat(codeOwnerInfos).comparingElementsUsing(hasAccountId()).containsExactly(admin.id());
    assertThat(codeOwnerInfos)
        .comparingElementsUsing(hasAccountName())
        .containsExactly(admin.fullName());
  }

  @Test
  public void getCodeOwnersWithSecondaryEmails() throws Exception {
    // create a code owner config
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/foo/bar/")
        .addCodeOwnerEmail(admin.email())
        .create();

    // add secondary email to admin account
    String secondaryEmail = "admin@foo.bar";
    accountOperations.account(admin.id()).forUpdate().addSecondaryEmail(secondaryEmail).update();

    // Make the request with the admin user that has the 'Modify Account' global capability.
    List<CodeOwnerInfo> codeOwnerInfos =
        queryCodeOwners(
            getCodeOwnersApi().query().withOptions(ListAccountsOption.ALL_EMAILS),
            "/foo/bar/baz.md");
    assertThat(codeOwnerInfos).comparingElementsUsing(hasAccountId()).containsExactly(admin.id());
    assertThatList(codeOwnerInfos)
        .onlyElement()
        .hasSecondaryEmailsThat()
        .containsExactly(secondaryEmail);
  }

  @Test
  public void cannotGetCodeOwnersWithSecondaryEmailsWithoutModifyAccountCapability()
      throws Exception {
    // create a code owner config
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/foo/bar/")
        .addCodeOwnerEmail(admin.email())
        .create();

    // add secondary email to admin account
    String secondaryEmail = "admin@foo.bar";
    accountOperations.account(admin.id()).forUpdate().addSecondaryEmail(secondaryEmail).update();

    // Make the request with a user that doesn't have the 'Modify Account' global capability.
    requestScopeOperations.setApiUser(user.id());

    AuthException exception =
        assertThrows(
            AuthException.class,
            () ->
                queryCodeOwners(
                    getCodeOwnersApi().query().withOptions(ListAccountsOption.ALL_EMAILS),
                    "/foo/bar/baz.md"));
    assertThat(exception).hasMessageThat().isEqualTo("modify account not permitted");
  }

  @Test
  public void getCodeOwnersWithMultipleAccountOptions() throws Exception {
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/foo/bar/")
        .addCodeOwnerEmail(admin.email())
        .create();

    // add secondary email to admin account
    String secondaryEmail = "admin@foo.bar";
    accountOperations.account(admin.id()).forUpdate().addSecondaryEmail(secondaryEmail).update();

    // Make the request with the admin user that has the 'Modify Account' global capability.
    List<CodeOwnerInfo> codeOwnerInfos =
        queryCodeOwners(
            getCodeOwnersApi()
                .query()
                .withOptions(ListAccountsOption.DETAILS, ListAccountsOption.ALL_EMAILS),
            "/foo/bar/baz.md");
    assertThat(codeOwnerInfos).comparingElementsUsing(hasAccountId()).containsExactly(admin.id());
    assertThat(codeOwnerInfos)
        .comparingElementsUsing(hasAccountName())
        .containsExactly(admin.fullName());
    assertThatList(codeOwnerInfos)
        .onlyElement()
        .hasSecondaryEmailsThat()
        .containsExactly(secondaryEmail);
  }

  @Test
  public void accountOptionCannotBeNull() throws Exception {
    NullPointerException npe =
        assertThrows(
            NullPointerException.class, () -> getCodeOwnersApi().query().withOptions(null));
    assertThat(npe).hasMessageThat().isEqualTo("option");
  }

  @Test
  public void furtherAccountOptionsCannotBeNull() throws Exception {
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                getCodeOwnersApi()
                    .query()
                    .withOptions(ListAccountsOption.DETAILS, (ListAccountsOption[]) null));
    assertThat(npe).hasMessageThat().isEqualTo("furtherOptions");
  }

  @Test
  @GerritConfig(name = "accounts.visibility", value = "SAME_GROUP")
  public void nonVisibleCodeOwnersAreFilteredOut() throws Exception {
    // Create 2 accounts that share a group.
    TestAccount user2 = accountCreator.user2();
    TestAccount user3 = accountCreator.create("user3", "user3@example.com", "User3", null);
    groupOperations.newGroup().addMember(user2.id()).addMember(user3.id()).create();

    // Create some code owner configs.
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/")
        .addCodeOwnerEmail(admin.email())
        .addCodeOwnerEmail(user3.email())
        .create();

    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/foo/")
        .addCodeOwnerEmail(user.email())
        .create();

    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/foo/bar/")
        .addCodeOwnerEmail(user2.email())
        .create();

    // Make the request as admin who can see all accounts.
    assertThat(queryCodeOwners("/foo/bar/baz.md"))
        .comparingElementsUsing(hasAccountId())
        .containsExactly(admin.id(), user.id(), user2.id(), user3.id());

    // Make the request as user2. This user only shares a group with user3. Since
    // "accounts.visibility" is set to "SAME_GROUP" user2 can only see user3's account (besides
    // the own account).
    requestScopeOperations.setApiUser(user2.id());

    // We expect only user2 and user3 as code owner (user and admin should be filtered
    // out because user2 cannot see their accounts).
    assertThat(queryCodeOwners("/foo/bar/baz.md"))
        .comparingElementsUsing(hasAccountId())
        .containsExactly(user2.id(), user3.id());
  }

  @Test
  public void codeOwnersThatCannotSeeTheBranchAreFilteredOut() throws Exception {
    // Create a code owner config with 2 code owners.
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/")
        .addCodeOwnerEmail(admin.email())
        .addCodeOwnerEmail(user.email())
        .create();

    // Check that both code owners are suggested.
    assertThat(queryCodeOwners("/foo/bar/baz.md"))
        .comparingElementsUsing(hasAccountId())
        .containsExactly(admin.id(), user.id());

    // Block read access for 'user'.
    AccountGroup.UUID blockedGroupUuid = groupOperations.newGroup().addMember(user.id()).create();
    projectOperations
        .project(project)
        .forUpdate()
        .add(block(Permission.READ).ref("refs/heads/master").group(blockedGroupUuid))
        .update();

    // Expect that 'user' is filtered out now.
    assertThat(queryCodeOwners("/foo/bar/baz.md"))
        .comparingElementsUsing(hasAccountId())
        .containsExactly(admin.id());
  }

  @Test
  public void getCodeOwnersReferencedBySecondaryEmails() throws Exception {
    // add secondary email to user account
    String secondaryEmail = "user@foo.bar";
    accountOperations.account(user.id()).forUpdate().addSecondaryEmail(secondaryEmail).update();

    // create a code owner config
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/foo/bar/")
        .addCodeOwnerEmail(secondaryEmail)
        .create();

    // admin has the "Modify Account" global capability and hence can see secondary emails
    assertThat(queryCodeOwners("/foo/bar/baz.md"))
        .comparingElementsUsing(hasAccountId())
        .containsExactly(user.id());

    // user can see the own secondary email
    requestScopeOperations.setApiUser(user.id());
    assertThat(queryCodeOwners("/foo/bar/baz.md"))
        .comparingElementsUsing(hasAccountId())
        .containsExactly(user.id());

    // user2 doesn't have the 'Modify Account' global capability and hence cannot see the secondary
    // email
    TestAccount user2 = accountCreator.user2();
    requestScopeOperations.setApiUser(user2.id());
    assertThat(queryCodeOwners("/foo/bar/baz.md")).isEmpty();
  }

  @Test
  public void getCodeOwnersIsLimitedByDefault() throws Exception {
    // Create a code owner config that has more code owners than the number of code owners which are
    // returned by default.
    TestCodeOwnerConfigCreation.Builder codeOwnerConfigCreation =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/");
    for (int i = 1; i <= GetCodeOwnersForPathInBranch.DEFAULT_LIMIT + 1; i++) {
      TestAccount user =
          accountCreator.create("foo" + i, "foo" + i + "@example.com", "Foo " + i, null);
      codeOwnerConfigCreation.addCodeOwnerEmail(user.email());
    }
    codeOwnerConfigCreation.create();

    // Assert that the result is limited by the default limit.
    List<CodeOwnerInfo> codeOwnerInfos = queryCodeOwners("/foo/bar.md");
    assertThat(codeOwnerInfos).hasSize(GetCodeOwnersForPathInBranch.DEFAULT_LIMIT);
  }

  @Test
  public void getCodeOwnersWithLimit() throws Exception {
    TestAccount user2 = accountCreator.user2();

    // create some code owner configs
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/")
        .addCodeOwnerEmail(admin.email())
        .create();

    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/foo/bar/")
        .addCodeOwnerEmail(user.email())
        .addCodeOwnerEmail(user2.email())
        .create();

    // get code owners with different limits
    List<CodeOwnerInfo> codeOwnerInfos =
        queryCodeOwners(getCodeOwnersApi().query().withLimit(1), "/foo/bar/baz.md");
    assertThat(codeOwnerInfos).hasSize(1);
    // the first 2 code owners have the same scoring, so their order is random and we don't know
    // which of them we get when the limit is 1
    assertThatList(codeOwnerInfos).element(0).hasAccountIdThat().isAnyOf(user.id(), user2.id());

    codeOwnerInfos = queryCodeOwners(getCodeOwnersApi().query().withLimit(2), "/foo/bar/baz.md");
    assertThat(codeOwnerInfos)
        .comparingElementsUsing(hasAccountId())
        .containsExactly(user.id(), user2.id());

    codeOwnerInfos = getCodeOwnersApi().query().withLimit(3).get("/foo/bar/baz.md");
    assertThat(codeOwnerInfos)
        .comparingElementsUsing(hasAccountId())
        .containsExactly(admin.id(), user.id(), user2.id());
  }

  @Test
  public void cannotGetCodeOwnersWithoutLimit() throws Exception {
    BadRequestException exception =
        assertThrows(
            BadRequestException.class,
            () -> queryCodeOwners(getCodeOwnersApi().query().withLimit(0), "/foo/bar/baz.md"));
    assertThat(exception).hasMessageThat().isEqualTo("limit must be positive");
  }

  @Test
  public void limitCannotBeNegative() throws Exception {
    BadRequestException exception =
        assertThrows(
            BadRequestException.class,
            () -> queryCodeOwners(getCodeOwnersApi().query().withLimit(-1), "/foo/bar/baz.md"));
    assertThat(exception).hasMessageThat().isEqualTo("limit must be positive");
  }

  @Test
  public void getCodeOwnersIfCodeOwnersFunctionalityIsDisabled() throws Exception {
    disableCodeOwnersForProject(project);

    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/")
        .addCodeOwnerEmail(admin.email())
        .create();

    List<CodeOwnerInfo> codeOwnerInfos = queryCodeOwners("/foo/bar/baz.md");
    assertThat(codeOwnerInfos).comparingElementsUsing(hasAccountId()).containsExactly(admin.id());
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.globalCodeOwner", value = "global.owner@example.com")
  public void getGlobalCodeOwners() throws Exception {
    TestAccount globalOwner =
        accountCreator.create("global_owner", "global.owner@example.com", "Global Owner", null);
    assertThat(queryCodeOwners("/foo/bar/baz.md"))
        .comparingElementsUsing(hasAccountId())
        .containsExactly(globalOwner.id());
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.globalCodeOwner", value = "*")
  public void getAllUsersAsGlobalCodeOwners() throws Exception {
    TestAccount user2 = accountCreator.user2();

    List<CodeOwnerInfo> codeOwnerInfos = queryCodeOwners("/foo/bar/baz.md");
    assertThat(codeOwnerInfos)
        .comparingElementsUsing(hasAccountId())
        .containsExactly(user.id(), user2.id(), admin.id());

    // Query code owners with a limit.
    requestScopeOperations.setApiUser(user.id());
    codeOwnerInfos = queryCodeOwners(getCodeOwnersApi().query().withLimit(2), "/foo/bar/baz.md");
    assertThat(codeOwnerInfos).hasSize(2);
    assertThatList(codeOwnerInfos)
        .element(0)
        .hasAccountIdThat()
        .isAnyOf(user.id(), user2.id(), admin.id());
    assertThatList(codeOwnerInfos)
        .element(1)
        .hasAccountIdThat()
        .isAnyOf(user.id(), user2.id(), admin.id());
  }

  @Test
  @GerritConfig(
      name = "plugin.code-owners.globalCodeOwner",
      values = {"global.owner1@example.com", "global.owner2@example.com"})
  public void getWithGlobalCodeOwnersAndLimit() throws Exception {
    TestAccount globalOwner1 =
        accountCreator.create(
            "global_owner_1", "global.owner1@example.com", "Global Owner 1", null);
    TestAccount globalOwner2 =
        accountCreator.create(
            "global_owner_2", "global.owner2@example.com", "Global Owner 2", null);

    TestAccount user2 = accountCreator.user2();

    // create some code owner configs
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/")
        .addCodeOwnerEmail(admin.email())
        .create();

    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/foo/bar/")
        .addCodeOwnerEmail(user.email())
        .addCodeOwnerEmail(user2.email())
        .create();

    // get code owners with different limits
    List<CodeOwnerInfo> codeOwnerInfos =
        queryCodeOwners(getCodeOwnersApi().query().withLimit(1), "/foo/bar/baz.md");
    assertThat(codeOwnerInfos).hasSize(1);
    // the first 2 code owners have the same scoring, so their order is random and we don't know
    // which of them we get when the limit is 1
    assertThatList(codeOwnerInfos).element(0).hasAccountIdThat().isAnyOf(user.id(), user2.id());

    codeOwnerInfos = queryCodeOwners(getCodeOwnersApi().query().withLimit(2), "/foo/bar/baz.md");
    assertThat(codeOwnerInfos)
        .comparingElementsUsing(hasAccountId())
        .containsExactly(user.id(), user2.id());

    codeOwnerInfos = getCodeOwnersApi().query().withLimit(3).get("/foo/bar/baz.md");
    assertThat(codeOwnerInfos)
        .comparingElementsUsing(hasAccountId())
        .containsExactly(admin.id(), user.id(), user2.id());

    codeOwnerInfos = getCodeOwnersApi().query().withLimit(4).get("/foo/bar/baz.md");
    assertThat(codeOwnerInfos).hasSize(4);
    // the order of the first 2 code owners is random
    assertThatList(codeOwnerInfos).element(0).hasAccountIdThat().isAnyOf(user.id(), user2.id());
    assertThatList(codeOwnerInfos).element(1).hasAccountIdThat().isAnyOf(user.id(), user2.id());
    assertThatList(codeOwnerInfos).element(2).hasAccountIdThat().isEqualTo(admin.id());
    // the order of the global code owners is random
    assertThatList(codeOwnerInfos)
        .element(3)
        .hasAccountIdThat()
        .isAnyOf(globalOwner1.id(), globalOwner2.id());

    codeOwnerInfos = getCodeOwnersApi().query().withLimit(5).get("/foo/bar/baz.md");
    assertThat(codeOwnerInfos)
        .comparingElementsUsing(hasAccountId())
        .containsExactly(admin.id(), user.id(), user2.id(), globalOwner1.id(), globalOwner2.id());
  }

  @Test
  public void getDefaultCodeOwners() throws Exception {
    // Create default code owner config file in refs/meta/config.
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch(RefNames.REFS_CONFIG)
        .folderPath("/")
        .addCodeOwnerEmail(user.email())
        .create();

    assertThat(queryCodeOwners("/foo/bar/baz.md"))
        .comparingElementsUsing(hasAccountId())
        .containsExactly(user.id());
  }

  @Test
  @GerritConfig(
      name = "plugin.code-owners.globalCodeOwner",
      values = {"global.owner1@example.com", "global.owner2@example.com"})
  public void getWithDefaultAndGlobalCodeOwnersAndLimit() throws Exception {
    TestAccount globalOwner1 =
        accountCreator.create(
            "global_owner_1", "global.owner1@example.com", "Global Owner 1", null);
    TestAccount globalOwner2 =
        accountCreator.create(
            "global_owner_2", "global.owner2@example.com", "Global Owner 2", null);

    TestAccount user2 = accountCreator.user2();
    TestAccount defaultCodeOwner1 =
        accountCreator.create("user3", "user3@example.com", "User3", null);
    TestAccount defaultCodeOwner2 =
        accountCreator.create("user4", "user4@example.com", "User4", null);

    // Create default code owner config file in refs/meta/config.
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch(RefNames.REFS_CONFIG)
        .folderPath("/")
        .addCodeOwnerEmail(defaultCodeOwner1.email())
        .addCodeOwnerEmail(defaultCodeOwner2.email())
        .create();

    // create some code owner configs
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/")
        .addCodeOwnerEmail(admin.email())
        .create();

    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/foo/bar/")
        .addCodeOwnerEmail(user.email())
        .addCodeOwnerEmail(user2.email())
        .create();

    // get code owners with different limits
    List<CodeOwnerInfo> codeOwnerInfos =
        queryCodeOwners(getCodeOwnersApi().query().withLimit(1), "/foo/bar/baz.md");
    assertThat(codeOwnerInfos).hasSize(1);
    // the first 2 code owners have the same scoring, so their order is random and we don't know
    // which of them we get when the limit is 1
    assertThatList(codeOwnerInfos).element(0).hasAccountIdThat().isAnyOf(user.id(), user2.id());

    codeOwnerInfos = queryCodeOwners(getCodeOwnersApi().query().withLimit(2), "/foo/bar/baz.md");
    assertThat(codeOwnerInfos)
        .comparingElementsUsing(hasAccountId())
        .containsExactly(user.id(), user2.id());

    codeOwnerInfos = getCodeOwnersApi().query().withLimit(3).get("/foo/bar/baz.md");
    assertThat(codeOwnerInfos)
        .comparingElementsUsing(hasAccountId())
        .containsExactly(admin.id(), user.id(), user2.id());

    codeOwnerInfos = getCodeOwnersApi().query().withLimit(4).get("/foo/bar/baz.md");
    assertThat(codeOwnerInfos).hasSize(4);
    // the order of the first 2 code owners is random
    assertThatList(codeOwnerInfos).element(0).hasAccountIdThat().isAnyOf(user.id(), user2.id());
    assertThatList(codeOwnerInfos).element(1).hasAccountIdThat().isAnyOf(user.id(), user2.id());
    assertThatList(codeOwnerInfos).element(2).hasAccountIdThat().isEqualTo(admin.id());
    // the order of the default code owners is random
    assertThatList(codeOwnerInfos)
        .element(3)
        .hasAccountIdThat()
        .isAnyOf(defaultCodeOwner1.id(), defaultCodeOwner2.id());

    codeOwnerInfos = getCodeOwnersApi().query().withLimit(5).get("/foo/bar/baz.md");
    assertThat(codeOwnerInfos)
        .comparingElementsUsing(hasAccountId())
        .containsExactly(
            admin.id(), user.id(), user2.id(), defaultCodeOwner1.id(), defaultCodeOwner2.id());

    codeOwnerInfos = getCodeOwnersApi().query().withLimit(6).get("/foo/bar/baz.md");
    assertThat(codeOwnerInfos).hasSize(6);
    // the order of the first 2 code owners is random
    assertThatList(codeOwnerInfos).element(0).hasAccountIdThat().isAnyOf(user.id(), user2.id());
    assertThatList(codeOwnerInfos).element(1).hasAccountIdThat().isAnyOf(user.id(), user2.id());
    assertThatList(codeOwnerInfos).element(2).hasAccountIdThat().isEqualTo(admin.id());
    // the order of the default code owners is random
    assertThatList(codeOwnerInfos)
        .element(3)
        .hasAccountIdThat()
        .isAnyOf(defaultCodeOwner1.id(), defaultCodeOwner2.id());
    assertThatList(codeOwnerInfos)
        .element(4)
        .hasAccountIdThat()
        .isAnyOf(defaultCodeOwner1.id(), defaultCodeOwner2.id());
    // the order of the global code owners is random
    assertThatList(codeOwnerInfos)
        .element(5)
        .hasAccountIdThat()
        .isAnyOf(globalOwner1.id(), globalOwner2.id());

    codeOwnerInfos = getCodeOwnersApi().query().withLimit(7).get("/foo/bar/baz.md");
    assertThat(codeOwnerInfos)
        .comparingElementsUsing(hasAccountId())
        .containsExactly(
            admin.id(),
            user.id(),
            user2.id(),
            defaultCodeOwner1.id(),
            defaultCodeOwner2.id(),
            globalOwner1.id(),
            globalOwner2.id());
  }

  @Test
  @GerritConfig(name = "accounts.visibility", value = "ALL")
  public void getAllUsersAsCodeOwners_allVisible() throws Exception {
    TestAccount user2 = accountCreator.user2();

    // Add a code owner config that makes all users code owners.
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/")
        .addCodeOwnerEmail("*")
        .create();

    List<CodeOwnerInfo> codeOwnerInfos = queryCodeOwners("/foo/bar/baz.md");
    assertThat(codeOwnerInfos)
        .comparingElementsUsing(hasAccountId())
        .containsExactly(user.id(), user2.id(), admin.id());

    // Query code owners with a limit.
    requestScopeOperations.setApiUser(user.id());
    codeOwnerInfos = queryCodeOwners(getCodeOwnersApi().query().withLimit(2), "/foo/bar/baz.md");
    assertThat(codeOwnerInfos).hasSize(2);
    assertThatList(codeOwnerInfos)
        .element(0)
        .hasAccountIdThat()
        .isAnyOf(user.id(), user2.id(), admin.id());
    assertThatList(codeOwnerInfos)
        .element(1)
        .hasAccountIdThat()
        .isAnyOf(user.id(), user2.id(), admin.id());
  }

  @Test
  @GerritConfig(name = "accounts.visibility", value = "SAME_GROUP")
  public void getAllUsersAsCodeOwners_sameGroupVisibility() throws Exception {
    // Create 2 accounts that share a group.
    TestAccount user2 = accountCreator.user2();
    TestAccount user3 = accountCreator.create("user3", "user3@example.com", "User3", null);
    groupOperations.newGroup().addMember(user2.id()).addMember(user3.id()).create();

    // Add a code owner config that makes all users code owners.
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/")
        .addCodeOwnerEmail("*")
        .create();

    // user can only see itself
    requestScopeOperations.setApiUser(user.id());
    List<CodeOwnerInfo> codeOwnerInfos = queryCodeOwners("/foo/bar/baz.md");
    assertThat(codeOwnerInfos).comparingElementsUsing(hasAccountId()).containsExactly(user.id());

    // user2 can see user3 and itself
    requestScopeOperations.setApiUser(user2.id());
    codeOwnerInfos = queryCodeOwners("/foo/bar/baz.md");
    assertThat(codeOwnerInfos)
        .comparingElementsUsing(hasAccountId())
        .containsExactly(user2.id(), user3.id());

    // admin can see all users
    requestScopeOperations.setApiUser(admin.id());
    codeOwnerInfos = queryCodeOwners("/foo/bar/baz.md");
    assertThat(codeOwnerInfos)
        .comparingElementsUsing(hasAccountId())
        .containsExactly(admin.id(), user.id(), user2.id(), user3.id());

    // Query code owners with a limit, user2 can see user3 and itself
    requestScopeOperations.setApiUser(user2.id());
    codeOwnerInfos = queryCodeOwners(getCodeOwnersApi().query().withLimit(1), "/foo/bar/baz.md");
    assertThat(codeOwnerInfos).hasSize(1);
    assertThatList(codeOwnerInfos).element(0).hasAccountIdThat().isAnyOf(user2.id(), user3.id());
  }

  @Test
  @GerritConfig(name = "accounts.visibility", value = "VISIBLE_GROUP")
  public void getAllUsersAsCodeOwners_visibleGroupVisibility() throws Exception {
    // create a group that until contains user
    AccountGroup.UUID userGroup = groupOperations.newGroup().addMember(user.id()).create();

    // create user2 account and a group that only contains user2, but which is visible to user
    // (since user owns the group)
    TestAccount user2 = accountCreator.user2();
    groupOperations.newGroup().addMember(user2.id()).ownerGroupUuid(userGroup).create();

    // create user3 account and a group that only contains user3, but which is visible to all users
    TestAccount user3 = accountCreator.create("user3", "user3@example.com", "User3", null);
    groupOperations.newGroup().addMember(user3.id()).visibleToAll(true).create();

    // Add a code owner config that makes all users code owners.
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/")
        .addCodeOwnerEmail("*")
        .create();

    // user can only see itself, user2 (because user is owner of a group that contains user2) and
    // user3 (because user3 is member of a group that is visible to all users)
    requestScopeOperations.setApiUser(user.id());
    List<CodeOwnerInfo> codeOwnerInfos = queryCodeOwners("/foo/bar/baz.md");
    assertThat(codeOwnerInfos)
        .comparingElementsUsing(hasAccountId())
        .containsExactly(user.id(), user2.id(), user3.id());

    // user2 can see user3 and itself
    requestScopeOperations.setApiUser(user2.id());
    codeOwnerInfos = queryCodeOwners("/foo/bar/baz.md");
    assertThat(codeOwnerInfos)
        .comparingElementsUsing(hasAccountId())
        .containsExactly(user2.id(), user3.id());

    // admin can see all users
    requestScopeOperations.setApiUser(admin.id());
    codeOwnerInfos = queryCodeOwners("/foo/bar/baz.md");
    assertThat(codeOwnerInfos)
        .comparingElementsUsing(hasAccountId())
        .containsExactly(admin.id(), user.id(), user2.id(), user3.id());

    // Query code owners with a limit, user2 can see user3 and itself
    requestScopeOperations.setApiUser(user2.id());
    codeOwnerInfos = queryCodeOwners(getCodeOwnersApi().query().withLimit(1), "/foo/bar/baz.md");
    assertThat(codeOwnerInfos).hasSize(1);
    assertThatList(codeOwnerInfos).element(0).hasAccountIdThat().isAnyOf(user2.id(), user3.id());
  }

  @Test
  @GerritConfig(name = "accounts.visibility", value = "NONE")
  public void getAllUsersAsCodeOwners_noneVisible() throws Exception {
    accountCreator.user2();

    // Add a code owner config that makes all users code owners.
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/")
        .addCodeOwnerEmail("*")
        .create();

    // Use user, since admin is allowed to view all accounts.
    requestScopeOperations.setApiUser(user.id());
    List<CodeOwnerInfo> codeOwnerInfos = queryCodeOwners("/foo/bar/baz.md");
    assertThat(codeOwnerInfos).isEmpty();
  }

  @Test
  @GerritConfig(name = "accounts.visibility", value = "NONE")
  public void getAllUsersAsCodeOwners_withViewAllAccounts() throws Exception {
    // Allow all users to view all accounts.
    projectOperations
        .allProjectsForUpdate()
        .add(allowCapability(GlobalCapability.VIEW_ALL_ACCOUNTS).group(REGISTERED_USERS))
        .update();

    TestAccount user2 = accountCreator.user2();

    // Add a code owner config that makes all users code owners.
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/")
        .addCodeOwnerEmail("*")
        .create();

    List<CodeOwnerInfo> codeOwnerInfos = queryCodeOwners("/foo/bar/baz.md");
    assertThat(codeOwnerInfos)
        .comparingElementsUsing(hasAccountId())
        .containsExactly(admin.id(), user.id(), user2.id());
  }

  @Test
  public void getAllUsersAsCodeOwners_explicitlyMentionedCodeOwnersArePreferred() throws Exception {
    TestAccount user2 = accountCreator.user2();

    // Add a code owner config that assigns code ownership to user2 and all users.
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/")
        .addCodeOwnerEmail(user2.email())
        .addCodeOwnerEmail("*")
        .create();

    // Query code owners with limits, "*" is resolved to random users, but user2 should always be
    // included since this user is set explicitly as code owner
    List<CodeOwnerInfo> codeOwnerInfos =
        queryCodeOwners(getCodeOwnersApi().query().withLimit(2), "/foo/bar/baz.md");
    assertThat(codeOwnerInfos).hasSize(2);
    assertThatList(codeOwnerInfos).comparingElementsUsing(hasAccountId()).contains(user2.id());

    codeOwnerInfos = queryCodeOwners(getCodeOwnersApi().query().withLimit(1), "/foo/bar/baz.md");
    assertThatList(codeOwnerInfos)
        .comparingElementsUsing(hasAccountId())
        .containsExactly(user2.id());
  }

  @Test
  public void getCodeOwnersProvidingASeedMakesSortOrderStableAcrocssRequests() throws Exception {
    TestAccount user2 = accountCreator.user2();

    // create some code owner configs
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/")
        .addCodeOwnerEmail(admin.email())
        .addCodeOwnerEmail(user.email())
        .addCodeOwnerEmail(user2.email())
        .create();

    long seed = (new Random()).nextLong();

    List<CodeOwnerInfo> codeOwnerInfos =
        queryCodeOwners(getCodeOwnersApi().query().withSeed(seed), "/foo/bar/baz.md");
    // all code owners have the same score, hence their order is random
    assertThatList(codeOwnerInfos)
        .comparingElementsUsing(hasAccountId())
        .containsExactly(admin.id(), user.id(), user2.id());

    // Check that the order for further requests that use the same seed is the same.
    List<Account.Id> expectedAccountIds =
        codeOwnerInfos.stream().map(info -> Account.id(info.account._accountId)).collect(toList());
    for (int i = 0; i < 10; i++) {
      assertThatList(queryCodeOwners(getCodeOwnersApi().query().withSeed(seed), "/foo/bar/baz.md"))
          .comparingElementsUsing(hasAccountId())
          .containsExactlyElementsIn(expectedAccountIds)
          .inOrder();
    }
  }

  @Test
  public void getCodeOwnersProvidingASeedMakesSortOrderStableAcrossRequests_allUsersAreCodeOwners()
      throws Exception {
    TestAccount user2 = accountCreator.user2();

    // create some code owner configs
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/")
        .addCodeOwnerEmail("*")
        .create();

    long seed = (new Random()).nextLong();

    List<CodeOwnerInfo> codeOwnerInfos =
        queryCodeOwners(getCodeOwnersApi().query().withSeed(seed), "/foo/bar/baz.md");
    // all code owners have the same score, hence their order is random
    assertThatList(codeOwnerInfos)
        .comparingElementsUsing(hasAccountId())
        .containsExactly(admin.id(), user.id(), user2.id());

    // Check that the order for further requests that use the same seed is the same.
    List<Account.Id> expectedAccountIds =
        codeOwnerInfos.stream().map(info -> Account.id(info.account._accountId)).collect(toList());
    for (int i = 0; i < 10; i++) {
      assertThatList(queryCodeOwners(getCodeOwnersApi().query().withSeed(seed), "/foo/bar/baz.md"))
          .comparingElementsUsing(hasAccountId())
          .containsExactlyElementsIn(expectedAccountIds)
          .inOrder();
    }
  }
}
