// Copyright (C) 2013 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.rest.change;

import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
import static com.google.common.truth.TruthJUnit.assume;
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.extensions.client.ListChangesOption.SUBMITTABLE;
import static com.google.gerrit.server.group.SystemGroupBackend.CHANGE_OWNER;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static java.util.stream.Collectors.toList;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.GitUtil;
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.TestProjectInput;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.extensions.api.changes.ChangeApi;
import com.google.gerrit.extensions.api.changes.SubmitInput;
import com.google.gerrit.extensions.api.projects.BranchInput;
import com.google.gerrit.extensions.api.projects.ConfigInput;
import com.google.gerrit.extensions.api.projects.ProjectInput;
import com.google.gerrit.extensions.client.ChangeStatus;
import com.google.gerrit.extensions.client.InheritableBoolean;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.ChangeInput;
import com.google.gerrit.extensions.common.LabelInfo;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.extensions.registration.RegistrationHandle;
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.RestApiException;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.change.TestSubmitInput;
import com.google.gerrit.server.git.validators.OnSubmitValidationListener;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.project.testing.Util;
import com.google.gerrit.server.restapi.change.Submit;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.gerrit.server.validators.ValidationException;
import com.google.gerrit.testing.ConfigSuite;
import com.google.gerrit.testing.TestTimeUtil;
import com.google.inject.Inject;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.ReceiveCommand;
import org.eclipse.jgit.transport.RefSpec;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

@NoHttpd
public abstract class AbstractSubmit extends AbstractDaemonTest {
  @ConfigSuite.Config
  public static Config submitWholeTopicEnabled() {
    return submitWholeTopicEnabledConfig();
  }

  @Inject private ApprovalsUtil approvalsUtil;
  @Inject private DynamicSet<OnSubmitValidationListener> onSubmitValidationListeners;
  @Inject private IdentifiedUser.GenericFactory userFactory;
  @Inject private ProjectOperations projectOperations;
  @Inject private RequestScopeOperations requestScopeOperations;
  @Inject private Submit submitHandler;

  private RegistrationHandle onSubmitValidatorHandle;
  private String systemTimeZone;

  @Before
  public void setTimeForTesting() {
    systemTimeZone = System.setProperty("user.timezone", "US/Eastern");
    TestTimeUtil.resetWithClockStep(1, SECONDS);
  }

  @After
  public void resetTime() {
    TestTimeUtil.useSystemTime();
    System.setProperty("user.timezone", systemTimeZone);
  }

  @After
  public void removeOnSubmitValidator() {
    if (onSubmitValidatorHandle != null) {
      onSubmitValidatorHandle.remove();
    }
  }

  protected abstract SubmitType getSubmitType();

  @Test
  @TestProjectInput(createEmptyCommit = false)
  public void submitToEmptyRepo() throws Exception {
    assertThat(projectOperations.project(project).hasHead("master")).isFalse();
    PushOneCommit.Result change = createChange();
    assertThat(change.getCommit().getParents()).isEmpty();
    Map<Branch.NameKey, ObjectId> actual = fetchFromSubmitPreview(change.getChangeId());
    assertThat(projectOperations.project(project).hasHead("master")).isFalse();
    assertThat(actual).hasSize(1);

    submit(change.getChangeId());
    assertThat(getRemoteHead().getId()).isEqualTo(change.getCommit());
    assertTrees(project, actual);
  }

  @Test
  public void submitSingleChange() throws Exception {
    RevCommit initialHead = getRemoteHead();
    PushOneCommit.Result change = createChange();
    Map<Branch.NameKey, ObjectId> actual = fetchFromSubmitPreview(change.getChangeId());
    RevCommit headAfterSubmit = getRemoteHead();
    assertThat(headAfterSubmit).isEqualTo(initialHead);
    assertRefUpdatedEvents();
    assertChangeMergedEvents();

    if ((getSubmitType() == SubmitType.CHERRY_PICK)
        || (getSubmitType() == SubmitType.REBASE_ALWAYS)) {
      // The change is updated as well:
      assertThat(actual).hasSize(2);
    } else {
      assertThat(actual).hasSize(1);
    }

    submit(change.getChangeId());
    assertTrees(project, actual);
  }

  @Test
  public void submitMultipleChangesOtherMergeConflictPreview() throws Exception {
    RevCommit initialHead = getRemoteHead();

    PushOneCommit.Result change = createChange("Change 1", "a.txt", "content");
    submit(change.getChangeId());

    RevCommit headAfterFirstSubmit = getRemoteHead();
    testRepo.reset(initialHead);
    PushOneCommit.Result change2 = createChange("Change 2", "a.txt", "other content");
    PushOneCommit.Result change3 = createChange("Change 3", "d", "d");
    PushOneCommit.Result change4 = createChange("Change 4", "e", "e");
    // change 2 is not approved, but we ignore labels
    approve(change3.getChangeId());

    try (BinaryResult request =
        gApi.changes().id(change4.getChangeId()).current().submitPreview()) {
      assertThat(getSubmitType()).isEqualTo(SubmitType.CHERRY_PICK);
      submit(change4.getChangeId());
    } catch (RestApiException e) {
      switch (getSubmitType()) {
        case FAST_FORWARD_ONLY:
          assertThat(e.getMessage())
              .isEqualTo(
                  "Failed to submit 3 changes due to the following problems:\n"
                      + "Change "
                      + change2.getChange().getId()
                      + ": internal error: "
                      + "change not processed by merge strategy\n"
                      + "Change "
                      + change3.getChange().getId()
                      + ": internal error: "
                      + "change not processed by merge strategy\n"
                      + "Change "
                      + change4.getChange().getId()
                      + ": Project policy "
                      + "requires all submissions to be a fast-forward. Please "
                      + "rebase the change locally and upload again for review.");
          break;
        case REBASE_IF_NECESSARY:
        case REBASE_ALWAYS:
          String change2hash = change2.getChange().currentPatchSet().getRevision().get();
          assertThat(e.getMessage())
              .isEqualTo(
                  "Cannot rebase "
                      + change2hash
                      + ": The change could "
                      + "not be rebased due to a conflict during merge.");
          break;
        case MERGE_ALWAYS:
        case MERGE_IF_NECESSARY:
        case INHERIT:
          assertThat(e.getMessage())
              .isEqualTo(
                  "Failed to submit 3 changes due to the following problems:\n"
                      + "Change "
                      + change2.getChange().getId()
                      + ": Change could not be "
                      + "merged due to a path conflict. Please rebase the change "
                      + "locally and upload the rebased commit for review.\n"
                      + "Change "
                      + change3.getChange().getId()
                      + ": Change could not be "
                      + "merged due to a path conflict. Please rebase the change "
                      + "locally and upload the rebased commit for review.\n"
                      + "Change "
                      + change4.getChange().getId()
                      + ": Change could not be "
                      + "merged due to a path conflict. Please rebase the change "
                      + "locally and upload the rebased commit for review.");
          break;
        case CHERRY_PICK:
        default:
          fail("Should not reach here.");
          break;
      }

      RevCommit headAfterSubmit = getRemoteHead();
      assertThat(headAfterSubmit).isEqualTo(headAfterFirstSubmit);
      assertRefUpdatedEvents(initialHead, headAfterFirstSubmit);
      assertChangeMergedEvents(change.getChangeId(), headAfterFirstSubmit.name());
    }
  }

