// 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.google.gerrit.server.notedb;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static com.google.common.truth.Truth.assertThat;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimaps;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Comment;
import com.google.gerrit.reviewdb.client.PatchLineComment.Status;
import com.google.gerrit.reviewdb.client.PatchSet;
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.server.CommentsUtil;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.notedb.CommentJsonMigrator.ProjectMigrationResult;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.gerrit.testing.TestChanges;
import com.google.inject.Inject;
import java.io.ByteArrayOutputStream;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.notes.NoteMap;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevSort;
import org.eclipse.jgit.revwalk.RevWalk;
import org.junit.Before;
import org.junit.Test;

public class CommentJsonMigratorTest extends AbstractChangeNotesTest {
  private CommentJsonMigrator migrator;
  @Inject private ChangeNoteUtil noteUtil;
  @Inject private CommentsUtil commentsUtil;
  @Inject private LegacyChangeNoteWrite legacyChangeNoteWrite;
  @Inject private AllUsersName allUsersName;

  private AtomicInteger uuidCounter;

  @Before
  public void setUpCounter() {
    uuidCounter = new AtomicInteger();
    migrator = new CommentJsonMigrator(new ChangeNoteJson(), "gerrit", allUsersName);
  }

  @Test
  public void noOpIfAllCommentsAreJson() throws Exception {
    Change c = newChange();
    incrementPatchSet(c);

    ChangeNotes notes = newNotes(c);
    ChangeUpdate update = newUpdate(c, changeOwner);
    Comment ps1Comment = newComment(notes, 1, "comment on ps1");
    update.putComment(Status.PUBLISHED, ps1Comment);
    update.commit();

    notes = newNotes(c);
    update = newUpdate(c, changeOwner);
    Comment ps2Comment = newComment(notes, 2, "comment on ps2");
    update.putComment(Status.PUBLISHED, ps2Comment);
    update.commit();

    notes = newNotes(c);
    assertThat(getToStringRepresentations(notes.getComments()))
        .containsExactly(
            getRevId(notes, 1), ps1Comment.toString(),
            getRevId(notes, 2), ps2Comment.toString());

    ChangeNotes oldNotes = notes;
    checkMigrate(project, ImmutableList.of());
    assertNoDifferences(notes, oldNotes);
    assertThat(notes.getMetaId()).isEqualTo(oldNotes.getMetaId());
  }

