// 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.truth.Truth.assertThat;
import static com.google.gerrit.plugins.codeowners.testing.CodeOwnerSetSubject.hasEmail;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.config.GerritConfig;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.Project.NameKey;
import com.google.gerrit.extensions.api.projects.ConfigInput;
import com.google.gerrit.extensions.client.ProjectState;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.registration.PrivateInternals_DynamicMapImpl;
import com.google.gerrit.extensions.registration.RegistrationHandle;
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.server.IdentifiedUser;
import com.google.inject.Inject;
import com.google.inject.Key;
import com.google.inject.Provider;
import com.google.inject.util.Providers;
import java.nio.file.Path;
import java.util.Optional;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Before;
import org.junit.Test;

/** Tests for {@link PathCodeOwners}. */
public class PathCodeOwnersTest extends AbstractCodeOwnersTest {
  @Inject private ProjectOperations projectOperations;

  private CodeOwnerConfigOperations codeOwnerConfigOperations;
  private PathCodeOwners.Factory pathCodeOwnersFactory;
  private DynamicMap<CodeOwnerBackend> codeOwnerBackends;
  private Provider<TransientCodeOwnerConfigCache> transientCodeOwnerConfigCacheProvider;
  private TestPathExpressions testPathExpressions;

  @Before
  public void setUpCodeOwnersPlugin() throws Exception {
    codeOwnerConfigOperations =
        plugin.getSysInjector().getInstance(CodeOwnerConfigOperations.class);
    pathCodeOwnersFactory = plugin.getSysInjector().getInstance(PathCodeOwners.Factory.class);
    codeOwnerBackends =
        plugin.getSysInjector().getInstance(new Key<DynamicMap<CodeOwnerBackend>>() {});
    transientCodeOwnerConfigCacheProvider =
        plugin.getSysInjector().getInstance(new Key<Provider<TransientCodeOwnerConfigCache>>() {});
    testPathExpressions = plugin.getSysInjector().getInstance(TestPathExpressions.class);
  }

  @Test
  public void createPathCodeOwnersForCodeOwnerConfig() throws Exception {
    PathCodeOwners pathCodeOwners =
        pathCodeOwnersFactory.createWithoutCache(
            createCodeOwnerBuilder().build(), Path.of("/foo/bar/baz.md"));
    assertThat(pathCodeOwners).isNotNull();
  }

