// 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.backend;

import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.plugins.codeowners.testing.CodeOwnerSubject.assertThat;
import static com.google.gerrit.plugins.codeowners.testing.OptionalResultWithMessagesSubject.assertThat;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;

import com.google.common.collect.ImmutableSet;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.TestMetricMaker;
import com.google.gerrit.acceptance.config.GerritConfig;
import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.entities.Account;
import com.google.gerrit.plugins.codeowners.acceptance.AbstractCodeOwnersTest;
import com.google.gerrit.server.ServerInitiated;
import com.google.gerrit.server.account.AccountsUpdate;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.account.externalids.ExternalIdNotes;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.inject.Inject;
import com.google.inject.Key;
import com.google.inject.Provider;
import java.nio.file.Paths;
import java.util.Optional;
import java.util.Set;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.junit.Before;
import org.junit.Test;

/** Tests for {@link CodeOwnerResolver}. */
public class CodeOwnerResolverTest extends AbstractCodeOwnersTest {
  private static final ObjectId TEST_REVISION =
      ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");

  @Inject private RequestScopeOperations requestScopeOperations;
  @Inject @ServerInitiated private Provider<AccountsUpdate> accountsUpdate;
  @Inject private AccountOperations accountOperations;
  @Inject private ExternalIdNotes.Factory externalIdNotesFactory;
  @Inject private TestMetricMaker testMetricMaker;

  private Provider<CodeOwnerResolver> codeOwnerResolverProvider;

  @Before
  public void setUpCodeOwnersPlugin() throws Exception {
    codeOwnerResolverProvider =
        plugin.getSysInjector().getInstance(new Key<Provider<CodeOwnerResolver>>() {});
  }

  @Test
  public void cannotResolveNullToCodeOwner() throws Exception {
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                codeOwnerResolverProvider
                    .get()
                    .resolve(/* codeOwnerReference= */ (CodeOwnerReference) null));
    assertThat(npe).hasMessageThat().isEqualTo("codeOwnerReference");

