// 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.common.truth.TruthJUnit.assume;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowLabel;
import static com.google.gerrit.plugins.codeowners.testing.CodeOwnerStatusInfoSubject.assertThat;
import static com.google.gerrit.plugins.codeowners.testing.LegacySubmitRequirementInfoSubject.assertThatCollection;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static com.google.gerrit.testing.TestActionRefUpdateContext.testRefAction;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.TestMetricMaker;
import com.google.gerrit.acceptance.TestProjectInput;
import com.google.gerrit.acceptance.config.GerritConfig;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.api.projects.BranchInput;
import com.google.gerrit.extensions.api.projects.DeleteBranchesInput;
import com.google.gerrit.extensions.client.ChangeStatus;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.SubmitRequirementInput;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.plugins.codeowners.acceptance.AbstractCodeOwnersIT;
import com.google.gerrit.plugins.codeowners.api.CodeOwnerStatusInfo;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerSet;
import com.google.gerrit.plugins.codeowners.backend.findowners.FindOwnersBackend;
import com.google.gerrit.plugins.codeowners.common.CodeOwnerStatus;
import com.google.gerrit.plugins.codeowners.testing.LegacySubmitRequirementInfoSubject;
import com.google.gerrit.plugins.codeowners.util.JgitPath;
import com.google.inject.Inject;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Test;

/** Acceptance test for {@code com.google.gerrit.plugins.codeowners.backend.CodeOwnerSubmitRule}. */
public class CodeOwnerSubmitRuleIT extends AbstractCodeOwnersIT {
  @Inject private RequestScopeOperations requestScopeOperations;
  @Inject private ProjectOperations projectOperations;
  @Inject private TestMetricMaker testMetricMaker;

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

    String changeId = createChange("Test Change", "foo/bar.baz", "file content").getChangeId();

    // Approve by a non-code-owner.
    approve(changeId);

    // Check the submittable flag.
    ChangeInfo changeInfo = gApi.changes().id(changeId).get(ListChangesOption.SUBMITTABLE);
    assertThat(changeInfo.submittable).isTrue();

    // Check that there is no submit requirement.
    assertThat(changeInfo.requirements).isEmpty();

    // Submit the change.
    gApi.changes().id(changeId).current().submit();
    assertThat(gApi.changes().id(changeId).get().status).isEqualTo(ChangeStatus.MERGED);
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.disabled", value = "true")
  @GerritConfig(name = "plugin.code-owners.requiredApproval", value = "INVALID")
  public void changeIsSubmittableIfCodeOwnersFuctionalityIsDisabled_invalidPluginConfig()
      throws Exception {
    String changeId = createChange("Test Change", "foo/bar.baz", "file content").getChangeId();

    // Approve by a non-code-owner.
    approve(changeId);

    // Check the submittable flag.
    ChangeInfo changeInfo = gApi.changes().id(changeId).get(ListChangesOption.SUBMITTABLE);
    assertThat(changeInfo.submittable).isTrue();

    // Check that there is no submit requirement.
    assertThat(changeInfo.requirements).isEmpty();

    // Submit the change.
    gApi.changes().id(changeId).current().submit();
    assertThat(gApi.changes().id(changeId).get().status).isEqualTo(ChangeStatus.MERGED);
  }

  @Test
  public void changeWithInsufficientReviewersIsNotSubmittable() throws Exception {
    testChangeWithInsufficientReviewersIsNotSubmittable();
  }

  @Test
  @TestProjectInput(createEmptyCommit = false)
  public void initialChangeWithInsufficientReviewersIsNotSubmittable() throws Exception {
    testChangeWithInsufficientReviewersIsNotSubmittable();
  }

