// Copyright (C) 2022 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.acceptance.pgm;

import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.Sandboxed;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.api.projects.SubmitRequirementApi;
import com.google.gerrit.extensions.common.LabelDefinitionInfo;
import com.google.gerrit.extensions.common.LabelDefinitionInput;
import com.google.gerrit.extensions.common.SubmitRequirementInfo;
import com.google.gerrit.extensions.common.SubmitRequirementInput;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.server.restapi.project.CreateLabel;
import com.google.gerrit.server.schema.MigrateLabelFunctionsToSubmitRequirement;
import com.google.gerrit.server.schema.MigrateLabelFunctionsToSubmitRequirement.Status;
import com.google.gerrit.server.schema.UpdateUI;
import com.google.inject.Inject;
import java.util.Map;
import java.util.Set;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Test;

/** Test for {@link com.google.gerrit.server.schema.MigrateLabelFunctionsToSubmitRequirement}. */
@Sandboxed
public class MigrateLabelFunctionsToSubmitRequirementIT extends AbstractDaemonTest {
  @Inject private ProjectOperations projectOperations;
  @Inject private CreateLabel createLabel;

  @Test
  public void migrateBlockingLabel_maxWithBlock() throws Exception {
    createLabel("Foo", "MaxWithBlock", /* ignoreSelfApproval= */ false);
    assertNonExistentSr(/* srName= */ "Foo");

    TestUpdateUI updateUI = runMigration(/* expectedResult= */ Status.MIGRATED);
    assertThat(updateUI.newlyCreatedSrs).isEqualTo(1);
    assertThat(updateUI.existingSrsMismatchingWithMigration).isEqualTo(0);

    assertExistentSr(
        /* srName */ "Foo",
        /* applicabilityExpression= */ null,
        /* submittabilityExpression= */ "label:Foo=MAX AND -label:Foo=MIN",
        /* canOverride= */ true);
    assertLabelFunction("Foo", "NoBlock");
  }

  @Test
  public void migrateBlockingLabel_maxNoBlock() throws Exception {
    createLabel("Foo", "MaxNoBlock", /* ignoreSelfApproval= */ false);
    assertNonExistentSr(/* srName= */ "Foo");

    TestUpdateUI updateUI = runMigration(/* expectedResult= */ Status.MIGRATED);
    assertThat(updateUI.newlyCreatedSrs).isEqualTo(1);
    assertThat(updateUI.existingSrsMismatchingWithMigration).isEqualTo(0);

    assertExistentSr(
        /* srName */ "Foo",
        /* applicabilityExpression= */ null,
        /* submittabilityExpression= */ "label:Foo=MAX",
        /* canOverride= */ true);
    assertLabelFunction("Foo", "NoBlock");
  }

  @Test
  public void migrateBlockingLabel_anyWithBlock() throws Exception {
    createLabel("Foo", "AnyWithBlock", /* ignoreSelfApproval= */ false);
    assertNonExistentSr(/* srName= */ "Foo");

    TestUpdateUI updateUI = runMigration(/* expectedResult= */ Status.MIGRATED);
    assertThat(updateUI.newlyCreatedSrs).isEqualTo(1);
    assertThat(updateUI.existingSrsMismatchingWithMigration).isEqualTo(0);

    assertExistentSr(
        /* srName */ "Foo",
        /* applicabilityExpression= */ null,
        /* submittabilityExpression= */ "-label:Foo=MIN",
        /* canOverride= */ true);
    assertLabelFunction("Foo", "NoBlock");
  }

  @Test
  public void migrateBlockingLabel_maxWithBlock_withIgnoreSelfApproval() throws Exception {
    createLabel("Foo", "MaxWithBlock", /* ignoreSelfApproval= */ true);
    assertNonExistentSr(/* srName= */ "Foo");

    TestUpdateUI updateUI = runMigration(/* expectedResult= */ Status.MIGRATED);
    assertThat(updateUI.newlyCreatedSrs).isEqualTo(1);
    assertThat(updateUI.existingSrsMismatchingWithMigration).isEqualTo(0);

    assertExistentSr(
        /* srName */ "Foo",
        /* applicabilityExpression= */ null,
        /* submittabilityExpression= */ "label:Foo=MAX,user=non_uploader AND -label:Foo=MIN",
        /* canOverride= */ true);
    assertLabelFunction("Foo", "NoBlock");
  }

