// 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.Truth.assert_;
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 static org.junit.Assert.fail;

import com.google.common.collect.ImmutableList;
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.NoHttpd;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.TestProjectInput;
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.extensions.api.changes.SubmitInput;
import com.google.gerrit.extensions.api.projects.BranchInput;
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.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.Submit;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.git.validators.OnSubmitValidationListener;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.project.Util;
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.validators.ValidationException;
import com.google.gerrit.testutil.ConfigSuite;
import com.google.gerrit.testutil.TestTimeUtil;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
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.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 Submit submitHandler;

  @Inject private IdentifiedUser.GenericFactory userFactory;

  @Inject private BatchUpdate.Factory updateFactory;

  @Inject private DynamicSet<OnSubmitValidationListener> onSubmitValidationListeners;
  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 cleanup() {
    db.close();
  }

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

  protected abstract SubmitType getSubmitType();

  @Test
  @TestProjectInput(createEmptyCommit = false)
  public void submitToEmptyRepo() throws Exception {
    RevCommit initialHead = getRemoteHead();
    PushOneCommit.Result change = createChange();
    Map<Branch.NameKey, ObjectId> actual = fetchFromSubmitPreview(change.getChangeId());
    RevCommit headAfterSubmitPreview = getRemoteHead();
    assertThat(headAfterSubmitPreview).isEqualTo(initialHead);
    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 = submitPreview(change4.getChangeId())) {
      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:
          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 = createProject("p");
    block(Permission.SUBMIT, REGISTERED_USERS, "refs/*", p);

    TestRepository<InMemoryRepository> repo = cloneProject(p, admin);
    PushOneCommit push = pushFactory.create(db, admin.getIdent(), 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 = createProject("p");
    ProjectConfig cfg = projectCache.checkedGet(p).getConfig();
    Util.block(cfg, Permission.SUBMIT, CHANGE_OWNER, "refs/*");
    Util.allow(cfg, Permission.SUBMIT, REGISTERED_USERS, "refs/heads/*");
    Util.allow(cfg, Permission.forLabel("Code-Review"), -2, +2, REGISTERED_USERS, "refs/*");
    saveProjectConfig(p, cfg);

    TestRepository<InMemoryRepository> repo = cloneProject(p, admin);
    PushOneCommit push = pushFactory.create(db, admin.getIdent(), 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");

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

  @Test
  public void onlySelfSubmit() throws Exception {
    // create project where only the change owner can submit
    Project.NameKey p = createProject("p");
    ProjectConfig cfg = projectCache.checkedGet(p).getConfig();
    Util.block(cfg, Permission.SUBMIT, REGISTERED_USERS, "refs/*");
    Util.allow(cfg, Permission.SUBMIT, CHANGE_OWNER, "refs/*");
    Util.allow(cfg, Permission.forLabel("Code-Review"), -2, +2, REGISTERED_USERS, "refs/*");
    saveProjectConfig(p, cfg);

    TestRepository<InMemoryRepository> repo = cloneProject(p, admin);
    PushOneCommit push = pushFactory.create(db, admin.getIdent(), 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());

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

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

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

    // Create test projects
    TestRepository<?> repoA = createProjectWithPush("project-a", null, getSubmitType());
    TestRepository<?> repoB = createProjectWithPush("project-b", null, getSubmitType());

    // 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
    String projectName = "project-a";
    TestRepository<?> repoA = createProjectWithPush(projectName, null, getSubmitType());

    RevCommit initialHead = getRemoteHead(new Project.NameKey(name(projectName)), "master");

    // Create the dev branch on the test project
    BranchInput in = new BranchInput();
    in.revision = initialHead.name();
    gApi.projects().name(name(projectName)).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(c -> c.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)
        .containsAllOf("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 submitDraftChange() throws Exception {
    PushOneCommit.Result draft = createDraftChange();
    Change.Id num = draft.getChange().getId();
    submitWithConflict(
        draft.getChangeId(),
        "Failed to submit 1 change due to the following problems:\n"
            + "Change "
            + num
            + ": Change "
            + num
            + " is draft");
  }

  @Test
  public void submitDraftPatchSet() throws Exception {
    PushOneCommit.Result change = createChange();
    PushOneCommit.Result draft = amendChangeAsDraft(change.getChangeId());
    Change.Id num = draft.getChange().getId();

    submitWithConflict(
        draft.getChangeId(),
        "Failed to submit 1 change due to the following problems:\n"
            + "Change "
            + num
            + ": submit rule error: "
            + "Cannot submit draft patch sets");
  }

  @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
    //
    ProjectConfig config = projectCache.checkedGet(project).getConfig();
    config.getProject().setCreateNewChangeForAllNotInTarget(InheritableBoolean.TRUE);
    saveProjectConfig(project, config);

    PushOneCommit push1 =
        pushFactory.create(
            db, admin.getIdent(), testRepo, PushOneCommit.SUBJECT, "a.txt", "content");
    PushOneCommit.Result c1 = push1.to("refs/heads/topic");
    c1.assertOkStatus();
    PushOneCommit push2 =
        pushFactory.create(
            db, admin.getIdent(), 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(
            db, admin.getIdent(), testRepo, "Tip of branch stable", "stable.txt", "");
    PushOneCommit.Result stable = stableTip.to("refs/heads/stable");
    PushOneCommit mergeCommit =
        pushFactory.create(db, admin.getIdent(), 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(db, admin.getIdent(), testRepo, "new commit into stable", "stable1.txt", "")
            .to("refs/heads/stable");
    // move the stable tip ahead to S2
    pushFactory
        .create(db, admin.getIdent(), testRepo, "Tip of branch stable", "stable2.txt", "")
        .to("refs/heads/stable");

    testRepo.reset(initial);

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

    // create merge change
    PushOneCommit mc =
        pushFactory.create(db, admin.getIdent(), 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(
        new OnSubmitValidationListener() {
          @Override
          public void preBranchUpdate(Arguments args) throws ValidationException {
            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
    TestRepository<?> repoA = createProjectWithPush("project-a", null, getSubmitType());
    TestRepository<?> repoB = createProjectWithPush("project-b", null, getSubmitType());

    // 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(
        new OnSubmitValidationListener() {
          @Override
          public void preBranchUpdate(Arguments args) throws ValidationException {
            assertThat(args.getCommands().keySet()).contains("refs/heads/master");
            try (RevWalk rw = args.newRevWalk()) {
              rw.parseBody(rw.parseCommit(args.getCommands().get("refs/heads/master").getNewId()));
            } catch (IOException e) {
              throw new ValidationException("Unexpected exception", 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(name("project-a"), name("project-b"));
    for (PushOneCommit.Result change : changes) {
      change.assertChange(Change.Status.NEW, name(topic), admin);
    }

    submit(change4.getChangeId());
    assertThat(projectsCalled)
        .containsExactly(
            name("project-a"), name("project-b"), name("project-a"), name("project-b"));
    for (PushOneCommit.Result change : changes) {
      change.assertChange(Change.Status.MERGED, name(topic), admin);
    }
  }

  private void setChangeStatusToNew(PushOneCommit.Result... changes) throws Exception {
    for (PushOneCommit.Result change : changes) {
      try (BatchUpdate bu =
          updateFactory.create(db, project, userFactory.create(admin.id), TimeUtil.nowTs())) {
        bu.addOp(
            change.getChange().getId(),
            new BatchUpdateOp() {
              @Override
              public boolean updateChange(ChangeContext ctx) throws OrmException {
                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")
        .isEqualTo(true);
    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(get(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.getId());
  }

  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 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(db, c);
    PatchSetApproval submitter =
        approvalsUtil.getSubmitter(db, cn, new PatchSet.Id(cn.getChangeId(), psId));
    assertThat(submitter).isNotNull();
    assertThat(submitter.isLegacySubmit()).isTrue();
    assertThat(submitter.getAccountId()).isEqualTo(user.getId());
  }

  protected void assertNoSubmitter(String changeId, int psId) throws Exception {
    Change c = getOnlyElement(queryProvider.get().byKeyPrefix(changeId)).change();
    ChangeNotes cn = notesFactory.createChecked(db, c);
    PatchSetApproval submitter =
        approvalsUtil.getSubmitter(db, 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);
    RevCommit remoteHead = getRemoteHead();
    assert_()
        .withFailureMessage(String.format("%s not equal %s", localHead.name(), remoteHead.name()))
        .that(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(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();
    }
  }
}
