// Copyright (C) 2017 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.googlesource.gerrit.plugins.automerger;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.OptionalSubject.optionals;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.common.truth.Truth8.assertThat;
import static com.google.gerrit.extensions.client.ListChangesOption.ALL_REVISIONS;
import static com.google.gerrit.extensions.client.ListChangesOption.CURRENT_COMMIT;
import static com.google.gerrit.extensions.client.ListChangesOption.CURRENT_REVISION;
import static com.google.gerrit.extensions.client.ListChangesOption.DETAILED_LABELS;
import static com.google.gerrit.extensions.client.ListChangesOption.MESSAGES;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static java.util.Comparator.comparing;

import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.io.CharStreams;
import com.google.gerrit.acceptance.GitUtil;
import com.google.gerrit.acceptance.LightweightPluginDaemonTest;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.TestPlugin;
import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.api.accounts.AccountApi;
import com.google.gerrit.extensions.api.changes.ChangeApi;
import com.google.gerrit.extensions.api.changes.RebaseInput;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.common.ApprovalInfo;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.ChangeMessageInfo;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.BranchNameKey;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.testing.TestTimeUtil;
import com.google.inject.Inject;
import com.googlesource.gerrit.plugins.automerger.helpers.ConfigOption;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
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.junit.Test;

@TestPlugin(
    name = "automerger",
    sysModule = "com.googlesource.gerrit.plugins.automerger.AutomergerModule")
public class DownstreamCreatorIT extends LightweightPluginDaemonTest {
  @Inject private GroupOperations groupOperations;
  @Inject private ProjectOperations projectOperations;

  @Test
  public void testExpectedFlow() throws Exception {
    Project.NameKey manifestNameKey = defaultSetup();
    // Create initial change
    PushOneCommit.Result result =
        createChange(testRepo, "master", "subject", "filename", "content", "testtopic");
    // Project name is scoped by test, so we need to get it from our initial change
    String projectName = result.getChange().project().get();
    createBranch(BranchNameKey.create(projectName, "ds_one"));
    createBranch(BranchNameKey.create(projectName, "ds_two"));
    pushDefaultConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
    // After we upload our config, we upload a new patchset to create the downstreams
    amendChange(result.getChangeId());
    result.assertOkStatus();
    // Check that there are the correct number of changes in the topic
    List<ChangeInfo> changesInTopic =
        gApi.changes()
            .query("topic: " + gApi.changes().id(result.getChangeId()).topic())
            .withOption(CURRENT_REVISION)
            .get();
    assertThat(changesInTopic).hasSize(3);

    List<ChangeInfo> sortedChanges = sortedChanges(changesInTopic);

    ChangeInfo dsOneChangeInfo = sortedChanges.get(0);
    assertThat(dsOneChangeInfo.branch).isEqualTo("ds_one");
    assertAutomergerChangeCreatedMessage(dsOneChangeInfo.id);

    ChangeInfo dsTwoChangeInfo = sortedChanges.get(1);
    assertThat(dsTwoChangeInfo.branch).isEqualTo("ds_two");
    assertAutomergerChangeCreatedMessage(dsTwoChangeInfo.id);

    ChangeInfo masterChangeInfo = sortedChanges.get(2);
    assertCodeReview(masterChangeInfo.id, 0, null);
    assertThat(masterChangeInfo.branch).isEqualTo("master");

    // Ensure that commit subjects are correct
    String masterSubject = masterChangeInfo.subject;
    String shortMasterSha = masterChangeInfo.currentRevision.substring(0, 10);
    assertThat(masterChangeInfo.subject).doesNotContainMatch("automerger");
    assertThat(dsOneChangeInfo.subject)
        .isEqualTo("[automerger] " + masterSubject + " am: " + shortMasterSha);
    assertThat(dsTwoChangeInfo.subject)
        .isEqualTo("[automerger] " + masterSubject + " am: " + shortMasterSha);

    // +2 and submit
    merge(result);
    assertCodeReview(masterChangeInfo.id, 2, null);
    assertCodeReview(dsOneChangeInfo.id, 2, "autogenerated:Automerger");
    assertCodeReview(dsTwoChangeInfo.id, 2, "autogenerated:Automerger");
  }

