// Copyright (C) 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.plugins.codeowners.backend.config;

import static com.google.common.truth.Truth.assertThat;

import com.google.common.collect.ImmutableList;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.plugins.codeowners.acceptance.AbstractCodeOwnersTest;
import com.google.inject.Inject;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Before;
import org.junit.Test;

/** Tests for {@link CodeOwnersPluginConfig}. */
public class CodeOwnersPluginConfigTest extends AbstractCodeOwnersTest {
  private static final String SECTION = CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS;
  private static final String SUBSECTION = "subsection";
  private static final String SUBSECTION_2 = "subsection2";
  private static final String SUBSECTION_3 = "subsection3";
  private static final String KEY = "key";
  private static final String VALUE = "foo";
  private static final String VALUE_2 = "bar";
  private static final String VALUE_3 = "baz";
  private static final String VALUE_4 = "foo_bar";
  private static final String VALUE_5 = "foo_baz";
  private static final String VALUE_6 = "bar_foo";

  @Inject private ProjectOperations projectOperations;

  private CodeOwnersPluginConfig.Factory codeOwnersPluginConfigFactory;
  private Project.NameKey parent;

  @Before
  public void setUpCodeOwnersPlugin() throws Exception {
    codeOwnersPluginConfigFactory =
        plugin.getSysInjector().getInstance(CodeOwnersPluginConfig.Factory.class);
  }

  @Before
  public void setUpProject() throws Exception {
    parent = project;
    project = projectOperations.newProject().parent(parent).create();
  }

  @Test
  public void getSingleValue_noValueSet() throws Exception {
    assertThat(cfg().getString(SECTION, /* subsection= */ null, KEY)).isNull();
  }

  @Test
  public void getSingleValue_singleValueSet() throws Exception {
    setSingleValue(project, VALUE);
    assertThat(cfg().getString(SECTION, /* subsection= */ null, KEY)).isEqualTo(VALUE);
  }

  @Test
  public void getSingleValue_multiValueSet() throws Exception {
    setMultiValue(project, VALUE, VALUE_2, VALUE_3);

    // last value takes precedence
    assertThat(cfg().getString(SECTION, /* subsection= */ null, KEY)).isEqualTo(VALUE_3);
  }

  @Test
  public void getSingleValue_singleValueSetForParent() throws Exception {
    setSingleValue(parent, VALUE);
    assertThat(cfg().getString(SECTION, /* subsection= */ null, KEY)).isEqualTo(VALUE);
  }

  @Test
  public void getSingleValue_multiValueSetForParent() throws Exception {
    setMultiValue(parent, VALUE, VALUE_2, VALUE_3);

    // last value takes precedence
    assertThat(cfg().getString(SECTION, /* subsection= */ null, KEY)).isEqualTo(VALUE_3);
  }

  @Test
  public void getSingleValue_valueOverridesSingleParentValues() throws Exception {
    setSingleValue(allProjects, VALUE);
    setSingleValue(parent, VALUE_2);
    setSingleValue(project, VALUE_3);
    assertThat(cfg().getString(SECTION, /* subsection= */ null, KEY)).isEqualTo(VALUE_3);
  }

  @Test
  public void getSingleValue_valueOverridesMultiParentValues() throws Exception {
    setMultiValue(allProjects, VALUE, VALUE_2);
    setMultiValue(parent, VALUE_3, VALUE_4);
    setSingleValue(project, VALUE_5);
    assertThat(cfg().getString(SECTION, /* subsection= */ null, KEY)).isEqualTo(VALUE_5);
  }

  @Test
  public void getSingleValue_unsetSingleParentValues() throws Exception {
    setSingleValue(allProjects, VALUE);
    setSingleValue(parent, VALUE_2);
    setSingleValue(project, "");
    assertThat(cfg().getString(SECTION, /* subsection= */ null, KEY)).isNull();
  }

