// Copyright (C) 2017 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.googlesource.gerrit.owners.common;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
import static com.googlesource.gerrit.owners.common.MatcherConfig.suffixMatcher;
import static java.util.Collections.emptyList;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.powermock.api.easymock.PowerMock.replayAll;

import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.eclipse.jgit.lib.Repository;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PowerMockIgnore("jdk.internal.reflect.*")
@PrepareForTest(JgitWrapper.class)
public class PathOwnersTest extends ClassicConfig {

  private static final String CLASSIC_OWNERS = "classic/OWNERS";
  private static final boolean EXPAND_GROUPS = true;
  private static final boolean DO_NOT_EXPAND_GROUPS = false;
  private static final String EXPECTED_LABEL = "expected-label";
  private static final String A_LABEL = "a-label";
  private static PathOwnersEntriesCache CACHE_MOCK = new PathOwnersEntriesCacheMock();

  public static final String CLASSIC_FILE_TXT = "classic/file.txt";
  public static final Project.NameKey parentRepository1NameKey =
      Project.NameKey.parse("parentRepository1");
  public static final Project.NameKey parentRepository2NameKey =
      Project.NameKey.parse("parentRepository2");

  @Override
  @Before
  public void setup() throws Exception {
    super.setup();
  }

  @Test
  public void testClassic() throws Exception {
    mockOwners(USER_A_EMAIL_COM, USER_B_EMAIL_COM);

    PathOwners owners =
        new PathOwners(
            accounts,
            repositoryManager,
            repository,
            emptyList(),
            branch,
            Set.of(CLASSIC_FILE_TXT),
            EXPAND_GROUPS,
            "foo",
            CACHE_MOCK);
    Set<Account.Id> ownersSet = owners.get().get(CLASSIC_OWNERS);
    assertEquals(2, ownersSet.size());
    assertTrue(ownersSet.contains(USER_A_ID));
    assertTrue(ownersSet.contains(USER_B_ID));
    assertTrue(owners.expandGroups());
  }

  @Test
  public void testFileBasedOwnersUnexpanded() throws Exception {
    mockOwners(USER_A_EMAIL_COM, USER_B_EMAIL_COM);

    PathOwners owners =
        new PathOwners(
            accounts,
            repositoryManager,
            repository,
            emptyList(),
            branch,
            Set.of(CLASSIC_FILE_TXT),
            DO_NOT_EXPAND_GROUPS,
            "foo",
            CACHE_MOCK);
    Set<String> ownersSet = owners.getFileGroupOwners().get(CLASSIC_FILE_TXT);
    assertEquals(2, ownersSet.size());
    assertTrue(ownersSet.contains(USER_A));
    assertTrue(ownersSet.contains(USER_B));
    assertFalse(owners.expandGroups());
  }

  @Test
  public void testDisabledBranch() throws Exception {
    mockOwners(USER_A_EMAIL_COM);

    PathOwners owners =
        new PathOwners(
            accounts,
            repositoryManager,
            repository,
            emptyList(),
            Optional.empty(),
            Set.of(CLASSIC_FILE_TXT),
            EXPAND_GROUPS,
            "foo",
            CACHE_MOCK);
    Set<Account.Id> ownersSet = owners.get().get(CLASSIC_OWNERS);
    assertEquals(0, ownersSet.size());
  }

  @Test
  public void testClassicWithInheritance() throws Exception {
    expectConfig("OWNERS", createConfig(true, Optional.of(A_LABEL), owners(USER_C_EMAIL_COM)));
    expectConfig(
        CLASSIC_OWNERS,
        createConfig(
            true, Optional.of(EXPECTED_LABEL), owners(USER_A_EMAIL_COM, USER_B_EMAIL_COM)));

    replayAll();

    PathOwners owners2 =
        new PathOwners(
            accounts,
            repositoryManager,
            repository,
            emptyList(),
            branch,
            Set.of("classic/file.txt"),
            EXPAND_GROUPS,
            "foo",
            CACHE_MOCK);
    Set<Account.Id> ownersSet2 = owners2.get().get(CLASSIC_OWNERS);

    // in this case we are inheriting the acct3 from /OWNERS
    assertEquals(3, ownersSet2.size());
    assertTrue(ownersSet2.contains(USER_A_ID));
    assertTrue(ownersSet2.contains(USER_B_ID));
    assertTrue(ownersSet2.contains(USER_C_ID));

    // expect that classic configuration takes precedence over `OWNERS` file for the label
    // definition
    assertThat(owners2.getLabel().map(LabelDefinition::getName)).hasValue(EXPECTED_LABEL);
  }