  @Test
  public void testDiamondMerge() throws Exception {
    Project.NameKey manifestNameKey = defaultSetup();
    // Create initial change
    PushOneCommit.Result initialResult = createChange("subject", "filename", "echo Hello");
    // Project name is scoped by test, so we need to get it from our initial change
    String projectName = initialResult.getChange().project().get();
    createBranch(BranchNameKey.create(projectName, "left"));
    createBranch(BranchNameKey.create(projectName, "right"));
    initialResult.assertOkStatus();
    merge(initialResult);
    // Reset to create a sibling
    ObjectId initial = repo().exactRef("HEAD").getLeaf().getObjectId();
    testRepo.reset(initial);
    // Make left != right
    PushOneCommit.Result left =
        createChange(
            testRepo, "left", "subject", "filename", "echo \"Hello asdfsd World\"", "randtopic");
    left.assertOkStatus();
    merge(left);

    String leftRevision = gApi.projects().name(projectName).branch("left").get().revision;
    String rightRevision = gApi.projects().name(projectName).branch("right").get().revision;
    // For this test, right != left
    assertThat(leftRevision).isNotEqualTo(rightRevision);
    createBranch(BranchNameKey.create(projectName, "bottom"));
    pushDiamondConfig(manifestNameKey.get(), projectName);
    // After we upload our config, we upload a new patchset to create the downstreams
    PushOneCommit.Result result =
        createChange(testRepo, "master", "subject", "filename2", "echo Hello", "sometopic");
    result.assertOkStatus();
    // Check that there are the correct number of changes in the topic
    List<ChangeInfo> changesInTopic =
        gApi.changes()
            .query("topic: " + gApi.changes().id(result.getChangeId()).topic())
            .withOptions(CURRENT_REVISION, CURRENT_COMMIT)
            .get();
    assertThat(changesInTopic).hasSize(5);
    // +2 and submit
    merge(result);
    List<ChangeInfo> sortedChanges = sortedChanges(changesInTopic);

    // Should create two changes on bottom, since left and right are different.
    ChangeInfo bottomChangeInfoA = sortedChanges.get(0);
    assertThat(bottomChangeInfoA.branch).isEqualTo("bottom");
    assertCodeReview(bottomChangeInfoA.id, 2, "autogenerated:Automerger");

    ChangeInfo bottomChangeInfoB = sortedChanges.get(1);
    assertThat(bottomChangeInfoB.branch).isEqualTo("bottom");
    assertCodeReview(bottomChangeInfoB.id, 2, "autogenerated:Automerger");

    ChangeInfo leftChangeInfo = sortedChanges.get(2);
    assertThat(leftChangeInfo.branch).isEqualTo("left");
    assertCodeReview(leftChangeInfo.id, 2, "autogenerated:Automerger");

    ChangeInfo masterChangeInfo = sortedChanges.get(3);
    assertThat(masterChangeInfo.branch).isEqualTo("master");
    assertCodeReview(masterChangeInfo.id, 2, null);

    ChangeInfo rightChangeInfo = sortedChanges.get(4);
    assertThat(rightChangeInfo.branch).isEqualTo("right");
    assertCodeReview(rightChangeInfo.id, 2, "autogenerated:Automerger");

    // Ensure that commit subjects are correct
    String masterSubject = masterChangeInfo.subject;
    String shortMasterSha = masterChangeInfo.currentRevision.substring(0, 10);
    String shortLeftSha = leftChangeInfo.currentRevision.substring(0, 10);
    String shortRightSha = rightChangeInfo.currentRevision.substring(0, 10);
    assertThat(masterChangeInfo.subject).doesNotContainMatch("automerger");
    assertThat(leftChangeInfo.subject)
        .isEqualTo("[automerger] " + masterSubject + " am: " + shortMasterSha);
    assertThat(rightChangeInfo.subject)
        .isEqualTo("[automerger] " + masterSubject + " am: " + shortMasterSha);

    // Either bottomChangeInfoA came from left and bottomChangeInfoB came from right, or vice versa
    // We don't know which, so we use the if condition to check
    String bottomChangeInfoASecondParent = getParent(bottomChangeInfoA, 1);
    if (bottomChangeInfoASecondParent.equals(leftChangeInfo.currentRevision)) {
      assertThat(bottomChangeInfoA.subject)
          .isEqualTo(
              "[automerger] " + masterSubject + " am: " + shortMasterSha + " am: " + shortLeftSha);
      assertThat(bottomChangeInfoB.subject)
          .isEqualTo(
              "[automerger] " + masterSubject + " am: " + shortMasterSha + " am: " + shortRightSha);
    } else {
      assertThat(bottomChangeInfoA.subject)
          .isEqualTo(
              "[automerger] " + masterSubject + " am: " + shortMasterSha + " am: " + shortRightSha);
      assertThat(bottomChangeInfoB.subject)
          .isEqualTo(
              "[automerger] " + masterSubject + " am: " + shortMasterSha + " am: " + shortLeftSha);
    }
  }

  @Test
  public void testDiamondMerge_identicalDiamondSides() throws Exception {
    Project.NameKey manifestNameKey = defaultSetup();
    // Create initial change
    PushOneCommit.Result initialResult = createChange("subject", "filename", "echo Hello");
    // Project name is scoped by test, so we need to get it from our initial change
    String projectName = initialResult.getChange().project().get();
    createBranch(BranchNameKey.create(projectName, "left"));
    createBranch(BranchNameKey.create(projectName, "right"));
    initialResult.assertOkStatus();
    merge(initialResult);

    String leftRevision = gApi.projects().name(projectName).branch("left").get().revision;
    String rightRevision = gApi.projects().name(projectName).branch("right").get().revision;
    // For this test, right == left
    assertThat(leftRevision).isEqualTo(rightRevision);
    createBranch(BranchNameKey.create(projectName, "bottom"));
    pushDiamondConfig(manifestNameKey.get(), projectName);

    // Freeze time so that the merge commit from left->bottom and right->bottom have same SHA
    TestTimeUtil.resetWithClockStep(0, TimeUnit.MILLISECONDS);
    TestTimeUtil.setClock(new Timestamp(TestTimeUtil.START.toEpochMilli()));
    // After we upload our config, we upload a new patchset to create the downstreams.
    PushOneCommit.Result result =
        createChange(testRepo, "master", "subject", "filename2", "echo Hello", "sometopic");
    TestTimeUtil.useSystemTime();
    result.assertOkStatus();

    List<ChangeInfo> changesInTopic =
        gApi.changes()
            .query("topic: " + gApi.changes().id(result.getChangeId()).topic())
            .withOption(CURRENT_REVISION)
            .get();
    assertThat(changesInTopic).hasSize(4);
    // +2 and submit
    merge(result);
    List<ChangeInfo> sortedChanges = sortedChanges(changesInTopic);

    // Should create two changes on bottom, since left and right are different.
    ChangeInfo bottomChangeInfo = sortedChanges.get(0);
    assertThat(bottomChangeInfo.branch).isEqualTo("bottom");
    assertCodeReview(bottomChangeInfo.id, 2, "autogenerated:Automerger");

    ChangeInfo leftChangeInfo = sortedChanges.get(1);
    assertThat(leftChangeInfo.branch).isEqualTo("left");
    assertCodeReview(leftChangeInfo.id, 2, "autogenerated:Automerger");

    ChangeInfo masterChangeInfo = sortedChanges.get(2);
    assertThat(masterChangeInfo.branch).isEqualTo("master");
    assertCodeReview(masterChangeInfo.id, 2, null);

    ChangeInfo rightChangeInfo = sortedChanges.get(3);
    assertThat(rightChangeInfo.branch).isEqualTo("right");
    assertCodeReview(rightChangeInfo.id, 2, "autogenerated:Automerger");

    // Ensure that commit subjects are correct
    String masterSubject = masterChangeInfo.subject;
    String shortMasterSha = masterChangeInfo.currentRevision.substring(0, 10);
    String shortLeftSha = leftChangeInfo.currentRevision.substring(0, 10);
    assertThat(masterChangeInfo.subject).doesNotContainMatch("automerger");
    assertThat(leftChangeInfo.subject)
        .isEqualTo("[automerger] " + masterSubject + " am: " + shortMasterSha);
    assertThat(rightChangeInfo.subject)
        .isEqualTo("[automerger] " + masterSubject + " am: " + shortMasterSha);
    assertThat(bottomChangeInfo.subject)
        .isEqualTo(
            "[automerger] " + masterSubject + " am: " + shortMasterSha + " am: " + shortLeftSha);
  }