  @Test
  public void getSingleValue_unsetMultiParentValues() throws Exception {
    setMultiValue(allProjects, VALUE, VALUE_2);
    setMultiValue(parent, VALUE_3, VALUE_4);
    setSingleValue(project, "");
    assertThat(cfg().getString(SECTION, /* subsection= */ null, KEY)).isNull();
  }

  @Test
  public void getSingleValueFromSubsection_noValueSet() throws Exception {
    assertThat(cfg().getString(SECTION, SUBSECTION, KEY)).isNull();
  }

  @Test
  public void getSingleValueFromSubsection_singleValueSet() throws Exception {
    setSingleValueForSubsection(project, SUBSECTION, VALUE);
    assertThat(cfg().getString(SECTION, SUBSECTION, KEY)).isEqualTo(VALUE);
  }

  @Test
  public void getSingleValueFromSubsection_multiValueSet() throws Exception {
    setMultiValueForSubsection(project, SUBSECTION, VALUE, VALUE_2, VALUE_3);

    // last value takes precedence
    assertThat(cfg().getString(SECTION, SUBSECTION, KEY)).isEqualTo(VALUE_3);
  }

  @Test
  public void getSingleValueFromSubsection_singleValueSetForParent() throws Exception {
    setSingleValueForSubsection(parent, SUBSECTION, VALUE);
    assertThat(cfg().getString(SECTION, SUBSECTION, KEY)).isEqualTo(VALUE);
  }

  @Test
  public void getSingleValueFromSubsection_multiValueSetForParent() throws Exception {
    setMultiValueForSubsection(parent, SUBSECTION, VALUE, VALUE_2, VALUE_3);

    // last value takes precedence
    assertThat(cfg().getString(SECTION, SUBSECTION, KEY)).isEqualTo(VALUE_3);
  }

  @Test
  public void getSingleValueFromSubsection_valueOverridesSingleParentValues() throws Exception {
    setSingleValueForSubsection(allProjects, SUBSECTION, VALUE);
    setSingleValueForSubsection(parent, SUBSECTION, VALUE_2);
    setSingleValueForSubsection(project, SUBSECTION, VALUE_3);
    assertThat(cfg().getString(SECTION, SUBSECTION, KEY)).isEqualTo(VALUE_3);
  }

  @Test
  public void getSingleValueFromSubsection_valueOverridesMultiParentValues() throws Exception {
    setMultiValueForSubsection(allProjects, SUBSECTION, VALUE, VALUE_2);
    setMultiValueForSubsection(parent, SUBSECTION, VALUE_3, VALUE_4);
    setSingleValueForSubsection(project, SUBSECTION, VALUE_5);
    assertThat(cfg().getString(SECTION, SUBSECTION, KEY)).isEqualTo(VALUE_5);
  }

  @Test
  public void getSingleValueFromSubsection_unsetSingleParentValues() throws Exception {
    setSingleValueForSubsection(allProjects, SUBSECTION, VALUE);
    setSingleValueForSubsection(parent, SUBSECTION, VALUE_2);
    setSingleValueForSubsection(project, SUBSECTION, "");
    assertThat(cfg().getString(SECTION, SUBSECTION, KEY)).isNull();
  }

  @Test
  public void getSingleValueFromSubsection_unsetMultiParentValues() throws Exception {
    setMultiValueForSubsection(allProjects, SUBSECTION, VALUE, VALUE_2);
    setMultiValueForSubsection(parent, SUBSECTION, VALUE_3, VALUE_4);
    setSingleValueForSubsection(project, SUBSECTION, "");
    assertThat(cfg().getString(SECTION, SUBSECTION, KEY)).isNull();
  }

  @Test
  public void getMultiValue_noValueSet() throws Exception {
    assertThat(cfg().getStringList(SECTION, /* subsection= */ null, KEY)).isEmpty();
  }

  @Test
  public void getMultiValue_singleValueSet() throws Exception {
    setSingleValue(project, VALUE);
    assertThat(cfg().getStringList(SECTION, /* subsection= */ null, KEY))
        .asList()
        .containsExactly(VALUE);
  }