  @Test
  public void migrateBlockingLabel_maxNoBlock_withIgnoreSelfApproval() throws Exception {
    createLabel("Foo", "MaxNoBlock", /* ignoreSelfApproval= */ true);
    assertNonExistentSr(/* srName= */ "Foo");

    TestUpdateUI updateUI = runMigration(/* expectedResult= */ Status.MIGRATED);
    assertThat(updateUI.newlyCreatedSrs).isEqualTo(1);
    assertThat(updateUI.existingSrsMismatchingWithMigration).isEqualTo(0);

    assertExistentSr(
        /* srName */ "Foo",
        /* applicabilityExpression= */ null,
        /* submittabilityExpression= */ "label:Foo=MAX,user=non_uploader",
        /* canOverride= */ true);
    assertLabelFunction("Foo", "NoBlock");
  }

  @Test
  public void migrateNonBlockingLabel_noBlock() throws Exception {
    // NoBlock labels are left as is, i.e. we don't create a "submit requirement" for them. Those
    // labels will then be treated as trigger votes in the change page.
    createLabel("Foo", "NoBlock", /* ignoreSelfApproval= */ false);
    assertNonExistentSr(/* srName= */ "Foo");

    TestUpdateUI updateUI = runMigration(/* expectedResult= */ Status.NO_CHANGE);
    assertThat(updateUI.newlyCreatedSrs).isEqualTo(0);
    assertThat(updateUI.existingSrsMismatchingWithMigration).isEqualTo(0);

    // No SR was created for the label. Label will be treated as a trigger vote.
    assertNonExistentSr("Foo");
    // Label function has not changed.
    assertLabelFunction("Foo", "NoBlock");
  }

  @Test
  public void migrateNonBlockingLabel_noOp() throws Exception {
    // NoOp labels are left as is, i.e. we don't create a "submit requirement" for them. Those
    // labels will then be treated as trigger votes in the change page.
    createLabel("Foo", "NoOp", /* ignoreSelfApproval= */ false);
    assertNonExistentSr(/* srName= */ "Foo");

    TestUpdateUI updateUI = runMigration(/* expectedResult= */ Status.MIGRATED);
    assertThat(updateUI.newlyCreatedSrs).isEqualTo(0);
    assertThat(updateUI.existingSrsMismatchingWithMigration).isEqualTo(0);

    // No SR was created for the label. Label will be treated as a trigger vote.
    assertNonExistentSr("Foo");
    // The NoOp function is converted to NoBlock. Both are same.
    assertLabelFunction("Foo", "NoBlock");
  }

  @Test
  public void migrateNoBlockLabel_withSingleZeroValue() throws Exception {
    // Labels that have a single "zero" value are skipped in the project. The migrator creates
    // non-applicable SR for these labels.
    createLabel("Foo", "NoBlock", /* ignoreSelfApproval= */ false, ImmutableMap.of("0", "No vote"));
    assertNonExistentSr(/* srName= */ "Foo");

    TestUpdateUI updateUI = runMigration(/* expectedResult= */ Status.MIGRATED);
    assertThat(updateUI.newlyCreatedSrs).isEqualTo(1);
    assertThat(updateUI.existingSrsMismatchingWithMigration).isEqualTo(0);

    // a non-applicable SR was created for the skipped label.
    assertExistentSr(
        /* srName */ "Foo",
        /* applicabilityExpression= */ "is:false",
        /* submittabilityExpression= */ "is:true",
        /* canOverride= */ true);

    assertLabelFunction("Foo", "NoBlock");
  }