  @Test
  public void testChangeStack() throws Exception {
    Project.NameKey manifestNameKey = defaultSetup();
    // Create initial change
    PushOneCommit.Result result =
        createChange(testRepo, "master", "subject", "filename", "content", "testtopic");
    // Project name is scoped by test, so we need to get it from our initial change
    String projectName = result.getChange().project().get();
    createBranch(BranchNameKey.create(projectName, "ds_one"));
    pushSimpleConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one");
    // After we upload our config, we upload a new patchset to create the downstreams
    amendChange(result.getChangeId());
    result.assertOkStatus();
    PushOneCommit.Result result2 =
        createChange(testRepo, "master", "subject2", "filename2", "content2", "testtopic");
    result2.assertOkStatus();
    // Check that there are the correct number of changes in the topic
    List<ChangeInfo> changesInTopic =
        gApi.changes()
            .query("topic: " + gApi.changes().id(result.getChangeId()).topic())
            .withOptions(ALL_REVISIONS, CURRENT_COMMIT)
            .get();
    assertThat(changesInTopic).hasSize(4);
    List<ChangeInfo> sortedChanges = sortedChanges(changesInTopic);

    // Change A'
    ChangeInfo aPrime = sortedChanges.get(0);
    assertThat(aPrime.branch).isEqualTo("ds_one");
    // Change B'
    ChangeInfo bPrime = sortedChanges.get(1);
    assertThat(bPrime.branch).isEqualTo("ds_one");
    String bPrimeFirstParent = getParent(bPrime, 0);
    assertThat(aPrime.currentRevision).isEqualTo(bPrimeFirstParent);

    // Change A
    ChangeInfo a = sortedChanges.get(2);
    assertThat(a.branch).isEqualTo("master");
    // Change B
    ChangeInfo b = sortedChanges.get(3);
    assertThat(b.branch).isEqualTo("master");
    String bFirstParent = getParent(b, 0);
    // Check that first parent of B is A
    assertThat(bFirstParent).isEqualTo(a.currentRevision);

    // Ensure that commit subjects are correct
    String shortASha = a.currentRevision.substring(0, 10);
    assertThat(a.subject).doesNotContainMatch("automerger");
    assertThat(aPrime.subject).isEqualTo("[automerger] test commit am: " + shortASha);
  }

  @Test
  public void testChangeStack_rebaseAfterUpload() throws Exception {
    Project.NameKey manifestNameKey = defaultSetup();
    // Save initial ref at HEAD
    ObjectId initial = repo().exactRef("HEAD").getLeaf().getObjectId();
    // Create initial change
    PushOneCommit.Result result =
        createChange(testRepo, "master", "subject", "filename", "content", "testtopic");
    // Project name is scoped by test, so we need to get it from our initial change
    String projectName = result.getChange().project().get();
    createBranch(BranchNameKey.create(projectName, "ds_one"));
    pushSimpleConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one");
    // After we upload our config, we upload a new patchset to create the downstreams
    amendChange(result.getChangeId());
    result.assertOkStatus();

    // Reset to initial ref to create a sibling
    testRepo.reset(initial);

    PushOneCommit.Result result2 =
        createChange(testRepo, "master", "subject2", "filename2", "content2", "testtopic");
    result2.assertOkStatus();
    // Check that there are the correct number of changes in the topic
    List<ChangeInfo> changesInTopic =
        gApi.changes()
            .query("topic: " + gApi.changes().id(result.getChangeId()).topic())
            .withOptions(ALL_REVISIONS, CURRENT_COMMIT)
            .get();
    assertThat(changesInTopic).hasSize(4);
    List<ChangeInfo> sortedChanges = sortedChanges(changesInTopic);

    // Check the first downstream change A'
    ChangeInfo aPrime = sortedChanges.get(0);
    assertThat(aPrime.branch).isEqualTo("ds_one");
    // Check the second downstream change B'
    ChangeInfo bPrime = sortedChanges.get(1);
    assertThat(bPrime.branch).isEqualTo("ds_one");
    // Check that B' does not have a first parent of A' yet
    String bPrimeFirstParent = getParent(bPrime, 0);
    assertThat(aPrime.currentRevision).isNotEqualTo(bPrimeFirstParent);

    // Change A
    ChangeInfo a = sortedChanges.get(2);
    assertThat(a.branch).isEqualTo("master");
    // Change B
    ChangeInfo b = sortedChanges.get(3);
    assertThat(b.branch).isEqualTo("master");
    String masterChangeInfo2FirstParentSha = getParent(b, 0);
    // Check that first parent of B is not A
    assertThat(a.currentRevision).isNotEqualTo(masterChangeInfo2FirstParentSha);

    // Rebase B on A
    RebaseInput rebaseInput = new RebaseInput();
    rebaseInput.base = a.currentRevision;
    gApi.changes().id(b.changeId).rebase(rebaseInput);

    // Check that B is now based on A, and B' is now based on A'
    ChangeInfo bAfterRebase = gApi.changes().id(b.changeId).get();
    String bAfterRebaseFirstParent = getParent(bAfterRebase, 0);
    assertThat(bAfterRebaseFirstParent).isEqualTo(a.currentRevision);

    ChangeInfo bPrimeAfterRebase = gApi.changes().id(bPrime.changeId).get();
    String bPrimeAfterRebaseFirstParent = getParent(bPrimeAfterRebase, 0);
    assertThat(bPrimeAfterRebaseFirstParent).isEqualTo(aPrime.currentRevision);
  }

  @Test
  public void testBlankMerge() throws Exception {
    Project.NameKey manifestNameKey = defaultSetup();
    // Create initial change
    PushOneCommit.Result result =
        createChange(
            testRepo, "master", "DO NOT MERGE subject", "filename", "content", "testtopic");
    // Project name is scoped by test, so we need to get it from our initial change
    String projectName = result.getChange().project().get();
    createBranch(BranchNameKey.create(projectName, "ds_one"));
    createBranch(BranchNameKey.create(projectName, "ds_two"));
    pushDefaultConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
    // After we upload our config, we upload a new patchset to create the downstreams
    amendChange(result.getChangeId(), "DO NOT MERGE subject", "filename", "content");
    result.assertOkStatus();

    ChangeApi change = gApi.changes().id(result.getChangeId());
    BinaryResult content = change.current().file("filename").content();

    List<ChangeInfo> changesInTopic =
        gApi.changes().query("topic: " + change.topic()).withOption(CURRENT_REVISION).get();
    assertThat(changesInTopic).hasSize(3);

    List<ChangeInfo> sortedChanges = sortedChanges(changesInTopic);

    ChangeInfo dsOneChangeInfo = sortedChanges.get(0);
    assertThat(dsOneChangeInfo.branch).isEqualTo("ds_one");
    assertAutomergerChangeCreatedMessage(dsOneChangeInfo.id);
    // It should skip ds_one, since this is a DO NOT MERGE
    ChangeApi dsOneChange = gApi.changes().id(dsOneChangeInfo._number);
    assertThat(dsOneChange.get().subject).contains("skipped:");
    assertThat(dsOneChange.current().files().keySet()).contains("filename");
    assertThat(dsOneChange.current().files().get("filename").linesDeleted).isEqualTo(1);

    ChangeInfo dsTwoChangeInfo = sortedChanges.get(1);
    assertThat(dsTwoChangeInfo.branch).isEqualTo("ds_two");
    assertAutomergerChangeCreatedMessage(dsTwoChangeInfo.id);
    // It should not skip ds_two, since it is marked with mergeAll: true
    ChangeApi dsTwoChange = gApi.changes().id(dsTwoChangeInfo._number);
    assertThat(dsTwoChange.get().subject).doesNotContain("skipped:");
    BinaryResult dsTwoContent = dsTwoChange.current().file("filename").content();
    assertThat(dsTwoContent.asString()).isEqualTo(content.asString());

    ChangeInfo masterChangeInfo = sortedChanges.get(2);
    assertCodeReview(masterChangeInfo.id, 0, null);
    assertThat(masterChangeInfo.branch).isEqualTo("master");

    // Ensure that commit subjects are correct
    String masterSubject = masterChangeInfo.subject;
    String shortMasterSha = masterChangeInfo.currentRevision.substring(0, 10);
    assertThat(masterChangeInfo.subject).doesNotContainMatch("automerger");
    assertThat(dsOneChangeInfo.subject)
        .isEqualTo("[automerger skipped] " + masterSubject + " skipped: " + shortMasterSha);
    assertThat(dsTwoChangeInfo.subject)
        .isEqualTo("[automerger] " + masterSubject + " am: " + shortMasterSha);
  }