  @Test
  public void submitMultipleChangesPreview() throws Exception {
    RevCommit initialHead = getRemoteHead();
    PushOneCommit.Result change2 = createChange("Change 2", "a.txt", "other content");
    PushOneCommit.Result change3 = createChange("Change 3", "d", "d");
    PushOneCommit.Result change4 = createChange("Change 4", "e", "e");
    // change 2 is not approved, but we ignore labels
    approve(change3.getChangeId());
    Map<Branch.NameKey, ObjectId> actual = fetchFromSubmitPreview(change4.getChangeId());
    Map<String, Map<String, Integer>> expected = new HashMap<>();
    expected.put(project.get(), new HashMap<>());
    expected.get(project.get()).put("refs/heads/master", 3);

    assertThat(actual).containsKey(new Branch.NameKey(project, "refs/heads/master"));
    if (getSubmitType() == SubmitType.CHERRY_PICK) {
      // CherryPick ignores dependencies, thus only change and destination
      // branch refs are modified.
      assertThat(actual).hasSize(2);
    } else if (getSubmitType() == SubmitType.REBASE_ALWAYS) {
      // RebaseAlways takes care of dependencies, therefore Change{2,3,4} and
      // destination branch will be modified.
      assertThat(actual).hasSize(4);
    } else {
      assertThat(actual).hasSize(1);
    }

    // check that the submit preview did not actually submit
    RevCommit headAfterSubmit = getRemoteHead();
    assertThat(headAfterSubmit).isEqualTo(initialHead);
    assertRefUpdatedEvents();
    assertChangeMergedEvents();

    // now check we actually have the same content:
    approve(change2.getChangeId());
    submit(change4.getChangeId());
    assertTrees(project, actual);
  }

  @Test
  public void submitNoPermission() throws Exception {
    // create project where submit is blocked
    Project.NameKey p = projectOperations.newProject().create();
    block(p, "refs/*", Permission.SUBMIT, REGISTERED_USERS);

    TestRepository<InMemoryRepository> repo = cloneProject(p, admin);
    PushOneCommit push = pushFactory.create(admin.newIdent(), repo);
    PushOneCommit.Result result = push.to("refs/for/master");
    result.assertOkStatus();

    submit(result.getChangeId(), new SubmitInput(), AuthException.class, "submit not permitted");
  }

  @Test
  public void noSelfSubmit() throws Exception {
    // create project where submit is blocked for the change owner
    Project.NameKey p = projectOperations.newProject().create();
    try (ProjectConfigUpdate u = updateProject(p)) {
      Util.block(u.getConfig(), Permission.SUBMIT, CHANGE_OWNER, "refs/*");
      Util.allow(u.getConfig(), Permission.SUBMIT, REGISTERED_USERS, "refs/heads/*");
      Util.allow(
          u.getConfig(), Permission.forLabel("Code-Review"), -2, +2, REGISTERED_USERS, "refs/*");
      u.save();
    }

    TestRepository<InMemoryRepository> repo = cloneProject(p, admin);
    PushOneCommit push = pushFactory.create(admin.newIdent(), repo);
    PushOneCommit.Result result = push.to("refs/for/master");
    result.assertOkStatus();

    ChangeInfo change = gApi.changes().id(result.getChangeId()).get();
    assertThat(change.owner._accountId).isEqualTo(admin.id().get());

    submit(result.getChangeId(), new SubmitInput(), AuthException.class, "submit not permitted");

    requestScopeOperations.setApiUser(user.id());
    submit(result.getChangeId());
  }

  @Test
  public void onlySelfSubmit() throws Exception {
    // create project where only the change owner can submit
    Project.NameKey p = projectOperations.newProject().create();
    try (ProjectConfigUpdate u = updateProject(p)) {
      Util.block(u.getConfig(), Permission.SUBMIT, REGISTERED_USERS, "refs/*");
      Util.allow(u.getConfig(), Permission.SUBMIT, CHANGE_OWNER, "refs/*");
      Util.allow(
          u.getConfig(), Permission.forLabel("Code-Review"), -2, +2, REGISTERED_USERS, "refs/*");
      u.save();
    }

    TestRepository<InMemoryRepository> repo = cloneProject(p, admin);
    PushOneCommit push = pushFactory.create(admin.newIdent(), repo);
    PushOneCommit.Result result = push.to("refs/for/master");
    result.assertOkStatus();

    ChangeInfo change = gApi.changes().id(result.getChangeId()).get();
    assertThat(change.owner._accountId).isEqualTo(admin.id().get());

    requestScopeOperations.setApiUser(user.id());
    submit(result.getChangeId(), new SubmitInput(), AuthException.class, "submit not permitted");

    requestScopeOperations.setApiUser(admin.id());
    submit(result.getChangeId());
  }

  @Test
  public void submitWholeTopicMultipleProjects() throws Exception {
    assume().that(isSubmitWholeTopicEnabled()).isTrue();
    String topic = "test-topic";

    // Create test projects
    Project.NameKey keyA = createProjectForPush(getSubmitType());
    TestRepository<?> repoA = cloneProject(keyA);
    Project.NameKey keyB = createProjectForPush(getSubmitType());
    TestRepository<?> repoB = cloneProject(keyB);

    // Create changes on project-a
    PushOneCommit.Result change1 =
        createChange(repoA, "master", "Change 1", "a.txt", "content", topic);
    PushOneCommit.Result change2 =
        createChange(repoA, "master", "Change 2", "b.txt", "content", topic);

    // Create changes on project-b
    PushOneCommit.Result change3 =
        createChange(repoB, "master", "Change 3", "a.txt", "content", topic);
    PushOneCommit.Result change4 =
        createChange(repoB, "master", "Change 4", "b.txt", "content", topic);

    approve(change1.getChangeId());
    approve(change2.getChangeId());
    approve(change3.getChangeId());
    approve(change4.getChangeId());
    submit(change4.getChangeId());

    String expectedTopic = name(topic);
    change1.assertChange(Change.Status.MERGED, expectedTopic, admin);
    change2.assertChange(Change.Status.MERGED, expectedTopic, admin);
    change3.assertChange(Change.Status.MERGED, expectedTopic, admin);
    change4.assertChange(Change.Status.MERGED, expectedTopic, admin);
  }