  @Test
  public void migrateMaxWithBlockLabel_withSingleZeroValue() throws Exception {
    // Labels that have a single "zero" value are skipped in the project. The migrator creates
    // non-applicable SRs for these labels.
    createLabel(
        "Foo", "MaxWithBlock", /* ignoreSelfApproval= */ false, ImmutableMap.of("0", "No vote"));
    assertNonExistentSr(/* srName= */ "Foo");

    TestUpdateUI updateUI = runMigration(/* expectedResult= */ Status.MIGRATED);
    assertThat(updateUI.newlyCreatedSrs).isEqualTo(1);
    assertThat(updateUI.existingSrsMismatchingWithMigration).isEqualTo(0);

    // a non-applicable SR was created for the skipped label.
    assertExistentSr(
        /* srName */ "Foo",
        /* applicabilityExpression= */ "is:false",
        /* submittabilityExpression= */ "is:true",
        /* canOverride= */ true);

    // The MaxWithBlock function is converted to NoBlock. This has no effect anyway because the
    // label was originally skipped.
    assertLabelFunction("Foo", "NoBlock");
  }

  @Test
  public void cannotCreateLabelsWithNoValues() {
    // This test just asserts the server's behaviour for visibility; admins cannot create a label
    // without any defined values.
    Exception thrown =
        assertThrows(
            BadRequestException.class,
            () ->
                createLabel("Foo", "NoBlock", /* ignoreSelfApproval= */ false, ImmutableMap.of()));
    assertThat(thrown).hasMessageThat().isEqualTo("values are required");
  }

  @Test
  public void migrateNonBlockingLabel_patchSetLock_doesNothing() throws Exception {
    createLabel("Foo", "PatchSetLock", /* ignoreSelfApproval= */ false);
    assertNonExistentSr(/* srName= */ "Foo");

    TestUpdateUI updateUI = runMigration(/* expectedResult= */ Status.NO_CHANGE);
    // No submit requirement created for the patchset lock label function
    assertThat(updateUI.newlyCreatedSrs).isEqualTo(0);
    assertThat(updateUI.existingSrsMismatchingWithMigration).isEqualTo(0);

    assertNonExistentSr(/* srName= */ "Foo");
    assertLabelFunction("Foo", "PatchSetLock");
  }

  @Test
  public void migrationIsCommittedWithServerIdent() throws Exception {
    RevCommit oldMetaCommit = projectOperations.project(project).getHead(RefNames.REFS_CONFIG);
    createLabel("Foo", "MaxWithBlock", /* ignoreSelfApproval= */ false);
    assertNonExistentSr(/* srName= */ "Foo");

    TestUpdateUI updateUI = runMigration(/* expectedResult= */ Status.MIGRATED);
    assertThat(updateUI.newlyCreatedSrs).isEqualTo(1);
    assertThat(updateUI.existingSrsMismatchingWithMigration).isEqualTo(0);

    assertExistentSr(
        /* srName */ "Foo",
        /* applicabilityExpression= */ null,
        /* submittabilityExpression= */ "label:Foo=MAX AND -label:Foo=MIN",
        /* canOverride= */ true);
    assertLabelFunction("Foo", "NoBlock");

    RevCommit newMetaCommit = projectOperations.project(project).getHead(RefNames.REFS_CONFIG);
    assertThat(newMetaCommit).isNotEqualTo(oldMetaCommit);
    assertThat(newMetaCommit.getCommitterIdent().getEmailAddress())
        .isEqualTo(serverIdent.get().getEmailAddress());
  }

  @Test
  public void migrateBlockingLabel_withBranchAttribute() throws Exception {
    createLabelWithBranch(
        "Foo",
        "MaxWithBlock",
        /* ignoreSelfApproval= */ false,
        ImmutableList.of("refs/heads/master"));

    assertNonExistentSr(/* srName= */ "Foo");

    TestUpdateUI updateUI = runMigration(/* expectedResult= */ Status.MIGRATED);
    assertThat(updateUI.newlyCreatedSrs).isEqualTo(1);
    assertThat(updateUI.existingSrsMismatchingWithMigration).isEqualTo(0);

    assertExistentSr(
        /* srName */ "Foo",
        /* applicabilityExpression= */ "branch:\\\"refs/heads/master\\\"",
        /* submittabilityExpression= */ "label:Foo=MAX AND -label:Foo=MIN",
        /* canOverride= */ true);
    assertLabelFunction("Foo", "NoBlock");
  }