  @Test
  public void testAlwaysBlankMerge() throws Exception {
    Project.NameKey manifestNameKey = defaultSetup();
    // Create initial change
    PushOneCommit.Result result =
        createChange(
            testRepo,
            "master",
            "DO NOT MERGE ANYWHERE subject",
            "filename",
            "content",
            "testtopic");
    // Project name is scoped by test, so we need to get it from our initial change
    String projectName = result.getChange().project().get();
    createBranch(BranchNameKey.create(projectName, "ds_one"));
    createBranch(BranchNameKey.create(projectName, "ds_two"));
    pushDefaultConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
    // After we upload our config, we upload a new patchset to create the downstreams
    amendChange(result.getChangeId(), "DO NOT MERGE ANYWHERE subject", "filename", "content");
    result.assertOkStatus();

    ChangeApi change = gApi.changes().id(result.getChangeId());
    List<ChangeInfo> changesInTopic =
        gApi.changes().query("topic: " + change.topic()).withOption(CURRENT_REVISION).get();
    assertThat(changesInTopic).hasSize(3);

    List<ChangeInfo> sortedChanges = sortedChanges(changesInTopic);

    ChangeInfo dsOneChangeInfo = sortedChanges.get(0);
    assertThat(dsOneChangeInfo.branch).isEqualTo("ds_one");
    assertAutomergerChangeCreatedMessage(dsOneChangeInfo.id);
    ChangeApi dsOneChange = gApi.changes().id(dsOneChangeInfo._number);
    // It should skip ds_one, since this is a DO NOT MERGE ANYWHERE
    assertThat(dsOneChange.get().subject).contains("skipped:");
    assertThat(dsOneChange.current().files().keySet()).contains("filename");
    assertThat(dsOneChange.current().files().get("filename").linesDeleted).isEqualTo(1);

    ChangeInfo dsTwoChangeInfo = sortedChanges.get(1);
    assertThat(dsTwoChangeInfo.branch).isEqualTo("ds_two");
    assertAutomergerChangeCreatedMessage(dsTwoChangeInfo.id);
    ChangeApi dsTwoChange = gApi.changes().id(dsTwoChangeInfo._number);
    // It should skip ds_one, since this is a DO NOT MERGE ANYWHERE
    assertThat(dsTwoChange.get().subject).contains("skipped:");
    assertThat(dsTwoChange.current().files().keySet()).contains("filename");
    assertThat(dsTwoChange.current().files().get("filename").linesDeleted).isEqualTo(1);

    ChangeInfo masterChangeInfo = sortedChanges.get(2);
    assertCodeReview(masterChangeInfo.id, 0, null);
    assertThat(masterChangeInfo.branch).isEqualTo("master");

    // Ensure that commit subjects are correct
    String masterSubject = masterChangeInfo.subject;
    String shortMasterSha = masterChangeInfo.currentRevision.substring(0, 10);
    assertThat(masterChangeInfo.subject).doesNotContainMatch("automerger");
    assertThat(dsOneChangeInfo.subject)
        .isEqualTo("[automerger skipped] " + masterSubject + " skipped: " + shortMasterSha);
    assertThat(dsTwoChangeInfo.subject)
        .isEqualTo("[automerger skipped] " + masterSubject + " skipped: " + shortMasterSha);
  }

  @Test
  public void testDownstreamMergeConflict() throws Exception {
    Project.NameKey manifestNameKey = defaultSetup();
    // Create initial change
    PushOneCommit.Result result = createChange("subject", "filename", "echo Hello");
    // Project name is scoped by test, so we need to get it from our initial change
    String projectName = result.getChange().project().get();
    createBranch(BranchNameKey.create(projectName, "ds_one"));
    createBranch(BranchNameKey.create(projectName, "ds_two"));
    result.assertOkStatus();
    merge(result);
    // Reset to create a sibling
    ObjectId initial = repo().exactRef("HEAD").getLeaf().getObjectId();
    testRepo.reset(initial);
    // Set up a merge conflict between master and ds_one
    PushOneCommit.Result ds1Result =
        createChange(
            testRepo, "ds_one", "subject", "filename", "echo \"Hello asdfsd World\"", "randtopic");
    ds1Result.assertOkStatus();
    merge(ds1Result);
    // Reset to allow our merge conflict to come
    testRepo.reset(initial);
    pushDefaultConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
    // After we upload our config, we upload a new change to create the downstreams
    PushOneCommit.Result masterResult =
        pushFactory
            .create(admin.newIdent(), testRepo, "subject", "filename", "echo 'Hello World!'")
            .to("refs/for/master");
    masterResult.assertOkStatus();

    // Since there's a conflict with ds_one, there should only be two changes in the topic
    List<ChangeInfo> changesInTopic =
        gApi.changes()
            .query("topic: " + gApi.changes().id(masterResult.getChangeId()).topic())
            .withOptions(CURRENT_REVISION, MESSAGES)
            .get();
    assertThat(changesInTopic).hasSize(2);
    List<ChangeInfo> sortedChanges = sortedChanges(changesInTopic);

    ChangeInfo dsTwoChangeInfo = sortedChanges.get(0);
    assertThat(dsTwoChangeInfo.branch).isEqualTo("ds_two");
    // This is -2 because the -2 vote from master propagated to ds_two
    assertCodeReview(dsTwoChangeInfo.id, -2, "autogenerated:Automerger");

    ChangeInfo masterChangeInfo = sortedChanges.get(1);
    assertCodeReview(masterChangeInfo.id, -2, "autogenerated:MergeConflict");
    assertThat(masterChangeInfo.branch).isEqualTo("master");

    // Make sure that merge conflict message is still added
    List<String> messages = new ArrayList<>();
    for (ChangeMessageInfo cmi : masterChangeInfo.messages) {
      messages.add(cmi.message);
    }
    assertThat(messages).contains("Patch Set 1: Code-Review-2\n\nMerge conflict found on ds_one");

    // Ensure that commit subjects are correct
    String masterSubject = masterChangeInfo.subject;
    String shortMasterSha = masterChangeInfo.currentRevision.substring(0, 10);
    assertThat(masterChangeInfo.subject).doesNotContainMatch("automerger");
    assertThat(dsTwoChangeInfo.subject)
        .isEqualTo("[automerger] " + masterSubject + " am: " + shortMasterSha);
  }

