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

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.gerrit.plugins.codeowners.testing.CodeOwnerConfigSubject.assertThat;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static java.util.stream.Collectors.joining;

import com.google.common.base.Joiner;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.plugins.codeowners.backend.AbstractCodeOwnerConfigParserTest;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfig;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfigImportMode;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfigParseException;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfigParser;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfigReference;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerReference;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerSet;
import com.google.gerrit.plugins.codeowners.testing.CodeOwnerConfigReferenceSubject;
import com.google.gerrit.plugins.codeowners.testing.CodeOwnerSetSubject;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.regex.Pattern;
import org.junit.Test;

/** Tests for {@link FindOwnersCodeOwnerConfigParser}. */
public class FindOwnersCodeOwnerConfigParserTest extends AbstractCodeOwnerConfigParserTest {
  @Override
  protected Class<? extends CodeOwnerConfigParser> getCodeOwnerConfigParserClass() {
    return FindOwnersCodeOwnerConfigParser.class;
  }

  @Override
  protected String getCodeOwnerConfig(CodeOwnerConfig codeOwnerConfig) {
    StringBuilder b = new StringBuilder();
    if (codeOwnerConfig.ignoreParentCodeOwners()) {
      b.append("set noparent\n");
    }

    codeOwnerConfig
        .imports()
        .forEach(
            codeOwnerConfigReference -> {
              String keyword;
              if (codeOwnerConfigReference.importMode().equals(CodeOwnerConfigImportMode.ALL)) {
                keyword = "include";
              } else {
                keyword = "file:";
              }
              b.append(
                  String.format(
                      "%s %s%s%s\n",
                      keyword,
                      codeOwnerConfigReference
                          .project()
                          .map(Project.NameKey::get)
                          .map(projectName -> projectName + ":")
                          .orElse(""),
                      codeOwnerConfigReference.branch().map(branch -> branch + ":").orElse(""),
                      codeOwnerConfigReference.filePath()));
            });

    // global code owners
    for (String email :
        codeOwnerConfig.codeOwnerSets().stream()
            .filter(codeOwnerSet -> codeOwnerSet.pathExpressions().isEmpty())
            .flatMap(codeOwnerSet -> codeOwnerSet.codeOwners().stream())
            .map(CodeOwnerReference::email)
            .sorted()
            .distinct()
            .collect(toImmutableList())) {
      b.append(email).append('\n');
    }

    // per-file code owners
    for (CodeOwnerSet codeOwnerSet :
        codeOwnerConfig.codeOwnerSets().stream()
            .filter(codeOwnerSet -> !codeOwnerSet.pathExpressions().isEmpty())
            .collect(toImmutableList())) {
      if (codeOwnerSet.ignoreGlobalAndParentCodeOwners()) {
        b.append(
            String.format(
                "per-file %s=set noparent\n",
                codeOwnerSet.pathExpressions().stream().sorted().collect(joining(","))));
      }
      for (CodeOwnerConfigReference codeOwnerConfigReference : codeOwnerSet.imports()) {
        b.append(
            String.format(
                "per-file %s=file: %s%s%s\n",
                codeOwnerSet.pathExpressions().stream().sorted().collect(joining(",")),
                codeOwnerConfigReference
                    .project()
                    .map(Project.NameKey::get)
                    .map(projectName -> projectName + ":")
                    .orElse(""),
                codeOwnerConfigReference.branch().map(branch -> branch + ":").orElse(""),
                codeOwnerConfigReference.filePath()));
      }
      if (!codeOwnerSet.codeOwners().isEmpty()) {
        b.append(
            String.format(
                "per-file %s=%s\n",
                codeOwnerSet.pathExpressions().stream().sorted().collect(joining(",")),
                codeOwnerSet.codeOwners().stream()
                    .map(CodeOwnerReference::email)
                    .sorted()
                    .collect(joining(","))));
      }
    }

    return b.toString();
  }