  @Test
  public void migrateBlockingLabel_withMultipleBranchAttributes() throws Exception {
    createLabelWithBranch(
        "Foo",
        "MaxWithBlock",
        /* ignoreSelfApproval= */ false,
        ImmutableList.of("refs/heads/master", "refs/heads/develop"));

    assertNonExistentSr(/* srName= */ "Foo");

    TestUpdateUI updateUI = runMigration(/* expectedResult= */ Status.MIGRATED);
    assertThat(updateUI.newlyCreatedSrs).isEqualTo(1);
    assertThat(updateUI.existingSrsMismatchingWithMigration).isEqualTo(0);

    assertExistentSr(
        /* srName */ "Foo",
        /* applicabilityExpression= */ "branch:\\\"refs/heads/master\\\" "
            + "OR branch:\\\"refs/heads/develop\\\"",
        /* submittabilityExpression= */ "label:Foo=MAX AND -label:Foo=MIN",
        /* canOverride= */ true);
    assertLabelFunction("Foo", "NoBlock");
  }

  @Test
  public void migrateBlockingLabel_withRegexBranchAttribute() throws Exception {
    createLabelWithBranch(
        "Foo",
        "MaxWithBlock",
        /* ignoreSelfApproval= */ false,
        ImmutableList.of("^refs/heads/main-.*"));

    assertNonExistentSr(/* srName= */ "Foo");

    TestUpdateUI updateUI = runMigration(/* expectedResult= */ Status.MIGRATED);
    assertThat(updateUI.newlyCreatedSrs).isEqualTo(1);
    assertThat(updateUI.existingSrsMismatchingWithMigration).isEqualTo(0);

    assertExistentSr(
        /* srName */ "Foo",
        /* applicabilityExpression= */ "branch:\\\"^refs/heads/main-.*\\\"",
        /* submittabilityExpression= */ "label:Foo=MAX AND -label:Foo=MIN",
        /* canOverride= */ true);
    assertLabelFunction("Foo", "NoBlock");
  }

  @Test
  public void migrateBlockingLabel_withRegexAndNonRegexBranchAttributes() throws Exception {
    createLabelWithBranch(
        "Foo",
        "MaxWithBlock",
        /* ignoreSelfApproval= */ false,
        ImmutableList.of("refs/heads/master", "^refs/heads/main-.*"));

    assertNonExistentSr(/* srName= */ "Foo");

    TestUpdateUI updateUI = runMigration(/* expectedResult= */ Status.MIGRATED);
    assertThat(updateUI.newlyCreatedSrs).isEqualTo(1);
    assertThat(updateUI.existingSrsMismatchingWithMigration).isEqualTo(0);

    assertExistentSr(
        /* srName */ "Foo",
        /* applicabilityExpression= */ "branch:\\\"refs/heads/master\\\" "
            + "OR branch:\\\"^refs/heads/main-.*\\\"",
        /* submittabilityExpression= */ "label:Foo=MAX AND -label:Foo=MIN",
        /* canOverride= */ true);
    assertLabelFunction("Foo", "NoBlock");
  }

