// Copyright (C) 2023 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.acceptance.api.change;

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.acceptance.testsuite.project.TestProjectUpdate.allowLabel;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.block;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_REAL_USER;
import static com.google.gerrit.server.project.testing.TestLabels.labelBuilder;
import static com.google.gerrit.server.project.testing.TestLabels.value;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;

import com.google.common.collect.Iterables;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.ExtensionRegistry;
import com.google.gerrit.acceptance.ExtensionRegistry.Registration;
import com.google.gerrit.acceptance.TestMetricMaker;
import com.google.gerrit.acceptance.UseLocalDisk;
import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
import com.google.gerrit.acceptance.testsuite.change.ChangeOperations;
import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
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.Account;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.LabelId;
import com.google.gerrit.entities.LabelType;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Permission;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.entities.SubmitRequirement;
import com.google.gerrit.entities.SubmitRequirementExpression;
import com.google.gerrit.extensions.api.changes.RebaseInput;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.common.ActionInfo;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.ChangeMessageInfo;
import com.google.gerrit.extensions.common.RevisionInfo;
import com.google.gerrit.extensions.events.RevisionCreatedListener;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.server.notedb.ChangeNoteUtil;
import com.google.gerrit.server.project.testing.TestLabels;
import com.google.gerrit.server.util.AccountTemplateUtil;
import com.google.inject.Inject;
import java.util.Collection;
import java.util.Optional;
import org.eclipse.jgit.lib.ReflogEntry;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.FooterLine;
import org.junit.Test;

/**
 * Tests for the {@link com.google.gerrit.server.restapi.change.Rebase} REST endpoint with the
 * {@link RebaseInput#onBehalfOfUploader} option being set.
 *
 * <p>Rebasing a chain on behalf of the uploader is covered by {@link
 * RebaseChainOnBehalfOfUploaderIT}.
 */
public class RebaseOnBehalfOfUploaderIT extends AbstractDaemonTest {
  @Inject private AccountOperations accountOperations;
  @Inject private ChangeOperations changeOperations;
  @Inject private GroupOperations groupOperations;
  @Inject private ProjectOperations projectOperations;
  @Inject private RequestScopeOperations requestScopeOperations;
  @Inject private ExtensionRegistry extensionRegistry;
  @Inject private TestMetricMaker testMetricMaker;

  @Test
  public void cannotRebaseOnBehalfOfUploaderWithAllowConflicts() throws Exception {
    Account.Id uploader = accountOperations.newAccount().create();
    Change.Id changeId = changeOperations.newChange().owner(uploader).create();
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    rebaseInput.allowConflicts = true;
    BadRequestException exception =
        assertThrows(
            BadRequestException.class, () -> gApi.changes().id(changeId.get()).rebase(rebaseInput));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo("allow_conflicts and on_behalf_of_uploader are mutually exclusive");
  }

  @Test
  public void rebaseOnBehalfOfUploaderWithCommitterEmail() throws Exception {
    allowPermissionToAllUsers(Permission.REBASE);

    String uploaderPreferredEmail = "uploader.preferred@example.com";
    String uploaderSecondaryEmail = "uploader.secondary@example.com";
    Account.Id uploader =
        accountOperations
            .newAccount()
            .preferredEmail(uploaderPreferredEmail)
            .addSecondaryEmail(uploaderSecondaryEmail)
            .create();
    Account.Id approver = admin.id();
    Account.Id rebaser = accountOperations.newAccount().create();

    projectOperations
        .allProjectsForUpdate()
        .add(allowCapability(GlobalCapability.VIEW_SECONDARY_EMAILS).group(REGISTERED_USERS))
        .update();

    // Create two changes both with the same parent.
    requestScopeOperations.setApiUser(uploader);
    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased =
        changeOperations.newChange().project(project).owner(uploader).create();

    // Approve and submit the change that will be the new base for the change that will be rebased.
    requestScopeOperations.setApiUser(approver);
    gApi.changes().id(changeToBeTheNewBase.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase.get()).current().submit();

    // Rebase the second change on behalf of the uploader
    requestScopeOperations.setApiUser(rebaser);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    rebaseInput.committerEmail = uploaderSecondaryEmail;
    gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput);

