// 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.common.truth.Truth8.assertThat;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allow;
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.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.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.Change;
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.HashMap;
import java.util.Map;
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.RebaseChain} REST endpoint with the
 * {@link RebaseInput#onBehalfOfUploader} option being set.
 *
 * <p>Rebasing a single change on behalf of the uploader is covered by {@link
 * RebaseOnBehalfOfUploaderIT}.
 */
public class RebaseChainOnBehalfOfUploaderIT 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()).rebaseChain(rebaseInput));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo("allow_conflicts and on_behalf_of_uploader are mutually exclusive");
  }

  @Test
  public void rebaseChangeOnBehalfOfUploader_withRebasePermission() throws Exception {
    testRebaseChainOnBehalfOfUploader(Permission.REBASE);
  }

  @Test
  public void rebaseChangeOnBehalfOfUploader_withSubmitPermission() throws Exception {
    testRebaseChainOnBehalfOfUploader(Permission.SUBMIT);
  }

  private void testRebaseChainOnBehalfOfUploader(String permissionToAllow) throws Exception {
    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 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);

    Change.Id changeToBeTheNewBase = changeOperations.newChange().project(project).create();

    // Create a chain of changes for being rebased, each change with a different uploader.
    Account.Id uploader1 =
        accountOperations.newAccount().preferredEmail("uploader1@example.com").create();
    Change.Id changeToBeRebased1 =
        changeOperations.newChange().project(project).owner(uploader1).create();

    Account.Id uploader2 =
        accountOperations.newAccount().preferredEmail("uploader2@example.com").create();
    Change.Id changeToBeRebased2 =
        changeOperations
            .newChange()
            .project(project)
            .childOf()
            .change(changeToBeRebased1)
            .owner(uploader2)
            .create();

    Account.Id uploader3 =
        accountOperations.newAccount().preferredEmail("uploader3@example.com").create();
    Change.Id changeToBeRebased3 =
        changeOperations
            .newChange()
            .project(project)
            .childOf()
            .change(changeToBeRebased2)
            .owner(uploader3)
            .create();

    Account.Id uploader4 =
        accountOperations.newAccount().preferredEmail("uploader4@example.com").create();
    Change.Id changeToBeRebased4 =
        changeOperations
            .newChange()
            .project(project)
            .childOf()
            .change(changeToBeRebased3)
            .owner(uploader4)
            .create();

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

    // Approve and submit the change that will be the new base for the chain 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 chain on behalf of the uploaders through changeToBeRebased4
    requestScopeOperations.setApiUser(rebaser);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;

    TestRevisionCreatedListener testRevisionCreatedListener = new TestRevisionCreatedListener();
    try (Registration registration =
        extensionRegistry.newRegistration().add(testRevisionCreatedListener)) {
      gApi.changes().id(changeToBeRebased4.get()).rebaseChain(rebaseInput);

      testRevisionCreatedListener.assertUploaders(changeToBeRebased1, uploader1, rebaser);
      testRevisionCreatedListener.assertUploaders(changeToBeRebased2, uploader2, rebaser);
      testRevisionCreatedListener.assertUploaders(changeToBeRebased3, uploader3, rebaser);
      testRevisionCreatedListener.assertUploaders(changeToBeRebased4, uploader4, rebaser);
    }

    assertRebase(changeToBeRebased1, 2, uploader1, rebaser);
    assertRebase(changeToBeRebased2, 2, uploader2, rebaser);
    assertRebase(changeToBeRebased3, 2, uploader3, rebaser);
    assertRebase(changeToBeRebased4, 2, uploader4, rebaser);
  }

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

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

    Change.Id changeToBeTheNewBase = changeOperations.newChange().project(project).create();

    // Create a chain of changes for being rebased, each change with a different uploader.
    Account.Id uploader1 =
        accountOperations.newAccount().preferredEmail("uploader1@example.com").create();
    Change.Id changeToBeRebased1 =
        changeOperations.newChange().project(project).owner(uploader1).create();

    Account.Id uploader2 =
        accountOperations.newAccount().preferredEmail("uploader2@example.com").create();
    Change.Id changeToBeRebased2 =
        changeOperations
            .newChange()
            .project(project)
            .childOf()
            .change(changeToBeRebased1)
            .owner(uploader2)
            .create();

    // Approve and submit the change that will be the new base for the chain 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 chain on behalf of the uploaders.
    requestScopeOperations.setApiUser(rebaser);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    gApi.changes().id(changeToBeRebased2.get()).rebaseChain(rebaseInput);

    assertRebase(changeToBeRebased1, 2, uploader1, rebaser);
    assertRebase(changeToBeRebased2, 2, uploader2, rebaser);

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

    // Rebase the chain once again on behalf of the uploaders.
    requestScopeOperations.setApiUser(rebaser);
    gApi.changes().id(changeToBeRebased2.get()).rebaseChain(rebaseInput);

    assertRebase(changeToBeRebased1, 3, uploader1, rebaser);
    assertRebase(changeToBeRebased2, 3, uploader2, rebaser);
  }

  @Test
  public void nonChangeOwnerWithoutSubmitAndRebasePermissionCannotRebaseChainOnBehalfOfUploader()
      throws Exception {
    Change.Id changeToBeRebased1 = changeOperations.newChange().project(project).create();
    Change.Id changeToBeRebased2 =
        changeOperations.newChange().project(project).childOf().change(changeToBeRebased1).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(changeToBeRebased2.get()).rebaseChain(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 cannotRebaseChainOnBehalfOfUploaderIfTheUploaderHasNoReadPermission()
      throws Exception {
    String uploaderEmail = "uploader@example.com";
    testCannotRebaseChainOnBehalfOfUploaderIfTheUploaderHasNoPermission(
        uploaderEmail,
        Permission.READ,
        String.format("uploader %s cannot read change", uploaderEmail));
  }

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

  private void testCannotRebaseChainOnBehalfOfUploaderIfTheUploaderHasNoPermission(
      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();

    Change.Id changeToBeTheNewBase = changeOperations.newChange().project(project).create();

    Change.Id changeToBeRebased1 =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased2 =
        changeOperations
            .newChange()
            .project(project)
            .owner(uploader)
            .childOf()
            .change(changeToBeRebased1)
            .create();

    // Approve and submit the change that will be the new base for the chain 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 chain on behalf of the uploader.
    requestScopeOperations.setApiUser(rebaser);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    ResourceConflictException exception =
        assertThrows(
            ResourceConflictException.class,
            () -> gApi.changes().id(changeToBeRebased2.get()).rebaseChain(rebaseInput));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(String.format("change %s: %s", changeToBeRebased1, expectedErrorMessage));
  }

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

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

    Change.Id changeToBeTheNewBase = changeOperations.newChange().project(project).create();

    Change.Id changeToBeRebased1 =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased2 =
        changeOperations
            .newChange()
            .project(project)
            .owner(uploader)
            .childOf()
            .change(changeToBeRebased1)
            .create();

    // Approve and submit the change that will be the new base for the chain 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 chain as uploader on behalf of the uploader
    requestScopeOperations.setApiUser(uploader);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    gApi.changes().id(changeToBeRebased2.get()).rebaseChain(rebaseInput);

    assertRebase(changeToBeRebased1, 2, uploader, /* expectedRealUploader= */ null);
    assertRebase(changeToBeRebased2, 2, uploader, /* expectedRealUploader= */ null);
  }

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

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

    Change.Id changeToBeTheNewBase = changeOperations.newChange().project(project).create();

    Change.Id changeToBeRebased1 =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased2 =
        changeOperations
            .newChange()
            .project(project)
            .owner(uploader)
            .childOf()
            .change(changeToBeRebased1)
            .create();

    // Approve and submit the change that will be the new base for the chain 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 the uploader aka the rebaser. This permission is required for creating the new
    // patch set and if it is blocked we expect the rebase to fail.
    AccountGroup.UUID cannotPushGroup =
        groupOperations.newGroup().name("cannot-push").addMember(uploader).create();
    blockPermission(Permission.PUSH, cannotPushGroup);

    // Rebase the chain 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(changeToBeRebased2.get()).rebaseChain(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 rebaseChainOnBehalfOfUploaderWhenUploaderIsNotTheChangeOwner() throws Exception {
    allowPermissionToAllUsers(Permission.REBASE);

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

    Change.Id changeToBeTheNewBase = changeOperations.newChange().project(project).create();

    Change.Id changeToBeRebased1 =
        changeOperations.newChange().project(project).owner(changeOwner).create();
    Change.Id changeToBeRebased2 =
        changeOperations
            .newChange()
            .project(project)
            .owner(changeOwner)
            .childOf()
            .change(changeToBeRebased1)
            .create();

    // Create a second patch set for the second change in the chain 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(changeToBeRebased2)
        .newPatchset()
        .uploader(uploader)
        .author(uploader)
        .committer(uploader)
        .create();

    // Approve and submit the change that will be the new base for the chain 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 chain on behalf of the uploader
    requestScopeOperations.setApiUser(rebaser);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    gApi.changes().id(changeToBeRebased2.get()).rebaseChain(rebaseInput);

    assertRebase(changeToBeRebased1, 2, changeOwner, rebaser);
    assertRebase(changeToBeRebased2, 3, uploader, rebaser);
  }

  @Test
  public void
      cannotRebaseChainOnBehalfOfUploaderWhenUploaderIsNotTheChangeOwnerAndDoesntHaveAddPatchSetPermission()
          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();

    Change.Id changeToBeTheNewBase = changeOperations.newChange().project(project).create();

    Change.Id changeToBeRebased1 =
        changeOperations.newChange().project(project).owner(changeOwner).create();
    Change.Id changeToBeRebased2 =
        changeOperations
            .newChange()
            .project(project)
            .owner(changeOwner)
            .childOf()
            .change(changeToBeRebased1)
            .create();

    // Create a second patch set for the second change in the chain 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(changeToBeRebased2)
        .newPatchset()
        .uploader(uploader)
        .author(uploader)
        .committer(uploader)
        .create();

    // Approve and submit the change that will be the new base for the chain 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 chain on behalf of the uploader
    requestScopeOperations.setApiUser(rebaser);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    ResourceConflictException exception =
        assertThrows(
            ResourceConflictException.class,
            () -> gApi.changes().id(changeToBeRebased2.get()).rebaseChain(rebaseInput));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(
            String.format(
                "change %s: uploader %s cannot add patch set", changeToBeRebased2, uploaderEmail));
  }

  @Test
  public void rebaseChainWithForgedAuthorOnBehalfOfUploader() 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();

    Change.Id changeToBeTheNewBase = changeOperations.newChange().project(project).create();

    Change.Id changeToBeRebased1 =
        changeOperations.newChange().project(project).owner(uploader).author(author).create();
    Change.Id changeToBeRebased2 =
        changeOperations
            .newChange()
            .project(project)
            .owner(uploader)
            .author(author)
            .childOf()
            .change(changeToBeRebased1)
            .create();

    // Approve and submit the change that will be the new base for the chain 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(changeToBeRebased2.get()).rebaseChain(rebaseInput);

    RevisionInfo currentRevisionInfo =
        gApi.changes().id(changeToBeRebased1.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());

    currentRevisionInfo = gApi.changes().id(changeToBeRebased2.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
      cannotRebaseChainWithForgedAuthorOnBehalfOfUploaderIfTheUploaderHasNoForgeAuthorPermission()
          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();

    Change.Id changeToBeTheNewBase = changeOperations.newChange().project(project).create();

    Change.Id changeToBeRebased1 =
        changeOperations.newChange().project(project).owner(uploader).author(author).create();
    Change.Id changeToBeRebased2 =
        changeOperations
            .newChange()
            .project(project)
            .owner(uploader)
            .author(author)
            .childOf()
            .change(changeToBeRebased1)
            .create();

    // Approve and submit the change that will be the new base for the chain 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 chain 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(changeToBeRebased2.get()).rebaseChain(rebaseInput));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo(
            String.format(
                "change %s: author of patch set 1 is forged and the uploader %s cannot forge author",
                changeToBeRebased1, uploaderEmail));
  }

  @Test
  public void
      rebaseChainWithForgedCommitterOnBehalfOfUploaderDoesntRequireForgeCommitterPermission()
          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();

    Change.Id changeToBeTheNewBase = changeOperations.newChange().project(project).create();

    Change.Id changeToBeRebased1 =
        changeOperations.newChange().project(project).owner(uploader).committer(committer).create();
    Change.Id changeToBeRebased2 =
        changeOperations
            .newChange()
            .project(project)
            .owner(uploader)
            .committer(committer)
            .childOf()
            .change(changeToBeRebased1)
            .create();

    // Approve and submit the change that will be the new base for the chain 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(changeToBeRebased2.get()).rebaseChain(rebaseInput);

    RevisionInfo currentRevisionInfo =
        gApi.changes().id(changeToBeRebased1.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());

    currentRevisionInfo = gApi.changes().id(changeToBeRebased2.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 rebaseChainWithServerIdentOnBehalfOfUploader() 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();

    Change.Id changeToBeTheNewBase = changeOperations.newChange().project(project).create();

    Change.Id changeToBeRebased1 =
        changeOperations
            .newChange()
            .project(project)
            .owner(uploader)
            .authorIdent(serverIdent.get())
            .create();
    Change.Id changeToBeRebased2 =
        changeOperations
            .newChange()
            .project(project)
            .owner(uploader)
            .authorIdent(serverIdent.get())
            .childOf()
            .change(changeToBeRebased1)
            .create();

    // Approve and submit the change that will be the new base for the chain 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 chain on behalf of the uploader.
    requestScopeOperations.setApiUser(rebaser);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    gApi.changes().id(changeToBeRebased2.get()).rebaseChain(rebaseInput);

    RevisionInfo currentRevisionInfo =
        gApi.changes().id(changeToBeRebased1.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());

    currentRevisionInfo = gApi.changes().id(changeToBeRebased2.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
      cannotRebaseChainWithServerIdentOnBehalfOfUploaderIfTheUploaderHasNoForgeServerPermission()
          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();

    Change.Id changeToBeTheNewBase = changeOperations.newChange().project(project).create();

    Change.Id changeToBeRebased1 =
        changeOperations
            .newChange()
            .project(project)
            .owner(uploader)
            .authorIdent(serverIdent.get())
            .create();
    Change.Id changeToBeRebased2 =
        changeOperations
            .newChange()
            .project(project)
            .owner(uploader)
            .authorIdent(serverIdent.get())
            .childOf()
            .change(changeToBeRebased1)
            .create();

    // Approve and submit the change that will be the new base for the chain 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 chain on behalf of the uploader.
    requestScopeOperations.setApiUser(rebaser);
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.onBehalfOfUploader = true;
    ResourceConflictException exception =
        assertThrows(
            ResourceConflictException.class,
            () -> gApi.changes().id(changeToBeRebased2.get()).rebaseChain(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",
                changeToBeRebased1, uploaderEmail));
  }

  @Test
  public void rebaseChainActionEnabled_withRebasePermission() throws Exception {
    allowPermissionToAllUsers(Permission.REBASE);
    testRebaseChainActionEnabled();
  }

  @Test
  public void rebaseChainActionEnabled_withSubmitPermission() throws Exception {
    allowPermissionToAllUsers(Permission.SUBMIT);
    testRebaseChainActionEnabled();
  }

  private void testRebaseChainActionEnabled() 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);

    Change.Id changeToBeTheNewBase = changeOperations.newChange().project(project).create();

    Change.Id changeToBeRebased1 =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased2 =
        changeOperations
            .newChange()
            .project(project)
            .owner(uploader)
            .childOf()
            .change(changeToBeRebased1)
            .create();

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

    requestScopeOperations.setApiUser(rebaser);
    ChangeInfo changeInfo = gApi.changes().id(changeToBeRebased2.get()).get();
    assertThat(changeInfo.actions).containsKey("rebase:chain");
    ActionInfo rebaseActionInfo = changeInfo.actions.get("rebase:chain");
    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 rebaseChainActionEnabled_forChangeOwner() throws Exception {
    Account.Id changeOwner = accountOperations.newAccount().create();
    Account.Id approver = admin.id();

    Change.Id changeToBeTheNewBase = changeOperations.newChange().project(project).create();

    Change.Id changeToBeRebased1 =
        changeOperations.newChange().project(project).owner(changeOwner).create();
    Change.Id changeToBeRebased2 =
        changeOperations
            .newChange()
            .project(project)
            .owner(changeOwner)
            .childOf()
            .change(changeToBeRebased1)
            .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);
    ChangeInfo changeInfo = gApi.changes().id(changeToBeRebased2.get()).get();
    assertThat(changeInfo.actions).containsKey("rebase:chain");
    ActionInfo rebaseActionInfo = changeInfo.actions.get("rebase:chain");
    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 rebaseChainWithIdenticalUploadersOnBehalfOfUploaderRecordsUploaderInRefLog()
      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();

    Change.Id changeToBeTheNewBase = changeOperations.newChange().project(project).create();

    Change.Id changeToBeRebased1 =
        changeOperations.newChange().project(project).owner(uploader).create();

    Change.Id changeToBeRebased2 =
        changeOperations
            .newChange()
            .project(project)
            .owner(uploader)
            .childOf()
            .change(changeToBeRebased1)
            .create();

    // Approve and submit the change that will be the new base for the chain 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 changeMetaRef1 = RefNames.changeMetaRef(changeToBeRebased1);
      String patchSetRef1 = RefNames.patchSetRef(PatchSet.id(changeToBeRebased1, 2));
      String changeMetaRef2 = RefNames.changeMetaRef(changeToBeRebased2);
      String patchSetRef2 = RefNames.patchSetRef(PatchSet.id(changeToBeRebased2, 2));
      createRefLogFileIfMissing(repo, changeMetaRef1);
      createRefLogFileIfMissing(repo, patchSetRef1);
      createRefLogFileIfMissing(repo, changeMetaRef2);
      createRefLogFileIfMissing(repo, patchSetRef2);

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

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

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

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

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

    Change.Id changeToBeTheNewBase = changeOperations.newChange().project(project).create();

    Account.Id uploader1 = accountOperations.newAccount().create();
    Change.Id changeToBeRebased1 =
        changeOperations.newChange().project(project).owner(uploader1).create();

    Account.Id uploader2 = accountOperations.newAccount().create();
    Change.Id changeToBeRebased2 =
        changeOperations
            .newChange()
            .project(project)
            .owner(uploader2)
            .childOf()
            .change(changeToBeRebased1)
            .create();

    // Approve and submit the change that will be the new base for the chain 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 changeMetaRef1 = RefNames.changeMetaRef(changeToBeRebased1);
      String patchSetRef1 = RefNames.patchSetRef(PatchSet.id(changeToBeRebased1, 2));
      String changeMetaRef2 = RefNames.changeMetaRef(changeToBeRebased2);
      String patchSetRef2 = RefNames.patchSetRef(PatchSet.id(changeToBeRebased2, 2));
      createRefLogFileIfMissing(repo, changeMetaRef1);
      createRefLogFileIfMissing(repo, patchSetRef1);
      createRefLogFileIfMissing(repo, changeMetaRef2);
      createRefLogFileIfMissing(repo, patchSetRef2);

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

      String combinedEmail = String.format("account-%s|account-%s@unknown", uploader1, uploader2);

      // The ref log for the patch set ref records the impersonated user aka the uploader.
      ReflogEntry patchSetRefLogEntry1 = repo.getReflogReader(patchSetRef1).getLastEntry();
      assertThat(patchSetRefLogEntry1.getWho().getEmailAddress()).isEqualTo(combinedEmail);
      ReflogEntry patchSetRefLogEntry2 = repo.getReflogReader(patchSetRef2).getLastEntry();
      assertThat(patchSetRefLogEntry2.getWho().getEmailAddress()).isEqualTo(combinedEmail);

      // The ref log for the change meta ref records the impersonated user aka the uploader.
      ReflogEntry changeMetaRefLogEntry1 = repo.getReflogReader(changeMetaRef1).getLastEntry();
      assertThat(changeMetaRefLogEntry1.getWho().getEmailAddress()).isEqualTo(combinedEmail);
      ReflogEntry changeMetaRefLogEntry2 = repo.getReflogReader(changeMetaRef2).getLastEntry();
      assertThat(changeMetaRefLogEntry2.getWho().getEmailAddress()).isEqualTo(combinedEmail);
    }
  }

  @Test
  public void rebaserCanApproveChainAfterRebasingOnBehalfOfUploader() 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();

    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().owner(uploader).project(project).create();

    Change.Id changeToBeRebased1 =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased2 =
        changeOperations
            .newChange()
            .project(project)
            .owner(uploader)
            .childOf()
            .change(changeToBeRebased1)
            .create();

    // Approve and submit the change that will be the new base for the chain 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(changeToBeRebased2.get()).rebaseChain(rebaseInput);

    // Approve the chain as the rebaser.
    allowVotingOnCodeReviewToAllUsers();
    gApi.changes().id(changeToBeRebased1.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeRebased2.get()).current().review(ReviewInput.approve());

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

    // Create and submit another change so that we can rebase the chain 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 chain 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(changeToBeRebased2.get()).rebaseChain(rebaseInput);
    gApi.changes().id(changeToBeRebased1.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeRebased2.get()).current().review(ReviewInput.approve());
    assertThat(gApi.changes().id(changeToBeRebased1.get()).get().submittable).isFalse();
    assertThat(gApi.changes().id(changeToBeRebased2.get()).get().submittable).isFalse();
  }

  @Test
  public void testSubmittedWithRebaserApprovalMetric() 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();

    Change.Id changeToBeTheNewBase =
        changeOperations.newChange().owner(uploader).project(project).create();

    Change.Id changeToBeRebased1 =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased2 =
        changeOperations
            .newChange()
            .project(project)
            .owner(uploader)
            .childOf()
            .change(changeToBeRebased1)
            .create();

    // Approve and submit the change that will be the new base for the chain that will be rebased.
    requestScopeOperations.setApiUser(approver);
    gApi.changes().id(changeToBeTheNewBase.get()).current().review(ReviewInput.approve());
    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(changeToBeRebased2.get()).rebaseChain(rebaseInput);

    // Approve the chain as the rebaser.
    allowVotingOnCodeReviewToAllUsers();
    gApi.changes().id(changeToBeRebased1.get()).current().review(ReviewInput.approve());
    gApi.changes().id(changeToBeRebased2.get()).current().review(ReviewInput.approve());

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

  @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();

    Change.Id changeToBeTheNewBase = changeOperations.newChange().project(project).create();

    Change.Id changeToBeRebased1 =
        changeOperations.newChange().project(project).owner(uploader).create();
    Change.Id changeToBeRebased2 =
        changeOperations
            .newChange()
            .project(project)
            .owner(uploader)
            .childOf()
            .change(changeToBeRebased1)
            .create();

    // Approve and submit the change that will be the new base for the chain 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(changeToBeRebased2.get()).rebaseChain(rebaseInput);
    // field1 is on_behalf_of_uploader, field2 is rebase_chain, field3 is allow_conflicts
    assertThat(testMetricMaker.getCount("change/count_rebases", true, true, false)).isEqualTo(1);
    assertThat(testMetricMaker.getCount("change/count_rebases", true, false, false)).isEqualTo(0);
    assertThat(testMetricMaker.getCount("change/count_rebases", false, false, 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(changeToBeRebased2.get()).rebaseChain(rebaseInput);
    // field1 is on_behalf_of_uploader, field2 is rebase_chain, field3 is allow_conflicts
    assertThat(testMetricMaker.getCount("change/count_rebases", false, true, false)).isEqualTo(1);
    assertThat(testMetricMaker.getCount("change/count_rebases", true, true, false)).isEqualTo(0);
    assertThat(testMetricMaker.getCount("change/count_rebases", false, false, false)).isEqualTo(0);
    assertThat(testMetricMaker.getCount("change/count_rebases", true, false, false)).isEqualTo(0);
  }

  private void assertRebase(
      Change.Id changeId,
      int expectedPatchSetNum,
      Account.Id expectedUploader,
      @Nullable Account.Id expectedRealUploader)
      throws RestApiException {
    assertRebaseRevision(changeId, expectedPatchSetNum, expectedUploader, expectedRealUploader);
    assetRebaseChangeMessage(changeId, expectedPatchSetNum, expectedUploader, expectedRealUploader);
    assertRealUserForChangeUpdate(changeId, expectedRealUploader);
  }

  private void assertRebaseRevision(
      Change.Id changeId,
      int expectedPatchSetNum,
      Account.Id expectedUploader,
      @Nullable Account.Id expectedRealUploader)
      throws RestApiException {
    RevisionInfo currentRevisionInfo = gApi.changes().id(changeId.get()).get().getCurrentRevision();

    assertThat(currentRevisionInfo._number).isEqualTo(expectedPatchSetNum);

    assertThat(currentRevisionInfo.uploader._accountId).isEqualTo(expectedUploader.get());

    if (expectedRealUploader != null) {
      assertThat(currentRevisionInfo.realUploader._accountId).isEqualTo(expectedRealUploader.get());
    } else {
      assertThat(currentRevisionInfo.realUploader).isNull();
    }

    String uploaderEmail = accountOperations.account(expectedUploader).get().preferredEmail().get();
    assertThat(currentRevisionInfo.commit.author.email).isEqualTo(uploaderEmail);
    assertThat(currentRevisionInfo.commit.committer.email).isEqualTo(uploaderEmail);
  }

  private void assetRebaseChangeMessage(
      Change.Id changeId,
      int expectedPatchSetNum,
      Account.Id expectedUploader,
      @Nullable Account.Id expectedRealUploader)
      throws RestApiException {
    Collection<ChangeMessageInfo> changeMessages = gApi.changes().id(changeId.get()).get().messages;

    // Expect 1 change message per patch set.
    assertThat(changeMessages).hasSize(expectedPatchSetNum);

    ChangeMessageInfo changeMessage = Iterables.getLast(changeMessages);
    assertThat(changeMessage.author._accountId).isEqualTo(expectedUploader.get());

    if (expectedRealUploader != null) {
      assertThat(changeMessage.message)
          .isEqualTo(
              String.format(
                  "Patch Set %d: Patch Set %d was rebased on behalf of %s",
                  expectedPatchSetNum,
                  expectedPatchSetNum - 1,
                  AccountTemplateUtil.getAccountTemplate(expectedUploader)));
      assertThat(changeMessage.realAuthor._accountId).isEqualTo(expectedRealUploader.get());
    } else {
      assertThat(changeMessage.message)
          .isEqualTo(
              String.format(
                  "Patch Set %d: Patch Set %d was rebased",
                  expectedPatchSetNum, expectedPatchSetNum - 1));
      assertThat(changeMessage.realAuthor).isNull();
    }
  }

  private void assertRealUserForChangeUpdate(
      Change.Id changeId, @Nullable Account.Id expectedRealUser) {
    Optional<FooterLine> realUserFooter =
        projectOperations.project(project).getHead(RefNames.changeMetaRef(changeId))
            .getFooterLines().stream()
            .filter(footerLine -> footerLine.matches(FOOTER_REAL_USER))
            .findFirst();

    if (expectedRealUser != null) {
      assertThat(realUserFooter.map(FooterLine::getValue))
          .hasValue(
              String.format(
                  "%s <%s>",
                  ChangeNoteUtil.getAccountIdAsUsername(expectedRealUser),
                  changeNoteUtil.getAccountIdAsEmailAddress(expectedRealUser)));
    } else {
      assertThat(realUserFooter).isEmpty();
    }
  }

  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 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();
  }

  private static class TestRevisionCreatedListener implements RevisionCreatedListener {
    private Map<Change.Id, RevisionInfo> revisionInfos = new HashMap<>();

    void assertUploaders(
        Change.Id changeId, Account.Id expectedUploader, Account.Id expectedRealUploader) {
      RevisionInfo revisionInfo = revisionInfos.get(changeId);
      assertThat(revisionInfo.uploader._accountId).isEqualTo(expectedUploader.get());
      assertThat(revisionInfo.realUploader._accountId).isEqualTo(expectedRealUploader.get());
    }

    @Override
    public void onRevisionCreated(RevisionCreatedListener.Event event) {
      revisionInfos.put(Change.id(event.getChange()._number), event.getRevision());
    }
  }
}