  @Test
  public void migratePublishedComments() throws Exception {
    Change c = newChange();
    incrementPatchSet(c);

    ChangeNotes notes = newNotes(c);

    Comment ps1Comment1 = newComment(notes, 1, "first comment on ps1");
    Comment ps2Comment1 = newComment(notes, 2, "first comment on ps2");
    Comment ps1Comment2 = newComment(notes, 1, "second comment on ps1");

    // Construct legacy format 'by hand'.
    ByteArrayOutputStream out1 = new ByteArrayOutputStream(0);
    legacyChangeNoteWrite.buildNote(
        ImmutableListMultimap.<Integer, Comment>builder().put(1, ps1Comment1).build(), out1);

    ByteArrayOutputStream out2 = new ByteArrayOutputStream(0);
    legacyChangeNoteWrite.buildNote(
        ImmutableListMultimap.<Integer, Comment>builder().put(2, ps2Comment1).build(), out2);

    ByteArrayOutputStream out3 = new ByteArrayOutputStream(0);
    legacyChangeNoteWrite.buildNote(
        ImmutableListMultimap.<Integer, Comment>builder()
            .put(1, ps1Comment2)
            .put(1, ps1Comment1)
            .build(),
        out3);

    TestRepository<Repository> testRepository = new TestRepository<>(repo, rw);

    String metaRefName = RefNames.changeMetaRef(c.getId());
    testRepository
        .branch(metaRefName)
        .commit()
        .message("Review ps 1\n\nPatch-set: 1")
        .add(ps1Comment1.revId, out1.toString())
        .author(serverIdent)
        .committer(serverIdent)
        .create();

    testRepository
        .branch(metaRefName)
        .commit()
        .message("Review ps 2\n\nPatch-set: 2")
        .add(ps2Comment1.revId, out2.toString())
        .add(ps1Comment1.revId, out3.toString())
        .author(serverIdent)
        .committer(serverIdent)
        .create();

    notes = newNotes(c);
    assertThat(getToStringRepresentations(notes.getComments()))
        .containsExactly(
            getRevId(notes, 1), ps1Comment1.toString(),
            getRevId(notes, 1), ps1Comment2.toString(),
            getRevId(notes, 2), ps2Comment1.toString());

    // Comments at each commit all have legacy format.
    ImmutableList<RevCommit> oldLog = log(project, RefNames.changeMetaRef(c.getId()));
    assertThat(oldLog).hasSize(4);
    assertThat(getLegacyFormatMapForPublishedComments(notes, oldLog.get(0))).isEmpty();
    assertThat(getLegacyFormatMapForPublishedComments(notes, oldLog.get(1))).isEmpty();
    assertThat(getLegacyFormatMapForPublishedComments(notes, oldLog.get(2)))
        .containsExactly(ps1Comment1.key, true);
    assertThat(getLegacyFormatMapForPublishedComments(notes, oldLog.get(3)))
        .containsExactly(ps1Comment1.key, true, ps1Comment2.key, true, ps2Comment1.key, true);

    // Check that dryRun doesn't touch anything.
    String refName = RefNames.changeMetaRef(c.getId());
    ObjectId before = repo.getRefDatabase().getRef(refName).getObjectId();
    ProjectMigrationResult dryRunResult = migrator.migrateProject(project, repo, true);
    ObjectId after = repo.getRefDatabase().getRef(refName).getObjectId();
    assertThat(before).isEqualTo(after);
    assertThat(dryRunResult.refsUpdated).isEqualTo(ImmutableList.of(refName));

    ChangeNotes oldNotes = notes;
    checkMigrate(project, ImmutableList.of(refName));

    // Comment content is the same.
    notes = newNotes(c);
    assertNoDifferences(notes, oldNotes);
    assertThat(getToStringRepresentations(notes.getComments()))
        .containsExactly(
            getRevId(notes, 1), ps1Comment1.toString(),
            getRevId(notes, 1), ps1Comment2.toString(),
            getRevId(notes, 2), ps2Comment1.toString());

    // Comments at each commit all have JSON format.
    ImmutableList<RevCommit> newLog = log(project, RefNames.changeMetaRef(c.getId()));
    assertThat(getLegacyFormatMapForPublishedComments(notes, newLog.get(0))).isEmpty();
    assertThat(getLegacyFormatMapForPublishedComments(notes, newLog.get(1))).isEmpty();
    assertThat(getLegacyFormatMapForPublishedComments(notes, newLog.get(2)))
        .containsExactly(ps1Comment1.key, false);
    assertThat(getLegacyFormatMapForPublishedComments(notes, newLog.get(3)))
        .containsExactly(ps1Comment1.key, false, ps1Comment2.key, false, ps2Comment1.key, false);
  }