  @Test
  public void cannotParseCodeOwnerConfigWithInvalidEmails() throws Exception {
    CodeOwnerConfigParseException exception =
        assertThrows(
            CodeOwnerConfigParseException.class,
            () ->
                codeOwnerConfigParser.parse(
                    TEST_REVISION,
                    CodeOwnerConfig.Key.create(project, "master", "/"),
                    getCodeOwnerConfig(
                        EMAIL_1, "@example.com", "admin@", "admin@example@com", EMAIL_2)));
    assertThat(exception.getFullMessage(FindOwnersBackend.CODE_OWNER_CONFIG_FILE_NAME))
        .isEqualTo(
            String.format(
                "invalid code owner config file '/OWNERS' (project = %s, branch = master):\n"
                    + "  invalid line: @example.com\n"
                    + "  invalid line: admin@\n"
                    + "  invalid line: admin@example@com",
                project));
  }

  @Test
  public void cannotParseCodeOwnerConfigWithInvalidLines() throws Exception {
    CodeOwnerConfigParseException exception =
        assertThrows(
            CodeOwnerConfigParseException.class,
            () ->
                codeOwnerConfigParser.parse(
                    TEST_REVISION,
                    CodeOwnerConfig.Key.create(project, "master", "/"),
                    getCodeOwnerConfig(EMAIL_1, "INVALID", "NOT_AN_EMAIL", EMAIL_2)));
    assertThat(exception.getFullMessage(FindOwnersBackend.CODE_OWNER_CONFIG_FILE_NAME))
        .isEqualTo(
            String.format(
                "invalid code owner config file '/OWNERS' (project = %s, branch = master):\n"
                    + "  invalid line: INVALID\n"
                    + "  invalid line: NOT_AN_EMAIL",
                project));
  }

  @Test
  public void codeOwnerConfigWithInlineComments() throws Exception {
    assertParseAndFormat(
        getCodeOwnerConfig(EMAIL_1, EMAIL_2 + " # some comment", EMAIL_3),
        codeOwnerConfig ->
            assertThat(codeOwnerConfig)
                .hasCodeOwnerSetsThat()
                .onlyElement()
                .hasCodeOwnersEmailsThat()
                .containsExactly(EMAIL_1, EMAIL_2, EMAIL_3),
        getCodeOwnerConfig(EMAIL_1, EMAIL_2, EMAIL_3));
  }

  @Test
  public void codeOwnerConfigWithNonSortedEmails() throws Exception {
    assertParseAndFormat(
        String.join("\n", EMAIL_3, EMAIL_2, EMAIL_1) + "\n",
        codeOwnerConfig ->
            assertThat(codeOwnerConfig)
                .hasCodeOwnerSetsThat()
                .onlyElement()
                .hasCodeOwnersEmailsThat()
                .containsExactly(EMAIL_1, EMAIL_2, EMAIL_3),
        getCodeOwnerConfig(EMAIL_1, EMAIL_2, EMAIL_3));
  }

  @Test
  public void setNoParentCanBeSetMultipleTimes() throws Exception {
    assertParseAndFormat(
        getCodeOwnerConfig(true, CodeOwnerSet.createWithoutPathExpressions(EMAIL_1))
            + "\nset noparent\nset noparent",
        codeOwnerConfig -> {
          assertThat(codeOwnerConfig).hasIgnoreParentCodeOwnersThat().isTrue();
          assertThat(codeOwnerConfig)
              .hasCodeOwnerSetsThat()
              .onlyElement()
              .hasCodeOwnersEmailsThat()
              .containsExactly(EMAIL_1);
        },
        getCodeOwnerConfig(true, CodeOwnerSet.createWithoutPathExpressions(EMAIL_1)));
  }

