// Copyright (C) 2022 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.Truth.assertWithMessage;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allow;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.block;
import static com.google.gerrit.extensions.client.ListChangesOption.ALL_REVISIONS;
import static com.google.gerrit.extensions.client.ListChangesOption.CURRENT_COMMIT;
import static com.google.gerrit.extensions.client.ListChangesOption.CURRENT_REVISION;
import static com.google.gerrit.extensions.client.ListChangesOption.DETAILED_LABELS;
import static com.google.gerrit.git.ObjectIds.abbreviateName;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.eclipse.jgit.lib.Constants.HEAD;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.ExtensionRegistry;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.TestMetricMaker;
import com.google.gerrit.acceptance.testsuite.change.ChangeOperations;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.common.RawInputUtil;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.LabelId;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Permission;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.api.changes.AttentionSetInput;
import com.google.gerrit.extensions.api.changes.RebaseInput;
import com.google.gerrit.extensions.api.changes.RelatedChangeAndCommitInfo;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.api.changes.RevisionApi;
import com.google.gerrit.extensions.api.projects.BranchInput;
import com.google.gerrit.extensions.client.ChangeStatus;
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.GitPerson;
import com.google.gerrit.extensions.common.LabelInfo;
import com.google.gerrit.extensions.common.RebaseChainInfo;
import com.google.gerrit.extensions.common.RevisionInfo;
import com.google.gerrit.extensions.events.WorkInProgressStateChangedListener;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.server.events.CommitReceivedEvent;
import com.google.gerrit.server.git.validators.CommitValidationException;
import com.google.gerrit.server.git.validators.CommitValidationListener;
import com.google.gerrit.server.git.validators.CommitValidationMessage;
import com.google.inject.Inject;
import java.io.ByteArrayOutputStream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;

@RunWith(Suite.class)
@Suite.SuiteClasses({
  RebaseIT.RebaseViaRevisionApi.class, //
  RebaseIT.RebaseViaChangeApi.class, //
  RebaseIT.RebaseChain.class, //
})
public class RebaseIT {
  public abstract static class Base extends AbstractDaemonTest {
    @Inject protected ChangeOperations changeOperations;
    @Inject protected RequestScopeOperations requestScopeOperations;
    @Inject protected ProjectOperations projectOperations;
    @Inject protected ExtensionRegistry extensionRegistry;
    @Inject protected TestMetricMaker testMetricMaker;

    @FunctionalInterface
    protected interface RebaseCall {
      void call(String id) throws RestApiException;
    }

    @FunctionalInterface
    protected interface RebaseCallWithInput {
      void call(String id, RebaseInput in) throws RestApiException;
    }

    protected RebaseCall rebaseCall;
    protected RebaseCallWithInput rebaseCallWithInput;

    protected void init(RebaseCall call, RebaseCallWithInput callWithInput) {
      this.rebaseCall = call;
      this.rebaseCallWithInput = callWithInput;
    }

    @Test
    public void rebaseChange() throws Exception {
      // Create two changes both with the same parent
      PushOneCommit.Result r = createChange();
      testRepo.reset("HEAD~1");
      PushOneCommit.Result r2 = createChange();

      // Approve and submit the first change
      RevisionApi revision = gApi.changes().id(r.getChangeId()).current();
      revision.review(ReviewInput.approve());
      revision.submit();

      // Add an approval whose score should be copied on trivial rebase
      gApi.changes().id(r2.getChangeId()).current().review(ReviewInput.recommend());

      // Rebase the second change
      rebaseCall.call(r2.getChangeId());

      verifyRebaseForChange(r2.getChange().getId(), r.getCommit().name(), true, 2);

      // Rebasing the second change again should fail
      verifyChangeIsUpToDate(r2);
    }

    @Test
    public void rebaseAbandonedChange() throws Exception {
      PushOneCommit.Result r = createChange();
      String changeId = r.getChangeId();
      assertThat(info(changeId).status).isEqualTo(ChangeStatus.NEW);
      gApi.changes().id(changeId).abandon();
      ChangeInfo info = info(changeId);
      assertThat(info.status).isEqualTo(ChangeStatus.ABANDONED);

      ResourceConflictException thrown =
          assertThrows(ResourceConflictException.class, () -> rebaseCall.call(changeId));
      assertThat(thrown)
          .hasMessageThat()
          .contains("Change " + r.getChange().getId() + " is abandoned");
    }

    @Test
    public void rebaseOntoAbandonedChange() throws Exception {
      // Create two changes both with the same parent
      PushOneCommit.Result r = createChange();
      testRepo.reset("HEAD~1");
      PushOneCommit.Result r2 = createChange();

      // Abandon the first change
      String changeId = r.getChangeId();
      assertThat(info(changeId).status).isEqualTo(ChangeStatus.NEW);
      gApi.changes().id(changeId).abandon();
      ChangeInfo info = info(changeId);
      assertThat(info.status).isEqualTo(ChangeStatus.ABANDONED);

      RebaseInput ri = new RebaseInput();
      ri.base = r.getCommit().name();

      ResourceConflictException thrown =
          assertThrows(
              ResourceConflictException.class,
              () -> rebaseCallWithInput.call(r2.getChangeId(), ri));
      assertThat(thrown).hasMessageThat().contains("base change is abandoned: " + changeId);
    }

    @Test
    public void rebaseOntoSelf() throws Exception {
      PushOneCommit.Result r = createChange();
      String changeId = r.getChangeId();
      String commit = r.getCommit().name();
      RebaseInput ri = new RebaseInput();
      ri.base = commit;
      ResourceConflictException thrown =
          assertThrows(
              ResourceConflictException.class, () -> rebaseCallWithInput.call(changeId, ri));
      assertThat(thrown)
          .hasMessageThat()
          .contains("cannot rebase change " + r.getChange().getId() + " onto itself");
    }

    @Test
    public void rebaseChangeBaseRecursion() throws Exception {
      PushOneCommit.Result r1 = createChange();
      PushOneCommit.Result r2 = createChange();

      RebaseInput ri = new RebaseInput();
      ri.base = r2.getCommit().name();
      String expectedMessage =
          "base change "
              + r2.getChangeId()
              + " is a descendant of the current change - recursion not allowed";
      ResourceConflictException thrown =
          assertThrows(
              ResourceConflictException.class,
              () -> rebaseCallWithInput.call(r1.getChangeId(), ri));
      assertThat(thrown).hasMessageThat().contains(expectedMessage);
    }