  @Test
  public void migrateDraftComments() throws Exception {
    Change c = newChange();
    incrementPatchSet(c);

    ChangeNotes notes = newNotes(c);
    ObjectId origMetaId = notes.getMetaId();

    Comment ownerCommentPs1 = newComment(notes, 1, "owner comment on ps1", changeOwner);
    Comment ownerCommentPs2 = newComment(notes, 2, "owner comment on ps2", changeOwner);
    Comment otherCommentPs1 = newComment(notes, 1, "other user comment on ps1", otherUser);

    ByteArrayOutputStream out1 = new ByteArrayOutputStream(0);
    legacyChangeNoteWrite.buildNote(
        ImmutableListMultimap.<Integer, Comment>builder().put(1, ownerCommentPs1).build(), out1);

    ByteArrayOutputStream out2 = new ByteArrayOutputStream(0);
    legacyChangeNoteWrite.buildNote(
        ImmutableListMultimap.<Integer, Comment>builder().put(2, ownerCommentPs2).build(), out2);

    ByteArrayOutputStream out3 = new ByteArrayOutputStream(0);
    legacyChangeNoteWrite.buildNote(
        ImmutableListMultimap.<Integer, Comment>builder().put(1, otherCommentPs1).build(), out3);

    try (Repository allUsersRepo = repoManager.openRepository(allUsers);
        RevWalk allUsersRw = new RevWalk(allUsersRepo)) {
      TestRepository<Repository> testRepository = new TestRepository<>(allUsersRepo, allUsersRw);

      testRepository
          .branch(RefNames.refsDraftComments(c.getId(), changeOwner.getAccountId()))
          .commit()
          .message("Review ps 1\n\nPatch-set: 1")
          .add(ownerCommentPs1.revId, out1.toString())
          .author(serverIdent)
          .committer(serverIdent)
          .create();

      testRepository
          .branch(RefNames.refsDraftComments(c.getId(), changeOwner.getAccountId()))
          .commit()
          .message("Review ps 1\n\nPatch-set: 2")
          .add(ownerCommentPs2.revId, out2.toString())
          .author(serverIdent)
          .committer(serverIdent)
          .create();

      testRepository
          .branch(RefNames.refsDraftComments(c.getId(), otherUser.getAccountId()))
          .commit()
          .message("Review ps 2\n\nPatch-set: 2")
          .add(otherCommentPs1.revId, out3.toString())
          .author(serverIdent)
          .committer(serverIdent)
          .create();
    }

    notes = newNotes(c);
    assertThat(getToStringRepresentations(notes.getDraftComments(changeOwner.getAccountId())))
        .containsExactly(
            getRevId(notes, 1), ownerCommentPs1.toString(),
            getRevId(notes, 2), ownerCommentPs2.toString());
    assertThat(getToStringRepresentations(notes.getDraftComments(otherUser.getAccountId())))
        .containsExactly(getRevId(notes, 1), otherCommentPs1.toString());

    // Comments at each commit all have legacy format.
    ImmutableList<RevCommit> oldOwnerLog =
        log(allUsers, RefNames.refsDraftComments(c.getId(), changeOwner.getAccountId()));
    assertThat(oldOwnerLog).hasSize(2);
    assertThat(getLegacyFormatMapForDraftComments(notes, oldOwnerLog.get(0)))
        .containsExactly(ownerCommentPs1.key, true);
    assertThat(getLegacyFormatMapForDraftComments(notes, oldOwnerLog.get(1)))
        .containsExactly(ownerCommentPs1.key, true, ownerCommentPs2.key, true);

    ImmutableList<RevCommit> oldOtherLog =
        log(allUsers, RefNames.refsDraftComments(c.getId(), otherUser.getAccountId()));
    assertThat(oldOtherLog).hasSize(1);
    assertThat(getLegacyFormatMapForDraftComments(notes, oldOtherLog.get(0)))
        .containsExactly(otherCommentPs1.key, true);

    ChangeNotes oldNotes = notes;
    checkMigrate(
        allUsers,
        ImmutableList.of(
            RefNames.refsDraftComments(c.getId(), changeOwner.getAccountId()),
            RefNames.refsDraftComments(c.getId(), otherUser.getAccountId())));
    assertNoDifferences(notes, oldNotes);

    // Migration doesn't touch change ref.
    assertThat(repo.exactRef(RefNames.changeMetaRef(c.getId())).getObjectId())
        .isEqualTo(origMetaId);

    // Comment content is the same.
    notes = newNotes(c);
    assertThat(getToStringRepresentations(notes.getDraftComments(changeOwner.getAccountId())))
        .containsExactly(
            getRevId(notes, 1), ownerCommentPs1.toString(),
            getRevId(notes, 2), ownerCommentPs2.toString());
    assertThat(getToStringRepresentations(notes.getDraftComments(otherUser.getAccountId())))
        .containsExactly(getRevId(notes, 1), otherCommentPs1.toString());

    // Comments at each commit all have JSON format.
    ImmutableList<RevCommit> newOwnerLog =
        log(allUsers, RefNames.refsDraftComments(c.getId(), changeOwner.getAccountId()));
    assertThat(getLegacyFormatMapForDraftComments(notes, newOwnerLog.get(0)))
        .containsExactly(ownerCommentPs1.key, false);
    assertThat(getLegacyFormatMapForDraftComments(notes, newOwnerLog.get(1)))
        .containsExactly(ownerCommentPs1.key, false, ownerCommentPs2.key, false);

    ImmutableList<RevCommit> newOtherLog =
        log(allUsers, RefNames.refsDraftComments(c.getId(), otherUser.getAccountId()));
    assertThat(getLegacyFormatMapForDraftComments(notes, newOtherLog.get(0)))
        .containsExactly(otherCommentPs1.key, false);
  }

