// 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.schema;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assert_;
import static com.google.gerrit.extensions.common.testing.CommitInfoSubject.assertThat;
import static com.google.gerrit.reviewdb.client.RefNames.REFS_GROUPNAMES;

import com.google.common.collect.ImmutableList;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.extensions.common.CommitInfo;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.AccountGroupById;
import com.google.gerrit.reviewdb.client.AccountGroupByIdAud;
import com.google.gerrit.reviewdb.client.AccountGroupMember;
import com.google.gerrit.reviewdb.client.AccountGroupMemberAudit;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.AllUsersNameProvider;
import com.google.gerrit.server.group.db.AuditLogFormatter;
import com.google.gerrit.server.group.db.AuditLogReader;
import com.google.gerrit.server.group.db.GroupNameNotes;
import com.google.gerrit.server.update.RefUpdateUtil;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.gerrit.testing.GerritBaseTests;
import com.google.gerrit.testing.GitTestUtil;
import com.google.gerrit.testing.InMemoryRepositoryManager;
import com.google.gerrit.testing.TestTimeUtil;
import com.google.gwtorm.server.OrmDuplicateKeyException;
import java.sql.Timestamp;
import java.util.Optional;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class GroupRebuilderTest extends GerritBaseTests {
  private static final TimeZone TZ = TimeZone.getTimeZone("America/Los_Angeles");
  private static final String SERVER_ID = "server-id";
  private static final String SERVER_NAME = "Gerrit Server";
  private static final String SERVER_EMAIL = "noreply@gerritcodereview.com";

  private AtomicInteger idCounter;
  private AllUsersName allUsersName;
  private Repository repo;
  private GroupRebuilder rebuilder;
  private GroupBundle.Factory bundleFactory;

  @Before
  public void setUp() throws Exception {
    TestTimeUtil.resetWithClockStep(1, TimeUnit.SECONDS);
    idCounter = new AtomicInteger();
    allUsersName = new AllUsersName(AllUsersNameProvider.DEFAULT);
    repo = new InMemoryRepositoryManager().createRepository(allUsersName);
    rebuilder =
        new GroupRebuilder(
            GroupRebuilderTest.newPersonIdent(),
            allUsersName,
            // Note that the expected name/email values in tests are not necessarily realistic,
            // since they use these trivial name/email functions.
            getAuditLogFormatter());
    bundleFactory = new GroupBundle.Factory(new AuditLogReader(SERVER_ID, allUsersName));
  }

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

  @Test
  public void minimalGroupFields() throws Exception {
    AccountGroup g = newGroup("a");
    GroupBundle b = builder().group(g).build();

    rebuilder.rebuild(repo, b, null);

    assertMigratedCleanly(reload(g), b);
    ImmutableList<CommitInfo> log = log(g);
    assertThat(log).hasSize(1);
    assertCommit(log.get(0), "Create group", SERVER_NAME, SERVER_EMAIL);
    assertThat(logGroupNames()).isEmpty();
  }

  @Test
  public void allGroupFields() throws Exception {
    AccountGroup g = newGroup("a");
    g.setDescription("Description");
    g.setOwnerGroupUUID(new AccountGroup.UUID("owner"));
    g.setVisibleToAll(true);
    GroupBundle b = builder().group(g).build();

    rebuilder.rebuild(repo, b, null);

    assertMigratedCleanly(reload(g), b);
    ImmutableList<CommitInfo> log = log(g);
    assertThat(log).hasSize(1);
    assertServerCommit(log.get(0), "Create group");
  }

  @Test
  public void emptyGroupName() throws Exception {
    AccountGroup g = newGroup("");
    GroupBundle b = builder().group(g).build();

    rebuilder.rebuild(repo, b, null);

    GroupBundle noteDbBundle = reload(g);
    assertMigratedCleanly(noteDbBundle, b);
    assertThat(noteDbBundle.group().getName()).isEmpty();
  }

  @Test
  public void nullGroupDescription() throws Exception {
    AccountGroup g = newGroup("a");
    g.setDescription(null);
    assertThat(g.getDescription()).isNull();
    GroupBundle b = builder().group(g).build();

    rebuilder.rebuild(repo, b, null);

    GroupBundle noteDbBundle = reload(g);
    assertMigratedCleanly(noteDbBundle, b);
    assertThat(noteDbBundle.group().getDescription()).isNull();
  }

  @Test
  public void emptyGroupDescription() throws Exception {
    AccountGroup g = newGroup("a");
    g.setDescription("");
    assertThat(g.getDescription()).isEmpty();
    GroupBundle b = builder().group(g).build();

    rebuilder.rebuild(repo, b, null);

    GroupBundle noteDbBundle = reload(g);
    assertMigratedCleanly(noteDbBundle, b);
    assertThat(noteDbBundle.group().getDescription()).isNull();
  }

  @Test
  public void membersAndSubgroups() throws Exception {
    AccountGroup g = newGroup("a");
    GroupBundle b =
        builder()
            .group(g)
            .members(member(g, 1), member(g, 2))
            .byId(byId(g, "x"), byId(g, "y"))
            .build();

    rebuilder.rebuild(repo, b, null);

    assertMigratedCleanly(reload(g), b);
    ImmutableList<CommitInfo> log = log(g);
    assertThat(log).hasSize(2);
    assertServerCommit(log.get(0), "Create group");
    assertServerCommit(
        log.get(1),
        "Update group\n"
            + "\n"
            + "Add-group: Group x <x>\n"
            + "Add-group: Group y <y>\n"
            + "Add: Account 1 <1@server-id>\n"
            + "Add: Account 2 <2@server-id>");
  }

  @Test
  public void memberAudit() throws Exception {
    AccountGroup g = newGroup("a");
    Timestamp t1 = TimeUtil.nowTs();
    Timestamp t2 = TimeUtil.nowTs();
    Timestamp t3 = TimeUtil.nowTs();
    GroupBundle b =
        builder()
            .group(g)
            .members(member(g, 1))
            .memberAudit(addMember(g, 1, 8, t2), addAndRemoveMember(g, 2, 8, t1, 9, t3))
            .build();

    rebuilder.rebuild(repo, b, null);

    assertMigratedCleanly(reload(g), b);
    ImmutableList<CommitInfo> log = log(g);
    assertThat(log).hasSize(4);
    assertServerCommit(log.get(0), "Create group");
    assertCommit(
        log.get(1), "Update group\n\nAdd: Account 2 <2@server-id>", "Account 8", "8@server-id");
    assertCommit(
        log.get(2), "Update group\n\nAdd: Account 1 <1@server-id>", "Account 8", "8@server-id");
    assertCommit(
        log.get(3), "Update group\n\nRemove: Account 2 <2@server-id>", "Account 9", "9@server-id");
  }

  @Test
  public void memberAuditLegacyRemoved() throws Exception {
    AccountGroup g = newGroup("a");
    GroupBundle b =
        builder()
            .group(g)
            .members(member(g, 2))
            .memberAudit(
                addAndLegacyRemoveMember(g, 1, 8, TimeUtil.nowTs()),
                addMember(g, 2, 8, TimeUtil.nowTs()))
            .build();

    rebuilder.rebuild(repo, b, null);

    assertMigratedCleanly(reload(g), b);
    ImmutableList<CommitInfo> log = log(g);
    assertThat(log).hasSize(4);
    assertServerCommit(log.get(0), "Create group");
    assertCommit(
        log.get(1), "Update group\n\nAdd: Account 1 <1@server-id>", "Account 8", "8@server-id");
    assertCommit(
        log.get(2), "Update group\n\nRemove: Account 1 <1@server-id>", "Account 8", "8@server-id");
    assertCommit(
        log.get(3), "Update group\n\nAdd: Account 2 <2@server-id>", "Account 8", "8@server-id");
  }

  @Test
  public void unauditedMembershipsAddedAtEnd() throws Exception {
    AccountGroup g = newGroup("a");
    GroupBundle b =
        builder()
            .group(g)
            .members(member(g, 1), member(g, 2), member(g, 3))
            .memberAudit(addMember(g, 1, 8, TimeUtil.nowTs()))
            .build();

    rebuilder.rebuild(repo, b, null);

    assertMigratedCleanly(reload(g), b);
    ImmutableList<CommitInfo> log = log(g);
    assertThat(log).hasSize(3);
    assertServerCommit(log.get(0), "Create group");
    assertCommit(
        log.get(1), "Update group\n\nAdd: Account 1 <1@server-id>", "Account 8", "8@server-id");
    assertServerCommit(
        log.get(2), "Update group\n\nAdd: Account 2 <2@server-id>\nAdd: Account 3 <3@server-id>");
  }

  @Test
  public void byIdAudit() throws Exception {
    AccountGroup g = newGroup("a");
    Timestamp t1 = TimeUtil.nowTs();
    Timestamp t2 = TimeUtil.nowTs();
    Timestamp t3 = TimeUtil.nowTs();
    GroupBundle b =
        builder()
            .group(g)
            .byId(byId(g, "x"))
            .byIdAudit(addById(g, "x", 8, t2), addAndRemoveById(g, "y", 8, t1, 9, t3))
            .build();

    rebuilder.rebuild(repo, b, null);

    assertMigratedCleanly(reload(g), b);
    ImmutableList<CommitInfo> log = log(g);
    assertThat(log).hasSize(4);
    assertServerCommit(log.get(0), "Create group");
    assertCommit(log.get(1), "Update group\n\nAdd-group: Group y <y>", "Account 8", "8@server-id");
    assertCommit(log.get(2), "Update group\n\nAdd-group: Group x <x>", "Account 8", "8@server-id");
    assertCommit(
        log.get(3), "Update group\n\nRemove-group: Group y <y>", "Account 9", "9@server-id");
  }

  @Test
  public void unauditedByIdAddedAtEnd() throws Exception {
    AccountGroup g = newGroup("a");
    GroupBundle b =
        builder()
            .group(g)
            .byId(byId(g, "x"), byId(g, "y"), byId(g, "z"))
            .byIdAudit(addById(g, "x", 8, TimeUtil.nowTs()))
            .build();

    rebuilder.rebuild(repo, b, null);

    assertMigratedCleanly(reload(g), b);
    ImmutableList<CommitInfo> log = log(g);
    assertThat(log).hasSize(3);
    assertServerCommit(log.get(0), "Create group");
    assertCommit(log.get(1), "Update group\n\nAdd-group: Group x <x>", "Account 8", "8@server-id");
    assertServerCommit(
        log.get(2), "Update group\n\nAdd-group: Group y <y>\nAdd-group: Group z <z>");
  }

  @Test
  public void auditsAtSameTimestampBrokenDownByType() throws Exception {
    AccountGroup g = newGroup("a");
    Timestamp ts = TimeUtil.nowTs();
    int user = 8;
    GroupBundle b =
        builder()
            .group(g)
            .members(member(g, 1), member(g, 2))
            .memberAudit(
                addMember(g, 1, user, ts),
                addMember(g, 2, user, ts),
                addAndRemoveMember(g, 3, user, ts, user, ts))
            .byId(byId(g, "x"), byId(g, "y"))
            .byIdAudit(
                addById(g, "x", user, ts),
                addById(g, "y", user, ts),
                addAndRemoveById(g, "z", user, ts, user, ts))
            .build();

    rebuilder.rebuild(repo, b, null);

    assertMigratedCleanly(reload(g), b);
    ImmutableList<CommitInfo> log = log(g);
    assertThat(log).hasSize(5);
    assertServerCommit(log.get(0), "Create group");
    assertCommit(
        log.get(1),
        "Update group\n"
            + "\n"
            + "Add: Account 1 <1@server-id>\n"
            + "Add: Account 2 <2@server-id>\n"
            + "Add: Account 3 <3@server-id>",
        "Account 8",
        "8@server-id");
    assertCommit(
        log.get(2), "Update group\n\nRemove: Account 3 <3@server-id>", "Account 8", "8@server-id");
    assertCommit(
        log.get(3),
        "Update group\n"
            + "\n"
            + "Add-group: Group x <x>\n"
            + "Add-group: Group y <y>\n"
            + "Add-group: Group z <z>",
        "Account 8",
        "8@server-id");
    assertCommit(
        log.get(4), "Update group\n\nRemove-group: Group z <z>", "Account 8", "8@server-id");
  }

  @Test
  public void auditsAtSameTimestampBrokenDownByUserAndType() throws Exception {
    AccountGroup g = newGroup("a");
    Timestamp ts = TimeUtil.nowTs();
    int user1 = 8;
    int user2 = 9;

    GroupBundle b =
        builder()
            .group(g)
            .members(member(g, 1), member(g, 2), member(g, 3))
            .memberAudit(
                addMember(g, 1, user1, ts), addMember(g, 2, user2, ts), addMember(g, 3, user1, ts))
            .byId(byId(g, "x"), byId(g, "y"), byId(g, "z"))
            .byIdAudit(
                addById(g, "x", user1, ts), addById(g, "y", user2, ts), addById(g, "z", user1, ts))
            .build();

    rebuilder.rebuild(repo, b, null);

    assertMigratedCleanly(reload(g), b);
    ImmutableList<CommitInfo> log = log(g);
    assertThat(log).hasSize(5);
    assertServerCommit(log.get(0), "Create group");
    assertCommit(
        log.get(1),
        "Update group\n" + "\n" + "Add: Account 1 <1@server-id>\n" + "Add: Account 3 <3@server-id>",
        "Account 8",
        "8@server-id");
    assertCommit(
        log.get(2),
        "Update group\n\nAdd-group: Group x <x>\nAdd-group: Group z <z>",
        "Account 8",
        "8@server-id");
    assertCommit(
        log.get(3), "Update group\n\nAdd: Account 2 <2@server-id>", "Account 9", "9@server-id");
    assertCommit(log.get(4), "Update group\n\nAdd-group: Group y <y>", "Account 9", "9@server-id");
  }

  @Test
  public void fixupCommitPostDatesAllAuditEventsEvenIfAuditEventsAreInTheFuture() throws Exception {
    AccountGroup g = newGroup("a");
    IntStream.range(0, 20).forEach(i -> TimeUtil.nowTs());
    Timestamp future = TimeUtil.nowTs();
    TestTimeUtil.resetWithClockStep(1, TimeUnit.SECONDS);

    GroupBundle b =
        builder()
            .group(g)
            .byId(byId(g, "x"), byId(g, "y"), byId(g, "z"))
            .byIdAudit(addById(g, "x", 8, future))
            .build();

    rebuilder.rebuild(repo, b, null);

    assertMigratedCleanly(reload(g), b);
    ImmutableList<CommitInfo> log = log(g);
    assertThat(log).hasSize(3);
    assertServerCommit(log.get(0), "Create group");
    assertCommit(log.get(1), "Update group\n\nAdd-group: Group x <x>", "Account 8", "8@server-id");
    assertServerCommit(
        log.get(2), "Update group\n\nAdd-group: Group y <y>\nAdd-group: Group z <z>");

    assertThat(log.stream().map(c -> c.committer.date).collect(toImmutableList()))
        .named("%s", log)
        .isOrdered();
    assertThat(TimeUtil.nowTs()).isLessThan(future);
  }

  @Test
  public void redundantMemberAuditsAreIgnored() throws Exception {
    AccountGroup g = newGroup("a");
    Timestamp t1 = TimeUtil.nowTs();
    Timestamp t2 = TimeUtil.nowTs();
    Timestamp t3 = TimeUtil.nowTs();
    Timestamp t4 = TimeUtil.nowTs();
    Timestamp t5 = TimeUtil.nowTs();
    GroupBundle b =
        builder()
            .group(g)
            .members(member(g, 2))
            .memberAudit(
                addMember(g, 1, 8, t1),
                addMember(g, 1, 8, t1),
                addMember(g, 1, 8, t3),
                addMember(g, 1, 9, t4),
                addAndRemoveMember(g, 1, 8, t2, 9, t5),
                addAndLegacyRemoveMember(g, 2, 9, t3),
                addMember(g, 2, 8, t1),
                addMember(g, 2, 9, t4),
                addMember(g, 1, 8, t5))
            .build();

    rebuilder.rebuild(repo, b, null);

    assertMigratedCleanly(reload(g), b);
    ImmutableList<CommitInfo> log = log(g);
    assertThat(log).hasSize(5);
    assertServerCommit(log.get(0), "Create group");
    assertCommit(
        log.get(1),
        "Update group\n\nAdd: Account 1 <1@server-id>\nAdd: Account 2 <2@server-id>",
        "Account 8",
        "8@server-id");
    assertCommit(
        log.get(2), "Update group\n\nRemove: Account 2 <2@server-id>", "Account 9", "9@server-id");
    assertCommit(
        log.get(3), "Update group\n\nAdd: Account 2 <2@server-id>", "Account 9", "9@server-id");
    assertCommit(
        log.get(4), "Update group\n\nRemove: Account 1 <1@server-id>", "Account 9", "9@server-id");
  }

  @Test
  public void additionsAndRemovalsWithinSameSecondCanBeMigrated() throws Exception {
    TestTimeUtil.resetWithClockStep(1, TimeUnit.MILLISECONDS);
    AccountGroup g = newGroup("a");
    Timestamp t1 = TimeUtil.nowTs();
    Timestamp t2 = TimeUtil.nowTs();
    Timestamp t3 = TimeUtil.nowTs();
    Timestamp t4 = TimeUtil.nowTs();
    Timestamp t5 = TimeUtil.nowTs();
    GroupBundle b =
        builder()
            .group(g)
            .members(member(g, 1))
            .memberAudit(
                addAndLegacyRemoveMember(g, 1, 8, t1),
                addMember(g, 1, 10, t2),
                addAndRemoveMember(g, 1, 8, t3, 9, t4),
                addMember(g, 1, 8, t5))
            .build();

    rebuilder.rebuild(repo, b, null);

    assertMigratedCleanly(reload(g), b);
    ImmutableList<CommitInfo> log = log(g);
    assertThat(log).hasSize(6);
    assertServerCommit(log.get(0), "Create group");
    assertCommit(
        log.get(1), "Update group\n\nAdd: Account 1 <1@server-id>", "Account 8", "8@server-id");
    assertCommit(
        log.get(2), "Update group\n\nRemove: Account 1 <1@server-id>", "Account 8", "8@server-id");
    assertCommit(
        log.get(3), "Update group\n\nAdd: Account 1 <1@server-id>", "Account 10", "10@server-id");
    assertCommit(
        log.get(4), "Update group\n\nRemove: Account 1 <1@server-id>", "Account 9", "9@server-id");
    assertCommit(
        log.get(5), "Update group\n\nAdd: Account 1 <1@server-id>", "Account 8", "8@server-id");
  }

  @Test
  public void redundantByIdAuditsAreIgnored() throws Exception {
    AccountGroup g = newGroup("a");
    Timestamp t1 = TimeUtil.nowTs();
    Timestamp t2 = TimeUtil.nowTs();
    Timestamp t3 = TimeUtil.nowTs();
    Timestamp t4 = TimeUtil.nowTs();
    Timestamp t5 = TimeUtil.nowTs();
    GroupBundle b =
        builder()
            .group(g)
            .byId()
            .byIdAudit(
                addById(g, "x", 8, t1),
                addById(g, "x", 8, t3),
                addById(g, "x", 9, t4),
                addAndRemoveById(g, "x", 8, t2, 9, t5))
            .build();

    rebuilder.rebuild(repo, b, null);

    assertMigratedCleanly(reload(g), b);
    ImmutableList<CommitInfo> log = log(g);
    assertThat(log).hasSize(3);
    assertServerCommit(log.get(0), "Create group");
    assertCommit(log.get(1), "Update group\n\nAdd-group: Group x <x>", "Account 8", "8@server-id");
    assertCommit(
        log.get(2), "Update group\n\nRemove-group: Group x <x>", "Account 9", "9@server-id");
  }

  @Test
  public void combineWithBatchGroupNameNotes() throws Exception {
    AccountGroup g1 = newGroup("a");
    AccountGroup g2 = newGroup("b");
    GroupReference gr1 = new GroupReference(g1.getGroupUUID(), g1.getName());
    GroupReference gr2 = new GroupReference(g2.getGroupUUID(), g2.getName());

    GroupBundle b1 = builder().group(g1).build();
    GroupBundle b2 = builder().group(g2).build();

    BatchRefUpdate bru = repo.getRefDatabase().newBatchUpdate();

    rebuilder.rebuild(repo, b1, bru);
    rebuilder.rebuild(repo, b2, bru);
    try (ObjectInserter inserter = repo.newObjectInserter()) {
      ImmutableList<GroupReference> refs = ImmutableList.of(gr1, gr2);
      GroupNameNotes.updateAllGroups(repo, inserter, bru, refs, newPersonIdent());
      inserter.flush();
    }

    assertThat(log(g1)).isEmpty();
    assertThat(log(g2)).isEmpty();
    assertThat(logGroupNames()).isEmpty();

    RefUpdateUtil.executeChecked(bru, repo);

    assertThat(log(g1)).hasSize(1);
    assertThat(log(g2)).hasSize(1);
    assertThat(logGroupNames()).hasSize(1);
    assertMigratedCleanly(reload(g1), b1);
    assertMigratedCleanly(reload(g2), b2);

    assertThat(GroupNameNotes.loadAllGroups(repo)).containsExactly(gr1, gr2);
  }

  @Test
  public void groupNamesWithLeadingAndTrailingWhitespace() throws Exception {
    for (String leading : ImmutableList.of("", " ", "  ")) {
      for (String trailing : ImmutableList.of("", " ", "  ")) {
        AccountGroup g = newGroup(leading + "a" + trailing);
        GroupBundle b = builder().group(g).build();
        rebuilder.rebuild(repo, b, null);
        assertMigratedCleanly(reload(g), b);
      }
    }
  }

  @Test
  public void disallowExisting() throws Exception {
    AccountGroup g = newGroup("a");
    GroupBundle b = builder().group(g).build();

    rebuilder.rebuild(repo, b, null);
    assertMigratedCleanly(reload(g), b);
    String refName = RefNames.refsGroups(g.getGroupUUID());
    ObjectId oldId = repo.exactRef(refName).getObjectId();

    try {
      rebuilder.rebuild(repo, b, null);
      assert_().fail("expected OrmDuplicateKeyException");
    } catch (OrmDuplicateKeyException e) {
      // Expected.
    }

    assertThat(repo.exactRef(refName).getObjectId()).isEqualTo(oldId);
  }

  private GroupBundle reload(AccountGroup g) throws Exception {
    return bundleFactory.fromNoteDb(allUsersName, repo, g.getGroupUUID());
  }

  private void assertMigratedCleanly(GroupBundle noteDbBundle, GroupBundle expectedReviewDbBundle) {
    assertThat(GroupBundle.compareWithAudits(expectedReviewDbBundle, noteDbBundle)).isEmpty();
  }

  private AccountGroup newGroup(String name) {
    int id = idCounter.incrementAndGet();
    return new AccountGroup(
        new AccountGroup.NameKey(name),
        new AccountGroup.Id(id),
        new AccountGroup.UUID(name.trim() + "-" + id),
        TimeUtil.nowTs());
  }

  private AccountGroupMember member(AccountGroup g, int accountId) {
    return new AccountGroupMember(new AccountGroupMember.Key(new Account.Id(accountId), g.getId()));
  }

  private AccountGroupMemberAudit addMember(
      AccountGroup g, int accountId, int adder, Timestamp addedOn) {
    return new AccountGroupMemberAudit(member(g, accountId), new Account.Id(adder), addedOn);
  }

  private AccountGroupMemberAudit addAndLegacyRemoveMember(
      AccountGroup g, int accountId, int adder, Timestamp addedOn) {
    AccountGroupMemberAudit a = addMember(g, accountId, adder, addedOn);
    a.removedLegacy();
    return a;
  }

  private AccountGroupMemberAudit addAndRemoveMember(
      AccountGroup g,
      int accountId,
      int adder,
      Timestamp addedOn,
      int removedBy,
      Timestamp removedOn) {
    AccountGroupMemberAudit a = addMember(g, accountId, adder, addedOn);
    a.removed(new Account.Id(removedBy), removedOn);
    return a;
  }

  private AccountGroupByIdAud addById(
      AccountGroup g, String subgroupUuid, int adder, Timestamp addedOn) {
    return new AccountGroupByIdAud(byId(g, subgroupUuid), new Account.Id(adder), addedOn);
  }

  private AccountGroupByIdAud addAndRemoveById(
      AccountGroup g,
      String subgroupUuid,
      int adder,
      Timestamp addedOn,
      int removedBy,
      Timestamp removedOn) {
    AccountGroupByIdAud a = addById(g, subgroupUuid, adder, addedOn);
    a.removed(new Account.Id(removedBy), removedOn);
    return a;
  }

  private AccountGroupById byId(AccountGroup g, String subgroupUuid) {
    return new AccountGroupById(
        new AccountGroupById.Key(g.getId(), new AccountGroup.UUID(subgroupUuid)));
  }

  private ImmutableList<CommitInfo> log(AccountGroup g) throws Exception {
    return GitTestUtil.log(repo, RefNames.refsGroups(g.getGroupUUID()));
  }

  private ImmutableList<CommitInfo> logGroupNames() throws Exception {
    return GitTestUtil.log(repo, REFS_GROUPNAMES);
  }

  private static GroupBundle.Builder builder() {
    return GroupBundle.builder().source(GroupBundle.Source.REVIEW_DB);
  }

  private static PersonIdent newPersonIdent() {
    return new PersonIdent(SERVER_NAME, SERVER_EMAIL, TimeUtil.nowTs(), TZ);
  }

  private static void assertServerCommit(CommitInfo commitInfo, String expectedMessage) {
    assertCommit(commitInfo, expectedMessage, SERVER_NAME, SERVER_EMAIL);
  }

  private static void assertCommit(
      CommitInfo commitInfo, String expectedMessage, String expectedName, String expectedEmail) {
    assertThat(commitInfo).message().isEqualTo(expectedMessage);
    assertThat(commitInfo).author().name().isEqualTo(expectedName);
    assertThat(commitInfo).author().email().isEqualTo(expectedEmail);

    // Committer should always be the server, regardless of author.
    assertThat(commitInfo).committer().name().isEqualTo(SERVER_NAME);
    assertThat(commitInfo).committer().email().isEqualTo(SERVER_EMAIL);
    assertThat(commitInfo).committer().date().isEqualTo(commitInfo.author.date);
    assertThat(commitInfo).committer().tz().isEqualTo(commitInfo.author.tz);
  }

  private static AuditLogFormatter getAuditLogFormatter() {
    return AuditLogFormatter.create(
        GroupRebuilderTest::getAccount, GroupRebuilderTest::getGroup, SERVER_ID);
  }

  private static Optional<Account> getAccount(Account.Id id) {
    Account account = new Account(id, TimeUtil.nowTs());
    account.setFullName("Account " + id);
    return Optional.of(account);
  }

  private static Optional<GroupDescription.Basic> getGroup(AccountGroup.UUID uuid) {
    GroupDescription.Basic group =
        new GroupDescription.Basic() {
          @Override
          public AccountGroup.UUID getGroupUUID() {
            return uuid;
          }

          @Override
          public String getName() {
            return "Group " + uuid;
          }

          @Nullable
          @Override
          public String getEmailAddress() {
            return null;
          }

          @Nullable
          @Override
          public String getUrl() {
            return null;
          }
        };
    return Optional.of(group);
  }
}
