// Copyright (C) 2020 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.plugins.codeowners.backend;

import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.plugins.codeowners.testing.CodeOwnerConfigSubject.assertThat;
import static com.google.gerrit.plugins.codeowners.testing.CodeOwnerConfigSubject.assertThatOptional;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;

import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.plugins.codeowners.acceptance.AbstractCodeOwnersTest;
import com.google.gerrit.plugins.codeowners.testing.CodeOwnerConfigSubject;
import com.google.gerrit.plugins.codeowners.testing.backend.TestCodeOwnerConfigStorage;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.junit.Before;
import org.junit.Test;

/** Tests for {@link CodeOwnerConfigFile}. */
public class CodeOwnerConfigFileTest extends AbstractCodeOwnersTest {
  private static final String CODE_OWNER_CONFIG_FILE_NAME = "CODE_OWNER_CONFIG";
  private static final CodeOwnerConfigParser CODE_OWNER_CONFIG_PARSER =
      new TestCodeOwnerConfigParser();

  @Inject private ProjectOperations projectOperations;
  @Inject private MetaDataUpdate.Server metaDataUpdateServer;

  private TestCodeOwnerConfigStorage testCodeOwnerConfigStorage;

  @Before
  public void setUpCodeOwnersPlugin() throws Exception {
    testCodeOwnerConfigStorage =
        plugin
            .getSysInjector()
            .getInstance(TestCodeOwnerConfigStorage.Factory.class)
            .create(CODE_OWNER_CONFIG_FILE_NAME, CODE_OWNER_CONFIG_PARSER);
  }