  @Test
  public void testRestrictedVotePermissions() throws Exception {
    Project.NameKey manifestNameKey = defaultSetup();
    // Create initial change
    PushOneCommit.Result result = createChange("subject", "filename", "echo Hello");
    // Project name is scoped by test, so we need to get it from our initial change
    String projectName = result.getChange().project().get();
    createBranch(BranchNameKey.create(projectName, "ds_one"));
    createBranch(BranchNameKey.create(projectName, "ds_two"));
    result.assertOkStatus();
    merge(result);
    // Reset to create a sibling
    ObjectId initial = repo().exactRef("HEAD").getLeaf().getObjectId();
    testRepo.reset(initial);
    // Set up a merge conflict between master and ds_one
    PushOneCommit.Result ds1Result =
        createChange(
            testRepo, "ds_one", "subject", "filename", "echo \"Hello asdfsd World\"", "randtopic");
    ds1Result.assertOkStatus();
    merge(ds1Result);
    // Reset to allow our merge conflict to come
    testRepo.reset(initial);
    pushDefaultConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");

    // Block Code Review label to test restrictions
    blockLabel("Code-Review", -2, 2, SystemGroupBackend.CHANGE_OWNER, "refs/heads/*", project);

    // After we upload our config, we upload a new change to create the downstreams
    PushOneCommit.Result masterResult =
        pushFactory
            .create(admin.newIdent(), testRepo, "subject", "filename", "echo 'Hello World!'")
            .to("refs/for/master");
    masterResult.assertOkStatus();

    // Since there's a conflict with ds_one, there should only be two changes in the topic
    List<ChangeInfo> changesInTopic =
        gApi.changes()
            .query("topic: " + gApi.changes().id(masterResult.getChangeId()).topic())
            .withOptions(CURRENT_REVISION, MESSAGES)
            .get();
    assertThat(changesInTopic).hasSize(2);
    List<ChangeInfo> sortedChanges = sortedChanges(changesInTopic);

    ChangeInfo dsTwoChangeInfo = sortedChanges.get(0);
    assertThat(dsTwoChangeInfo.branch).isEqualTo("ds_two");
    assertAutomergerChangeCreatedMessage(dsTwoChangeInfo.id);

    ChangeInfo masterChangeInfo = sortedChanges.get(1);
    // This is 0 because the -2 vote on master failed due to permissions
    assertCodeReview(masterChangeInfo.id, 0, null);
    assertThat(masterChangeInfo.branch).isEqualTo("master");
    assertThat(getLastMessage(masterChangeInfo.id).tag).isEqualTo("autogenerated:MergeConflict");

    // Make sure that merge conflict message is still added
    List<String> messages = new ArrayList<>();
    for (ChangeMessageInfo cmi : masterChangeInfo.messages) {
      messages.add(cmi.message);
    }
    assertThat(messages).contains("Patch Set 1:\n\nMerge conflict found on ds_one");

    // Ensure that commit subjects are correct
    String masterSubject = masterChangeInfo.subject;
    String shortMasterSha = masterChangeInfo.currentRevision.substring(0, 10);
    assertThat(masterChangeInfo.subject).doesNotContainMatch("automerger");
    assertThat(dsTwoChangeInfo.subject)
        .isEqualTo("[automerger] " + masterSubject + " am: " + shortMasterSha);
  }

  @Test
  public void testTopicEditedListener() throws Exception {
    Project.NameKey manifestNameKey = defaultSetup();
    // Create initial change
    PushOneCommit.Result result =
        createChange(testRepo, "master", "subject", "filename", "content", "testtopic");
    // Project name is scoped by test, so we need to get it from our initial change
    String projectName = result.getChange().project().get();
    createBranch(BranchNameKey.create(projectName, "ds_one"));
    createBranch(BranchNameKey.create(projectName, "ds_two"));
    pushDefaultConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
    // After we upload our config, we upload a new patchset to create the downstreams
    amendChange(result.getChangeId());
    result.assertOkStatus();
    gApi.changes().id(result.getChangeId()).topic("multiple words");
    gApi.changes().id(result.getChangeId()).topic("singlewordagain");
    // Check that there are the correct number of changes in the topic
    List<ChangeInfo> changesInTopic =
        gApi.changes()
            .query("topic:\"" + gApi.changes().id(result.getChangeId()).topic() + "\"")
            .get();
    assertThat(changesInTopic).hasSize(3);
    // +2 and submit
    merge(result);
  }

  @Test
  public void testTopicEditedListener_withQuotes() throws Exception {
    Project.NameKey manifestNameKey = defaultSetup();
    // Create initial change
    PushOneCommit.Result result =
        createChange(testRepo, "master", "subject", "filename", "content", "testtopic");
    // Project name is scoped by test, so we need to get it from our initial change
    String projectName = result.getChange().project().get();
    createBranch(BranchNameKey.create(projectName, "ds_one"));
    createBranch(BranchNameKey.create(projectName, "ds_two"));
    pushDefaultConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
    // After we upload our config, we upload a new patchset to create the downstreams
    amendChange(result.getChangeId());
    result.assertOkStatus();
    gApi.changes().id(result.getChangeId()).topic("multiple words");
    gApi.changes().id(result.getChangeId()).topic("with\"quotes\"inside");
    // Gerrit fails to submit changes in the same topic together if it contains quotes.
    gApi.changes().id(result.getChangeId()).topic("without quotes anymore");
    // Check that there are the correct number of changes in the topic
    List<ChangeInfo> changesInTopic =
        gApi.changes()
            .query("topic:{" + gApi.changes().id(result.getChangeId()).topic() + "}")
            .get();
    assertThat(changesInTopic).hasSize(3);
    // +2 and submit
    merge(result);
  }

