// Copyright (C) 2016 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.server.notedb;

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.reviewdb.client.RefNames.changeMetaRef;
import static com.google.gerrit.reviewdb.client.RefNames.refsDraftComments;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.concurrent.TimeUnit.DAYS;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Ordering;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.AcceptanceTestRequestScope;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.extensions.api.changes.DraftInput;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.api.changes.ReviewInput.CommentInput;
import com.google.gerrit.extensions.api.changes.ReviewInput.DraftHandling;
import com.google.gerrit.extensions.client.Side;
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.extensions.common.Input;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchLineComment;
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.reviewdb.client.RevId;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.reviewdb.server.ReviewDbUtil;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.Sequences;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.git.RepoRefCache;
import com.google.gerrit.server.notedb.ChangeBundle;
import com.google.gerrit.server.notedb.ChangeBundleReader;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.NoteDbChangeState;
import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
import com.google.gerrit.server.notedb.NoteDbUpdateManager;
import com.google.gerrit.server.notedb.TestChangeRebuilderWrapper;
import com.google.gerrit.server.notedb.rebuild.ChangeRebuilder.NoPatchSetsException;
import com.google.gerrit.server.patch.PatchListCache;
import com.google.gerrit.server.patch.PatchListNotAvailableException;
import com.google.gerrit.server.patch.PatchSetInfoFactory;
import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
import com.google.gerrit.server.project.testing.Util;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.restapi.change.PostReview;
import com.google.gerrit.server.restapi.change.Rebuild;
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.update.UpdateException;
import com.google.gerrit.testing.ConfigSuite;
import com.google.gerrit.testing.NoteDbChecker;
import com.google.gerrit.testing.NoteDbMode;
import com.google.gerrit.testing.TestChanges;
import com.google.gerrit.testing.TestTimeUtil;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.OrmRuntimeException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.sql.Timestamp;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import org.apache.http.Header;
import org.apache.http.message.BasicHeader;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class ChangeRebuilderIT extends AbstractDaemonTest {
  @ConfigSuite.Default
  public static Config defaultConfig() {
    Config cfg = new Config();
    cfg.setBoolean("noteDb", null, "testRebuilderWrapper", true);

    // Disable async reindex-if-stale check after index update. This avoids
    // unintentional auto-rebuilding of the change in NoteDb during the read
    // path of the reindex-if-stale check. For the purposes of this test, we
    // want precise control over when auto-rebuilding happens.
    cfg.setBoolean("index", null, "autoReindexIfStale", false);

    // setNotesMigration tries to keep IDs in sync between ReviewDb and NoteDb, which is behavior
    // unique to this test. This gets prohibitively slow if we use the default sequence gap.
    cfg.setInt("noteDb", "changes", "initialSequenceGap", 0);

    return cfg;
  }

  @Inject private NoteDbChecker checker;

  @Inject private Rebuild rebuildHandler;

  @Inject private Provider<ReviewDb> dbProvider;

  @Inject private CommentsUtil commentsUtil;

  @Inject private Provider<PostReview> postReview;

  @Inject private TestChangeRebuilderWrapper rebuilderWrapper;

  @Inject private Sequences seq;

  @Inject private ChangeBundleReader bundleReader;

  @Inject private PatchSetInfoFactory patchSetInfoFactory;

  @Inject private PatchListCache patchListCache;

  @Before
  public void setUp() throws Exception {
    assume().that(NoteDbMode.get()).isEqualTo(NoteDbMode.OFF);
    TestTimeUtil.resetWithClockStep(1, SECONDS);
    setNotesMigration(false, false);
  }

  @After
  public void tearDown() {
    TestTimeUtil.useSystemTime();
  }

  @SuppressWarnings("deprecation")
  private void setNotesMigration(boolean writeChanges, boolean readChanges) throws Exception {
    notesMigration.setWriteChanges(writeChanges);
    notesMigration.setReadChanges(readChanges);
    db = atrScope.reopenDb().getReviewDbProvider().get();

    if (notesMigration.readChangeSequence()) {
      // Copy next ReviewDb ID to NoteDb.
      seq.getChangeIdRepoSequence().set(db.nextChangeId());
    } else {
      // Copy next NoteDb ID to ReviewDb.
      while (db.nextChangeId() < seq.getChangeIdRepoSequence().next()) {}
    }
  }

  @Test
  public void changeFields() throws Exception {
    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    gApi.changes().id(id.get()).topic(name("a-topic"));
    checker.rebuildAndCheckChanges(id);
  }

  @Test
  public void patchSets() throws Exception {
    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    amendChange(r.getChangeId());
    checker.rebuildAndCheckChanges(id);
  }

  @Test
  public void publishedComment() throws Exception {
    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    putComment(user, id, 1, "comment", null);
    checker.rebuildAndCheckChanges(id);
  }

  @Test
  public void publishedCommentAndReply() throws Exception {
    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    putComment(user, id, 1, "comment", null);
    Map<String, List<CommentInfo>> comments = getPublishedComments(id);
    String parentUuid = comments.get("a.txt").get(0).id;
    putComment(user, id, 1, "comment", parentUuid);
    checker.rebuildAndCheckChanges(id);
  }

  @Test
  public void patchSetWithNullGroups() throws Exception {
    Timestamp ts = TimeUtil.nowTs();
    Change c = TestChanges.newChange(project, user.getId(), seq.nextChangeId());
    c.setCreatedOn(ts);
    c.setLastUpdatedOn(ts);
    c.setReviewStarted(true);
    PatchSet ps =
        TestChanges.newPatchSet(
            c.currentPatchSetId(), "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef", user.getId());
    ps.setCreatedOn(ts);
    db.changes().insert(Collections.singleton(c));
    db.patchSets().insert(Collections.singleton(ps));

    assertThat(ps.getGroups()).isEmpty();
    checker.rebuildAndCheckChanges(c.getId());
  }

  @Test
  public void draftComment() throws Exception {
    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    putDraft(user, id, 1, "comment", null);
    checker.rebuildAndCheckChanges(id);
  }

  @Test
  public void draftAndPublishedComment() throws Exception {
    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    putDraft(user, id, 1, "draft comment", null);
    putComment(user, id, 1, "published comment", null);
    checker.rebuildAndCheckChanges(id);
  }

  @Test
  public void publishDraftComment() throws Exception {
    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    putDraft(user, id, 1, "draft comment", null);
    publishDrafts(user, id);
    checker.rebuildAndCheckChanges(id);
  }

  @Test
  public void nullAccountId() throws Exception {
    PushOneCommit.Result r = createChange();
    PatchSet.Id psId = r.getPatchSetId();
    Change.Id id = psId.getParentKey();

    // Events need to be otherwise identical for the account ID to be compared.
    ChangeMessage msg1 = insertMessage(id, psId, user.getId(), TimeUtil.nowTs(), "message 1");
    insertMessage(id, psId, null, msg1.getWrittenOn(), "message 2");

    checker.rebuildAndCheckChanges(id);
  }

  @Test
  public void nullPatchSetId() throws Exception {
    PushOneCommit.Result r = createChange();
    PatchSet.Id psId1 = r.getPatchSetId();
    Change.Id id = psId1.getParentKey();

    // Events need to be otherwise identical for the PatchSet.ID to be compared.
    ChangeMessage msg1 = insertMessage(id, null, user.getId(), TimeUtil.nowTs(), "message 1");
    insertMessage(id, null, user.getId(), msg1.getWrittenOn(), "message 2");

    PatchSet.Id psId2 = amendChange(r.getChangeId()).getPatchSetId();

    ChangeMessage msg3 = insertMessage(id, null, user.getId(), TimeUtil.nowTs(), "message 3");
    insertMessage(id, null, user.getId(), msg3.getWrittenOn(), "message 4");

    checker.rebuildAndCheckChanges(id);

    setNotesMigration(true, true);

    ChangeNotes notes = notesFactory.create(db, project, id);
    Map<String, PatchSet.Id> psIds = new HashMap<>();
    for (ChangeMessage msg : notes.getChangeMessages()) {
      PatchSet.Id psId = msg.getPatchSetId();
      assertThat(psId).named("patchset for " + msg).isNotNull();
      psIds.put(msg.getMessage(), psId);
    }
    // Patch set IDs were replaced during conversion process.
    assertThat(psIds).containsEntry("message 1", psId1);
    assertThat(psIds).containsEntry("message 2", psId1);
    assertThat(psIds).containsEntry("message 3", psId2);
    assertThat(psIds).containsEntry("message 4", psId2);
  }

  @Test
  public void noWriteToNewRef() throws Exception {
    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    checker.assertNoChangeRef(project, id);

    setNotesMigration(true, false);
    gApi.changes().id(id.get()).topic(name("a-topic"));

    // First write doesn't create the ref, but rebuilding works.
    checker.assertNoChangeRef(project, id);
    assertThat(getUnwrappedDb().changes().get(id).getNoteDbState()).isNull();
    checker.rebuildAndCheckChanges(id);

    // Now that there is a ref, writes are "turned on" for this change, and
    // NoteDb stays up to date without explicit rebuilding.
    gApi.changes().id(id.get()).topic(name("new-topic"));
    assertThat(getUnwrappedDb().changes().get(id).getNoteDbState()).isNotNull();
    checker.checkChanges(id);
  }

  @Test
  public void restApiNotFoundWhenNoteDbDisabled() throws Exception {
    PushOneCommit.Result r = createChange();
    exception.expect(ResourceNotFoundException.class);
    rebuildHandler.apply(parseChangeResource(r.getChangeId()), new Input());
  }

  @Test
  public void rebuildViaRestApi() throws Exception {
    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    setNotesMigration(true, false);

    checker.assertNoChangeRef(project, id);
    rebuildHandler.apply(parseChangeResource(r.getChangeId()), new Input());
    checker.checkChanges(id);
  }

  @Test
  public void writeToNewRefForNewChange() throws Exception {
    PushOneCommit.Result r1 = createChange();
    Change.Id id1 = r1.getPatchSetId().getParentKey();

    setNotesMigration(true, false);
    gApi.changes().id(id1.get()).topic(name("a-topic"));
    PushOneCommit.Result r2 = createChange();
    Change.Id id2 = r2.getPatchSetId().getParentKey();

    // Second change was created after NoteDb writes were turned on, so it was
    // allowed to write to a new ref.
    checker.checkChanges(id2);

    // First change was created before NoteDb writes were turned on, so its meta
    // ref doesn't exist until a manual rebuild.
    checker.assertNoChangeRef(project, id1);
    checker.rebuildAndCheckChanges(id1);
  }

  @Test
  public void noteDbChangeState() throws Exception {
    setNotesMigration(true, true);
    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();

    ObjectId changeMetaId = getMetaRef(project, changeMetaRef(id));
    assertThat(getUnwrappedDb().changes().get(id).getNoteDbState()).isEqualTo(changeMetaId.name());

    putDraft(user, id, 1, "comment by user", null);
    ObjectId userDraftsId = getMetaRef(allUsers, refsDraftComments(id, user.getId()));
    assertThat(getUnwrappedDb().changes().get(id).getNoteDbState())
        .isEqualTo(changeMetaId.name() + "," + user.getId() + "=" + userDraftsId.name());

    putDraft(admin, id, 2, "comment by admin", null);
    ObjectId adminDraftsId = getMetaRef(allUsers, refsDraftComments(id, admin.getId()));
    assertThat(admin.getId().get()).isLessThan(user.getId().get());
    assertThat(getUnwrappedDb().changes().get(id).getNoteDbState())
        .isEqualTo(
            changeMetaId.name()
                + ","
                + admin.getId()
                + "="
                + adminDraftsId.name()
                + ","
                + user.getId()
                + "="
                + userDraftsId.name());

    putDraft(admin, id, 2, "revised comment by admin", null);
    adminDraftsId = getMetaRef(allUsers, refsDraftComments(id, admin.getId()));
    assertThat(getUnwrappedDb().changes().get(id).getNoteDbState())
        .isEqualTo(
            changeMetaId.name()
                + ","
                + admin.getId()
                + "="
                + adminDraftsId.name()
                + ","
                + user.getId()
                + "="
                + userDraftsId.name());
  }

  @Test
  public void rebuildAutomaticallyWhenChangeOutOfDate() throws Exception {
    setNotesMigration(true, true);

    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    assertChangeUpToDate(true, id);

    // Make a ReviewDb change behind NoteDb's back and ensure it's detected.
    setNotesMigration(false, false);
    gApi.changes().id(id.get()).topic(name("a-topic"));
    setInvalidNoteDbState(id);
    assertChangeUpToDate(false, id);

    // On next NoteDb read, the change is transparently rebuilt.
    setNotesMigration(true, true);
    assertThat(gApi.changes().id(id.get()).info().topic).isEqualTo(name("a-topic"));
    assertChangeUpToDate(true, id);

    // Check that the bundles are equal.
    ChangeBundle actual =
        ChangeBundle.fromNotes(commentsUtil, notesFactory.create(dbProvider.get(), project, id));
    ChangeBundle expected = bundleReader.fromReviewDb(getUnwrappedDb(), id);
    assertThat(actual.differencesFrom(expected)).isEmpty();
  }

  @Test
  public void rebuildAutomaticallyWithinBatchUpdate() throws Exception {
    setNotesMigration(true, true);

    PushOneCommit.Result r = createChange();
    final Change.Id id = r.getPatchSetId().getParentKey();
    assertChangeUpToDate(true, id);

    // Update ReviewDb and NoteDb, then revert the corresponding NoteDb change
    // to simulate it failing.
    NoteDbChangeState oldState = NoteDbChangeState.parse(getUnwrappedDb().changes().get(id));
    String topic = name("a-topic");
    gApi.changes().id(id.get()).topic(topic);
    try (Repository repo = repoManager.openRepository(project)) {
      new TestRepository<>(repo).update(RefNames.changeMetaRef(id), oldState.getChangeMetaId());
    }
    assertChangeUpToDate(false, id);

    // Next NoteDb read comes inside the transaction started by BatchUpdate. In
    // reality this could be caused by a failed update happening between when
    // the change is parsed by ChangesCollection and when the BatchUpdate
    // executes. We simulate it here by using BatchUpdate directly and not going
    // through an API handler.
    final String msg = "message from BatchUpdate";
    try (BatchUpdate bu =
        batchUpdateFactory.create(
            db, project, identifiedUserFactory.create(user.getId()), TimeUtil.nowTs())) {
      bu.addOp(
          id,
          new BatchUpdateOp() {
            @Override
            public boolean updateChange(ChangeContext ctx) throws OrmException {
              PatchSet.Id psId = ctx.getChange().currentPatchSetId();
              ChangeMessage cm =
                  new ChangeMessage(
                      new ChangeMessage.Key(id, ChangeUtil.messageUuid()),
                      ctx.getAccountId(),
                      ctx.getWhen(),
                      psId);
              cm.setMessage(msg);
              ctx.getDb().changeMessages().insert(Collections.singleton(cm));
              ctx.getUpdate(psId).setChangeMessage(msg);
              return true;
            }
          });
      try {
        bu.execute();
        fail("expected update to fail");
      } catch (UpdateException e) {
        assertThat(e.getMessage()).contains("cannot copy ChangeNotesState");
      }
    }

    // TODO(dborowitz): Re-enable these assertions once we fix auto-rebuilding
    // in the BatchUpdate path.
    // As an implementation detail, change wasn't actually rebuilt inside the
    // BatchUpdate transaction, but it was rebuilt during read for the
    // subsequent reindex. Thus it's impossible to actually observe an
    // out-of-date state in the caller.
    // assertChangeUpToDate(true, id);

    // Check that the bundles are equal.
    // ChangeNotes notes = notesFactory.create(dbProvider.get(), project, id);
    // ChangeBundle actual = ChangeBundle.fromNotes(commentsUtil, notes);
    // ChangeBundle expected = bundleReader.fromReviewDb(getUnwrappedDb(), id);
    // assertThat(actual.differencesFrom(expected)).isEmpty();
    // assertThat(
    //        Iterables.transform(
    //            notes.getChangeMessages(),
    //            ChangeMessage::getMessage))
    //    .contains(msg);
    // assertThat(actual.getChange().getTopic()).isEqualTo(topic);
  }

  @Test
  public void rebuildIgnoresErrorIfChangeIsUpToDateAfter() throws Exception {
    setNotesMigration(true, true);

    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    assertChangeUpToDate(true, id);

    // Make a ReviewDb change behind NoteDb's back and ensure it's detected.
    setNotesMigration(false, false);
    gApi.changes().id(id.get()).topic(name("a-topic"));
    setInvalidNoteDbState(id);
    assertChangeUpToDate(false, id);

    // Force the next rebuild attempt to fail but also rebuild the change in the
    // background.
    rebuilderWrapper.stealNextUpdate();
    setNotesMigration(true, true);
    assertThat(gApi.changes().id(id.get()).info().topic).isEqualTo(name("a-topic"));
    assertChangeUpToDate(true, id);

    // Check that the bundles are equal.
    ChangeBundle actual =
        ChangeBundle.fromNotes(commentsUtil, notesFactory.create(dbProvider.get(), project, id));
    ChangeBundle expected = bundleReader.fromReviewDb(getUnwrappedDb(), id);
    assertThat(actual.differencesFrom(expected)).isEmpty();
  }

  @Test
  public void rebuildReturnsCorrectResultEvenIfSavingToNoteDbFailed() throws Exception {
    setNotesMigration(true, true);

    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    assertChangeUpToDate(true, id);
    ObjectId oldMetaId = getMetaRef(project, changeMetaRef(id));

    // Make a ReviewDb change behind NoteDb's back.
    setNotesMigration(false, false);
    gApi.changes().id(id.get()).topic(name("a-topic"));
    setInvalidNoteDbState(id);
    assertChangeUpToDate(false, id);
    assertThat(getMetaRef(project, changeMetaRef(id))).isEqualTo(oldMetaId);

    // Force the next rebuild attempt to fail.
    rebuilderWrapper.failNextUpdate();
    setNotesMigration(true, true);
    ChangeNotes notes = notesFactory.create(dbProvider.get(), project, id);

    // Not up to date, but the actual returned state matches anyway.
    assertChangeUpToDate(false, id);
    assertThat(getMetaRef(project, changeMetaRef(id))).isEqualTo(oldMetaId);
    ChangeBundle actual = ChangeBundle.fromNotes(commentsUtil, notes);
    ChangeBundle expected = bundleReader.fromReviewDb(getUnwrappedDb(), id);
    assertThat(actual.differencesFrom(expected)).isEmpty();
    assertChangeUpToDate(false, id);

    // Another rebuild attempt succeeds
    notesFactory.create(dbProvider.get(), project, id);
    assertThat(getMetaRef(project, changeMetaRef(id))).isNotEqualTo(oldMetaId);
    assertChangeUpToDate(true, id);
  }

  @Test
  public void rebuildReturnsDraftResultWhenRebuildingInChangeNotesFails() throws Exception {
    setNotesMigration(true, true);

    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    putDraft(user, id, 1, "comment by user", null);
    assertChangeUpToDate(true, id);

    ObjectId oldMetaId = getMetaRef(allUsers, refsDraftComments(id, user.getId()));

    // Add a draft behind NoteDb's back.
    setNotesMigration(false, false);
    putDraft(user, id, 1, "second comment by user", null);
    setInvalidNoteDbState(id);
    assertDraftsUpToDate(false, id, user);
    assertThat(getMetaRef(allUsers, refsDraftComments(id, user.getId()))).isEqualTo(oldMetaId);

    // Force the next rebuild attempt to fail (in ChangeNotes).
    rebuilderWrapper.failNextUpdate();
    setNotesMigration(true, true);
    ChangeNotes notes = notesFactory.create(dbProvider.get(), project, id);
    notes.getDraftComments(user.getId());
    assertThat(getMetaRef(allUsers, refsDraftComments(id, user.getId()))).isEqualTo(oldMetaId);

    // Not up to date, but the actual returned state matches anyway.
    assertDraftsUpToDate(false, id, user);
    ChangeBundle actual = ChangeBundle.fromNotes(commentsUtil, notes);
    ChangeBundle expected = bundleReader.fromReviewDb(getUnwrappedDb(), id);
    assertThat(actual.differencesFrom(expected)).isEmpty();

    // Another rebuild attempt succeeds
    notesFactory.create(dbProvider.get(), project, id);
    assertChangeUpToDate(true, id);
    assertDraftsUpToDate(true, id, user);
    assertThat(getMetaRef(allUsers, refsDraftComments(id, user.getId()))).isNotEqualTo(oldMetaId);
  }

  @Test
  public void rebuildReturnsDraftResultWhenRebuildingInDraftCommentNotesFails() throws Exception {
    setNotesMigration(true, true);

    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    putDraft(user, id, 1, "comment by user", null);
    assertChangeUpToDate(true, id);

    ObjectId oldMetaId = getMetaRef(allUsers, refsDraftComments(id, user.getId()));

    // Add a draft behind NoteDb's back.
    setNotesMigration(false, false);
    putDraft(user, id, 1, "second comment by user", null);

    ReviewDb db = getUnwrappedDb();
    Change c = db.changes().get(id);
    // Leave change meta ID alone so DraftCommentNotes does the rebuild.
    ObjectId badSha = ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
    NoteDbChangeState bogusState =
        new NoteDbChangeState(
            id,
            PrimaryStorage.REVIEW_DB,
            Optional.of(
                NoteDbChangeState.RefState.create(
                    NoteDbChangeState.parse(c).getChangeMetaId(),
                    ImmutableMap.of(user.getId(), badSha))),
            Optional.empty());
    c.setNoteDbState(bogusState.toString());
    db.changes().update(Collections.singleton(c));

    assertDraftsUpToDate(false, id, user);
    assertThat(getMetaRef(allUsers, refsDraftComments(id, user.getId()))).isEqualTo(oldMetaId);

    // Force the next rebuild attempt to fail (in DraftCommentNotes).
    rebuilderWrapper.failNextUpdate();
    setNotesMigration(true, true);
    ChangeNotes notes = notesFactory.create(dbProvider.get(), project, id);
    notes.getDraftComments(user.getId());
    assertThat(getMetaRef(allUsers, refsDraftComments(id, user.getId()))).isEqualTo(oldMetaId);

    // Not up to date, but the actual returned state matches anyway.
    assertChangeUpToDate(true, id);
    assertDraftsUpToDate(false, id, user);
    ChangeBundle actual = ChangeBundle.fromNotes(commentsUtil, notes);
    ChangeBundle expected = bundleReader.fromReviewDb(getUnwrappedDb(), id);
    assertThat(actual.differencesFrom(expected)).isEmpty();

    // Another rebuild attempt succeeds
    notesFactory.create(dbProvider.get(), project, id).getDraftComments(user.getId());
    assertChangeUpToDate(true, id);
    assertDraftsUpToDate(true, id, user);
    assertThat(getMetaRef(allUsers, refsDraftComments(id, user.getId()))).isNotEqualTo(oldMetaId);
  }

  @Test
  public void rebuildAutomaticallyWhenDraftsOutOfDate() throws Exception {
    setNotesMigration(true, true);
    setApiUser(user);

    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    putDraft(user, id, 1, "comment", null);
    assertDraftsUpToDate(true, id, user);

    // Make a ReviewDb change behind NoteDb's back and ensure it's detected.
    setNotesMigration(false, false);
    putDraft(user, id, 1, "comment", null);
    setInvalidNoteDbState(id);
    assertDraftsUpToDate(false, id, user);

    // On next NoteDb read, the drafts are transparently rebuilt.
    setNotesMigration(true, true);
    assertThat(gApi.changes().id(id.get()).current().drafts()).containsKey(PushOneCommit.FILE_NAME);
    assertDraftsUpToDate(true, id, user);
  }

  @Test
  public void pushCert() throws Exception {
    // We don't have the code in our test harness to do signed pushes, so just
    // use a hard-coded cert. This cert was actually generated by C git 2.2.0
    // (albeit not for sending to Gerrit).
    String cert =
        "certificate version 0.1\n"
            + "pusher Dave Borowitz <dborowitz@google.com> 1433954361 -0700\n"
            + "pushee git://localhost/repo.git\n"
            + "nonce 1433954361-bde756572d665bba81d8\n"
            + "\n"
            + "0000000000000000000000000000000000000000"
            + "b981a177396fb47345b7df3e4d3f854c6bea7"
            + "s/heads/master\n"
            + "-----BEGIN PGP SIGNATURE-----\n"
            + "Version: GnuPG v1\n"
            + "\n"
            + "iQEcBAABAgAGBQJVeGg5AAoJEPfTicJkUdPkUggH/RKAeI9/i/LduuiqrL/SSdIa\n"
            + "9tYaSqJKLbXz63M/AW4Sp+4u+dVCQvnAt/a35CVEnpZz6hN4Kn/tiswOWVJf4CO7\n"
            + "htNubGs5ZMwvD6sLYqKAnrM3WxV/2TbbjzjZW6Jkidz3jz/WRT4SmjGYiEO7aA+V\n"
            + "4ZdIS9f7sW5VsHHYlNThCA7vH8Uu48bUovFXyQlPTX0pToSgrWV3JnTxDNxfn3iG\n"
            + "IL0zTY/qwVCdXgFownLcs6J050xrrBWIKqfcWr3u4D2aCLyR0v+S/KArr7ulZygY\n"
            + "+SOklImn8TAZiNxhWtA6ens66IiammUkZYFv7SSzoPLFZT4dC84SmGPWgf94NoQ=\n"
            + "=XFeC\n"
            + "-----END PGP SIGNATURE-----\n";

    PushOneCommit.Result r = createChange();
    PatchSet.Id psId = r.getPatchSetId();
    Change.Id id = psId.getParentKey();

    PatchSet ps = db.patchSets().get(psId);
    ps.setPushCertificate(cert);
    db.patchSets().update(Collections.singleton(ps));
    indexer.index(db, project, id);

    checker.rebuildAndCheckChanges(id);
  }

  @Test
  public void emptyTopic() throws Exception {
    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    Change c = db.changes().get(id);
    assertThat(c.getTopic()).isNull();
    c.setTopic("");
    db.changes().update(Collections.singleton(c));

    checker.rebuildAndCheckChanges(id);

    setNotesMigration(true, true);

    // Rebuild and check was successful, but NoteDb doesn't support storing an
    // empty topic, so it comes out as null.
    ChangeNotes notes = notesFactory.create(db, project, id);
    assertThat(notes.getChange().getTopic()).isNull();
  }

  @Test
  public void commentBeforeFirstPatchSet() throws Exception {
    PushOneCommit.Result r = createChange();
    PatchSet.Id psId = r.getPatchSetId();
    Change.Id id = psId.getParentKey();

    Change c = db.changes().get(id);
    c.setCreatedOn(new Timestamp(c.getCreatedOn().getTime() - 5000));
    db.changes().update(Collections.singleton(c));
    indexer.index(db, project, id);

    ReviewInput rin = new ReviewInput();
    rin.message = "comment";

    Timestamp ts = new Timestamp(c.getCreatedOn().getTime() + 2000);
    assertThat(ts).isGreaterThan(c.getCreatedOn());
    assertThat(ts).isLessThan(db.patchSets().get(psId).getCreatedOn());
    RevisionResource revRsrc = parseCurrentRevisionResource(r.getChangeId());
    postReview.get().apply(batchUpdateFactory, revRsrc, rin, ts);

    checker.rebuildAndCheckChanges(id);
  }

  @Test
  public void commentPredatingChangeBySomeoneOtherThanOwner() throws Exception {
    PushOneCommit.Result r = createChange();
    PatchSet.Id psId = r.getPatchSetId();
    Change.Id id = psId.getParentKey();
    Change c = db.changes().get(id);

    ReviewInput rin = new ReviewInput();
    rin.message = "comment";

    Timestamp ts = new Timestamp(c.getCreatedOn().getTime() - 10000);
    RevisionResource revRsrc = parseCurrentRevisionResource(r.getChangeId());
    setApiUser(user);
    postReview.get().apply(batchUpdateFactory, revRsrc, rin, ts);

    checker.rebuildAndCheckChanges(id);
  }

  @Test
  public void noteDbUsesOriginalSubjectFromPatchSetAndIgnoresChangeField() throws Exception {
    PushOneCommit.Result r = createChange();
    String orig = r.getChange().change().getSubject();
    r =
        pushFactory
            .create(
                db,
                admin.getIdent(),
                testRepo,
                orig + " v2",
                PushOneCommit.FILE_NAME,
                "new contents",
                r.getChangeId())
            .to("refs/for/master");
    r.assertOkStatus();

    PatchSet.Id psId = r.getPatchSetId();
    Change.Id id = psId.getParentKey();
    Change c = db.changes().get(id);

    c.setCurrentPatchSet(psId, c.getSubject(), "Bogus original subject");
    db.changes().update(Collections.singleton(c));

    checker.rebuildAndCheckChanges(id);

    setNotesMigration(true, true);
    ChangeNotes notes = notesFactory.create(db, project, id);
    Change nc = notes.getChange();
    assertThat(nc.getSubject()).isEqualTo(c.getSubject());
    assertThat(nc.getSubject()).isEqualTo(orig + " v2");
    assertThat(nc.getOriginalSubject()).isNotEqualTo(c.getOriginalSubject());
    assertThat(nc.getOriginalSubject()).isEqualTo(orig);
  }

  @Test
  public void ignorePatchLineCommentsOnPatchSet0() throws Exception {
    PushOneCommit.Result r = createChange();
    Change change = r.getChange().change();
    Change.Id id = change.getId();

    PatchLineComment comment =
        new PatchLineComment(
            new PatchLineComment.Key(
                new Patch.Key(new PatchSet.Id(id, 0), PushOneCommit.FILE_NAME), "uuid"),
            0,
            user.getId(),
            null,
            TimeUtil.nowTs());
    comment.setSide((short) 1);
    comment.setMessage("message");
    comment.setStatus(PatchLineComment.Status.PUBLISHED);
    db.patchComments().insert(Collections.singleton(comment));
    indexer.index(db, change.getProject(), id);

    checker.rebuildAndCheckChanges(id);

    setNotesMigration(true, true);
    ChangeNotes notes = notesFactory.create(db, project, id);
    assertThat(notes.getComments()).isEmpty();
  }

  @Test
  public void leadingSpacesInSubject() throws Exception {
    String subj = "   " + PushOneCommit.SUBJECT;
    PushOneCommit push =
        pushFactory.create(
            db,
            admin.getIdent(),
            testRepo,
            subj,
            PushOneCommit.FILE_NAME,
            PushOneCommit.FILE_CONTENT);
    PushOneCommit.Result r = push.to("refs/for/master");
    r.assertOkStatus();
    Change change = r.getChange().change();
    assertThat(change.getSubject()).isEqualTo(subj);
    Change.Id id = r.getPatchSetId().getParentKey();

    checker.rebuildAndCheckChanges(id);

    setNotesMigration(true, true);
    ChangeNotes notes = notesFactory.create(db, project, id);
    assertThat(notes.getChange().getSubject()).isNotEqualTo(subj);
    assertThat(notes.getChange().getSubject()).isEqualTo(PushOneCommit.SUBJECT);
  }

  @Test
  public void allTimestampsExceptUpdatedAreEqualDueToBadMigration() throws Exception {
    // https://bugs.chromium.org/p/gerrit/issues/detail?id=7397
    PushOneCommit.Result r = createChange();
    Change c = r.getChange().change();
    Change.Id id = c.getId();
    Timestamp ts = TimeUtil.nowTs();
    Timestamp origUpdated = c.getLastUpdatedOn();

    c.setCreatedOn(ts);
    assertThat(c.getCreatedOn()).isGreaterThan(c.getLastUpdatedOn());
    db.changes().update(Collections.singleton(c));

    List<ChangeMessage> cm = db.changeMessages().byChange(id).toList();
    cm.forEach(m -> m.setWrittenOn(ts));
    db.changeMessages().update(cm);

    List<PatchSet> ps = db.patchSets().byChange(id).toList();
    ps.forEach(p -> p.setCreatedOn(ts));
    db.patchSets().update(ps);

    List<PatchSetApproval> psa = db.patchSetApprovals().byChange(id).toList();
    psa.forEach(p -> p.setGranted(ts));
    db.patchSetApprovals().update(psa);

    List<PatchLineComment> plc = db.patchComments().byChange(id).toList();
    plc.forEach(p -> p.setWrittenOn(ts));
    db.patchComments().update(plc);

    checker.rebuildAndCheckChanges(id);

    setNotesMigration(true, true);
    ChangeNotes notes = notesFactory.create(db, project, id);
    assertThat(notes.getChange().getCreatedOn()).isEqualTo(origUpdated);
    assertThat(notes.getChange().getLastUpdatedOn()).isAtLeast(origUpdated);
    assertThat(notes.getPatchSets().get(new PatchSet.Id(id, 1)).getCreatedOn())
        .isEqualTo(origUpdated);
  }

  @Test
  public void createWithAutoRebuildingDisabled() throws Exception {
    ReviewDb oldDb = db;
    setNotesMigration(true, true);

    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    ChangeNotes oldNotes = notesFactory.create(db, project, id);

    // Make a ReviewDb change behind NoteDb's back.
    Change c = oldDb.changes().get(id);
    assertThat(c.getTopic()).isNull();
    String topic = name("a-topic");
    c.setTopic(topic);
    oldDb.changes().update(Collections.singleton(c));

    c = oldDb.changes().get(c.getId());
    ChangeNotes newNotes = notesFactory.createWithAutoRebuildingDisabled(c, null);
    assertThat(newNotes.getChange().getTopic()).isNotEqualTo(topic);
    assertThat(newNotes.getChange().getTopic()).isEqualTo(oldNotes.getChange().getTopic());
  }

  @Test
  public void rebuildDeletesOldDraftRefs() throws Exception {
    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    putDraft(user, id, 1, "comment", null);

    Account.Id otherAccountId = new Account.Id(user.getId().get() + 1234);
    String otherDraftRef = refsDraftComments(id, otherAccountId);

    try (Repository repo = repoManager.openRepository(allUsers);
        ObjectInserter ins = repo.newObjectInserter()) {
      ObjectId sha = ins.insert(OBJ_BLOB, "garbage data".getBytes(UTF_8));
      ins.flush();
      RefUpdate ru = repo.updateRef(otherDraftRef);
      ru.setExpectedOldObjectId(ObjectId.zeroId());
      ru.setNewObjectId(sha);
      assertThat(ru.update()).isEqualTo(RefUpdate.Result.NEW);
    }

    checker.rebuildAndCheckChanges(id);

    try (Repository repo = repoManager.openRepository(allUsers)) {
      assertThat(repo.exactRef(otherDraftRef)).isNull();
    }
  }

  @Test
  public void failWhenWritesDisabled() throws Exception {
    setNotesMigration(true, true);

    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    assertChangeUpToDate(true, id);
    assertThat(gApi.changes().id(id.get()).info().topic).isNull();

    // Turning off writes causes failure.
    setNotesMigration(false, true);
    try {
      gApi.changes().id(id.get()).topic(name("a-topic"));
      fail("Expected write to fail");
    } catch (RestApiException e) {
      assertChangesReadOnly(e);
    }

    // Update was not written.
    assertThat(gApi.changes().id(id.get()).info().topic).isNull();
    assertChangeUpToDate(true, id);
  }

  @Test
  public void rebuildWhenWritesDisabledWorksButDoesNotWrite() throws Exception {
    setNotesMigration(true, true);

    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    assertChangeUpToDate(true, id);

    // Make a ReviewDb change behind NoteDb's back and ensure it's detected.
    setNotesMigration(false, false);
    gApi.changes().id(id.get()).topic(name("a-topic"));
    setInvalidNoteDbState(id);
    assertChangeUpToDate(false, id);

    // On next NoteDb read, change is rebuilt in-memory but not stored.
    setNotesMigration(false, true);
    assertThat(gApi.changes().id(id.get()).info().topic).isEqualTo(name("a-topic"));
    assertChangeUpToDate(false, id);

    // Attempting to write directly causes failure.
    try {
      gApi.changes().id(id.get()).topic(name("other-topic"));
      fail("Expected write to fail");
    } catch (RestApiException e) {
      assertChangesReadOnly(e);
    }

    // Update was not written.
    assertThat(gApi.changes().id(id.get()).info().topic).isEqualTo(name("a-topic"));
    assertChangeUpToDate(false, id);
  }

  @Test
  public void rebuildChangeWithNoPatchSets() throws Exception {
    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    db.changes().beginTransaction(id);
    try {
      db.patchSets().delete(db.patchSets().byChange(id));
      db.commit();
    } finally {
      db.rollback();
    }

    try {
      checker.rebuildAndCheckChanges(id);
      assert_().fail("expected NoPatchSetsException");
    } catch (NoPatchSetsException e) {
      // Expected.
    }

    Change c = db.changes().get(id);
    assertThat(c.getNoteDbState()).isNull();
    checker.assertNoChangeRef(project, id);
  }

  @Test
  public void rebuildChangeWithNoEntitiesOtherThanChange() throws Exception {
    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    db.changes().beginTransaction(id);
    try {
      db.changeMessages().delete(db.changeMessages().byChange(id));
      db.patchSets().delete(db.patchSets().byChange(id));
      db.patchSetApprovals().delete(db.patchSetApprovals().byChange(id));
      db.patchComments().delete(db.patchComments().byChange(id));
      db.commit();
    } finally {
      db.rollback();
    }

    try {
      checker.rebuildAndCheckChanges(id);
      assert_().fail("expected NoPatchSetsException");
    } catch (NoPatchSetsException e) {
      // Expected.
    }

    Change c = db.changes().get(id);
    assertThat(c.getNoteDbState()).isNull();
    checker.assertNoChangeRef(project, id);
  }

  @Test
  public void rebuildEntitiesCreatedByImpersonation() throws Exception {
    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    PatchSet.Id psId = new PatchSet.Id(id, 1);
    String prefix = "/changes/" + id + "/revisions/current/";

    // For each of the entities that have a real user field, create one entity
    // without impersonation and one with.
    CommentInput ci = new CommentInput();
    ci.path = Patch.COMMIT_MSG;
    ci.side = Side.REVISION;
    ci.line = 1;
    ci.message = "comment without impersonation";
    ReviewInput ri = new ReviewInput();
    ri.label("Code-Review", -1);
    ri.message = "message without impersonation";
    ri.drafts = DraftHandling.KEEP;
    ri.comments = ImmutableMap.of(ci.path, ImmutableList.of(ci));
    userRestSession.post(prefix + "review", ri).assertOK();

    DraftInput di = new DraftInput();
    di.path = Patch.COMMIT_MSG;
    di.side = Side.REVISION;
    di.line = 1;
    di.message = "draft without impersonation";
    userRestSession.put(prefix + "drafts", di).assertCreated();

    allowRunAs();
    try {
      Header runAs = new BasicHeader("X-Gerrit-RunAs", user.id.toString());
      ci.message = "comment with impersonation";
      ri.message = "message with impersonation";
      ri.label("Code-Review", 1);
      adminRestSession.postWithHeader(prefix + "review", runAs, ri).assertOK();

      di.message = "draft with impersonation";
      adminRestSession.putWithHeader(prefix + "drafts", runAs, di).assertCreated();
    } finally {
      removeRunAs();
    }

    List<ChangeMessage> msgs =
        Ordering.natural()
            .onResultOf(ChangeMessage::getWrittenOn)
            .sortedCopy(db.changeMessages().byChange(id));
    assertThat(msgs).hasSize(3);
    assertThat(msgs.get(1).getMessage()).endsWith("message without impersonation");
    assertThat(msgs.get(1).getAuthor()).isEqualTo(user.id);
    assertThat(msgs.get(1).getRealAuthor()).isEqualTo(user.id);
    assertThat(msgs.get(2).getMessage()).endsWith("message with impersonation");
    assertThat(msgs.get(2).getAuthor()).isEqualTo(user.id);
    assertThat(msgs.get(2).getRealAuthor()).isEqualTo(admin.id);

    List<PatchSetApproval> psas = db.patchSetApprovals().byChange(id).toList();
    assertThat(psas).hasSize(1);
    assertThat(psas.get(0).getLabel()).isEqualTo("Code-Review");
    assertThat(psas.get(0).getValue()).isEqualTo(1);
    assertThat(psas.get(0).getAccountId()).isEqualTo(user.id);
    assertThat(psas.get(0).getRealAccountId()).isEqualTo(admin.id);

    Ordering<PatchLineComment> commentOrder =
        Ordering.natural().onResultOf(PatchLineComment::getWrittenOn);
    List<PatchLineComment> drafts =
        commentOrder.sortedCopy(db.patchComments().draftByPatchSetAuthor(psId, user.id));
    assertThat(drafts).hasSize(2);
    assertThat(drafts.get(0).getMessage()).isEqualTo("draft without impersonation");
    assertThat(drafts.get(0).getAuthor()).isEqualTo(user.id);
    assertThat(drafts.get(0).getRealAuthor()).isEqualTo(user.id);
    assertThat(drafts.get(1).getMessage()).isEqualTo("draft with impersonation");
    assertThat(drafts.get(1).getAuthor()).isEqualTo(user.id);
    assertThat(drafts.get(1).getRealAuthor()).isEqualTo(admin.id);

    List<PatchLineComment> pub =
        commentOrder.sortedCopy(db.patchComments().publishedByPatchSet(psId));
    assertThat(pub).hasSize(2);
    assertThat(pub.get(0).getMessage()).isEqualTo("comment without impersonation");
    assertThat(pub.get(0).getAuthor()).isEqualTo(user.id);
    assertThat(pub.get(0).getRealAuthor()).isEqualTo(user.id);
    assertThat(pub.get(1).getMessage()).isEqualTo("comment with impersonation");
    assertThat(pub.get(1).getAuthor()).isEqualTo(user.id);
    assertThat(pub.get(1).getRealAuthor()).isEqualTo(admin.id);
  }

  @Test
  public void laterEventsDependingOnEarlierPatchSetDontIntefereWithOtherPatchSets()
      throws Exception {
    PushOneCommit.Result r1 = createChange();
    ChangeData cd = r1.getChange();
    Change.Id id = cd.getId();
    amendChange(cd.change().getKey().get());
    TestTimeUtil.incrementClock(90, TimeUnit.DAYS);

    ReviewInput rin = ReviewInput.approve();
    rin.message = "Some very late message on PS1";
    gApi.changes().id(id.get()).revision(1).review(rin);

    checker.rebuildAndCheckChanges(id);
  }

  @Test
  public void ignoreChangeMessageBeyondCurrentPatchSet() throws Exception {
    PushOneCommit.Result r = createChange();
    PatchSet.Id psId1 = r.getPatchSetId();
    Change.Id id = psId1.getParentKey();
    gApi.changes().id(id.get()).current().review(ReviewInput.recommend());

    r = amendChange(r.getChangeId());
    PatchSet.Id psId2 = r.getPatchSetId();

    assertThat(db.patchSets().byChange(id)).hasSize(2);
    assertThat(db.changeMessages().byPatchSet(psId2)).hasSize(1);
    db.patchSets().deleteKeys(Collections.singleton(psId2));

    checker.rebuildAndCheckChanges(psId2.getParentKey());
    setNotesMigration(true, true);

    ChangeData cd = changeDataFactory.create(db, project, id);
    assertThat(cd.change().currentPatchSetId()).isEqualTo(psId1);
    assertThat(cd.patchSets().stream().map(PatchSet::getId).collect(toList()))
        .containsExactly(psId1);
    PatchSet ps = cd.currentPatchSet();
    assertThat(ps).isNotNull();
    assertThat(ps.getId()).isEqualTo(psId1);
  }

  @Test
  public void highestNumberedPatchSetIsNotCurrent() throws Exception {
    PushOneCommit.Result r1 = createChange();
    PatchSet.Id psId1 = r1.getPatchSetId();
    Change.Id id = psId1.getParentKey();
    PushOneCommit.Result r2 = amendChange(r1.getChangeId());
    PatchSet.Id psId2 = r2.getPatchSetId();

    try (BatchUpdate bu =
        batchUpdateFactory.create(
            db, project, identifiedUserFactory.create(user.getId()), TimeUtil.nowTs())) {
      bu.addOp(
          id,
          new BatchUpdateOp() {
            @Override
            public boolean updateChange(ChangeContext ctx)
                throws PatchSetInfoNotAvailableException {
              ctx.getChange()
                  .setCurrentPatchSet(patchSetInfoFactory.get(ctx.getDb(), ctx.getNotes(), psId1));
              return true;
            }
          });
      bu.execute();
    }
    ChangeNotes notes = notesFactory.create(db, project, id);
    assertThat(psUtil.byChangeAsMap(db, notes).keySet()).containsExactly(psId1, psId2);
    assertThat(notes.getChange().currentPatchSetId()).isEqualTo(psId1);

    assertThat(db.changes().get(id).currentPatchSetId()).isEqualTo(psId1);

    checker.rebuildAndCheckChanges(id);
    setNotesMigration(true, true);

    notes = notesFactory.create(db, project, id);
    assertThat(psUtil.byChangeAsMap(db, notes).keySet()).containsExactly(psId1, psId2);
    assertThat(notes.getChange().currentPatchSetId()).isEqualTo(psId1);
  }

  @Test
  public void resolveCommentsInheritsValueFromParentWhenUnspecified() throws Exception {
    PushOneCommit.Result r = createChange();
    Change.Id id = r.getPatchSetId().getParentKey();
    putDraft(user, id, 1, "comment", true);
    putDraft(user, id, 1, "newComment", null);

    Map<String, List<CommentInfo>> comments = gApi.changes().id(id.get()).current().drafts();
    for (List<CommentInfo> cList : comments.values()) {
      for (CommentInfo ci : cList) {
        assertThat(ci.unresolved).isTrue();
      }
    }
  }

  @Test
  public void rebuilderRespectsReadOnlyInNoteDbChangeState() throws Exception {
    TestTimeUtil.resetWithClockStep(1, SECONDS);
    PushOneCommit.Result r = createChange();
    PatchSet.Id psId1 = r.getPatchSetId();
    Change.Id id = psId1.getParentKey();

    checker.rebuildAndCheckChanges(id);
    setNotesMigration(true, true);

    ReviewDb db = getUnwrappedDb();
    Change c = db.changes().get(id);
    NoteDbChangeState state = NoteDbChangeState.parse(c);
    Timestamp until = new Timestamp(TimeUtil.nowMs() + MILLISECONDS.convert(1, DAYS));
    state = state.withReadOnlyUntil(until);
    c.setNoteDbState(state.toString());
    db.changes().update(Collections.singleton(c));

    try {
      rebuilderWrapper.rebuild(db, id);
      fail("expected rebuild to fail");
    } catch (OrmRuntimeException e) {
      assertThat(e.getMessage()).contains("read-only until");
    }

    TestTimeUtil.setClock(new Timestamp(until.getTime() + MILLISECONDS.convert(1, SECONDS)));
    rebuilderWrapper.rebuild(db, id);
  }

  @Test
  public void commitWithCrLineEndings() throws Exception {
    PushOneCommit.Result r =
        createChange("Subject\r\rBody\r", PushOneCommit.FILE_NAME, PushOneCommit.FILE_CONTENT);
    Change c = r.getChange().change();

    // This assertion demonstrates an arguable bug in JGit's commit subject
    // parsing, and shows how this kind of data might have gotten into
    // ReviewDb. If that bug ever gets fixed upstream, this assert may start
    // failing. If that happens, this test can be rewritten to directly set the
    // subject field in ReviewDb.
    assertThat(c.getSubject()).isEqualTo("Subject\r\rBody");

    checker.rebuildAndCheckChanges(c.getId());
  }

  @Test
  public void patchSetsOutOfOrder() throws Exception {
    String id = createChange().getChangeId();
    amendChange(id);
    PushOneCommit.Result r = amendChange(id);

    ChangeData cd = r.getChange();
    PatchSet.Id psId3 = cd.change().currentPatchSetId();
    assertThat(psId3.get()).isEqualTo(3);

    PatchSet ps1 = db.patchSets().get(new PatchSet.Id(cd.getId(), 1));
    PatchSet ps3 = db.patchSets().get(psId3);
    assertThat(ps1.getCreatedOn()).isLessThan(ps3.getCreatedOn());

    // Simulate an old Gerrit bug by setting the created timestamp of the latest
    // patch set ID to the timestamp of PS1.
    ps3.setCreatedOn(ps1.getCreatedOn());
    db.patchSets().update(Collections.singleton(ps3));

    checker.rebuildAndCheckChanges(cd.getId());

    setNotesMigration(true, true);
    cd = changeDataFactory.create(db, project, cd.getId());
    assertThat(cd.change().currentPatchSetId()).isEqualTo(psId3);

    List<PatchSet> patchSets = ImmutableList.copyOf(cd.patchSets());
    assertThat(patchSets).hasSize(3);

    PatchSet newPs1 = patchSets.get(0);
    assertThat(newPs1.getId()).isEqualTo(ps1.getId());
    assertThat(newPs1.getCreatedOn()).isEqualTo(ps1.getCreatedOn());

    PatchSet newPs2 = patchSets.get(1);
    assertThat(newPs2.getCreatedOn()).isGreaterThan(newPs1.getCreatedOn());

    PatchSet newPs3 = patchSets.get(2);
    assertThat(newPs3.getId()).isEqualTo(ps3.getId());
    // Migrated with a newer timestamp than the original, to preserve ordering.
    assertThat(newPs3.getCreatedOn()).isAtLeast(newPs2.getCreatedOn());
    assertThat(newPs3.getCreatedOn()).isGreaterThan(ps1.getCreatedOn());
  }

  @Test
  public void ignoreNoteDbStateWithNoCorrespondingRefWhenWritesAndReadsDisabled() throws Exception {
    PushOneCommit.Result r = createChange();
    Change.Id id = r.getChange().getId();
    ReviewDb db = getUnwrappedDb();
    Change c = db.changes().get(id);
    c.setNoteDbState("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
    db.changes().update(Collections.singleton(c));
    c = db.changes().get(id);

    String refName = RefNames.changeMetaRef(id);
    assertThat(getMetaRef(project, refName)).isNull();

    ChangeNotes notes = notesFactory.create(dbProvider.get(), project, id);
    assertThat(notes.getChange().getRowVersion()).isEqualTo(c.getRowVersion());

    notes = notesFactory.createChecked(dbProvider.get(), project, id);
    assertThat(notes.getChange().getRowVersion()).isEqualTo(c.getRowVersion());

    assertThat(getMetaRef(project, refName)).isNull();
  }

  @Test
  public void autoRebuildMissingRefWriteOnly() throws Exception {
    setNotesMigration(true, false);
    testAutoRebuildMissingRef();
  }

  @Test
  public void autoRebuildMissingRefReadWrite() throws Exception {
    setNotesMigration(true, true);
    testAutoRebuildMissingRef();
  }

  private void testAutoRebuildMissingRef() throws Exception {
    PushOneCommit.Result r = createChange();
    Change.Id id = r.getChange().getId();

    assertChangeUpToDate(true, id);
    notesFactory.createChecked(db, project, id);

    try (Repository repo = repoManager.openRepository(project)) {
      RefUpdate ru = repo.updateRef(RefNames.changeMetaRef(id));
      ru.setForceUpdate(true);
      assertThat(ru.delete()).isEqualTo(RefUpdate.Result.FORCED);
    }
    assertChangeUpToDate(false, id);

    notesFactory.createChecked(db, project, id);
    assertChangeUpToDate(true, id);
  }

  @Test
  public void missingPatchSetCommitOkForCommentsNotOnParentSide() throws Exception {
    PushOneCommit.Result r = createChange();
    Change.Id id = r.getChange().getId();

    putDraft(user, id, 1, "draft comment", null, Side.REVISION);
    putComment(user, id, 1, "published comment", null, Side.REVISION);

    ReviewDb db = getUnwrappedDb();
    PatchSet ps = db.patchSets().get(new PatchSet.Id(id, 1));
    ps.setRevision(new RevId("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));
    db.patchSets().update(Collections.singleton(ps));

    try {
      patchListCache.getOldId(db.changes().get(id), ps, null);
      assert_().fail("Expected PatchListNotAvailableException");
    } catch (PatchListNotAvailableException e) {
      // Expected.
    }

    checker.rebuildAndCheckChanges(id);
  }

  @Test
  public void missingPatchSetCommitOmitsCommentsOnParentSide() throws Exception {
    PushOneCommit.Result r = createChange();
    Change.Id id = r.getChange().getId();

    CommentInfo draftInfo = putDraft(user, id, 1, "draft comment", null, Side.PARENT);
    putComment(user, id, 1, "published comment", null, Side.PARENT);
    CommentInfo commentInfo =
        gApi.changes()
            .id(id.get())
            .comments()
            .values()
            .stream()
            .flatMap(List::stream)
            .findFirst()
            .get();

    ReviewDb db = getUnwrappedDb();
    PatchSet ps = db.patchSets().get(new PatchSet.Id(id, 1));
    ps.setRevision(new RevId("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));
    db.patchSets().update(Collections.singleton(ps));

    try {
      patchListCache.getOldId(db.changes().get(id), ps, null);
      assert_().fail("Expected PatchListNotAvailableException");
    } catch (PatchListNotAvailableException e) {
      // Expected.
    }

    checker.rebuildAndCheckChange(
        id,
        Stream.of(draftInfo.id, commentInfo.id)
            .sorted()
            .map(c -> id + ",1," + PushOneCommit.FILE_NAME + "," + c)
            .collect(
                joining(", ", "PatchLineComment.Key sets differ: [", "] only in A; [] only in B")));
  }

  private void assertChangesReadOnly(RestApiException e) throws Exception {
    Throwable cause = e.getCause();
    assertThat(cause).isInstanceOf(UpdateException.class);
    assertThat(cause.getCause()).isInstanceOf(OrmException.class);
    assertThat(cause.getCause()).hasMessageThat().isEqualTo(NoteDbUpdateManager.CHANGES_READ_ONLY);
  }

  private void setInvalidNoteDbState(Change.Id id) throws Exception {
    ReviewDb db = getUnwrappedDb();
    Change c = db.changes().get(id);
    // In reality we would have NoteDb writes enabled, which would write a real
    // state into this field. For tests however, we turn NoteDb writes off, so
    // just use a dummy state to force ChangeNotes to view the notes as
    // out-of-date.
    c.setNoteDbState("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
    db.changes().update(Collections.singleton(c));
  }

  private void assertChangeUpToDate(boolean expected, Change.Id id) throws Exception {
    try (Repository repo = repoManager.openRepository(project)) {
      Change c = getUnwrappedDb().changes().get(id);
      assertThat(c).isNotNull();
      assertThat(c.getNoteDbState()).isNotNull();
      NoteDbChangeState state = NoteDbChangeState.parse(c);
      assertThat(state).isNotNull();
      assertThat(state.getPrimaryStorage()).isEqualTo(PrimaryStorage.REVIEW_DB);
      assertThat(state.isChangeUpToDate(new RepoRefCache(repo))).isEqualTo(expected);
    }
  }

  private void assertDraftsUpToDate(boolean expected, Change.Id changeId, TestAccount account)
      throws Exception {
    try (Repository repo = repoManager.openRepository(allUsers)) {
      Change c = getUnwrappedDb().changes().get(changeId);
      assertThat(c).isNotNull();
      assertThat(c.getNoteDbState()).isNotNull();
      NoteDbChangeState state = NoteDbChangeState.parse(c);
      assertThat(state.areDraftsUpToDate(new RepoRefCache(repo), account.getId()))
          .isEqualTo(expected);
    }
  }

  private ObjectId getMetaRef(Project.NameKey p, String name) throws Exception {
    try (Repository repo = repoManager.openRepository(p)) {
      Ref ref = repo.exactRef(name);
      return ref != null ? ref.getObjectId() : null;
    }
  }

  private CommentInfo putDraft(
      TestAccount account, Change.Id id, int line, String msg, Boolean unresolved)
      throws Exception {
    return putDraft(account, id, line, msg, unresolved, Side.REVISION);
  }

  private CommentInfo putDraft(
      TestAccount account, Change.Id id, int line, String msg, Boolean unresolved, Side side)
      throws Exception {
    DraftInput in = new DraftInput();
    in.side = side;
    in.line = line;
    in.message = msg;
    in.path = PushOneCommit.FILE_NAME;
    in.unresolved = unresolved;
    AcceptanceTestRequestScope.Context old = setApiUser(account);
    try {
      return gApi.changes().id(id.get()).current().createDraft(in).get();
    } finally {
      atrScope.set(old);
    }
  }

  private void putComment(TestAccount account, Change.Id id, int line, String msg, String inReplyTo)
      throws Exception {
    putComment(account, id, line, msg, inReplyTo, Side.REVISION);
  }

  private void putComment(
      TestAccount account, Change.Id id, int line, String msg, String inReplyTo, Side side)
      throws Exception {
    CommentInput in = new CommentInput();
    in.side = side;
    in.line = line;
    in.message = msg;
    in.inReplyTo = inReplyTo;
    ReviewInput rin = new ReviewInput();
    rin.comments = new HashMap<>();
    rin.comments.put(PushOneCommit.FILE_NAME, ImmutableList.of(in));
    rin.drafts = ReviewInput.DraftHandling.KEEP;
    AcceptanceTestRequestScope.Context old = setApiUser(account);
    try {
      gApi.changes().id(id.get()).current().review(rin);
    } finally {
      atrScope.set(old);
    }
  }

  private void publishDrafts(TestAccount account, Change.Id id) throws Exception {
    ReviewInput rin = new ReviewInput();
    rin.drafts = ReviewInput.DraftHandling.PUBLISH_ALL_REVISIONS;
    AcceptanceTestRequestScope.Context old = setApiUser(account);
    try {
      gApi.changes().id(id.get()).current().review(rin);
    } finally {
      atrScope.set(old);
    }
  }

  private ChangeMessage insertMessage(
      Change.Id id, PatchSet.Id psId, Account.Id author, Timestamp ts, String message)
      throws Exception {
    ChangeMessage msg =
        new ChangeMessage(new ChangeMessage.Key(id, ChangeUtil.messageUuid()), author, ts, psId);
    msg.setMessage(message);
    db.changeMessages().insert(Collections.singleton(msg));

    Change c = db.changes().get(id);
    if (ts.compareTo(c.getLastUpdatedOn()) > 0) {
      c.setLastUpdatedOn(ts);
      db.changes().update(Collections.singleton(c));
    }

    return msg;
  }

  private ReviewDb getUnwrappedDb() {
    ReviewDb db = dbProvider.get();
    return ReviewDbUtil.unwrapDb(db);
  }

  private void allowRunAs() throws Exception {
    try (ProjectConfigUpdate u = updateProject(allProjects)) {
      Util.allow(
          u.getConfig(),
          GlobalCapability.RUN_AS,
          systemGroupBackend.getGroup(REGISTERED_USERS).getUUID());
      u.save();
    }
  }

  private void removeRunAs() throws Exception {
    try (ProjectConfigUpdate u = updateProject(allProjects)) {
      Util.remove(
          u.getConfig(),
          GlobalCapability.RUN_AS,
          systemGroupBackend.getGroup(REGISTERED_USERS).getUUID());
      u.save();
    }
  }

  private Map<String, List<CommentInfo>> getPublishedComments(Change.Id id) throws Exception {
    return gApi.changes().id(id.get()).current().comments();
  }
}
