// 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.acceptance.api;

import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allow;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowCapability;
import static com.google.gerrit.plugins.codeowners.testing.CodeOwnerConfigSubject.assertThat;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;

import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Permission;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.plugins.codeowners.acceptance.AbstractCodeOwnersIT;
import com.google.gerrit.plugins.codeowners.api.RenameEmailInput;
import com.google.gerrit.plugins.codeowners.api.RenameEmailResultInfo;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfig;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfigFileUpdateScanner;
import com.google.gerrit.plugins.codeowners.restapi.RenameEmail;
import com.google.inject.Inject;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;

/**
 * Acceptance test for the {@link com.google.gerrit.plugins.codeowners.restapi.RenameEmail} REST
 * endpoint.
 *
 * <p>Further tests for the {@link com.google.gerrit.plugins.codeowners.restapi.RenameEmail} REST
 * endpoint that require using the REST API are implemented in {@link
 * com.google.gerrit.plugins.codeowners.acceptance.restapi.RenameEmailRestIT}.
 */
public class RenameEmailIT extends AbstractCodeOwnersIT {
  @Inject private AccountOperations accountOperations;
  @Inject private ProjectOperations projectOperations;
  @Inject private RequestScopeOperations requestScopeOperations;

  private CodeOwnerConfigFileUpdateScanner codeOwnerConfigFileUpdateScanner;

  @Before
  public void setup() throws Exception {
    codeOwnerConfigFileUpdateScanner =
        plugin.getSysInjector().getInstance(CodeOwnerConfigFileUpdateScanner.class);
  }

  @Test
  public void oldEmailIsRequired() throws Exception {
    RenameEmailInput input = new RenameEmailInput();
    input.newEmail = "new@example.com";
    BadRequestException exception =
        assertThrows(BadRequestException.class, () -> renameEmail(project, "master", input));
    assertThat(exception).hasMessageThat().isEqualTo("old email is required");
  }

  @Test
  public void newEmailIsRequired() throws Exception {
    RenameEmailInput input = new RenameEmailInput();
    input.oldEmail = "old@example.com";
    BadRequestException exception =
        assertThrows(BadRequestException.class, () -> renameEmail(project, "master", input));
    assertThat(exception).hasMessageThat().isEqualTo("new email is required");
  }

  @Test
  public void oldEmailNotResolvable() throws Exception {
    RenameEmailInput input = new RenameEmailInput();
    input.oldEmail = "unknown@example.com";
    input.newEmail = admin.email();
    UnprocessableEntityException exception =
        assertThrows(
            UnprocessableEntityException.class, () -> renameEmail(project, "master", input));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(String.format("cannot resolve email %s", input.oldEmail));
  }

  @Test
  public void newEmailNotResolvable() throws Exception {
    RenameEmailInput input = new RenameEmailInput();
    input.oldEmail = admin.email();
    input.newEmail = "unknown@example.com";
    UnprocessableEntityException exception =
        assertThrows(
            UnprocessableEntityException.class, () -> renameEmail(project, "master", input));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(String.format("cannot resolve email %s", input.newEmail));
  }

  @Test
  public void emailsMustBelongToSameAccount() throws Exception {
    RenameEmailInput input = new RenameEmailInput();
    input.oldEmail = admin.email();
    input.newEmail = user.email();
    BadRequestException exception =
        assertThrows(BadRequestException.class, () -> renameEmail(project, "master", input));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(
            String.format(
                "emails must belong to the same account"
                    + " (old email %s is owned by account %d, new email %s is owned by account %d)",
                admin.email(), admin.id().get(), user.email(), user.id().get()));
  }

  @Test
  public void oldAndNewEmailMustDiffer() throws Exception {
    RenameEmailInput input = new RenameEmailInput();
    input.oldEmail = admin.email();
    input.newEmail = admin.email();
    BadRequestException exception =
        assertThrows(BadRequestException.class, () -> renameEmail(project, "master", input));
    assertThat(exception).hasMessageThat().isEqualTo("old and new email must differ");
  }

  @Test
  public void requiresAuthenticatedUser() throws Exception {
    requestScopeOperations.setApiUserAnonymous();
    AuthException authException =
        assertThrows(
            AuthException.class, () -> renameEmail(project, "master", new RenameEmailInput()));
    assertThat(authException).hasMessageThat().contains("Authentication required");
  }

