// 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(repoMetaDataUpdater, repoManager);
    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;
    }
  }
}