  @Test
  public void migrateMixOfJsonAndLegacyComments() throws Exception {
    // 3 comments: legacy, JSON, legacy. Because adding a comment necessarily rewrites the entire
    // note, these comments need to be on separate patch sets.
    Change c = newChange();
    incrementPatchSet(c);
    incrementPatchSet(c);

    ChangeNotes notes = newNotes(c);

    Comment ps1Comment = newComment(notes, 1, "comment on ps1 (legacy)");

    ByteArrayOutputStream out1 = new ByteArrayOutputStream(0);
    legacyChangeNoteWrite.buildNote(
        ImmutableListMultimap.<Integer, Comment>builder().put(1, ps1Comment).build(), out1);

    TestRepository<Repository> testRepository = new TestRepository<>(repo, rw);

    String metaRefName = RefNames.changeMetaRef(c.getId());
    testRepository
        .branch(metaRefName)
        .commit()
        .message("Review ps 1\n\nPatch-set: 1")
        .add(ps1Comment.revId, out1.toString())
        .author(serverIdent)
        .committer(serverIdent)
        .create();

    notes = newNotes(c);
    ChangeUpdate update = newUpdate(c, changeOwner);
    Comment ps2Comment = newComment(notes, 2, "comment on ps2 (JSON)");
    update.putComment(Status.PUBLISHED, ps2Comment);
    update.commit();

    Comment ps3Comment = newComment(notes, 3, "comment on ps3 (legacy)");
    ByteArrayOutputStream out3 = new ByteArrayOutputStream(0);
    legacyChangeNoteWrite.buildNote(
        ImmutableListMultimap.<Integer, Comment>builder().put(3, ps3Comment).build(), out3);

    testRepository
        .branch(metaRefName)
        .commit()
        .message("Review ps 3\n\nPatch-set: 3")
        .add(ps3Comment.revId, out3.toString())
        .author(serverIdent)
        .committer(serverIdent)
        .create();

    notes = newNotes(c);
    assertThat(getToStringRepresentations(notes.getComments()))
        .containsExactly(
            getRevId(notes, 1), ps1Comment.toString(),
            getRevId(notes, 2), ps2Comment.toString(),
            getRevId(notes, 3), ps3Comment.toString());

    // Comments at each commit match expected format.
    ImmutableList<RevCommit> oldLog = log(project, RefNames.changeMetaRef(c.getId()));
    assertThat(oldLog).hasSize(6);
    assertThat(getLegacyFormatMapForPublishedComments(notes, oldLog.get(0))).isEmpty();
    assertThat(getLegacyFormatMapForPublishedComments(notes, oldLog.get(1))).isEmpty();
    assertThat(getLegacyFormatMapForPublishedComments(notes, oldLog.get(2))).isEmpty();
    assertThat(getLegacyFormatMapForPublishedComments(notes, oldLog.get(3)))
        .containsExactly(ps1Comment.key, true);
    assertThat(getLegacyFormatMapForPublishedComments(notes, oldLog.get(4)))
        .containsExactly(ps1Comment.key, true, ps2Comment.key, false);
    assertThat(getLegacyFormatMapForPublishedComments(notes, oldLog.get(5)))
        .containsExactly(ps1Comment.key, true, ps2Comment.key, false, ps3Comment.key, true);

    ChangeNotes oldNotes = notes;
    checkMigrate(project, ImmutableList.of(RefNames.changeMetaRef(c.getId())));
    assertNoDifferences(notes, oldNotes);

    // Comment content is the same.
    notes = newNotes(c);
    assertThat(getToStringRepresentations(notes.getComments()))
        .containsExactly(
            getRevId(notes, 1), ps1Comment.toString(),
            getRevId(notes, 2), ps2Comment.toString(),
            getRevId(notes, 3), ps3Comment.toString());

    // Comments at each commit all have JSON format.
    ImmutableList<RevCommit> newLog = log(project, RefNames.changeMetaRef(c.getId()));
    assertThat(getLegacyFormatMapForPublishedComments(notes, newLog.get(0))).isEmpty();
    assertThat(getLegacyFormatMapForPublishedComments(notes, newLog.get(1))).isEmpty();
    assertThat(getLegacyFormatMapForPublishedComments(notes, newLog.get(2))).isEmpty();
    assertThat(getLegacyFormatMapForPublishedComments(notes, newLog.get(3)))
        .containsExactly(ps1Comment.key, false);
    assertThat(getLegacyFormatMapForPublishedComments(notes, newLog.get(4)))
        .containsExactly(ps1Comment.key, false, ps2Comment.key, false);
    assertThat(getLegacyFormatMapForPublishedComments(notes, newLog.get(5)))
        .containsExactly(ps1Comment.key, false, ps2Comment.key, false, ps3Comment.key, false);
  }