    @Test
    public void cannotRebaseOntoBaseThatIsNotPresentInTargetBranch() throws Exception {
      ObjectId initial = repo().exactRef(HEAD).getLeaf().getObjectId();

      BranchInput branchInput = new BranchInput();
      branchInput.revision = initial.getName();
      gApi.projects().name(project.get()).branch("foo").create(branchInput);

      PushOneCommit.Result r1 =
          pushFactory
              .create(admin.newIdent(), testRepo, "Change on foo branch", "a.txt", "a-content")
              .to("refs/for/foo");
      approve(r1.getChangeId());
      gApi.changes().id(r1.getChangeId()).current().submit();

      // reset HEAD in order to create a sibling of the first change
      testRepo.reset(initial);

      PushOneCommit.Result r2 =
          pushFactory
              .create(admin.newIdent(), testRepo, "Change on master branch", "b.txt", "b-content")
              .to("refs/for/master");

      RebaseInput rebaseInput = new RebaseInput();
      rebaseInput.base = r1.getCommit().getName();
      ResourceConflictException thrown =
          assertThrows(
              ResourceConflictException.class,
              () -> rebaseCallWithInput.call(r2.getChangeId(), rebaseInput));
      assertThat(thrown)
          .hasMessageThat()
          .contains(
              String.format(
                  "base change is targeting wrong branch: %s,refs/heads/foo", project.get()));

      rebaseInput.base = "refs/heads/foo";
      thrown =
          assertThrows(
              ResourceConflictException.class,
              () -> rebaseCallWithInput.call(r2.getChangeId(), rebaseInput));
      assertThat(thrown)
          .hasMessageThat()
          .contains(
              String.format(
                  "base revision is missing from the destination branch: %s", rebaseInput.base));
    }

    @Test
    public void rebaseUpToDateChange() throws Exception {
      PushOneCommit.Result r = createChange();
      verifyChangeIsUpToDate(r);
    }

    @Test
    public void rebaseDoesNotAddWorkInProgress() throws Exception {
      PushOneCommit.Result r = createChange();

      // create an unrelated change so that we can rebase
      testRepo.reset("HEAD~1");
      PushOneCommit.Result unrelated = createChange();
      gApi.changes().id(unrelated.getChangeId()).current().review(ReviewInput.approve());
      gApi.changes().id(unrelated.getChangeId()).current().submit();

      rebaseCall.call(r.getChangeId());

      // change is still ready for review after rebase
      assertThat(gApi.changes().id(r.getChangeId()).get().workInProgress).isNull();
    }

    @Test
    public void rebaseDoesNotRemoveWorkInProgress() throws Exception {
      PushOneCommit.Result r = createChange();
      change(r).setWorkInProgress();

      // create an unrelated change so that we can rebase
      testRepo.reset("HEAD~1");
      PushOneCommit.Result unrelated = createChange();
      gApi.changes().id(unrelated.getChangeId()).current().review(ReviewInput.approve());
      gApi.changes().id(unrelated.getChangeId()).current().submit();

      rebaseCall.call(r.getChangeId());

      // change is still work in progress after rebase
      assertThat(gApi.changes().id(r.getChangeId()).get().workInProgress).isTrue();
    }

    @Test
    public void rebaseAsUploaderInAttentionSet() throws Exception {
      // Create two changes both with the same parent
      PushOneCommit.Result r = createChange();
      testRepo.reset("HEAD~1");
      PushOneCommit.Result r2 = createChange();

      // Approve and submit the first change
      RevisionApi revision = gApi.changes().id(r.getChangeId()).current();
      revision.review(ReviewInput.approve());
      revision.submit();

      TestAccount admin2 = accountCreator.admin2();
      requestScopeOperations.setApiUser(admin2.id());
      amendChangeWithUploader(r2, project, admin2);
      gApi.changes()
          .id(r2.getChangeId())
          .addToAttentionSet(new AttentionSetInput(admin2.id().toString(), "manual update"));

      rebaseCall.call(r2.getChangeId());
    }

    @Test
    public void rebaseOnChangeNumber() throws Exception {
      String branchTip = testRepo.getRepository().exactRef("HEAD").getObjectId().name();
      PushOneCommit.Result r1 = createChange();
      testRepo.reset("HEAD~1");
      PushOneCommit.Result r2 = createChange();

      RevisionInfo ri2 =
          get(r2.getChangeId(), CURRENT_REVISION, CURRENT_COMMIT).getCurrentRevision();
      assertThat(ri2.commit.parents.get(0).commit).isEqualTo(branchTip);

      Change.Id id1 = r1.getChange().getId();
      RebaseInput in = new RebaseInput();
      in.base = id1.toString();
      rebaseCallWithInput.call(r2.getChangeId(), in);

      Change.Id id2 = r2.getChange().getId();
      ri2 = get(r2.getChangeId(), CURRENT_REVISION, CURRENT_COMMIT).getCurrentRevision();
      assertThat(ri2.commit.parents.get(0).commit).isEqualTo(r1.getCommit().name());

      List<RelatedChangeAndCommitInfo> related =
          gApi.changes().id(id2.get()).revision(ri2._number).related().changes;
      assertThat(related).hasSize(2);
      assertThat(related.get(0)._changeNumber).isEqualTo(id2.get());
      assertThat(related.get(0)._revisionNumber).isEqualTo(2);
      assertThat(related.get(1)._changeNumber).isEqualTo(id1.get());
      assertThat(related.get(1)._revisionNumber).isEqualTo(1);
    }

    @Test
    public void rebaseOnClosedChange() throws Exception {
      String branchTip = testRepo.getRepository().exactRef("HEAD").getObjectId().name();
      PushOneCommit.Result r1 = createChange();
      testRepo.reset("HEAD~1");
      PushOneCommit.Result r2 = createChange();

      RevisionInfo ri2 =
          get(r2.getChangeId(), CURRENT_REVISION, CURRENT_COMMIT).getCurrentRevision();
      assertThat(ri2.commit.parents.get(0).commit).isEqualTo(branchTip);

      // Submit first change.
      Change.Id id1 = r1.getChange().getId();
      gApi.changes().id(id1.get()).current().review(ReviewInput.approve());
      gApi.changes().id(id1.get()).current().submit();

      // Rebase second change on first change.
      RebaseInput in = new RebaseInput();
      in.base = id1.toString();
      rebaseCallWithInput.call(r2.getChangeId(), in);

      Change.Id id2 = r2.getChange().getId();
      ri2 = get(r2.getChangeId(), CURRENT_REVISION, CURRENT_COMMIT).getCurrentRevision();
      assertThat(ri2.commit.parents.get(0).commit).isEqualTo(r1.getCommit().name());

      assertThat(gApi.changes().id(id2.get()).revision(ri2._number).related().changes).isEmpty();
    }