  @Test
  public void getMultiValue_multiValueSet() throws Exception {
    setMultiValue(project, VALUE, VALUE_2, VALUE_3);
    assertThat(cfg().getStringList(SECTION, /* subsection= */ null, KEY))
        .asList()
        .containsExactly(VALUE, VALUE_2, VALUE_3)
        .inOrder();
  }

  @Test
  public void getMultiValue_singleValueSetForParent() throws Exception {
    setSingleValue(parent, VALUE);
    assertThat(cfg().getStringList(SECTION, /* subsection= */ null, KEY))
        .asList()
        .containsExactly(VALUE);
  }

  @Test
  public void getMultiValue_multiValueSetForParent() throws Exception {
    setMultiValue(parent, VALUE, VALUE_2, VALUE_3);
    assertThat(cfg().getStringList(SECTION, /* subsection= */ null, KEY))
        .asList()
        .containsExactly(VALUE, VALUE_2, VALUE_3)
        .inOrder();
  }

  @Test
  public void getMultiValue_singleValueExtendsSingleParentValues() throws Exception {
    setSingleValue(allProjects, VALUE);
    setSingleValue(parent, VALUE_2);
    setSingleValue(project, VALUE_3);
    assertThat(cfg().getStringList(SECTION, /* subsection= */ null, KEY))
        .asList()
        .containsExactly(VALUE, VALUE_2, VALUE_3)
        .inOrder();
  }

  @Test
  public void getMultiValue_singleValueOverridesMultiParentValues() throws Exception {
    setMultiValue(allProjects, VALUE, VALUE_2);
    setMultiValue(parent, VALUE_3, VALUE_4);
    setSingleValue(project, VALUE_5);
    assertThat(cfg().getStringList(SECTION, /* subsection= */ null, KEY))
        .asList()
        .containsExactly(VALUE, VALUE_2, VALUE_3, VALUE_4, VALUE_5)
        .inOrder();
  }

  @Test
  public void getMultiValue_multiValueExtendsSingleParentValues() throws Exception {
    setSingleValue(allProjects, VALUE);
    setSingleValue(parent, VALUE_2);
    setMultiValue(project, VALUE_3, VALUE_4);
    assertThat(cfg().getStringList(SECTION, /* subsection= */ null, KEY))
        .asList()
        .containsExactly(VALUE, VALUE_2, VALUE_3, VALUE_4)
        .inOrder();
  }

  @Test
  public void getMultiValue_multiValueExtendsMultiParentValues() throws Exception {
    setMultiValue(allProjects, VALUE, VALUE_2);
    setMultiValue(parent, VALUE_3, VALUE_4);
    setMultiValue(project, VALUE_5, VALUE_6);
    assertThat(cfg().getStringList(SECTION, /* subsection= */ null, KEY))
        .asList()
        .containsExactly(VALUE, VALUE_2, VALUE_3, VALUE_4, VALUE_5, VALUE_6)
        .inOrder();
  }

  @Test
  public void getMultiValue_multiValueExtendsMultiParentValues_withDuplicates() throws Exception {
    setMultiValue(allProjects, VALUE, VALUE_2);
    setMultiValue(parent, VALUE_3);
    setMultiValue(project, VALUE, VALUE_2);
    assertThat(cfg().getStringList(SECTION, /* subsection= */ null, KEY))
        .asList()
        .containsExactly(VALUE, VALUE_2, VALUE_3, VALUE, VALUE_2)
        .inOrder();
  }

  @Test
  public void getMultiValue_cannotUnsetSingleParentValues() throws Exception {
    setSingleValue(allProjects, VALUE);
    setSingleValue(parent, VALUE_2);
    setSingleValue(project, "");

    // the empty string is returned as null value in the list
    assertThat(cfg().getStringList(SECTION, /* subsection= */ null, KEY))
        .asList()
        .containsExactly(VALUE, VALUE_2, null)
        .inOrder();
  }

