// 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.common.truth.Truth8.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.nio.file.Paths;
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(), Paths.get("/foo/bar/baz.md"));
    assertThat(pathCodeOwners).isNotNull();
  }

  @Test
  public void cannotCreatePathCodeOwnersForNullCodeOwnerConfig() throws Exception {
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                pathCodeOwnersFactory.createWithoutCache(
                    /* codeOwnerConfig= */ null, Paths.get("/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, Paths.get(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"),
            Paths.get("/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"), Paths.get("/")),
                    projectOperations.project(project).getHead("master"),
                    Paths.get("/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"),
                    Paths.get("/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"), Paths.get("/")),
                    /* revision= */ null,
                    Paths.get("/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"),
                    Paths.get(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, Paths.get("/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, Paths.get("/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, Paths.get("/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, Paths.get("/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, Paths.get("/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, Paths.get("/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, Paths.get("/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(),
            Paths.get("/foo/bar/baz.md"));
    assertThat(pathCodeOwners.resolveCodeOwnerConfig().get().ignoreParentCodeOwners()).isTrue();
  }

  @Test
  public void checkThatParentCodeOwnersAreNotIgnoredIfCodeOwnerConfigDoesNotIgnoreParentCodeOwners()
      throws Exception {
    PathCodeOwners pathCodeOwners =
        pathCodeOwnersFactory.createWithoutCache(
            createCodeOwnerBuilder().setIgnoreParentCodeOwners(false).build(),
            Paths.get("/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(),
            Paths.get("/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(),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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,
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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,
                    Paths.get("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()),
                    Paths.get(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()),
                    Paths.get("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()),
                    Paths.get("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(),
                Paths.get("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(),
                Paths.get("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(),
                Paths.get("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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"),
            Paths.get("/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"), Paths.get("/")),
        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");
    }
  }
}