  @Test
  public void submitWholeTopicMultipleBranchesOnSameProject() throws Exception {
    assume().that(isSubmitWholeTopicEnabled()).isTrue();
    String topic = "test-topic";

    // Create test project
    Project.NameKey keyA = createProjectForPush(getSubmitType());
    TestRepository<?> repoA = cloneProject(keyA);

    RevCommit initialHead = getRemoteHead(keyA, "master");

    // Create the dev branch on the test project
    BranchInput in = new BranchInput();
    in.revision = initialHead.name();
    gApi.projects().name(keyA.get()).branch("dev").create(in);

    // Create changes on master
    PushOneCommit.Result change1 =
        createChange(repoA, "master", "Change 1", "a.txt", "content", topic);
    PushOneCommit.Result change2 =
        createChange(repoA, "master", "Change 2", "b.txt", "content", topic);

    // Create  changes on dev
    repoA.reset(initialHead);
    PushOneCommit.Result change3 =
        createChange(repoA, "dev", "Change 3", "a.txt", "content", topic);
    PushOneCommit.Result change4 =
        createChange(repoA, "dev", "Change 4", "b.txt", "content", topic);

    approve(change1.getChangeId());
    approve(change2.getChangeId());
    approve(change3.getChangeId());
    approve(change4.getChangeId());
    submit(change4.getChangeId());

    String expectedTopic = name(topic);
    change1.assertChange(Change.Status.MERGED, expectedTopic, admin);
    change2.assertChange(Change.Status.MERGED, expectedTopic, admin);
    change3.assertChange(Change.Status.MERGED, expectedTopic, admin);
    change4.assertChange(Change.Status.MERGED, expectedTopic, admin);
  }

  @Test
  public void submitWholeTopic() throws Exception {
    assume().that(isSubmitWholeTopicEnabled()).isTrue();
    String topic = "test-topic";
    PushOneCommit.Result change1 = createChange("Change 1", "a.txt", "content", topic);
    PushOneCommit.Result change2 = createChange("Change 2", "b.txt", "content", topic);
    PushOneCommit.Result change3 = createChange("Change 3", "c.txt", "content", topic);
    approve(change1.getChangeId());
    approve(change2.getChangeId());
    approve(change3.getChangeId());
    submit(change3.getChangeId());
    String expectedTopic = name(topic);
    change1.assertChange(Change.Status.MERGED, expectedTopic, admin);
    change2.assertChange(Change.Status.MERGED, expectedTopic, admin);
    change3.assertChange(Change.Status.MERGED, expectedTopic, admin);

    // Check for the exact change to have the correct submitter.
    assertSubmitter(change3);
    // Also check submitters for changes submitted via the topic relationship.
    assertSubmitter(change1);
    assertSubmitter(change2);

    // Check that the repo has the expected commits
    List<RevCommit> log = getRemoteLog();
    List<String> commitsInRepo = log.stream().map(RevCommit::getShortMessage).collect(toList());
    int expectedCommitCount =
        getSubmitType() == SubmitType.MERGE_ALWAYS
            ? 5 // initial commit + 3 commits + merge commit
            : 4; // initial commit + 3 commits
    assertThat(log).hasSize(expectedCommitCount);

    assertThat(commitsInRepo)
        .containsAtLeast("Initial empty repository", "Change 1", "Change 2", "Change 3");
    if (getSubmitType() == SubmitType.MERGE_ALWAYS) {
      assertThat(commitsInRepo).contains("Merge changes from topic \"" + expectedTopic + "\"");
    }
  }

  @Test
  public void submitReusingOldTopic() throws Exception {
    assume().that(isSubmitWholeTopicEnabled()).isTrue();

    String topic = "test-topic";
    PushOneCommit.Result change1 = createChange("Change 1", "a.txt", "content", topic);
    PushOneCommit.Result change2 = createChange("Change 2", "a.txt", "content", topic);
    String id1 = change1.getChangeId();
    String id2 = change2.getChangeId();
    approve(id1);
    approve(id2);
    assertSubmittedTogether(id1, ImmutableList.of(id1, id2));
    assertSubmittedTogether(id2, ImmutableList.of(id1, id2));
    submit(id2);

    String expectedTopic = name(topic);
    change1.assertChange(Change.Status.MERGED, expectedTopic, admin);
    change2.assertChange(Change.Status.MERGED, expectedTopic, admin);
    assertSubmittedTogether(id1, ImmutableList.of(id1, id2));
    assertSubmittedTogether(id2, ImmutableList.of(id1, id2));

    PushOneCommit.Result change3 = createChange("Change 3", "c.txt", "content", topic);
    String id3 = change3.getChangeId();
    approve(id3);
    assertSubmittedTogether(id3, ImmutableList.of());
    submit(id3);

    change3.assertChange(Change.Status.MERGED, expectedTopic, admin);
    assertSubmittedTogether(id3, ImmutableList.of());
  }

  private void assertSubmittedTogether(String changeId, Iterable<String> expected)
      throws Exception {
    assertThat(gApi.changes().id(changeId).submittedTogether().stream().map(i -> i.changeId))
        .containsExactlyElementsIn(expected);
  }

  @Test
  public void submitWorkInProgressChange() throws Exception {
    PushOneCommit.Result change = pushTo("refs/for/master%wip");
    Change.Id num = change.getChange().getId();
    submitWithConflict(
        change.getChangeId(),
        "Failed to submit 1 change due to the following problems:\n"
            + "Change "
            + num
            + ": Change "
            + num
            + " is work in progress");
  }

  @Test
  public void submitWithHiddenBranchInSameTopic() throws Exception {
    assume().that(isSubmitWholeTopicEnabled()).isTrue();
    PushOneCommit.Result visible = createChange("refs/for/master/" + name("topic"));
    Change.Id num = visible.getChange().getId();

    createBranch(new Branch.NameKey(project, "hidden"));
    PushOneCommit.Result hidden = createChange("refs/for/hidden/" + name("topic"));
    approve(hidden.getChangeId());
    blockRead("refs/heads/hidden");

    submit(
        visible.getChangeId(),
        new SubmitInput(),
        AuthException.class,
        "A change to be submitted with " + num + " is not visible");
  }