  private void checkMigrate(Project.NameKey project, List<String> expectedRefs) throws Exception {
    try (Repository repo = repoManager.openRepository(project)) {
      ProjectMigrationResult progress = migrator.migrateProject(project, repo, false);

      assertThat(progress.ok).isTrue();
      assertThat(progress.refsUpdated).isEqualTo(expectedRefs);
    }
  }

  private Comment newComment(ChangeNotes notes, int psNum, String message) {
    return newComment(notes, psNum, message, changeOwner);
  }

  private Comment newComment(
      ChangeNotes notes, int psNum, String message, IdentifiedUser commenter) {
    return newComment(
        new PatchSet.Id(notes.getChangeId(), psNum),
        "filename",
        "uuid-" + uuidCounter.getAndIncrement(),
        null,
        0,
        commenter,
        null,
        TimeUtil.nowTs(),
        message,
        (short) 1,
        getRevId(notes, psNum).get(),
        false);
  }

  private void incrementPatchSet(Change c) throws Exception {
    TestChanges.incrementPatchSet(c);
    RevCommit commit = tr.commit().message("PS" + c.currentPatchSetId().get()).create();
    ChangeUpdate update = newUpdate(c, changeOwner);
    update.setCommit(rw, commit);
    update.commit();
  }

  private static RevId getRevId(ChangeNotes notes, int psNum) {
    PatchSet.Id psId = new PatchSet.Id(notes.getChangeId(), psNum);
    PatchSet ps = notes.getPatchSets().get(psId);
    checkArgument(ps != null, "no patch set %s: %s", psNum, notes.getPatchSets());
    return ps.getRevision();
  }

  private static ListMultimap<RevId, String> getToStringRepresentations(
      ListMultimap<RevId, Comment> comments) {
    // Use string representation for equality comparison in this test, because Comment#equals only
    // compares keys.
    return Multimaps.transformValues(comments, Comment::toString);
  }

  private ImmutableMap<Comment.Key, Boolean> getLegacyFormatMapForPublishedComments(
      ChangeNotes notes, ObjectId metaId) throws Exception {
    return getLegacyFormatMap(project, notes.getChangeId(), metaId, Status.PUBLISHED);
  }

  private ImmutableMap<Comment.Key, Boolean> getLegacyFormatMapForDraftComments(
      ChangeNotes notes, ObjectId metaId) throws Exception {
    return getLegacyFormatMap(allUsers, notes.getChangeId(), metaId, Status.DRAFT);
  }

  private ImmutableMap<Comment.Key, Boolean> getLegacyFormatMap(
      Project.NameKey project, Change.Id changeId, ObjectId metaId, Status status)
      throws Exception {
    try (Repository repo = repoManager.openRepository(project);
        ObjectReader reader = repo.newObjectReader();
        RevWalk rw = new RevWalk(reader)) {
      NoteMap noteMap = NoteMap.read(reader, rw.parseCommit(metaId));
      RevisionNoteMap<ChangeRevisionNote> revNoteMap =
          RevisionNoteMap.parse(
              noteUtil.getChangeNoteJson(),
              noteUtil.getLegacyChangeNoteRead(),
              changeId,
              reader,
              noteMap,
              status);
      return revNoteMap.revisionNotes.values().stream()
          .flatMap(crn -> crn.getEntities().stream())
          .collect(toImmutableMap(c -> c.key, c -> c.legacyFormat));
    }
  }

  private ImmutableList<RevCommit> log(Project.NameKey project, String refName) throws Exception {
    try (Repository repo = repoManager.openRepository(project)) {
      return log(repo, refName);
    }
  }

  private ImmutableList<RevCommit> log(Repository repo, String refName) throws Exception {
    try (RevWalk rw = new RevWalk(repo)) {
      rw.sort(RevSort.TOPO);
      rw.sort(RevSort.REVERSE);
      Ref ref = repo.exactRef(refName);
      if (ref == null) {
        return ImmutableList.of();
      }
      rw.markStart(rw.parseCommit(ref.getObjectId()));
      return ImmutableList.copyOf(rw);
    }
  }

