// 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.gerrit.acceptance.GitUtil.fetch;
import static com.google.gerrit.acceptance.GitUtil.pushHead;
import static com.google.gerrit.extensions.client.ListChangesOption.CURRENT_REVISION;
import static com.google.gerrit.plugins.codeowners.testing.RequiredApprovalSubject.assertThat;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static com.google.gerrit.truth.OptionalSubject.assertThat;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.gerrit.acceptance.GitUtil;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.config.GerritConfig;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.api.changes.RebaseInput;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.git.ObjectIds;
import com.google.gerrit.plugins.codeowners.acceptance.AbstractCodeOwnersIT;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerBackendId;
import com.google.gerrit.plugins.codeowners.backend.FallbackCodeOwners;
import com.google.gerrit.plugins.codeowners.backend.PathExpressions;
import com.google.gerrit.plugins.codeowners.backend.config.BackendConfig;
import com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginConfiguration;
import com.google.gerrit.plugins.codeowners.backend.config.GeneralConfig;
import com.google.gerrit.plugins.codeowners.backend.config.OverrideApprovalConfig;
import com.google.gerrit.plugins.codeowners.backend.config.RequiredApproval;
import com.google.gerrit.plugins.codeowners.backend.config.RequiredApprovalConfig;
import com.google.gerrit.plugins.codeowners.backend.config.StatusConfig;
import com.google.gerrit.plugins.codeowners.backend.proto.ProtoBackend;
import com.google.gerrit.plugins.codeowners.common.MergeCommitStrategy;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.RemoteRefUpdate.Status;
import org.eclipse.jgit.util.RawParseUtils;
import org.junit.Before;
import org.junit.Test;

/**
 * Tests for {@code com.google.gerrit.plugins.codeowners.config.CodeOwnersPluginConfigValidator}.
 *
 * <p>Unit tests for {@code
 * com.google.gerrit.plugins.codeowners.config.CodeOwnersPluginConfigValidator} are contained in
 * {@code com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginConfigValidatorTest}.
 */
public class CodeOwnersPluginConfigValidatorIT extends AbstractCodeOwnersIT {
  private CodeOwnersPluginConfiguration codeOwnersPluginConfiguration;

  @Before
  public void setUpCodeOwnersPlugin() throws Exception {
    codeOwnersPluginConfiguration =
        plugin.getSysInjector().getInstance(CodeOwnersPluginConfiguration.class);
  }