  @Test
  public void submitChangeWhenParentOfOtherBranchTip() throws Exception {
    // Chain of two commits
    // Push both to topic-branch
    // Push the first commit for review and submit
    //
    // C2 -- tip of topic branch
    //  |
    // C1 -- pushed for review
    //  |
    // C0 -- Master
    //
    enableCreateNewChangeForAllNotInTarget();

    PushOneCommit push1 =
        pushFactory.create(admin.newIdent(), testRepo, PushOneCommit.SUBJECT, "a.txt", "content");
    PushOneCommit.Result c1 = push1.to("refs/heads/topic");
    c1.assertOkStatus();
    PushOneCommit push2 =
        pushFactory.create(
            admin.newIdent(), testRepo, PushOneCommit.SUBJECT, "b.txt", "anotherContent");
    PushOneCommit.Result c2 = push2.to("refs/heads/topic");
    c2.assertOkStatus();

    PushOneCommit.Result change1 = push1.to("refs/for/master");
    change1.assertOkStatus();

    approve(change1.getChangeId());
    submit(change1.getChangeId());
  }

  @Test
  public void submitMergeOfNonChangeBranchTip() throws Exception {
    // Merge a branch with commits that have not been submitted as
    // changes.
    //
    // M  -- mergeCommit (pushed for review and submitted)
    // | \
    // |  S -- stable (pushed directly to refs/heads/stable)
    // | /
    // I   -- master
    //
    RevCommit master = getRemoteHead(project, "master");
    PushOneCommit stableTip =
        pushFactory.create(admin.newIdent(), testRepo, "Tip of branch stable", "stable.txt", "");
    PushOneCommit.Result stable = stableTip.to("refs/heads/stable");
    PushOneCommit mergeCommit =
        pushFactory.create(admin.newIdent(), testRepo, "The merge commit", "merge.txt", "");
    mergeCommit.setParents(ImmutableList.of(master, stable.getCommit()));
    PushOneCommit.Result mergeReview = mergeCommit.to("refs/for/master");
    approve(mergeReview.getChangeId());
    submit(mergeReview.getChangeId());

    List<RevCommit> log = getRemoteLog();
    assertThat(log).contains(stable.getCommit());
    assertThat(log).contains(mergeReview.getCommit());
  }

  @Test
  public void submitMergeOfNonChangeBranchNonTip() throws Exception {
    // Merge a branch with commits that have not been submitted as
    // changes.
    //
    // MC  -- merge commit (pushed for review and submitted)
    // |\   S2 -- new stable tip (pushed directly to refs/heads/stable)
    // M \ /
    // |  S1 -- stable (pushed directly to refs/heads/stable)
    // | /
    // I -- master
    //
    RevCommit initial = getRemoteHead(project, "master");
    // push directly to stable to S1
    PushOneCommit.Result s1 =
        pushFactory
            .create(admin.newIdent(), testRepo, "new commit into stable", "stable1.txt", "")
            .to("refs/heads/stable");
    // move the stable tip ahead to S2
    pushFactory
        .create(admin.newIdent(), testRepo, "Tip of branch stable", "stable2.txt", "")
        .to("refs/heads/stable");

    testRepo.reset(initial);

    // move the master ahead
    PushOneCommit.Result m =
        pushFactory
            .create(admin.newIdent(), testRepo, "Move master ahead", "master.txt", "")
            .to("refs/heads/master");

    // create merge change
    PushOneCommit mc =
        pushFactory.create(admin.newIdent(), testRepo, "The merge commit", "merge.txt", "");
    mc.setParents(ImmutableList.of(m.getCommit(), s1.getCommit()));
    PushOneCommit.Result mergeReview = mc.to("refs/for/master");
    approve(mergeReview.getChangeId());
    submit(mergeReview.getChangeId());

    List<RevCommit> log = getRemoteLog();
    assertThat(log).contains(s1.getCommit());
    assertThat(log).contains(mergeReview.getCommit());
  }

  @Test
  public void submitChangeWithCommitThatWasAlreadyMerged() throws Exception {
    // create and submit a change
    PushOneCommit.Result change = createChange();
    submit(change.getChangeId());
    RevCommit headAfterSubmit = getRemoteHead();

    // set the status of the change back to NEW to simulate a failed submit that
    // merged the commit but failed to update the change status
    setChangeStatusToNew(change);

    // submitting the change again should detect that the commit was already
    // merged and just fix the change status to be MERGED
    submit(change.getChangeId());
    assertThat(getRemoteHead()).isEqualTo(headAfterSubmit);
  }

  @Test
  public void submitChangesWithCommitsThatWereAlreadyMerged() throws Exception {
    // create and submit 2 changes
    PushOneCommit.Result change1 = createChange();
    PushOneCommit.Result change2 = createChange();
    approve(change1.getChangeId());
    if (getSubmitType() == SubmitType.CHERRY_PICK) {
      submit(change1.getChangeId());
    }
    submit(change2.getChangeId());
    assertMerged(change1.getChangeId());
    RevCommit headAfterSubmit = getRemoteHead();

    // set the status of the changes back to NEW to simulate a failed submit that
    // merged the commits but failed to update the change status
    setChangeStatusToNew(change1, change2);

    // submitting the changes again should detect that the commits were already
    // merged and just fix the change status to be MERGED
    submit(change1.getChangeId());
    submit(change2.getChangeId());
    assertThat(getRemoteHead()).isEqualTo(headAfterSubmit);
  }

  @Test
  public void submitTopicWithCommitsThatWereAlreadyMerged() throws Exception {
    assume().that(isSubmitWholeTopicEnabled()).isTrue();

    // create and submit 2 changes with the same topic
    String topic = name("topic");
    PushOneCommit.Result change1 = createChange("refs/for/master/" + topic);
    PushOneCommit.Result change2 = createChange("refs/for/master/" + topic);
    approve(change1.getChangeId());
    submit(change2.getChangeId());
    assertMerged(change1.getChangeId());
    RevCommit headAfterSubmit = getRemoteHead();

    // set the status of the second change back to NEW to simulate a failed
    // submit that merged the commits but failed to update the change status of
    // some changes in the topic
    setChangeStatusToNew(change2);

    // submitting the topic again should detect that the commits were already
    // merged and just fix the change status to be MERGED
    submit(change2.getChangeId());
    assertThat(getRemoteHead()).isEqualTo(headAfterSubmit);
  }