  @Test
  public void getMultiValue_cannotUnsetMultiParentValues() throws Exception {
    setMultiValue(allProjects, VALUE, VALUE_2);
    setMultiValue(parent, VALUE_3, VALUE_4);
    setSingleValue(project, "");

    // the empty string is returned as null value in the list
    assertThat(cfg().getStringList(SECTION, /* subsection= */ null, KEY))
        .asList()
        .containsExactly(VALUE, VALUE_2, VALUE_3, VALUE_4, null)
        .inOrder();
  }

  @Test
  public void getMultiValueFromSubsection_noValueSet() throws Exception {
    assertThat(cfg().getStringList(SECTION, SUBSECTION, KEY)).isEmpty();
  }

  @Test
  public void getMultiValueFromSubsection_singleValueSet() throws Exception {
    setSingleValueForSubsection(project, SUBSECTION, VALUE);
    assertThat(cfg().getStringList(SECTION, SUBSECTION, KEY)).asList().containsExactly(VALUE);
  }

  @Test
  public void getMultiValueFromSubsection_multiValueSet() throws Exception {
    setMultiValueForSubsection(project, SUBSECTION, VALUE, VALUE_2, VALUE_3);
    assertThat(cfg().getStringList(SECTION, SUBSECTION, KEY))
        .asList()
        .containsExactly(VALUE, VALUE_2, VALUE_3)
        .inOrder();
  }

  @Test
  public void getMultiValueFromSubsection_singleValueSetForParent() throws Exception {
    setSingleValueForSubsection(parent, SUBSECTION, VALUE);
    assertThat(cfg().getStringList(SECTION, SUBSECTION, KEY)).asList().containsExactly(VALUE);
  }

  @Test
  public void getMultiValueFromSubsection_multiValueSetForParent() throws Exception {
    setMultiValueForSubsection(parent, SUBSECTION, VALUE, VALUE_2, VALUE_3);
    assertThat(cfg().getStringList(SECTION, SUBSECTION, KEY))
        .asList()
        .containsExactly(VALUE, VALUE_2, VALUE_3)
        .inOrder();
  }

  @Test
  public void getMultiValueFromSubsection_singleValueExtendsSingleParentValues() throws Exception {
    setSingleValueForSubsection(allProjects, SUBSECTION, VALUE);
    setSingleValueForSubsection(parent, SUBSECTION, VALUE_2);
    setSingleValueForSubsection(project, SUBSECTION, VALUE_3);
    assertThat(cfg().getStringList(SECTION, SUBSECTION, KEY))
        .asList()
        .containsExactly(VALUE, VALUE_2, VALUE_3)
        .inOrder();
  }

  @Test
  public void getMultiValueFromSubsection_singleValueOverridesMultiParentValues() throws Exception {
    setMultiValueForSubsection(allProjects, SUBSECTION, VALUE, VALUE_2);
    setMultiValueForSubsection(parent, SUBSECTION, VALUE_3, VALUE_4);
    setSingleValueForSubsection(project, SUBSECTION, VALUE_5);
    assertThat(cfg().getStringList(SECTION, SUBSECTION, KEY))
        .asList()
        .containsExactly(VALUE, VALUE_2, VALUE_3, VALUE_4, VALUE_5)
        .inOrder();
  }

  @Test
  public void getMultiValueFromSubsection_multiValueExtendsSingleParentValues() throws Exception {
    setSingleValueForSubsection(allProjects, SUBSECTION, VALUE);
    setSingleValueForSubsection(parent, SUBSECTION, VALUE_2);
    setMultiValueForSubsection(project, SUBSECTION, VALUE_3, VALUE_4);
    assertThat(cfg().getStringList(SECTION, SUBSECTION, KEY))
        .asList()
        .containsExactly(VALUE, VALUE_2, VALUE_3, VALUE_4)
        .inOrder();
  }