  @Test
  public void codeOwnerSetWithGlobalCodeOwnersIsReturnedFirst() throws Exception {
    CodeOwnerSet perFileCodeOwnerSet =
        CodeOwnerSet.builder().addPathExpression("foo").addCodeOwnerEmail(EMAIL_2).build();
    CodeOwnerSet globalCodeOwnerSet = CodeOwnerSet.createWithoutPathExpressions(EMAIL_1, EMAIL_3);
    assertParseAndFormat(
        getCodeOwnerConfig(false, perFileCodeOwnerSet, globalCodeOwnerSet),
        codeOwnerConfig -> {
          assertThat(codeOwnerConfig)
              .hasCodeOwnerSetsThat()
              .containsExactly(globalCodeOwnerSet, perFileCodeOwnerSet)
              .inOrder();
        },
        getCodeOwnerConfig(false, globalCodeOwnerSet, perFileCodeOwnerSet));
  }

  @Test
  public void setMultipleCodeOwnerSetsWithoutPathExpressions() throws Exception {
    CodeOwnerSet codeOwnerSet1 = CodeOwnerSet.createWithoutPathExpressions(EMAIL_1, EMAIL_3);
    CodeOwnerSet codeOwnerSet2 = CodeOwnerSet.createWithoutPathExpressions(EMAIL_2);
    assertParseAndFormat(
        getCodeOwnerConfig(false, codeOwnerSet1, codeOwnerSet2),
        codeOwnerConfig -> {
          assertThat(codeOwnerConfig)
              .hasCodeOwnerSetsThat()
              .onlyElement()
              .hasCodeOwnersEmailsThat()
              .containsExactly(EMAIL_1, EMAIL_2, EMAIL_3);
        },
        // The code owner sets without path expressions are merged into one code owner set.
        getCodeOwnerConfig(
            false, CodeOwnerSet.createWithoutPathExpressions(EMAIL_1, EMAIL_2, EMAIL_3)));
  }

  @Test
  public void setNoParentForPathExpressions() throws Exception {
    CodeOwnerSet codeOwnerSet =
        CodeOwnerSet.builder()
            .setIgnoreGlobalAndParentCodeOwners()
            .addPathExpression("*.md")
            .addPathExpression("foo")
            .addCodeOwnerEmail(EMAIL_1)
            .addCodeOwnerEmail(EMAIL_2)
            .build();
    assertParseAndFormat(
        getCodeOwnerConfig(false, codeOwnerSet),
        codeOwnerConfig -> {
          // we expect 2 code owner sets:
          // 1. code owner set for line "per-file *.md,foo=set noparent"
          // 2. code owner set for line "per-file *.md,foo=admin@example.com,jdoe@example.com"
          assertThat(codeOwnerConfig).hasCodeOwnerSetsThat().hasSize(2);

          // 1. assert code owner set for line "per-file *.md,foo=set noparent"
          CodeOwnerSetSubject codeOwnerSet1Subject =
              assertThat(codeOwnerConfig).hasCodeOwnerSetsThat().element(0);
          codeOwnerSet1Subject.hasIgnoreGlobalAndParentCodeOwnersThat().isTrue();
          codeOwnerSet1Subject.hasPathExpressionsThat().containsExactly("*.md", "foo");
          codeOwnerSet1Subject.hasCodeOwnersThat().isEmpty();

          // 2. assert code owner set for line "per-file
          // *.md,foo=admin@example.com,jdoe@example.com"
          CodeOwnerSetSubject codeOwnerSet2Subject =
              assertThat(codeOwnerConfig).hasCodeOwnerSetsThat().element(1);
          codeOwnerSet2Subject.hasIgnoreGlobalAndParentCodeOwnersThat().isFalse();
          codeOwnerSet2Subject.hasPathExpressionsThat().containsExactly("*.md", "foo");
          codeOwnerSet2Subject.hasCodeOwnersEmailsThat().containsExactly(EMAIL_1, EMAIL_2);
        });
  }