  @Test
  public void migrationIsIdempotent() throws Exception {
    String oldRefsConfigId;
    try (Repository repo = repoManager.openRepository(project)) {
      oldRefsConfigId = repo.exactRef(RefNames.REFS_CONFIG).getObjectId().toString();
    }
    createLabel("Foo", "MaxWithBlock", /* ignoreSelfApproval= */ false);
    assertNonExistentSr(/* srName= */ "Foo");

    // Running the migration causes REFS_CONFIG to change.
    TestUpdateUI updateUI = runMigration(/* expectedResult= */ Status.MIGRATED);
    assertThat(updateUI.newlyCreatedSrs).isEqualTo(1);
    assertThat(updateUI.existingSrsMismatchingWithMigration).isEqualTo(0);
    try (Repository repo = repoManager.openRepository(project)) {
      assertThat(oldRefsConfigId)
          .isNotEqualTo(repo.exactRef(RefNames.REFS_CONFIG).getObjectId().toString());
      oldRefsConfigId = repo.exactRef(RefNames.REFS_CONFIG).getObjectId().toString();
    }

    // No new SRs will be created. No conflicting submit requirements either since the migration
    // detects that a previous run was made and skips the migration.
    updateUI = runMigration(/* expectedResult= */ Status.PREVIOUSLY_MIGRATED);
    assertThat(updateUI.newlyCreatedSrs).isEqualTo(0);
    assertThat(updateUI.existingSrsMismatchingWithMigration).isEqualTo(0);
    // Running the migration a second time won't update REFS_CONFIG.
    try (Repository repo = repoManager.openRepository(project)) {
      assertThat(oldRefsConfigId)
          .isEqualTo(repo.exactRef(RefNames.REFS_CONFIG).getObjectId().toString());
    }
  }

  @Test
  public void migrationDoesNotCreateANewSubmitRequirement_ifSRAlreadyExists_matchingWithMigration()
      throws Exception {
    createLabel("Foo", "MaxWithBlock", /* ignoreSelfApproval= */ false);
    createSubmitRequirement("Foo", "label:Foo=MAX AND -label:Foo=MIN", /* canOverride= */ true);
    assertExistentSr(
        /* srName */ "Foo",
        /* applicabilityExpression= */ null,
        /* submittabilityExpression= */ "label:Foo=MAX AND -label:Foo=MIN",
        /* canOverride= */ true);

    TestUpdateUI updateUI = runMigration(/* expectedResult= */ Status.MIGRATED);
    // No new submit requirements are created.
    assertThat(updateUI.newlyCreatedSrs).isEqualTo(0);
    // No conflicting submit requirements from migration vs. what was previously configured.
    assertThat(updateUI.existingSrsMismatchingWithMigration).isEqualTo(0);

    // The existing SR was left as is.
    assertExistentSr(
        /* srName */ "Foo",
        /* applicabilityExpression= */ null,
        /* submittabilityExpression= */ "label:Foo=MAX AND -label:Foo=MIN",
        /* canOverride= */ true);
  }

  @Test
  public void
      migrationDoesNotCreateANewSubmitRequirement_ifSRAlreadyExists_mismatchingWithMigration()
          throws Exception {
    createLabel("Foo", "MaxWithBlock", /* ignoreSelfApproval= */ false);
    createSubmitRequirement("Foo", "project:" + project, /* canOverride= */ true);
    assertExistentSr(
        /* srName */ "Foo",
        /* applicabilityExpression= */ null,
        /* submittabilityExpression= */ "project:" + project,
        /* canOverride= */ true);

    TestUpdateUI updateUI = runMigration(/* expectedResult= */ Status.MIGRATED);
    // One conflicting submit requirement between migration vs. what was previously configured.
    assertThat(updateUI.existingSrsMismatchingWithMigration).isEqualTo(1);

    // The existing SR was left as is.
    assertExistentSr(
        /* srName */ "Foo",
        /* applicabilityExpression= */ null,
        /* submittabilityExpression= */ "project:" + project,
        /* canOverride= */ true);
  }

  @Test
  public void migrationResetsBlockingLabel_ifSRAlreadyExists() throws Exception {
    createLabel("Foo", "MaxWithBlock", /* ignoreSelfApproval= */ false);
    createSubmitRequirement("Foo", "owner:" + admin.email(), /* canOverride= */ true);

    TestUpdateUI updateUI = runMigration(/* expectedResult= */ Status.MIGRATED);
    assertThat(updateUI.newlyCreatedSrs).isEqualTo(0);

    // The label function was reset
    assertLabelFunction("Foo", "NoBlock");
  }