  @Test
  public void testTopicEditedListener_withBraces() throws Exception {
    Project.NameKey manifestNameKey = defaultSetup();
    // Create initial change
    PushOneCommit.Result result =
        createChange(testRepo, "master", "subject", "filename", "content", "testtopic");
    // Project name is scoped by test, so we need to get it from our initial change
    String projectName = result.getChange().project().get();
    createBranch(BranchNameKey.create(projectName, "ds_one"));
    createBranch(BranchNameKey.create(projectName, "ds_two"));
    pushDefaultConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
    // After we upload our config, we upload a new patchset to create the downstreams
    amendChange(result.getChangeId());
    result.assertOkStatus();
    gApi.changes().id(result.getChangeId()).topic("multiple words");
    gApi.changes().id(result.getChangeId()).topic("with{braces}inside");
    // Check that there are the correct number of changes in the topic
    List<ChangeInfo> changesInTopic =
        gApi.changes()
            .query("topic:\"" + gApi.changes().id(result.getChangeId()).topic() + "\"")
            .get();
    assertThat(changesInTopic).hasSize(3);
    // +2 and submit
    merge(result);
  }

  @Test
  public void testTopicEditedListener_branchWithBracesAndQuotes() throws Exception {
    Project.NameKey manifestNameKey = defaultSetup();
    // Create initial change
    PushOneCommit.Result result =
        createChange(testRepo, "master", "subject", "filename", "content", "testtopic");
    // Project name is scoped by test, so we need to get it from our initial change
    String projectName = result.getChange().project().get();
    createBranch(BranchNameKey.create(projectName, "branch{}braces"));
    createBranch(BranchNameKey.create(projectName, "branch\"quotes"));
    pushDefaultConfig(
        "automerger.config",
        manifestNameKey.get(),
        projectName,
        "branch{}braces",
        "branch\"quotes");
    // After we upload our config, we upload a new patchset to create the downstreams
    amendChange(result.getChangeId());
    result.assertOkStatus();
    // Check that there are the correct number of changes in the topic
    List<ChangeInfo> changesInTopic =
        gApi.changes()
            .query("topic:\"" + gApi.changes().id(result.getChangeId()).topic() + "\"")
            .get();
    assertThat(changesInTopic).hasSize(3);
    // +2 and submit
    merge(result);
  }

  @Test
  public void testTopicEditedListener_emptyTopic() throws Exception {
    Project.NameKey manifestNameKey = defaultSetup();
    // Create initial change
    PushOneCommit.Result result =
        createChange(testRepo, "master", "subject", "filename", "content", "testtopic");
    // Project name is scoped by test, so we need to get it from our initial change
    String projectName = result.getChange().project().get();
    createBranch(BranchNameKey.create(projectName, "ds_one"));
    pushSimpleConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one");
    // After we upload our config, we upload a new patchset to create the downstreams
    amendChange(result.getChangeId());
    result.assertOkStatus();
    // Setting the topic to empty should be a no-op.
    gApi.changes().id(result.getChangeId()).topic("");
    assertThat(gApi.changes().id(result.getChangeId()).topic())
        .isEqualTo(gApi.changes().id(result.getChangeId()).topic());
    // +2 and submit
    merge(result);
  }

  @Test
  public void testContextUser() throws Exception {
    // Branch flow for contextUser is master -> ds_one -> ds_two
    Project.NameKey manifestNameKey = defaultSetup();
    // Create initial change
    PushOneCommit.Result initialResult = createChange("subject", "filename", "echo Hello");
    // Project name is scoped by test, so we need to get it from our initial change
    Project.NameKey projectNameKey = initialResult.getChange().project();
    String projectName = projectNameKey.get();
    createBranch(BranchNameKey.create(projectName, "ds_one"));
    createBranch(BranchNameKey.create(projectName, "ds_two"));
    initialResult.assertOkStatus();
    merge(initialResult);

    // Create normalUserGroup, containing user, and contextUserGroup, containing contextUser
    String normalUserGroup = groupOperations.newGroup().name("normalUserGroup").create().get();
    gApi.groups().id(normalUserGroup).addMembers(user.id().toString());
    AccountApi contextUserApi = gApi.accounts().create("someContextUser");
    String contextUserGroup = groupOperations.newGroup().name("contextUserGroup").create().get();
    gApi.groups().id(contextUserGroup).addMembers(contextUserApi.get().name);

    // Grant exclusive +2 to context user
    grantLabel(
        "Code-Review",
        -2,
        2,
        projectNameKey,
        "refs/heads/ds_one",
        false,
        AccountGroup.UUID.parse(gApi.groups().id(contextUserGroup).get().id),
        true);
    pushContextUserConfig(
        manifestNameKey.get(), projectName, contextUserApi.get()._accountId.toString());

    // After we upload our config, we upload a new patchset to create the downstreams
    PushOneCommit.Result result =
        createChange(testRepo, "master", "subject", "filename2", "echo Hello", "sometopic");
    result.assertOkStatus();
    // Check that there are the correct number of changes in the topic
    List<ChangeInfo> changesInTopic =
        gApi.changes()
            .query("topic: " + gApi.changes().id(result.getChangeId()).topic())
            .withOptions(CURRENT_REVISION, CURRENT_COMMIT)
            .get();
    assertThat(changesInTopic).hasSize(3);

    List<ChangeInfo> sortedChanges = sortedChanges(changesInTopic);

    // Check that downstream is at Code-Review 0
    ChangeInfo dsOneChangeInfo = sortedChanges.get(0);
    assertThat(dsOneChangeInfo.branch).isEqualTo("ds_one");
    assertCodeReview(dsOneChangeInfo.id, 0, null);

    // Try to +2 master and see it succeed to +2 master and ds_one
    ChangeInfo masterChangeInfo = sortedChanges.get(2);
    assertThat(masterChangeInfo.branch).isEqualTo("master");
    assertCodeReviewMissing(masterChangeInfo.id);
    approve(masterChangeInfo.id);
    assertCodeReview(masterChangeInfo.id, 2, null);
    assertCodeReview(dsOneChangeInfo.id, 2, "autogenerated:Automerger");

    // Try to +2 downstream and see it fail
    AuthException thrown = assertThrows(AuthException.class, () -> approve(dsOneChangeInfo.id));
    assertThat(thrown).hasMessageThat().contains("Applying label \"Code-Review\": 2 is restricted");
  }