  @Test
  public void importCodeOwnerConfigFromSameProjectAndBranch() throws Exception {
    Path path = Paths.get("/foo/bar/OWNERS");
    CodeOwnerConfigReference codeOwnerConfigReference =
        CodeOwnerConfigReference.builder(CodeOwnerConfigImportMode.ALL, path).build();
    assertParseAndFormat(
        getCodeOwnerConfig(codeOwnerConfigReference),
        codeOwnerConfig -> {
          CodeOwnerConfigReferenceSubject codeOwnerConfigReferenceSubject =
              assertThat(codeOwnerConfig).hasImportsThat().onlyElement();
          codeOwnerConfigReferenceSubject.hasProjectThat().isEmpty();
          codeOwnerConfigReferenceSubject.hasBranchThat().isEmpty();
          codeOwnerConfigReferenceSubject.hasFilePathThat().isEqualTo(path);
        });
  }

  @Test
  public void importCodeOwnerConfigFromOtherProject() throws Exception {
    String otherProject = "otherProject";
    Path path = Paths.get("/foo/bar/OWNERS");
    CodeOwnerConfigReference codeOwnerConfigReference =
        CodeOwnerConfigReference.builder(CodeOwnerConfigImportMode.ALL, path)
            .setProject(Project.nameKey(otherProject))
            .build();
    assertParseAndFormat(
        getCodeOwnerConfig(codeOwnerConfigReference),
        codeOwnerConfig -> {
          CodeOwnerConfigReferenceSubject codeOwnerConfigReferenceSubject =
              assertThat(codeOwnerConfig).hasImportsThat().onlyElement();
          codeOwnerConfigReferenceSubject.hasProjectThat().value().isEqualTo(otherProject);
          codeOwnerConfigReferenceSubject.hasFilePathThat().isEqualTo(path);
        });
  }

  @Test
  public void cannotFormatCodeOwnerConfigWithImportThatSpecifiesBranchWithoutProject()
      throws Exception {
    Path path = Paths.get("/foo/bar/OWNERS");
    CodeOwnerConfigReference codeOwnerConfigReference =
        CodeOwnerConfigReference.builder(CodeOwnerConfigImportMode.ALL, path)
            .setBranch("refs/heads/foo")
            .build();
    CodeOwnerConfig codeOwnerConfig =
        CodeOwnerConfig.builder(
                CodeOwnerConfig.Key.create(Project.nameKey("project"), "master", "/"),
                TEST_REVISION)
            .addImport(codeOwnerConfigReference)
            .build();
    IllegalStateException exception =
        assertThrows(
            IllegalStateException.class,
            () -> codeOwnerConfigParser.formatAsString(codeOwnerConfig));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(
            String.format(
                "project is required if branch is specified: %s", codeOwnerConfigReference));
  }

  @Test
  public void importCodeOwnerConfigFromOtherBranch_fullName() throws Exception {
    testImportCodeOwnerConfigFromOtherBranch("refs/heads/foo");
  }

  @Test
  public void importCodeOwnerConfigFromOtherBranch_shortName() throws Exception {
    testImportCodeOwnerConfigFromOtherBranch("foo");
  }

  private void testImportCodeOwnerConfigFromOtherBranch(String branchName) throws Exception {
    Path path = Paths.get("/foo/bar/OWNERS");
    CodeOwnerConfigReference codeOwnerConfigReference =
        CodeOwnerConfigReference.builder(CodeOwnerConfigImportMode.ALL, path)
            .setProject(project)
            .setBranch(branchName)
            .build();
    assertParseAndFormat(
        getCodeOwnerConfig(codeOwnerConfigReference),
        codeOwnerConfig -> {
          CodeOwnerConfigReferenceSubject codeOwnerConfigReferenceSubject =
              assertThat(codeOwnerConfig).hasImportsThat().onlyElement();
          codeOwnerConfigReferenceSubject.hasProjectThat().value().isEqualTo(project.get());
          codeOwnerConfigReferenceSubject
              .hasBranchThat()
              .value()
              .isEqualTo(RefNames.fullName(branchName));
          codeOwnerConfigReferenceSubject.hasFilePathThat().isEqualTo(path);
        });
  }