  private TestUpdateUI runMigration(Status expectedResult) throws Exception {
    TestUpdateUI updateUi = new TestUpdateUI();
    MigrateLabelFunctionsToSubmitRequirement executor =
        new MigrateLabelFunctionsToSubmitRequirement(repoManager, serverIdent.get());
    Status status = executor.executeMigration(project, updateUi);
    assertThat(status).isEqualTo(expectedResult);
    projectCache.evictAndReindex(project);
    return updateUi;
  }

  private void createLabel(String labelName, String function, boolean ignoreSelfApproval)
      throws Exception {
    createLabel(
        labelName,
        function,
        ignoreSelfApproval,
        ImmutableMap.of("+1", "Looks Good", " 0", "Don't Know", "-1", "Looks Bad"));
  }

  private void createLabel(
      String labelName, String function, boolean ignoreSelfApproval, Map<String, String> values)
      throws Exception {
    LabelDefinitionInput input = new LabelDefinitionInput();
    input.name = labelName;
    input.function = function;
    input.ignoreSelfApproval = ignoreSelfApproval;
    input.values = values;
    createLabel.createLabelWithoutInputValidation(project, labelName, input);
  }

  private void createLabelWithBranch(
      String labelName,
      String function,
      boolean ignoreSelfApproval,
      ImmutableList<String> refPatterns)
      throws Exception {
    LabelDefinitionInput input = new LabelDefinitionInput();
    input.name = labelName;
    input.function = function;
    input.ignoreSelfApproval = ignoreSelfApproval;
    input.values = ImmutableMap.of("+1", "Looks Good", " 0", "Don't Know", "-1", "Looks Bad");
    input.branches = refPatterns;
    createLabel.createLabelWithoutInputValidation(project, labelName, input);
  }

  @CanIgnoreReturnValue
  private SubmitRequirementApi createSubmitRequirement(
      String name, String submitExpression, boolean canOverride) throws Exception {
    SubmitRequirementInput input = new SubmitRequirementInput();
    input.name = name;
    input.submittabilityExpression = submitExpression;
    input.allowOverrideInChildProjects = canOverride;
    return gApi.projects().name(project.get()).submitRequirement(name).create(input);
  }

  private void assertLabelFunction(String labelName, String function) throws Exception {
    LabelDefinitionInfo info = gApi.projects().name(project.get()).label(labelName).get();
    assertThat(info.function).isEqualTo(function);
  }

  private void assertNonExistentSr(String srName) {
    ResourceNotFoundException foo =
        assertThrows(
            ResourceNotFoundException.class,
            () -> gApi.projects().name(project.get()).submitRequirement("Foo").get());
    assertThat(foo.getMessage()).isEqualTo("Submit requirement '" + srName + "' does not exist");
  }

  private void assertExistentSr(
      String srName,
      String applicabilityExpression,
      String submittabilityExpression,
      boolean canOverride)
      throws Exception {
    SubmitRequirementInfo sr = gApi.projects().name(project.get()).submitRequirement(srName).get();
    assertThat(sr.applicabilityExpression).isEqualTo(applicabilityExpression);
    assertThat(sr.submittabilityExpression).isEqualTo(submittabilityExpression);
    assertThat(sr.allowOverrideInChildProjects).isEqualTo(canOverride);
  }

  private static class TestUpdateUI implements UpdateUI {
    int existingSrsMismatchingWithMigration = 0;
    int newlyCreatedSrs = 0;

    @Override
    public void message(String message) {
      if (message.startsWith("Warning")) {
        existingSrsMismatchingWithMigration += 1;
      } else if (message.startsWith("Project")) {
        newlyCreatedSrs += 1;
      }
    }

    @Override
    public boolean yesno(boolean defaultValue, String message) {
      return false;
    }

    @Override
    public void waitForUser() {}

    @Override
    public String readString(String defaultValue, Set<String> allowedValues, String message) {
      return null;
    }

    @Override
    public boolean isBatch() {
      return false;
    }
  }
}