  private ImmutableListMultimap<String, RevCommit> logAll(
      Project.NameKey project, Collection<Ref> refs) throws Exception {
    ImmutableListMultimap.Builder<String, RevCommit> logs = ImmutableListMultimap.builder();
    try (Repository repo = repoManager.openRepository(project)) {
      for (Ref r : refs) {
        logs.putAll(r.getName(), log(repo, r.getName()));
      }
    }
    return logs.build();
  }

  private static void assertLogEqualExceptTrees(
      ImmutableList<RevCommit> actualLog, ImmutableList<RevCommit> expectedLog) {
    assertThat(actualLog).hasSize(expectedLog.size());
    for (int i = 0; i < expectedLog.size(); i++) {
      RevCommit actual = actualLog.get(i);
      RevCommit expected = expectedLog.get(i);
      assertThat(actual.getAuthorIdent())
          .named("author of entry %s", i)
          .isEqualTo(expected.getAuthorIdent());
      assertThat(actual.getCommitterIdent())
          .named("committer of entry %s", i)
          .isEqualTo(expected.getCommitterIdent());
      assertThat(actual.getFullMessage()).named("message of entry %s", i).isNotNull();
      assertThat(actual.getFullMessage())
          .named("message of entry %s", i)
          .isEqualTo(expected.getFullMessage());
    }
  }

  private void assertNoDifferences(ChangeNotes actual, ChangeNotes expected) throws Exception {
    checkArgument(
        actual.getChangeId().equals(expected.getChangeId()),
        "must be same change: %s != %s",
        actual.getChangeId(),
        expected.getChangeId());

    // Parsed comment representations are equal.
    // TODO(dborowitz): Comparing collections directly would be much easier, but Comment doesn't
    // have a proper equals; switch to that when the issues with
    // https://gerrit-review.googlesource.com/c/gerrit/+/207013 are resolved.
    assertCommentsEqual(commentsUtil.draftByChange(actual), commentsUtil.draftByChange(expected));
    assertCommentsEqual(
        commentsUtil.publishedByChange(actual), commentsUtil.publishedByChange(expected));

    // Change metadata is equal.
    assertLogEqualExceptTrees(
        log(project, actual.getRefName()), log(project, expected.getRefName()));

    // Logs of all draft refs are equal.
    ImmutableListMultimap<String, RevCommit> actualDraftLogs =
        logAll(allUsersName, commentsUtil.getDraftRefs(actual.getChangeId()));
    ImmutableListMultimap<String, RevCommit> expectedDraftLogs =
        logAll(allUsersName, commentsUtil.getDraftRefs(expected.getChangeId()));
    assertThat(actualDraftLogs.keySet())
        .named("draft ref names")
        .containsExactlyElementsIn(expectedDraftLogs.keySet());
    for (String refName : actualDraftLogs.keySet()) {
      assertLogEqualExceptTrees(actualDraftLogs.get(refName), actualDraftLogs.get(refName));
    }
  }

  private static void assertCommentsEqual(List<Comment> actualList, List<Comment> expectedList) {
    ImmutableMap<Comment.Key, Comment> actualMap = byKey(actualList);
    ImmutableMap<Comment.Key, Comment> expectedMap = byKey(expectedList);
    assertThat(actualMap.keySet()).isEqualTo(expectedMap.keySet());
    for (Comment.Key key : actualMap.keySet()) {
      Comment actual = actualMap.get(key);
      Comment expected = expectedMap.get(key);
      assertThat(actual.key).isEqualTo(expected.key);
      assertThat(actual.lineNbr).isEqualTo(expected.lineNbr);
      assertThat(actual.author).isEqualTo(expected.author);
      assertThat(actual.getRealAuthor()).isEqualTo(expected.getRealAuthor());
      assertThat(actual.writtenOn).isEqualTo(expected.writtenOn);
      assertThat(actual.side).isEqualTo(expected.side);
      assertThat(actual.message).isEqualTo(expected.message);
      assertThat(actual.parentUuid).isEqualTo(expected.parentUuid);
      assertThat(actual.range).isEqualTo(expected.range);
      assertThat(actual.tag).isEqualTo(expected.tag);
      assertThat(actual.revId).isEqualTo(expected.revId);
      assertThat(actual.serverId).isEqualTo(expected.serverId);
      assertThat(actual.unresolved).isEqualTo(expected.unresolved);
    }
  }

  private static ImmutableMap<Comment.Key, Comment> byKey(List<Comment> comments) {
    return comments.stream().collect(toImmutableMap(c -> c.key, c -> c));
  }
}