  @Test
  public void testContextUser_downstreamHighestVote() throws Exception {
    // Branch flow for contextUser is master -> ds_one -> ds_two
    Project.NameKey manifestNameKey = defaultSetup();
    // Create initial change
    PushOneCommit.Result initialResult = createChange("subject", "filename", "echo Hello");
    // Project name is scoped by test, so we need to get it from our initial change
    Project.NameKey projectNameKey = initialResult.getChange().project();
    String projectName = projectNameKey.get();
    createBranch(BranchNameKey.create(projectName, "ds_one"));
    createBranch(BranchNameKey.create(projectName, "ds_two"));
    initialResult.assertOkStatus();
    merge(initialResult);

    // Create normalUserGroup, containing user, and contextUserGroup, containing contextUser
    String normalUserGroup = groupOperations.newGroup().name("normalUserGroup").create().get();
    gApi.groups().id(normalUserGroup).addMembers(user.id().toString());
    AccountApi contextUserApi = gApi.accounts().create("randomContextUser");
    String contextUserGroup = groupOperations.newGroup().name("contextUserGroup").create().get();
    gApi.groups().id(contextUserGroup).addMembers(contextUserApi.get().name);

    // Grant +2 to context user, since it doesn't have it by default
    grantLabel(
        "Code-Review",
        -2,
        2,
        projectNameKey,
        "refs/heads/*",
        false,
        AccountGroup.UUID.parse(gApi.groups().id(contextUserGroup).get().id),
        false);
    pushContextUserConfig(
        manifestNameKey.get(), projectName, contextUserApi.get()._accountId.toString());

    // After we upload our config, we upload a new patchset to create the downstreams
    PushOneCommit.Result result =
        createChange(testRepo, "master", "subject", "filename2", "echo Hello", "sometopic");
    result.assertOkStatus();
    // Check that there are the correct number of changes in the topic
    List<ChangeInfo> changesInTopic =
        gApi.changes()
            .query("topic: " + gApi.changes().id(result.getChangeId()).topic())
            .withOptions(CURRENT_REVISION, CURRENT_COMMIT)
            .get();
    assertThat(changesInTopic).hasSize(3);

    List<ChangeInfo> sortedChanges = sortedChanges(changesInTopic);

    // Check that downstream is at Code-Review 0
    ChangeInfo dsOneChangeInfo = sortedChanges.get(0);
    assertThat(dsOneChangeInfo.branch).isEqualTo("ds_one");
    assertCodeReview(dsOneChangeInfo.id, 0, null);

    // Try to +1 master and see it succeed to +1 master and ds_one
    ChangeInfo masterChangeInfo = sortedChanges.get(2);
    assertThat(masterChangeInfo.branch).isEqualTo("master");
    assertCodeReviewMissing(masterChangeInfo.id);
    recommend(masterChangeInfo.id);
    assertCodeReview(masterChangeInfo.id, 1, null);
    assertCodeReview(dsOneChangeInfo.id, 1, "autogenerated:Automerger");

    ChangeInfo dsTwoChangeInfo = sortedChanges.get(1);
    assertThat(dsTwoChangeInfo.branch).isEqualTo("ds_two");
    assertCodeReview(dsTwoChangeInfo.id, 1, "autogenerated:Automerger");

    // +2 ds_one and see that it overrides the +1 of the contextUser
    approve(dsOneChangeInfo.id);
    assertCodeReview(dsOneChangeInfo.id, 2, null);
    assertCodeReview(dsTwoChangeInfo.id, 2, "autogenerated:Automerger");
    // +0 ds_one and see that it goes back to the +1 of the contextUser
    gApi.changes().id(dsOneChangeInfo.id).revision("current").review(ReviewInput.noScore());
    assertCodeReview(dsOneChangeInfo.id, 1, "autogenerated:Automerger");
    assertCodeReview(dsTwoChangeInfo.id, 1, "autogenerated:Automerger");
  }

  @Test
  public void testContextUser_mergeConflictOnDownstreamVotesOnTopLevel() throws Exception {
    // Branch flow for contextUser is master -> ds_one -> ds_two
    Project.NameKey manifestNameKey = defaultSetup();
    // Create initial change
    PushOneCommit.Result initialResult = createChange("subject", "filename", "echo Hello");
    // Project name is scoped by test, so we need to get it from our initial change
    Project.NameKey projectNameKey = initialResult.getChange().project();
    String projectName = projectNameKey.get();
    createBranch(BranchNameKey.create(projectName, "ds_one"));
    createBranch(BranchNameKey.create(projectName, "ds_two"));
    initialResult.assertOkStatus();
    merge(initialResult);

    // Reset to create a sibling
    ObjectId initial = repo().exactRef("HEAD").getLeaf().getObjectId();
    PushOneCommit.Result ds1Result =
        createChange(
            testRepo, "ds_one", "subject", "filename", "echo \"Hello asdfsd World\"", "randtopic");
    ds1Result.assertOkStatus();
    merge(ds1Result);
    // Reset to allow our merge conflict to come
    testRepo.reset(initial);
    // Set up a merge conflict between ds_one and ds_two
    PushOneCommit.Result ds2Result =
        createChange(
            testRepo, "ds_two", "subject", "filename", "echo yo World wutup wutup", "randtopic");
    ds2Result.assertOkStatus();
    merge(ds2Result);
    testRepo.reset(initial);

    // Create normalUserGroup, containing current user, and contextUserGroup, containing contextUser
    String normalUserGroup = groupOperations.newGroup().name("normalUserGroup").create().get();
    gApi.groups().id(normalUserGroup).addMembers(user.id().toString());
    AccountApi contextUserApi = gApi.accounts().create("asdfContextUser");
    String contextUserGroup = groupOperations.newGroup().name("contextUserGroup").create().get();
    gApi.groups().id(contextUserGroup).addMembers(contextUserApi.get().name);

    // Grant +2 to context user, since it doesn't have it by default
    grantLabel(
        "Code-Review",
        -2,
        2,
        projectNameKey,
        "refs/heads/*",
        false,
        AccountGroup.UUID.parse(gApi.groups().id(contextUserGroup).get().id),
        false);
    pushContextUserConfig(
        manifestNameKey.get(), projectName, contextUserApi.get()._accountId.toString());

    // After we upload our config, we upload a new patchset to create the downstreams
    PushOneCommit.Result result =
        createChange(testRepo, "master", "subject", "filename2", "echo Hello", "sometopic");
    result.assertOkStatus();
    // Check that there are the correct number of changes in the topic
    List<ChangeInfo> changesInTopic =
        gApi.changes()
            .query("topic: " + gApi.changes().id(result.getChangeId()).topic())
            .withOptions(CURRENT_REVISION, CURRENT_COMMIT)
            .get();
    // There should only be two, as ds_one to ds_two should be a merge conflict
    assertThat(changesInTopic).hasSize(2);

    List<ChangeInfo> sortedChanges = sortedChanges(changesInTopic);

    // Check that master is at Code-Review -2
    ChangeInfo masterChangeInfo = sortedChanges.get(1);
    assertThat(masterChangeInfo.branch).isEqualTo("master");
    assertCodeReview(masterChangeInfo.id, -2, "autogenerated:MergeConflict");
  }