    @Test
    public void rebaseOnNonExistingChange() throws Exception {
      String changeId = createChange().getChangeId();
      RebaseInput in = new RebaseInput();
      in.base = "999999";
      UnprocessableEntityException exception =
          assertThrows(
              UnprocessableEntityException.class, () -> rebaseCallWithInput.call(changeId, in));
      assertThat(exception).hasMessageThat().contains("Base change not found: " + in.base);
    }

    @Test
    public void rebaseNotAllowedWithoutPermission() throws Exception {
      // Create two changes both with the same parent
      PushOneCommit.Result r = createChange();
      testRepo.reset("HEAD~1");
      PushOneCommit.Result r2 = createChange();

      // Approve and submit the first change
      RevisionApi revision = gApi.changes().id(r.getChangeId()).current();
      revision.review(ReviewInput.approve());
      revision.submit();

      // Rebase the second
      String changeId = r2.getChangeId();
      requestScopeOperations.setApiUser(user.id());
      AuthException thrown = assertThrows(AuthException.class, () -> rebaseCall.call(changeId));
      assertThat(thrown)
          .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 rebaseAllowedWithPermission() throws Exception {
      // Create two changes both with the same parent
      PushOneCommit.Result r = createChange();
      testRepo.reset("HEAD~1");
      PushOneCommit.Result r2 = createChange();

      // Approve and submit the first change
      RevisionApi revision = gApi.changes().id(r.getChangeId()).current();
      revision.review(ReviewInput.approve());
      revision.submit();

      projectOperations
          .project(project)
          .forUpdate()
          .add(allow(Permission.REBASE).ref("refs/heads/master").group(REGISTERED_USERS))
          .update();

      // Rebase the second
      String changeId = r2.getChangeId();
      requestScopeOperations.setApiUser(user.id());
      rebaseCall.call(changeId);
    }

    @Test
    public void rebaseNotAllowedWithoutPushPermission() throws Exception {
      // Create two changes both with the same parent
      PushOneCommit.Result r = createChange();
      testRepo.reset("HEAD~1");
      PushOneCommit.Result r2 = createChange();

      // Approve and submit the first change
      RevisionApi revision = gApi.changes().id(r.getChangeId()).current();
      revision.review(ReviewInput.approve());
      revision.submit();

      projectOperations
          .project(project)
          .forUpdate()
          .add(allow(Permission.REBASE).ref("refs/heads/master").group(REGISTERED_USERS))
          .add(block(Permission.PUSH).ref("refs/for/*").group(REGISTERED_USERS))
          .update();

      // Rebase the second
      String changeId = r2.getChangeId();
      requestScopeOperations.setApiUser(user.id());
      AuthException thrown = assertThrows(AuthException.class, () -> rebaseCall.call(changeId));
      assertThat(thrown)
          .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 rebaseNotAllowedForOwnerWithoutPushPermission() throws Exception {
      // Create two changes both with the same parent
      PushOneCommit.Result r = createChange();
      testRepo.reset("HEAD~1");
      PushOneCommit.Result r2 = createChange();

      // Approve and submit the first change
      RevisionApi revision = gApi.changes().id(r.getChangeId()).current();
      revision.review(ReviewInput.approve());
      revision.submit();

      projectOperations
          .project(project)
          .forUpdate()
          .add(block(Permission.PUSH).ref("refs/for/*").group(REGISTERED_USERS))
          .update();

      // Rebase the second
      String changeId = r2.getChangeId();
      AuthException thrown = assertThrows(AuthException.class, () -> rebaseCall.call(changeId));
      assertThat(thrown)
          .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 rebaseWithValidationOptions() throws Exception {
      // Create two changes both with the same parent
      PushOneCommit.Result r = createChange();
      testRepo.reset("HEAD~1");
      PushOneCommit.Result r2 = createChange();

      // Approve and submit the first change
      RevisionApi revision = gApi.changes().id(r.getChangeId()).current();
      revision.review(ReviewInput.approve());
      revision.submit();

      RebaseInput rebaseInput = new RebaseInput();
      rebaseInput.validationOptions = ImmutableMap.of("key", "value");

      TestCommitValidationListener testCommitValidationListener =
          new TestCommitValidationListener();
      try (ExtensionRegistry.Registration unusedRegistration =
          extensionRegistry.newRegistration().add(testCommitValidationListener)) {
        // Rebase the second change
        rebaseCallWithInput.call(r2.getChangeId(), rebaseInput);
        assertThat(testCommitValidationListener.receiveEvent.pushOptions)
            .containsExactly("key", "value");
      }
    }

    @Test
    public void rebaseChangeWhenChecksRefExists() throws Exception {
      // Create two changes both with the same parent
      PushOneCommit.Result r = createChange();
      testRepo.reset("HEAD~1");
      PushOneCommit.Result r2 = createChange();

      // Approve and submit the first change
      RevisionApi revision = gApi.changes().id(r.getChangeId()).current();
      revision.review(ReviewInput.approve());
      revision.submit();

      // Create checks ref
      try (TestRepository<Repository> testRepo =
          new TestRepository<>(repoManager.openRepository(project))) {
        testRepo.update(
            RefNames.changeRefPrefix(r2.getChange().getId()) + "checks",
            testRepo.commit().message("Empty commit"));
      }

      // Rebase the second change
      rebaseCall.call(r2.getChangeId());

      verifyRebaseForChange(
          r2.getChange().getId(),
          r.getCommit().name(),
          /* shouldHaveApproval= */ false,
          /* expectedNumRevisions= */ 2);
    }

    protected void verifyRebaseForChange(
        Change.Id changeId, Change.Id baseChangeId, boolean shouldHaveApproval)
        throws RestApiException {
      verifyRebaseForChange(changeId, baseChangeId, shouldHaveApproval, 2);
    }

    protected void verifyRebaseForChange(
        Change.Id changeId,
        Change.Id baseChangeId,
        boolean shouldHaveApproval,
        int expectedNumRevisions)
        throws RestApiException {
      ChangeInfo baseInfo = gApi.changes().id(baseChangeId.get()).get(CURRENT_REVISION);
      verifyRebaseForChange(
          changeId, baseInfo.currentRevision, shouldHaveApproval, expectedNumRevisions);
    }

    protected void verifyRebaseForChange(
        Change.Id changeId, String baseCommit, boolean shouldHaveApproval, int expectedNumRevisions)
        throws RestApiException {
      ChangeInfo info =
          gApi.changes().id(changeId.get()).get(CURRENT_REVISION, CURRENT_COMMIT, DETAILED_LABELS);

      RevisionInfo r = info.getCurrentRevision();
      assertThat(r._number).isEqualTo(expectedNumRevisions);
      assertThat(r.realUploader).isNull();

      // ...and the base should be correct
      assertThat(r.commit.parents).hasSize(1);
      assertWithMessage("base commit for change " + changeId)
          .that(r.commit.parents.get(0).commit)
          .isEqualTo(baseCommit);

      // ...and the committer and description should be correct
      GitPerson committer = r.commit.committer;
      assertThat(committer.name).isEqualTo(admin.fullName());
      assertThat(committer.email).isEqualTo(admin.email());
      String description = r.description;
      assertThat(description).isEqualTo("Rebase");

      if (shouldHaveApproval) {
        // ...and the approval was copied
        LabelInfo cr = info.labels.get(LabelId.CODE_REVIEW);
        assertThat(cr).isNotNull();
        assertThat(cr.all).isNotNull();
        assertThat(cr.all).hasSize(1);
        assertThat(cr.all.get(0).value).isEqualTo(1);
      }
    }

    protected void verifyChangeIsUpToDate(PushOneCommit.Result r) {
      ResourceConflictException thrown =
          assertThrows(ResourceConflictException.class, () -> rebaseCall.call(r.getChangeId()));
      assertThat(thrown).hasMessageThat().contains("Change is already up to date");
    }

    protected static class TestCommitValidationListener implements CommitValidationListener {
      public CommitReceivedEvent receiveEvent;

      @Override
      public List<CommitValidationMessage> onCommitReceived(CommitReceivedEvent receiveEvent)
          throws CommitValidationException {
        this.receiveEvent = receiveEvent;
        return ImmutableList.of();
      }
    }

    protected static class TestWorkInProgressStateChangedListener
        implements WorkInProgressStateChangedListener {
      boolean invoked;
      Boolean wip;

      @Override
      public void onWorkInProgressStateChanged(WorkInProgressStateChangedListener.Event event) {
        this.invoked = true;
        this.wip =
            event.getChange().workInProgress != null ? event.getChange().workInProgress : false;
      }
    }
  }

  public abstract static class Rebase extends Base {
    @Test
    public void rebaseChangeBase() throws Exception {
      PushOneCommit.Result r1 = createChange();
      PushOneCommit.Result r2 = createChange();
      PushOneCommit.Result r3 = createChange();
      RebaseInput ri = new RebaseInput();

      // rebase r3 directly onto master (break dep. towards r2)
      ri.base = "";
      rebaseCallWithInput.call(r3.getChangeId(), ri);
      PatchSet ps3 = r3.getPatchSet();
      assertThat(ps3.id().get()).isEqualTo(2);

      // rebase r2 onto r3 (referenced by ref)
      ri.base = ps3.id().toRefName();
      rebaseCallWithInput.call(r2.getChangeId(), ri);
      PatchSet ps2 = r2.getPatchSet();
      assertThat(ps2.id().get()).isEqualTo(2);

      // rebase r1 onto r2 (referenced by commit)
      ri.base = ps2.commitId().name();
      rebaseCallWithInput.call(r1.getChangeId(), ri);
      PatchSet ps1 = r1.getPatchSet();
      assertThat(ps1.id().get()).isEqualTo(2);

      // rebase r1 onto r3 (referenced by change number)
      ri.base = String.valueOf(r3.getChange().getId().get());
      rebaseCallWithInput.call(r1.getChangeId(), ri);
      assertThat(r1.getPatchSetId().get()).isEqualTo(3);
    }

    @Test
    public void rebaseWithConflict_conflictsAllowed() throws Exception {
      String patchSetSubject = "patch set change";
      String patchSetContent = "patch set content";
      String baseSubject = "base change";
      String baseContent = "base content";

      PushOneCommit.Result r1 = createChange(baseSubject, PushOneCommit.FILE_NAME, baseContent);
      gApi.changes()
          .id(r1.getChangeId())
          .revision(r1.getCommit().name())
          .review(ReviewInput.approve());
      gApi.changes().id(r1.getChangeId()).revision(r1.getCommit().name()).submit();

      testRepo.reset("HEAD~1");
      PushOneCommit push =
          pushFactory.create(
              admin.newIdent(),
              testRepo,
              patchSetSubject,
              PushOneCommit.FILE_NAME,
              patchSetContent);
      PushOneCommit.Result r2 = push.to("refs/for/master");
      r2.assertOkStatus();

      String changeId = r2.getChangeId();
      RevCommit patchSet = r2.getCommit();
      RevCommit base = r1.getCommit();

      TestWorkInProgressStateChangedListener wipStateChangedListener =
          new TestWorkInProgressStateChangedListener();
      try (ExtensionRegistry.Registration registration =
          extensionRegistry.newRegistration().add(wipStateChangedListener)) {
        RebaseInput rebaseInput = new RebaseInput();
        rebaseInput.allowConflicts = true;
        testMetricMaker.reset();
        ChangeInfo changeInfo =
            gApi.changes().id(changeId).revision(patchSet.name()).rebaseAsInfo(rebaseInput);
        assertThat(changeInfo.containsGitConflicts).isTrue();
        assertThat(changeInfo.workInProgress).isTrue();

        // field1 is on_behalf_of_uploader, field2 is rebase_chain, field3 is allow_conflicts
        assertThat(testMetricMaker.getCount("change/count_rebases", false, false, true))
            .isEqualTo(1);
      }
      assertThat(wipStateChangedListener.invoked).isTrue();
      assertThat(wipStateChangedListener.wip).isTrue();

      // To get the revisions, we must retrieve the change with more change options.
      ChangeInfo changeInfo =
          gApi.changes().id(changeId).get(ALL_REVISIONS, CURRENT_COMMIT, CURRENT_REVISION);
      assertThat(changeInfo.revisions).hasSize(2);
      assertThat(changeInfo.getCurrentRevision().commit.parents.get(0).commit)
          .isEqualTo(base.name());

      // Verify that the file content in the created patch set is correct.
      // We expect that it has conflict markers to indicate the conflict.
      BinaryResult bin =
          gApi.changes().id(changeId).current().file(PushOneCommit.FILE_NAME).content();
      ByteArrayOutputStream os = new ByteArrayOutputStream();
      bin.writeTo(os);
      String fileContent = new String(os.toByteArray(), UTF_8);
      String patchSetSha1 = abbreviateName(patchSet, 6);
      String baseSha1 = abbreviateName(base, 6);
      assertThat(fileContent)
          .isEqualTo(
              "<<<<<<< PATCH SET ("
                  + patchSetSha1
                  + " "
                  + patchSetSubject
                  + ")\n"
                  + patchSetContent
                  + "\n"
                  + "=======\n"
                  + baseContent
                  + "\n"
                  + ">>>>>>> BASE      ("
                  + baseSha1
                  + " "
                  + baseSubject
                  + ")\n");

      // Verify the message that has been posted on the change.
      List<ChangeMessageInfo> messages = gApi.changes().id(changeId).messages();
      assertThat(messages).hasSize(2);
      assertThat(Iterables.getLast(messages).message)
          .isEqualTo(
              "Patch Set 2: Patch Set 1 was rebased\n\n"
                  + "The following files contain Git conflicts:\n"
                  + "* "
                  + PushOneCommit.FILE_NAME
                  + "\n");
    }

    @Test
    public void rebaseWithConflict_conflictsForbidden() throws Exception {
      PushOneCommit.Result r1 = createChange();
      gApi.changes()
          .id(r1.getChangeId())
          .revision(r1.getCommit().name())
          .review(ReviewInput.approve());
      gApi.changes().id(r1.getChangeId()).revision(r1.getCommit().name()).submit();

      PushOneCommit push =
          pushFactory.create(
              admin.newIdent(),
              testRepo,
              PushOneCommit.SUBJECT,
              PushOneCommit.FILE_NAME,
              "other content",
              "If09d8782c1e59dd0b33de2b1ec3595d69cc10ad5");
      PushOneCommit.Result r2 = push.to("refs/for/master");
      r2.assertOkStatus();
      ResourceConflictException exception =
          assertThrows(ResourceConflictException.class, () -> rebaseCall.call(r2.getChangeId()));
      assertThat(exception)
          .hasMessageThat()
          .isEqualTo(
              String.format(
                  "Change %s could not be rebased due to a conflict during merge.\n\n"
                      + "merge conflict(s):\n%s",
                  r2.getChange().getId(), PushOneCommit.FILE_NAME));
    }

    @Test
    public void rebaseFromRelationChainToClosedChange() throws Exception {
      PushOneCommit.Result r1 = createChange();
      testRepo.reset("HEAD~1");

      createChange();
      PushOneCommit.Result r3 = createChange();

      // Submit first change.
      Change.Id id1 = r1.getChange().getId();
      gApi.changes().id(id1.get()).current().review(ReviewInput.approve());
      gApi.changes().id(id1.get()).current().submit();

      // Rebase third change on first change.
      RebaseInput in = new RebaseInput();
      in.base = id1.toString();
      rebaseCallWithInput.call(r3.getChangeId(), in);

      Change.Id id3 = r3.getChange().getId();
      RevisionInfo ri3 =
          get(r3.getChangeId(), CURRENT_REVISION, CURRENT_COMMIT).getCurrentRevision();
      assertThat(ri3.commit.parents.get(0).commit).isEqualTo(r1.getCommit().name());

      assertThat(gApi.changes().id(id3.get()).revision(ri3._number).related().changes).isEmpty();
    }

    @Test
    public void testCountRebasesMetric() throws Exception {
      // Create two changes both with the same parent
      PushOneCommit.Result r = createChange();
      testRepo.reset("HEAD~1");
      PushOneCommit.Result r2 = createChange();

      // Approve and submit the first change
      RevisionApi revision = gApi.changes().id(r.getChangeId()).current();
      revision.review(ReviewInput.approve());
      revision.submit();

      // Rebase the second change
      testMetricMaker.reset();
      rebaseCallWithInput.call(r2.getChangeId(), new 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", true, true, false)).isEqualTo(0);
      assertThat(testMetricMaker.getCount("change/count_rebases", false, true, false)).isEqualTo(0);
    }

    @Test
    public void rebaseActionEnabledIfChangeCanBeRebased() throws Exception {
      Change.Id changeToBeTheNewBase = changeOperations.newChange().project(project).create();
      Change.Id changeToBeRebased = changeOperations.newChange().project(project).create();

      // Change cannot be rebased since its parent commit is the same commit as the HEAD of the
      // destination branch.
      RevisionInfo currentRevisionInfo =
          gApi.changes().id(changeToBeRebased.get()).get().getCurrentRevision();
      assertThat(currentRevisionInfo.actions).containsKey("rebase");
      ActionInfo rebaseActionInfo = currentRevisionInfo.actions.get("rebase");
      assertThat(rebaseActionInfo.enabled).isNull();

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

      // Change can be rebased since its parent commit differs from the commit at the HEAD of the
      // destination branch.
      currentRevisionInfo = gApi.changes().id(changeToBeRebased.get()).get().getCurrentRevision();
      assertThat(currentRevisionInfo.actions).containsKey("rebase");
      rebaseActionInfo = currentRevisionInfo.actions.get("rebase");
      assertThat(rebaseActionInfo.enabled).isTrue();
    }

    @Test
    public void rebaseActionEnabledIfChangeHasAParentChange() throws Exception {
      Change.Id change1 = changeOperations.newChange().project(project).create();
      Change.Id change2 =
          changeOperations.newChange().project(project).childOf().change(change1).create();

      // change1 cannot be rebased since its parent commit is the same commit as the HEAD of the
      // destination branch.
      RevisionInfo currentRevisionInfo =
          gApi.changes().id(change1.get()).get().getCurrentRevision();
      assertThat(currentRevisionInfo.actions).containsKey("rebase");
      ActionInfo rebaseActionInfo = currentRevisionInfo.actions.get("rebase");
      assertThat(rebaseActionInfo.enabled).isNull();

      // change2 can be rebased to break the relation to change1
      currentRevisionInfo = gApi.changes().id(change2.get()).get().getCurrentRevision();
      assertThat(currentRevisionInfo.actions).containsKey("rebase");
      rebaseActionInfo = currentRevisionInfo.actions.get("rebase");
      assertThat(rebaseActionInfo.enabled).isTrue();
    }
  }

  public static class RebaseViaRevisionApi extends Rebase {
    @Before
    public void setUp() throws Exception {
      init(
          id -> gApi.changes().id(id).current().rebase(),
          (id, in) -> gApi.changes().id(id).current().rebase(in));
    }

    @Test
    public void rebaseOutdatedPatchSet() throws Exception {
      String fileName1 = "a.txt";
      String fileContent1 = "some content";
      String fileName2 = "b.txt";
      String fileContent2Ps1 = "foo";
      String fileContent2Ps2 = "foo/bar";

      // Create two changes both with the same parent touching disjunct files
      PushOneCommit.Result r =
          pushFactory
              .create(admin.newIdent(), testRepo, PushOneCommit.SUBJECT, fileName1, fileContent1)
              .to("refs/for/master");
      r.assertOkStatus();
      String changeId1 = r.getChangeId();
      testRepo.reset("HEAD~1");
      PushOneCommit push =
          pushFactory.create(
              admin.newIdent(), testRepo, PushOneCommit.SUBJECT, fileName2, fileContent2Ps1);
      PushOneCommit.Result r2 = push.to("refs/for/master");
      r2.assertOkStatus();
      String changeId2 = r2.getChangeId();

      // Approve and submit the first change
      RevisionApi revision = gApi.changes().id(changeId1).current();
      revision.review(ReviewInput.approve());
      revision.submit();

      // Amend the second change so that it has 2 patch sets
      amendChange(
              changeId2,
              "refs/for/master",
              admin,
              testRepo,
              PushOneCommit.SUBJECT,
              fileName2,
              fileContent2Ps2)
          .assertOkStatus();
      assertThat(gApi.changes().id(changeId2).get().getCurrentRevision()._number).isEqualTo(2);

      // Rebase the first patch set of the second change
      gApi.changes().id(changeId2).revision(1).rebase();

      // Second change should have 3 patch sets
      assertThat(gApi.changes().id(changeId2).get().getCurrentRevision()._number).isEqualTo(3);

      // ... and the committer and description should be correct
      ChangeInfo info = gApi.changes().id(changeId2).get(CURRENT_REVISION, CURRENT_COMMIT);
      GitPerson committer = info.getCurrentRevision().commit.committer;
      assertThat(committer.name).isEqualTo(admin.fullName());
      assertThat(committer.email).isEqualTo(admin.email());
      String description = info.getCurrentRevision().description;
      assertThat(description).isEqualTo("Rebase");

      // ... and the file contents should match with patch set 1 based on change1
      assertThat(gApi.changes().id(changeId2).current().file(fileName1).content().asString())
          .isEqualTo(fileContent1);
      assertThat(gApi.changes().id(changeId2).current().file(fileName2).content().asString())
          .isEqualTo(fileContent2Ps1);
    }
  }

  public static class RebaseViaChangeApi extends Rebase {
    @Before
    public void setUp() throws Exception {
      init(id -> gApi.changes().id(id).rebase(), (id, in) -> gApi.changes().id(id).rebase(in));
    }
  }

  public static class RebaseChain extends Base {
    @Before
    public void setUp() throws Exception {
      init(
          id -> {
            @SuppressWarnings("unused")
            Object unused = gApi.changes().id(id).rebaseChain();
          },
          (id, in) -> {
            @SuppressWarnings("unused")
            Object unused = gApi.changes().id(id).rebaseChain(in);
          });
    }

    @Override
    protected void verifyChangeIsUpToDate(PushOneCommit.Result r) {
      ResourceConflictException thrown =
          assertThrows(ResourceConflictException.class, () -> rebaseCall.call(r.getChangeId()));
      assertThat(thrown).hasMessageThat().contains("The whole chain is already up to date.");
    }

    @Test
    public void rebaseChain() throws Exception {
      // Create changes with the following hierarchy:
      // * HEAD
      //   * r (merged)
      //   * r2
      //     * r3
      //       * r4
      //         *r5
      PushOneCommit.Result r = createChange();
      testRepo.reset("HEAD~1");
      PushOneCommit.Result r2 = createChange();
      PushOneCommit.Result r3 = createChange();
      PushOneCommit.Result r4 = createChange();
      PushOneCommit.Result r5 = createChange();

      // Approve and submit the first change
      RevisionApi revision = gApi.changes().id(r.getChangeId()).current();
      revision.review(ReviewInput.approve());
      revision.submit();

      // Add an approval whose score should be copied on trivial rebase
      gApi.changes().id(r2.getChangeId()).current().review(ReviewInput.recommend());
      gApi.changes().id(r3.getChangeId()).current().review(ReviewInput.recommend());

      // Rebase the chain through r4.
      verifyRebaseChainResponse(
          gApi.changes().id(r4.getChangeId()).rebaseChain(), false, r2, r3, r4);

      // Only r2, r3 and r4 are rebased.
      verifyRebaseForChange(r2.getChange().getId(), r.getCommit().name(), true, 2);
      verifyRebaseForChange(r3.getChange().getId(), r2.getChange().getId(), true);
      verifyRebaseForChange(r4.getChange().getId(), r3.getChange().getId(), false);

      verifyChangeIsUpToDate(r2);
      verifyChangeIsUpToDate(r3);
      verifyChangeIsUpToDate(r4);

      // r5 wasn't rebased.
      assertThat(
              gApi.changes()
                  .id(r5.getChangeId())
                  .get(CURRENT_REVISION)
                  .getCurrentRevision()
                  ._number)
          .isEqualTo(1);

      // Rebasing r5
      verifyRebaseChainResponse(
          gApi.changes().id(r5.getChangeId()).rebaseChain(), false, r2, r3, r4, r5);

      verifyRebaseForChange(r5.getChange().getId(), r4.getChange().getId(), false);
    }

    @Test
    public void rebasePartlyOutdatedChain() throws Exception {
      final String file = "modified_file.txt";
      final String oldContent = "old content";
      final String newContent = "new content";
      // Create changes with the following revision hierarchy:
      // * HEAD
      //   * r (merged)
      //   * r2
      //     * r3/1    r3/2
      //       * r4
      PushOneCommit.Result r = createChange();
      testRepo.reset("HEAD~1");
      PushOneCommit.Result r2 = createChange();
      PushOneCommit.Result r3 = createChange("original patch-set", file, oldContent);
      PushOneCommit.Result r4 = createChange();
      gApi.changes()
          .id(r3.getChangeId())
          .edit()
          .modifyFile(file, RawInputUtil.create(newContent.getBytes(UTF_8)));
      gApi.changes().id(r3.getChangeId()).edit().publish();

      // Approve and submit the first change
      RevisionApi revision = gApi.changes().id(r.getChangeId()).current();
      revision.review(ReviewInput.approve());
      revision.submit();

      // Rebase the chain through r4.
      rebaseCall.call(r4.getChangeId());

      verifyRebaseForChange(r2.getChange().getId(), r.getCommit().name(), false, 2);
      verifyRebaseForChange(r3.getChange().getId(), r2.getChange().getId(), false, 3);
      verifyRebaseForChange(r4.getChange().getId(), r3.getChange().getId(), false);

      assertThat(gApi.changes().id(r3.getChangeId()).current().file(file).content().asString())
          .isEqualTo(newContent);

      verifyChangeIsUpToDate(r2);
      verifyChangeIsUpToDate(r3);
      verifyChangeIsUpToDate(r4);
    }

    @Test
    public void rebaseChainWithMergedAncestor() throws Exception {
      final String file = "modified_file.txt";
      final String newContent = "new content";

      // Create changes with the following hierarchy:
      // * HEAD
      //   * r (merged)
      //   * r2.1         r2.2 (merged)
      //     * r3
      //       * r4
      //         *r5
      PushOneCommit.Result r = createChange();
      PushOneCommit.Result r2 = createChange();
      PushOneCommit.Result r3 = createChange();
      PushOneCommit.Result r4 = createChange();
      PushOneCommit.Result r5 = createChange();

      // Approve and submit the first change
      RevisionApi revision = gApi.changes().id(r.getChangeId()).current();
      revision.review(ReviewInput.approve());
      revision.submit();
      testRepo.reset("HEAD~1");

      // Create r2.2
      gApi.changes()
          .id(r2.getChangeId())
          .edit()
          .modifyFile(file, RawInputUtil.create(newContent.getBytes(UTF_8)));
      gApi.changes().id(r2.getChangeId()).edit().publish();
      // Approve and submit r2.2
      revision = gApi.changes().id(r2.getChangeId()).current();
      revision.review(ReviewInput.approve());
      revision.submit();

      // Add an approval whose score should be copied on trivial rebase
      gApi.changes().id(r3.getChangeId()).current().review(ReviewInput.recommend());

      // Rebase the chain through r4.
      verifyRebaseChainResponse(gApi.changes().id(r4.getChangeId()).rebaseChain(), false, r3, r4);

      // Only r3 and r4 are rebased.
      verifyRebaseForChange(r3.getChange().getId(), r2.getChange().getId(), true);
      verifyRebaseForChange(r4.getChange().getId(), r3.getChange().getId(), false);

      verifyChangeIsUpToDate(r2);
      verifyChangeIsUpToDate(r3);
      verifyChangeIsUpToDate(r4);

      // r5 wasn't rebased.
      assertThat(
              gApi.changes()
                  .id(r5.getChangeId())
                  .get(CURRENT_REVISION)
                  .getCurrentRevision()
                  ._number)
          .isEqualTo(1);

      // Rebasing r5
      verifyRebaseChainResponse(
          gApi.changes().id(r5.getChangeId()).rebaseChain(), false, r3, r4, r5);

      verifyRebaseForChange(r5.getChange().getId(), r4.getChange().getId(), false);
    }

    @Test
    public void rebaseChainWithConflicts_conflictsForbidden() throws Exception {
      PushOneCommit.Result r1 = createChange();
      gApi.changes()
          .id(r1.getChangeId())
          .revision(r1.getCommit().name())
          .review(ReviewInput.approve());
      gApi.changes().id(r1.getChangeId()).revision(r1.getCommit().name()).submit();

      PushOneCommit push =
          pushFactory.create(
              admin.newIdent(),
              testRepo,
              PushOneCommit.SUBJECT,
              PushOneCommit.FILE_NAME,
              "other content",
              "I0020020020020020020020020020020020020002");
      PushOneCommit.Result r2 = push.to("refs/for/master");
      r2.assertOkStatus();
      PushOneCommit.Result r3 = createChange("refs/for/master");
      r3.assertOkStatus();
      ResourceConflictException exception =
          assertThrows(
              ResourceConflictException.class,
              () -> gApi.changes().id(r3.getChangeId()).rebaseChain());
      assertThat(exception)
          .hasMessageThat()
          .isEqualTo(
              String.format(
                  "Change %s could not be rebased due to a conflict during merge.\n\n"
                      + "merge conflict(s):\n%s",
                  r2.getChange().getId(), PushOneCommit.FILE_NAME));
    }

    @Test
    public void rebaseChainWithConflicts_conflictsAllowed() throws Exception {
      String patchSetSubject = "patch set change";
      String patchSetContent = "patch set content";
      String baseSubject = "base change";
      String baseContent = "base content";

      PushOneCommit.Result r1 = createChange(baseSubject, PushOneCommit.FILE_NAME, baseContent);
      gApi.changes()
          .id(r1.getChangeId())
          .revision(r1.getCommit().name())
          .review(ReviewInput.approve());
      gApi.changes().id(r1.getChangeId()).revision(r1.getCommit().name()).submit();

      testRepo.reset("HEAD~1");
      PushOneCommit push =
          pushFactory.create(
              admin.newIdent(),
              testRepo,
              patchSetSubject,
              PushOneCommit.FILE_NAME,
              patchSetContent);
      PushOneCommit.Result r2 = push.to("refs/for/master");
      r2.assertOkStatus();

      String changeWithConflictId = r2.getChangeId();
      RevCommit patchSet = r2.getCommit();
      RevCommit base = r1.getCommit();
      PushOneCommit.Result r3 = createChange("refs/for/master");
      r3.assertOkStatus();

      TestWorkInProgressStateChangedListener wipStateChangedListener =
          new TestWorkInProgressStateChangedListener();
      try (ExtensionRegistry.Registration registration =
          extensionRegistry.newRegistration().add(wipStateChangedListener)) {
        RebaseInput rebaseInput = new RebaseInput();
        rebaseInput.allowConflicts = true;
        Response<RebaseChainInfo> res =
            gApi.changes().id(r3.getChangeId()).rebaseChain(rebaseInput);
        verifyRebaseChainResponse(res, true, r2, r3);
        RebaseChainInfo rebaseChainInfo = res.value();
        ChangeInfo changeWithConflictInfo = rebaseChainInfo.rebasedChanges.get(0);
        assertThat(changeWithConflictInfo.changeId).isEqualTo(r2.getChangeId());
        assertThat(changeWithConflictInfo.containsGitConflicts).isTrue();
        assertThat(changeWithConflictInfo.workInProgress).isTrue();
        ChangeInfo childChangeInfo = rebaseChainInfo.rebasedChanges.get(1);
        assertThat(childChangeInfo.changeId).isEqualTo(r3.getChangeId());
        assertThat(childChangeInfo.containsGitConflicts).isTrue();
        assertThat(childChangeInfo.workInProgress).isTrue();
      }
      assertThat(wipStateChangedListener.invoked).isTrue();
      assertThat(wipStateChangedListener.wip).isTrue();

      // To get the revisions, we must retrieve the change with more change options.
      ChangeInfo changeInfo =
          gApi.changes()
              .id(changeWithConflictId)
              .get(ALL_REVISIONS, CURRENT_COMMIT, CURRENT_REVISION);
      assertThat(changeInfo.revisions).hasSize(2);
      assertThat(changeInfo.getCurrentRevision().commit.parents.get(0).commit)
          .isEqualTo(base.name());

      // Verify that the file content in the created patch set is correct.
      // We expect that it has conflict markers to indicate the conflict.
      BinaryResult bin =
          gApi.changes().id(changeWithConflictId).current().file(PushOneCommit.FILE_NAME).content();
      ByteArrayOutputStream os = new ByteArrayOutputStream();
      bin.writeTo(os);
      String fileContent = new String(os.toByteArray(), UTF_8);
      String patchSetSha1 = abbreviateName(patchSet, 6);
      String baseSha1 = abbreviateName(base, 6);
      assertThat(fileContent)
          .isEqualTo(
              "<<<<<<< PATCH SET ("
                  + patchSetSha1
                  + " "
                  + patchSetSubject
                  + ")\n"
                  + patchSetContent
                  + "\n"
                  + "=======\n"
                  + baseContent
                  + "\n"
                  + ">>>>>>> BASE      ("
                  + baseSha1
                  + " "
                  + baseSubject
                  + ")\n");

      // Verify the message that has been posted on the change.
      List<ChangeMessageInfo> messages = gApi.changes().id(changeWithConflictId).messages();
      assertThat(messages).hasSize(2);
      assertThat(Iterables.getLast(messages).message)
          .isEqualTo(
              "Patch Set 2: Patch Set 1 was rebased\n\n"
                  + "The following files contain Git conflicts:\n"
                  + "* "
                  + PushOneCommit.FILE_NAME
                  + "\n");
    }

    @Test
    public void rebaseOntoMidChain() throws Exception {
      // Create changes with the following hierarchy:
      // * HEAD
      //   * r1
      //   * r2
      //     * r3
      //       * r4
      PushOneCommit.Result r = createChange();
      r.assertOkStatus();
      testRepo.reset("HEAD~1");
      PushOneCommit.Result r2 = createChange();
      r2.assertOkStatus();
      PushOneCommit.Result r3 = createChange();
      r3.assertOkStatus();
      PushOneCommit.Result r4 = createChange();

      RebaseInput ri = new RebaseInput();
      ri.base = r3.getCommit().name();
      ResourceConflictException thrown =
          assertThrows(
              ResourceConflictException.class,
              () -> rebaseCallWithInput.call(r4.getChangeId(), ri));
      assertThat(thrown).hasMessageThat().contains("recursion not allowed");
    }

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

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

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

      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();
      assertThat(rebaseActionInfo.enabledOptions)
          .containsExactly("rebase", "rebase_on_behalf_of_uploader");
    }

    @Test
    public void rebaseChainWhenChecksRefExists() throws Exception {
      // Create changes with the following hierarchy:
      // * HEAD
      //   * r1
      //   * r2
      //     * r3
      PushOneCommit.Result r = createChange();
      testRepo.reset("HEAD~1");
      PushOneCommit.Result r2 = createChange();
      PushOneCommit.Result r3 = createChange();

      // Create checks ref
      try (TestRepository<Repository> testRepo =
          new TestRepository<>(repoManager.openRepository(project))) {
        testRepo.update(
            RefNames.changeRefPrefix(r2.getChange().getId()) + "checks",
            testRepo.commit().message("Empty commit"));
      }

      // Approve and submit the first change
      RevisionApi revision = gApi.changes().id(r.getChangeId()).current();
      revision.review(ReviewInput.approve());
      revision.submit();

      // Add an approval whose score should be copied on trivial rebase
      gApi.changes().id(r2.getChangeId()).current().review(ReviewInput.recommend());
      gApi.changes().id(r3.getChangeId()).current().review(ReviewInput.recommend());

      // Rebase the chain through r3.
      verifyRebaseChainResponse(gApi.changes().id(r3.getChangeId()).rebaseChain(), false, r2, r3);
    }

    @Test
    public void testCountRebasesMetric() throws Exception {
      // Create changes with the following hierarchy:
      // * HEAD
      //   * r1
      //   * r2
      //     * r3
      //       * r4
      PushOneCommit.Result r = createChange();
      testRepo.reset("HEAD~1");
      PushOneCommit.Result r2 = createChange();
      PushOneCommit.Result r3 = createChange();
      PushOneCommit.Result r4 = createChange();

      // Approve and submit the first change
      RevisionApi revision = gApi.changes().id(r.getChangeId()).current();
      revision.review(ReviewInput.approve());
      revision.submit();

      // Rebase the chain.
      testMetricMaker.reset();
      verifyRebaseChainResponse(
          gApi.changes().id(r4.getChangeId()).rebaseChain(), false, r2, r3, r4);
      // 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", false, false, false))
          .isEqualTo(0);
      assertThat(testMetricMaker.getCount("change/count_rebases", true, true, false)).isEqualTo(0);
      assertThat(testMetricMaker.getCount("change/count_rebases", true, false, false)).isEqualTo(0);
    }

    private void verifyRebaseChainResponse(
        Response<RebaseChainInfo> res,
        boolean shouldHaveConflicts,
        PushOneCommit.Result... changes) {
      assertThat(res.statusCode()).isEqualTo(200);
      RebaseChainInfo info = res.value();
      assertThat(info.rebasedChanges.stream().map(c -> c._number).collect(Collectors.toList()))
          .containsExactlyElementsIn(
              Arrays.stream(changes)
                  .map(c -> c.getChange().getId().get())
                  .collect(Collectors.toList()))
          .inOrder();
      assertThat(info.containsGitConflicts).isEqualTo(shouldHaveConflicts ? true : null);
    }
  }
}