    npe =
        assertThrows(
            NullPointerException.class,
            () ->
                codeOwnerResolverProvider
                    .get()
                    .resolve(/* codeOwnerReferences= */ (Set<CodeOwnerReference>) null));
    assertThat(npe).hasMessageThat().isEqualTo("codeOwnerReferences");
  }

  @Test
  public void resolveCodeOwnerReferenceForNonExistingEmail() throws Exception {
    String nonExistingEmail = "non-existing@example.com";
    OptionalResultWithMessages<CodeOwner> result =
        codeOwnerResolverProvider
            .get()
            .resolveWithMessages(CodeOwnerReference.create(nonExistingEmail));
    assertThat(result).isEmpty();
    assertThat(result)
        .hasMessagesThat()
        .contains(
            String.format(
                "cannot resolve code owner email %s: no account with this email exists",
                nonExistingEmail));
  }

  @Test
  public void resolveCodeOwnerReferenceForEmail() throws Exception {
    OptionalResultWithMessages<CodeOwner> result =
        codeOwnerResolverProvider
            .get()
            .resolveWithMessages(CodeOwnerReference.create(admin.email()));
    assertThat(result.get()).hasAccountIdThat().isEqualTo(admin.id());
    assertThat(result)
        .hasMessagesThat()
        .contains(String.format("account %s is visible to user %s", admin.id(), admin.username()));
  }

  @Test
  public void cannotResolveCodeOwnerReferenceForStarAsEmail() throws Exception {
    OptionalResultWithMessages<CodeOwner> result =
        codeOwnerResolverProvider
            .get()
            .resolveWithMessages(CodeOwnerReference.create(CodeOwnerResolver.ALL_USERS_WILDCARD));
    assertThat(result).isEmpty();
    assertThat(result)
        .hasMessagesThat()
        .contains(
            String.format(
                "cannot resolve code owner email %s: no account with this email exists",
                CodeOwnerResolver.ALL_USERS_WILDCARD));
  }

  @Test
  public void resolveCodeOwnerReferenceForAmbiguousEmailIfOtherAccountIsInactive()
      throws Exception {
    // Create an external ID for 'user' account that has the same email as the 'admin' account.
    accountsUpdate
        .get()
        .update(
            "Test update",
            user.id(),
            (a, u) ->
                u.addExternalId(
                    ExternalId.create(
                        "foo", "bar", user.id(), admin.email(), /* hashedPassword= */ null)));

    // Deactivate the 'user' account.
    accountOperations.account(user.id()).forUpdate().inactive().update();

    OptionalResultWithMessages<CodeOwner> result =
        codeOwnerResolverProvider
            .get()
            .resolveWithMessages(CodeOwnerReference.create(admin.email()));
    assertThat(result.get()).hasAccountIdThat().isEqualTo(admin.id());
  }

  @Test
  public void resolveCodeOwnerReferenceForAmbiguousEmail() throws Exception {
    // Create an external ID for 'user' account that has the same email as the 'admin' account.
    accountsUpdate
        .get()
        .update(
            "Test update",
            user.id(),
            (a, u) ->
                u.addExternalId(
                    ExternalId.create(
                        "foo", "bar", user.id(), admin.email(), /* hashedPassword= */ null)));

    OptionalResultWithMessages<CodeOwner> result =
        codeOwnerResolverProvider
            .get()
            .resolveWithMessages(CodeOwnerReference.create(admin.email()));
    assertThat(result).isEmpty();
    assertThat(result)
        .hasMessagesThat()
        .contains(
            String.format("cannot resolve code owner email %s: email is ambiguous", admin.email()));
  }

  @Test
  public void resolveCodeOwnerReferenceForOrphanedEmail() throws Exception {
    // Create an external ID with an email for a non-existing account.
    String email = "foo.bar@example.com";
    Account.Id accountId = Account.id(999999);
    try (Repository allUsersRepo = repoManager.openRepository(allUsers);
        MetaDataUpdate md = metaDataUpdateFactory.create(allUsers)) {
      ExternalIdNotes extIdNotes = externalIdNotesFactory.load(allUsersRepo);
      extIdNotes.upsert(ExternalId.createEmail(accountId, email));
      extIdNotes.commit(md);
    }

    OptionalResultWithMessages<CodeOwner> result =
        codeOwnerResolverProvider.get().resolveWithMessages(CodeOwnerReference.create(email));
    assertThat(result).isEmpty();
    assertThat(result)
        .hasMessagesThat()
        .containsAnyOf(
            String.format(
                "cannot resolve account %s for email %s: account does not exists",
                accountId, email),
            String.format(
                "cannost resolve code owner email %s: no active account with this email found",
                email));
  }

  @Test
  public void resolveCodeOwnerReferenceForInactiveUser() throws Exception {
    accountOperations.account(user.id()).forUpdate().inactive().update();
    OptionalResultWithMessages<CodeOwner> result =
        codeOwnerResolverProvider
            .get()
            .resolveWithMessages(CodeOwnerReference.create(user.email()));
    assertThat(result).isEmpty();
    assertThat(result)
        .hasMessagesThat()
        .contains(
            String.format("ignoring inactive account %s for email %s", user.id(), user.email()));
  }

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

    // Set user2 as current user.
    requestScopeOperations.setApiUser(user2.id());

    // user2 cannot see the admin account since they do not share any group and
    // "accounts.visibility" is set to "SAME_GROUP".
    OptionalResultWithMessages<CodeOwner> result =
        codeOwnerResolverProvider
            .get()
            .resolveWithMessages(CodeOwnerReference.create(admin.email()));
    assertThat(result).isEmpty();
    assertThat(result)
        .hasMessagesThat()
        .contains(
            String.format(
                "cannot resolve code owner email %s: account %s is not visible to user %s",
                admin.email(), admin.id(), user2.username()));
  }

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

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

    // admin has the "Modify Account" global capability and hence can see the secondary email of the
    // user account.
    OptionalResultWithMessages<CodeOwner> result =
        codeOwnerResolverProvider
            .get()
            .resolveWithMessages(CodeOwnerReference.create(secondaryEmail));
    assertThat(result.get()).hasAccountIdThat().isEqualTo(user.id());
    assertThat(result)
        .hasMessagesThat()
        .contains(
            String.format(
                "resolved code owner email %s: account %s is referenced by secondary email and the calling user %s can see secondary emails",
                secondaryEmail, user.id(), admin.username()));

    // admin has the "Modify Account" global capability and hence can see the secondary email of the
    // user account if another user is the calling user
    requestScopeOperations.setApiUser(user2.id());
    result =
        codeOwnerResolverProvider
            .get()
            .forUser(identifiedUserFactory.create(admin.id()))
            .resolveWithMessages(CodeOwnerReference.create(secondaryEmail));
    assertThat(result.get()).hasAccountIdThat().isEqualTo(user.id());
    assertThat(result)
        .hasMessagesThat()
        .contains(
            String.format(
                "resolved code owner email %s: account %s is referenced by secondary email and user %s can see secondary emails",
                secondaryEmail, user.id(), admin.username()));

    // user can see its own secondary email.
    requestScopeOperations.setApiUser(user.id());
    result =
        codeOwnerResolverProvider
            .get()
            .resolveWithMessages(CodeOwnerReference.create(secondaryEmail));
    assertThat(result.get()).hasAccountIdThat().isEqualTo(user.id());
    assertThat(result)
        .hasMessagesThat()
        .contains(
            String.format(
                "email %s is visible to the calling user %s: email is a secondary email that is owned by this user",
                secondaryEmail, user.username()));

    // user can see its own secondary email if another user is the calling user.
    requestScopeOperations.setApiUser(user2.id());
    result =
        codeOwnerResolverProvider
            .get()
            .forUser(identifiedUserFactory.create(user.id()))
            .resolveWithMessages(CodeOwnerReference.create(secondaryEmail));
    assertThat(result.get()).hasAccountIdThat().isEqualTo(user.id());
    assertThat(result)
        .hasMessagesThat()
        .contains(
            String.format(
                "email %s is visible to user %s: email is a secondary email that is owned by this user",
                secondaryEmail, user.username()));
  }

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

    // user doesn't have the "Modify Account" global capability and hence cannot see the secondary
    // email of the admin account.
    requestScopeOperations.setApiUser(user.id());
    OptionalResultWithMessages<CodeOwner> result =
        codeOwnerResolverProvider
            .get()
            .resolveWithMessages(CodeOwnerReference.create(secondaryEmail));
    assertThat(result).isEmpty();
    assertThat(result)
        .hasMessagesThat()
        .contains(
            String.format(
                "cannot resolve code owner email %s: account %s is referenced by secondary email but the calling user %s cannot see secondary emails",
                secondaryEmail, admin.id(), user.username()));

    // user doesn't have the "Modify Account" global capability and hence cannot see the secondary
    // email of the admin account if another user is the calling user
    requestScopeOperations.setApiUser(admin.id());
    result =
        codeOwnerResolverProvider
            .get()
            .forUser(identifiedUserFactory.create(user.id()))
            .resolveWithMessages(CodeOwnerReference.create(secondaryEmail));
    assertThat(result).isEmpty();
    assertThat(result)
        .hasMessagesThat()
        .contains(
            String.format(
                "cannot resolve code owner email %s: account %s is referenced by secondary email but user %s cannot see secondary emails",
                secondaryEmail, admin.id(), user.username()));
  }

  @Test
  public void resolvePathCodeOwnersForEmptyCodeOwnerConfig() throws Exception {
    CodeOwnerConfig codeOwnerConfig =
        CodeOwnerConfig.builder(CodeOwnerConfig.Key.create(project, "master", "/"), TEST_REVISION)
            .build();
    CodeOwnerResolverResult result =
        codeOwnerResolverProvider
            .get()
            .resolvePathCodeOwners(codeOwnerConfig, Paths.get("/README.md"));
    assertThat(result.codeOwners()).isEmpty();
    assertThat(result.ownedByAllUsers()).isFalse();
    assertThat(result.hasUnresolvedCodeOwners()).isFalse();
  }

  @Test
  public void resolvePathCodeOwners() throws Exception {
    CodeOwnerConfig codeOwnerConfig =
        CodeOwnerConfig.builder(CodeOwnerConfig.Key.create(project, "master", "/"), TEST_REVISION)
            .addCodeOwnerSet(CodeOwnerSet.createWithoutPathExpressions(admin.email(), user.email()))
            .build();

    CodeOwnerResolverResult result =
        codeOwnerResolverProvider
            .get()
            .resolvePathCodeOwners(codeOwnerConfig, Paths.get("/README.md"));
    assertThat(result.codeOwnersAccountIds()).containsExactly(admin.id(), user.id());
    assertThat(result.ownedByAllUsers()).isFalse();
    assertThat(result.hasUnresolvedCodeOwners()).isFalse();
  }

  @Test
  public void resolvePathCodeOwnersWhenStarIsUsedAsEmail() throws Exception {
    CodeOwnerConfig codeOwnerConfig =
        CodeOwnerConfig.builder(CodeOwnerConfig.Key.create(project, "master", "/"), TEST_REVISION)
            .addCodeOwnerSet(
                CodeOwnerSet.createWithoutPathExpressions(CodeOwnerResolver.ALL_USERS_WILDCARD))
            .build();

    CodeOwnerResolverResult result =
        codeOwnerResolverProvider
            .get()
            .resolvePathCodeOwners(codeOwnerConfig, Paths.get("/README.md"));
    assertThat(result.codeOwnersAccountIds()).isEmpty();
    assertThat(result.ownedByAllUsers()).isTrue();
    assertThat(result.hasUnresolvedCodeOwners()).isFalse();
  }

  @Test
  public void resolvePathCodeOwnersNonResolvableCodeOwnersAreFilteredOut() throws Exception {
    CodeOwnerConfig codeOwnerConfig =
        CodeOwnerConfig.builder(CodeOwnerConfig.Key.create(project, "master", "/"), TEST_REVISION)
            .addCodeOwnerSet(
                CodeOwnerSet.createWithoutPathExpressions(
                    admin.email(), "non-existing@example.com"))
            .build();
    CodeOwnerResolverResult result =
        codeOwnerResolverProvider
            .get()
            .resolvePathCodeOwners(codeOwnerConfig, Paths.get("/README.md"));
    assertThat(result.codeOwnersAccountIds()).containsExactly(admin.id());
    assertThat(result.ownedByAllUsers()).isFalse();
    assertThat(result.hasUnresolvedCodeOwners()).isTrue();
  }

  @Test
  public void resolvePathCodeOwnersNonResolvableCodeOwnersAreFilteredOutIfOwnedByAllUsers()
      throws Exception {
    CodeOwnerConfig codeOwnerConfig =
        CodeOwnerConfig.builder(CodeOwnerConfig.Key.create(project, "master", "/"), TEST_REVISION)
            .addCodeOwnerSet(
                CodeOwnerSet.createWithoutPathExpressions(
                    "*", admin.email(), "non-existing@example.com"))
            .build();
    CodeOwnerResolverResult result =
        codeOwnerResolverProvider
            .get()
            .resolvePathCodeOwners(codeOwnerConfig, Paths.get("/README.md"));
    assertThat(result.codeOwnersAccountIds()).containsExactly(admin.id());
    assertThat(result.ownedByAllUsers()).isTrue();
    assertThat(result.hasUnresolvedCodeOwners()).isTrue();
  }

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

    CodeOwnerConfig codeOwnerConfig =
        CodeOwnerConfig.builder(CodeOwnerConfig.Key.create(project, "master", "/"), TEST_REVISION)
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addCodeOwnerEmail(admin.email())
                    .addAnnotation(admin.email(), CodeOwnerAnnotation.create("FOO"))
                    .addAnnotation(admin.email(), CodeOwnerAnnotation.create("BAR"))
                    .addCodeOwnerEmail(user.email())
                    .addAnnotation(user.email(), CodeOwnerAnnotation.create("BAZ"))
                    .addCodeOwnerEmail(user2.email())
                    .build())
            .build();

    CodeOwnerResolverResult result =
        codeOwnerResolverProvider
            .get()
            .resolvePathCodeOwners(codeOwnerConfig, Paths.get("/README.md"));
    assertThat(result.codeOwnersAccountIds()).containsExactly(admin.id(), user.id(), user2.id());
    assertThat(result.annotations().keySet())
        .containsExactly(CodeOwner.create(admin.id()), CodeOwner.create(user.id()));
    assertThat(result.annotations().get(CodeOwner.create(admin.id())))
        .containsExactly(CodeOwnerAnnotation.create("FOO"), CodeOwnerAnnotation.create("BAR"));
    assertThat(result.annotations().get(CodeOwner.create(user.id())))
        .containsExactly(CodeOwnerAnnotation.create("BAZ"));
  }

  @Test
  public void resolvePathCodeOwnersWithAnnotations_annotationOnAllUsersWildcard() throws Exception {
    CodeOwnerConfig codeOwnerConfig =
        CodeOwnerConfig.builder(CodeOwnerConfig.Key.create(project, "master", "/"), TEST_REVISION)
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addCodeOwnerEmail(admin.email())
                    .addAnnotation(admin.email(), CodeOwnerAnnotation.create("FOO"))
                    .addCodeOwnerEmail(CodeOwnerResolver.ALL_USERS_WILDCARD)
                    .addAnnotation(
                        CodeOwnerResolver.ALL_USERS_WILDCARD, CodeOwnerAnnotation.create("BAR"))
                    .addCodeOwnerEmail(user.email())
                    .build())
            .build();

    CodeOwnerResolverResult result =
        codeOwnerResolverProvider
            .get()
            .resolvePathCodeOwners(codeOwnerConfig, Paths.get("/README.md"));
    assertThat(result.codeOwnersAccountIds()).containsExactly(admin.id(), user.id());
    assertThat(result.annotations().keySet())
        .containsExactly(CodeOwner.create(admin.id()), CodeOwner.create(user.id()));
    assertThat(result.annotations().get(CodeOwner.create(admin.id())))
        .containsExactly(CodeOwnerAnnotation.create("FOO"), CodeOwnerAnnotation.create("BAR"));
    assertThat(result.annotations().get(CodeOwner.create(user.id())))
        .containsExactly(CodeOwnerAnnotation.create("BAR"));
  }

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

    CodeOwnerConfig codeOwnerConfig =
        CodeOwnerConfig.builder(CodeOwnerConfig.Key.create(project, "master", "/"), TEST_REVISION)
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addCodeOwnerEmail(user.email())
                    .addAnnotation(user.email(), CodeOwnerAnnotation.create("FOO"))
                    .addCodeOwnerEmail(secondaryEmail)
                    .addAnnotation(secondaryEmail, CodeOwnerAnnotation.create("BAR"))
                    .build())
            .build();

    // admin has the "Modify Account" global capability and hence can see the secondary email of the
    // user account.
    CodeOwnerResolverResult result =
        codeOwnerResolverProvider
            .get()
            .resolvePathCodeOwners(codeOwnerConfig, Paths.get("/README.md"));
    assertThat(result.codeOwnersAccountIds()).containsExactly(user.id());
    assertThat(result.annotations().keySet()).containsExactly(CodeOwner.create(user.id()));
    assertThat(result.annotations().get(CodeOwner.create(user.id())))
        .containsExactly(CodeOwnerAnnotation.create("FOO"), CodeOwnerAnnotation.create("BAR"));
  }

  @Test
  public void cannotResolvePathCodeOwnersOfNullCodeOwnerConfig() throws Exception {
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                codeOwnerResolverProvider
                    .get()
                    .resolvePathCodeOwners(/* codeOwnerConfig= */ null, Paths.get("/README.md")));
    assertThat(npe).hasMessageThat().isEqualTo("codeOwnerConfig");
  }

  @Test
  public void cannotResolvePathCodeOwnersForNullPath() throws Exception {
    CodeOwnerConfig codeOwnerConfig =
        CodeOwnerConfig.builder(CodeOwnerConfig.Key.create(project, "master", "/"), TEST_REVISION)
            .addCodeOwnerSet(CodeOwnerSet.createWithoutPathExpressions(admin.email()))
            .build();
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                codeOwnerResolverProvider
                    .get()
                    .resolvePathCodeOwners(codeOwnerConfig, /* absolutePath= */ null));
    assertThat(npe).hasMessageThat().isEqualTo("absolutePath");
  }

  @Test
  public void cannotResolvePathCodeOwnersOfNullPathCodeOwners() throws Exception {
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                codeOwnerResolverProvider.get().resolvePathCodeOwners(/* pathCodeOwners= */ null));
    assertThat(npe).hasMessageThat().isEqualTo("pathCodeOwners");
  }

  @Test
  public void cannotResolvePathCodeOwnersForRelativePath() throws Exception {
    String relativePath = "foo/bar.md";
    CodeOwnerConfig codeOwnerConfig =
        CodeOwnerConfig.builder(CodeOwnerConfig.Key.create(project, "master", "/"), TEST_REVISION)
            .addCodeOwnerSet(CodeOwnerSet.createWithoutPathExpressions(admin.email()))
            .build();
    IllegalStateException npe =
        assertThrows(
            IllegalStateException.class,
            () ->
                codeOwnerResolverProvider
                    .get()
                    .resolvePathCodeOwners(codeOwnerConfig, Paths.get(relativePath)));
    assertThat(npe)
        .hasMessageThat()
        .isEqualTo(String.format("path %s must be absolute", relativePath));
  }

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

    // Set user2 as current user.
    requestScopeOperations.setApiUser(user2.id());

    CodeOwnerReference adminCodeOwnerReference = CodeOwnerReference.create(admin.email());

    // user2 cannot see the admin account since they do not share any group and
    // "accounts.visibility" is set to "SAME_GROUP".
    assertThat(codeOwnerResolverProvider.get().resolve(adminCodeOwnerReference)).isEmpty();

    // if visibility is not enforced the code owner reference can be resolved regardless
    Optional<CodeOwner> codeOwner =
        codeOwnerResolverProvider.get().enforceVisibility(false).resolve(adminCodeOwnerReference);
    assertThat(codeOwner).value().hasAccountIdThat().isEqualTo(admin.id());
  }

  @Test
  @GerritConfig(name = "accounts.visibility", value = "SAME_GROUP")
  public void codeOwnerVisibilityIsCheckedForGivenAccount() throws Exception {
    // Create a new user that is not a member of any group. This means 'user' and 'admin' are not
    // visible to this user since they do not share any group.
    TestAccount user2 = accountCreator.user2();

    // admin is the current user and can see the account
    assertThat(codeOwnerResolverProvider.get().resolve(CodeOwnerReference.create(user.email())))
        .isPresent();
    assertThat(
            codeOwnerResolverProvider
                .get()
                .forUser(identifiedUserFactory.create(admin.id()))
                .resolve(CodeOwnerReference.create(user.email())))
        .isPresent();

    // user2 cannot see the account
    assertThat(
            codeOwnerResolverProvider
                .get()
                .forUser(identifiedUserFactory.create(user2.id()))
                .resolve(CodeOwnerReference.create(user.email())))
        .isEmpty();
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.allowedEmailDomain", value = "example.net")
  public void resolveCodeOwnerReferenceForEmailWithNonAllowedEmailDomain() throws Exception {
    assertThat(
            codeOwnerResolverProvider.get().resolve(CodeOwnerReference.create("foo@example.com")))
        .isEmpty();
  }

  @Test
  public void isEmailDomainAllowedRequiresEmailToBeNonNull() throws Exception {
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () -> codeOwnerResolverProvider.get().isEmailDomainAllowed(/* email= */ null));
    assertThat(npe).hasMessageThat().isEqualTo("email");
  }

  @Test
  @GerritConfig(
      name = "plugin.code-owners.allowedEmailDomain",
      values = {"example.com", "example.net"})
  public void configuredEmailDomainsAreAllowed() throws Exception {
    assertIsEmailDomainAllowed(
        "foo@example.com", true, "domain example.com of email foo@example.com is allowed");
    assertIsEmailDomainAllowed(
        "foo@example.net", true, "domain example.net of email foo@example.net is allowed");
    assertIsEmailDomainAllowed(
        "foo@example.org@example.com",
        true,
        "domain example.com of email foo@example.org@example.com is allowed");
    assertIsEmailDomainAllowed(
        "foo@example.org", false, "domain example.org of email foo@example.org is not allowed");
    assertIsEmailDomainAllowed("foo", false, "email foo has no domain");
    assertIsEmailDomainAllowed(
        "foo@example.com@example.org",
        false,
        "domain example.org of email foo@example.com@example.org is not allowed");
    assertIsEmailDomainAllowed(
        CodeOwnerResolver.ALL_USERS_WILDCARD, true, "all users wildcard is allowed");
  }

  @Test
  public void allEmailDomainsAreAllowed() throws Exception {
    String expectedMessage = "all domains are allowed";
    assertIsEmailDomainAllowed("foo@example.com", true, expectedMessage);
    assertIsEmailDomainAllowed("foo@example.net", true, expectedMessage);
    assertIsEmailDomainAllowed("foo@example.org@example.com", true, expectedMessage);
    assertIsEmailDomainAllowed("foo@example.org", true, expectedMessage);
    assertIsEmailDomainAllowed("foo", true, expectedMessage);
    assertIsEmailDomainAllowed("foo@example.com@example.org", true, expectedMessage);
    assertIsEmailDomainAllowed(CodeOwnerResolver.ALL_USERS_WILDCARD, true, expectedMessage);
  }

  private void assertIsEmailDomainAllowed(
      String email, boolean expectedResult, String expectedMessage) {
    OptionalResultWithMessages<Boolean> isEmailDomainAllowedResult =
        codeOwnerResolverProvider.get().isEmailDomainAllowed(email);
    assertThat(isEmailDomainAllowedResult.get()).isEqualTo(expectedResult);
    assertThat(isEmailDomainAllowedResult.messages()).containsExactly(expectedMessage);
  }

  @Test
  public void resolveCodeOwnerReferences() throws Exception {
    CodeOwnerResolverResult result =
        codeOwnerResolverProvider
            .get()
            .resolve(
                ImmutableSet.of(
                    CodeOwnerReference.create(admin.email()),
                    CodeOwnerReference.create(user.email())));
    assertThat(result.codeOwnersAccountIds()).containsExactly(admin.id(), user.id());
    assertThat(result.ownedByAllUsers()).isFalse();
    assertThat(result.hasUnresolvedCodeOwners()).isFalse();
  }

  @Test
  public void resolveCodeOwnerReferencesNonResolveableCodeOwnersAreFilteredOut() throws Exception {
    CodeOwnerResolverResult result =
        codeOwnerResolverProvider
            .get()
            .resolve(
                ImmutableSet.of(
                    CodeOwnerReference.create(admin.email()),
                    CodeOwnerReference.create("non-existing@example.com")));
    assertThat(result.codeOwnersAccountIds()).containsExactly(admin.id());
    assertThat(result.ownedByAllUsers()).isFalse();
    assertThat(result.hasUnresolvedCodeOwners()).isTrue();
  }

  @Test
  public void isResolvable() throws Exception {
    assertThat(
            codeOwnerResolverProvider.get().isResolvable(CodeOwnerReference.create(admin.email())))
        .isTrue();
  }

  @Test
  public void isNotResolvable() throws Exception {
    assertThat(
            codeOwnerResolverProvider
                .get()
                .isResolvable(CodeOwnerReference.create("unknown@example.com")))
        .isFalse();
  }

  @Test
  public void emailIsResolvedOnlyOnce() throws Exception {
    testMetricMaker.reset();
    CodeOwnerResolver codeOwnerResolver = codeOwnerResolverProvider.get();
    OptionalResultWithMessages<CodeOwner> result =
        codeOwnerResolver.resolveWithMessages(CodeOwnerReference.create(admin.email()));
    assertThat(result.get()).hasAccountIdThat().isEqualTo(admin.id());
    assertThat(testMetricMaker.getCount("plugins/code-owners/count_code_owner_resolutions"))
        .isEqualTo(1);
    assertThat(testMetricMaker.getCount("plugins/code-owners/count_code_owner_cache_reads"))
        .isEqualTo(0);

    // Doing the same lookup again doesn't resolve the code owner again.
    testMetricMaker.reset();
    result = codeOwnerResolver.resolveWithMessages(CodeOwnerReference.create(admin.email()));
    assertThat(result.get()).hasAccountIdThat().isEqualTo(admin.id());
    assertThat(testMetricMaker.getCount("plugins/code-owners/count_code_owner_resolutions"))
        .isEqualTo(0);
    assertThat(testMetricMaker.getCount("plugins/code-owners/count_code_owner_cache_reads"))
        .isEqualTo(1);
  }

  @Test
  public void nonExistingEmailIsResolvedOnlyOnce() throws Exception {
    testMetricMaker.reset();
    CodeOwnerResolver codeOwnerResolver = codeOwnerResolverProvider.get();
    OptionalResultWithMessages<CodeOwner> result =
        codeOwnerResolver.resolveWithMessages(
            CodeOwnerReference.create("non-existing@example.com"));
    assertThat(result).isEmpty();
    assertThat(testMetricMaker.getCount("plugins/code-owners/count_code_owner_resolutions"))
        .isEqualTo(1);
    assertThat(testMetricMaker.getCount("plugins/code-owners/count_code_owner_cache_reads"))
        .isEqualTo(0);

    // Doing the same lookup again doesn't resolve the code owner again.
    testMetricMaker.reset();
    result =
        codeOwnerResolver.resolveWithMessages(
            CodeOwnerReference.create("non-existing@example.com"));
    assertThat(result).isEmpty();
    assertThat(testMetricMaker.getCount("plugins/code-owners/count_code_owner_resolutions"))
        .isEqualTo(0);
    assertThat(testMetricMaker.getCount("plugins/code-owners/count_code_owner_cache_reads"))
        .isEqualTo(1);
  }

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

    // admin has the "Modify Account" global capability and hence can see the secondary email of the
    // user account.
    CodeOwnerResolverResult result =
        codeOwnerResolverProvider
            .get()
            .resolve(
                ImmutableSet.of(
                    CodeOwnerReference.create(user.email()),
                    CodeOwnerReference.create(secondaryEmail)));
    assertThat(result.codeOwnersAccountIds()).containsExactly(user.id());
    assertThat(result.ownedByAllUsers()).isFalse();
    assertThat(result.hasUnresolvedCodeOwners()).isFalse();
  }
}