  @Test
  public void cannotCreatePathCodeOwnersForNullCodeOwnerConfig() throws Exception {
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                pathCodeOwnersFactory.createWithoutCache(
                    /* codeOwnerConfig= */ null, Path.of("/foo/bar/baz.md")));
    assertThat(npe).hasMessageThat().isEqualTo("codeOwnerConfig");
  }

  @Test
  public void cannotCreatePathCodeOwnersForCodeOwnerConfigWithNullPath() throws Exception {
    CodeOwnerConfig codeOwnerConfig = createCodeOwnerBuilder().build();
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                pathCodeOwnersFactory.createWithoutCache(
                    codeOwnerConfig, /* absolutePath= */ null));
    assertThat(npe).hasMessageThat().isEqualTo("path");
  }

  @Test
  public void cannotCreatePathCodeOwnersForCodeOwnerConfigWithRelativePath() throws Exception {
    String relativePath = "foo/bar/baz.md";
    CodeOwnerConfig codeOwnerConfig = createCodeOwnerBuilder().build();
    IllegalStateException exception =
        assertThrows(
            IllegalStateException.class,
            () -> pathCodeOwnersFactory.createWithoutCache(codeOwnerConfig, Path.of(relativePath)));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(String.format("path %s must be absolute", relativePath));
  }

  @Test
  public void createPathCodeOwnersForCodeOwnerConfigKey() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            codeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo/bar/baz.md"));
    assertThat(pathCodeOwners).isPresent();
  }

  @Test
  public void cannotCreatePathCodeOwnersForNullCache() throws Exception {
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                pathCodeOwnersFactory.create(
                    /* transientCodeOwnerConfigCache= */ null,
                    CodeOwnerConfig.Key.create(
                        BranchNameKey.create(project, "master"), Path.of("/")),
                    projectOperations.project(project).getHead("master"),
                    Path.of("/foo/bar/baz.md")));
    assertThat(npe).hasMessageThat().isEqualTo("transientCodeOwnerConfigCache");
  }

  @Test
  public void cannotCreatePathCodeOwnersForNullCodeOwnerConfigKey() throws Exception {
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                pathCodeOwnersFactory.create(
                    transientCodeOwnerConfigCacheProvider.get(),
                    /* codeOwnerConfigKey= */ null,
                    projectOperations.project(project).getHead("master"),
                    Path.of("/foo/bar/baz.md")));
    assertThat(npe).hasMessageThat().isEqualTo("codeOwnerConfigKey");
  }

  @Test
  public void cannotCreatePathCodeOwnersForNullRevision() throws Exception {
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                pathCodeOwnersFactory.create(
                    transientCodeOwnerConfigCacheProvider.get(),
                    CodeOwnerConfig.Key.create(
                        BranchNameKey.create(project, "master"), Path.of("/")),
                    /* revision= */ null,
                    Path.of("/foo/bar/baz.md")));
    assertThat(npe).hasMessageThat().isEqualTo("revision");
  }

  @Test
  public void cannotCreatePathCodeOwnersForCodeOwnerConfigKeyWithNullPath() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .create();

    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                pathCodeOwnersFactory.create(
                    transientCodeOwnerConfigCacheProvider.get(),
                    codeOwnerConfigKey,
                    projectOperations.project(project).getHead("master"),
                    /* absolutePath= */ null));
    assertThat(npe).hasMessageThat().isEqualTo("path");
  }

  @Test
  public void cannotCreatePathForCodeOwnerConfigKeyWithRelativePath() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .create();

    String relativePath = "foo/bar/baz.md";
    IllegalStateException exception =
        assertThrows(
            IllegalStateException.class,
            () ->
                pathCodeOwnersFactory.create(
                    transientCodeOwnerConfigCacheProvider.get(),
                    codeOwnerConfigKey,
                    projectOperations.project(project).getHead("master"),
                    Path.of(relativePath)));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(String.format("path %s must be absolute", relativePath));
  }

  @Test
  public void getEmptyPathCodeOwners() throws Exception {
    CodeOwnerConfig emptyCodeOwnerConfig = createCodeOwnerBuilder().build();
    PathCodeOwners pathCodeOwners =
        pathCodeOwnersFactory.createWithoutCache(emptyCodeOwnerConfig, Path.of("/foo/bar/baz.md"));
    assertThat(pathCodeOwners.resolveCodeOwnerConfig().get().getPathCodeOwners()).isEmpty();
    assertThat(pathCodeOwners.resolveCodeOwnerConfig().get().resolvedImports()).isEmpty();
    assertThat(pathCodeOwners.resolveCodeOwnerConfig().get().unresolvedImports()).isEmpty();
  }

  @Test
  public void getPathCodeOwnersIfNoPathExpressionsAreUsed() throws Exception {
    CodeOwnerConfig codeOwnerConfig =
        createCodeOwnerBuilder()
            .addCodeOwnerSet(CodeOwnerSet.createWithoutPathExpressions(admin.email(), user.email()))
            .build();
    PathCodeOwners pathCodeOwners =
        pathCodeOwnersFactory.createWithoutCache(codeOwnerConfig, Path.of("/foo/bar/baz.md"));
    assertThat(pathCodeOwners.resolveCodeOwnerConfig().get().getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email(), user.email());
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.backend", value = TestCodeOwnerBackend.ID)
  public void getPathCodeOwnersReturnsCodeOwnersFromMatchingCodeOwnerSets() throws Exception {
    PathExpressionMatcher pathExpressionMatcher = mock(PathExpressionMatcher.class);

    // Create a matching code owner set.
    CodeOwnerSet matchingCodeOwnerSet1 =
        CodeOwnerSet.builder().addPathExpression("*.md").addCodeOwnerEmail(admin.email()).build();
    when(pathExpressionMatcher.matches(eq("*.md"), any(Path.class))).thenReturn(true);

    // Create another matching code owner set.
    CodeOwnerSet matchingCodeOwnerSet2 =
        CodeOwnerSet.builder().addPathExpression("baz.*").addCodeOwnerEmail(user.email()).build();
    when(pathExpressionMatcher.matches(eq("baz.*"), any(Path.class))).thenReturn(true);

    // Create a non-matching code owner set.
    CodeOwnerSet nonMatchingCodeOwnerSet =
        CodeOwnerSet.builder()
            .addPathExpression("*.txt")
            .addCodeOwnerEmail("foo@example.com")
            .addCodeOwnerEmail("bar@example.com")
            .build();
    when(pathExpressionMatcher.matches(eq("*.txt"), any(Path.class))).thenReturn(false);

    try (AutoCloseable registration = registerTestBackend(pathExpressionMatcher)) {
      CodeOwnerConfig codeOwnerConfig =
          createCodeOwnerBuilder()
              .addCodeOwnerSet(matchingCodeOwnerSet1)
              .addCodeOwnerSet(matchingCodeOwnerSet2)
              .addCodeOwnerSet(nonMatchingCodeOwnerSet)
              .build();
      PathCodeOwners pathCodeOwners =
          pathCodeOwnersFactory.createWithoutCache(codeOwnerConfig, Path.of("/foo/bar/baz.md"));
      assertThat(pathCodeOwners.resolveCodeOwnerConfig().get().getPathCodeOwners())
          .comparingElementsUsing(hasEmail())
          .containsExactly(admin.email(), user.email());
    }
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.backend", value = TestCodeOwnerBackend.ID)
  public void codeOwnerSetsWithPathExpressionsAreIgnoredIfBackendDoesntSupportPathExpressions()
      throws Exception {
    try (AutoCloseable registration = registerTestBackend(/* pathExpressionMatcher= */ null)) {
      CodeOwnerConfig codeOwnerConfig =
          createCodeOwnerBuilder()
              .addCodeOwnerSet(
                  CodeOwnerSet.builder()
                      .addPathExpression("*.md")
                      .addCodeOwnerEmail(admin.email())
                      .build())
              .build();
      PathCodeOwners pathCodeOwners =
          pathCodeOwnersFactory.createWithoutCache(codeOwnerConfig, Path.of("/foo/bar/baz.md"));
      assertThat(pathCodeOwners.resolveCodeOwnerConfig().get().getPathCodeOwners()).isEmpty();
    }
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.backend", value = TestCodeOwnerBackend.ID)
  public void
      getPathCodeOwnersOmitsGlobalCodeOwnersIfMatchingPerFileCodeOwnerSetIgnoresParentCodeOwners()
          throws Exception {
    PathExpressionMatcher pathExpressionMatcher = mock(PathExpressionMatcher.class);

    // Create a matching per file code owner set that ignores parent code owners.
    CodeOwnerSet perFileCodeOwnerSet =
        CodeOwnerSet.builder()
            .setIgnoreGlobalAndParentCodeOwners()
            .addPathExpression("*.md")
            .addCodeOwnerEmail(admin.email())
            .build();
    when(pathExpressionMatcher.matches(eq("*.md"), any(Path.class))).thenReturn(true);

    // Create a global code owner set.
    CodeOwnerSet globalCodeOwnerSet =
        CodeOwnerSet.builder().addCodeOwnerEmail(user.email()).build();

    try (AutoCloseable registration = registerTestBackend(pathExpressionMatcher)) {
      CodeOwnerConfig codeOwnerConfig =
          createCodeOwnerBuilder()
              .addCodeOwnerSet(perFileCodeOwnerSet)
              .addCodeOwnerSet(globalCodeOwnerSet)
              .build();
      PathCodeOwners pathCodeOwners =
          pathCodeOwnersFactory.createWithoutCache(codeOwnerConfig, Path.of("/foo/bar/baz.md"));
      assertThat(pathCodeOwners.resolveCodeOwnerConfig().get().getPathCodeOwners())
          .comparingElementsUsing(hasEmail())
          .containsExactly(admin.email());
    }
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.backend", value = TestCodeOwnerBackend.ID)
  public void
      getPathCodeOwnersIncludesGlobalCodeOwnersIfMatchingPerFileCodeOwnerSetDoesNotIgnoreParentCodeOwners()
          throws Exception {
    PathExpressionMatcher pathExpressionMatcher = mock(PathExpressionMatcher.class);

    // Create a matching per file code owner set that doesn't ignore parent code owners.
    CodeOwnerSet perFileCodeOwnerSet =
        CodeOwnerSet.builder()
            .setIgnoreGlobalAndParentCodeOwners(false)
            .addPathExpression("*.md")
            .addCodeOwnerEmail(admin.email())
            .build();
    when(pathExpressionMatcher.matches(eq("*.md"), any(Path.class))).thenReturn(true);

    // Create a global code owner set.
    CodeOwnerSet globalCodeOwnerSet =
        CodeOwnerSet.builder().addCodeOwnerEmail(user.email()).build();

    try (AutoCloseable registration = registerTestBackend(pathExpressionMatcher)) {
      CodeOwnerConfig codeOwnerConfig =
          createCodeOwnerBuilder()
              .addCodeOwnerSet(perFileCodeOwnerSet)
              .addCodeOwnerSet(globalCodeOwnerSet)
              .build();
      PathCodeOwners pathCodeOwners =
          pathCodeOwnersFactory.createWithoutCache(codeOwnerConfig, Path.of("/foo/bar/baz.md"));
      assertThat(pathCodeOwners.resolveCodeOwnerConfig().get().getPathCodeOwners())
          .comparingElementsUsing(hasEmail())
          .containsExactly(admin.email(), user.email());
    }
  }

  @Test
  @GerritConfig(name = "plugin.code-owners.backend", value = TestCodeOwnerBackend.ID)
  public void
      getPathCodeOwnersIncludesCodeOwnersFromAllMatchingPerFileCodeOwnerSetsIfOneIgnoresParentCodeOwners()
          throws Exception {
    PathExpressionMatcher pathExpressionMatcher = mock(PathExpressionMatcher.class);

    // Create a matching per file code owner set that ignores parent code owners.
    CodeOwnerSet perFileCodeOwnerSet1 =
        CodeOwnerSet.builder()
            .setIgnoreGlobalAndParentCodeOwners()
            .addPathExpression("*.md")
            .addCodeOwnerEmail(admin.email())
            .build();
    when(pathExpressionMatcher.matches(eq("*.md"), any(Path.class))).thenReturn(true);

    // Create another matching per-file code owner set that does not ignore parent code owners.
    CodeOwnerSet perFileCodeOwnerSet2 =
        CodeOwnerSet.builder().addPathExpression("baz.*").addCodeOwnerEmail(user.email()).build();
    when(pathExpressionMatcher.matches(eq("baz.*"), any(Path.class))).thenReturn(true);

    try (AutoCloseable registration = registerTestBackend(pathExpressionMatcher)) {
      CodeOwnerConfig codeOwnerConfig =
          createCodeOwnerBuilder()
              .addCodeOwnerSet(perFileCodeOwnerSet1)
              .addCodeOwnerSet(perFileCodeOwnerSet2)
              .build();
      PathCodeOwners pathCodeOwners =
          pathCodeOwnersFactory.createWithoutCache(codeOwnerConfig, Path.of("/foo/bar/baz.md"));
      assertThat(pathCodeOwners.resolveCodeOwnerConfig().get().getPathCodeOwners())
          .comparingElementsUsing(hasEmail())
          .containsExactly(admin.email(), user.email());
    }
  }

  @Test
  public void checkThatParentCodeOwnersAreIgnoredIfCodeOwnerConfigIgnoresParentCodeOwners()
      throws Exception {
    PathCodeOwners pathCodeOwners =
        pathCodeOwnersFactory.createWithoutCache(
            createCodeOwnerBuilder().setIgnoreParentCodeOwners().build(),
            Path.of("/foo/bar/baz.md"));
    assertThat(pathCodeOwners.resolveCodeOwnerConfig().get().ignoreParentCodeOwners()).isTrue();
  }

  @Test
  public void checkThatParentCodeOwnersAreNotIgnoredIfCodeOwnerConfigDoesNotIgnoreParentCodeOwners()
      throws Exception {
    PathCodeOwners pathCodeOwners =
        pathCodeOwnersFactory.createWithoutCache(
            createCodeOwnerBuilder().setIgnoreParentCodeOwners(false).build(),
            Path.of("/foo/bar/baz.md"));
    assertThat(pathCodeOwners.resolveCodeOwnerConfig().get().ignoreParentCodeOwners()).isFalse();
  }

  @Test
  public void checkThatParentCodeOwnersAreIgnoredIfMatchingCodeOwnerSetIgnoresParentCodeOwners()
      throws Exception {
    PathCodeOwners pathCodeOwners =
        pathCodeOwnersFactory.createWithoutCache(
            createCodeOwnerBuilder()
                .addCodeOwnerSet(
                    CodeOwnerSet.builder()
                        .setIgnoreGlobalAndParentCodeOwners()
                        .addPathExpression("*.md")
                        .build())
                .build(),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners.resolveCodeOwnerConfig().get().ignoreParentCodeOwners()).isTrue();
  }

  @Test
  public void
      checkThatParentCodeOwnersAreNotIgnoredIfNonMatchingCodeOwnerSetIgnoresParentCodeOwners()
          throws Exception {
    PathCodeOwners pathCodeOwners =
        pathCodeOwnersFactory.createWithoutCache(
            createCodeOwnerBuilder()
                .addCodeOwnerSet(
                    CodeOwnerSet.builder()
                        .setIgnoreGlobalAndParentCodeOwners()
                        .addPathExpression("*.txt")
                        .build())
                .build(),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners.resolveCodeOwnerConfig().get().ignoreParentCodeOwners()).isFalse();
  }

  @Test
  public void nonResolveableImportIsIgnored() throws Exception {
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        CodeOwnerConfig.Key.create(project, "master", "/non-existing/", "OWNERS");
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(CodeOwnerConfigImportMode.ALL, keyOfImportedCodeOwnerConfig);

    // create importing config with non-resolveable import
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addImport(codeOwnerConfigReference)
            .addCodeOwnerSet(CodeOwnerSet.builder().addCodeOwnerEmail(admin.email()).build())
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the global code owner from the importing code owner config, the
    // non-resolveable import is silently ignored
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email());
    assertThat(pathCodeOwnersResult.resolvedImports()).isEmpty();
    assertThat(pathCodeOwnersResult.unresolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createUnresolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference,
                String.format(
                    "code owner config does not exist (revision = %s)",
                    projectOperations
                        .project(keyOfImportedCodeOwnerConfig.project())
                        .getHead(keyOfImportedCodeOwnerConfig.branchNameKey().branch())
                        .name())));
  }

  @Test
  public void importOfNonCodeOwnerConfigFileIsIgnored() throws Exception {
    // create a file that looks like a code owner config file, but which has a name that is not
    // allowed as code owner config file
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .fileName("FOO")
            .addCodeOwnerEmail(user.email())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(CodeOwnerConfigImportMode.ALL, keyOfImportedCodeOwnerConfig);

    // create config with import of non code owner config file
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addImport(codeOwnerConfigReference)
            .addCodeOwnerSet(CodeOwnerSet.builder().addCodeOwnerEmail(admin.email()).build())
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the global code owner from the importing code owner config, the
    // import of the non code owner config file is silently ignored
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email());
    assertThat(pathCodeOwnersResult.resolvedImports()).isEmpty();
    assertThat(pathCodeOwnersResult.unresolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createUnresolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference,
                String.format(
                    "code owner config does not exist (revision = %s)",
                    projectOperations
                        .project(keyOfImportedCodeOwnerConfig.project())
                        .getHead(keyOfImportedCodeOwnerConfig.branchNameKey().branch())
                        .name())));
  }

  @Test
  public void importOfCodeOwnerConfigFileWithFileExtensionIsIgnored() throws Exception {
    // Create a code owner config file with a file extension. This file is only considered as a code
    // owner config file if either the file extension matches the configured file extension (config
    // parameter fileExtension) or file extensions are enabled for code owner config files (config
    // paramater enableCodeOwnerConfigFilesWithFileExtensions). Both is not the case here, hence any
    // import of this file in another code owner config file should get ignored.
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .fileName("OWNERS.foo")
            .addCodeOwnerEmail(user.email())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(CodeOwnerConfigImportMode.ALL, keyOfImportedCodeOwnerConfig);

    // create the importing config
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addImport(codeOwnerConfigReference)
            .addCodeOwnerSet(CodeOwnerSet.builder().addCodeOwnerEmail(admin.email()).build())
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the global code owner from the importing code owner config, the
    // import of the code owner config file with the file extension is silently ignored since it is
    // not considered as a code owner config file
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email());
    assertThat(pathCodeOwnersResult.resolvedImports()).isEmpty();
    assertThat(pathCodeOwnersResult.unresolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createUnresolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference,
                String.format(
                    "code owner config does not exist (revision = %s)",
                    projectOperations
                        .project(keyOfImportedCodeOwnerConfig.project())
                        .getHead(keyOfImportedCodeOwnerConfig.branchNameKey().branch())
                        .name())));
  }

  @Test
  @GerritConfig(
      name = "plugin.code-owners.enableCodeOwnerConfigFilesWithFileExtensions",
      value = "true")
  public void importOfCodeOwnerConfigFileWithFileExtension() throws Exception {
    // Create a code owner config file with a file extension. This file is considered as a code
    // owner config file since file extensions for code owner config files are enabled (paramater
    // enableCodeOwnerConfigFilesWithFileExtensions).
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .fileName("OWNERS.FOO")
            .addCodeOwnerEmail(user.email())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(CodeOwnerConfigImportMode.ALL, keyOfImportedCodeOwnerConfig);

    // create the importing config
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addImport(codeOwnerConfigReference)
            .addCodeOwnerSet(CodeOwnerSet.builder().addCodeOwnerEmail(admin.email()).build())
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the global code owner from the importing code owner config and the global
    // code owner from the imported code owner config
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email(), user.email());
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void importGlobalCodeOwners_importModeAll() throws Exception {
    testImportGlobalCodeOwners(CodeOwnerConfigImportMode.ALL);
  }

  @Test
  public void importGlobalCodeOwners_importModeGlobalCodeOwnerSetsOnly() throws Exception {
    testImportGlobalCodeOwners(CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY);
  }

  private void testImportGlobalCodeOwners(CodeOwnerConfigImportMode importMode) throws Exception {
    // create imported config with global code owner
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/bar/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(user.email())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(importMode, keyOfImportedCodeOwnerConfig);

    // create importing config with global code owner and import
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .addImport(codeOwnerConfigReference)
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the global code owners from the importing and the imported code owner
    // config
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email(), user.email());
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void importPerFileCodeOwners_importModeAll() throws Exception {
    // create imported config with matching per-file code owner
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/bar/")
            .fileName("OWNERS")
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression("*.md")
                    .addCodeOwnerEmail(user.email())
                    .build())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(CodeOwnerConfigImportMode.ALL, keyOfImportedCodeOwnerConfig);

    // create importing config with matching per-file code owner and import
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression("*.md")
                    .addCodeOwnerEmail(admin.email())
                    .build())
            .addImport(codeOwnerConfigReference)
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the matching per-file code owners from the importing and the imported
    // code owner config
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email(), user.email());
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void nonMatchingPerFileCodeOwnersAreNotImported_importModeAll() throws Exception {
    // create imported config with non-matching per-file code owner
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/bar/")
            .fileName("OWNERS")
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression("*.txt")
                    .addCodeOwnerEmail(user.email())
                    .build())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(CodeOwnerConfigImportMode.ALL, keyOfImportedCodeOwnerConfig);

    // create importing config with matching per-file code owner and import
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression("*.md")
                    .addCodeOwnerEmail(admin.email())
                    .build())
            .addImport(codeOwnerConfigReference)
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we only get the matching per-file code owners from the importing code owner
    // config, the per-file code owners from the imported code owner config are not relevant since
    // they do not match
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email());
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void perFileCodeOwnersAreNotImported_importModeGlobalCodeOwnerSetsOnly() throws Exception {
    // create imported config with matching per-file code owner
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/bar/")
            .fileName("OWNERS")
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression("*.md")
                    .addCodeOwnerEmail(user.email())
                    .build())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(
            CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, keyOfImportedCodeOwnerConfig);

    // create importing config with matching per-file code owner and import
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression("*.md")
                    .addCodeOwnerEmail(admin.email())
                    .build())
            .addImport(codeOwnerConfigReference)
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we only get the matching per-file code owners from the importing code owner
    // config, the matching per-file code owners from the imported code owner config are not
    // relevant with import mode GLOBAL_CODE_OWNER_SETS_ONLY
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email());
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void
      importIgnoreGlobalAndParentCodeOwnersFlagFromMatchingPerFileCodeOwnerSet_importModeAll()
          throws Exception {
    // create imported config with matching per-file code owner that has the
    // ignoreGlobalAndParentCodeOwners flag set to true
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/bar/")
            .fileName("OWNERS")
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .setIgnoreGlobalAndParentCodeOwners()
                    .addPathExpression("*.md")
                    .addCodeOwnerEmail(user.email())
                    .build())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(CodeOwnerConfigImportMode.ALL, keyOfImportedCodeOwnerConfig);

    // create importing config with global code owner and import
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .addImport(codeOwnerConfigReference)
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we only get the matching per-file code owners from the imported code owner
    // config, the global code owners from the importing code owner config are not relevant since
    // the matching per-file code owner set in the imported code owner config has the
    // ignoreGlobalAndParentCodeOwners flag set to true which causes global code owners to be
    // ignored, in addition this flag causes parent code owners to be ignored
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(user.email());
    assertThat(pathCodeOwnersResult.ignoreParentCodeOwners()).isTrue();
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void
      ignoreGlobalAndParentCodeOwnersFlagIsNotImportedFromNonMatchingPerFileCodeOwnerSet_importModeAll()
          throws Exception {
    // create imported config with non-matching per-file code owner that has the
    // ignoreGlobalAndParentCodeOwners flag set to true
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/bar/")
            .fileName("OWNERS")
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .setIgnoreGlobalAndParentCodeOwners()
                    .addPathExpression("*.txt")
                    .addCodeOwnerEmail(user.email())
                    .build())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(CodeOwnerConfigImportMode.ALL, keyOfImportedCodeOwnerConfig);

    // create importing config with global code owner and import
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .addImport(codeOwnerConfigReference)
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we only get the global code owners from the importing code owner config, the
    // per-file code owners from the imported code owner config and its
    // ignoreGlobalAndParentCodeOwners flag are not relevant since the per-file code owner set does
    // not match
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email());
    assertThat(pathCodeOwnersResult.ignoreParentCodeOwners()).isFalse();
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void ignoreGlobalAndParentCodeOwnersFlagIsNotImported_importModeGlobalCodeOwnerSetsOnly()
      throws Exception {
    // create imported config with matching per-file code owner that has the
    // ignoreGlobalAndParentCodeOwners flag set to true
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/bar/")
            .fileName("OWNERS")
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .setIgnoreGlobalAndParentCodeOwners()
                    .addPathExpression("*.md")
                    .addCodeOwnerEmail(user.email())
                    .build())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(
            CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, keyOfImportedCodeOwnerConfig);

    // create importing config with global code owner and import
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .addImport(codeOwnerConfigReference)
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we only get the global code owners from the importing code owner config, the
    // matching per-file code owners from the imported code owner config and its
    // ignoreGlobalAndParentCodeOwners flag are not relevant with import mode
    // GLOBAL_CODE_OWNER_SETS_ONLY
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email());
    assertThat(pathCodeOwnersResult.ignoreParentCodeOwners()).isFalse();
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void importIgnoreParentCodeOwnersFlag_importModeAll() throws Exception {
    // create imported config with the ignoreParentCodeOnwers flag set to true
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/bar/")
            .fileName("OWNERS")
            .ignoreParentCodeOwners()
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(CodeOwnerConfigImportMode.ALL, keyOfImportedCodeOwnerConfig);

    // create importing config
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .addImport(codeOwnerConfigReference)
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: ignoreParentCodeOwners is true because the ignoreParentCodeOwners flag in the
    // imported code owner config is set to true
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.ignoreParentCodeOwners()).isTrue();
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void ignoreParentCodeOwnersFlagNotImported_importModeGlobalCodeOwnerSetsOnly()
      throws Exception {
    // create imported config with the ignoreParentCodeOnwers flag set to true
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/bar/")
            .fileName("OWNERS")
            .ignoreParentCodeOwners()
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(
            CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, keyOfImportedCodeOwnerConfig);

    // create importing config
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .addImport(codeOwnerConfigReference)
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: ignoreParentCodeOwners is false because the ignoreParentCodeOwners flag in the
    // imported code owner config is not relevant with import mode GLOBAL_CODE_OWNER_SETS_ONLY
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.ignoreParentCodeOwners()).isFalse();
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void importsOfImportedCodeOwnerConfigAreResolved_importModeAll() throws Exception {
    testImportsOfImportedCodeOwnerConfigAreResolved(CodeOwnerConfigImportMode.ALL);
  }

  @Test
  public void importsOfImportedCodeOwnerConfigAreResolved_importModeGlobalCodeOwnerSetsOnly()
      throws Exception {
    testImportsOfImportedCodeOwnerConfigAreResolved(
        CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY);
  }

  private void testImportsOfImportedCodeOwnerConfigAreResolved(CodeOwnerConfigImportMode importMode)
      throws Exception {
    TestAccount user2 = accountCreator.user2();

    // create config with global code owner that is imported by the imported config
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig2 =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/baz/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(user2.email())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference2 =
        createCodeOwnerConfigReference(importMode, keyOfImportedCodeOwnerConfig2);

    // create imported config with global code owner and import
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig1 =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/bar/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(user.email())
            .addImport(codeOwnerConfigReference2)
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference1 =
        createCodeOwnerConfigReference(importMode, keyOfImportedCodeOwnerConfig1);

    // create importing config with global code owner and import
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .addImport(codeOwnerConfigReference1)
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the global owners from the importing code owner config, the imported code
    // owner config and the code owner config that is imported by the imported code owner config
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email(), user.email(), user2.email());
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig1,
                codeOwnerConfigReference1),
            CodeOwnerConfigImport.createResolvedImport(
                keyOfImportedCodeOwnerConfig1,
                keyOfImportedCodeOwnerConfig2,
                codeOwnerConfigReference2));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void
      onlyGlobalCodeOwnersAreImportedForTransitiveImportsIfImportModeIsGlobalCodeOwnerSetsOnly()
          throws Exception {
    TestAccount user2 = accountCreator.user2();

    // create config with per file code owner that is imported by the imported config
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig2 =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/baz/")
            .fileName("OWNERS")
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression("foo.md")
                    .addCodeOwnerEmail(user2.email())
                    .build())
            .create();

    // create imported config with global code owner and import with import mode ALL
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig1 =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/bar/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(user.email())
            .addImport(
                createCodeOwnerConfigReference(
                    CodeOwnerConfigImportMode.ALL, keyOfImportedCodeOwnerConfig2))
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference1 =
        createCodeOwnerConfigReference(
            CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, keyOfImportedCodeOwnerConfig1);

    // create importing config with global code owner and import with import mode
    // GLOBAL_CODE_OWNER_SETS_ONLY
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .addImport(codeOwnerConfigReference1)
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the global owners from the importing code owner config and the imported
    // code owner config but not the per file code owner from the code owner config that is imported
    // by the imported code owner config
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email(), user.email());
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig1,
                codeOwnerConfigReference1),
            CodeOwnerConfigImport.createResolvedImport(
                keyOfImportedCodeOwnerConfig1,
                keyOfImportedCodeOwnerConfig2,
                createCodeOwnerConfigReference(
                    CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY,
                    keyOfImportedCodeOwnerConfig2)));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void importCodeOwnerConfigWithPostFix() throws Exception {
    testImportCodeOwnerConfigWithNameExtension("OWNERS_post_fix");
  }

  @Test
  public void importCodeOwnerConfigWithPostFixThatContainsHyphen() throws Exception {
    testImportCodeOwnerConfigWithNameExtension("OWNERS_post-fix");
  }

  @Test
  public void importCodeOwnerConfigWithPreFix() throws Exception {
    testImportCodeOwnerConfigWithNameExtension("pre_fix_OWNERS");
  }

  @Test
  public void importCodeOwnerConfigWithPreFixThatContainsHyphen() throws Exception {
    testImportCodeOwnerConfigWithNameExtension("pre-fix_OWNERS");
  }

  private void testImportCodeOwnerConfigWithNameExtension(String nameOfImportedCodeOwnerConfig)
      throws Exception {
    // create imported config with global code owner
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/bar/")
            .fileName("OWNERS")
            .fileName(nameOfImportedCodeOwnerConfig)
            .addCodeOwnerEmail(user.email())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(
            CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, keyOfImportedCodeOwnerConfig);

    // create importing config with global code owner and import
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .addImport(codeOwnerConfigReference)
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the global code owners from the importing and the imported code owner
    // config
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email(), user.email());
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void cyclicImports() throws Exception {
    CodeOwnerConfigReference codeOwnerConfigReference2 =
        CodeOwnerConfigReference.create(CodeOwnerConfigImportMode.ALL, "/OWNERS");

    // create imported config with global code owner and that imports the importing config
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/bar/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(user.email())
            .addImport(codeOwnerConfigReference2)
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference1 =
        createCodeOwnerConfigReference(CodeOwnerConfigImportMode.ALL, keyOfImportedCodeOwnerConfig);

    // create importing config with global code owner and import
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(admin.email())
            .addImport(codeOwnerConfigReference1)
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the global owners from the importing and the imported code owner config
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email(), user.email());
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference1),
            CodeOwnerConfigImport.createResolvedImport(
                keyOfImportedCodeOwnerConfig,
                importingCodeOwnerConfigKey,
                codeOwnerConfigReference2));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void importsAreResolvedFromSameRevision() throws Exception {
    TestAccount user2 = accountCreator.user2();

    // create importing config with global code owner and import
    CodeOwnerConfig.Key rootCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .addImport(
                CodeOwnerConfigReference.create(CodeOwnerConfigImportMode.ALL, "/bar/OWNERS"))
            .create();

    // create imported config with global code owner
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/bar/")
            .addCodeOwnerEmail(user.email())
            .create();

    // remember the revision
    RevCommit oldRevision = projectOperations.project(project).getHead("master");

    // update imported config and add one additional global code owner
    codeOwnerConfigOperations
        .codeOwnerConfig(keyOfImportedCodeOwnerConfig)
        .forUpdate()
        .codeOwnerSetsModification(CodeOwnerSetModification.addToOnlySet(user2.email()))
        .update();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            rootCodeOwnerConfigKey,
            oldRevision,
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the global owners from the importing and the imported code owner config
    // as they were defined at oldRevision
    assertThat(pathCodeOwners.get().resolveCodeOwnerConfig().get().getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email(), user.email());
  }

  @Test
  public void importWithRelativePath() throws Exception {
    // create imported config with global code owner
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/foo/baz/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(user.email())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(CodeOwnerConfigImportMode.ALL, keyOfImportedCodeOwnerConfig);

    // create importing config with global code owner and import with relative path
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/foo/bar/")
            .addCodeOwnerEmail(admin.email())
            .addImport(codeOwnerConfigReference)
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo/bar/baz.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the global owners from the importing and the imported code owner config
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email(), user.email());
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void importFromNonExistingProjectIsIgnored() throws Exception {
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        CodeOwnerConfig.Key.create(Project.nameKey("non-existing"), "master", "/bar/", "OWNERS");
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(CodeOwnerConfigImportMode.ALL, keyOfImportedCodeOwnerConfig);

    // create importing config with global code owner and import from non-existing project
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .addImport(codeOwnerConfigReference)
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo/bar/baz.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the global owners from the importing code owner config
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email());
    assertThat(pathCodeOwnersResult.resolvedImports()).isEmpty();
    assertThat(pathCodeOwnersResult.unresolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createUnresolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference,
                String.format("project %s not found", keyOfImportedCodeOwnerConfig.project())));
  }

  @Test
  public void importFromHiddenProjectIsIgnored() throws Exception {
    // create a hidden project with a code owner config file
    Project.NameKey hiddenProject = projectOperations.newProject().name("hidden-project").create();
    ConfigInput configInput = new ConfigInput();
    configInput.state = ProjectState.HIDDEN;
    gApi.projects().name(hiddenProject.get()).config(configInput);
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(hiddenProject)
            .branch("master")
            .folderPath("/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(user.email())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(CodeOwnerConfigImportMode.ALL, keyOfImportedCodeOwnerConfig);

    // create importing config with global code owner and import from the hidden project
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .addImport(codeOwnerConfigReference)
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo/bar/baz.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the global owners from the importing code owner config, the global code
    // owners from the imported code owner config are ignored since the project that contains the
    // code owner config is hidden
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email());
    assertThat(pathCodeOwnersResult.resolvedImports()).isEmpty();
    assertThat(pathCodeOwnersResult.unresolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createUnresolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference,
                String.format(
                    "state of project %s doesn't permit read",
                    keyOfImportedCodeOwnerConfig.project())));
  }

  @Test
  public void importFromNonExistingBranchIsIgnored() throws Exception {
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        CodeOwnerConfig.Key.create(project, "non-existing", "/bar/", "OWNERS");
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(CodeOwnerConfigImportMode.ALL, keyOfImportedCodeOwnerConfig);

    // create importing config with global code owner and import from non-existing branch
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .addImport(codeOwnerConfigReference)
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo/bar/baz.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the global owners from the importing code owner config
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwners.get().resolveCodeOwnerConfig().get().getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email());
    assertThat(pathCodeOwnersResult.resolvedImports()).isEmpty();
    assertThat(pathCodeOwnersResult.unresolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createUnresolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference,
                "code owner config does not exist (revision = current)"));
  }

  @Test
  public void importFromOtherProject() throws Exception {
    Project.NameKey otherProject = projectOperations.newProject().create();

    // create imported config with global code owner
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(otherProject)
            .branch("master")
            .folderPath("/bar/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(user.email())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(CodeOwnerConfigImportMode.ALL, keyOfImportedCodeOwnerConfig);

    // create importing config with global code owner and import with relative path
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .addImport(codeOwnerConfigReference)
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo/bar/baz.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the global owners from the importing and the imported code owner config
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email(), user.email());
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void importFromOtherProjectIsResolvedFromSameBranch() throws Exception {
    Project.NameKey otherProject = projectOperations.newProject().create();

    // Create other branches in project.
    String branchName = "foo";
    createBranch(BranchNameKey.create(project, branchName));

    // Create other branches in other project.
    createBranch(BranchNameKey.create(otherProject, branchName));

    // create imported config with global code owner
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(otherProject)
            .branch(branchName)
            .folderPath("/bar/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(user.email())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference =
        CodeOwnerConfigReference.builder(CodeOwnerConfigImportMode.ALL, "/bar/OWNERS")
            .setProject(otherProject)
            .build();

    // create importing config with global code owner and import with relative path
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch(branchName)
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .addImport(codeOwnerConfigReference)
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead(branchName),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the global owners from the importing and the imported code owner config
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email(), user.email());
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void importFromOtherBranch() throws Exception {
    // Create other branch.
    String otherBranch = "foo";
    createBranch(BranchNameKey.create(project, otherBranch));

    // create imported config with global code owner
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch(otherBranch)
            .folderPath("/bar/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(user.email())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(CodeOwnerConfigImportMode.ALL, keyOfImportedCodeOwnerConfig);

    // create importing config with global code owner and import with relative path
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .addImport(codeOwnerConfigReference)
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo/bar/baz.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the global owners from the importing and the imported code owner config
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email(), user.email());
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void importFromOtherProjectAndBranch() throws Exception {
    Project.NameKey otherProject = projectOperations.newProject().create();

    // Create other branch.
    String otherBranch = "foo";
    createBranch(BranchNameKey.create(otherProject, otherBranch));

    // create imported config with global code owner
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(otherProject)
            .branch(otherBranch)
            .folderPath("/bar/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(user.email())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(CodeOwnerConfigImportMode.ALL, keyOfImportedCodeOwnerConfig);

    // create importing config with global code owner and import with relative path
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .addImport(codeOwnerConfigReference)
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo/bar/baz.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the global owners from the importing and the imported code owner config
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email(), user.email());
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void nonResolveablePerFileImportIsIgnored() throws Exception {
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        CodeOwnerConfig.Key.create(project, "master", "/non-existing/", "OWNERS");
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(
            CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, keyOfImportedCodeOwnerConfig);

    // create importing config with non-resolveable per file import
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addCodeOwnerEmail(admin.email())
                    .addPathExpression("foo.md")
                    .addImport(codeOwnerConfigReference)
                    .build())
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the per file code owner from the importing code owner config, the
    // non-resolveable per file import is silently ignored
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email());
    assertThat(pathCodeOwnersResult.resolvedImports()).isEmpty();
    assertThat(pathCodeOwnersResult.unresolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createUnresolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference,
                String.format(
                    "code owner config does not exist (revision = %s)",
                    projectOperations
                        .project(keyOfImportedCodeOwnerConfig.project())
                        .getHead(keyOfImportedCodeOwnerConfig.branchNameKey().branch())
                        .name())));
  }

  @Test
  public void perFileImport() throws Exception {
    TestAccount user2 = accountCreator.user2();

    // create imported config with ignoreParentCodeOwners = true, a global code owner and a per file
    // code owner
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/bar/")
            .fileName("OWNERS")
            .ignoreParentCodeOwners()
            .addCodeOwnerEmail(user.email())
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression("foo.md")
                    .addCodeOwnerEmail(user2.email())
                    .build())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(
            CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, keyOfImportedCodeOwnerConfig);

    // create importing config with per code owner and per file import
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression("foo.md")
                    .addCodeOwnerEmail(admin.email())
                    .addImport(codeOwnerConfigReference)
                    .build())
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the per file code owners from the importing and the global code owner
    // from the imported code owner config, but not the per file code owner from the imported code
    // owner config
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email(), user.email());

    // Expectation: the ignoreParentCodeOwners flag from the imported code owner config is ignored
    assertThat(pathCodeOwnersResult.ignoreParentCodeOwners()).isFalse();

    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void importsOfPerFileImportedCodeOwnerConfigAreResolved() throws Exception {
    TestAccount user2 = accountCreator.user2();

    // create config with global code owner that is imported by the imported config
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig2 =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/baz/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(user2.email())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference2 =
        createCodeOwnerConfigReference(
            CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, keyOfImportedCodeOwnerConfig2);

    // create imported config with global code owner and global import
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig1 =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/bar/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(user.email())
            .addImport(codeOwnerConfigReference2)
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference1 =
        createCodeOwnerConfigReference(
            CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, keyOfImportedCodeOwnerConfig1);

    // create importing config with per file code owner and per file import
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression("foo.md")
                    .addCodeOwnerEmail(admin.email())
                    .addImport(codeOwnerConfigReference1)
                    .build())
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the global owners from the importing code owner config, the imported code
    // owner config and the code owner config that is imported by the imported code owner config
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email(), user.email(), user2.email());
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig1,
                codeOwnerConfigReference1),
            CodeOwnerConfigImport.createResolvedImport(
                keyOfImportedCodeOwnerConfig1,
                keyOfImportedCodeOwnerConfig2,
                codeOwnerConfigReference2));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void onlyGlobalCodeOwnersAreImportedForTransitivePerFileImports() throws Exception {
    TestAccount user2 = accountCreator.user2();

    // create config with per file code owner that is imported by the imported config
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig2 =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/baz/")
            .fileName("OWNERS")
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression("foo.md")
                    .addCodeOwnerEmail(user2.email())
                    .build())
            .create();

    // create imported config with per global owner and global import with mode ALL
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig1 =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/bar/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(user.email())
            .addImport(
                createCodeOwnerConfigReference(
                    CodeOwnerConfigImportMode.ALL, keyOfImportedCodeOwnerConfig2))
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference1 =
        createCodeOwnerConfigReference(
            CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, keyOfImportedCodeOwnerConfig1);

    // create importing config with per file code owner and per file import
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression("foo.md")
                    .addCodeOwnerEmail(admin.email())
                    .addImport(codeOwnerConfigReference1)
                    .build())
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the global owners from the importing code owner config and the imported
    // code owner config, but not the per file code owner from the code owner config that is
    // imported by the imported code owner config
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email(), user.email());
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig1,
                codeOwnerConfigReference1),
            CodeOwnerConfigImport.createResolvedImport(
                keyOfImportedCodeOwnerConfig1,
                keyOfImportedCodeOwnerConfig2,
                createCodeOwnerConfigReference(
                    CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY,
                    keyOfImportedCodeOwnerConfig2)));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void onlyMatchingTransitivePerFileImportsAreImported() throws Exception {
    TestAccount user2 = accountCreator.user2();

    // create config with global code owner that is imported by the imported config for *.md files
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig2 =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/md/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(user.email())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference2 =
        createCodeOwnerConfigReference(
            CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, keyOfImportedCodeOwnerConfig2);

    // create config with global code owner that is imported by the imported config for *.txt files
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig3 =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/txt/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(user2.email())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference3 =
        createCodeOwnerConfigReference(
            CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, keyOfImportedCodeOwnerConfig3);

    // create imported config with 2 per file imports, one for *.md files and one for *.txt
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig1 =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/bar/")
            .fileName("OWNERS")
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression("*.md")
                    .addImport(codeOwnerConfigReference2)
                    .build())
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression("*.txt")
                    .addImport(codeOwnerConfigReference3)
                    .build())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference1 =
        createCodeOwnerConfigReference(
            CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, keyOfImportedCodeOwnerConfig1);

    // create importing config with global import
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addImport(codeOwnerConfigReference1)
            .create();

    // Expectation for foo.xyz file: code owners is empty since foo.xyz neither matches *.md nor
    // *.txt
    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.xyz"));
    assertThat(pathCodeOwners).isPresent();
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners()).isEmpty();
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig1,
                codeOwnerConfigReference1));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();

    // Expectation for foo.md file: code owners contains only user since foo.md only matches *.md
    pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();
    pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(user.email());
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig1,
                codeOwnerConfigReference1),
            CodeOwnerConfigImport.createResolvedImport(
                keyOfImportedCodeOwnerConfig1,
                keyOfImportedCodeOwnerConfig2,
                codeOwnerConfigReference2));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();

    // Expectation for foo.txt file: code owners contains only user2 since foo.txt only matches
    // *.txt
    pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.txt"));
    assertThat(pathCodeOwners).isPresent();
    pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(user2.email());
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig1,
                codeOwnerConfigReference1),
            CodeOwnerConfigImport.createResolvedImport(
                keyOfImportedCodeOwnerConfig1,
                keyOfImportedCodeOwnerConfig3,
                codeOwnerConfigReference3));
  }

  @Test
  public void cannotMatchAgainstNullCodeOwnerSet() throws Exception {
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                PathCodeOwners.matches(
                    /* codeOwnerSet= */ null,
                    Path.of("bar/baz.md"),
                    mock(PathExpressionMatcher.class)));
    assertThat(npe).hasMessageThat().isEqualTo("codeOwnerSet");
  }

  @Test
  public void cannotMatchNullPath() throws Exception {
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                PathCodeOwners.matches(
                    CodeOwnerSet.createWithoutPathExpressions(admin.email()),
                    /* relativePath= */ null,
                    mock(PathExpressionMatcher.class)));
    assertThat(npe).hasMessageThat().isEqualTo("relativePath");
  }

  @Test
  public void cannotMatchAbsolutePath() throws Exception {
    String absolutePath = "/foo/bar/baz.md";
    IllegalStateException exception =
        assertThrows(
            IllegalStateException.class,
            () ->
                PathCodeOwners.matches(
                    CodeOwnerSet.createWithoutPathExpressions(admin.email()),
                    Path.of(absolutePath),
                    mock(PathExpressionMatcher.class)));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(String.format("path %s must be relative", absolutePath));
  }

  @Test
  public void cannotMatchWithNullPathExpressionMatcher() throws Exception {
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                PathCodeOwners.matches(
                    CodeOwnerSet.createWithoutPathExpressions(admin.email()),
                    Path.of("bar/baz.md"),
                    /* matcher= */ null));
    assertThat(npe).hasMessageThat().isEqualTo("matcher");
  }

  @Test
  public void cannotCheckIfCodeOwnerSetWithoutPathExpressionsMatches() throws Exception {
    PathExpressionMatcher pathExpressionMatcher = mock(PathExpressionMatcher.class);
    IllegalStateException exception =
        assertThrows(
            IllegalStateException.class,
            () ->
                PathCodeOwners.matches(
                    CodeOwnerSet.createWithoutPathExpressions(admin.email()),
                    Path.of("bar/baz.md"),
                    pathExpressionMatcher));
    assertThat(exception).hasMessageThat().isEqualTo("code owner set must have path expressions");
  }

  @Test
  public void codeOwnerSetMatchesIfPathExpressionMatches() throws Exception {
    PathExpressionMatcher pathExpressionMatcher = mock(PathExpressionMatcher.class);
    when(pathExpressionMatcher.matches(anyString(), any(Path.class))).thenReturn(true);
    assertThat(
            PathCodeOwners.matches(
                CodeOwnerSet.builder()
                    .addPathExpression("*.md")
                    .addCodeOwnerEmail(admin.email())
                    .build(),
                Path.of("bar/baz.md"),
                pathExpressionMatcher))
        .isTrue();
  }

  @Test
  public void codeOwnerSetDoesntMatchIfPathExpressionDoesntMatch() throws Exception {
    PathExpressionMatcher pathExpressionMatcher = mock(PathExpressionMatcher.class);
    when(pathExpressionMatcher.matches(anyString(), any(Path.class))).thenReturn(false);
    assertThat(
            PathCodeOwners.matches(
                CodeOwnerSet.builder()
                    .addPathExpression("*.md")
                    .addCodeOwnerEmail(admin.email())
                    .build(),
                Path.of("bar/baz.md"),
                pathExpressionMatcher))
        .isFalse();
  }

  @Test
  public void codeOwnerSetMatchesIfAnyPathExpressionMatches() throws Exception {
    PathExpressionMatcher pathExpressionMatcher = mock(PathExpressionMatcher.class);
    when(pathExpressionMatcher.matches(anyString(), any(Path.class)))
        .thenReturn(true)
        .thenReturn(false);
    assertThat(
            PathCodeOwners.matches(
                CodeOwnerSet.builder()
                    .addPathExpression("*.md")
                    .addPathExpression("config/*")
                    .addPathExpression("build/*")
                    .addCodeOwnerEmail(admin.email())
                    .build(),
                Path.of("bar/baz.md"),
                pathExpressionMatcher))
        .isTrue();
  }

  @Test
  public void perFileRuleThatIgnoresGlobalCodeOwnersCanImportGlobalCodeOwnersFromOtherFile()
      throws Exception {
    // create imported config with a global code owner
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/bar/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(user.email())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(
            CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, keyOfImportedCodeOwnerConfig);

    // create importing config that:
    // * has a global code owner
    // * has a per-file import for md files
    // * ignores global and parent code owners for md files
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression(testPathExpressions.matchFileType("md"))
                    .setIgnoreGlobalAndParentCodeOwners()
                    .addImport(codeOwnerConfigReference)
                    .build())
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the global code owner from the imported code owner config (since it is
    // imported by a matching per-file rule), the global code owner from the importing code owner
    // config is ignored (since the matching per-file rule ignores parent and global code owners)
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(user.email());
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void
      perFileRuleThatIsImportedByAGlobalImportIsRespectedIfALocalPerFileRuleIgnoresGlobalCodeOwners()
          throws Exception {
    TestAccount user2 = accountCreator.user2();
    TestAccount user3 =
        accountCreator.create("user3", "user3@example.com", "User3", /* displayName= */ null);

    // create imported config that has a matching per-file rule
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/bar/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(user2.email())
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression(testPathExpressions.matchFileType("md"))
                    .addCodeOwnerEmail(user3.email())
                    .build())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference =
        createCodeOwnerConfigReference(CodeOwnerConfigImportMode.ALL, keyOfImportedCodeOwnerConfig);

    // create importing config that has a global import with mode ALL and a per-file rule for md
    // files that ignores global and parent code owners
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .addImport(codeOwnerConfigReference)
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression(testPathExpressions.matchFileType("md"))
                    .setIgnoreGlobalAndParentCodeOwners()
                    .addCodeOwnerEmail(user.email())
                    .build())
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the code owner from the matching per-file rule in the importing code
    // owner config and the code owner from the matching per-file rule in the imported code owner
    // config, the global code owners are ignored since there is a matching per-file rule that
    // ignores parent and global code owners
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(user.email(), user3.email());
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig,
                codeOwnerConfigReference));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void transitiveImportsAcrossProjects() throws Exception {
    TestAccount user2 = accountCreator.user2();

    Project.NameKey otherProject = projectOperations.newProject().create();

    // create transitively imported config in other project
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig2 =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(otherProject)
            .branch("master")
            .folderPath("/baz/")
            .fileName("OWNERS")
            .addCodeOwnerSet(CodeOwnerSet.builder().addCodeOwnerEmail(user2.email()).build())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference2 =
        createCodeOwnerConfigReference(
            CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, keyOfImportedCodeOwnerConfig2);

    // create imported config in other project
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig1 =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(otherProject)
            .branch("master")
            .folderPath("/bar/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(user.email())
            .addImport(codeOwnerConfigReference2)
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference1 =
        createCodeOwnerConfigReference(
            CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, keyOfImportedCodeOwnerConfig1);

    // create importing config
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .addImport(codeOwnerConfigReference1)
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the global owners from the importing code owner config and from the
    // directly and transitively imported code owner configs in the other project
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwnersResult.getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email(), user.email(), user2.email());
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig1,
                codeOwnerConfigReference1),
            CodeOwnerConfigImport.createResolvedImport(
                keyOfImportedCodeOwnerConfig1,
                keyOfImportedCodeOwnerConfig2,
                codeOwnerConfigReference2));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  @Test
  public void transitiveImportsWithRelativePaths() throws Exception {
    TestAccount user2 = accountCreator.user2();

    Project.NameKey otherProject = projectOperations.newProject().create();

    // create transitively imported config
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig2 =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(otherProject)
            .branch("master")
            .folderPath("/bar/baz/")
            .fileName("OWNERS")
            .addCodeOwnerSet(CodeOwnerSet.builder().addCodeOwnerEmail(user2.email()).build())
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference2 =
        createCodeOwnerConfigReference(
            CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, keyOfImportedCodeOwnerConfig2);

    // create imported config
    CodeOwnerConfig.Key keyOfImportedCodeOwnerConfig1 =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(otherProject)
            .branch("master")
            .folderPath("/bar/")
            .fileName("OWNERS")
            .addCodeOwnerEmail(user.email())
            .addImport(codeOwnerConfigReference2)
            .create();
    CodeOwnerConfigReference codeOwnerConfigReference1 =
        createCodeOwnerConfigReference(
            CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, keyOfImportedCodeOwnerConfig1);

    // create importing config
    CodeOwnerConfig.Key importingCodeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(admin.email())
            .addImport(codeOwnerConfigReference1)
            .create();

    Optional<PathCodeOwners> pathCodeOwners =
        pathCodeOwnersFactory.create(
            transientCodeOwnerConfigCacheProvider.get(),
            importingCodeOwnerConfigKey,
            projectOperations.project(project).getHead("master"),
            Path.of("/foo.md"));
    assertThat(pathCodeOwners).isPresent();

    // Expectation: we get the global owners from the importing code owner config and from the
    // directly and transitively imported code owner configs
    PathCodeOwnersResult pathCodeOwnersResult = pathCodeOwners.get().resolveCodeOwnerConfig().get();
    assertThat(pathCodeOwners.get().resolveCodeOwnerConfig().get().getPathCodeOwners())
        .comparingElementsUsing(hasEmail())
        .containsExactly(admin.email(), user.email(), user2.email());
    assertThat(pathCodeOwnersResult.resolvedImports())
        .containsExactly(
            CodeOwnerConfigImport.createResolvedImport(
                importingCodeOwnerConfigKey,
                keyOfImportedCodeOwnerConfig1,
                codeOwnerConfigReference1),
            CodeOwnerConfigImport.createResolvedImport(
                keyOfImportedCodeOwnerConfig1,
                keyOfImportedCodeOwnerConfig2,
                codeOwnerConfigReference2));
    assertThat(pathCodeOwnersResult.unresolvedImports()).isEmpty();
  }

  private CodeOwnerConfig.Builder createCodeOwnerBuilder() {
    return CodeOwnerConfig.builder(
        CodeOwnerConfig.Key.create(BranchNameKey.create(project, "master"), Path.of("/")),
        ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));
  }

  private AutoCloseable registerTestBackend(@Nullable PathExpressionMatcher pathExpressionMatcher) {
    RegistrationHandle registrationHandle =
        ((PrivateInternals_DynamicMapImpl<CodeOwnerBackend>) codeOwnerBackends)
            .put(
                "gerrit",
                TestCodeOwnerBackend.ID,
                Providers.of(new TestCodeOwnerBackend(pathExpressionMatcher)));
    return registrationHandle::remove;
  }

  private static class TestCodeOwnerBackend implements CodeOwnerBackend {
    static final String ID = "test-backend";

    @Nullable private final PathExpressionMatcher pathExpressionMatcher;

    TestCodeOwnerBackend(PathExpressionMatcher pathExpressionMatcher) {
      this.pathExpressionMatcher = pathExpressionMatcher;
    }

    @Override
    public Optional<CodeOwnerConfig> getCodeOwnerConfig(
        CodeOwnerConfig.Key codeOwnerConfigKey, @Nullable ObjectId revision) {
      throw new UnsupportedOperationException("not implemented");
    }

    @Override
    public Optional<CodeOwnerConfig> upsertCodeOwnerConfig(
        CodeOwnerConfig.Key codeOwnerConfigKey,
        CodeOwnerConfigUpdate codeOwnerConfigUpdate,
        @Nullable IdentifiedUser currentUser) {
      throw new UnsupportedOperationException("not implemented");
    }

    @Override
    public Optional<PathExpressionMatcher> getPathExpressionMatcher(BranchNameKey branchNameKey) {
      return Optional.ofNullable(pathExpressionMatcher);
    }

    @Override
    public boolean isCodeOwnerConfigFile(NameKey project, String fileName) {
      throw new UnsupportedOperationException("not implemented");
    }

    @Override
    public Path getFilePath(CodeOwnerConfig.Key codeOwnerConfigKey) {
      throw new UnsupportedOperationException("not implemented");
    }
  }
}