  private Project.NameKey defaultSetup() throws Exception {
    Project.NameKey manifestNameKey =
        projectOperations.newProject().name(name("platform/manifest")).create();
    setupTestRepo("default.xml", manifestNameKey, "master", "default.xml");
    setupTestRepo("ds_one.xml", manifestNameKey, "ds_one", "default.xml");
    setupTestRepo("ds_two.xml", manifestNameKey, "ds_two", "default.xml");
    return manifestNameKey;
  }

  private void setupTestRepo(
      String resourceName, Project.NameKey projectNameKey, String branchName, String filename)
      throws Exception {
    TestRepository<InMemoryRepository> repo = cloneProject(projectNameKey, admin);
    try (InputStream in = getClass().getResourceAsStream(resourceName)) {
      String resourceString = CharStreams.toString(new InputStreamReader(in, Charsets.UTF_8));

      PushOneCommit push =
          pushFactory.create(admin.newIdent(), repo, "some subject", filename, resourceString);
      push.to("refs/heads/" + branchName).assertOkStatus();
    }
  }

  private void pushConfig(List<ConfigOption> cfgOptions, String resourceName) throws Exception {
    TestRepository<InMemoryRepository> allProjectRepo = cloneProject(allProjects, admin);
    GitUtil.fetch(allProjectRepo, RefNames.REFS_CONFIG + ":config");
    allProjectRepo.reset("config");
    try (InputStream in = getClass().getResourceAsStream(resourceName)) {
      String resourceString = CharStreams.toString(new InputStreamReader(in, Charsets.UTF_8));

      Config cfg = new Config();
      cfg.fromText(resourceString);

      for (ConfigOption cfgOption : cfgOptions) {
        cfg.setString(cfgOption.section, cfgOption.subsection, cfgOption.key, cfgOption.value);
      }

      PushOneCommit push =
          pushFactory.create(
              admin.newIdent(), allProjectRepo, "Subject", "automerger.config", cfg.toText());
      push.to(RefNames.REFS_CONFIG).assertOkStatus();
    }
  }

  private void pushSimpleConfig(
      String resourceName, String manifestName, String project, String branch1) throws Exception {
    List<ConfigOption> options = new ArrayList<>();
    options.add(new ConfigOption("global", null, "manifestProject", manifestName));
    options.add(new ConfigOption("automerger", "master:" + branch1, "setProjects", project));
    pushConfig(options, resourceName);
  }

  private void pushDefaultConfig(
      String resourceName, String manifestName, String project, String branch1, String branch2)
      throws Exception {
    List<ConfigOption> options = new ArrayList<>();
    options.add(new ConfigOption("global", null, "manifestProject", manifestName));
    options.add(new ConfigOption("automerger", "master:" + branch1, "setProjects", project));
    options.add(new ConfigOption("automerger", "master:" + branch2, "setProjects", project));
    pushConfig(options, resourceName);
  }

  private void pushDiamondConfig(String manifestName, String project) throws Exception {
    List<ConfigOption> options = new ArrayList<>();
    options.add(new ConfigOption("global", null, "manifestProject", manifestName));
    options.add(new ConfigOption("automerger", "master:left", "setProjects", project));
    options.add(new ConfigOption("automerger", "master:right", "setProjects", project));
    options.add(new ConfigOption("automerger", "left:bottom", "setProjects", project));
    options.add(new ConfigOption("automerger", "right:bottom", "setProjects", project));
    pushConfig(options, "diamond.config");
  }

  private void pushContextUserConfig(String manifestName, String project, String contextUserId)
      throws Exception {
    List<ConfigOption> options = new ArrayList<>();
    options.add(new ConfigOption("global", null, "manifestProject", manifestName));
    options.add(new ConfigOption("global", null, "contextUserId", contextUserId));
    options.add(new ConfigOption("automerger", "master:ds_one", "setProjects", project));
    options.add(new ConfigOption("automerger", "ds_one:ds_two", "setProjects", project));
    pushConfig(options, "context_user.config");
  }

  private Optional<ApprovalInfo> getCodeReview(String id) throws RestApiException {
    List<ApprovalInfo> approvals =
        gApi.changes().id(id).get(DETAILED_LABELS).labels.get("Code-Review").all;
    if (approvals == null) {
      return Optional.empty();
    }
    return approvals.stream().max(comparing(a -> a.value));
  }

  private void assertCodeReview(String id, int expectedValue, @Nullable String expectedTag)
      throws RestApiException {
    Optional<ApprovalInfo> vote = getCodeReview(id);
    assertWithMessage("Code-Review vote").about(optionals()).that(vote).isPresent();
    assertWithMessage("value of Code-Review vote").that(vote.get().value).isEqualTo(expectedValue);
    assertWithMessage("tag of Code-Review vote").that(vote.get().tag).isEqualTo(expectedTag);
  }

  private void assertCodeReviewMissing(String id) throws RestApiException {
    assertThat(getCodeReview(id)).isEmpty();
  }

  private void assertAutomergerChangeCreatedMessage(String id) throws RestApiException {
    ChangeMessageInfo message = getLastMessage(id);
    assertThat(message.message).contains("Automerger change created!");
    assertThat(message.tag).isEqualTo("autogenerated:Automerger");
  }

  private ChangeMessageInfo getLastMessage(String id) throws RestApiException {
    List<ChangeMessageInfo> messages = gApi.changes().id(id).messages();
    assertThat(messages).isNotEmpty();
    return Iterables.getLast(messages);
  }

  private ImmutableList<ChangeInfo> sortedChanges(List<ChangeInfo> changes) {
    return changes.stream()
        .sorted(comparing((ChangeInfo c) -> c.branch).thenComparing(c -> c._number))
        .collect(toImmutableList());
  }

  public String getParent(ChangeInfo info, int number) {
    return info.revisions.get(info.currentRevision).commit.parents.get(number).commit;
  }
}