    assertThat(
            gApi.changes()
                .id(changeToBeRebased.get())
                .get()
                .getCurrentRevision()
                .commit
                .committer
                .email)
        .isEqualTo(uploaderSecondaryEmail);
  }

  @Test
  public void cannotRebaseOnBehalfOfUploaderWithCommitterEmailWithoutViewSecondaryEmails()
      throws Exception {
    allowPermissionToAllUsers(Permission.REBASE);

    String uploaderPreferredEmail = "uploader.preferred@example.com";
    String uploaderSecondaryEmail = "uploader.secondary@example.com";
    Account.Id uploader =
        accountOperations
            .newAccount()
            .preferredEmail(uploaderPreferredEmail)
            .addSecondaryEmail(uploaderSecondaryEmail)
            .create();
    Account.Id approver = admin.id();
    Account.Id rebaser = accountOperations.newAccount().create();

    // Create two changes both with the same parent.
    requestScopeOperations.setApiUser(uploader);
    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased =
        changeOperations.newChange().project(project).owner(uploader).create();

    // Approve and submit the change that will be the new base for the change that will be rebased.
    requestScopeOperations.setApiUser(approver);
    gApi.changes().id(changeToBeTheNewBase.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase.get()).current().submit();

    // Rebase the second change on behalf of the uploader
    requestScopeOperations.setApiUser(rebaser);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    rebaseInput.committerEmail = uploaderSecondaryEmail;

    ResourceConflictException exception =
        assertThrows(
            ResourceConflictException.class,
            () -> gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(
            String.format(
                "Cannot rebase using committer email '%s'. It can only be done using "
                    + "the preferred email or the committer email of the uploader",
                uploaderSecondaryEmail));
  }

  @Test
  public void cannotRebaseNonCurrentPatchSetOnBehalfOfUploader() throws Exception {
    Account.Id uploader = accountOperations.newAccount().create();
    Change.Id changeId = changeOperations.newChange().owner(uploader).create();
    changeOperations.change(changeId).newPatchset().create();
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    BadRequestException exception =
        assertThrows(
            BadRequestException.class,
            () -> gApi.changes().id(changeId.get()).revision(1).rebase(rebaseInput));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(
            String.format(
                "change %s: non-current patch set cannot be rebased on behalf of the uploader",
                changeId));
  }

  @Test
  public void rebaseChangeOnBehalfOfUploader_withRebasePermission() throws Exception {
    testRebaseChangeOnBehalfOfUploader(
        Permission.REBASE,
        (changeId, rebaseInput) -> gApi.changes().id(changeId.get()).rebase(rebaseInput));
  }

  @Test
  public void rebaseCurrentPatchSetOnBehalfOfUploader_withRebasePermission() throws Exception {
    testRebaseChangeOnBehalfOfUploader(
        Permission.REBASE,
        (changeId, rebaseInput) -> gApi.changes().id(changeId.get()).current().rebase(rebaseInput));
  }

  @Test
  public void rebaseChangeOnBehalfOfUploader_withSubmitPermission() throws Exception {
    testRebaseChangeOnBehalfOfUploader(
        Permission.SUBMIT,
        (changeId, rebaseInput) -> gApi.changes().id(changeId.get()).rebase(rebaseInput));
  }

  @Test
  public void rebaseCurrentPatchSetOnBehalfOfUploader_withSubmitPermission() throws Exception {
    testRebaseChangeOnBehalfOfUploader(
        Permission.SUBMIT,
        (changeId, rebaseInput) -> gApi.changes().id(changeId.get()).current().rebase(rebaseInput));
  }

  private void testRebaseChangeOnBehalfOfUploader(String permissionToAllow, RebaseCall rebaseCall)
      throws Exception {
    String uploaderEmail = "uploader@example.com";
    Account.Id uploader = accountOperations.newAccount().preferredEmail(uploaderEmail).create();
    Account.Id changeOwner = accountOperations.newAccount().create();
    Account.Id approver = admin.id();
    Account.Id rebaser = accountOperations.newAccount().create();

    // Grant permission to rebaser that is required to rebase on behalf of the uploader.
    AccountGroup.UUID allowedGroup =
        groupOperations.newGroup().name("can-" + permissionToAllow).addMember(rebaser).create();
    allowPermission(permissionToAllow, allowedGroup);

    // Block rebase and submit permission for uploader. For rebase on behalf of the uploader only
    // the rebaser needs to have this permission, but not the uploader on whom's behalf the rebase
    // is done.
    AccountGroup.UUID cannotRebaseAndSubmitGroup =
        groupOperations.newGroup().name("cannot-rebase").addMember(uploader).create();
    blockPermission(Permission.REBASE, cannotRebaseAndSubmitGroup);
    blockPermission(Permission.SUBMIT, cannotRebaseAndSubmitGroup);

    // Block push permission for rebaser, as in contrast to rebase, rebase on behalf of the uploader
    // doesn't require the rebaser to have the push permission.
    AccountGroup.UUID cannotUploadGroup =
        groupOperations.newGroup().name("cannot-upload").addMember(rebaser).create();
    blockPermission(Permission.PUSH, cannotUploadGroup);

    // Create two changes both with the same parent
    requestScopeOperations.setApiUser(changeOwner);
    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().project(project).owner(changeOwner).create();
    Change.Id changeToBeRebased =
        changeOperations.newChange().project(project).owner(changeOwner).create();

    // Create a second patch set for the change that will be rebased so that the uploader is
    // different to the change owner. This is to verify that being change owner doesn't matter for
    // the user on whom's behalf the rebase is done.
    // Set author and committer to the uploader so that rebasing on behalf of the uploader doesn't
    // require the Forge Author and Forge Committer permission.
    changeOperations
        .change(changeToBeRebased)
        .newPatchset()
        .uploader(uploader)
        .author(uploader)
        .committer(uploader)
        .create();

    // Approve and submit the change that will be the new base for the change that will be rebased.
    requestScopeOperations.setApiUser(approver);
    gApi.changes().id(changeToBeTheNewBase.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase.get()).current().submit();

    // Rebase the second change on behalf of the uploader
    requestScopeOperations.setApiUser(rebaser);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;

    TestRevisionCreatedListener testRevisionCreatedListener = new TestRevisionCreatedListener();
    try (Registration registration =
        extensionRegistry.newRegistration().add(testRevisionCreatedListener)) {
      rebaseCall.call(changeToBeRebased, rebaseInput);

      assertThat(testRevisionCreatedListener.revisionInfo.uploader._accountId)
          .isEqualTo(uploader.get());
      assertThat(testRevisionCreatedListener.revisionInfo.realUploader._accountId)
          .isEqualTo(rebaser.get());
    }

    ChangeInfo changeInfo2 = gApi.changes().id(changeToBeRebased.get()).get();
    RevisionInfo currentRevisionInfo = changeInfo2.getCurrentRevision();
    // The change had 2 patch sets before the rebase, now it should be 3
    assertThat(currentRevisionInfo._number).isEqualTo(3);
    assertThat(currentRevisionInfo.uploader._accountId).isEqualTo(uploader.get());
    assertThat(currentRevisionInfo.realUploader._accountId).isEqualTo(rebaser.get());
    assertThat(currentRevisionInfo.commit.author.email).isEqualTo(uploaderEmail);
    assertThat(currentRevisionInfo.commit.committer.email).isEqualTo(uploaderEmail);

    // Verify that the rebaser was recorded as realUser in NoteDb.
    Optional<FooterLine> realUserFooter =
        projectOperations
            .project(project)
            .getHead(RefNames.changeMetaRef(changeToBeRebased))
            .getFooterLines()
            .stream()
            .filter(footerLine -> footerLine.matches(FOOTER_REAL_USER))
            .findFirst();
    assertThat(realUserFooter.map(FooterLine::getValue))
        .hasValue(
            String.format(
                "%s <%s>",
                ChangeNoteUtil.getAccountIdAsUsername(rebaser),
                changeNoteUtil.getAccountIdAsEmailAddress(rebaser)));

    // Verify the message that has been posted on the change.
    Collection<ChangeMessageInfo> changeMessages = changeInfo2.messages;
    // Before the rebase the change had 2 messages for the upload of the 2 patch sets. Rebase is
    // expected to add another message.
    assertThat(changeMessages).hasSize(3);
    ChangeMessageInfo changeMessage = Iterables.getLast(changeMessages);
    assertThat(changeMessage.message)
        .isEqualTo(
            "Patch Set 3: Patch Set 2 was rebased on behalf of "
                + AccountTemplateUtil.getAccountTemplate(uploader));
    assertThat(changeMessage.author._accountId).isEqualTo(uploader.get());
    assertThat(changeMessage.realAuthor._accountId).isEqualTo(rebaser.get());
  }

  @Test
  public void rebaseChangeOnBehalfOfUploaderAfterUpdatingPreferredEmailForUploader()
      throws Exception {
    String uploaderEmailOne = "uploader1@example.com";
    Account.Id uploader = accountOperations.newAccount().preferredEmail(uploaderEmailOne).create();

    // Create two changes both with the same parent
    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased =
        changeOperations.newChange().project(project).owner(uploader).create();

    // Approve and submit the change that will be the new base for the change that will be rebased.
    gApi.changes().id(changeToBeTheNewBase.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase.get()).current().submit();

    // Change preferred email for the uploader
    String uploaderEmailTwo = "uploader2@example.com";
    accountOperations.account(uploader).forUpdate().preferredEmail(uploaderEmailTwo).update();

    // Rebase the second change on behalf of the uploader
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput);
    assertThat(
            gApi.changes()
                .id(changeToBeRebased.get())
                .get()
                .getCurrentRevision()
                .commit
                .committer
                .email)
        .isEqualTo(uploaderEmailOne);
  }

  @Test
  public void rebaseChangeOnBehalfOfUploaderMultipleTimesInARow() throws Exception {
    allowPermissionToAllUsers(Permission.REBASE);

    String uploaderEmail = "uploader@example.com";
    Account.Id uploader = accountOperations.newAccount().preferredEmail(uploaderEmail).create();
    Account.Id approver = admin.id();
    Account.Id rebaser = accountOperations.newAccount().create();

    // Create two changes both with the same parent.
    requestScopeOperations.setApiUser(uploader);
    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased =
        changeOperations.newChange().project(project).owner(uploader).create();

    // Approve and submit the change that will be the new base for the change that will be rebased.
    requestScopeOperations.setApiUser(approver);
    gApi.changes().id(changeToBeTheNewBase.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase.get()).current().submit();

    // Rebase the second change on behalf of the uploader
    requestScopeOperations.setApiUser(rebaser);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput);

    ChangeInfo changeInfo2 = gApi.changes().id(changeToBeRebased.get()).get();
    RevisionInfo currentRevisionInfo = changeInfo2.getCurrentRevision();
    // The change had 1 patch set before the rebase, now it should be 2
    assertThat(currentRevisionInfo._number).isEqualTo(2);
    assertThat(currentRevisionInfo.commit.committer.email).isEqualTo(uploaderEmail);
    assertThat(currentRevisionInfo.uploader._accountId).isEqualTo(uploader.get());
    assertThat(currentRevisionInfo.realUploader._accountId).isEqualTo(rebaser.get());

    // Create and submit another change so that we can rebase the change once again.
    requestScopeOperations.setApiUser(approver);
    Change.Id changeToBeTheNewBase2 =
        changeOperations.newChange().project(project).owner(uploader).create();
    gApi.changes().id(changeToBeTheNewBase2.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase2.get()).current().submit();

    // Rebase the change once again on behalf of the uploader.
    requestScopeOperations.setApiUser(rebaser);
    gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput);

    changeInfo2 = gApi.changes().id(changeToBeRebased.get()).get();
    currentRevisionInfo = changeInfo2.getCurrentRevision();
    // The change had 2 patch sets before the rebase, now it should be 3
    assertThat(currentRevisionInfo._number).isEqualTo(3);
    assertThat(currentRevisionInfo.commit.committer.email).isEqualTo(uploaderEmail);
    assertThat(currentRevisionInfo.uploader._accountId).isEqualTo(uploader.get());
    assertThat(currentRevisionInfo.realUploader._accountId).isEqualTo(rebaser.get());

    // Create and submit another change so that we can rebase the change once again.
    requestScopeOperations.setApiUser(approver);
    Change.Id changeToBeTheNewBase3 =
        changeOperations.newChange().project(project).owner(uploader).create();
    gApi.changes().id(changeToBeTheNewBase3.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase3.get()).current().submit();

    // Rebase the change once again on behalf of the uploader, this time by another rebaser.
    Account.Id rebaser2 = accountOperations.newAccount().create();
    requestScopeOperations.setApiUser(rebaser2);
    gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput);

    changeInfo2 = gApi.changes().id(changeToBeRebased.get()).get();
    currentRevisionInfo = changeInfo2.getCurrentRevision();
    // The change had 3 patch sets before the rebase, now it should be 4
    assertThat(currentRevisionInfo._number).isEqualTo(4);
    assertThat(currentRevisionInfo.commit.committer.email).isEqualTo(uploaderEmail);
    assertThat(currentRevisionInfo.uploader._accountId).isEqualTo(uploader.get());
    assertThat(currentRevisionInfo.realUploader._accountId).isEqualTo(rebaser2.get());
  }

  @Test
  public void nonChangeOwnerWithoutSubmitAndRebasePermissionCannotRebaseOnBehalfOfUploader()
      throws Exception {
    Change.Id changeId = changeOperations.newChange().project(project).create();

    blockPermissionForAllUsers(Permission.REBASE);
    blockPermissionForAllUsers(Permission.SUBMIT);

    Account.Id rebaserId = accountOperations.newAccount().create();
    requestScopeOperations.setApiUser(rebaserId);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    AuthException exception =
        assertThrows(
            AuthException.class, () -> gApi.changes().id(changeId.get()).rebase(rebaseInput));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(
            "rebase on behalf of uploader not permitted (change owners and users with the 'Submit'"
                + " or 'Rebase' permission can rebase on behalf of the uploader)");
  }

  @Test
  public void cannotRebaseChangeOnBehalfOfUploaderIfTheUploaderHasNoReadPermission()
      throws Exception {
    String uploaderEmail = "uploader@example.com";
    testCannotRebaseChangeOnBehalfOfUploaderIfTheUploaderHasNoPermission(
        uploaderEmail,
        Permission.READ,
        String.format("uploader %s cannot read change", uploaderEmail));
  }

  @Test
  public void cannotRebaseChangeOnBehalfOfUploaderIfTheUploaderHasNoPushPermission()
      throws Exception {
    String uploaderEmail = "uploader@example.com";
    testCannotRebaseChangeOnBehalfOfUploaderIfTheUploaderHasNoPermission(
        uploaderEmail,
        Permission.PUSH,
        String.format("uploader %s cannot add patch set", uploaderEmail));
  }

  private void testCannotRebaseChangeOnBehalfOfUploaderIfTheUploaderHasNoPermission(
      String uploaderEmail, String permissionToBlock, String expectedErrorMessage)
      throws Exception {
    allowPermissionToAllUsers(Permission.REBASE);

    Account.Id uploader = accountOperations.newAccount().preferredEmail(uploaderEmail).create();
    Account.Id approver = admin.id();
    Account.Id rebaser = accountOperations.newAccount().create();

    // Create two changes both with the same parent
    requestScopeOperations.setApiUser(uploader);
    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased =
        changeOperations.newChange().project(project).owner(uploader).create();

    // Approve and submit the change that will be the new base for the change that will be rebased.
    requestScopeOperations.setApiUser(approver);
    gApi.changes().id(changeToBeTheNewBase.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase.get()).current().submit();

    // Block the required permission for uploader. Without this permission it should not be possible
    // to rebase the change on behalf of the uploader.
    AccountGroup.UUID blockedGroup =
        groupOperations.newGroup().name("cannot-" + permissionToBlock).addMember(uploader).create();
    blockPermission(permissionToBlock, blockedGroup);

    // Try to rebase the second change on behalf of the uploader
    requestScopeOperations.setApiUser(rebaser);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    ResourceConflictException exception =
        assertThrows(
            ResourceConflictException.class,
            () -> gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(String.format("change %s: %s", changeToBeRebased, expectedErrorMessage));
  }

  @Test
  public void rebaseChangeOnBehalfOfYourself() throws Exception {
    allowPermissionToAllUsers(Permission.REBASE);

    Account.Id uploader =
        accountOperations.newAccount().preferredEmail("uploader@example.com").create();
    Account.Id approver = admin.id();

    // Create two changes both with the same parent. Forge the author of the change that will be
    // rebased.
    requestScopeOperations.setApiUser(uploader);
    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased =
        changeOperations.newChange().project(project).owner(uploader).create();

    // Approve and submit the change that will be the new base for the change that will be rebased.
    requestScopeOperations.setApiUser(approver);
    gApi.changes().id(changeToBeTheNewBase.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase.get()).current().submit();

    // Rebase the second change as uploader on behalf of the uploader
    requestScopeOperations.setApiUser(uploader);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput);

    RevisionInfo currentRevisionInfo =
        gApi.changes().id(changeToBeRebased.get()).get().getCurrentRevision();
    // The change had 1 patch set before the rebase, now it should be 2
    assertThat(currentRevisionInfo._number).isEqualTo(2);
    assertThat(currentRevisionInfo.uploader._accountId).isEqualTo(uploader.get());
    assertThat(currentRevisionInfo.realUploader).isNull();
  }

  @Test
  public void cannotRebaseChangeOnBehalfOfYourselfWithoutPushPermission() throws Exception {
    allowPermissionToAllUsers(Permission.REBASE);

    Account.Id uploader =
        accountOperations.newAccount().preferredEmail("uploader@example.com").create();
    Account.Id approver = admin.id();

    // Create two changes both with the same parent. Forge the author of the change that will be
    // rebased.
    requestScopeOperations.setApiUser(uploader);
    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased =
        changeOperations.newChange().project(project).owner(uploader).create();

    // Approve and submit the change that will be the new base for the change that will be rebased.
    requestScopeOperations.setApiUser(approver);
    gApi.changes().id(changeToBeTheNewBase.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase.get()).current().submit();

    // Block push for uploader. For rebase on behalf of the uploader only
    // the rebaser needs to have this permission, but not the uploader on whom's behalf the rebase
    // is done.
    AccountGroup.UUID cannotPushGroup =
        groupOperations.newGroup().name("cannot-push").addMember(uploader).create();
    blockPermission(Permission.PUSH, cannotPushGroup);

    // Rebase the second change as uploader on behalf of the uploader
    requestScopeOperations.setApiUser(uploader);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    AuthException exception =
        assertThrows(
            AuthException.class,
            () -> gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(
            "rebase not permitted (change owners and users with the 'Submit' or 'Rebase'"
                + " permission can rebase if they have the 'Push' permission)");
  }

  @Test
  public void rebaseChangeOnBehalfOfUploaderWhenUploaderIsNotTheChangeOwner() throws Exception {
    allowPermissionToAllUsers(Permission.REBASE);

    Account.Id changeOwner = accountOperations.newAccount().create();
    Account.Id uploader =
        accountOperations.newAccount().preferredEmail("uploader@example.com").create();
    Account.Id approver = admin.id();
    Account.Id rebaser = accountOperations.newAccount().create();

    // Create two changes both with the same parent. Forge the author of the change that will be
    // rebased.
    requestScopeOperations.setApiUser(changeOwner);
    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().project(project).owner(changeOwner).create();
    Change.Id changeToBeRebased =
        changeOperations.newChange().project(project).owner(changeOwner).create();

    // Create a second patch set for the change that will be rebased so that the uploader is
    // different to the change owner.
    // Set author and committer to the uploader so that rebasing on behalf of the uploader doesn't
    // require the Forge Author and Forge Committer permission.
    changeOperations
        .change(changeToBeRebased)
        .newPatchset()
        .uploader(uploader)
        .author(uploader)
        .committer(uploader)
        .create();

    // Approve and submit the change that will be the new base for the change that will be rebased.
    requestScopeOperations.setApiUser(approver);
    gApi.changes().id(changeToBeTheNewBase.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase.get()).current().submit();

    // Grant add patch set permission for uploader. Without the add patch set permission it is not
    // possible to rebase the change on behalf of the uploader since the uploader cannot add a
    // patch set to a change that is owned by another user.
    AccountGroup.UUID canAddPatchSet =
        groupOperations.newGroup().name("can-add-patch-set").addMember(uploader).create();
    allowPermission(Permission.ADD_PATCH_SET, canAddPatchSet);

    // Rebase the second change on behalf of the uploader
    requestScopeOperations.setApiUser(rebaser);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput);

    RevisionInfo currentRevisionInfo =
        gApi.changes().id(changeToBeRebased.get()).get().getCurrentRevision();
    // The change had 2 patch set before the rebase, now it should be 3
    assertThat(currentRevisionInfo._number).isEqualTo(3);
    assertThat(currentRevisionInfo.uploader._accountId).isEqualTo(uploader.get());
    assertThat(currentRevisionInfo.realUploader._accountId).isEqualTo(rebaser.get());
  }

  @Test
  public void
      cannotRebaseChangeOnBehalfOfUploaderWhenUploaderIsNotTheChangeOwnerAndDoesntHaveAddPatchSetPermission()
          throws Exception {
    allowPermissionToAllUsers(Permission.REBASE);

    String uploaderEmail = "uploader@example.com";
    Account.Id uploader = accountOperations.newAccount().preferredEmail(uploaderEmail).create();
    Account.Id changeOwner = accountOperations.newAccount().create();
    Account.Id approver = admin.id();
    Account.Id rebaser = accountOperations.newAccount().create();

    // Create two changes both with the same parent. Forge the author of the change that will be
    // rebased.
    requestScopeOperations.setApiUser(changeOwner);
    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().project(project).owner(changeOwner).create();
    Change.Id changeToBeRebased =
        changeOperations.newChange().project(project).owner(changeOwner).create();

    // Create a second patch set for the change that will be rebased so that the uploader is
    // different to the change owner.
    // Set author and committer to the uploader so that rebasing on behalf of the uploader doesn't
    // require the Forge Author and Forge Committer permission.
    changeOperations
        .change(changeToBeRebased)
        .newPatchset()
        .uploader(uploader)
        .author(uploader)
        .committer(uploader)
        .create();

    // Approve and submit the change that will be the new base for the change that will be rebased.
    requestScopeOperations.setApiUser(approver);
    gApi.changes().id(changeToBeTheNewBase.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase.get()).current().submit();

    // Block add patch set permission for uploader. Without the add patch set permission it should
    // not possible to rebase the change on behalf of the uploader since the uploader cannot add a
    // patch set to a change that is owned by another user.
    AccountGroup.UUID cannotAddPatchSet =
        groupOperations.newGroup().name("cannot-add-patch-set").addMember(uploader).create();
    blockPermission(Permission.ADD_PATCH_SET, cannotAddPatchSet);

    // Try to rebase the second change on behalf of the uploader
    requestScopeOperations.setApiUser(rebaser);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    ResourceConflictException exception =
        assertThrows(
            ResourceConflictException.class,
            () -> gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(
            String.format(
                "change %s: uploader %s cannot add patch set", changeToBeRebased, uploaderEmail));
  }

  @Test
  public void rebaseChangeWithForgedAuthorOnBehalfOfUploader() throws Exception {
    allowPermissionToAllUsers(Permission.REBASE);

    String authorEmail = "author@example.com";
    Account.Id author = accountOperations.newAccount().preferredEmail(authorEmail).create();
    Account.Id uploader =
        accountOperations.newAccount().preferredEmail("uploader@example.com").create();
    Account.Id approver = admin.id();
    Account.Id rebaser = accountOperations.newAccount().create();

    // Create two changes both with the same parent. Forge the author of the change that will be
    // rebased.
    requestScopeOperations.setApiUser(uploader);
    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased =
        changeOperations.newChange().project(project).owner(uploader).author(author).create();

    // Approve and submit the change that will be the new base for the change that will be rebased.
    requestScopeOperations.setApiUser(approver);
    gApi.changes().id(changeToBeTheNewBase.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase.get()).current().submit();

    // Grant forge author permission for uploader. Without the forge author permission it is not
    // possible to rebase the change on behalf of the uploader.
    AccountGroup.UUID canForgeAuthor =
        groupOperations.newGroup().name("can-forge-author").addMember(uploader).create();
    allowPermission(Permission.FORGE_AUTHOR, canForgeAuthor);

    // Rebase the second change on behalf of the uploader
    requestScopeOperations.setApiUser(rebaser);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput);

    RevisionInfo currentRevisionInfo =
        gApi.changes().id(changeToBeRebased.get()).get().getCurrentRevision();
    // The change had 1 patch set before the rebase, now it should be 2
    assertThat(currentRevisionInfo._number).isEqualTo(2);
    assertThat(currentRevisionInfo.commit.author.email).isEqualTo(authorEmail);
    assertThat(currentRevisionInfo.uploader._accountId).isEqualTo(uploader.get());
    assertThat(currentRevisionInfo.realUploader._accountId).isEqualTo(rebaser.get());
  }

  @Test
  public void
      cannotRebaseChangeWithForgedAuthorOnBehalfOfUploaderIfTheUploaderHasNoForgeAuthorPermission()
          throws Exception {
    allowPermissionToAllUsers(Permission.REBASE);

    String uploaderEmail = "uploader@example.com";
    Account.Id uploader = accountOperations.newAccount().preferredEmail(uploaderEmail).create();
    Account.Id author = accountOperations.newAccount().create();
    Account.Id approver = admin.id();
    Account.Id rebaser = accountOperations.newAccount().create();

    // Create two changes both with the same parent. Forge the author of the change that will be
    // rebased.
    requestScopeOperations.setApiUser(uploader);
    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased =
        changeOperations.newChange().project(project).owner(uploader).author(author).create();

    // Approve and submit the change that will be the new base for the change that will be rebased.
    requestScopeOperations.setApiUser(approver);
    gApi.changes().id(changeToBeTheNewBase.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase.get()).current().submit();

    // Block forge author permission for uploader. Without the forge author permission it should not
    // be possible to rebase the change on behalf of the uploader.
    AccountGroup.UUID cannotForgeAuthor =
        groupOperations.newGroup().name("cannot-forge-author").addMember(uploader).create();
    blockPermission(Permission.FORGE_AUTHOR, cannotForgeAuthor);

    // Try to rebase the second change on behalf of the uploader
    requestScopeOperations.setApiUser(rebaser);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    ResourceConflictException exception =
        assertThrows(
            ResourceConflictException.class,
            () -> gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(
            String.format(
                "change %s: author of patch set 1 is forged and the uploader %s cannot forge"
                    + " author",
                changeToBeRebased, uploaderEmail));
  }

  @Test
  public void
      rebaseChangeWithForgedCommitterOnBehalfOfUploaderDoesntRequireForgeCommitterPermission()
          throws Exception {
    allowPermissionToAllUsers(Permission.REBASE);

    String uploaderEmail = "uploader@example.com";
    Account.Id uploader = accountOperations.newAccount().preferredEmail(uploaderEmail).create();
    Account.Id committer =
        accountOperations.newAccount().preferredEmail("committer@example.com").create();
    Account.Id approver = admin.id();
    Account.Id rebaser = accountOperations.newAccount().create();

    // Create two changes both with the same parent. Forge the committer of the change that will be
    // rebased.
    requestScopeOperations.setApiUser(uploader);
    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased =
        changeOperations.newChange().project(project).owner(uploader).committer(committer).create();

    // Approve and submit the change that will be the new base for the change that will be rebased.
    requestScopeOperations.setApiUser(approver);
    gApi.changes().id(changeToBeTheNewBase.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase.get()).current().submit();

    // Rebase the second change on behalf of the uploader
    requestScopeOperations.setApiUser(rebaser);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput);

    RevisionInfo currentRevisionInfo =
        gApi.changes().id(changeToBeRebased.get()).get().getCurrentRevision();
    // The change had 1 patch set before the rebase, now it should be 2
    assertThat(currentRevisionInfo._number).isEqualTo(2);
    assertThat(currentRevisionInfo.commit.committer.email).isEqualTo(uploaderEmail);
    assertThat(currentRevisionInfo.uploader._accountId).isEqualTo(uploader.get());
    assertThat(currentRevisionInfo.realUploader._accountId).isEqualTo(rebaser.get());
  }

  @Test
  public void rebaseChangeWithServerIdentOnBehalfOfUploader() throws Exception {
    allowPermissionToAllUsers(Permission.REBASE);

    String uploaderEmail = "uploader@example.com";
    Account.Id uploader = accountOperations.newAccount().preferredEmail(uploaderEmail).create();
    Account.Id approver = admin.id();
    Account.Id rebaser = accountOperations.newAccount().create();

    // Create two changes both with the same parent. Use the server identity as the author of the
    // change that will be rebased.
    requestScopeOperations.setApiUser(uploader);
    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased =
        changeOperations
            .newChange()
            .project(project)
            .owner(uploader)
            .authorIdent(serverIdent.get())
            .create();

    // Approve and submit the change that will be the new base for the change that will be rebased.
    requestScopeOperations.setApiUser(approver);
    gApi.changes().id(changeToBeTheNewBase.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase.get()).current().submit();

    // Grant forge author and forge server permission for uploader. Without these permissions it is
    // not possible to rebase the change on behalf of the uploader.
    AccountGroup.UUID canForgeAuthorAndForgeServer =
        groupOperations
            .newGroup()
            .name("can-forge-author-and-forge-server")
            .addMember(uploader)
            .create();
    allowPermission(Permission.FORGE_AUTHOR, canForgeAuthorAndForgeServer);
    allowPermission(Permission.FORGE_SERVER, canForgeAuthorAndForgeServer);

    // Rebase the second change on behalf of the uploader.
    requestScopeOperations.setApiUser(rebaser);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput);

    RevisionInfo currentRevisionInfo =
        gApi.changes().id(changeToBeRebased.get()).get().getCurrentRevision();
    // The change had 1 patch set before the rebase, now it should be 2
    assertThat(currentRevisionInfo._number).isEqualTo(2);
    assertThat(currentRevisionInfo.commit.author.email)
        .isEqualTo(serverIdent.get().getEmailAddress());
    assertThat(currentRevisionInfo.uploader._accountId).isEqualTo(uploader.get());
    assertThat(currentRevisionInfo.realUploader._accountId).isEqualTo(rebaser.get());
  }

  @Test
  public void
      cannotRebaseChangeWithServerIdentOnBehalfOfUploaderIfTheUploaderHasNoForgeServerPermission()
          throws Exception {
    allowPermissionToAllUsers(Permission.REBASE);

    String uploaderEmail = "uploader@example.com";
    Account.Id uploader = accountOperations.newAccount().preferredEmail(uploaderEmail).create();
    Account.Id approver = admin.id();
    Account.Id rebaser = accountOperations.newAccount().create();

    // Create two changes both with the same parent. Use the server identity as the author of the
    // change that will be rebased.
    requestScopeOperations.setApiUser(uploader);
    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased =
        changeOperations
            .newChange()
            .project(project)
            .owner(uploader)
            .authorIdent(serverIdent.get())
            .create();

    // Approve and submit the change that will be the new base for the change that will be rebased.
    requestScopeOperations.setApiUser(approver);
    gApi.changes().id(changeToBeTheNewBase.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase.get()).current().submit();

    // Grant forge author permission for uploader, but not the forge server permission. Without the
    // forge server permission it is not possible to rebase the change on behalf of the uploader.
    AccountGroup.UUID canForgeAuthor =
        groupOperations.newGroup().name("can-forge-author").addMember(uploader).create();
    allowPermission(Permission.FORGE_AUTHOR, canForgeAuthor);

    // Try to rebase the second change on behalf of the uploader.
    requestScopeOperations.setApiUser(rebaser);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    ResourceConflictException exception =
        assertThrows(
            ResourceConflictException.class,
            () -> gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(
            String.format(
                "change %s: author of patch set 1 is the server identity and the uploader %s cannot"
                    + " forge the server identity",
                changeToBeRebased, uploaderEmail));
  }

  @Test
  public void rebaseActionEnabled_withRebasePermission() throws Exception {
    allowPermissionToAllUsers(Permission.REBASE);
    testRebaseActionEnabled();
  }

  @Test
  public void rebaseActionEnabled_withSubmitPermission() throws Exception {
    allowPermissionToAllUsers(Permission.SUBMIT);
    testRebaseActionEnabled();
  }

  private void testRebaseActionEnabled() throws Exception {
    Account.Id uploader = accountOperations.newAccount().create();
    Account.Id approver = admin.id();
    Account.Id rebaser = accountOperations.newAccount().create();

    // Block push permission for rebaser, as in contrast to rebase, rebase on behalf of the uploader
    // doesn't require the rebaser to have the push permission.
    AccountGroup.UUID cannotUploadGroup =
        groupOperations.newGroup().name("cannot-upload").addMember(rebaser).create();
    blockPermission(Permission.PUSH, cannotUploadGroup);

    // Create two changes both with the same parent
    requestScopeOperations.setApiUser(uploader);
    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased =
        changeOperations.newChange().project(project).owner(uploader).create();

    // Approve and submit the change that will be the new base for the change that will be rebased.
    requestScopeOperations.setApiUser(approver);
    gApi.changes().id(changeToBeTheNewBase.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase.get()).current().submit();

    requestScopeOperations.setApiUser(rebaser);
    RevisionInfo revisionInfo =
        gApi.changes().id(changeToBeRebased.get()).get().getCurrentRevision();
    assertThat(revisionInfo.actions).containsKey("rebase");
    ActionInfo rebaseActionInfo = revisionInfo.actions.get("rebase");
    assertThat(rebaseActionInfo.enabled).isTrue();

    // rebase is disabled because rebaser doesn't have the 'Push' permission and hence cannot create
    // new patch sets
    assertThat(rebaseActionInfo.enabledOptions).containsExactly("rebase_on_behalf_of_uploader");
  }

  @Test
  public void rebaseActionEnabled_forChangeOwner() throws Exception {
    Account.Id changeOwner = accountOperations.newAccount().create();
    Account.Id approver = admin.id();

    // Create two changes both with the same parent
    requestScopeOperations.setApiUser(changeOwner);
    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().project(project).owner(changeOwner).create();
    Change.Id changeToBeRebased =
        changeOperations.newChange().project(project).owner(changeOwner).create();

    // Approve and submit the change that will be the new base for the change that will be rebased.
    requestScopeOperations.setApiUser(approver);
    gApi.changes().id(changeToBeTheNewBase.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase.get()).current().submit();

    requestScopeOperations.setApiUser(changeOwner);
    RevisionInfo revisionInfo =
        gApi.changes().id(changeToBeRebased.get()).get().getCurrentRevision();
    assertThat(revisionInfo.actions).containsKey("rebase");
    ActionInfo rebaseActionInfo = revisionInfo.actions.get("rebase");
    assertThat(rebaseActionInfo.enabled).isTrue();

    // rebase is enabled because change owner has the 'Push' permission and hence can create new
    // patch sets
    assertThat(rebaseActionInfo.enabledOptions)
        .containsExactly("rebase", "rebase_on_behalf_of_uploader");
  }

  @UseLocalDisk
  @Test
  public void rebaseChangeOnBehalfOfUploaderRecordsUploaderInRefLog() throws Exception {
    allowPermissionToAllUsers(Permission.REBASE);

    String uploaderEmail = "uploader@example.com";
    Account.Id uploader = accountOperations.newAccount().preferredEmail(uploaderEmail).create();
    Account.Id approver = admin.id();
    Account.Id rebaser = accountOperations.newAccount().create();

    // Create two changes both with the same parent
    requestScopeOperations.setApiUser(uploader);
    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased =
        changeOperations.newChange().project(project).owner(uploader).create();

    // Approve and submit the change that will be the new base for the change that will be rebased.
    requestScopeOperations.setApiUser(approver);
    gApi.changes().id(changeToBeTheNewBase.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase.get()).current().submit();

    try (Repository repo = repoManager.openRepository(project)) {
      String changeMetaRef = RefNames.changeMetaRef(changeToBeRebased);
      String patchSetRef = RefNames.patchSetRef(PatchSet.id(changeToBeRebased, 2));
      createRefLogFileIfMissing(repo, changeMetaRef);
      createRefLogFileIfMissing(repo, patchSetRef);

      // Rebase the second change on behalf of the uploader
      requestScopeOperations.setApiUser(rebaser);
      RebaseInput rebaseInput = new RebaseInput();
      rebaseInput.onBehalfOfUploader = true;
      gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput);

      // The ref log for the patch set ref records the impersonated user aka the uploader.
      ReflogEntry patchSetRefLogEntry = repo.getReflogReader(patchSetRef).getLastEntry();
      assertThat(patchSetRefLogEntry.getWho().getEmailAddress()).isEqualTo(uploaderEmail);

      // The ref log for the change meta ref records the impersonated user aka the uploader.
      ReflogEntry changeMetaRefLogEntry = repo.getReflogReader(changeMetaRef).getLastEntry();
      assertThat(changeMetaRefLogEntry.getWho().getEmailAddress()).isEqualTo(uploaderEmail);
    }
  }

  @Test
  public void rebaserCanApproveChangeAfterRebasingOnBehalfOfUploader() throws Exception {
    // Require a Code-Review approval from a non-uploader for submit.
    try (ProjectConfigUpdate u = updateProject(project)) {
      u.getConfig()
          .upsertSubmitRequirement(
              SubmitRequirement.builder()
                  .setName(TestLabels.codeReview().getName())
                  .setSubmittabilityExpression(
                      SubmitRequirementExpression.create(
                          String.format(
                              "label:%s=MAX,user=non_uploader", TestLabels.codeReview().getName())))
                  .setAllowOverrideInChildProjects(false)
                  .build());
      u.save();
    }

    allowPermissionToAllUsers(Permission.REBASE);

    String uploaderEmail = "uploader@example.com";
    Account.Id uploader = accountOperations.newAccount().preferredEmail(uploaderEmail).create();
    Account.Id approver = admin.id();
    Account.Id rebaser = accountOperations.newAccount().create();

    // Create two changes both with the same parent
    requestScopeOperations.setApiUser(uploader);
    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased =
        changeOperations.newChange().project(project).owner(uploader).create();

    // Approve and submit the change that will be the new base for the change that will be rebased.
    requestScopeOperations.setApiUser(approver);
    gApi.changes().id(changeToBeTheNewBase.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase.get()).current().submit();

    // Rebase it on behalf of the uploader
    requestScopeOperations.setApiUser(rebaser);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput);

    // Approve the change as the rebaser.
    allowVotingOnCodeReviewToAllUsers();
    gApi.changes().id(changeToBeRebased.get()).current().review(ReviewInput.approve());

    // The change is submittable because the approval is from a user (the rebaser) that is not the
    // uploader.
    assertThat(gApi.changes().id(changeToBeRebased.get()).get().submittable).isTrue();

    // Create and submit another change so that we can rebase the change once again.
    requestScopeOperations.setApiUser(approver);
    Change.Id changeToBeTheNewBase2 =
        changeOperations.newChange().project(project).owner(uploader).create();
    gApi.changes().id(changeToBeTheNewBase2.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase2.get()).current().submit();

    // Doing a normal rebase (not on behalf of the uploader) makes the rebaser the uploader. This
    // makse the change non-submittable since the approval of the rebaser is ignored now (due to
    // using 'user=non_uploader' in the submit requirement expression).
    requestScopeOperations.setApiUser(rebaser);
    rebaseInput.onBehalfOfUploader = false;
    gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput);
    gApi.changes().id(changeToBeRebased.get()).current().review(ReviewInput.approve());
    assertThat(gApi.changes().id(changeToBeRebased.get()).get().submittable).isFalse();
  }

  @Test
  public void testSubmittedWithRebaserApprovalMetric() throws Exception {
    allowVotingOnCodeReviewToAllUsers();

    createVerifiedLabel();
    allowVotingOnVerifiedToAllUsers();

    // Require a Code-Review approval from a non-uploader for submit.
    try (ProjectConfigUpdate u = updateProject(project)) {
      u.getConfig()
          .upsertSubmitRequirement(
              SubmitRequirement.builder()
                  .setName(TestLabels.verified().getName())
                  .setSubmittabilityExpression(
                      SubmitRequirementExpression.create(
                          String.format("label:%s=MAX", TestLabels.verified().getName())))
                  .setAllowOverrideInChildProjects(false)
                  .build());
      u.getConfig()
          .upsertSubmitRequirement(
              SubmitRequirement.builder()
                  .setName(TestLabels.codeReview().getName())
                  .setSubmittabilityExpression(
                      SubmitRequirementExpression.create(
                          String.format(
                              "label:%s=MAX,user=non_uploader", TestLabels.codeReview().getName())))
                  .setAllowOverrideInChildProjects(false)
                  .build());
      u.save();
    }

    allowPermissionToAllUsers(Permission.REBASE);

    String uploaderEmail = "uploader@example.com";
    Account.Id uploader = accountOperations.newAccount().preferredEmail(uploaderEmail).create();
    Account.Id approver = admin.id();
    Account.Id rebaser = accountOperations.newAccount().create();

    // Create two changes both with the same parent
    requestScopeOperations.setApiUser(uploader);
    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased =
        changeOperations.newChange().project(project).owner(uploader).create();

    // Approve and submit the change that will be the new base for the change that will be rebased.
    requestScopeOperations.setApiUser(approver);
    gApi.changes()
        .id(changeToBeTheNewBase.get())
        .current()
        .review(ReviewInput.approve().label(TestLabels.verified().getName(), 1));
    testMetricMaker.reset();
    gApi.changes().id(changeToBeTheNewBase.get()).current().submit();
    assertThat(testMetricMaker.getCount("change/submitted_with_rebaser_approval")).isEqualTo(0);

    // Rebase it on behalf of the uploader
    requestScopeOperations.setApiUser(rebaser);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput);

    // Approve the change as the rebaser.
    gApi.changes()
        .id(changeToBeRebased.get())
        .current()
        .review(ReviewInput.approve().label(TestLabels.verified().getName(), 1));

    // The change is submittable because the approval is from a user (the rebaser) that is not the
    // uploader.
    allowPermissionToAllUsers(Permission.SUBMIT);
    testMetricMaker.reset();
    gApi.changes().id(changeToBeRebased.get()).current().submit();
    assertThat(testMetricMaker.getCount("change/submitted_with_rebaser_approval")).isEqualTo(1);
  }

  @Test
  public void submittedWithRebaserApprovalMetricIsNotIncreasedIfANonRebaserApprovalIsPresent()
      throws Exception {
    allowVotingOnCodeReviewToAllUsers();

    createVerifiedLabel();
    allowVotingOnVerifiedToAllUsers();

    // Require a Code-Review approval from a non-uploader for submit.
    try (ProjectConfigUpdate u = updateProject(project)) {
      u.getConfig()
          .upsertSubmitRequirement(
              SubmitRequirement.builder()
                  .setName(TestLabels.verified().getName())
                  .setSubmittabilityExpression(
                      SubmitRequirementExpression.create(
                          String.format("label:%s=MAX", TestLabels.verified().getName())))
                  .setAllowOverrideInChildProjects(false)
                  .build());
      u.getConfig()
          .upsertSubmitRequirement(
              SubmitRequirement.builder()
                  .setName(TestLabels.codeReview().getName())
                  .setSubmittabilityExpression(
                      SubmitRequirementExpression.create(
                          String.format(
                              "label:%s=MAX,user=non_uploader", TestLabels.codeReview().getName())))
                  .setAllowOverrideInChildProjects(false)
                  .build());
      u.save();
    }

    allowPermissionToAllUsers(Permission.REBASE);

    String uploaderEmail = "uploader@example.com";
    Account.Id uploader = accountOperations.newAccount().preferredEmail(uploaderEmail).create();
    Account.Id approver = admin.id();
    Account.Id rebaser = accountOperations.newAccount().create();

    // Create two changes both with the same parent
    requestScopeOperations.setApiUser(uploader);
    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased =
        changeOperations.newChange().project(project).owner(uploader).create();

    // Approve and submit the change that will be the new base for the change that will be rebased.
    requestScopeOperations.setApiUser(approver);
    gApi.changes()
        .id(changeToBeTheNewBase.get())
        .current()
        .review(ReviewInput.approve().label(TestLabels.verified().getName(), 1));
    testMetricMaker.reset();
    gApi.changes().id(changeToBeTheNewBase.get()).current().submit();
    assertThat(testMetricMaker.getCount("change/submitted_with_rebaser_approval")).isEqualTo(0);

    // Rebase it on behalf of the uploader
    requestScopeOperations.setApiUser(rebaser);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput);

    // Approve the change as the rebaser.
    gApi.changes()
        .id(changeToBeRebased.get())
        .current()
        .review(ReviewInput.approve().label(TestLabels.verified().getName(), 1));

    // Approve the change as another user.
    requestScopeOperations.setApiUser(approver);
    gApi.changes().id(changeToBeRebased.get()).current().review(ReviewInput.approve());

    // Due to the second approval the change would also be submittable if the approval of the
    // rebaser would be ignored due to the rebaser being the uploader.
    allowPermissionToAllUsers(Permission.SUBMIT);
    testMetricMaker.reset();
    gApi.changes().id(changeToBeRebased.get()).current().submit();
    assertThat(testMetricMaker.getCount("change/submitted_with_rebaser_approval")).isEqualTo(0);
  }

  @Test
  public void testCountRebasesMetric() throws Exception {
    allowPermissionToAllUsers(Permission.REBASE);

    Account.Id uploader = accountOperations.newAccount().create();
    Account.Id approver = admin.id();
    Account.Id rebaser = accountOperations.newAccount().create();

    // Create two changes both with the same parent
    requestScopeOperations.setApiUser(uploader);
    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased =
        changeOperations.newChange().project(project).owner(uploader).create();

    // Approve and submit the change that will be the new base for the change that will be rebased.
    requestScopeOperations.setApiUser(approver);
    gApi.changes().id(changeToBeTheNewBase.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase.get()).current().submit();

    // Rebase it on behalf of the uploader
    testMetricMaker.reset();
    requestScopeOperations.setApiUser(rebaser);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput);
    // field1 is on_behalf_of_uploader, field2 is rebase_chain, field3 is allow_conflicts
    assertThat(testMetricMaker.getCount("change/count_rebases", true, false, false)).isEqualTo(1);
    assertThat(testMetricMaker.getCount("change/count_rebases", false, false, false)).isEqualTo(0);
    assertThat(testMetricMaker.getCount("change/count_rebases", true, true, false)).isEqualTo(0);
    assertThat(testMetricMaker.getCount("change/count_rebases", false, true, false)).isEqualTo(0);

    // Create and submit another change so that we can rebase the change once again.
    requestScopeOperations.setApiUser(approver);
    Change.Id changeToBeTheNewBase2 =
        changeOperations.newChange().project(project).owner(uploader).create();
    gApi.changes().id(changeToBeTheNewBase2.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeTheNewBase2.get()).current().submit();

    // Rebase the change once again, this time as the uploader.
    // If the uploader sets on_behalf_of_uploader = true, the flag is ignored and a normal rebase is
    // done, hence the metric should count this as a a rebase with on_behalf_of_uploader = false.
    requestScopeOperations.setApiUser(uploader);
    testMetricMaker.reset();
    gApi.changes().id(changeToBeRebased.get()).rebase(rebaseInput);
    // field1 is on_behalf_of_uploader, field2 is rebase_chain, field3 is allow_conflicts
    assertThat(testMetricMaker.getCount("change/count_rebases", false, false, false)).isEqualTo(1);
    assertThat(testMetricMaker.getCount("change/count_rebases", true, false, false)).isEqualTo(0);
    assertThat(testMetricMaker.getCount("change/count_rebases", false, true, false)).isEqualTo(0);
    assertThat(testMetricMaker.getCount("change/count_rebases", true, true, false)).isEqualTo(0);
  }

  private void allowPermissionToAllUsers(String permission) {
    allowPermission(permission, REGISTERED_USERS);
  }

  private void allowPermission(String permission, AccountGroup.UUID groupUuid) {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(permission).ref("refs/*").group(groupUuid))
        .update();
  }

  private void allowVotingOnCodeReviewToAllUsers() {
    projectOperations
        .project(project)
        .forUpdate()
        .add(
            allowLabel(TestLabels.codeReview().getName())
                .ref("refs/*")
                .group(REGISTERED_USERS)
                .range(-2, 2))
        .update();
  }

  private void createVerifiedLabel() throws Exception {
    try (ProjectConfigUpdate u = updateProject(project)) {
      LabelType.Builder verified =
          labelBuilder(
                  LabelId.VERIFIED, value(1, "Passes"), value(0, "No score"), value(-1, "Failed"))
              .setCopyCondition("is:MIN");
      u.getConfig().upsertLabelType(verified.build());
      u.save();
    }
  }

  private void allowVotingOnVerifiedToAllUsers() {
    projectOperations
        .project(project)
        .forUpdate()
        .add(
            allowLabel(TestLabels.verified().getName())
                .ref("refs/*")
                .group(REGISTERED_USERS)
                .range(-1, 1))
        .update();
  }

  private void blockPermissionForAllUsers(String permission) {
    blockPermission(permission, REGISTERED_USERS);
  }

  private void blockPermission(String permission, AccountGroup.UUID groupUuid) {
    projectOperations
        .project(project)
        .forUpdate()
        .add(block(permission).ref("refs/*").group(groupUuid))
        .update();
  }

  @FunctionalInterface
  private interface RebaseCall {
    void call(Change.Id changeId, RebaseInput rebaseInput) throws RestApiException;
  }

  private static class TestRevisionCreatedListener implements RevisionCreatedListener {
    public RevisionInfo revisionInfo;

    @Override
    public void onRevisionCreated(Event event) {
      revisionInfo = event.getRevision();
    }
  }
}