  @Test
  public void submitWithValidation() throws Exception {
    AtomicBoolean called = new AtomicBoolean(false);
    this.addOnSubmitValidationListener(
        args -> {
          called.set(true);
          HashSet<String> refs = Sets.newHashSet(args.getCommands().keySet());
          assertThat(refs).contains("refs/heads/master");
          refs.remove("refs/heads/master");
          if (!refs.isEmpty()) {
            // Some submit strategies need to insert new patchset.
            assertThat(refs).hasSize(1);
            assertThat(refs.iterator().next()).startsWith(RefNames.REFS_CHANGES);
          }
        });

    PushOneCommit.Result change = createChange();
    approve(change.getChangeId());
    submit(change.getChangeId());
    assertThat(called.get()).isTrue();
  }

  @Test
  public void submitWithValidationMultiRepo() throws Exception {
    assume().that(isSubmitWholeTopicEnabled()).isTrue();
    String topic = "test-topic";

    // Create test projects
    Project.NameKey keyA = createProjectForPush(getSubmitType());
    TestRepository<?> repoA = cloneProject(keyA);
    Project.NameKey keyB = createProjectForPush(getSubmitType());
    TestRepository<?> repoB = cloneProject(keyB);

    // Create changes on project-a
    PushOneCommit.Result change1 =
        createChange(repoA, "master", "Change 1", "a.txt", "content", topic);
    PushOneCommit.Result change2 =
        createChange(repoA, "master", "Change 2", "b.txt", "content", topic);

    // Create changes on project-b
    PushOneCommit.Result change3 =
        createChange(repoB, "master", "Change 3", "a.txt", "content", topic);
    PushOneCommit.Result change4 =
        createChange(repoB, "master", "Change 4", "b.txt", "content", topic);

    List<PushOneCommit.Result> changes = Lists.newArrayList(change1, change2, change3, change4);
    for (PushOneCommit.Result change : changes) {
      approve(change.getChangeId());
    }

    // Construct validator which will throw on a second call.
    // Since there are 2 repos, first submit attempt will fail, the second will
    // succeed.
    List<String> projectsCalled = new ArrayList<>(4);
    this.addOnSubmitValidationListener(
        args -> {
          String master = "refs/heads/master";
          assertThat(args.getCommands()).containsKey(master);
          ReceiveCommand cmd = args.getCommands().get(master);
          ObjectId newMasterId = cmd.getNewId();
          try (Repository repo = repoManager.openRepository(args.getProject())) {
            assertThat(repo.exactRef(master).getObjectId()).isEqualTo(cmd.getOldId());
            assertThat(args.getRef(master)).hasValue(newMasterId);
            args.getRevWalk().parseBody(args.getRevWalk().parseCommit(newMasterId));
          } catch (IOException e) {
            throw new AssertionError("failed checking new ref value", e);
          }
          projectsCalled.add(args.getProject().get());
          if (projectsCalled.size() == 2) {
            throw new ValidationException("time to fail");
          }
        });
    submitWithConflict(change4.getChangeId(), "time to fail");
    assertThat(projectsCalled).containsExactly(keyA.get(), keyB.get());
    for (PushOneCommit.Result change : changes) {
      change.assertChange(Change.Status.NEW, name(topic), admin);
    }

    submit(change4.getChangeId());
    assertThat(projectsCalled).containsExactly(keyA.get(), keyB.get(), keyA.get(), keyB.get());
    for (PushOneCommit.Result change : changes) {
      change.assertChange(Change.Status.MERGED, name(topic), admin);
    }
  }

  @Test
  public void submitWithCommitAndItsMergeCommitTogether() throws Exception {
    assume().that(isSubmitWholeTopicEnabled()).isTrue();

    RevCommit initialHead = getRemoteHead();

    // Create a stable branch and bootstrap it.
    gApi.projects().name(project.get()).branch("stable").create(new BranchInput());
    PushOneCommit push =
        pushFactory.create(user.newIdent(), testRepo, "initial commit", "a.txt", "a");
    PushOneCommit.Result change = push.to("refs/heads/stable");

    RevCommit stable = getRemoteHead(project, "stable");
    RevCommit master = getRemoteHead(project, "master");

    assertThat(master).isEqualTo(initialHead);
    assertThat(stable).isEqualTo(change.getCommit());

    testRepo.git().fetch().call();
    testRepo.git().branchCreate().setName("stable").setStartPoint(stable).call();
    testRepo.git().branchCreate().setName("master").setStartPoint(master).call();

    // Create a fix in stable branch.
    testRepo.reset(stable);
    RevCommit fix =
        testRepo
            .commit()
            .parent(stable)
            .message("small fix")
            .add("b.txt", "b")
            .insertChangeId()
            .create();
    testRepo.branch("refs/heads/stable").update(fix);
    testRepo
        .git()
        .push()
        .setRefSpecs(new RefSpec("refs/heads/stable:refs/for/stable/" + name("topic")))
        .call();

    // Merge the fix into master.
    testRepo.reset(master);
    RevCommit merge =
        testRepo
            .commit()
            .parent(master)
            .parent(fix)
            .message("Merge stable into master")
            .insertChangeId()
            .create();
    testRepo.branch("refs/heads/master").update(merge);
    testRepo
        .git()
        .push()
        .setRefSpecs(new RefSpec("refs/heads/master:refs/for/master/" + name("topic")))
        .call();

    // Submit together.
    String fixId = GitUtil.getChangeId(testRepo, fix).get();
    String mergeId = GitUtil.getChangeId(testRepo, merge).get();
    approve(fixId);
    approve(mergeId);
    submit(mergeId);
    assertMerged(fixId);
    assertMerged(mergeId);
    testRepo.git().fetch().call();
    RevWalk rw = testRepo.getRevWalk();
    master = rw.parseCommit(getRemoteHead(project, "master"));
    assertThat(rw.isMergedInto(merge, master)).isTrue();
    assertThat(rw.isMergedInto(fix, master)).isTrue();
  }