  private void testChangeWithInsufficientReviewersIsNotSubmittable() throws Exception {
    String changeId = createChange("Test Change", "foo/bar.baz", "file content").getChangeId();

    // Approve by a non-code-owner.
    approve(changeId);

    // Verify that the code owner status for the changed file is INSUFFICIENT_REVIEWERS.
    CodeOwnerStatusInfo codeOwnerStatus =
        changeCodeOwnersApiFactory.change(changeId).getCodeOwnerStatus().get();
    assertThat(codeOwnerStatus)
        .hasFileCodeOwnerStatusesThat()
        .onlyElement()
        .hasNewPathStatusThat()
        .value()
        .hasStatusThat()
        .isEqualTo(CodeOwnerStatus.INSUFFICIENT_REVIEWERS);

    // Check the submittable flag.
    ChangeInfo changeInfo = gApi.changes().id(changeId).get(ListChangesOption.SUBMITTABLE);
    assertThat(changeInfo.submittable).isFalse();

    // Check the submit requirement.
    LegacySubmitRequirementInfoSubject submitRequirementInfoSubject =
        assertThatCollection(changeInfo.requirements).onlyElement();
    submitRequirementInfoSubject.hasStatusThat().isEqualTo("NOT_READY");
    submitRequirementInfoSubject.hasFallbackTextThat().isEqualTo("Code-Owners");
    submitRequirementInfoSubject.hasTypeThat().isEqualTo("code-owners");

    // Try to submit the change.
    ResourceConflictException exception =
        assertThrows(
            ResourceConflictException.class, () -> gApi.changes().id(changeId).current().submit());
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(
            String.format(
                "Failed to submit 1 change due to the following problems:\n"
                    + "Change %d: submit requirement 'Code-Owners' is unsatisfied.",
                changeInfo._number));
  }

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