  @Test
  public void testRootInheritFromProject() throws Exception {
    expectConfig("OWNERS", "master", createConfig(true, owners()));
    expectConfig(
        "OWNERS",
        RefNames.REFS_CONFIG,
        createConfig(
            true,
            Optional.of(EXPECTED_LABEL),
            owners(),
            suffixMatcher(".sql", USER_A_EMAIL_COM, USER_B_EMAIL_COM)));

    String fileName = "file.sql";
    replayAll();

    PathOwners owners =
        new PathOwners(
            accounts,
            repositoryManager,
            repository,
            emptyList(),
            branch,
            Set.of(fileName),
            EXPAND_GROUPS,
            "foo",
            CACHE_MOCK);

    Map<String, Set<Account.Id>> fileOwners = owners.getFileOwners();
    assertEquals(1, fileOwners.size());

    Set<Account.Id> ownersSet = fileOwners.get(fileName);
    assertEquals(2, ownersSet.size());
    assertTrue(ownersSet.contains(USER_A_ID));
    assertTrue(ownersSet.contains(USER_B_ID));
    assertThat(owners.getLabel().map(LabelDefinition::getName)).hasValue(EXPECTED_LABEL);
  }

  @Test
  public void testProjectInheritFromParentProject() throws Exception {
    expectConfig("OWNERS", "master", createConfig(true, Optional.of(EXPECTED_LABEL), owners()));
    expectConfig(
        "OWNERS",
        RefNames.REFS_CONFIG,
        repository,
        createConfig(true, Optional.of("foo"), owners()));
    expectConfig(
        "OWNERS",
        RefNames.REFS_CONFIG,
        parentRepository1,
        createConfig(
            true,
            Optional.of(A_LABEL),
            owners(),
            suffixMatcher(".sql", USER_A_EMAIL_COM, USER_B_EMAIL_COM)));

    String fileName = "file.sql";

    mockParentRepository(parentRepository1NameKey, parentRepository1);
    replayAll();

    PathOwners owners =
        new PathOwners(
            accounts,
            repositoryManager,
            repository,
            Arrays.asList(parentRepository1NameKey),
            branch,
            Set.of(fileName),
            EXPAND_GROUPS,
            "foo",
            CACHE_MOCK);

    Map<String, Set<Account.Id>> fileOwners = owners.getFileOwners();
    assertEquals(fileOwners.size(), 1);

    Set<Account.Id> ownersSet = fileOwners.get(fileName);
    assertEquals(2, ownersSet.size());
    assertTrue(ownersSet.contains(USER_A_ID));
    assertTrue(ownersSet.contains(USER_B_ID));

    // expect that `master` configuration overwrites the label definition of both `refs/meta/config`
    // and parent repo
    assertThat(owners.getLabel().map(LabelDefinition::getName)).hasValue(EXPECTED_LABEL);
  }

  @Test
  public void testProjectInheritFromMultipleParentProjects() throws Exception {
    expectConfig("OWNERS", "master", createConfig(true, owners()));
    expectConfig("OWNERS", RefNames.REFS_CONFIG, repository, createConfig(true, owners()));
    expectConfig(
        "OWNERS",
        RefNames.REFS_CONFIG,
        parentRepository1,
        createConfig(
            true, Optional.of(EXPECTED_LABEL), owners(), suffixMatcher(".sql", USER_A_EMAIL_COM)));
    expectConfig(
        "OWNERS",
        RefNames.REFS_CONFIG,
        parentRepository2,
        createConfig(
            true, Optional.of(A_LABEL), owners(), suffixMatcher(".java", USER_B_EMAIL_COM)));

    String sqlFileName = "file.sql";
    String javaFileName = "file.java";

    mockParentRepository(parentRepository1NameKey, parentRepository1);
    mockParentRepository(parentRepository2NameKey, parentRepository2);
    replayAll();

    PathOwners owners =
        new PathOwners(
            accounts,
            repositoryManager,
            repository,
            Arrays.asList(parentRepository1NameKey, parentRepository2NameKey),
            branch,
            Set.of(sqlFileName, javaFileName),
            EXPAND_GROUPS,
            "foo",
            CACHE_MOCK);

    Map<String, Set<Account.Id>> fileOwners = owners.getFileOwners();
    assertEquals(fileOwners.size(), 2);

    Set<Account.Id> ownersSet1 = fileOwners.get(sqlFileName);
    assertEquals(1, ownersSet1.size());
    assertTrue(ownersSet1.contains(USER_A_ID));

    Set<Account.Id> ownersSet2 = fileOwners.get(javaFileName);
    assertEquals(1, ownersSet2.size());
    assertTrue(ownersSet2.contains(USER_B_ID));

    // expect that closer parent (parentRepository1) overwrites the label definition
    assertThat(owners.getLabel().map(LabelDefinition::getName)).hasValue(EXPECTED_LABEL);
  }

  private void mockParentRepository(Project.NameKey repositoryName, Repository repository)
      throws IOException {
    expect(repositoryManager.openRepository(eq(repositoryName))).andReturn(repository).anyTimes();
    repository.close();
    expectLastCall();
  }