  @Test
  public void getMultiValueFromSubsection_multiValueExtendsMultiParentValues() throws Exception {
    setMultiValueForSubsection(allProjects, SUBSECTION, VALUE, VALUE_2);
    setMultiValueForSubsection(parent, SUBSECTION, VALUE_3, VALUE_4);
    setMultiValueForSubsection(project, SUBSECTION, VALUE_5, VALUE_6);
    assertThat(cfg().getStringList(SECTION, SUBSECTION, KEY))
        .asList()
        .containsExactly(VALUE, VALUE_2, VALUE_3, VALUE_4, VALUE_5, VALUE_6)
        .inOrder();
  }

  @Test
  public void getMultiValueFromSubsection_cannotUnsetSingleParentValues() throws Exception {
    setSingleValueForSubsection(allProjects, SUBSECTION, VALUE);
    setSingleValueForSubsection(parent, SUBSECTION, VALUE_2);
    setSingleValueForSubsection(project, SUBSECTION, "");

    // the empty string is returned as null value in the list
    assertThat(cfg().getStringList(SECTION, SUBSECTION, KEY))
        .asList()
        .containsExactly(VALUE, VALUE_2, null)
        .inOrder();
  }

  @Test
  public void getMultiValueFromSubsection_cannotUnsetMultiParentValues() throws Exception {
    setMultiValueForSubsection(allProjects, SUBSECTION, VALUE, VALUE_2);
    setMultiValueForSubsection(parent, SUBSECTION, VALUE_3, VALUE_4);
    setSingleValueForSubsection(project, SUBSECTION, "");

    // the empty string is returned as null value in the list
    assertThat(cfg().getStringList(SECTION, SUBSECTION, KEY))
        .asList()
        .containsExactly(VALUE, VALUE_2, VALUE_3, VALUE_4, null)
        .inOrder();
  }

  @Test
  public void getSubsections() throws Exception {
    setSingleValueForSubsection(allProjects, SUBSECTION, VALUE);
    setSingleValueForSubsection(parent, SUBSECTION_2, VALUE_2);
    setSingleValueForSubsection(project, SUBSECTION_3, VALUE_3);
    assertThat(cfg().getSubsections(SECTION))
        .containsExactly(SUBSECTION, SUBSECTION_2, SUBSECTION_3);
  }

  @Test
  public void getEmptySubsections() throws Exception {
    createConfigWithEmptySubsection(allProjects, SUBSECTION);
    createConfigWithEmptySubsection(parent, SUBSECTION_2);
    createConfigWithEmptySubsection(project, SUBSECTION_3);
    assertThat(cfg().getSubsections(SECTION))
        .containsExactly(SUBSECTION, SUBSECTION_2, SUBSECTION_3);
  }

  private Config cfg() {
    return codeOwnersPluginConfigFactory.create(project).get();
  }

  private void setSingleValue(Project.NameKey project, String value) throws Exception {
    setSingleValueForSubsection(project, /* subsection= */ null, value);
  }

  private void setSingleValueForSubsection(
      Project.NameKey project, @Nullable String subsection, String value) throws Exception {
    setCodeOwnersConfig(project, subsection, KEY, value);
  }

  private void setMultiValue(Project.NameKey project, String... values) throws Exception {
    setMultiValueForSubsection(project, /* subsection= */ null, values);
  }

  private void setMultiValueForSubsection(
      Project.NameKey project, @Nullable String subsection, String... values) throws Exception {
    setCodeOwnersConfig(project, subsection, KEY, ImmutableList.copyOf(values));
  }

  private void createConfigWithEmptySubsection(Project.NameKey project, String subsection)
      throws Exception {
    try (TestRepository<Repository> testRepo =
        new TestRepository<>(repoManager.openRepository(project))) {
      Ref ref = testRepo.getRepository().exactRef(RefNames.REFS_CONFIG);
      RevCommit head = testRepo.getRevWalk().parseCommit(ref.getObjectId());
      testRepo.update(
          RefNames.REFS_CONFIG,
          testRepo
              .commit()
              .parent(head)
              .message("Configure code owner backend")
              .add("code-owners.config", String.format("[%s \"%s\"]", SECTION, subsection)));
    }
    projectCache.evictAndReindex(project);
  }
}