  @Test
  public void renameEmailRequiresDirectPushPermissionsForNonProjectOwner() throws Exception {
    String secondaryEmail = "user-foo@example.com";
    accountOperations.account(user.id()).forUpdate().addSecondaryEmail(secondaryEmail).update();

    requestScopeOperations.setApiUser(user.id());
    RenameEmailInput input = new RenameEmailInput();
    input.oldEmail = user.email();
    input.newEmail = secondaryEmail;
    AuthException exception =
        assertThrows(AuthException.class, () -> renameEmail(project, "master", input));
    assertThat(exception).hasMessageThat().isEqualTo("not permitted: update on refs/heads/master");
  }

  @Test
  public void renameEmail_noCodeOwnerConfig() throws Exception {
    String secondaryEmail = "user-foo@example.com";
    accountOperations.account(user.id()).forUpdate().addSecondaryEmail(secondaryEmail).update();

    RenameEmailInput input = new RenameEmailInput();
    input.oldEmail = user.email();
    input.newEmail = secondaryEmail;
    RenameEmailResultInfo result = renameEmail(project, "master", input);
    assertThat(result.commit).isNull();
  }

  @Test
  public void renameEmail_noUpdateIfEmailIsNotContainedInCodeOwnerConfigs() throws Exception {
    skipTestIfRenameEmailNotSupportedByCodeOwnersBackend();

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

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

    String secondaryEmail = "user-foo@example.com";
    accountOperations.account(user.id()).forUpdate().addSecondaryEmail(secondaryEmail).update();

    RenameEmailInput input = new RenameEmailInput();
    input.oldEmail = user.email();
    input.newEmail = secondaryEmail;
    RenameEmailResultInfo result = renameEmail(project, "master", input);
    assertThat(result.commit).isNull();
  }

