// 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.backend;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;

import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.plugins.codeowners.acceptance.AbstractCodeOwnersTest;
import com.google.gerrit.plugins.codeowners.acceptance.testsuite.CodeOwnerConfigOperations;
import com.google.gerrit.plugins.codeowners.acceptance.testsuite.TestPathExpressions;
import com.google.gerrit.plugins.codeowners.backend.config.InvalidPluginConfigurationException;
import com.google.inject.Inject;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.function.Consumer;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.mockito.quality.Strictness;

/** Tests for {@link CodeOwnerConfigHierarchy}. */
public class CodeOwnerConfigHierarchyTest extends AbstractCodeOwnersTest {
  @Rule public final MockitoRule mockito = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);

  @Mock private CodeOwnerConfigVisitor visitor;
  @Mock private Consumer<CodeOwnerConfig.Key> parentCodeOwnersIgnoredCallback;

  @Inject private ProjectOperations projectOperations;

  private CodeOwnerConfigOperations codeOwnerConfigOperations;
  private CodeOwnerConfigHierarchy codeOwnerConfigHierarchy;
  private TestPathExpressions testPathExpressions;

  @Before
  public void setUpCodeOwnersPlugin() throws Exception {
    codeOwnerConfigOperations =
        plugin.getSysInjector().getInstance(CodeOwnerConfigOperations.class);
    codeOwnerConfigHierarchy = plugin.getSysInjector().getInstance(CodeOwnerConfigHierarchy.class);
    testPathExpressions = plugin.getSysInjector().getInstance(TestPathExpressions.class);
  }

  @Test
  public void cannotVisitCodeOwnerConfigsForNullBranch() throws Exception {
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                codeOwnerConfigHierarchy.visit(
                    /* branchNameKey= */ null,
                    getCurrentRevision(BranchNameKey.create(project, "master")),
                    Paths.get("/foo/bar/baz.md"),
                    visitor));
    assertThat(npe).hasMessageThat().isEqualTo("branch");
  }

  @Test
  public void cannotVisitCodeOwnerConfigsForNullRevision() throws Exception {
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                codeOwnerConfigHierarchy.visit(
                    BranchNameKey.create(project, "master"),
                    /* revision= */ null,
                    Paths.get("/foo/bar/baz.md"),
                    visitor));
    assertThat(npe).hasMessageThat().isEqualTo("revision");
  }

  @Test
  public void cannotVisitCodeOwnerConfigsForNullPath() throws Exception {
    BranchNameKey branchNameKey = BranchNameKey.create(project, "master");
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                codeOwnerConfigHierarchy.visit(
                    branchNameKey,
                    getCurrentRevision(branchNameKey),
                    /* absolutePath= */ null,
                    visitor));
    assertThat(npe).hasMessageThat().isEqualTo("absolutePath");
  }

  @Test
  public void cannotVisitCodeOwnerConfigsForRelativePath() throws Exception {
    BranchNameKey branchNameKey = BranchNameKey.create(project, "master");
    String relativePath = "foo/bar/baz.md";
    IllegalStateException exception =
        assertThrows(
            IllegalStateException.class,
            () ->
                codeOwnerConfigHierarchy.visit(
                    branchNameKey,
                    getCurrentRevision(branchNameKey),
                    Paths.get(relativePath),
                    visitor));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(String.format("path %s must be absolute", relativePath));
  }

  @Test
  public void cannotVisitCodeOwnerConfigsWithNullVisitor() throws Exception {
    BranchNameKey branchNameKey = BranchNameKey.create(project, "master");
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                codeOwnerConfigHierarchy.visit(
                    branchNameKey,
                    getCurrentRevision(branchNameKey),
                    Paths.get("/foo/bar/baz.md"),
                    /* codeOwnerConfigVisitor= */ null));
    assertThat(npe).hasMessageThat().isEqualTo("codeOwnerConfigVisitor");
  }

  @Test
  public void cannotVisitCodeOwnerConfigsWithNullCallback() throws Exception {
    BranchNameKey branchNameKey = BranchNameKey.create(project, "master");
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                codeOwnerConfigHierarchy.visit(
                    branchNameKey,
                    getCurrentRevision(branchNameKey),
                    Paths.get("/foo/bar/baz.md"),
                    visitor,
                    /* parentCodeOwnersIgnoredCallback= */ null));
    assertThat(npe).hasMessageThat().isEqualTo("parentCodeOwnersIgnoredCallback");
  }

  @Test
  public void visitorNotInvokedIfNoCodeOwnerConfigExists() throws Exception {
    visit("master", "/foo/bar/baz.md");
    verifyZeroInteractions(visitor);
  }

  @Test
  public void visitorNotInvokedForNonApplyingCodeOwnerConfig() throws Exception {
    String branch = "master";

    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch(branch)
        .folderPath("/other/")
        .addCodeOwnerEmail(admin.email())
        .create();

    visit(branch, "/foo/bar/baz.md");
    verifyZeroInteractions(visitor);
  }

  @Test
  public void visitorInvokedForApplyingCodeOwnerConfigs() throws Exception {
    String branch = "master";

    CodeOwnerConfig.Key rootCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch(branch)
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .create();

    CodeOwnerConfig.Key fooCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch(branch)
            .folderPath("/foo/")
            .addCodeOwnerEmail(admin.email())
            .create();

    CodeOwnerConfig.Key fooBarCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch(branch)
            .folderPath("/foo/bar/")
            .addCodeOwnerEmail(admin.email())
            .create();

    when(visitor.visit(any(CodeOwnerConfig.class))).thenReturn(true);
    visit(branch, "/foo/bar/baz.md");

    // Verify that we received the callbacks in the right order, starting from the folder of the
    // given path up to the root folder.
    InOrder orderVerifier = Mockito.inOrder(visitor);
    orderVerifier
        .verify(visitor)
        .visit(codeOwnerConfigOperations.codeOwnerConfig(fooBarCodeOwnerConfigKey).get());
    orderVerifier
        .verify(visitor)
        .visit(codeOwnerConfigOperations.codeOwnerConfig(fooCodeOwnerConfigKey).get());
    orderVerifier
        .verify(visitor)
        .visit(codeOwnerConfigOperations.codeOwnerConfig(rootCodeOwnerConfigKey).get());
    verifyNoMoreInteractions(visitor);
  }

  @Test
  public void visitorIsNotInvokedForFolderThatHasNoCodeOwnerConfig() throws Exception {
    String branch = "master";

    CodeOwnerConfig.Key rootCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch(branch)
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .create();

    CodeOwnerConfig.Key fooBarCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch(branch)
            .folderPath("/foo/bar/")
            .addCodeOwnerEmail(admin.email())
            .create();

    when(visitor.visit(any(CodeOwnerConfig.class))).thenReturn(true);
    visit(branch, "/foo/bar/baz.md");

    // Verify that we received the callbacks in the right order, starting from the folder of the
    // given path up to the root folder. There is no callback for the '/foo/' folder as this folder
    // doesn't contain a code owner config file.
    InOrder orderVerifier = Mockito.inOrder(visitor);
    orderVerifier
        .verify(visitor)
        .visit(codeOwnerConfigOperations.codeOwnerConfig(fooBarCodeOwnerConfigKey).get());
    orderVerifier
        .verify(visitor)
        .visit(codeOwnerConfigOperations.codeOwnerConfig(rootCodeOwnerConfigKey).get());
    verifyNoMoreInteractions(visitor);
  }

  @Test
  public void visitorInvokedWithCodeOwnerConfigsFromOldRevision() throws Exception {
    String branch = "master";

    CodeOwnerConfig.Key rootCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch(branch)
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .create();

    CodeOwnerConfig.Key fooCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch(branch)
            .folderPath("/foo/")
            .addCodeOwnerEmail(admin.email())
            .create();

    RevCommit revision1 = projectOperations.project(project).getHead(branch);
    CodeOwnerConfig expectedRootCodeOwnerConfig =
        codeOwnerConfigOperations.codeOwnerConfig(rootCodeOwnerConfigKey).get();
    CodeOwnerConfig expectedFooCodeOwnerConfig =
        codeOwnerConfigOperations.codeOwnerConfig(fooCodeOwnerConfigKey).get();

    // Update one code owner config.
    codeOwnerConfigOperations
        .codeOwnerConfig(fooCodeOwnerConfigKey)
        .forUpdate()
        .ignoreParentCodeOwners()
        .update();

    // Create a new code owner config.
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch(branch)
        .folderPath("/foo/bar/")
        .addCodeOwnerEmail(admin.email())
        .create();

    RevCommit revision2 = projectOperations.project(project).getHead(branch);
    assertThat(revision1).isNotEqualTo(revision2);

    when(visitor.visit(any(CodeOwnerConfig.class))).thenReturn(true);
    codeOwnerConfigHierarchy.visit(
        BranchNameKey.create(project, branch), revision1, Paths.get("/foo/bar/baz.md"), visitor);

    // Verify that we received the callbacks for the code owner configs from the old revison, in
    // the right order, starting from the folder of the given path up to the root folder.
    InOrder orderVerifier = Mockito.inOrder(visitor);
    orderVerifier.verify(visitor).visit(expectedFooCodeOwnerConfig);
    orderVerifier.verify(visitor).visit(expectedRootCodeOwnerConfig);
    verifyNoMoreInteractions(visitor);
  }

  @Test
  public void visitorCanStopTheIterationOverCodeOwnerConfigsByReturningFalse() throws Exception {
    String branch = "master";

    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch(branch)
        .folderPath("/")
        .addCodeOwnerEmail(admin.email())
        .create();

    CodeOwnerConfig.Key fooCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch(branch)
            .folderPath("/foo/")
            .addCodeOwnerEmail(admin.email())
            .create();

    CodeOwnerConfig.Key fooBarCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch(branch)
            .folderPath("/foo/bar/")
            .addCodeOwnerEmail(admin.email())
            .create();

    // Return true for the first time the visitor is invoked, and false for all further invocations.
    when(visitor.visit(any(CodeOwnerConfig.class))).thenReturn(true).thenReturn(false);
    visit(branch, "/foo/bar/baz.md");

    // Verify that we received the callbacks in the right order, starting from the folder of the
    // given path up to the root folder. We expect only 2 callbacks, since the visitor returns false
    // for the second invocation.
    InOrder orderVerifier = Mockito.inOrder(visitor);
    orderVerifier
        .verify(visitor)
        .visit(codeOwnerConfigOperations.codeOwnerConfig(fooBarCodeOwnerConfigKey).get());
    orderVerifier
        .verify(visitor)
        .visit(codeOwnerConfigOperations.codeOwnerConfig(fooCodeOwnerConfigKey).get());
    verifyNoMoreInteractions(visitor);
  }

  @Test
  public void visitorIsNotInvokedForParentCodeOwnerConfigsIfParentCodeOwnersAreIgnored()
      throws Exception {
    String branch = "master";

    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch(branch)
        .folderPath("/")
        .addCodeOwnerEmail(admin.email())
        .create();

    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch(branch)
        .folderPath("/foo/")
        .addCodeOwnerEmail(admin.email())
        .create();

    CodeOwnerConfig.Key fooBarCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch(branch)
            .folderPath("/foo/bar/")
            .ignoreParentCodeOwners()
            .addCodeOwnerEmail(admin.email())
            .create();

    CodeOwnerConfig.Key fooBarBazCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch(branch)
            .folderPath("/foo/bar/baz")
            .addCodeOwnerEmail(admin.email())
            .create();

    when(visitor.visit(any(CodeOwnerConfig.class))).thenReturn(true);
    visit(branch, "/foo/bar/baz/README.md");

    // Verify that we received the callbacks in the right order, starting from the folder of the
    // given path up to the root folder. There is no callback for the '/' and '/foo/' folders since
    // the code owner config for the '/foo/bar/' folder defines that parent code owners should be
    // ignored.
    InOrder orderVerifier = Mockito.inOrder(visitor);
    orderVerifier
        .verify(visitor)
        .visit(codeOwnerConfigOperations.codeOwnerConfig(fooBarBazCodeOwnerConfigKey).get());
    orderVerifier
        .verify(visitor)
        .visit(codeOwnerConfigOperations.codeOwnerConfig(fooBarCodeOwnerConfigKey).get());
    verifyNoMoreInteractions(visitor);

    verify(parentCodeOwnersIgnoredCallback).accept(fooBarCodeOwnerConfigKey);
    verifyNoMoreInteractions(parentCodeOwnersIgnoredCallback);
  }

  @Test
  public void
      visitorIsNotInvokedForParentCodeOwnerConfigsIfAMatchingCodeOwnerSetIgnoresParentCodeOwners()
          throws Exception {
    String branch = "master";

    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch(branch)
        .folderPath("/")
        .addCodeOwnerEmail(admin.email())
        .create();

    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch(branch)
        .folderPath("/foo/")
        .addCodeOwnerEmail(admin.email())
        .create();

    CodeOwnerConfig.Key fooBarCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch(branch)
            .folderPath("/foo/bar/")
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .setIgnoreGlobalAndParentCodeOwners()
                    .addPathExpression(testPathExpressions.matchAllFilesInSubfolder("baz"))
                    .addCodeOwnerEmail(admin.email())
                    .build())
            .create();

    CodeOwnerConfig.Key fooBarBazCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch(branch)
            .folderPath("/foo/bar/baz")
            .addCodeOwnerEmail(admin.email())
            .create();

    when(visitor.visit(any(CodeOwnerConfig.class))).thenReturn(true);
    visit(branch, "/foo/bar/baz/README.md");

    // Verify that we received the callbacks in the right order, starting from the folder of the
    // given path up to the root folder. There is no callback for the '/' and '/foo/' folders since
    // the code owner config for the '/foo/bar/' folder contains a matching code owner set that
    // defines that parent code owners should be
    // ignored.
    InOrder orderVerifier = Mockito.inOrder(visitor);
    orderVerifier
        .verify(visitor)
        .visit(codeOwnerConfigOperations.codeOwnerConfig(fooBarBazCodeOwnerConfigKey).get());
    orderVerifier
        .verify(visitor)
        .visit(codeOwnerConfigOperations.codeOwnerConfig(fooBarCodeOwnerConfigKey).get());
    verifyNoMoreInteractions(visitor);

    verify(parentCodeOwnersIgnoredCallback).accept(fooBarCodeOwnerConfigKey);
    verifyNoMoreInteractions(parentCodeOwnersIgnoredCallback);
  }

  @Test
  public void
      visitorIsInvokedForParentCodeOwnerConfigsIfANonMatchingCodeOwnerSetIgnoresParentCodeOwners()
          throws Exception {
    String branch = "master";

    CodeOwnerConfig.Key rootCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch(branch)
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .create();

    CodeOwnerConfig.Key fooCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch(branch)
            .folderPath("/foo/")
            .addCodeOwnerEmail(admin.email())
            .create();

    CodeOwnerConfig.Key fooBarCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch(branch)
            .folderPath("/foo/bar/")
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .setIgnoreGlobalAndParentCodeOwners()
                    .addPathExpression(testPathExpressions.matchFileTypeInCurrentFolder("txt"))
                    .addCodeOwnerEmail(admin.email())
                    .build())
            .create();

    when(visitor.visit(any(CodeOwnerConfig.class))).thenReturn(true);
    visit(branch, "/foo/bar/baz.md");

    // Verify that we received the callbacks in the right order, starting from the folder of the
    // given path up to the root folder.
    InOrder orderVerifier = Mockito.inOrder(visitor);
    orderVerifier
        .verify(visitor)
        .visit(codeOwnerConfigOperations.codeOwnerConfig(fooBarCodeOwnerConfigKey).get());
    orderVerifier
        .verify(visitor)
        .visit(codeOwnerConfigOperations.codeOwnerConfig(fooCodeOwnerConfigKey).get());
    orderVerifier
        .verify(visitor)
        .visit(codeOwnerConfigOperations.codeOwnerConfig(rootCodeOwnerConfigKey).get());
    verifyNoMoreInteractions(visitor);

    verifyZeroInteractions(parentCodeOwnersIgnoredCallback);
  }

  @Test
  public void visitorInvokedForCodeOwnerConfigInRefsMetaConfig() throws Exception {
    CodeOwnerConfig.Key metaCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch(RefNames.REFS_CONFIG)
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .create();

    when(visitor.visit(any(CodeOwnerConfig.class))).thenReturn(true);
    visit("master", "/foo/bar/baz.md");
    verify(visitor).visit(codeOwnerConfigOperations.codeOwnerConfig(metaCodeOwnerConfigKey).get());
    verifyNoMoreInteractions(visitor);
  }

  @Test
  public void visitorNotInvokedForCodeOwnerConfigInRefsMetaConfigIfItDoesntApply()
      throws Exception {
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch(RefNames.REFS_CONFIG)
        .folderPath("/")
        .addCodeOwnerSet(
            CodeOwnerSet.builder()
                .addPathExpression(testPathExpressions.matchAllFilesInSubfolder("other"))
                .addCodeOwnerEmail(admin.email())
                .build())
        .create();

    when(visitor.visit(any(CodeOwnerConfig.class))).thenReturn(true);
    visit("master", "/foo/bar/baz.md");
    verifyZeroInteractions(visitor);
  }

  @Test
  public void visitorInvokedForCodeOwnerConfigInRefsMetaConfigWithMatchingPathExpression()
      throws Exception {
    CodeOwnerConfig.Key metaCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch(RefNames.REFS_CONFIG)
            .folderPath("/")
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression(testPathExpressions.matchAllFilesInSubfolder("foo"))
                    .addCodeOwnerEmail(admin.email())
                    .build())
            .create();

    when(visitor.visit(any(CodeOwnerConfig.class))).thenReturn(true);
    visit("master", "/foo/bar/baz.md");
    verify(visitor).visit(codeOwnerConfigOperations.codeOwnerConfig(metaCodeOwnerConfigKey).get());
    verifyNoMoreInteractions(visitor);
  }

  @Test
  public void visitorForCodeOwnerConfigInRefsMetaConfigInvokedLast() throws Exception {
    CodeOwnerConfig.Key metaCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch(RefNames.REFS_CONFIG)
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .create();

    CodeOwnerConfig.Key rootCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression(testPathExpressions.matchAllFilesInSubfolder("other"))
                    .addCodeOwnerEmail(admin.email())
                    .build())
            .create();

    when(visitor.visit(any(CodeOwnerConfig.class))).thenReturn(true);
    visit("master", "/foo/bar/baz.md");

    InOrder orderVerifier = Mockito.inOrder(visitor);
    orderVerifier
        .verify(visitor)
        .visit(codeOwnerConfigOperations.codeOwnerConfig(rootCodeOwnerConfigKey).get());
    orderVerifier
        .verify(visitor)
        .visit(codeOwnerConfigOperations.codeOwnerConfig(metaCodeOwnerConfigKey).get());
    verifyNoMoreInteractions(visitor);
  }

  @Test
  public void
      visitorNotInvokedForCodeOwnerConfigInRefsMetaConfigIfRootCodeOwnerConfigIgnoresParent()
          throws Exception {
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch(RefNames.REFS_CONFIG)
        .folderPath("/")
        .addCodeOwnerEmail(admin.email())
        .create();

    CodeOwnerConfig.Key rootCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .ignoreParentCodeOwners()
            .addCodeOwnerEmail(admin.email())
            .create();

    when(visitor.visit(any(CodeOwnerConfig.class))).thenReturn(true);
    visit("master", "/foo/bar/baz.md");
    verify(visitor).visit(codeOwnerConfigOperations.codeOwnerConfig(rootCodeOwnerConfigKey).get());
    verifyNoMoreInteractions(visitor);

    verify(parentCodeOwnersIgnoredCallback).accept(rootCodeOwnerConfigKey);
    verifyNoMoreInteractions(parentCodeOwnersIgnoredCallback);
  }

  @Test
  public void visitorCanStopTheIterationAtRoot() throws Exception {
    codeOwnerConfigOperations
        .newCodeOwnerConfig()
        .project(project)
        .branch(RefNames.REFS_CONFIG)
        .folderPath("/")
        .addCodeOwnerEmail(admin.email())
        .create();

    CodeOwnerConfig.Key rootCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .ignoreParentCodeOwners()
            .addCodeOwnerEmail(admin.email())
            .create();

    when(visitor.visit(any(CodeOwnerConfig.class))).thenReturn(false);
    visit("master", "/foo/bar/baz.md");
    verify(visitor).visit(codeOwnerConfigOperations.codeOwnerConfig(rootCodeOwnerConfigKey).get());
    verifyNoMoreInteractions(visitor);
  }

  @Test
  public void
      visitorIsOnlyInvokedOnceForDefaultCodeOnwerConfigFileIfConfigsInRefsMetaConxfigAreIterated()
          throws Exception {
    CodeOwnerConfig.Key metaCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch(RefNames.REFS_CONFIG)
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .create();

    when(visitor.visit(any(CodeOwnerConfig.class))).thenReturn(true);
    visit(RefNames.REFS_CONFIG, "/foo/bar/baz.md");

    // Verify that we received the callback for the code owner config only once.
    verify(visitor).visit(codeOwnerConfigOperations.codeOwnerConfig(metaCodeOwnerConfigKey).get());

    verifyNoMoreInteractions(visitor);
  }

  private void visit(String branchName, String path)
      throws InvalidPluginConfigurationException, IOException {
    BranchNameKey branchNameKey = BranchNameKey.create(project, branchName);
    codeOwnerConfigHierarchy.visit(
        branchNameKey,
        getCurrentRevision(branchNameKey),
        Paths.get(path),
        visitor,
        parentCodeOwnersIgnoredCallback);
  }

  private ObjectId getCurrentRevision(BranchNameKey branchNameKey) throws IOException {
    try (Repository repository = repoManager.openRepository(branchNameKey.project());
        RevWalk rw = new RevWalk(repository)) {
      Ref ref = repository.exactRef(branchNameKey.branch());
      checkNotNull(
          ref,
          "branch %s in repository %s not found",
          branchNameKey.branch(),
          branchNameKey.project().get());
      return rw.parseCommit(ref.getObjectId());
    }
  }
}