  @Test
  public void testClassicWithInheritanceAndDeepNesting() throws Exception {
    expectConfig("OWNERS", createConfig(true, owners(USER_C_EMAIL_COM)));
    expectConfig("dir/OWNERS", createConfig(true, Optional.of(A_LABEL), owners(USER_B_EMAIL_COM)));
    expectConfig(
        "dir/subdir/OWNERS",
        createConfig(true, Optional.of(EXPECTED_LABEL), owners(USER_A_EMAIL_COM)));

    replayAll();

    PathOwners owners =
        new PathOwners(
            accounts,
            repositoryManager,
            repository,
            emptyList(),
            branch,
            Set.of("dir/subdir/file.txt"),
            EXPAND_GROUPS,
            "foo",
            CACHE_MOCK);
    Set<Account.Id> ownersSet = owners.get().get("dir/subdir/OWNERS");

    assertEquals(3, ownersSet.size());
    assertTrue(ownersSet.contains(USER_A_ID));
    assertTrue(ownersSet.contains(USER_B_ID));
    assertTrue(ownersSet.contains(USER_C_ID));

    // expect that more specific configuration overwrites the label definition
    assertThat(owners.getLabel().map(LabelDefinition::getName)).hasValue(EXPECTED_LABEL);
  }

  @Test
  public void testParsingYamlWithLabelWithScore() throws IOException {
    String yamlString =
        "inherited: true\nlabel: " + EXPECTED_LABEL + ",1\nowners:\n- " + USER_C_EMAIL_COM;
    OwnersConfig ownersConfig = getOwnersConfig(yamlString);

    assertTrue(ownersConfig.isInherited());
    assertThat(ownersConfig.getLabel()).isPresent();

    LabelDefinition label = ownersConfig.getLabel().get();
    assertThat(label.getName()).isEqualTo(EXPECTED_LABEL);
    assertThat(label.getScore()).hasValue(1);

    Set<String> owners = ownersConfig.getOwners();
    assertEquals(1, owners.size());
    assertTrue(owners.contains(USER_C_EMAIL_COM));
  }

  @Test
  public void testParsingYamlWithLabelWithoutScore() throws IOException {
    String yamlString =
        "inherited: true\nlabel: " + EXPECTED_LABEL + "\nowners:\n- " + USER_C_EMAIL_COM;
    OwnersConfig ownersConfig = getOwnersConfig(yamlString);

    assertTrue(ownersConfig.isInherited());
    assertThat(ownersConfig.getLabel()).isPresent();

    LabelDefinition label = ownersConfig.getLabel().get();
    assertThat(label.getName()).isEqualTo(EXPECTED_LABEL);
    assertThat(label.getScore()).isEmpty();

    Set<String> owners = ownersConfig.getOwners();
    assertEquals(1, owners.size());
    assertTrue(owners.contains(USER_C_EMAIL_COM));
  }

  @Test
  public void testPathOwnersEntriesCacheIsCalled() throws Exception {
    expectConfig("OWNERS", "master", createConfig(true, Optional.of(EXPECTED_LABEL), owners()));
    expectConfig(
        "OWNERS",
        RefNames.REFS_CONFIG,
        repository,
        createConfig(true, Optional.of("foo"), owners()));
    expectConfig("dir/OWNERS", createConfig(true, Optional.of(A_LABEL), owners(USER_B_EMAIL_COM)));
    expectConfig(
        "dir/subdir/OWNERS",
        createConfig(true, Optional.of(EXPECTED_LABEL), owners(USER_A_EMAIL_COM)));
    expectConfig(
        "OWNERS",
        RefNames.REFS_CONFIG,
        parentRepository1,
        createConfig(true, Optional.of("bar"), owners()));

    mockParentRepository(parentRepository1NameKey, parentRepository1);
    replayAll();

    PathOwnersEntriesCacheMock cacheMock = new PathOwnersEntriesCacheMock();
    PathOwners owners =
        new PathOwners(
            accounts,
            repositoryManager,
            repository,
            Arrays.asList(parentRepository1NameKey),
            branch,
            Set.of("dir/subdir/file.txt"),
            EXPAND_GROUPS,
            "foo",
            cacheMock);

    assertThat(owners.getFileOwners()).isNotEmpty();
    int expectedCacheCalls =
        1 /* for refs/meta/config/OWNERS */
            + 3 /* for each parent directory of 'file.txt' */
            + 1 /* for parent's refs/meta/config/OWNERS */;
    assertThat(cacheMock.hit).isEqualTo(expectedCacheCalls);
  }

  private void mockOwners(String... owners) throws IOException {
    expectNoConfig("OWNERS");
    expectConfig(CLASSIC_OWNERS, createConfig(false, owners(owners)));

    replayAll();
  }
}
