// 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.testing.GerritJUnit.assertThrows;

import com.google.common.collect.ImmutableSet;
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.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;

  private Provider<CodeOwnerResolver> codeOwnerResolver;

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

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

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

  @Test
  public void resolveCodeOwnerReferenceForNonExistingEmail() throws Exception {
    assertThat(
            codeOwnerResolver.get().resolve(CodeOwnerReference.create("non-existing@example.com")))
        .isEmpty();
  }

  @Test
  public void resolveCodeOwnerReferenceForEmail() throws Exception {
    Optional<CodeOwner> codeOwner =
        codeOwnerResolver.get().resolve(CodeOwnerReference.create(admin.email()));
    assertThat(codeOwner).value().hasAccountIdThat().isEqualTo(admin.id());
  }

  @Test
  public void cannotResolveCodeOwnerReferenceForStarAsEmail() throws Exception {
    Optional<CodeOwner> codeOwner =
        codeOwnerResolver
            .get()
            .resolve(CodeOwnerReference.create(CodeOwnerResolver.ALL_USERS_WILDCARD));
    assertThat(codeOwner).isEmpty();
  }

  @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)));

    assertThat(codeOwnerResolver.get().resolve(CodeOwnerReference.create(admin.email()))).isEmpty();
  }

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

    assertThat(codeOwnerResolver.get().resolve(CodeOwnerReference.create(email))).isEmpty();
  }

  @Test
  public void resolveCodeOwnerReferenceForInactiveUser() throws Exception {
    accountOperations.account(user.id()).forUpdate().inactive().update();
    assertThat(codeOwnerResolver.get().resolve(CodeOwnerReference.create(user.email()))).isEmpty();
  }

  @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".
    assertThat(codeOwnerResolver.get().resolve(CodeOwnerReference.create(admin.email()))).isEmpty();
  }

  @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.
    Optional<CodeOwner> codeOwner =
        codeOwnerResolver.get().resolve(CodeOwnerReference.create(secondaryEmail));
    assertThat(codeOwner).value().hasAccountIdThat().isEqualTo(user.id());

    // 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());
    codeOwner =
        codeOwnerResolver
            .get()
            .forUser(identifiedUserFactory.create(admin.id()))
            .resolve(CodeOwnerReference.create(secondaryEmail));
    assertThat(codeOwner).value().hasAccountIdThat().isEqualTo(user.id());

    // user can see its own secondary email.
    requestScopeOperations.setApiUser(user.id());
    codeOwner = codeOwnerResolver.get().resolve(CodeOwnerReference.create(secondaryEmail));
    assertThat(codeOwner).value().hasAccountIdThat().isEqualTo(user.id());

    // user can see its own secondary email if another user is the calling user.
    requestScopeOperations.setApiUser(user2.id());
    codeOwner =
        codeOwnerResolver
            .get()
            .forUser(identifiedUserFactory.create(user.id()))
            .resolve(CodeOwnerReference.create(secondaryEmail));
    assertThat(codeOwner).value().hasAccountIdThat().isEqualTo(user.id());
  }

  @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());
    assertThat(codeOwnerResolver.get().resolve(CodeOwnerReference.create(secondaryEmail)))
        .isEmpty();

    // 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());
    assertThat(
            codeOwnerResolver
                .get()
                .forUser(identifiedUserFactory.create(user.id()))
                .resolve(CodeOwnerReference.create(secondaryEmail)))
        .isEmpty();
  }

  @Test
  public void resolvePathCodeOwnersForEmptyCodeOwnerConfig() throws Exception {
    CodeOwnerConfig codeOwnerConfig =
        CodeOwnerConfig.builder(CodeOwnerConfig.Key.create(project, "master", "/"), TEST_REVISION)
            .build();
    CodeOwnerResolverResult result =
        codeOwnerResolver.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 =
        codeOwnerResolver.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 =
        codeOwnerResolver.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 =
        codeOwnerResolver.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 =
        codeOwnerResolver.get().resolvePathCodeOwners(codeOwnerConfig, Paths.get("/README.md"));
    assertThat(result.codeOwnersAccountIds()).containsExactly(admin.id());
    assertThat(result.ownedByAllUsers()).isTrue();
    assertThat(result.hasUnresolvedCodeOwners()).isTrue();
  }

  @Test
  public void cannotResolvePathCodeOwnersOfNullCodeOwnerConfig() throws Exception {
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                codeOwnerResolver
                    .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,
            () ->
                codeOwnerResolver
                    .get()
                    .resolvePathCodeOwners(codeOwnerConfig, /* absolutePath= */ null));
    assertThat(npe).hasMessageThat().isEqualTo("absolutePath");
  }

  @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,
            () ->
                codeOwnerResolver
                    .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(codeOwnerResolver.get().resolve(adminCodeOwnerReference)).isEmpty();

    // if visibility is not enforced the code owner reference can be resolved regardless
    Optional<CodeOwner> codeOwner =
        codeOwnerResolver.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(codeOwnerResolver.get().resolve(CodeOwnerReference.create(user.email())))
        .isPresent();
    assertThat(
            codeOwnerResolver
                .get()
                .forUser(identifiedUserFactory.create(admin.id()))
                .resolve(CodeOwnerReference.create(user.email())))
        .isPresent();

    // user2 cannot see the account
    assertThat(
            codeOwnerResolver
                .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(codeOwnerResolver.get().resolve(CodeOwnerReference.create("foo@example.com")))
        .isEmpty();
  }

  @Test
  public void isEmailDomainAllowedRequiresEmailToBeNonNull() throws Exception {
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () -> codeOwnerResolver.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 {
    assertThat(codeOwnerResolver.get().isEmailDomainAllowed("foo@example.com")).isTrue();
    assertThat(codeOwnerResolver.get().isEmailDomainAllowed("foo@example.net")).isTrue();
    assertThat(codeOwnerResolver.get().isEmailDomainAllowed("foo@example.org@example.com"))
        .isTrue();
    assertThat(codeOwnerResolver.get().isEmailDomainAllowed("foo@example.org")).isFalse();
    assertThat(codeOwnerResolver.get().isEmailDomainAllowed("foo")).isFalse();
    assertThat(codeOwnerResolver.get().isEmailDomainAllowed("foo@example.com@example.org"))
        .isFalse();
    assertThat(codeOwnerResolver.get().isEmailDomainAllowed(CodeOwnerResolver.ALL_USERS_WILDCARD))
        .isTrue();
  }

  @Test
  public void allEmailDomainsAreAllowed() throws Exception {
    assertThat(codeOwnerResolver.get().isEmailDomainAllowed("foo@example.com")).isTrue();
    assertThat(codeOwnerResolver.get().isEmailDomainAllowed("foo@example.net")).isTrue();
    assertThat(codeOwnerResolver.get().isEmailDomainAllowed("foo@example.org@example.com"))
        .isTrue();
    assertThat(codeOwnerResolver.get().isEmailDomainAllowed("foo@example.org")).isTrue();
    assertThat(codeOwnerResolver.get().isEmailDomainAllowed("foo")).isTrue();
    assertThat(codeOwnerResolver.get().isEmailDomainAllowed("foo@example.com@example.org"))
        .isTrue();
    assertThat(codeOwnerResolver.get().isEmailDomainAllowed(CodeOwnerResolver.ALL_USERS_WILDCARD))
        .isTrue();
  }

  @Test
  public void resolveCodeOwnerReferences() throws Exception {
    CodeOwnerResolverResult result =
        codeOwnerResolver
            .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 =
        codeOwnerResolver
            .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(codeOwnerResolver.get().isResolvable(CodeOwnerReference.create(admin.email())))
        .isTrue();
  }

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