  @Test
  public void loadNonExistingCodeOwnerConfigFile() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey =
        CodeOwnerConfig.Key.create(project, "master", "/non-existing/");
    CodeOwnerConfigFile codeOwnerConfigFile = loadCodeOwnerConfig(codeOwnerConfigKey);
    assertThatOptional(codeOwnerConfigFile.getLoadedCodeOwnerConfig()).isEmpty();
  }

  @Test
  public void loadCodeOwnerConfigFileFromNonExistingBranch() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey =
        CodeOwnerConfig.Key.create(project, "non-existing", "/");
    CodeOwnerConfigFile codeOwnerConfigFile = loadCodeOwnerConfig(codeOwnerConfigKey);
    assertThatOptional(codeOwnerConfigFile.getLoadedCodeOwnerConfig()).isEmpty();
  }

  @Test
  public void loadEmptyCodeOwnerConfigFile() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey = CodeOwnerConfig.Key.create(project, "master", "/");
    testCodeOwnerConfigStorage.writeCodeOwnerConfig(codeOwnerConfigKey, b -> {});

    CodeOwnerConfigFile codeOwnerConfigFile = loadCodeOwnerConfig(codeOwnerConfigKey);
    CodeOwnerConfigSubject codeOwnerConfigSubject =
        assertThatOptional(codeOwnerConfigFile.getLoadedCodeOwnerConfig()).value();
    codeOwnerConfigSubject.hasCodeOwnerSetsThat().isEmpty();
    codeOwnerConfigSubject
        .hasRevisionThat()
        .isEqualTo(projectOperations.project(project).getHead("master"));
  }

  @Test
  public void loadCodeOwnerConfigFile() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey = CodeOwnerConfig.Key.create(project, "master", "/");
    testCodeOwnerConfigStorage.writeCodeOwnerConfig(
        codeOwnerConfigKey,
        b ->
            b.setIgnoreParentCodeOwners()
                .addCodeOwnerSet(CodeOwnerSet.createWithoutPathExpressions(admin.email())));

    CodeOwnerConfigFile codeOwnerConfigFile = loadCodeOwnerConfig(codeOwnerConfigKey);
    CodeOwnerConfigSubject codeOwnerConfigSubject =
        assertThatOptional(codeOwnerConfigFile.getLoadedCodeOwnerConfig()).value();
    codeOwnerConfigSubject.hasIgnoreParentCodeOwnersThat().isTrue();
    codeOwnerConfigSubject
        .hasCodeOwnerSetsThat()
        .onlyElement()
        .hasCodeOwnersEmailsThat()
        .containsExactly(admin.email());
    codeOwnerConfigSubject
        .hasRevisionThat()
        .isEqualTo(projectOperations.project(project).getHead("master"));
  }

  @Test
  public void loadCodeOwnerConfigFileFromOldRevision() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey = CodeOwnerConfig.Key.create(project, "master", "/");
    ObjectId revision1 =
        testCodeOwnerConfigStorage
            .writeCodeOwnerConfig(
                codeOwnerConfigKey,
                b ->
                    b.setIgnoreParentCodeOwners()
                        .addCodeOwnerSet(CodeOwnerSet.createWithoutPathExpressions(admin.email())))
            .revision();

    // update the code owner config, which creates a new revision
    ObjectId revision2 =
        testCodeOwnerConfigStorage
            .writeCodeOwnerConfig(codeOwnerConfigKey, b -> b.setIgnoreParentCodeOwners(false))
            .revision();
    assertThat(revision1).isNotEqualTo(revision2);

    CodeOwnerConfigFile codeOwnerConfigFile = loadCodeOwnerConfig(codeOwnerConfigKey, revision1);
    CodeOwnerConfigSubject codeOwnerConfigSubject =
        assertThatOptional(codeOwnerConfigFile.getLoadedCodeOwnerConfig()).value();
    codeOwnerConfigSubject.hasIgnoreParentCodeOwnersThat().isTrue();
    codeOwnerConfigSubject.hasRevisionThat().isEqualTo(revision1);
  }

  @Test
  public void cannotLoadCodeOwnerConfigFileFromNonExistingRevision() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey = CodeOwnerConfig.Key.create(project, "master", "/");
    assertThrows(
        MissingObjectException.class,
        () ->
            loadCodeOwnerConfig(
                codeOwnerConfigKey,
                ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef")));
  }

  @Test
  public void loadCodeOwnerConfigFileWithCustomFileName() throws Exception {
    String customFileName = "FOO_CODE_OWNERS";
    CodeOwnerConfig.Key codeOwnerConfigKey =
        CodeOwnerConfig.Key.create(project, "master", "/", customFileName);
    testCodeOwnerConfigStorage.writeCodeOwnerConfig(
        codeOwnerConfigKey,
        b ->
            b.setIgnoreParentCodeOwners()
                .addCodeOwnerSet(CodeOwnerSet.createWithoutPathExpressions(admin.email())));

    CodeOwnerConfigFile codeOwnerConfigFile = loadCodeOwnerConfig(codeOwnerConfigKey);
    assertThatOptional(codeOwnerConfigFile.getLoadedCodeOwnerConfig())
        .value()
        .hasIgnoreParentCodeOwnersThat()
        .isTrue();
    assertThat(codeOwnerConfigFile.getLoadedCodeOwnerConfig().get())
        .hasCodeOwnerSetsThat()
        .onlyElement()
        .hasCodeOwnersEmailsThat()
        .containsExactly(admin.email());
  }

  @Test
  public void createCodeOwnerConfigFile() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey =
        CodeOwnerConfig.Key.create(project, "master", "/foo/bar/");
    try (Repository repo = repoManager.openRepository(project);
        MetaDataUpdate metaDataUpdate = metaDataUpdateServer.create(project)) {
      CodeOwnerConfigFile codeOwnerConfigFile = loadCodeOwnerConfig(codeOwnerConfigKey);

      // Check that the code owner config doesn't exist yet.
      assertThatOptional(codeOwnerConfigFile.getLoadedCodeOwnerConfig()).isEmpty();
      assertThatOptional(testCodeOwnerConfigStorage.readCodeOwnerConfig(codeOwnerConfigKey))
          .isEmpty();

      // Remember head so that we can check that the branch is changed.
      RevCommit oldHead = getHead(repo, codeOwnerConfigKey.ref());

      // Create the code owner config.
      codeOwnerConfigFile.setCodeOwnerConfigUpdate(
          CodeOwnerConfigUpdate.builder()
              .setIgnoreParentCodeOwners(true)
              .setCodeOwnerSetsModification(
                  CodeOwnerSetModification.set(
                      CodeOwnerSet.createWithoutPathExpressions(admin.email())))
              .build());
      codeOwnerConfigFile.commit(metaDataUpdate);

      RevCommit newHead = getHead(repo, codeOwnerConfigKey.ref());

      // Check that the loaded code owner config was updated.
      CodeOwnerConfigSubject loadedCodeOwnerConfigSubject =
          assertThatOptional(codeOwnerConfigFile.getLoadedCodeOwnerConfig()).value();
      loadedCodeOwnerConfigSubject.hasIgnoreParentCodeOwnersThat().isTrue();
      loadedCodeOwnerConfigSubject
          .hasCodeOwnerSetsThat()
          .onlyElement()
          .hasCodeOwnersEmailsThat()
          .containsExactly(admin.email());
      loadedCodeOwnerConfigSubject.hasRevisionThat().isEqualTo(newHead);

      // Check that the code owner config was created in the repository.
      Optional<CodeOwnerConfig> codeOwnerConfigInRepo =
          testCodeOwnerConfigStorage.readCodeOwnerConfig(codeOwnerConfigKey);
      CodeOwnerConfigSubject codeOwnerConfigInRepoSubject =
          assertThatOptional(codeOwnerConfigInRepo).value();
      codeOwnerConfigInRepoSubject.hasIgnoreParentCodeOwnersThat().isTrue();
      codeOwnerConfigInRepoSubject
          .hasCodeOwnerSetsThat()
          .onlyElement()
          .hasCodeOwnersEmailsThat()
          .containsExactly(admin.email());

      // Check that the branch was changed.
      assertThat(oldHead).isNotEqualTo(newHead);
    }
  }

  @Test
  public void codeOwnerConfigFileIsNotCreatedIfNoCodeOwnerConfigUpdateSpecified() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey =
        CodeOwnerConfig.Key.create(project, "master", "/foo/bar/");
    try (Repository repo = repoManager.openRepository(project);
        MetaDataUpdate metaDataUpdate = metaDataUpdateServer.create(project)) {
      CodeOwnerConfigFile codeOwnerConfigFile = loadCodeOwnerConfig(codeOwnerConfigKey);

      // Check that the code owner config doesn't exist yet.
      assertThatOptional(codeOwnerConfigFile.getLoadedCodeOwnerConfig()).isEmpty();
      assertThatOptional(testCodeOwnerConfigStorage.readCodeOwnerConfig(codeOwnerConfigKey))
          .isEmpty();

      // Remember head so that we can check that the branch doesn't change.
      RevCommit head = getHead(repo, codeOwnerConfigKey.ref());

      // Try to create the code owner config without setting a code owner config update.
      codeOwnerConfigFile.commit(metaDataUpdate);

      // Check that the loaded code owner config was not created.
      assertThatOptional(codeOwnerConfigFile.getLoadedCodeOwnerConfig()).isEmpty();

      // Check that no code owner config was created in the repository.
      Optional<CodeOwnerConfig> codeOwnerConfigInRepo =
          testCodeOwnerConfigStorage.readCodeOwnerConfig(codeOwnerConfigKey);
      assertThatOptional(codeOwnerConfigInRepo).isEmpty();

      // Check that the branch didn't change.
      assertThat(head).isEqualTo(getHead(repo, codeOwnerConfigKey.ref()));
    }
  }

  @Test
  public void codeOwnerConfigFileIsNotCreatedIfEmpty() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey =
        CodeOwnerConfig.Key.create(project, "master", "/foo/bar/");
    try (Repository repo = repoManager.openRepository(project);
        MetaDataUpdate metaDataUpdate = metaDataUpdateServer.create(project)) {
      CodeOwnerConfigFile codeOwnerConfigFile = loadCodeOwnerConfig(codeOwnerConfigKey);

      // Check that the code owner config doesn't exist yet.
      assertThatOptional(codeOwnerConfigFile.getLoadedCodeOwnerConfig()).isEmpty();
      assertThatOptional(testCodeOwnerConfigStorage.readCodeOwnerConfig(codeOwnerConfigKey))
          .isEmpty();

      // Remember head so that we can check that the branch doesn't change.
      RevCommit head = getHead(repo, codeOwnerConfigKey.ref());

      // Try to create the code owner config without specifying code owners.
      codeOwnerConfigFile.setCodeOwnerConfigUpdate(CodeOwnerConfigUpdate.builder().build());
      codeOwnerConfigFile.commit(metaDataUpdate);

      // Check that the loaded code owner config was not created.
      assertThatOptional(codeOwnerConfigFile.getLoadedCodeOwnerConfig()).isEmpty();

      // Check that no code owner config was created in the repository.
      Optional<CodeOwnerConfig> codeOwnerConfigInRepo =
          testCodeOwnerConfigStorage.readCodeOwnerConfig(codeOwnerConfigKey);
      assertThatOptional(codeOwnerConfigInRepo).isEmpty();

      // Check that the branch didn't change.
      assertThat(head).isEqualTo(getHead(repo, codeOwnerConfigKey.ref()));
    }
  }

  @Test
  public void cannotCreateCodeOwnerConfigFileInNonExistingBranch() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey =
        CodeOwnerConfig.Key.create(project, "non-existing", "/foo/bar/");
    try (Repository repo = repoManager.openRepository(project);
        MetaDataUpdate metaDataUpdate = metaDataUpdateServer.create(project)) {
      CodeOwnerConfigFile codeOwnerConfigFile = loadCodeOwnerConfig(codeOwnerConfigKey);

      // Check that the code owner config doesn't exist yet.
      assertThatOptional(codeOwnerConfigFile.getLoadedCodeOwnerConfig()).isEmpty();
      assertThatOptional(testCodeOwnerConfigStorage.readCodeOwnerConfig(codeOwnerConfigKey))
          .isEmpty();

      // Create the code owner config.
      String email = "admin@example.com";
      codeOwnerConfigFile.setCodeOwnerConfigUpdate(
          CodeOwnerConfigUpdate.builder()
              .setCodeOwnerSetsModification(
                  CodeOwnerSetModification.set(CodeOwnerSet.createWithoutPathExpressions(email)))
              .build());
      IllegalStateException exception =
          assertThrows(
              IllegalStateException.class, () -> codeOwnerConfigFile.commit(metaDataUpdate));
      assertThat(exception)
          .hasMessageThat()
          .isEqualTo(String.format("branch %s does not exist", codeOwnerConfigKey.ref()));

      // Check that the loaded code owner config is still empty.
      assertThatOptional(codeOwnerConfigFile.getLoadedCodeOwnerConfig()).isEmpty();

      // Check that the code owner config was not created in the repository.
      assertThatOptional(testCodeOwnerConfigStorage.readCodeOwnerConfig(codeOwnerConfigKey))
          .isEmpty();

      // Check that the branch was not created.
      assertThat(repo.exactRef(codeOwnerConfigKey.ref())).isNull();
    }
  }

  @Test
  public void createCodeOwnerConfigFileWithCustomName() throws Exception {
    String customFileName = "FOO_CODE_OWNERS";
    CodeOwnerConfig.Key codeOwnerConfigKey =
        CodeOwnerConfig.Key.create(project, "master", "/foo/bar/", customFileName);
    try (Repository repo = repoManager.openRepository(project);
        MetaDataUpdate metaDataUpdate = metaDataUpdateServer.create(project)) {
      CodeOwnerConfigFile codeOwnerConfigFile = loadCodeOwnerConfig(codeOwnerConfigKey);

      // Check that the code owner config doesn't exist yet.
      assertThatOptional(codeOwnerConfigFile.getLoadedCodeOwnerConfig()).isEmpty();
      assertThatOptional(testCodeOwnerConfigStorage.readCodeOwnerConfig(codeOwnerConfigKey))
          .isEmpty();

      // Remember head so that we can check that the branch is changed.
      RevCommit head = getHead(repo, codeOwnerConfigKey.ref());

      // Create the code owner config.
      codeOwnerConfigFile.setCodeOwnerConfigUpdate(
          CodeOwnerConfigUpdate.builder()
              .setIgnoreParentCodeOwners(true)
              .setCodeOwnerSetsModification(
                  CodeOwnerSetModification.set(
                      CodeOwnerSet.createWithoutPathExpressions(admin.email())))
              .build());
      codeOwnerConfigFile.commit(metaDataUpdate);

      // Check that the loaded code owner config was updated.
      assertThatOptional(codeOwnerConfigFile.getLoadedCodeOwnerConfig())
          .value()
          .hasIgnoreParentCodeOwnersThat()
          .isTrue();
      assertThat(codeOwnerConfigFile.getLoadedCodeOwnerConfig().get())
          .hasCodeOwnerSetsThat()
          .onlyElement()
          .hasCodeOwnersEmailsThat()
          .containsExactly(admin.email());

      // Check that the code owner config was created in the repository.
      Optional<CodeOwnerConfig> codeOwnerConfigInRepo =
          testCodeOwnerConfigStorage.readCodeOwnerConfig(codeOwnerConfigKey);
      assertThatOptional(codeOwnerConfigInRepo).value().hasIgnoreParentCodeOwnersThat().isTrue();
      assertThatOptional(codeOwnerConfigInRepo)
          .value()
          .hasCodeOwnerSetsThat()
          .onlyElement()
          .hasCodeOwnersEmailsThat()
          .containsExactly(admin.email());

      // Check that the branch was changed.
      assertThat(head).isNotEqualTo(getHead(repo, codeOwnerConfigKey.ref()));
    }
  }

  @Test
  public void updateCodeOwnerConfigFile() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey = CodeOwnerConfig.Key.create(project, "master", "/");
    testCodeOwnerConfigStorage.writeCodeOwnerConfig(
        codeOwnerConfigKey,
        b -> b.addCodeOwnerSet(CodeOwnerSet.createWithoutPathExpressions(admin.email())));

    try (Repository repo = repoManager.openRepository(project);
        MetaDataUpdate metaDataUpdate = metaDataUpdateServer.create(project)) {
      CodeOwnerConfigFile codeOwnerConfigFile = loadCodeOwnerConfig(codeOwnerConfigKey);

      // Check that the code owner config exists.
      assertThatOptional(codeOwnerConfigFile.getLoadedCodeOwnerConfig()).isPresent();
      assertThatOptional(testCodeOwnerConfigStorage.readCodeOwnerConfig(codeOwnerConfigKey))
          .isPresent();

      // Remember head so that we can check that the branch is changed.
      RevCommit oldHead = getHead(repo, codeOwnerConfigKey.ref());

      // Update the code owner config.
      codeOwnerConfigFile.setCodeOwnerConfigUpdate(
          CodeOwnerConfigUpdate.builder()
              .setIgnoreParentCodeOwners(true)
              .setCodeOwnerSetsModification(CodeOwnerSetModification.addToOnlySet(user.email()))
              .build());

      codeOwnerConfigFile.commit(metaDataUpdate);

      RevCommit newHead = getHead(repo, codeOwnerConfigKey.ref());

      // Check that the loaded code owner config was updated.
      CodeOwnerConfigSubject loadedCodeOwnerConfigSubject =
          assertThatOptional(codeOwnerConfigFile.getLoadedCodeOwnerConfig()).value();
      loadedCodeOwnerConfigSubject.hasIgnoreParentCodeOwnersThat().isTrue();
      loadedCodeOwnerConfigSubject
          .hasCodeOwnerSetsThat()
          .onlyElement()
          .hasCodeOwnersEmailsThat()
          .containsExactly(admin.email(), user.email());
      loadedCodeOwnerConfigSubject.hasRevisionThat().isEqualTo(newHead);

      // Check that the code owner config was updated in the repository.
      Optional<CodeOwnerConfig> codeOwnerConfigInRepo =
          testCodeOwnerConfigStorage.readCodeOwnerConfig(codeOwnerConfigKey);
      CodeOwnerConfigSubject codeOwnerConfigInRepoSubject =
          assertThatOptional(codeOwnerConfigInRepo).value();
      codeOwnerConfigInRepoSubject.hasIgnoreParentCodeOwnersThat().isTrue();
      codeOwnerConfigInRepoSubject
          .hasCodeOwnerSetsThat()
          .onlyElement()
          .hasCodeOwnersEmailsThat()
          .containsExactly(admin.email(), user.email());

      // Check that the branch was changed.
      assertThat(oldHead).isNotEqualTo(newHead);
    }
  }

  @Test
  public void codeOwnerConfigFileIsNotUpdatedIfUpdateIsANoOp() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey = CodeOwnerConfig.Key.create(project, "master", "/");
    testCodeOwnerConfigStorage.writeCodeOwnerConfig(
        codeOwnerConfigKey,
        b -> b.addCodeOwnerSet(CodeOwnerSet.createWithoutPathExpressions(admin.email())));

    try (Repository repo = repoManager.openRepository(project);
        MetaDataUpdate metaDataUpdate = metaDataUpdateServer.create(project)) {
      CodeOwnerConfigFile codeOwnerConfigFile = loadCodeOwnerConfig(codeOwnerConfigKey);

      // Check that the code owner config exists.
      assertThatOptional(codeOwnerConfigFile.getLoadedCodeOwnerConfig()).isPresent();
      assertThatOptional(testCodeOwnerConfigStorage.readCodeOwnerConfig(codeOwnerConfigKey))
          .isPresent();

      // Remember head so that we can check that the branch doesn't change.
      RevCommit oldHead = getHead(repo, codeOwnerConfigKey.ref());

      // Update the code owner config without changing it.
      codeOwnerConfigFile.setCodeOwnerConfigUpdate(CodeOwnerConfigUpdate.builder().build());
      codeOwnerConfigFile.commit(metaDataUpdate);

      RevCommit newHead = getHead(repo, codeOwnerConfigKey.ref());

      // Check that the loaded code owner config didn't change.
      CodeOwnerConfigSubject loadedCodeOwnerConfigSubject =
          assertThatOptional(codeOwnerConfigFile.getLoadedCodeOwnerConfig()).value();
      loadedCodeOwnerConfigSubject
          .hasCodeOwnerSetsThat()
          .onlyElement()
          .hasCodeOwnersEmailsThat()
          .containsExactly(admin.email());
      loadedCodeOwnerConfigSubject.hasRevisionThat().isEqualTo(newHead);

      // Check that the code owner config in the repository didn't change.
      Optional<CodeOwnerConfig> codeOwnerConfigInRepo =
          testCodeOwnerConfigStorage.readCodeOwnerConfig(codeOwnerConfigKey);
      assertThatOptional(codeOwnerConfigInRepo)
          .value()
          .hasCodeOwnerSetsThat()
          .onlyElement()
          .hasCodeOwnersEmailsThat()
          .containsExactly(admin.email());

      // Check that the branch didn't change.
      assertThat(oldHead).isEqualTo(newHead);
    }
  }

  @Test
  public void updateCodeOwnerConfigFileSoThatItBecomesEmptyAndIsDeleted() throws Exception {
    CodeOwnerConfig.Key codeOwnerConfigKey = CodeOwnerConfig.Key.create(project, "master", "/");
    testCodeOwnerConfigStorage.writeCodeOwnerConfig(
        codeOwnerConfigKey,
        b -> b.addCodeOwnerSet(CodeOwnerSet.createWithoutPathExpressions(admin.email())));

    try (Repository repo = repoManager.openRepository(project);
        MetaDataUpdate metaDataUpdate = metaDataUpdateServer.create(project)) {
      CodeOwnerConfigFile codeOwnerConfigFile = loadCodeOwnerConfig(codeOwnerConfigKey);

      // Check that the code owner config exists.
      assertThatOptional(codeOwnerConfigFile.getLoadedCodeOwnerConfig()).isPresent();
      assertThatOptional(testCodeOwnerConfigStorage.readCodeOwnerConfig(codeOwnerConfigKey))
          .isPresent();

      // Remember head so that we can check that the branch is changed.
      RevCommit head = getHead(repo, codeOwnerConfigKey.ref());

      // Update the code owner config so that it becomes empty.
      codeOwnerConfigFile.setCodeOwnerConfigUpdate(
          CodeOwnerConfigUpdate.builder()
              .setCodeOwnerSetsModification(CodeOwnerSetModification.clear())
              .build());
      codeOwnerConfigFile.commit(metaDataUpdate);

      // Check that the loaded code owner config was unset.
      assertThatOptional(codeOwnerConfigFile.getLoadedCodeOwnerConfig()).isEmpty();

      // Check that the code owner config was deleted in the repository.
      assertThatOptional(testCodeOwnerConfigStorage.readCodeOwnerConfig(codeOwnerConfigKey))
          .isEmpty();

      // Check that the branch was changed.
      assertThat(head).isNotEqualTo(getHead(repo, codeOwnerConfigKey.ref()));
    }
  }

  private CodeOwnerConfigFile loadCodeOwnerConfig(CodeOwnerConfig.Key codeOwnerConfigKey)
      throws IOException, ConfigInvalidException {
    try (Repository repository = repoManager.openRepository(codeOwnerConfigKey.project())) {
      return CodeOwnerConfigFile.loadCurrent(
          CODE_OWNER_CONFIG_FILE_NAME, CODE_OWNER_CONFIG_PARSER, repository, codeOwnerConfigKey);
    }
  }

  private CodeOwnerConfigFile loadCodeOwnerConfig(
      CodeOwnerConfig.Key codeOwnerConfigKey, ObjectId revision)
      throws IOException, ConfigInvalidException {
    try (Repository repository = repoManager.openRepository(codeOwnerConfigKey.project());
        RevWalk revWalk = new RevWalk(repository)) {
      return CodeOwnerConfigFile.load(
          CODE_OWNER_CONFIG_FILE_NAME,
          CODE_OWNER_CONFIG_PARSER,
          revWalk,
          revision,
          codeOwnerConfigKey);
    }
  }

  private static class TestCodeOwnerConfigParser implements CodeOwnerConfigParser {
    private final Map<String, CodeOwnerConfig> codeOwnerConfigCache = new HashMap<>();

    @Override
    public CodeOwnerConfig parse(
        ObjectId revision, CodeOwnerConfig.Key codeOwnerConfigKey, String codeOwnerConfigAsString)
        throws IOException {
      if (codeOwnerConfigAsString.isEmpty()) {
        return CodeOwnerConfig.builder(codeOwnerConfigKey, revision).build();
      }

      return codeOwnerConfigCache
          .get(codeOwnerConfigAsString)
          .toBuilder()
          .setRevision(revision)
          .build();
    }

    @Override
    public String formatAsString(CodeOwnerConfig codeOwnerConfig) throws IOException {
      if (codeOwnerConfig.codeOwnerSets().isEmpty()) {
        return "";
      }

      String key = codeOwnerConfig.toString();
      codeOwnerConfigCache.put(key, codeOwnerConfig);
      return key;
    }
  }
}