  @Test
  public void retrySubmitSingleChangeOnLockFailure() throws Exception {
    PushOneCommit.Result change = createChange();
    String id = change.getChangeId();
    approve(id);

    TestSubmitInput input = new TestSubmitInput();
    input.generateLockFailures =
        new ArrayDeque<>(
            ImmutableList.of(
                true, // Attempt 1: lock failure
                false, // Attempt 2: success
                false)); // Leftover value to check total number of calls.
    submit(id, input);
    assertMerged(id);

    testRepo.git().fetch().call();
    RevWalk rw = testRepo.getRevWalk();
    RevCommit master = rw.parseCommit(getRemoteHead(project, "master"));
    RevCommit patchSet = parseCurrentRevision(rw, change.getChangeId());
    assertThat(rw.isMergedInto(patchSet, master)).isTrue();

    assertThat(input.generateLockFailures).containsExactly(false);
  }

  @Test
  public void retrySubmitAfterTornTopicOnLockFailure() throws Exception {
    assume().that(isSubmitWholeTopicEnabled()).isTrue();

    String topic = "test-topic";

    Project.NameKey keyA = createProjectForPush(getSubmitType());
    Project.NameKey keyB = createProjectForPush(getSubmitType());
    TestRepository<?> repoA = cloneProject(keyA);
    TestRepository<?> repoB = cloneProject(keyB);

    PushOneCommit.Result change1 =
        createChange(repoA, "master", "Change 1", "a.txt", "content", topic);
    PushOneCommit.Result change2 =
        createChange(repoB, "master", "Change 2", "b.txt", "content", topic);

    approve(change1.getChangeId());
    approve(change2.getChangeId());

    TestSubmitInput input = new TestSubmitInput();
    input.generateLockFailures =
        new ArrayDeque<>(
            ImmutableList.of(
                false, // Change 1, attempt 1: success
                true, // Change 2, attempt 1: lock failure
                false, // Change 1, attempt 2: success
                false, // Change 2, attempt 2: success
                false)); // Leftover value to check total number of calls.
    submit(change2.getChangeId(), input);

    String expectedTopic = name(topic);
    change1.assertChange(Change.Status.MERGED, expectedTopic, admin);
    change2.assertChange(Change.Status.MERGED, expectedTopic, admin);

    repoA.git().fetch().call();
    RevWalk rwA = repoA.getRevWalk();
    RevCommit masterA = rwA.parseCommit(getRemoteHead(keyA, "master"));
    RevCommit change1Ps = parseCurrentRevision(rwA, change1.getChangeId());
    assertThat(rwA.isMergedInto(change1Ps, masterA)).isTrue();

    repoB.git().fetch().call();
    RevWalk rwB = repoB.getRevWalk();
    RevCommit masterB = rwB.parseCommit(getRemoteHead(keyB, "master"));
    RevCommit change2Ps = parseCurrentRevision(rwB, change2.getChangeId());
    assertThat(rwB.isMergedInto(change2Ps, masterB)).isTrue();

    assertThat(input.generateLockFailures).containsExactly(false);
  }

  @Test
  public void authorAndCommitDateAreEqual() throws Exception {
    assume().that(getSubmitType()).isNotEqualTo(SubmitType.FAST_FORWARD_ONLY);

    ConfigInput ci = new ConfigInput();
    ci.matchAuthorToCommitterDate = InheritableBoolean.TRUE;
    gApi.projects().name(project.get()).config(ci);

    RevCommit initialHead = getRemoteHead();
    testRepo.reset(initialHead);
    PushOneCommit.Result change = createChange("Change 1", "b", "b");

    testRepo.reset(initialHead);
    PushOneCommit.Result change2 = createChange("Change 2", "c", "c");

    if (getSubmitType() == SubmitType.MERGE_IF_NECESSARY
        || getSubmitType() == SubmitType.REBASE_IF_NECESSARY) {
      // Merge another change so that change2 is not a fast-forward
      submit(change.getChangeId());
    }

    submit(change2.getChangeId());
    assertAuthorAndCommitDateEquals(getRemoteHead());
  }

  @Test
  @TestProjectInput(rejectEmptyCommit = InheritableBoolean.FALSE)
  public void submitEmptyCommitPatchSetCanNotFastForward_emptyCommitAllowed() throws Exception {
    assume().that(getSubmitType()).isNotEqualTo(SubmitType.FAST_FORWARD_ONLY);

    PushOneCommit.Result change = createChange("Change 1", "a.txt", "content");
    submit(change.getChangeId());

    ChangeApi revert1 = gApi.changes().id(change.getChangeId()).revert();
    approve(revert1.id());
    revert1.current().submit();

    ChangeApi revert2 = gApi.changes().id(change.getChangeId()).revert();
    approve(revert2.id());
    revert2.current().submit();
  }

  @Test
  @TestProjectInput(rejectEmptyCommit = InheritableBoolean.TRUE)
  public void submitEmptyCommitPatchSetCanNotFastForward_emptyCommitNotAllowed() throws Exception {
    assume().that(getSubmitType()).isNotEqualTo(SubmitType.FAST_FORWARD_ONLY);

    PushOneCommit.Result change = createChange("Change 1", "a.txt", "content");
    submit(change.getChangeId());

    ChangeApi revert1 = gApi.changes().id(change.getChangeId()).revert();
    approve(revert1.id());
    revert1.current().submit();

    ChangeApi revert2 = gApi.changes().id(change.getChangeId()).revert();
    approve(revert2.id());

    exception.expect(ResourceConflictException.class);
    exception.expectMessage(
        "Change "
            + revert2.get()._number
            + ": Change could not be merged because the commit is empty. "
            + "Project policy requires all commits to contain modifications to at least one file.");
    revert2.current().submit();
  }

  @Test
  @TestProjectInput(rejectEmptyCommit = InheritableBoolean.FALSE)
  public void submitEmptyCommitPatchSetCanFastForward_emptyCommitAllowed() throws Exception {
    ChangeInput ci = new ChangeInput();
    ci.subject = "Empty change";
    ci.project = project.get();
    ci.branch = "master";
    ChangeApi change = gApi.changes().create(ci);
    approve(change.id());
    change.current().submit();
  }

  @Test
  @TestProjectInput(rejectEmptyCommit = InheritableBoolean.TRUE)
  public void submitEmptyCommitPatchSetCanFastForward_emptyCommitNotAllowed() throws Exception {
    ChangeInput ci = new ChangeInput();
    ci.subject = "Empty change";
    ci.project = project.get();
    ci.branch = "master";
    ChangeApi change = gApi.changes().create(ci);
    approve(change.id());

    exception.expect(ResourceConflictException.class);
    exception.expectMessage(
        "Change "
            + change.get()._number
            + ": Change could not be merged because the commit is empty. "
            + "Project policy requires all commits to contain modifications to at least one file.");
    change.current().submit();
  }