  @Test
  public void importCodeOwnerConfigWithImportModeAll() throws Exception {
    CodeOwnerConfigReference codeOwnerConfigReference =
        CodeOwnerConfigReference.builder(CodeOwnerConfigImportMode.ALL, "/foo/bar/OWNERS").build();
    assertParseAndFormat(
        getCodeOwnerConfig(codeOwnerConfigReference),
        codeOwnerConfig -> {
          assertThat(codeOwnerConfig)
              .hasImportsThat()
              .onlyElement()
              .hasImportModeThat()
              .isEqualTo(CodeOwnerConfigImportMode.ALL);
        });
  }

  @Test
  public void importCodeOwnerConfigWithImportModeGlobalCodeOwnerSetsOnly() throws Exception {
    CodeOwnerConfigReference codeOwnerConfigReference =
        CodeOwnerConfigReference.builder(
                CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, "/foo/bar/OWNERS")
            .build();
    assertParseAndFormat(
        getCodeOwnerConfig(codeOwnerConfigReference),
        codeOwnerConfig -> {
          assertThat(codeOwnerConfig)
              .hasImportsThat()
              .onlyElement()
              .hasImportModeThat()
              .isEqualTo(CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY);
        });
  }

  @Test
  public void importMultipleCodeOwnerConfigs() throws Exception {
    Path path1 = Paths.get("/foo/bar/OWNERS");
    CodeOwnerConfigReference codeOwnerConfigReference1 =
        CodeOwnerConfigReference.builder(CodeOwnerConfigImportMode.ALL, path1).build();
    Path path2 = Paths.get("/foo/baz/OWNERS");
    CodeOwnerConfigReference codeOwnerConfigReference2 =
        CodeOwnerConfigReference.builder(
                CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, path2)
            .build();
    assertParseAndFormat(
        getCodeOwnerConfig(codeOwnerConfigReference1, codeOwnerConfigReference2),
        codeOwnerConfig -> {
          assertThat(codeOwnerConfig).hasImportsThat().hasSize(2);
          assertThat(codeOwnerConfig)
              .hasImportsThat()
              .element(0)
              .hasFilePathThat()
              .isEqualTo(path1);
          assertThat(codeOwnerConfig)
              .hasImportsThat()
              .element(1)
              .hasFilePathThat()
              .isEqualTo(path2);
        });
  }

  @Test
  public void perFileCodeOwnerConfigImportFromSameProjectAndBranch() throws Exception {
    Path path = Paths.get("/foo/bar/OWNERS");
    CodeOwnerConfigReference codeOwnerConfigReference =
        CodeOwnerConfigReference.builder(
                CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, path)
            .build();
    CodeOwnerConfig codeOwnerConfig =
        CodeOwnerConfig.builder(CodeOwnerConfig.Key.create(project, "master", "/"), TEST_REVISION)
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression("foo")
                    .addImport(codeOwnerConfigReference)
                    .build())
            .build();