  @Test
  public void cannotUploadNonParseableConfig() throws Exception {
    fetchRefsMetaConfig();

    setCodeOwnersConfig("INVALID");

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus())
        .isEqualTo(Status.REJECTED_OTHER_REASON);
    assertThat(r.getMessages())
        .contains(
            String.format(
                "Invalid config file code-owners.config in project %s in branch %s",
                project, RefNames.REFS_CONFIG));
    assertThat(r.getMessages()).contains("Invalid line in config file");
  }

  @Test
  public void setDisabledForProject() throws Exception {
    fetchRefsMetaConfig();

    Config cfg = new Config();
    cfg.setBoolean(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        StatusConfig.KEY_DISABLED,
        /* value= */ true);
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus()).isEqualTo(Status.OK);
    assertThat(codeOwnersPluginConfiguration.getProjectConfig(project).isDisabled()).isTrue();
  }

  @Test
  public void configureDisabledBranch() throws Exception {
    fetchRefsMetaConfig();

    Config cfg = new Config();
    cfg.setString(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        StatusConfig.KEY_DISABLED_BRANCH,
        "refs/heads/master");
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus()).isEqualTo(Status.OK);
    assertThat(codeOwnersPluginConfiguration.getProjectConfig(project).isDisabled("master"))
        .isTrue();
  }

  @Test
  public void cannotSetInvalidValueForDisabledForProject() throws Exception {
    fetchRefsMetaConfig();

    Config cfg = new Config();
    cfg.setString(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        StatusConfig.KEY_DISABLED,
        "INVALID");
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus())
        .isEqualTo(Status.REJECTED_OTHER_REASON);
    assertThat(r.getMessages())
        .contains(
            "Disabled value 'INVALID' that is configured in code-owners.config"
                + " (parameter codeOwners.disabled) is invalid.");
  }

  @Test
  public void cannotConfigureInvalidDisabledBranch() throws Exception {
    fetchRefsMetaConfig();

    Config cfg = new Config();
    cfg.setString(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        StatusConfig.KEY_DISABLED_BRANCH,
        "^refs/heads/[");
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus())
        .isEqualTo(Status.REJECTED_OTHER_REASON);
    assertThat(r.getMessages())
        .contains(
            "Disabled branch '^refs/heads/[' that is configured in code-owners.config (parameter"
                + " codeOwners.disabledBranch) is invalid: Unclosed character class");
  }

  @Test
  public void configureBackendForProject() throws Exception {
    fetchRefsMetaConfig();

    Config cfg = new Config();
    cfg.setString(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        BackendConfig.KEY_BACKEND,
        CodeOwnerBackendId.PROTO.getBackendId());
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus()).isEqualTo(Status.OK);
    assertThat(codeOwnersPluginConfiguration.getProjectConfig(project).getBackend("master"))
        .isInstanceOf(ProtoBackend.class);
  }

  @Test
  public void configureBackendForBranch() throws Exception {
    fetchRefsMetaConfig();

    Config cfg = new Config();
    cfg.setString(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        "master",
        BackendConfig.KEY_BACKEND,
        CodeOwnerBackendId.PROTO.getBackendId());
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus()).isEqualTo(Status.OK);
    assertThat(codeOwnersPluginConfiguration.getProjectConfig(project).getBackend("master"))
        .isInstanceOf(ProtoBackend.class);
  }

  @Test
  public void cannotConfigureInvalidBackendForProject() throws Exception {
    fetchRefsMetaConfig();

    Config cfg = new Config();
    cfg.setString(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        BackendConfig.KEY_BACKEND,
        "INVALID");
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus())
        .isEqualTo(Status.REJECTED_OTHER_REASON);
    assertThat(r.getMessages())
        .contains(
            "Code owner backend 'INVALID' that is configured in code-owners.config"
                + " (parameter codeOwners.backend) not found.");
  }

  @Test
  public void cannotConfigureInvalidBackendForBranch() throws Exception {
    fetchRefsMetaConfig();

    Config cfg = new Config();
    cfg.setString(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        "master",
        BackendConfig.KEY_BACKEND,
        "INVALID");
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus())
        .isEqualTo(Status.REJECTED_OTHER_REASON);
    assertThat(r.getMessages())
        .contains(
            "Code owner backend 'INVALID' that is configured in code-owners.config"
                + " (parameter codeOwners.master.backend) not found.");
  }

  @Test
  public void configurePathExpressionsForProject() throws Exception {
    fetchRefsMetaConfig();

    Config cfg = new Config();
    cfg.setString(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        BackendConfig.KEY_PATH_EXPRESSIONS,
        PathExpressions.GLOB.name());
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus()).isEqualTo(Status.OK);
    assertThat(codeOwnersPluginConfiguration.getProjectConfig(project).getPathExpressions("master"))
        .value()
        .isEqualTo(PathExpressions.GLOB);
  }

  @Test
  public void configurePathExpressionsForBranch() throws Exception {
    fetchRefsMetaConfig();

    Config cfg = new Config();
    cfg.setString(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        "master",
        BackendConfig.KEY_PATH_EXPRESSIONS,
        PathExpressions.GLOB.name());
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus()).isEqualTo(Status.OK);
    assertThat(codeOwnersPluginConfiguration.getProjectConfig(project).getPathExpressions("master"))
        .value()
        .isEqualTo(PathExpressions.GLOB);
  }

  @Test
  public void cannotConfigureInvalidPathExpressionsForProject() throws Exception {
    fetchRefsMetaConfig();

    Config cfg = new Config();
    cfg.setString(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        BackendConfig.KEY_PATH_EXPRESSIONS,
        "INVALID");
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus())
        .isEqualTo(Status.REJECTED_OTHER_REASON);
    assertThat(r.getMessages())
        .contains(
            "Path expressions 'INVALID' that are configured in code-owners.config"
                + " (parameter codeOwners.pathExpressions) not found.");
  }

  @Test
  public void cannotConfigureInvalidPathExpressionsForBranch() throws Exception {
    fetchRefsMetaConfig();

    Config cfg = new Config();
    cfg.setString(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        "master",
        BackendConfig.KEY_PATH_EXPRESSIONS,
        "INVALID");
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus())
        .isEqualTo(Status.REJECTED_OTHER_REASON);
    assertThat(r.getMessages())
        .contains(
            "Path expressions 'INVALID' that are configured in code-owners.config"
                + " (parameter codeOwners.master.pathExpressions) not found.");
  }

  @Test
  public void configureRequiredApproval() throws Exception {
    fetchRefsMetaConfig();

    Config cfg = new Config();
    cfg.setString(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        RequiredApprovalConfig.KEY_REQUIRED_APPROVAL,
        "Code-Review+2");
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus()).isEqualTo(Status.OK);
    RequiredApproval requiredApproval =
        codeOwnersPluginConfiguration.getProjectConfig(project).getRequiredApproval();
    assertThat(requiredApproval).hasLabelNameThat().isEqualTo("Code-Review");
    assertThat(requiredApproval).hasValueThat().isEqualTo(2);
  }

  @Test
  public void cannotConfigureInvalidRequiredApproval() throws Exception {
    fetchRefsMetaConfig();

    Config cfg = new Config();
    cfg.setString(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        RequiredApprovalConfig.KEY_REQUIRED_APPROVAL,
        "INVALID");
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus())
        .isEqualTo(Status.REJECTED_OTHER_REASON);
    assertThat(r.getMessages())
        .contains(
            String.format(
                "Required approval 'INVALID' that is configured in code-owners.config (parameter"
                    + " codeOwners.%s) is invalid: Invalid format, expected"
                    + " '<label-name>+<label-value>'.",
                RequiredApprovalConfig.KEY_REQUIRED_APPROVAL));
  }

  @Test
  public void allRequiredApprovalsAreValidated() throws Exception {
    fetchRefsMetaConfig();

    ImmutableList<String> invalidValues = ImmutableList.of("INVALID", "ALSO_INVALID");
    Config cfg = new Config();
    cfg.setStringList(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        RequiredApprovalConfig.KEY_REQUIRED_APPROVAL,
        invalidValues);
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus())
        .isEqualTo(Status.REJECTED_OTHER_REASON);
    for (String invalidValue : invalidValues) {
      assertThat(r.getMessages())
          .contains(
              String.format(
                  "Required approval '%s' that is configured in code-owners.config (parameter"
                      + " codeOwners.%s) is invalid: Invalid format, expected"
                      + " '<label-name>+<label-value>'.",
                  invalidValue, RequiredApprovalConfig.KEY_REQUIRED_APPROVAL));
    }
  }

  @Test
  public void configureOverrideApproval() throws Exception {
    fetchRefsMetaConfig();

    Config cfg = new Config();
    cfg.setString(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        OverrideApprovalConfig.KEY_OVERRIDE_APPROVAL,
        "Code-Review+2");
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus()).isEqualTo(Status.OK);
    ImmutableSortedSet<RequiredApproval> overrideApprovals =
        codeOwnersPluginConfiguration.getProjectConfig(project).getOverrideApprovals();
    assertThat(overrideApprovals).hasSize(1);
    assertThat(overrideApprovals).element(0).hasLabelNameThat().isEqualTo("Code-Review");
    assertThat(overrideApprovals).element(0).hasValueThat().isEqualTo(2);
  }

  @Test
  public void cannotConfigureInvalidOverrideApproval() throws Exception {
    fetchRefsMetaConfig();

    Config cfg = new Config();
    cfg.setString(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        OverrideApprovalConfig.KEY_OVERRIDE_APPROVAL,
        "INVALID");
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus())
        .isEqualTo(Status.REJECTED_OTHER_REASON);
    assertThat(r.getMessages())
        .contains(
            String.format(
                "Required approval 'INVALID' that is configured in code-owners.config (parameter"
                    + " codeOwners.%s) is invalid: Invalid format, expected"
                    + " '<label-name>+<label-value>'.",
                OverrideApprovalConfig.KEY_OVERRIDE_APPROVAL));
  }

  @Test
  public void allOverrideApprovalsAreValidated() throws Exception {
    fetchRefsMetaConfig();

    ImmutableList<String> invalidValues = ImmutableList.of("INVALID", "ALSO_INVALID");
    Config cfg = new Config();
    cfg.setStringList(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        OverrideApprovalConfig.KEY_OVERRIDE_APPROVAL,
        invalidValues);
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus())
        .isEqualTo(Status.REJECTED_OTHER_REASON);
    for (String invalidValue : invalidValues) {
      assertThat(r.getMessages())
          .contains(
              String.format(
                  "Required approval '%s' that is configured in code-owners.config (parameter"
                      + " codeOwners.%s) is invalid: Invalid format, expected"
                      + " '<label-name>+<label-value>'.",
                  invalidValue, OverrideApprovalConfig.KEY_OVERRIDE_APPROVAL));
    }
  }

  @Test
  public void defineAndConfigureOverrideLabelInSameCommit() throws Exception {
    fetchRefsMetaConfig();

    RevCommit head = getHead(testRepo.getRepository(), RefNames.REFS_CONFIG);
    RevObject blob = testRepo.get(head.getTree(), "project.config");
    byte[] data = testRepo.getRepository().open(blob).getCachedBytes(Integer.MAX_VALUE);
    String projectConfigText = RawParseUtils.decode(data);

    Config projectConfig = new Config();
    projectConfig.fromText(projectConfigText);
    String labelName = "Owners-Override";
    projectConfig.setString("label", labelName, "function", "NoOp");
    projectConfig.setStringList(
        "label", labelName, "value", ImmutableList.of("0 Not Override", "+1 Override"));

    Config codeOwnersConfig = new Config();
    codeOwnersConfig.setString(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        OverrideApprovalConfig.KEY_OVERRIDE_APPROVAL,
        "Owners-Override+1");

    RevCommit commit =
        testRepo.update(
            RefNames.REFS_CONFIG,
            testRepo
                .commit()
                .parent(head)
                .message("Add test code owner config")
                .author(admin.newIdent())
                .committer(admin.newIdent())
                .add("code-owners.config", codeOwnersConfig.toText())
                .add("project.config", projectConfig.toText()));

    testRepo.reset(commit);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus()).isEqualTo(Status.OK);
    ImmutableSortedSet<RequiredApproval> overrideApprovals =
        codeOwnersPluginConfiguration.getProjectConfig(project).getOverrideApprovals();
    assertThat(overrideApprovals).hasSize(1);
    assertThat(overrideApprovals).element(0).hasLabelNameThat().isEqualTo("Owners-Override");
    assertThat(overrideApprovals).element(0).hasValueThat().isEqualTo(1);
  }

  @Test
  public void configureMergeCommitStrategy() throws Exception {
    fetchRefsMetaConfig();

    Config cfg = new Config();
    cfg.setEnum(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        GeneralConfig.KEY_MERGE_COMMIT_STRATEGY,
        MergeCommitStrategy.ALL_CHANGED_FILES);
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus()).isEqualTo(Status.OK);
    assertThat(codeOwnersPluginConfiguration.getProjectConfig(project).getMergeCommitStrategy())
        .isEqualTo(MergeCommitStrategy.ALL_CHANGED_FILES);
  }

  @Test
  public void cannotSetInvalidMergeCommitStrategy() throws Exception {
    fetchRefsMetaConfig();

    Config cfg = new Config();
    cfg.setString(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        GeneralConfig.KEY_MERGE_COMMIT_STRATEGY,
        "INVALID");
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus())
        .isEqualTo(Status.REJECTED_OTHER_REASON);
    assertThat(r.getMessages())
        .contains(
            "Merge commit strategy 'INVALID' that is configured in code-owners.config"
                + " (parameter codeOwners.mergeCommitStrategy) is invalid.");
  }

  @Test
  public void configureFallbackCodeOwners() throws Exception {
    fetchRefsMetaConfig();

    Config cfg = new Config();
    cfg.setEnum(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        GeneralConfig.KEY_FALLBACK_CODE_OWNERS,
        FallbackCodeOwners.ALL_USERS);
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus()).isEqualTo(Status.OK);
    assertThat(codeOwnersPluginConfiguration.getProjectConfig(project).getFallbackCodeOwners())
        .isEqualTo(FallbackCodeOwners.ALL_USERS);
  }

  @Test
  public void cannotSetInvalidFallbackCodeOwners() throws Exception {
    fetchRefsMetaConfig();

    Config cfg = new Config();
    cfg.setString(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        GeneralConfig.KEY_FALLBACK_CODE_OWNERS,
        "INVALID");
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus())
        .isEqualTo(Status.REJECTED_OTHER_REASON);
    assertThat(r.getMessages())
        .contains(
            "The value for fallback code owners 'INVALID' that is configured in code-owners.config"
                + " (parameter codeOwners.fallbackCodeOwners) is invalid.");
  }

  @Test
  public void configureMaxPathsInChangeMessages() throws Exception {
    fetchRefsMetaConfig();

    Config cfg = new Config();
    cfg.setInt(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        GeneralConfig.KEY_MAX_PATHS_IN_CHANGE_MESSAGES,
        50);
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus()).isEqualTo(Status.OK);
    assertThat(
            codeOwnersPluginConfiguration.getProjectConfig(project).getMaxPathsInChangeMessages())
        .isEqualTo(50);
  }

  @Test
  public void configureEnableAsyncMessageOnAddReviewer() throws Exception {
    fetchRefsMetaConfig();

    Config cfg = new Config();
    cfg.setBoolean(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        GeneralConfig.KEY_ENABLE_ASYNC_MESSAGE_ON_ADD_REVIEWER,
        false);
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus()).isEqualTo(Status.OK);
    assertThat(
            codeOwnersPluginConfiguration
                .getProjectConfig(project)
                .enableAsyncMessageOnAddReviewer())
        .isFalse();
  }

  @Test
  public void cannotSetInvalidMaxPathsInChangeMessages() throws Exception {
    fetchRefsMetaConfig();

    Config cfg = new Config();
    cfg.setString(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        GeneralConfig.KEY_MAX_PATHS_IN_CHANGE_MESSAGES,
        "INVALID");
    setCodeOwnersConfig(cfg);

    PushResult r = pushRefsMetaConfig();
    assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus())
        .isEqualTo(Status.REJECTED_OTHER_REASON);
    assertThat(r.getMessages())
        .contains(
            "The value for max paths in change messages 'INVALID' that is configured in"
                + " code-owners.config (parameter codeOwners.maxPathsInChangeMessages) is invalid.");
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.disabledBranch", value = "refs/meta/config")
  public void validationDoesntFailOnRebaseChange_unrelatedChange() throws Exception {
    // Create two changes for refs/meta/config both with the same parent.
    GitUtil.fetch(testRepo, RefNames.REFS_CONFIG + ":config");
    testRepo.reset("config");
    PushOneCommit push =
        pushFactory.create(admin.newIdent(), testRepo, "Change 1", "a.txt", "content");
    PushOneCommit.Result r = push.to("refs/for/" + RefNames.REFS_CONFIG);
    r.assertOkStatus();
    String changeId1 = r.getChangeId();

    testRepo.reset("config");
    push = pushFactory.create(admin.newIdent(), testRepo, "Change 2", "b.txt", "content");
    r = push.to("refs/for/" + RefNames.REFS_CONFIG);
    r.assertOkStatus();
    String changeId2 = r.getChangeId();

    // Approve and submit the first change
    approve(changeId1);
    gApi.changes().id(changeId1).current().submit();

    // Rebase the second change, throws an exception if the code owner plugin config validation
    // fails.
    gApi.changes().id(changeId2).rebase();

    // Second change should have 2 patch sets now.
    ChangeInfo changeInfo = gApi.changes().id(changeId2).get(CURRENT_REVISION);
    assertThat(changeInfo.revisions.get(changeInfo.currentRevision)._number).isEqualTo(2);
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.disabledBranch", value = "refs/meta/config")
  public void validationDoesntFailOnRebaseChange_changeThatUpdatesTheCodeOwnersConfig()
      throws Exception {
    // Create two changes for refs/meta/config both with the same parent.
    GitUtil.fetch(testRepo, RefNames.REFS_CONFIG + ":config");
    testRepo.reset("config");
    PushOneCommit push =
        pushFactory.create(admin.newIdent(), testRepo, "Change 1", "a,txt", "content");
    PushOneCommit.Result r = push.to("refs/for/" + RefNames.REFS_CONFIG);
    r.assertOkStatus();
    String changeId1 = r.getChangeId();

    testRepo.reset("config");
    Config cfg = new Config();
    cfg.setEnum(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        GeneralConfig.KEY_FALLBACK_CODE_OWNERS,
        FallbackCodeOwners.ALL_USERS);
    push =
        pushFactory.create(
            admin.newIdent(), testRepo, "Change 2", "code-owners.config", cfg.toText());
    r = push.to("refs/for/" + RefNames.REFS_CONFIG);
    r.assertOkStatus();
    String changeId2 = r.getChangeId();

    // Approve and submit the first change
    approve(changeId1);
    gApi.changes().id(changeId1).current().submit();

    // Rebase the second change, throws an exception if the code owner plugin config validation
    // fails.
    gApi.changes().id(changeId2).rebase();

    // Second change should have 2 patch sets now.
    ChangeInfo changeInfo = gApi.changes().id(changeId2).get(CURRENT_REVISION);
    assertThat(changeInfo.revisions.get(changeInfo.currentRevision)._number).isEqualTo(2);
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.disabledBranch", value = "refs/meta/config")
  public void validationFailsOnRebaseChange_changeThatCreatesInvalidCodeOwnerConfig()
      throws Exception {
    // Create two changes for refs/meta/config both with the same parent.
    GitUtil.fetch(testRepo, RefNames.REFS_CONFIG + ":config");
    testRepo.reset("config");
    Config cfg = new Config();
    cfg.setEnum(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        GeneralConfig.KEY_FALLBACK_CODE_OWNERS,
        FallbackCodeOwners.NONE);
    PushOneCommit push =
        pushFactory.create(
            admin.newIdent(), testRepo, "Change 1", "code-owners.config", cfg.toText());
    PushOneCommit.Result r = push.to("refs/for/" + RefNames.REFS_CONFIG);
    r.assertOkStatus();
    String changeId1 = r.getChangeId();

    testRepo.reset("config");
    cfg = new Config();
    cfg.setEnum(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        GeneralConfig.KEY_FALLBACK_CODE_OWNERS,
        FallbackCodeOwners.ALL_USERS);
    push =
        pushFactory.create(
            admin.newIdent(), testRepo, "Change 2", "code-owners.config", cfg.toText());
    r = push.to("refs/for/" + RefNames.REFS_CONFIG);
    r.assertOkStatus();
    String changeId2 = r.getChangeId();

    // Approve and submit the first change
    approve(changeId1);
    gApi.changes().id(changeId1).current().submit();

    // Rebase the second change with allowing conflicts. This results in a code-owners.config that
    // contains conflict markers and hence is rejected as invalid.
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.allowConflicts = true;
    ResourceConflictException exception =
        assertThrows(
            ResourceConflictException.class,
            () -> gApi.changes().id(changeId2).rebase(rebaseInput));
    assertThat(exception)
        .hasMessageThat()
        .contains(
            String.format(
                "Invalid config file code-owners.config in project %s in branch %s",
                project, RefNames.REFS_CONFIG));
  }

  @Test
  public void validatorForProjectConfigIsInvokedBeforeCodeOwnersConfigValidator() throws Exception {
    fetchRefsMetaConfig();
    Config cfg = new Config();
    cfg.setEnum(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        GeneralConfig.KEY_FALLBACK_CODE_OWNERS,
        FallbackCodeOwners.ALL_USERS);
    PushOneCommit push =
        pushFactory.create(
            admin.newIdent(),
            testRepo,
            "Change 1",
            ImmutableMap.of("code-owners.config", cfg.toText(), "project.config", "INVALID"));
    PushOneCommit.Result r = push.to("refs/for/" + RefNames.REFS_CONFIG);

    // The invalid project.config is rejected by the project config validator in Gerrit core before
    // CodeOwnersPluginConfigValidator is invoked (if CodeOwnersPluginConfigValidator would be
    // invoked first it would fail with a ConfigInvalidException and the message would be "internal
    // error").
    r.assertMessage(
        String.format(
            "commit %s: invalid project configuration",
            ObjectIds.abbreviateName(r.getCommit(), testRepo.getRevWalk().getObjectReader())));
  }

  @Test
  public void warnIfCodeOwnersConfigurationIsDoneInProjectConfig_configWithPluginCodeOwnersSection()
      throws Exception {
    fetchRefsMetaConfig();
    Config cfg = new Config();
    cfg.setEnum(
        /* section= */ "plugin",
        /* subsection= */ "code-owners",
        GeneralConfig.KEY_FALLBACK_CODE_OWNERS,
        FallbackCodeOwners.ALL_USERS);
    PushOneCommit push =
        pushFactory.create(admin.newIdent(), testRepo, "Change", "project.config", cfg.toText());
    PushOneCommit.Result r = push.to("refs/for/" + RefNames.REFS_CONFIG);
    r.assertOkStatus();
    r.assertMessage(
        String.format(
            "hint: commit %s: Section 'plugin.code-owners' in project.config is ignored and has no"
                + " effect. The configuration for the code-owners plugin must be done in"
                + " code-owners.config.",
            ObjectIds.abbreviateName(r.getCommit(), testRepo.getRevWalk().getObjectReader())));
  }

  @Test
  public void warnIfCodeOwnersConfigurationIsDoneInProjectConfig_configWithCodeOwnersSection()
      throws Exception {
    fetchRefsMetaConfig();
    Config cfg = new Config();
    cfg.setEnum(
        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
        /* subsection= */ null,
        GeneralConfig.KEY_FALLBACK_CODE_OWNERS,
        FallbackCodeOwners.ALL_USERS);
    PushOneCommit push =
        pushFactory.create(admin.newIdent(), testRepo, "Change", "project.config", cfg.toText());
    PushOneCommit.Result r = push.to("refs/for/" + RefNames.REFS_CONFIG);
    r.assertOkStatus();
    r.assertMessage(
        String.format(
            "hint: commit %s: Section 'codeOwners' in project.config is ignored and has no effect."
                + " The configuration for the code-owners plugin must be done in code-owners.config.",
            ObjectIds.abbreviateName(r.getCommit(), testRepo.getRevWalk().getObjectReader())));
  }

  @Test
  public void noWarningIfProjectConfigIsUpdatedWithoutCodeOwnerSettings() throws Exception {
    fetchRefsMetaConfig();
    Config cfg = new Config();
    cfg.setString(
        /* section= */ "foo", /* subsection= */ null, /* name= */ "bar", /* value= */ "baz");
    PushOneCommit push =
        pushFactory.create(admin.newIdent(), testRepo, "Change", "project.config", cfg.toText());
    PushOneCommit.Result r = push.to("refs/for/" + RefNames.REFS_CONFIG);
    r.assertOkStatus();
    r.assertNotMessage(
        "The configuration for the code-owners plugin must be done in code-owners.config.");
  }

  private void fetchRefsMetaConfig() throws Exception {
    fetch(testRepo, RefNames.REFS_CONFIG + ":" + RefNames.REFS_CONFIG);
    testRepo.reset(RefNames.REFS_CONFIG);
  }

  private PushResult pushRefsMetaConfig() throws Exception {
    return pushHead(testRepo, RefNames.REFS_CONFIG);
  }

  private void setCodeOwnersConfig(Config codeOwnersConfig) throws Exception {
    setCodeOwnersConfig(codeOwnersConfig.toText());
  }

  private void setCodeOwnersConfig(String codeOwnersConfig) throws Exception {
    RevCommit head = getHead(testRepo.getRepository(), RefNames.REFS_CONFIG);
    RevCommit commit =
        testRepo.update(
            RefNames.REFS_CONFIG,
            testRepo
                .commit()
                .parent(head)
                .message("Add test code owner config")
                .author(admin.newIdent())
                .committer(admin.newIdent())
                .add("code-owners.config", codeOwnersConfig));

    testRepo.reset(commit);
  }
}