  @Test
  @TestProjectInput(createEmptyCommit = false, rejectEmptyCommit = InheritableBoolean.TRUE)
  public void submitNonemptyCommitToEmptyRepoWithRejectEmptyCommit_allowed() throws Exception {
    assertThat(projectOperations.project(project).hasHead("master")).isFalse();
    PushOneCommit.Result change = createChange();
    assertThat(change.getCommit().getParents()).isEmpty();
    Map<Branch.NameKey, ObjectId> actual = fetchFromSubmitPreview(change.getChangeId());
    assertThat(projectOperations.project(project).hasHead("master")).isFalse();
    assertThat(actual).hasSize(1);

    submit(change.getChangeId());
    assertThat(getRemoteHead().getId()).isEqualTo(change.getCommit());
    assertTrees(project, actual);
  }

  @Test
  @TestProjectInput(createEmptyCommit = false, rejectEmptyCommit = InheritableBoolean.TRUE)
  public void submitEmptyCommitToEmptyRepoWithRejectEmptyCommit_allowed() throws Exception {
    assertThat(projectOperations.project(project).hasHead("master")).isFalse();
    PushOneCommit.Result change =
        pushFactory
            .create(admin.newIdent(), testRepo, "Change 1", ImmutableMap.of())
            .to("refs/for/master");
    change.assertOkStatus();
    // TODO(dborowitz): Use EMPTY_TREE_ID after upgrading to https://git.eclipse.org/r/127473
    assertThat(change.getCommit().getTree())
        .isEqualTo(ObjectId.fromString("4b825dc642cb6eb9a060e54bf8d69288fbee4904"));

    Map<Branch.NameKey, ObjectId> actual = fetchFromSubmitPreview(change.getChangeId());
    assertThat(projectOperations.project(project).hasHead("master")).isFalse();
    assertThat(actual).hasSize(1);

    submit(change.getChangeId());
    assertThat(getRemoteHead().getId()).isEqualTo(change.getCommit());
    assertTrees(project, actual);
  }

  private void setChangeStatusToNew(PushOneCommit.Result... changes) throws Exception {
    for (PushOneCommit.Result change : changes) {
      try (BatchUpdate bu =
          batchUpdateFactory.create(project, userFactory.create(admin.id()), TimeUtil.nowTs())) {
        bu.addOp(
            change.getChange().getId(),
            new BatchUpdateOp() {
              @Override
              public boolean updateChange(ChangeContext ctx) {
                ctx.getChange().setStatus(Change.Status.NEW);
                ctx.getUpdate(ctx.getChange().currentPatchSetId()).setStatus(Change.Status.NEW);
                return true;
              }
            });
        bu.execute();
      }
    }
  }

  private void assertSubmitter(PushOneCommit.Result change) throws Exception {
    ChangeInfo info = get(change.getChangeId(), ListChangesOption.MESSAGES);
    assertThat(info.messages).isNotNull();
    Iterable<String> messages = Iterables.transform(info.messages, i -> i.message);
    assertThat(messages).hasSize(3);
    String last = Iterables.getLast(messages);
    if (getSubmitType() == SubmitType.CHERRY_PICK) {
      assertThat(last).startsWith("Change has been successfully cherry-picked as ");
    } else if (getSubmitType() == SubmitType.REBASE_ALWAYS) {
      assertThat(last).startsWith("Change has been successfully rebased and submitted as");
    } else {
      assertThat(last).isEqualTo("Change has been successfully merged by Administrator");
    }
  }

  @Override
  protected void updateProjectInput(ProjectInput in) {
    in.submitType = getSubmitType();
    if (in.useContentMerge == InheritableBoolean.INHERIT) {
      in.useContentMerge = InheritableBoolean.FALSE;
    }
  }

  protected void submit(String changeId) throws Exception {
    submit(changeId, new SubmitInput(), null, null);
  }

  protected void submit(String changeId, SubmitInput input) throws Exception {
    submit(changeId, input, null, null);
  }

  protected void submitWithConflict(String changeId, String expectedError) throws Exception {
    submit(changeId, new SubmitInput(), ResourceConflictException.class, expectedError);
  }

  protected void submit(
      String changeId,
      SubmitInput input,
      Class<? extends RestApiException> expectedExceptionType,
      String expectedExceptionMsg)
      throws Exception {
    approve(changeId);
    if (expectedExceptionType == null) {
      assertSubmittable(changeId);
    }
    try {
      gApi.changes().id(changeId).current().submit(input);
      if (expectedExceptionType != null) {
        fail("Expected exception of type " + expectedExceptionType.getSimpleName());
      }
    } catch (RestApiException e) {
      if (expectedExceptionType == null) {
        throw e;
      }
      // More verbose than using assertThat and/or ExpectedException, but gives
      // us the stack trace.
      if (!expectedExceptionType.isAssignableFrom(e.getClass())
          || !e.getMessage().equals(expectedExceptionMsg)) {
        throw new AssertionError(
            "Expected exception of type "
                + expectedExceptionType.getSimpleName()
                + " with message: \""
                + expectedExceptionMsg
                + "\" but got exception of type "
                + e.getClass().getSimpleName()
                + " with message \""
                + e.getMessage()
                + "\"",
            e);
      }
      return;
    }
    ChangeInfo change = gApi.changes().id(changeId).info();
    assertMerged(change.changeId);
  }

  protected void assertSubmittable(String changeId) throws Exception {
    assertThat(get(changeId, SUBMITTABLE).submittable).named("submit bit on ChangeInfo").isTrue();
    RevisionResource rsrc = parseCurrentRevisionResource(changeId);
    UiAction.Description desc = submitHandler.getDescription(rsrc);
    assertThat(desc.isVisible()).named("visible bit on submit action").isTrue();
    assertThat(desc.isEnabled()).named("enabled bit on submit action").isTrue();
  }

  protected void assertChangeMergedEvents(String... expected) throws Exception {
    eventRecorder.assertChangeMergedEvents(project.get(), "refs/heads/master", expected);
  }

  protected void assertRefUpdatedEvents(RevCommit... expected) throws Exception {
    eventRecorder.assertRefUpdatedEvents(project.get(), "refs/heads/master", expected);
  }

  protected void assertCurrentRevision(String changeId, int expectedNum, ObjectId expectedId)
      throws Exception {
    ChangeInfo c = get(changeId, CURRENT_REVISION);
    assertThat(c.currentRevision).isEqualTo(expectedId.name());
    assertThat(c.revisions.get(expectedId.name())._number).isEqualTo(expectedNum);
    try (Repository repo = repoManager.openRepository(new Project.NameKey(c.project))) {
      String refName = new PatchSet.Id(new Change.Id(c._number), expectedNum).toRefName();
      Ref ref = repo.exactRef(refName);
      assertThat(ref).named(refName).isNotNull();
      assertThat(ref.getObjectId()).isEqualTo(expectedId);
    }
  }