    assertParseAndFormat(
        getCodeOwnerConfig(codeOwnerConfig),
        parsedCodeOwnerConfig -> {
          CodeOwnerSetSubject codeOwnerSetSubject =
              assertThat(parsedCodeOwnerConfig).hasCodeOwnerSetsThat().onlyElement();
          codeOwnerSetSubject.hasPathExpressionsThat().containsExactly("foo");
          CodeOwnerConfigReferenceSubject codeOwnerConfigReferenceSubject =
              codeOwnerSetSubject.hasImportsThat().onlyElement();
          codeOwnerConfigReferenceSubject.hasProjectThat().isEmpty();
          codeOwnerConfigReferenceSubject.hasBranchThat().isEmpty();
          codeOwnerConfigReferenceSubject.hasFilePathThat().isEqualTo(path);
        });
  }

  @Test
  public void perFileCodeOwnerConfigImportFromOtherProject() throws Exception {
    String otherProject = "otherProject";
    Path path = Paths.get("/foo/bar/OWNERS");
    CodeOwnerConfigReference codeOwnerConfigReference =
        CodeOwnerConfigReference.builder(
                CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, path)
            .setProject(Project.nameKey(otherProject))
            .build();
    CodeOwnerConfig codeOwnerConfig =
        CodeOwnerConfig.builder(CodeOwnerConfig.Key.create(project, "master", "/"), TEST_REVISION)
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression("foo")
                    .addImport(codeOwnerConfigReference)
                    .build())
            .build();

    assertParseAndFormat(
        getCodeOwnerConfig(codeOwnerConfig),
        parsedCodeOwnerConfig -> {
          CodeOwnerSetSubject codeOwnerSetSubject =
              assertThat(parsedCodeOwnerConfig).hasCodeOwnerSetsThat().onlyElement();
          codeOwnerSetSubject.hasPathExpressionsThat().containsExactly("foo");
          CodeOwnerConfigReferenceSubject codeOwnerConfigReferenceSubject =
              codeOwnerSetSubject.hasImportsThat().onlyElement();
          codeOwnerConfigReferenceSubject.hasProjectThat().value().isEqualTo(otherProject);
          codeOwnerConfigReferenceSubject.hasFilePathThat().isEqualTo(path);
        });
  }

  @Test
  public void cannotFormatCodeOwnerConfigWithPerFileImportThatSpecifiesBranchWithoutProject()
      throws Exception {
    Path path = Paths.get("/foo/bar/OWNERS");
    CodeOwnerConfigReference codeOwnerConfigReference =
        CodeOwnerConfigReference.builder(
                CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, path)
            .setBranch("refs/heads/foo")
            .build();
    CodeOwnerConfig codeOwnerConfig =
        CodeOwnerConfig.builder(
                CodeOwnerConfig.Key.create(Project.nameKey("project"), "master", "/"),
                TEST_REVISION)
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression("foo")
                    .addImport(codeOwnerConfigReference)
                    .build())
            .build();
    IllegalStateException exception =
        assertThrows(
            IllegalStateException.class,
            () -> codeOwnerConfigParser.formatAsString(codeOwnerConfig));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(
            String.format(
                "project is required if branch is specified: %s", codeOwnerConfigReference));
  }

  @Test
  public void perFileImportOfCodeOwnerConfigFromOtherBranch_fullName() throws Exception {
    testPerFileImportOfCodeOwnerConfigFromOtherBranch("refs/heads/foo");
  }

  @Test
  public void perFileImportOfCodeOwnerConfigFromOtherBranch_shortName() throws Exception {
    testPerFileImportOfCodeOwnerConfigFromOtherBranch("foo");
  }

  private void testPerFileImportOfCodeOwnerConfigFromOtherBranch(String branchName)
      throws Exception {
    Path path = Paths.get("/foo/bar/OWNERS");
    CodeOwnerConfigReference codeOwnerConfigReference =
        CodeOwnerConfigReference.builder(
                CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, path)
            .setProject(project)
            .setBranch(branchName)
            .build();
    CodeOwnerConfig codeOwnerConfig =
        CodeOwnerConfig.builder(
                CodeOwnerConfig.Key.create(Project.nameKey("project"), "master", "/"),
                TEST_REVISION)
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression("foo")
                    .addImport(codeOwnerConfigReference)
                    .build())
            .build();
    assertParseAndFormat(
        getCodeOwnerConfig(codeOwnerConfig),
        parsedCodeOwnerConfig -> {
          CodeOwnerSetSubject codeOwnerSetSubject =
              assertThat(parsedCodeOwnerConfig).hasCodeOwnerSetsThat().onlyElement();
          codeOwnerSetSubject.hasPathExpressionsThat().containsExactly("foo");
          CodeOwnerConfigReferenceSubject codeOwnerConfigReferenceSubject =
              codeOwnerSetSubject.hasImportsThat().onlyElement();
          codeOwnerConfigReferenceSubject.hasProjectThat().value().isEqualTo(project.get());
          codeOwnerConfigReferenceSubject
              .hasBranchThat()
              .value()
              .isEqualTo(RefNames.fullName(branchName));
          codeOwnerConfigReferenceSubject.hasFilePathThat().isEqualTo(path);
        });
  }

  @Test
  public void perFileCodeOwnerConfigImportCannotHaveImportModeAll() throws Exception {
    // The 'include' keyword is used to for imports with import mode ALL, but it is not supported
    // for per-file imports. Trying to use it anyway should result in a proper error message.
    String line = "per-file foo=include /foo/bar/OWNERS";
    IllegalStateException exception =
        assertThrows(
            IllegalStateException.class,
            () ->
                codeOwnerConfigParser.parse(
                    TEST_REVISION, CodeOwnerConfig.Key.create(project, "master", "/"), line));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(
            String.format(
                "import mode %s is unsupported for per file import: %s",
                CodeOwnerConfigImportMode.ALL.name(), line));
  }

  @Test
  public void cannotParseCodeOwnerConfigWithPerFileLineThatHasAnInvalidImportKeyword()
      throws Exception {
    // The 'import' keyword doesn't exist
    String invalidLine = "per-file foo=import /foo/bar/OWNERS";

    CodeOwnerConfigParseException exception =
        assertThrows(
            CodeOwnerConfigParseException.class,
            () ->
                codeOwnerConfigParser.parse(
                    TEST_REVISION,
                    CodeOwnerConfig.Key.create(project, "master", "/"),
                    invalidLine));
    assertThat(exception.getFullMessage(FindOwnersBackend.CODE_OWNER_CONFIG_FILE_NAME))
        .isEqualTo(
            String.format(
                "invalid code owner config file '/OWNERS' (project = %s, branch = master):\n"
                    + "  invalid line: %s",
                project, invalidLine));
  }

  @Test
  public void perFileCodeOwnerConfigImportWithImportModeGlobalCodeOwnerSetsOnly() throws Exception {
    CodeOwnerConfigReference codeOwnerConfigReference =
        CodeOwnerConfigReference.builder(
                CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY, "/foo/bar/OWNERS")
            .build();
    CodeOwnerConfig codeOwnerConfig =
        CodeOwnerConfig.builder(CodeOwnerConfig.Key.create(project, "master", "/"), TEST_REVISION)
            .addCodeOwnerSet(
                CodeOwnerSet.builder()
                    .addPathExpression("foo")
                    .addImport(codeOwnerConfigReference)
                    .build())
            .build();

    assertParseAndFormat(
        getCodeOwnerConfig(codeOwnerConfig),
        parsedCodeOwnerConfig -> {
          assertThat(parsedCodeOwnerConfig)
              .hasCodeOwnerSetsThat()
              .onlyElement()
              .hasImportsThat()
              .onlyElement()
              .hasImportModeThat()
              .isEqualTo(CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY);
        });
  }

  @Test
  public void replaceEmail_contentCannotBeNull() throws Exception {
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                FindOwnersCodeOwnerConfigParser.replaceEmail(
                    /* codeOwnerConfigFileContent= */ null, admin.email(), user.email()));
    assertThat(npe).hasMessageThat().isEqualTo("codeOwnerConfigFileContent");
  }

  @Test
  public void replaceEmail_oldEmailCannotBeNull() throws Exception {
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                FindOwnersCodeOwnerConfigParser.replaceEmail(
                    "content", /* oldEmail= */ null, user.email()));
    assertThat(npe).hasMessageThat().isEqualTo("oldEmail");
  }

  @Test
  public void replaceEmail_newEmailCannotBeNull() throws Exception {
    NullPointerException npe =
        assertThrows(
            NullPointerException.class,
            () ->
                FindOwnersCodeOwnerConfigParser.replaceEmail(
                    "content", admin.email(), /* newEmail= */ null));
    assertThat(npe).hasMessageThat().isEqualTo("newEmail");
  }

  @Test
  public void replaceEmail() throws Exception {
    String oldEmail = "old@example.com";
    String newEmail = "new@example.com";

    // In the following test lines '${email} is used as placefolder for the email that we expect to
    // be replaced.
    String[] testLines = {
      // line = email
      "${email}",
      // line = email with leading whitespace
      " ${email}",
      // line = email with trailing whitespace
      "${email} ",
      // line = email with leading and trailing whitespace
      " ${email} ",
      // line = email with comment
      "${email}# comment",
      // line = email with trailing whitespace and comment
      "${email} # comment",
      // line = email with leading whitespace and comment
      " ${email}# comment",
      // line = email with leading and trailing whitespace and comment
      " ${email} # comment",
      // line = email that ends with oldEmail
      "foo" + oldEmail,
      // line = email that starts with oldEmail
      oldEmail + "bar",
      // line = email that contains oldEmail
      "foo" + oldEmail + "bar",
      // line = email that contains oldEmail with leading and trailing whitespace
      " foo" + oldEmail + "bar ",
      // line = email that contains oldEmail with leading and trailing whitespace and comment
      " foo" + oldEmail + "bar # comment",
      // email in comment
      "foo@example.com # ${email}",
      // email in comment that contains oldEmail
      "foo@example.com # foo" + oldEmail + "bar",
      // per-file line with email
      "per-file *.md=${email}",
      // per-file line with email and whitespace
      "per-file *.md = ${email} ",
      // per-file line with multiple emails and old email at first position
      "per-file *.md=${email},foo@example.com,bar@example.com",
      // per-file line with multiple emails and old email at middle position
      "per-file *.md=foo@example.com,${email},bar@example.com",
      // per-file line with multiple emails and old email at last position
      "per-file *.md=foo@example.com,bar@example.com,${email}",
      // per-file line with multiple emails and old email at last position and comment
      "per-file *.md=foo@example.com,bar@example.com,${email}# comment",
      // per-file line with multiple emails and old email at last position and comment with
      // whitespace
      "per-file *.md = foo@example.com, bar@example.com , ${email} # comment",
      // per-file line with multiple emails and old email appearing multiple times
      "per-file *.md=${email},${email}",
      "per-file *.md=${email},${email},${email}",
      "per-file *.md=${email},foo@example.com,${email},bar@example.com,${email}",
      // per-file line with multiple emails and old email appearing multiple times and comment
      "per-file *.md=${email},foo@example.com,${email},bar@example.com,${email}# comment",
      // per-file line with multiple emails and old email appearing multiple times and comment and
      // whitespace
      "per-file *.md= ${email} , foo@example.com , ${email} , bar@example.com , ${email} # comment",
      // per-file line with email that contains old email
      "per-file *.md=for" + oldEmail + "bar",
      // per-file line with multiple emails and one email that contains the old email
      "per-file *.md=for" + oldEmail + "bar,${email}",
    };

    for (String testLine : testLines) {
      String content = testLine.replaceAll(Pattern.quote("${email}"), oldEmail);
      String expectedContent = testLine.replaceAll(Pattern.quote("${email}"), newEmail);
      assertWithMessage(testLine)
          .that(FindOwnersCodeOwnerConfigParser.replaceEmail(content, oldEmail, newEmail))
          .isEqualTo(expectedContent);
    }

    // join all test lines and replace email in all of them at once
    String testContent = Joiner.on("\n").join(testLines);
    String content = testContent.replaceAll(Pattern.quote("${email}"), oldEmail);
    String expectedContent = testContent.replaceAll(Pattern.quote("${email}"), newEmail);
    assertThat(FindOwnersCodeOwnerConfigParser.replaceEmail(content, oldEmail, newEmail))
        .isEqualTo(expectedContent);

    // test that trailing new line is preserved
    assertThat(FindOwnersCodeOwnerConfigParser.replaceEmail(content + "\n", oldEmail, newEmail))
        .isEqualTo(expectedContent + "\n");
  }
}