    testChangeWithPendingCodeOwnerApprovalsIsNotSubmittable(user);
  }

  @Test
  @TestProjectInput(createEmptyCommit = false)
  public void initialChangeWithPendingCodeOwnerApprovalsIsNotSubmittable() throws Exception {
    setAsDefaultCodeOwners(user);

    testChangeWithPendingCodeOwnerApprovalsIsNotSubmittable(user);
  }

  private void testChangeWithPendingCodeOwnerApprovalsIsNotSubmittable(TestAccount codeOwner)
      throws Exception {
    String changeId = createChange("Test Change", "foo/bar.baz", "file content").getChangeId();

    // Add a reviewer that is a code owner.
    gApi.changes().id(changeId).addReviewer(codeOwner.email());

    // Approve by a non-code-owner.
    approve(changeId);

    // Verify that the code owner status for the changed file is PENDING.
    CodeOwnerStatusInfo codeOwnerStatus =
        changeCodeOwnersApiFactory.change(changeId).getCodeOwnerStatus().get();
    assertThat(codeOwnerStatus)
        .hasFileCodeOwnerStatusesThat()
        .onlyElement()
        .hasNewPathStatusThat()
        .value()
        .hasStatusThat()
        .isEqualTo(CodeOwnerStatus.PENDING);

    // Check the submittable flag.
    ChangeInfo changeInfo = gApi.changes().id(changeId).get(ListChangesOption.SUBMITTABLE);
    assertThat(changeInfo.submittable).isFalse();

    // Check the submit requirement.
    LegacySubmitRequirementInfoSubject submitRequirementInfoSubject =
        assertThatCollection(changeInfo.requirements).onlyElement();
    submitRequirementInfoSubject.hasStatusThat().isEqualTo("NOT_READY");
    submitRequirementInfoSubject.hasFallbackTextThat().isEqualTo("Code-Owners");
    submitRequirementInfoSubject.hasTypeThat().isEqualTo("code-owners");

    // Try to submit the change.
    ResourceConflictException exception =
        assertThrows(
            ResourceConflictException.class, () -> gApi.changes().id(changeId).current().submit());
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(
            String.format(
                "Failed to submit 1 change due to the following problems:\n"
                    + "Change %d: submit requirement 'Code-Owners' is unsatisfied.",
                changeInfo._number));
  }

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

    testChangeWithCodeOwnerApprovalsIsSubmittable(user);
  }

  @Test
  @TestProjectInput(createEmptyCommit = false)
  public void initialChangeWithCodeOwnerApprovalsIsSubmittable() throws Exception {
    setAsDefaultCodeOwners(user);

    testChangeWithCodeOwnerApprovalsIsSubmittable(user);
  }

  private void testChangeWithCodeOwnerApprovalsIsSubmittable(TestAccount codeOwner)
      throws Exception {
    String changeId = createChange("Test Change", "foo/bar.baz", "file content").getChangeId();

    // Approve by a code-owner.
    projectOperations
        .project(project)
        .forUpdate()
        .add(allowLabel("Code-Review").ref("refs/heads/*").group(REGISTERED_USERS).range(-2, +2))
        .update();
    requestScopeOperations.setApiUser(codeOwner.id());
    approve(changeId);
    requestScopeOperations.setApiUser(admin.id());

    // Verify that the code owner status for the changed file is APPROVED.
    CodeOwnerStatusInfo codeOwnerStatus =
        changeCodeOwnersApiFactory.change(changeId).getCodeOwnerStatus().get();
    assertThat(codeOwnerStatus)
        .hasFileCodeOwnerStatusesThat()
        .onlyElement()
        .hasNewPathStatusThat()
        .value()
        .hasStatusThat()
        .isEqualTo(CodeOwnerStatus.APPROVED);

    // Check the submittable flag.
    ChangeInfo changeInfo = gApi.changes().id(changeId).get(ListChangesOption.SUBMITTABLE);
    assertThat(changeInfo.submittable).isTrue();

    // Check the submit requirement.
    LegacySubmitRequirementInfoSubject submitRequirementInfoSubject =
        assertThatCollection(changeInfo.requirements).onlyElement();
    submitRequirementInfoSubject.hasStatusThat().isEqualTo("OK");
    submitRequirementInfoSubject.hasFallbackTextThat().isEqualTo("Code-Owners");
    submitRequirementInfoSubject.hasTypeThat().isEqualTo("code-owners");

    // Submit the change.
    gApi.changes().id(changeId).current().submit();
    assertThat(gApi.changes().id(changeId).get().status).isEqualTo(ChangeStatus.MERGED);
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.overrideApproval", value = "Owners-Override+1")
  public void changeWithOverrideApprovalIsSubmittable() throws Exception {
    testChangeWithOverrideApprovalIsSubmittable();
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.overrideApproval", value = "Owners-Override+1")
  @TestProjectInput(createEmptyCommit = false)
  public void initialChangeWithOverrideApprovalIsSubmittable() throws Exception {
    testChangeWithOverrideApprovalIsSubmittable();
  }

  private void testChangeWithOverrideApprovalIsSubmittable() throws Exception {
    createOwnersOverrideLabel();

    String changeId = createChange("Test Change", "foo/bar.baz", "file content").getChangeId();

    // Check that the change is not submittable.
    assertThat(gApi.changes().id(changeId).get(ListChangesOption.SUBMITTABLE).submittable)
        .isFalse();

    // Add an override approval.
    gApi.changes().id(changeId).current().review(new ReviewInput().label("Owners-Override", 1));

    // Verify that the code owner status for the changed file is APPROVED.
    CodeOwnerStatusInfo codeOwnerStatus =
        changeCodeOwnersApiFactory.change(changeId).getCodeOwnerStatus().get();
    assertThat(codeOwnerStatus)
        .hasFileCodeOwnerStatusesThat()
        .onlyElement()
        .hasNewPathStatusThat()
        .value()
        .hasStatusThat()
        .isEqualTo(CodeOwnerStatus.APPROVED);

    // Approve by a non-code-owner to satisfy the Code-Review+2 requirement.
    approve(changeId);

    // Check the submit requirement.
    LegacySubmitRequirementInfoSubject submitRequirementInfoSubject =
        assertThatCollection(gApi.changes().id(changeId).get().requirements).onlyElement();
    submitRequirementInfoSubject.hasStatusThat().isEqualTo("OK");
    submitRequirementInfoSubject.hasFallbackTextThat().isEqualTo("Code-Owners");
    submitRequirementInfoSubject.hasTypeThat().isEqualTo("code-owners");

    // Submit the change.
    gApi.changes().id(changeId).current().submit();
    assertThat(gApi.changes().id(changeId).get().status).isEqualTo(ChangeStatus.MERGED);
  }

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

    String branchName = "tempBranch";
    createBranch(BranchNameKey.create(project, branchName));

    String changeId = createChange("refs/for/" + branchName).getChangeId();

    // Approve by a code-owner.
    approve(changeId);

    DeleteBranchesInput input = new DeleteBranchesInput();
    input.branches = ImmutableList.of(branchName);
    gApi.projects().name(project.get()).deleteBranches(input);

    ChangeInfo changeInfo = gApi.changes().id(changeId).get(ListChangesOption.SUBMITTABLE);
    assertThat(changeInfo.submittable).isFalse();

    // Check that the submit requirement.
    LegacySubmitRequirementInfoSubject submitRequirementInfoSubject =
        assertThatCollection(changeInfo.requirements).onlyElement();
    submitRequirementInfoSubject.hasStatusThat().isEqualTo("NOT_READY");
    submitRequirementInfoSubject.hasFallbackTextThat().isEqualTo("Code-Owners");
    submitRequirementInfoSubject.hasTypeThat().isEqualTo("code-owners");

    // Try to submit the change.
    ResourceConflictException exception =
        assertThrows(
            ResourceConflictException.class, () -> gApi.changes().id(changeId).current().submit());
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(String.format("destination branch \"refs/heads/%s\" not found.", branchName));
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.exemptedUser", value = "exempted-user@example.com")
  public void changeIsSubmittableIfUserIsExcempted() throws Exception {
    TestAccount exemptedUser =
        accountCreator.create(
            "exemptedUser", "exempted-user@example.com", "Exempted User", /* displayName= */ null);

    PushOneCommit.Result r = createChange(exemptedUser, "Some Change", "foo.txt", "some content");
    String changeId = r.getChangeId();

    // Apply Code-Review+2 by a non-code-owner to satisfy the MaxWithBlock function of the
    // Code-Review label.
    approve(changeId);

    ChangeInfo changeInfo =
        gApi.changes()
            .id(changeId)
            .get(
                ListChangesOption.SUBMITTABLE,
                ListChangesOption.ALL_REVISIONS,
                ListChangesOption.CURRENT_ACTIONS);
    assertThat(changeInfo.submittable).isTrue();

    // Check that the submit button is enabled.
    assertThat(changeInfo.revisions.get(r.getCommit().getName()).actions.get("submit").enabled)
        .isTrue();

    // Check the submit requirement.
    LegacySubmitRequirementInfoSubject submitRequirementInfoSubject =
        assertThatCollection(changeInfo.requirements).onlyElement();
    submitRequirementInfoSubject.hasStatusThat().isEqualTo("OK");
    submitRequirementInfoSubject.hasFallbackTextThat().isEqualTo("Code-Owners");
    submitRequirementInfoSubject.hasTypeThat().isEqualTo("code-owners");

    // Submit the change.
    gApi.changes().id(changeId).current().submit();
    assertThat(gApi.changes().id(changeId).get().status).isEqualTo(ChangeStatus.MERGED);
  }

  @Test
  public void changeIsNotSubmittableIfOwnersFileIsNonParsable() throws Exception {
    testChangeIsNotSubmittableIfOwnersFileIsNonParsable(/* invalidCodeOwnerConfigInfoUrl= */ null);
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.invalidCodeOwnerConfigInfoUrl", value = "http://foo.bar")
  public void changeIsNotSubmittableIfOwnersFileIsNonParsable_withInvalidCodeOwnerConfigInfoUrl()
      throws Exception {
    testChangeIsNotSubmittableIfOwnersFileIsNonParsable("http://foo.bar");
  }

  private void testChangeIsNotSubmittableIfOwnersFileIsNonParsable(
      @Nullable String invalidCodeOwnerConfigInfoUrl) throws Exception {
    // Add a non-parsable code owner config.
    String nameOfInvalidCodeOwnerConfigFile = getCodeOwnerConfigFileName();
    createNonParseableCodeOwnerConfig(nameOfInvalidCodeOwnerConfigFile);

    PushOneCommit.Result r = createChange("Some Change", "foo.txt", "some content");
    String changeId = r.getChangeId();

    // Apply Code-Review+2 to satisfy the MaxWithBlock function of the Code-Review label.
    approve(changeId);

    ChangeInfo changeInfo =
        gApi.changes()
            .id(changeId)
            .get(
                ListChangesOption.SUBMITTABLE,
                ListChangesOption.ALL_REVISIONS,
                ListChangesOption.CURRENT_ACTIONS);
    assertThat(changeInfo.submittable).isFalse();

    // Check that the submit button is not visible.
    assertThat(changeInfo.revisions.get(r.getCommit().getName()).actions.get("submit")).isNull();

    // Check the submit requirement.
    assertThatCollection(changeInfo.requirements).isEmpty();

    // Try to submit the change.
    ResourceConflictException exception =
        assertThrows(
            ResourceConflictException.class, () -> gApi.changes().id(changeId).current().submit());
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(
            String.format(
                "Failed to submit 1 change due to the following problems:\n"
                    + "Change %s: submit requirement 'Code-Owners' has an"
                    + " error: Submittability expression result has an error:"
                    + " Failed to evaluate code owner statuses for"
                    + " patch set 1 of change %s (cause: invalid code owner config file '%s'"
                    + " (project = %s, branch = master):\n  %s).%s",
                changeInfo._number,
                changeInfo._number,
                JgitPath.of(nameOfInvalidCodeOwnerConfigFile).getAsAbsolutePath(),
                project,
                getParsingErrorMessageForNonParseableCodeOwnerConfig(),
                invalidCodeOwnerConfigInfoUrl != null
                    ? String.format("\nFor help check %s.", invalidCodeOwnerConfigInfoUrl)
                    : ""));
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.overrideApproval", value = "Owners-Override+1")
  public void changeIsSubmittableWithOverrideIfOwnersFileIsNonParsable() throws Exception {
    createOwnersOverrideLabel();

    // Add a non-parsable code owner config.
    String nameOfInvalidCodeOwnerConfigFile = getCodeOwnerConfigFileName();
    createNonParseableCodeOwnerConfig(nameOfInvalidCodeOwnerConfigFile);

    PushOneCommit.Result r = createChange("Some Change", "foo.txt", "some content");
    String changeId = r.getChangeId();

    // Apply Code-Review+2 to satisfy the MaxWithBlock function of the Code-Review label.
    approve(changeId);

    ChangeInfo changeInfo =
        gApi.changes()
            .id(changeId)
            .get(
                ListChangesOption.SUBMITTABLE,
                ListChangesOption.ALL_REVISIONS,
                ListChangesOption.CURRENT_ACTIONS);
    assertThat(changeInfo.submittable).isFalse();

    // Check that the submit button is not visible.
    assertThat(changeInfo.revisions.get(r.getCommit().getName()).actions.get("submit")).isNull();

    // Check the submit requirement.
    assertThatCollection(changeInfo.requirements).isEmpty();

    // Try to submit the change.
    ResourceConflictException exception =
        assertThrows(
            ResourceConflictException.class, () -> gApi.changes().id(changeId).current().submit());
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(
            String.format(
                "Failed to submit 1 change due to the following problems:\n"
                    + "Change %s: submit requirement 'Code-Owners' has an"
                    + " error: Submittability expression result has an error:"
                    + " Failed to evaluate code owner statuses for"
                    + " patch set 1 of change %s (cause: invalid code owner config file '%s'"
                    + " (project = %s, branch = master):\n  %s).",
                changeInfo._number,
                changeInfo._number,
                JgitPath.of(nameOfInvalidCodeOwnerConfigFile).getAsAbsolutePath(),
                project,
                getParsingErrorMessageForNonParseableCodeOwnerConfig()));

    // Apply an override.
    gApi.changes().id(changeId).current().review(new ReviewInput().label("Owners-Override", 1));

    // Check the submittable flag.
    changeInfo =
        gApi.changes()
            .id(changeId)
            .get(
                ListChangesOption.SUBMITTABLE,
                ListChangesOption.ALL_REVISIONS,
                ListChangesOption.CURRENT_ACTIONS);
    assertThat(changeInfo.submittable).isTrue();

    // Check the submit requirement.
    LegacySubmitRequirementInfoSubject submitRequirementInfoSubject =
        assertThatCollection(changeInfo.requirements).onlyElement();
    submitRequirementInfoSubject.hasStatusThat().isEqualTo("OK");
    submitRequirementInfoSubject.hasFallbackTextThat().isEqualTo("Code-Owners");
    submitRequirementInfoSubject.hasTypeThat().isEqualTo("code-owners");

    // Submit the change.
    gApi.changes().id(changeId).current().submit();
    assertThat(gApi.changes().id(changeId).get().status).isEqualTo(ChangeStatus.MERGED);
  }

  @Test
  public void changeIsSubmittableIfOwnersFileContainsInvalidPathExpression() throws Exception {
    assume().that(backendConfig.getDefaultBackend()).isInstanceOf(FindOwnersBackend.class);

    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch("master")
        .folderPath("/")
        .addCodeOwnerEmail(admin.email())
        .addCodeOwnerSet(
            CodeOwnerSet.builder()
                .addPathExpression("{foo") // invalid because '{' is not closed
                .addCodeOwnerEmail(user.email())
                .build())
        .create();

    PushOneCommit.Result r = createChange("Some Change", "foo.txt", "some content");
    String changeId = r.getChangeId();

    // Apply Code-Review+2 to satisfy the MaxWithBlock function of the Code-Review label.
    approve(changeId);

    ChangeInfo changeInfo =
        gApi.changes()
            .id(changeId)
            .get(
                ListChangesOption.SUBMITTABLE,
                ListChangesOption.ALL_REVISIONS,
                ListChangesOption.CURRENT_ACTIONS);
    assertThat(changeInfo.submittable).isTrue();

    // Check the submit requirement.
    LegacySubmitRequirementInfoSubject submitRequirementInfoSubject =
        assertThatCollection(changeInfo.requirements).onlyElement();
    submitRequirementInfoSubject.hasStatusThat().isEqualTo("OK");
    submitRequirementInfoSubject.hasFallbackTextThat().isEqualTo("Code-Owners");
    submitRequirementInfoSubject.hasTypeThat().isEqualTo("code-owners");

    // Submit the change.
    gApi.changes().id(changeId).current().submit();
    assertThat(gApi.changes().id(changeId).get().status).isEqualTo(ChangeStatus.MERGED);
  }

  @Test
  @GerritConfig(
      name = "plugin.code-owners.mergeCommitStrategy",
      value = "FILES_WITH_CONFLICT_RESOLUTION")
  public void changeIsSubmittableIfAutoMergeIsNotPresent() throws Exception {
    setAsDefaultCodeOwners(admin);

    // Create another branch
    String branchName = "foo";
    BranchInput branchInput = new BranchInput();
    branchInput.ref = branchName;
    branchInput.revision = projectOperations.project(project).getHead("master").name();
    gApi.projects().name(project.get()).branch(branchInput.ref).create(branchInput);

    // Create 2 parent commits.
    ObjectId initial = projectOperations.project(project).getHead("master");

    PushOneCommit.Result p1 =
        pushFactory
            .create(
                admin.newIdent(),
                testRepo,
                "parent 1",
                ImmutableMap.of("foo", "foo-1.2", "bar", "bar-1.2"))
            .to("refs/for/master");
    RevCommit parent1 = p1.getCommit();
    approve(p1.getChangeId());
    gApi.changes().id(p1.getChangeId()).current().submit();

    testRepo.reset(initial);
    PushOneCommit.Result p2 =
        pushFactory
            .create(
                admin.newIdent(),
                testRepo,
                "parent 2",
                ImmutableMap.of("foo", "foo-2.2", "bar", "bar-2.2"))
            .to("refs/for/foo");
    RevCommit parent2 = p2.getCommit();
    approve(p2.getChangeId());
    gApi.changes().id(p2.getChangeId()).current().submit();

    // Create the merge commit.
    PushOneCommit m =
        pushFactory.create(
            admin.newIdent(), testRepo, "merge", ImmutableMap.of("foo", "foo-1", "bar", "bar-2"));
    m.setParents(ImmutableList.of(parent1, parent2));
    PushOneCommit.Result r = m.to("refs/for/master");
    r.assertOkStatus();
    String changeId = r.getChangeId();

    // Apply Code-Review+2 by a non-code-owner to satisfy the MaxWithBlock function of the
    // Code-Review label.
    approve(changeId);

    // Delete the auto-merge ref so that the auto-merge needs to be computed in-memory when the
    // code-owners submit rule is executed.
    deleteAutoMergeBranch(r.getCommit());

    ChangeInfo changeInfo =
        gApi.changes()
            .id(changeId)
            .get(
                ListChangesOption.SUBMITTABLE,
                ListChangesOption.ALL_REVISIONS,
                ListChangesOption.CURRENT_ACTIONS);
    assertThat(changeInfo.submittable).isTrue();

    // Check that the submit button is enabled.
    assertThat(changeInfo.revisions.get(r.getCommit().getName()).actions.get("submit").enabled)
        .isTrue();

    // Check the submit requirement.
    LegacySubmitRequirementInfoSubject submitRequirementInfoSubject =
        assertThatCollection(changeInfo.requirements).onlyElement();
    submitRequirementInfoSubject.hasStatusThat().isEqualTo("OK");
    submitRequirementInfoSubject.hasFallbackTextThat().isEqualTo("Code-Owners");
    submitRequirementInfoSubject.hasTypeThat().isEqualTo("code-owners");

    // Submit the change.
    gApi.changes().id(changeId).current().submit();
    assertThat(gApi.changes().id(changeId).get().status).isEqualTo(ChangeStatus.MERGED);
  }

  @Test
  public void submitRuleIsInvokedOnlyOnceWhenGettingChangeDetails() throws Exception {
    PushOneCommit.Result r = createChange("Some Change", "foo.txt", "some content");
    String changeId = r.getChangeId();

    testMetricMaker.reset();
    gApi.changes()
        .id(changeId)
        .get(ListChangesOption.ALL_REVISIONS, ListChangesOption.CURRENT_ACTIONS);

    // Submit rules are computed freshly, but only once.
    assertThat(testMetricMaker.getCount("plugins/code-owners/count_code_owner_submit_rule_runs"))
        .isEqualTo(1);
  }

  @Test
  public void submitRuleIsInvokedTwiceWhenACodeOwnersSubmitRequirementIsConfigured()
      throws Exception {
    // Configure a Code-Owners submit requirement
    SubmitRequirementInput input = new SubmitRequirementInput();
    input.name = "Code-Owners";
    input.submittabilityExpression = "has:approval_code-owners";
    gApi.projects().name(project.get()).submitRequirement("Code-Owners").create(input);

    // Getting change details triggers the Code-Owners submit requirement twice, once because the
    // CodeOwnerSubmitRule implements the SubmitRule extension point and once because there is a
    // submit requirement configured that uses the CodeOwnerApprovalPredicate.
    PushOneCommit.Result r = createChange("Some Change", "foo.txt", "some content");
    String changeId = r.getChangeId();

    testMetricMaker.reset();
    gApi.changes()
        .id(changeId)
        .get(ListChangesOption.ALL_REVISIONS, ListChangesOption.CURRENT_ACTIONS);

    // Submit rules are computed freshly, but only once.
    assertThat(testMetricMaker.getCount("plugins/code-owners/count_code_owner_submit_rule_runs"))
        .isEqualTo(2);
  }

  @Test
  public void submitRuleIsNotInvokedWhenQueryingChange() throws Exception {
    PushOneCommit.Result r = createChange("Some Change", "foo.txt", "some content");
    String changeId = r.getChangeId();

    testMetricMaker.reset();
    gApi.changes()
        .query(changeId)
        .withOptions(ListChangesOption.ALL_REVISIONS, ListChangesOption.CURRENT_ACTIONS)
        .get();

    // Submit rule evaluation results from the change index are reused
    assertThat(testMetricMaker.getCount("plugins/code-owners/count_code_owner_submit_rule_runs"))
        .isEqualTo(0);
  }

  private void deleteAutoMergeBranch(ObjectId mergeCommit) throws Exception {
    try (Repository repo = repoManager.openRepository(project)) {
      RefUpdate ru = repo.updateRef(RefNames.refsCacheAutomerge(mergeCommit.name()));
      ru.setForceUpdate(true);
      assertThat(testRefAction(() -> ru.delete())).isEqualTo(RefUpdate.Result.FORCED);
      assertThat(repo.exactRef(RefNames.refsCacheAutomerge(mergeCommit.name()))).isNull();
    }
  }
}