  protected void assertNew(String changeId) throws Exception {
    assertThat(info(changeId).status).isEqualTo(ChangeStatus.NEW);
  }

  protected void assertApproved(String changeId) throws Exception {
    assertApproved(changeId, admin);
  }

  protected void assertApproved(String changeId, TestAccount user) throws Exception {
    ChangeInfo c = get(changeId, DETAILED_LABELS);
    LabelInfo cr = c.labels.get("Code-Review");
    assertThat(cr.all).hasSize(1);
    assertThat(cr.all.get(0).value).isEqualTo(2);
    assertThat(new Account.Id(cr.all.get(0)._accountId)).isEqualTo(user.id());
  }

  protected void assertMerged(String changeId) throws RestApiException {
    ChangeStatus status = gApi.changes().id(changeId).info().status;
    assertThat(status).isEqualTo(ChangeStatus.MERGED);
  }

  protected void assertPersonEquals(PersonIdent expected, PersonIdent actual) {
    assertThat(actual.getEmailAddress()).isEqualTo(expected.getEmailAddress());
    assertThat(actual.getName()).isEqualTo(expected.getName());
    assertThat(actual.getTimeZone()).isEqualTo(expected.getTimeZone());
  }

  protected void assertAuthorAndCommitDateEquals(RevCommit commit) {
    assertThat(commit.getAuthorIdent().getWhen()).isEqualTo(commit.getCommitterIdent().getWhen());
    assertThat(commit.getAuthorIdent().getTimeZone())
        .isEqualTo(commit.getCommitterIdent().getTimeZone());
  }

  protected void assertSubmitter(String changeId, int psId) throws Exception {
    assertSubmitter(changeId, psId, admin);
  }

  protected void assertSubmitter(String changeId, int psId, TestAccount user) throws Exception {
    Change c = getOnlyElement(queryProvider.get().byKeyPrefix(changeId)).change();
    ChangeNotes cn = notesFactory.createChecked(c);
    PatchSetApproval submitter =
        approvalsUtil.getSubmitter(cn, new PatchSet.Id(cn.getChangeId(), psId));
    assertThat(submitter).isNotNull();
    assertThat(submitter.isLegacySubmit()).isTrue();
    assertThat(submitter.getAccountId()).isEqualTo(user.id());
  }

  protected void assertNoSubmitter(String changeId, int psId) throws Exception {
    Change c = getOnlyElement(queryProvider.get().byKeyPrefix(changeId)).change();
    ChangeNotes cn = notesFactory.createChecked(c);
    PatchSetApproval submitter =
        approvalsUtil.getSubmitter(cn, new PatchSet.Id(cn.getChangeId(), psId));
    assertThat(submitter).isNull();
  }

  protected void assertCherryPick(TestRepository<?> testRepo, boolean contentMerge)
      throws Exception {
    assertRebase(testRepo, contentMerge);
    RevCommit remoteHead = getRemoteHead();
    assertThat(remoteHead.getFooterLines("Reviewed-On")).isNotEmpty();
    assertThat(remoteHead.getFooterLines("Reviewed-By")).isNotEmpty();
  }

  protected void assertRebase(TestRepository<?> testRepo, boolean contentMerge) throws Exception {
    Repository repo = testRepo.getRepository();
    RevCommit localHead = getHead(repo, "HEAD");
    RevCommit remoteHead = getRemoteHead();
    assertThat(localHead.getId()).isNotEqualTo(remoteHead.getId());
    assertThat(remoteHead.getParentCount()).isEqualTo(1);
    if (!contentMerge) {
      assertThat(getLatestRemoteDiff()).isEqualTo(getLatestDiff(repo));
    }
    assertThat(remoteHead.getShortMessage()).isEqualTo(localHead.getShortMessage());
  }

  protected List<RevCommit> getRemoteLog(Project.NameKey project, String branch) throws Exception {
    try (Repository repo = repoManager.openRepository(project);
        RevWalk rw = new RevWalk(repo)) {
      rw.markStart(rw.parseCommit(repo.exactRef("refs/heads/" + branch).getObjectId()));
      return Lists.newArrayList(rw);
    }
  }

  protected List<RevCommit> getRemoteLog() throws Exception {
    return getRemoteLog(project, "master");
  }

  protected void addOnSubmitValidationListener(OnSubmitValidationListener listener) {
    assertThat(onSubmitValidatorHandle).isNull();
    onSubmitValidatorHandle = onSubmitValidationListeners.add("gerrit", listener);
  }

  private String getLatestDiff(Repository repo) throws Exception {
    ObjectId oldTreeId = repo.resolve("HEAD~1^{tree}");
    ObjectId newTreeId = repo.resolve("HEAD^{tree}");
    return getLatestDiff(repo, oldTreeId, newTreeId);
  }

  private String getLatestRemoteDiff() throws Exception {
    try (Repository repo = repoManager.openRepository(project);
        RevWalk rw = new RevWalk(repo)) {
      ObjectId oldTreeId = repo.resolve("refs/heads/master~1^{tree}");
      ObjectId newTreeId = repo.resolve("refs/heads/master^{tree}");
      return getLatestDiff(repo, oldTreeId, newTreeId);
    }
  }

  private String getLatestDiff(Repository repo, ObjectId oldTreeId, ObjectId newTreeId)
      throws Exception {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    try (DiffFormatter fmt = new DiffFormatter(out)) {
      fmt.setRepository(repo);
      fmt.format(oldTreeId, newTreeId);
      fmt.flush();
      return out.toString();
    }
  }

  // TODO(hanwen): the submodule tests have a similar method; maybe we could share code?
  protected Project.NameKey createProjectForPush(SubmitType submitType) throws Exception {
    Project.NameKey project = projectOperations.newProject().submitType(submitType).create();
    grant(project, "refs/heads/*", Permission.PUSH);
    grant(project, "refs/for/refs/heads/*", Permission.SUBMIT);
    return project;
  }

  protected PushOneCommit.Result createChange(
      String subject, String fileName, String content, String topic) throws Exception {
    PushOneCommit push = pushFactory.create(admin.newIdent(), testRepo, subject, fileName, content);
    return push.to("refs/for/master/" + name(topic));
  }
}