  @Test
  public void renameOwnEmailWithDirectPushPermission() throws Exception {
    skipTestIfRenameEmailNotSupportedByCodeOwnersBackend();

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

    CodeOwnerConfig.Key codeOwnerConfigKey2 =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/foo/")
            .addCodeOwnerEmail(user.email())
            .create();

    // grant all users direct push permissions
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.PUSH).ref("refs/*").group(REGISTERED_USERS))
        .update();

    String secondaryEmail = "user-foo@example.com";
    accountOperations.account(user.id()).forUpdate().addSecondaryEmail(secondaryEmail).update();

    requestScopeOperations.setApiUser(user.id());
    RenameEmailInput input = new RenameEmailInput();
    input.oldEmail = user.email();
    input.newEmail = secondaryEmail;
    RenameEmailResultInfo result = renameEmail(project, "master", input);
    assertThat(result.commit).isNotNull();

    assertThat(codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey1).get())
        .hasCodeOwnerSetsThat()
        .onlyElement()
        .hasCodeOwnersEmailsThat()
        .containsExactly(secondaryEmail, admin.email());
    assertThat(codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey2).get())
        .hasCodeOwnerSetsThat()
        .onlyElement()
        .hasCodeOwnersEmailsThat()
        .containsExactly(secondaryEmail);
  }

  @Test
  public void renameOtherEmailWithDirectPushPermission() throws Exception {
    skipTestIfRenameEmailNotSupportedByCodeOwnersBackend();

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

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

    // grant all users direct push permissions
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.PUSH).ref("refs/*").group(REGISTERED_USERS))
        .update();

    // Allow all users to see secondary emails.
    projectOperations
        .project(allProjects)
        .forUpdate()
        .add(allowCapability(GlobalCapability.MODIFY_ACCOUNT).group(REGISTERED_USERS))
        .update();

    String secondaryEmail = "admin-foo@example.com";
    accountOperations.account(admin.id()).forUpdate().addSecondaryEmail(secondaryEmail).update();

    requestScopeOperations.setApiUser(user.id());
    RenameEmailInput input = new RenameEmailInput();
    input.oldEmail = admin.email();
    input.newEmail = secondaryEmail;
    RenameEmailResultInfo result = renameEmail(project, "master", input);
    assertThat(result.commit).isNotNull();

    assertThat(codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey1).get())
        .hasCodeOwnerSetsThat()
        .onlyElement()
        .hasCodeOwnersEmailsThat()
        .containsExactly(secondaryEmail, user.email());
    assertThat(codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey2).get())
        .hasCodeOwnerSetsThat()
        .onlyElement()
        .hasCodeOwnersEmailsThat()
        .containsExactly(secondaryEmail);
  }

  @Test
  public void renameOwnEmailAsProjectOwner() throws Exception {
    skipTestIfRenameEmailNotSupportedByCodeOwnersBackend();

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

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

    String secondaryEmail = "admin-foo@example.com";
    accountOperations.account(admin.id()).forUpdate().addSecondaryEmail(secondaryEmail).update();

    RenameEmailInput input = new RenameEmailInput();
    input.oldEmail = admin.email();
    input.newEmail = secondaryEmail;
    RenameEmailResultInfo result = renameEmail(project, "master", input);
    assertThat(result.commit).isNotNull();

    assertThat(codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey1).get())
        .hasCodeOwnerSetsThat()
        .onlyElement()
        .hasCodeOwnersEmailsThat()
        .containsExactly(secondaryEmail, user.email());
    assertThat(codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey2).get())
        .hasCodeOwnerSetsThat()
        .onlyElement()
        .hasCodeOwnersEmailsThat()
        .containsExactly(secondaryEmail);
  }

  @Test
  public void renameOtherEmailAsProjectOwner() throws Exception {
    skipTestIfRenameEmailNotSupportedByCodeOwnersBackend();

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

    CodeOwnerConfig.Key codeOwnerConfigKey2 =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/foo/")
            .addCodeOwnerEmail(user.email())
            .create();

    String secondaryEmail = "user-foo@example.com";
    accountOperations.account(user.id()).forUpdate().addSecondaryEmail(secondaryEmail).update();

    RenameEmailInput input = new RenameEmailInput();
    input.oldEmail = user.email();
    input.newEmail = secondaryEmail;
    RenameEmailResultInfo result = renameEmail(project, "master", input);
    assertThat(result.commit).isNotNull();

    assertThat(codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey1).get())
        .hasCodeOwnerSetsThat()
        .onlyElement()
        .hasCodeOwnersEmailsThat()
        .containsExactly(secondaryEmail, admin.email());
    assertThat(codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey2).get())
        .hasCodeOwnerSetsThat()
        .onlyElement()
        .hasCodeOwnersEmailsThat()
        .containsExactly(secondaryEmail);
  }

  @Test
  public void renameEmail_callingUserBecomesCommitAuthor() throws Exception {
    skipTestIfRenameEmailNotSupportedByCodeOwnersBackend();

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

    String secondaryEmail = "user-foo@example.com";
    accountOperations.account(user.id()).forUpdate().addSecondaryEmail(secondaryEmail).update();

    RenameEmailInput input = new RenameEmailInput();
    input.oldEmail = user.email();
    input.newEmail = secondaryEmail;
    RenameEmailResultInfo result = renameEmail(project, "master", input);
    assertThat(result.commit).isNotNull();
    assertThat(result.commit.author.email).isEqualTo(admin.email());
  }

  @Test
  public void renameEmailWithDefaultCommitMessage() throws Exception {
    skipTestIfRenameEmailNotSupportedByCodeOwnersBackend();

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

    String secondaryEmail = "user-foo@example.com";
    accountOperations.account(user.id()).forUpdate().addSecondaryEmail(secondaryEmail).update();

    RenameEmailInput input = new RenameEmailInput();
    input.oldEmail = user.email();
    input.newEmail = secondaryEmail;
    RenameEmailResultInfo result = renameEmail(project, "master", input);
    assertThat(result.commit).isNotNull();
    assertThat(result.commit.message).isEqualTo(RenameEmail.DEFAULT_COMMIT_MESSAGE);
  }

  @Test
  public void renameEmailWithSpecifiedCommitMessage() throws Exception {
    skipTestIfRenameEmailNotSupportedByCodeOwnersBackend();

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

    String secondaryEmail = "user-foo@example.com";
    accountOperations.account(user.id()).forUpdate().addSecondaryEmail(secondaryEmail).update();

    RenameEmailInput input = new RenameEmailInput();
    input.oldEmail = user.email();
    input.newEmail = secondaryEmail;
    input.message = "Update email with custom message";
    RenameEmailResultInfo result = renameEmail(project, "master", input);
    assertThat(result.commit).isNotNull();
    assertThat(result.commit.message).isEqualTo(input.message);
  }

  @Test
  public void renameEmail_specifiedCommitMessageIsTrimmed() throws Exception {
    skipTestIfRenameEmailNotSupportedByCodeOwnersBackend();

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

    String secondaryEmail = "user-foo@example.com";
    accountOperations.account(user.id()).forUpdate().addSecondaryEmail(secondaryEmail).update();

    String message = "Update email with custom message";
    RenameEmailInput input = new RenameEmailInput();
    input.oldEmail = user.email();
    input.newEmail = secondaryEmail;
    input.message = "  " + message + "\t";
    RenameEmailResultInfo result = renameEmail(project, "master", input);
    assertThat(result.commit).isNotNull();
    assertThat(result.commit.message).isEqualTo(message);
  }

  @Test
  public void renameEmail_lineCommentsArePreserved() throws Exception {
    skipTestIfRenameEmailNotSupportedByCodeOwnersBackend();

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

    // insert some comments
    codeOwnerConfigFileUpdateScanner.update(
        BranchNameKey.create(project, "master"),
        "Insert comments",
        (codeOwnerConfigFilePath, codeOwnerConfigFileContent) -> {
          StringBuilder b = new StringBuilder();
          // insert comment line at the top of the file
          b.append("# top comment\n");

          Iterable<String> lines = Splitter.on('\n').split(codeOwnerConfigFileContent);
          b.append(Iterables.get(lines, /* position= */ 0) + "\n");

          // insert comment line in the middle of the file
          b.append("# middle comment\n");

          for (String line : Iterables.skip(lines, /* numberToSkip= */ 1)) {
            b.append(line + "\n");
          }

          // insert comment line at the bottom of the file
          b.append("# bottom comment\n");

          return Optional.of(b.toString());
        });

    String secondaryEmail = "user-foo@example.com";
    accountOperations.account(user.id()).forUpdate().addSecondaryEmail(secondaryEmail).update();

    RenameEmailInput input = new RenameEmailInput();
    input.oldEmail = user.email();
    input.newEmail = secondaryEmail;
    renameEmail(project, "master", input);

    assertThat(codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).get())
        .hasCodeOwnerSetsThat()
        .onlyElement()
        .hasCodeOwnersEmailsThat()
        .containsExactly(secondaryEmail, admin.email());

    // verify that the comments are still present
    String codeOwnerConfigFileContent =
        codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).getContent();
    Iterable<String> lines = Splitter.on('\n').split(codeOwnerConfigFileContent);
    assertThat(Iterables.get(lines, /* position= */ 0)).isEqualTo("# top comment");
    assertThat(Iterables.get(lines, /* position= */ 2)).isEqualTo("# middle comment");
    assertThat(Iterables.get(lines, /* position= */ Iterables.size(lines) - 2))
        .isEqualTo("# bottom comment");
  }

  @Test
  public void renameEmail_inlineCommentsArePreserved() throws Exception {
    skipTestIfRenameEmailNotSupportedByCodeOwnersBackend();

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

    // insert some inline comments
    codeOwnerConfigFileUpdateScanner.update(
        BranchNameKey.create(project, "master"),
        "Insert comments",
        (codeOwnerConfigFilePath, codeOwnerConfigFileContent) -> {
          StringBuilder b = new StringBuilder();
          for (String line : Splitter.on('\n').split(codeOwnerConfigFileContent)) {
            if (line.contains(user.email())) {
              b.append(line + "# some comment\n");
              continue;
            }
            if (line.contains(admin.email())) {
              b.append(line + "# other comment\n");
              continue;
            }
            b.append(line + "\n");
          }

          return Optional.of(b.toString());
        });

    String secondaryEmail = "user-foo@example.com";
    accountOperations.account(user.id()).forUpdate().addSecondaryEmail(secondaryEmail).update();

    RenameEmailInput input = new RenameEmailInput();
    input.oldEmail = user.email();
    input.newEmail = secondaryEmail;
    renameEmail(project, "master", input);

    assertThat(codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).get())
        .hasCodeOwnerSetsThat()
        .onlyElement()
        .hasCodeOwnersEmailsThat()
        .containsExactly(secondaryEmail, admin.email());

    // verify that the inline comments are still present
    String codeOwnerConfigFileContent =
        codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).getContent();
    for (String line : Splitter.on('\n').split(codeOwnerConfigFileContent)) {
      if (line.contains(secondaryEmail)) {
        assertThat(line).endsWith("# some comment");
      } else if (line.contains(admin.email())) {
        assertThat(line).endsWith("# other comment");
      }
    }
  }

  @Test
  public void renameEmail_emailInCommentIsReplaced() throws Exception {
    skipTestIfRenameEmailNotSupportedByCodeOwnersBackend();

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

    // insert some comments
    codeOwnerConfigFileUpdateScanner.update(
        BranchNameKey.create(project, "master"),
        "Insert comments",
        (codeOwnerConfigFilePath, codeOwnerConfigFileContent) ->
            Optional.of("# foo " + user.email() + " bar\n" + codeOwnerConfigFileContent));

    String secondaryEmail = "user-foo@example.com";
    accountOperations.account(user.id()).forUpdate().addSecondaryEmail(secondaryEmail).update();

    RenameEmailInput input = new RenameEmailInput();
    input.oldEmail = user.email();
    input.newEmail = secondaryEmail;
    renameEmail(project, "master", input);

    assertThat(codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).get())
        .hasCodeOwnerSetsThat()
        .onlyElement()
        .hasCodeOwnersEmailsThat()
        .containsExactly(secondaryEmail, admin.email());

    // verify that the comments are still present
    String codeOwnerConfigFileContent =
        codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).getContent();
    assertThat(
            Iterables.get(Splitter.on('\n').split(codeOwnerConfigFileContent), /* position= */ 0))
        .endsWith("# foo " + secondaryEmail + " bar");
  }

  @Test
  public void renameEmail_emailThatContainsEmailToBeReplacesAsSubstringStaysIntact()
      throws Exception {
    skipTestIfRenameEmailNotSupportedByCodeOwnersBackend();

    TestAccount otherUser1 =
        accountCreator.create(
            "otherUser1", "foo" + user.email(), "Other User 1", /* displayName= */ null);
    TestAccount otherUser2 =
        accountCreator.create(
            "otherUser2", user.email() + "bar", "Other User 2", /* displayName= */ null);
    TestAccount otherUser3 =
        accountCreator.create(
            "otherUser3", "foo" + user.email() + "bar", "Other User 3", /* displayName= */ null);

    CodeOwnerConfig.Key codeOwnerConfigKey =
        codeOwnerConfigOperations
            .newCodeOwnerConfig()
            .project(project)
            .branch("master")
            .folderPath("/")
            .addCodeOwnerEmail(user.email())
            .addCodeOwnerEmail(otherUser1.email())
            .addCodeOwnerEmail(otherUser2.email())
            .addCodeOwnerEmail(otherUser3.email())
            .create();

    // grant all users direct push permissions
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.PUSH).ref("refs/*").group(REGISTERED_USERS))
        .update();

    String secondaryEmail = "user-new@example.com";
    accountOperations.account(user.id()).forUpdate().addSecondaryEmail(secondaryEmail).update();

    requestScopeOperations.setApiUser(user.id());
    RenameEmailInput input = new RenameEmailInput();
    input.oldEmail = user.email();
    input.newEmail = secondaryEmail;
    RenameEmailResultInfo result = renameEmail(project, "master", input);
    assertThat(result.commit).isNotNull();

    assertThat(codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).get())
        .hasCodeOwnerSetsThat()
        .onlyElement()
        .hasCodeOwnersEmailsThat()
        .containsExactly(
            secondaryEmail, otherUser1.email(), otherUser2.email(), otherUser3.email());
  }

  private RenameEmailResultInfo renameEmail(
      Project.NameKey projectName, String branchName, RenameEmailInput input)
      throws RestApiException {
    return projectCodeOwnersApiFactory
        .project(projectName)
        .branch(branchName)
        .renameEmailInCodeOwnerConfigFiles(input);
  }

  private void skipTestIfRenameEmailNotSupportedByCodeOwnersBackend() {
    // the proto backend doesn't support renaming emails
    assumeThatCodeOwnersBackendIsNotProtoBackend();
  }
}
