// 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.group.db;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.gerrit.server.group.testing.InternalGroupSubject.internalGroups;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static com.google.gerrit.truth.OptionalSubject.assertThat;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.MatcherAssert.assertThat;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.GroupDescription;
import com.google.gerrit.entities.InternalGroup;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.group.testing.InternalGroupSubject;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.gerrit.truth.OptionalSubject;
import java.io.IOException;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneId;
import java.util.Optional;
import java.util.TimeZone;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.junit.Before;
import org.junit.Test;

public class GroupConfigTest {
  private Project.NameKey projectName;
  private Repository repository;
  private TestRepository<?> testRepository;
  private final AccountGroup.UUID groupUuid = AccountGroup.uuid("users-XYZ");
  private final AccountGroup.NameKey groupName = AccountGroup.nameKey("users");
  private final AccountGroup.Id groupId = AccountGroup.id(123);
  private final AuditLogFormatter auditLogFormatter =
      AuditLogFormatter.createBackedBy(ImmutableSet.of(), ImmutableSet.of(), "server-id");
  private final TimeZone timeZone = TimeZone.getTimeZone("America/Los_Angeles");

  @Before
  public void setUp() throws Exception {
    projectName = Project.nameKey("Test Repository");
    repository = new InMemoryRepository(new DfsRepositoryDescription("Test Repository"));
    testRepository = new TestRepository<>(repository);
  }

  @Test
  public void specifiedGroupUuidIsRespectedForNewGroup() throws Exception {
    InternalGroupCreation groupCreation =
        getPrefilledGroupCreationBuilder().setGroupUUID(groupUuid).build();
    createGroup(groupCreation);

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group).value().groupUuid().isEqualTo(groupUuid);
  }

  @Test
  public void specifiedNameIsRespectedForNewGroup() throws Exception {
    InternalGroupCreation groupCreation =
        getPrefilledGroupCreationBuilder().setNameKey(groupName).build();
    createGroup(groupCreation);

    Optional<InternalGroup> group = loadGroup(groupCreation.getGroupUUID());
    assertThatGroup(group).value().nameKey().isEqualTo(groupName);
  }

  @Test
  public void nameOfGroupUpdateOverridesGroupCreation() throws Exception {
    AccountGroup.NameKey anotherName = AccountGroup.nameKey("Another name");

    InternalGroupCreation groupCreation =
        getPrefilledGroupCreationBuilder().setNameKey(groupName).build();
    GroupDelta groupDelta = GroupDelta.builder().setName(anotherName).build();
    createGroup(groupCreation, groupDelta);

    Optional<InternalGroup> group = loadGroup(groupCreation.getGroupUUID());
    assertThatGroup(group).value().nameKey().isEqualTo(anotherName);
  }

  @Test
  public void nameOfNewGroupMustNotBeEmpty() throws Exception {
    InternalGroupCreation groupCreation =
        getPrefilledGroupCreationBuilder().setNameKey(AccountGroup.nameKey("")).build();
    GroupConfig groupConfig = GroupConfig.createForNewGroup(projectName, repository, groupCreation);

    try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
      Throwable thrown = assertThrows(Throwable.class, () -> groupConfig.commit(metaDataUpdate));
      assertThat(thrown.getCause(), instanceOf(ConfigInvalidException.class));
      assertThat(thrown).hasMessageThat().contains("Name of the group " + groupUuid);
    }
  }

  @Test
  public void specifiedIdIsRespectedForNewGroup() throws Exception {
    InternalGroupCreation groupCreation = getPrefilledGroupCreationBuilder().setId(groupId).build();
    createGroup(groupCreation);

    Optional<InternalGroup> group = loadGroup(groupCreation.getGroupUUID());
    assertThatGroup(group).value().id().isEqualTo(groupId);
  }

  @Test
  public void idOfNewGroupMustNotBeNegative() throws Exception {
    InternalGroupCreation groupCreation =
        getPrefilledGroupCreationBuilder().setId(AccountGroup.id(-2)).build();
    GroupConfig groupConfig = GroupConfig.createForNewGroup(projectName, repository, groupCreation);

    try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
      Throwable thrown = assertThrows(Throwable.class, () -> groupConfig.commit(metaDataUpdate));
      assertThat(thrown.getCause(), instanceOf(ConfigInvalidException.class));
      assertThat(thrown).hasMessageThat().contains("ID of the group " + groupUuid);
    }
  }

  @Test
  public void descriptionDefaultsToNull() throws Exception {
    InternalGroupCreation groupCreation =
        InternalGroupCreation.builder()
            .setGroupUUID(groupUuid)
            .setNameKey(groupName)
            .setId(groupId)
            .build();
    createGroup(groupCreation);

    Optional<InternalGroup> group = loadGroup(groupCreation.getGroupUUID());
    assertThatGroup(group).value().description().isNull();
  }

  @Test
  public void specifiedDescriptionIsRespectedForNewGroup() throws Exception {
    String description = "This is a test group.";

    InternalGroupCreation groupCreation = getPrefilledGroupCreationBuilder().build();
    GroupDelta groupDelta = GroupDelta.builder().setDescription(description).build();
    createGroup(groupCreation, groupDelta);

    Optional<InternalGroup> group = loadGroup(groupCreation.getGroupUUID());
    assertThatGroup(group).value().description().isEqualTo(description);
  }

  @Test
  public void emptyDescriptionForNewGroupIsIgnored() throws Exception {
    InternalGroupCreation groupCreation = getPrefilledGroupCreationBuilder().build();
    GroupDelta groupDelta = GroupDelta.builder().setDescription("").build();
    createGroup(groupCreation, groupDelta);

    Optional<InternalGroup> group = loadGroup(groupCreation.getGroupUUID());
    assertThatGroup(group).value().description().isNull();
  }

  @Test
  public void ownerGroupUuidDefaultsToGroupItself() throws Exception {
    InternalGroupCreation groupCreation =
        InternalGroupCreation.builder()
            .setGroupUUID(groupUuid)
            .setNameKey(groupName)
            .setId(groupId)
            .build();
    createGroup(groupCreation);

    Optional<InternalGroup> group = loadGroup(groupCreation.getGroupUUID());
    assertThatGroup(group).value().ownerGroupUuid().isEqualTo(groupUuid);
  }

  @Test
  public void specifiedOwnerGroupUuidIsRespectedForNewGroup() throws Exception {
    AccountGroup.UUID ownerGroupUuid = AccountGroup.uuid("anotherOwnerUuid");

    InternalGroupCreation groupCreation = getPrefilledGroupCreationBuilder().build();
    GroupDelta groupDelta = GroupDelta.builder().setOwnerGroupUUID(ownerGroupUuid).build();
    createGroup(groupCreation, groupDelta);

    Optional<InternalGroup> group = loadGroup(groupCreation.getGroupUUID());
    assertThatGroup(group).value().ownerGroupUuid().isEqualTo(ownerGroupUuid);
  }

  @Test
  public void ownerGroupUuidOfNewGroupMustNotBeEmpty() throws Exception {
    InternalGroupCreation groupCreation = getPrefilledGroupCreationBuilder().build();
    GroupDelta groupDelta = GroupDelta.builder().setOwnerGroupUUID(AccountGroup.uuid("")).build();
    GroupConfig groupConfig = GroupConfig.createForNewGroup(projectName, repository, groupCreation);
    groupConfig.setGroupDelta(groupDelta, auditLogFormatter);

    try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
      Throwable thrown = assertThrows(Throwable.class, () -> groupConfig.commit(metaDataUpdate));
      assertThat(thrown.getCause(), instanceOf(ConfigInvalidException.class));
      assertThat(thrown).hasMessageThat().contains("Owner UUID of the group " + groupUuid);
    }
  }

  @Test
  public void visibleToAllDefaultsToFalse() throws Exception {
    InternalGroupCreation groupCreation =
        InternalGroupCreation.builder()
            .setGroupUUID(groupUuid)
            .setNameKey(groupName)
            .setId(groupId)
            .build();
    createGroup(groupCreation);

    Optional<InternalGroup> group = loadGroup(groupCreation.getGroupUUID());
    assertThatGroup(group).value().visibleToAll().isFalse();
  }

  @Test
  public void specifiedVisibleToAllIsRespectedForNewGroup() throws Exception {
    InternalGroupCreation groupCreation = getPrefilledGroupCreationBuilder().build();
    GroupDelta groupDelta = GroupDelta.builder().setVisibleToAll(true).build();
    createGroup(groupCreation, groupDelta);

    Optional<InternalGroup> group = loadGroup(groupCreation.getGroupUUID());
    assertThatGroup(group).value().visibleToAll().isTrue();
  }

  @Test
  public void createdOnDefaultsToNow() throws Exception {
    // Git timestamps are only precise to the second.
    Timestamp testStart = TimeUtil.truncateToSecond(TimeUtil.nowTs());

    InternalGroupCreation groupCreation =
        InternalGroupCreation.builder()
            .setGroupUUID(groupUuid)
            .setNameKey(groupName)
            .setId(groupId)
            .build();
    createGroup(groupCreation);

    Optional<InternalGroup> group = loadGroup(groupCreation.getGroupUUID());
    assertThatGroup(group).value().createdOn().isAtLeast(testStart);
  }

  @Test
  public void specifiedCreatedOnIsRespectedForNewGroup() throws Exception {
    Timestamp createdOn = toTimestamp(LocalDate.of(2017, Month.DECEMBER, 11).atTime(13, 44, 10));

    InternalGroupCreation groupCreation = getPrefilledGroupCreationBuilder().build();
    GroupDelta groupDelta = GroupDelta.builder().setUpdatedOn(createdOn).build();
    createGroup(groupCreation, groupDelta);

    Optional<InternalGroup> group = loadGroup(groupCreation.getGroupUUID());
    assertThatGroup(group).value().createdOn().isEqualTo(createdOn);
  }

  @Test
  public void specifiedMembersAreRespectedForNewGroup() throws Exception {
    Account.Id member1 = Account.id(1);
    Account.Id member2 = Account.id(2);

    InternalGroupCreation groupCreation = getPrefilledGroupCreationBuilder().build();
    GroupDelta groupDelta =
        GroupDelta.builder()
            .setMemberModification(members -> ImmutableSet.of(member1, member2))
            .build();
    createGroup(groupCreation, groupDelta);

    Optional<InternalGroup> group = loadGroup(groupCreation.getGroupUUID());
    assertThatGroup(group).value().members().containsExactly(member1, member2);
  }

  @Test
  public void specifiedSubgroupsAreRespectedForNewGroup() throws Exception {
    AccountGroup.UUID subgroup1 = AccountGroup.uuid("subgroup1");
    AccountGroup.UUID subgroup2 = AccountGroup.uuid("subgroup2");

    InternalGroupCreation groupCreation = getPrefilledGroupCreationBuilder().build();
    GroupDelta groupDelta =
        GroupDelta.builder()
            .setSubgroupModification(subgroups -> ImmutableSet.of(subgroup1, subgroup2))
            .build();
    createGroup(groupCreation, groupDelta);

    Optional<InternalGroup> group = loadGroup(groupCreation.getGroupUUID());
    assertThatGroup(group).value().subgroups().containsExactly(subgroup1, subgroup2);
  }

  @Test
  public void nameInConfigMayBeUndefined() throws Exception {
    populateGroupConfig(groupUuid, "[group]\n\tid = 42\n\townerGroupUuid = owners\n");

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group).value().name().isEmpty();
  }

  @Test
  public void nameInConfigMayBeEmpty() throws Exception {
    populateGroupConfig(groupUuid, "[group]\n\tname=\n\tid = 42\n\townerGroupUuid = owners\n");

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group).value().name().isEmpty();
  }

  @Test
  public void idInConfigMustBeDefined() throws Exception {
    populateGroupConfig(groupUuid, "[group]\n\tname = users\n\townerGroupUuid = owners\n");

    ConfigInvalidException thrown =
        assertThrows(
            ConfigInvalidException.class,
            () -> GroupConfig.loadForGroup(projectName, repository, groupUuid));
    assertThat(thrown).hasMessageThat().contains("ID of the group " + groupUuid);
  }

  @Test
  public void idInConfigMustNotBeNegative() throws Exception {
    populateGroupConfig(
        groupUuid, "[group]\n\tname = users\n\tid = -5\n\townerGroupUuid = owners\n");

    ConfigInvalidException thrown =
        assertThrows(
            ConfigInvalidException.class,
            () -> GroupConfig.loadForGroup(projectName, repository, groupUuid));
    assertThat(thrown).hasMessageThat().contains("ID of the group " + groupUuid);
  }

  @Test
  public void descriptionInConfigMayBeUndefined() throws Exception {
    populateGroupConfig(groupUuid, "[group]\n\tid = 42\n\townerGroupUuid = owners\n");

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group).value().description().isNull();
  }

  @Test
  public void descriptionInConfigMayBeEmpty() throws Exception {
    populateGroupConfig(
        groupUuid, "[group]\n\tdescription=\n\tid = 42\n\townerGroupUuid = owners\n");

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group).value().description().isNull();
  }

  @Test
  public void ownerGroupUuidInConfigMustBeDefined() throws Exception {
    populateGroupConfig(groupUuid, "[group]\n\tname = users\n\tid = 42\n");

    ConfigInvalidException thrown =
        assertThrows(
            ConfigInvalidException.class,
            () -> GroupConfig.loadForGroup(projectName, repository, groupUuid));
    assertThat(thrown).hasMessageThat().contains("Owner UUID of the group " + groupUuid);
  }

  @Test
  public void membersFileNeedNotExist() throws Exception {
    populateGroupConfig(groupUuid, "[group]\n\tname=users\n\tid = 42\n\townerGroupUuid = owners\n");

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group).value().members().isEmpty();
  }

  @Test
  public void membersFileMayBeEmpty() throws Exception {
    populateGroupConfig(groupUuid, "[group]\n\tname=users\n\tid = 42\n\townerGroupUuid = owners\n");
    populateSubgroupsFile(groupUuid, "");

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group).value().members().isEmpty();
  }

  @Test
  public void membersFileMayContainOnlyWhitespace() throws Exception {
    populateGroupConfig(groupUuid, "[group]\n\tname=users\n\tid = 42\n\townerGroupUuid = owners\n");
    populateMembersFile(groupUuid, "\n\t\n\n");

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group).value().members().isEmpty();
  }

  @Test
  public void membersFileMayUseAnyLineBreakCharacters() throws Exception {
    populateGroupConfig(groupUuid, "[group]\n\tname=users\n\tid = 42\n\townerGroupUuid = owners\n");
    populateMembersFile(groupUuid, "1\n2\n3\r4\r\n5\u20296");

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group)
        .value()
        .members()
        .containsExactly(
            Account.id(1),
            Account.id(2),
            Account.id(3),
            Account.id(4),
            Account.id(5),
            Account.id(6));
  }

  @Test
  public void membersFileMustContainIntegers() throws Exception {
    populateGroupConfig(groupUuid, "[group]\n\tname=users\n\tid = 42\n\townerGroupUuid = owners\n");
    populateMembersFile(groupUuid, "One");

    ConfigInvalidException thrown =
        assertThrows(ConfigInvalidException.class, () -> loadGroup(groupUuid));
    assertThat(thrown).hasMessageThat().contains("Invalid file members");
  }

  @Test
  public void membersFileUsesLineBreaksToSeparateMembers() throws Exception {
    populateGroupConfig(groupUuid, "[group]\n\tname=users\n\tid = 42\n\townerGroupUuid = owners\n");
    populateMembersFile(groupUuid, "1\t2");

    ConfigInvalidException thrown =
        assertThrows(ConfigInvalidException.class, () -> loadGroup(groupUuid));
    assertThat(thrown).hasMessageThat().contains("Invalid file members");
  }

  @Test
  public void subgroupsFileNeedNotExist() throws Exception {
    populateGroupConfig(groupUuid, "[group]\n\tname=users\n\tid = 42\n\townerGroupUuid = owners\n");

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group).value().subgroups().isEmpty();
  }

  @Test
  public void subgroupsFileMayBeEmpty() throws Exception {
    populateGroupConfig(groupUuid, "[group]\n\tname=users\n\tid = 42\n\townerGroupUuid = owners\n");
    populateMembersFile(groupUuid, "");

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group).value().subgroups().isEmpty();
  }

  @Test
  public void subgroupsFileMayContainOnlyWhitespace() throws Exception {
    populateGroupConfig(groupUuid, "[group]\n\tname=users\n\tid = 42\n\townerGroupUuid = owners\n");
    populateSubgroupsFile(groupUuid, "\n\t\n\n");

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group).value().subgroups().isEmpty();
  }

  @Test
  public void subgroupsFileMayUseAnyLineBreakCharacters() throws Exception {
    populateGroupConfig(groupUuid, "[group]\n\tname=users\n\tid = 42\n\townerGroupUuid = owners\n");
    populateSubgroupsFile(groupUuid, "1\n2\n3\r4\r\n5\u20296");

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group)
        .value()
        .subgroups()
        .containsExactly(
            AccountGroup.uuid("1"),
            AccountGroup.uuid("2"),
            AccountGroup.uuid("3"),
            AccountGroup.uuid("4"),
            AccountGroup.uuid("5"),
            AccountGroup.uuid("6"));
  }

  @Test
  public void subgroupsFileMayContainSubgroupsWithWhitespaceInUuid() throws Exception {
    populateGroupConfig(groupUuid, "[group]\n\tname=users\n\tid = 42\n\townerGroupUuid = owners\n");
    populateSubgroupsFile(groupUuid, "1\t2 3");

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group).value().subgroups().containsExactly(AccountGroup.uuid("1\t2 3"));
  }

  @Test
  public void subgroupsFileUsesLineBreaksToSeparateSubgroups() throws Exception {
    populateGroupConfig(groupUuid, "[group]\n\tname=users\n\tid = 42\n\townerGroupUuid = owners\n");
    populateSubgroupsFile(groupUuid, "1\t2\n3");

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group)
        .value()
        .subgroups()
        .containsExactly(AccountGroup.uuid("1\t2"), AccountGroup.uuid("3"));
  }

  @Test
  public void nameCanBeUpdated() throws Exception {
    createArbitraryGroup(groupUuid);
    AccountGroup.NameKey newName = AccountGroup.nameKey("New name");

    GroupDelta groupDelta = GroupDelta.builder().setName(newName).build();
    updateGroup(groupUuid, groupDelta);

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group).value().nameKey().isEqualTo(newName);
  }

  @Test
  public void nameCannotBeUpdatedToEmptyString() throws Exception {
    createArbitraryGroup(groupUuid);

    GroupConfig groupConfig = GroupConfig.loadForGroup(projectName, repository, groupUuid);
    GroupDelta groupDelta = GroupDelta.builder().setName(AccountGroup.nameKey("")).build();
    groupConfig.setGroupDelta(groupDelta, auditLogFormatter);

    try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
      Throwable thrown = assertThrows(Throwable.class, () -> groupConfig.commit(metaDataUpdate));
      assertThat(thrown.getCause(), instanceOf(ConfigInvalidException.class));
      assertThat(thrown).hasMessageThat().contains("Name of the group " + groupUuid);
    }
  }

  @Test
  public void nameCanBeUpdatedToEmptyStringIfExplicitlySpecified() throws Exception {
    createArbitraryGroup(groupUuid);
    AccountGroup.NameKey emptyName = AccountGroup.nameKey("");

    GroupConfig groupConfig = GroupConfig.loadForGroup(projectName, repository, groupUuid);
    groupConfig.setAllowSaveEmptyName();
    GroupDelta groupDelta = GroupDelta.builder().setName(emptyName).build();
    groupConfig.setGroupDelta(groupDelta, auditLogFormatter);
    commit(groupConfig);

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group).value().nameKey().isEqualTo(emptyName);
  }

  @Test
  public void descriptionCanBeUpdated() throws Exception {
    createArbitraryGroup(groupUuid);
    String newDescription = "New description";

    GroupDelta groupDelta = GroupDelta.builder().setDescription(newDescription).build();
    updateGroup(groupUuid, groupDelta);

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group).value().description().isEqualTo(newDescription);
  }

  @Test
  public void descriptionCanBeRemoved() throws Exception {
    createArbitraryGroup(groupUuid);

    GroupDelta groupDelta = GroupDelta.builder().setDescription("").build();
    Optional<InternalGroup> group = updateGroup(groupUuid, groupDelta);

    assertThatGroup(group).value().description().isNull();
  }

  @Test
  public void ownerGroupUuidCanBeUpdated() throws Exception {
    createArbitraryGroup(groupUuid);
    AccountGroup.UUID newOwnerGroupUuid = AccountGroup.uuid("New owner");

    GroupDelta groupDelta = GroupDelta.builder().setOwnerGroupUUID(newOwnerGroupUuid).build();
    updateGroup(groupUuid, groupDelta);

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group).value().ownerGroupUuid().isEqualTo(newOwnerGroupUuid);
  }

  @Test
  public void ownerGroupUuidCannotBeUpdatedToEmptyString() throws Exception {
    createArbitraryGroup(groupUuid);

    GroupConfig groupConfig = GroupConfig.loadForGroup(projectName, repository, groupUuid);
    GroupDelta groupDelta = GroupDelta.builder().setOwnerGroupUUID(AccountGroup.uuid("")).build();
    groupConfig.setGroupDelta(groupDelta, auditLogFormatter);

    try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
      Throwable thrown = assertThrows(Throwable.class, () -> groupConfig.commit(metaDataUpdate));
      assertThat(thrown.getCause(), instanceOf(ConfigInvalidException.class));
      assertThat(thrown).hasMessageThat().contains("Owner UUID of the group " + groupUuid);
    }
  }

  @Test
  public void visibleToAllCanBeUpdated() throws Exception {
    createArbitraryGroup(groupUuid);
    boolean oldVisibleAll = loadGroup(groupUuid).map(InternalGroup::isVisibleToAll).orElse(false);

    GroupDelta groupDelta = GroupDelta.builder().setVisibleToAll(!oldVisibleAll).build();
    updateGroup(groupUuid, groupDelta);

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group).value().visibleToAll().isEqualTo(!oldVisibleAll);
  }

  @Test
  public void createdOnIsNotAffectedByFurtherUpdates() throws Exception {
    Timestamp createdOn = toTimestamp(LocalDate.of(2017, Month.MAY, 11).atTime(13, 44, 10));
    Timestamp updatedOn = toTimestamp(LocalDate.of(2017, Month.DECEMBER, 12).atTime(10, 21, 49));

    InternalGroupCreation groupCreation = getPrefilledGroupCreationBuilder().build();
    GroupDelta initialGroupDelta = GroupDelta.builder().setUpdatedOn(createdOn).build();
    createGroup(groupCreation, initialGroupDelta);

    GroupDelta laterGroupDelta =
        GroupDelta.builder()
            .setName(AccountGroup.nameKey("Another name"))
            .setUpdatedOn(updatedOn)
            .build();
    Optional<InternalGroup> group = updateGroup(groupCreation.getGroupUUID(), laterGroupDelta);

    assertThatGroup(group).value().createdOn().isEqualTo(createdOn);
    Optional<InternalGroup> reloadedGroup = loadGroup(groupUuid);
    assertThatGroup(reloadedGroup).value().createdOn().isEqualTo(createdOn);
  }

  @Test
  public void membersCanBeAdded() throws Exception {
    createArbitraryGroup(groupUuid);
    Account.Id member1 = Account.id(1);
    Account.Id member2 = Account.id(2);

    GroupDelta groupDelta1 =
        GroupDelta.builder().setMemberModification(members -> ImmutableSet.of(member1)).build();
    updateGroup(groupUuid, groupDelta1);

    GroupDelta groupDelta2 =
        GroupDelta.builder()
            .setMemberModification(members -> Sets.union(members, ImmutableSet.of(member2)))
            .build();
    updateGroup(groupUuid, groupDelta2);

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group).value().members().containsExactly(member1, member2);
  }

  @Test
  public void membersCanBeDeleted() throws Exception {
    createArbitraryGroup(groupUuid);
    Account.Id member1 = Account.id(1);
    Account.Id member2 = Account.id(2);

    GroupDelta groupDelta1 =
        GroupDelta.builder()
            .setMemberModification(members -> ImmutableSet.of(member1, member2))
            .build();
    updateGroup(groupUuid, groupDelta1);

    GroupDelta groupDelta2 =
        GroupDelta.builder()
            .setMemberModification(members -> Sets.difference(members, ImmutableSet.of(member1)))
            .build();
    updateGroup(groupUuid, groupDelta2);

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group).value().members().containsExactly(member2);
  }

  @Test
  public void subgroupsCanBeAdded() throws Exception {
    createArbitraryGroup(groupUuid);
    AccountGroup.UUID subgroup1 = AccountGroup.uuid("subgroups1");
    AccountGroup.UUID subgroup2 = AccountGroup.uuid("subgroups2");

    GroupDelta groupDelta1 =
        GroupDelta.builder()
            .setSubgroupModification(subgroups -> ImmutableSet.of(subgroup1))
            .build();
    updateGroup(groupUuid, groupDelta1);

    GroupDelta groupDelta2 =
        GroupDelta.builder()
            .setSubgroupModification(subgroups -> Sets.union(subgroups, ImmutableSet.of(subgroup2)))
            .build();
    updateGroup(groupUuid, groupDelta2);

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group).value().subgroups().containsExactly(subgroup1, subgroup2);
  }

  @Test
  public void subgroupsCanBeDeleted() throws Exception {
    createArbitraryGroup(groupUuid);
    AccountGroup.UUID subgroup1 = AccountGroup.uuid("subgroups1");
    AccountGroup.UUID subgroup2 = AccountGroup.uuid("subgroups2");

    GroupDelta groupDelta1 =
        GroupDelta.builder()
            .setSubgroupModification(members -> ImmutableSet.of(subgroup1, subgroup2))
            .build();
    updateGroup(groupUuid, groupDelta1);

    GroupDelta groupDelta2 =
        GroupDelta.builder()
            .setSubgroupModification(
                members -> Sets.difference(members, ImmutableSet.of(subgroup1)))
            .build();
    updateGroup(groupUuid, groupDelta2);

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group).value().subgroups().containsExactly(subgroup2);
  }

  @Test
  public void createdGroupIsLoadedAutomatically() throws Exception {
    InternalGroupCreation groupCreation = getPrefilledGroupCreationBuilder().build();
    Optional<InternalGroup> group = createGroup(groupCreation);

    assertThat(group).isPresent();
  }

  @Test
  public void loadedNewGroupWithMandatoryPropertiesDoesNotChangeOnReload() throws Exception {
    InternalGroupCreation groupCreation = getPrefilledGroupCreationBuilder().build();

    Optional<InternalGroup> createdGroup = createGroup(groupCreation);
    Optional<InternalGroup> reloadedGroup = loadGroup(groupCreation.getGroupUUID());

    assertThat(createdGroup).isEqualTo(reloadedGroup);
  }

  @Test
  public void loadedNewGroupWithAllPropertiesDoesNotChangeOnReload() throws Exception {
    InternalGroupCreation groupCreation = getPrefilledGroupCreationBuilder().build();
    GroupDelta groupDelta =
        GroupDelta.builder()
            .setDescription("A test group")
            .setOwnerGroupUUID(AccountGroup.uuid("another owner"))
            .setVisibleToAll(true)
            .setName(AccountGroup.nameKey("Another name"))
            .setUpdatedOn(new Timestamp(92900892))
            .setMemberModification(members -> ImmutableSet.of(Account.id(1), Account.id(2)))
            .setSubgroupModification(subgroups -> ImmutableSet.of(AccountGroup.uuid("subgroup")))
            .build();

    Optional<InternalGroup> createdGroup = createGroup(groupCreation, groupDelta);
    Optional<InternalGroup> reloadedGroup = loadGroup(groupCreation.getGroupUUID());

    assertThat(createdGroup).isEqualTo(reloadedGroup);
  }

  @Test
  public void loadedGroupAfterUpdatesForAllPropertiesDoesNotChangeOnReload() throws Exception {
    createArbitraryGroup(groupUuid);

    GroupDelta groupDelta =
        GroupDelta.builder()
            .setDescription("A test group")
            .setOwnerGroupUUID(AccountGroup.uuid("another owner"))
            .setVisibleToAll(true)
            .setName(AccountGroup.nameKey("Another name"))
            .setUpdatedOn(new Timestamp(92900892))
            .setMemberModification(members -> ImmutableSet.of(Account.id(1), Account.id(2)))
            .setSubgroupModification(subgroups -> ImmutableSet.of(AccountGroup.uuid("subgroup")))
            .build();

    Optional<InternalGroup> updatedGroup = updateGroup(groupUuid, groupDelta);
    Optional<InternalGroup> reloadedGroup = loadGroup(groupUuid);

    assertThat(updatedGroup).isEqualTo(reloadedGroup);
  }

  @Test
  public void loadedGroupWithAllPropertiesAndUpdateOfSinglePropertyDoesNotChangeOnReload()
      throws Exception {
    // Create a group with all properties set.
    InternalGroupCreation groupCreation = getPrefilledGroupCreationBuilder().build();
    GroupDelta initialGroupDelta =
        GroupDelta.builder()
            .setDescription("A test group")
            .setOwnerGroupUUID(AccountGroup.uuid("another owner"))
            .setVisibleToAll(true)
            .setName(AccountGroup.nameKey("Another name"))
            .setUpdatedOn(new Timestamp(92900892))
            .setMemberModification(members -> ImmutableSet.of(Account.id(1), Account.id(2)))
            .setSubgroupModification(subgroups -> ImmutableSet.of(AccountGroup.uuid("subgroup")))
            .build();
    createGroup(groupCreation, initialGroupDelta);

    // Only update one of the properties.
    GroupDelta groupDelta =
        GroupDelta.builder().setName(AccountGroup.nameKey("Another name")).build();

    Optional<InternalGroup> updatedGroup = updateGroup(groupCreation.getGroupUUID(), groupDelta);
    Optional<InternalGroup> reloadedGroup = loadGroup(groupCreation.getGroupUUID());

    assertThat(updatedGroup).isEqualTo(reloadedGroup);
  }

  @Test
  public void groupConfigMayBeReusedForFurtherUpdates() throws Exception {
    InternalGroupCreation groupCreation =
        getPrefilledGroupCreationBuilder().setGroupUUID(groupUuid).setId(groupId).build();
    GroupConfig groupConfig = GroupConfig.createForNewGroup(projectName, repository, groupCreation);
    commit(groupConfig);

    AccountGroup.NameKey name = AccountGroup.nameKey("Robots");
    GroupDelta groupDelta1 = GroupDelta.builder().setName(name).build();
    groupConfig.setGroupDelta(groupDelta1, auditLogFormatter);
    commit(groupConfig);

    String description = "Test group for robots";
    GroupDelta groupDelta2 = GroupDelta.builder().setDescription(description).build();
    groupConfig.setGroupDelta(groupDelta2, auditLogFormatter);
    commit(groupConfig);

    Optional<InternalGroup> group = loadGroup(groupUuid);
    assertThatGroup(group).value().id().isEqualTo(groupId);
    assertThatGroup(group).value().nameKey().isEqualTo(name);
    assertThatGroup(group).value().description().isEqualTo(description);
  }

  @Test
  public void newGroupIsRepresentedByARefPointingToARootCommit() throws Exception {
    createArbitraryGroup(groupUuid);

    Ref ref = repository.exactRef(RefNames.refsGroups(groupUuid));
    assertThat(ref.getObjectId()).isNotNull();

    try (RevWalk revWalk = new RevWalk(repository)) {
      RevCommit revCommit = revWalk.parseCommit(ref.getObjectId());
      assertThat(revCommit.getParentCount()).isEqualTo(0);
    }
  }

  @Test
  public void updatedGroupIsRepresentedByARefPointingToACommitSequence() throws Exception {
    createArbitraryGroup(groupUuid);

    RevCommit commitAfterCreation = getLatestCommitForGroup(groupUuid);

    GroupDelta groupDelta =
        GroupDelta.builder().setName(AccountGroup.nameKey("Another name")).build();
    updateGroup(groupUuid, groupDelta);

    RevCommit commitAfterUpdate = getLatestCommitForGroup(groupUuid);
    assertThat(commitAfterUpdate).isNotEqualTo(commitAfterCreation);
    assertThat(commitAfterUpdate.getParents()).asList().containsExactly(commitAfterCreation);
  }

  @Test
  public void newCommitIsNotCreatedForEmptyUpdate() throws Exception {
    createArbitraryGroup(groupUuid);

    GroupDelta groupDelta = GroupDelta.builder().build();

    RevCommit commitBeforeUpdate = getLatestCommitForGroup(groupUuid);
    updateGroup(groupUuid, groupDelta);
    RevCommit commitAfterUpdate = getLatestCommitForGroup(groupUuid);

    assertThat(commitAfterUpdate).isEqualTo(commitBeforeUpdate);
  }

  @Test
  public void newCommitIsNotCreatedForPureUpdatedOnUpdate() throws Exception {
    createArbitraryGroup(groupUuid);

    Timestamp updatedOn = toTimestamp(LocalDate.of(3017, Month.DECEMBER, 12).atTime(10, 21, 49));
    GroupDelta groupDelta = GroupDelta.builder().setUpdatedOn(updatedOn).build();

    RevCommit commitBeforeUpdate = getLatestCommitForGroup(groupUuid);
    updateGroup(groupUuid, groupDelta);
    RevCommit commitAfterUpdate = getLatestCommitForGroup(groupUuid);

    assertThat(commitAfterUpdate).isEqualTo(commitBeforeUpdate);
  }

  @Test
  public void newCommitIsNotCreatedForRedundantNameUpdate() throws Exception {
    createArbitraryGroup(groupUuid);

    GroupDelta groupDelta = GroupDelta.builder().setName(groupName).build();
    updateGroup(groupUuid, groupDelta);

    RevCommit commitBeforeUpdate = getLatestCommitForGroup(groupUuid);
    updateGroup(groupUuid, groupDelta);
    RevCommit commitAfterUpdate = getLatestCommitForGroup(groupUuid);

    assertThat(commitAfterUpdate).isEqualTo(commitBeforeUpdate);
  }

  @Test
  public void newCommitIsNotCreatedForRedundantDescriptionUpdate() throws Exception {
    createArbitraryGroup(groupUuid);

    GroupDelta groupDelta = GroupDelta.builder().setDescription("A test group").build();
    updateGroup(groupUuid, groupDelta);

    RevCommit commitBeforeUpdate = getLatestCommitForGroup(groupUuid);
    updateGroup(groupUuid, groupDelta);
    RevCommit commitAfterUpdate = getLatestCommitForGroup(groupUuid);

    assertThat(commitAfterUpdate).isEqualTo(commitBeforeUpdate);
  }

  @Test
  public void newCommitIsNotCreatedForRedundantVisibleToAllUpdate() throws Exception {
    createArbitraryGroup(groupUuid);

    GroupDelta groupDelta = GroupDelta.builder().setVisibleToAll(true).build();
    updateGroup(groupUuid, groupDelta);

    RevCommit commitBeforeUpdate = getLatestCommitForGroup(groupUuid);
    updateGroup(groupUuid, groupDelta);
    RevCommit commitAfterUpdate = getLatestCommitForGroup(groupUuid);

    assertThat(commitAfterUpdate).isEqualTo(commitBeforeUpdate);
  }

  @Test
  public void newCommitIsNotCreatedForRedundantOwnerGroupUuidUpdate() throws Exception {
    createArbitraryGroup(groupUuid);

    GroupDelta groupDelta =
        GroupDelta.builder().setOwnerGroupUUID(AccountGroup.uuid("Another owner")).build();
    updateGroup(groupUuid, groupDelta);

    RevCommit commitBeforeUpdate = getLatestCommitForGroup(groupUuid);
    updateGroup(groupUuid, groupDelta);
    RevCommit commitAfterUpdate = getLatestCommitForGroup(groupUuid);

    assertThat(commitAfterUpdate).isEqualTo(commitBeforeUpdate);
  }

  @Test
  public void newCommitIsNotCreatedForRedundantMemberUpdate() throws Exception {
    createArbitraryGroup(groupUuid);

    GroupDelta groupDelta =
        GroupDelta.builder()
            .setMemberModification(members -> Sets.union(members, ImmutableSet.of(Account.id(10))))
            .build();
    updateGroup(groupUuid, groupDelta);

    RevCommit commitBeforeUpdate = getLatestCommitForGroup(groupUuid);
    updateGroup(groupUuid, groupDelta);
    RevCommit commitAfterUpdate = getLatestCommitForGroup(groupUuid);

    assertThat(commitAfterUpdate).isEqualTo(commitBeforeUpdate);
  }

  @Test
  public void newCommitIsNotCreatedForRedundantSubgroupsUpdate() throws Exception {
    createArbitraryGroup(groupUuid);

    GroupDelta groupDelta =
        GroupDelta.builder()
            .setSubgroupModification(
                subgroups -> Sets.union(subgroups, ImmutableSet.of(AccountGroup.uuid("subgroup"))))
            .build();
    updateGroup(groupUuid, groupDelta);

    RevCommit commitBeforeUpdate = getLatestCommitForGroup(groupUuid);
    updateGroup(groupUuid, groupDelta);
    RevCommit commitAfterUpdate = getLatestCommitForGroup(groupUuid);

    assertThat(commitAfterUpdate).isEqualTo(commitBeforeUpdate);
  }

  @Test
  public void newCommitIsNotCreatedWhenCommittingGroupCreationTwice() throws Exception {
    InternalGroupCreation groupCreation =
        getPrefilledGroupCreationBuilder().setGroupUUID(groupUuid).build();

    GroupDelta groupDelta =
        GroupDelta.builder().setName(AccountGroup.nameKey("Another name")).build();

    GroupConfig groupConfig = GroupConfig.createForNewGroup(projectName, repository, groupCreation);
    groupConfig.setGroupDelta(groupDelta, auditLogFormatter);
    commit(groupConfig);

    RevCommit commitBeforeSecondCommit = getLatestCommitForGroup(groupUuid);
    commit(groupConfig);
    RevCommit commitAfterSecondCommit = getLatestCommitForGroup(groupUuid);

    assertThat(commitAfterSecondCommit).isEqualTo(commitBeforeSecondCommit);
  }

  @Test
  public void newCommitIsNotCreatedWhenCommittingGroupUpdateTwice() throws Exception {
    createArbitraryGroup(groupUuid);

    GroupDelta groupDelta = GroupDelta.builder().setDescription("A test group").build();

    GroupConfig groupConfig = GroupConfig.loadForGroup(projectName, repository, groupUuid);
    groupConfig.setGroupDelta(groupDelta, auditLogFormatter);
    commit(groupConfig);

    RevCommit commitBeforeSecondCommit = getLatestCommitForGroup(groupUuid);
    commit(groupConfig);
    RevCommit commitAfterSecondCommit = getLatestCommitForGroup(groupUuid);

    assertThat(commitAfterSecondCommit).isEqualTo(commitBeforeSecondCommit);
  }

  @Test
  public void commitTimeMatchesDefaultCreatedOnOfNewGroup() throws Exception {
    // Git timestamps are only precise to the second.
    long testStartAsSecondsSinceEpoch = TimeUtil.nowTs().getTime() / 1000;

    InternalGroupCreation groupCreation =
        InternalGroupCreation.builder()
            .setGroupUUID(groupUuid)
            .setNameKey(groupName)
            .setId(groupId)
            .build();
    createGroup(groupCreation);

    RevCommit revCommit = getLatestCommitForGroup(groupUuid);
    assertThat(revCommit.getCommitTime()).isAtLeast((int) testStartAsSecondsSinceEpoch);
  }

  @Test
  public void commitTimeMatchesSpecifiedCreatedOnOfNewGroup() throws Exception {
    // Git timestamps are only precise to the second.
    long createdOnAsSecondsSinceEpoch = 9082093;

    InternalGroupCreation groupCreation =
        InternalGroupCreation.builder()
            .setGroupUUID(groupUuid)
            .setNameKey(groupName)
            .setId(groupId)
            .build();
    GroupDelta groupDelta =
        GroupDelta.builder()
            .setUpdatedOn(new Timestamp(createdOnAsSecondsSinceEpoch * 1000))
            .build();
    createGroup(groupCreation, groupDelta);

    RevCommit revCommit = getLatestCommitForGroup(groupUuid);
    assertThat(revCommit.getCommitTime()).isEqualTo(createdOnAsSecondsSinceEpoch);
  }

  @Test
  public void timestampOfCommitterMatchesSpecifiedCreatedOnOfNewGroup() throws Exception {
    Timestamp committerTimestamp =
        toTimestamp(LocalDate.of(2017, Month.DECEMBER, 13).atTime(15, 5, 27));
    Timestamp createdOn = toTimestamp(LocalDate.of(2016, Month.MARCH, 11).atTime(23, 49, 11));

    InternalGroupCreation groupCreation =
        InternalGroupCreation.builder()
            .setGroupUUID(groupUuid)
            .setNameKey(groupName)
            .setId(groupId)
            .build();
    GroupDelta groupDelta =
        GroupDelta.builder()
            .setName(AccountGroup.nameKey("Another name"))
            .setUpdatedOn(createdOn)
            .build();
    GroupConfig groupConfig = GroupConfig.createForNewGroup(projectName, repository, groupCreation);
    groupConfig.setGroupDelta(groupDelta, auditLogFormatter);

    PersonIdent committerIdent =
        new PersonIdent("Jane", "Jane@gerritcodereview.com", committerTimestamp, timeZone);
    try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
      metaDataUpdate.getCommitBuilder().setCommitter(committerIdent);
      groupConfig.commit(metaDataUpdate);
    }

    RevCommit revCommit = getLatestCommitForGroup(groupUuid);
    assertThat(revCommit.getCommitterIdent().getWhen()).isEqualTo(createdOn);
    assertThat(revCommit.getCommitterIdent().getTimeZone().getRawOffset())
        .isEqualTo(timeZone.getRawOffset());
  }

  @Test
  public void timestampOfAuthorMatchesSpecifiedCreatedOnOfNewGroup() throws Exception {
    Timestamp authorTimestamp =
        toTimestamp(LocalDate.of(2017, Month.DECEMBER, 13).atTime(15, 5, 27));
    Timestamp createdOn = toTimestamp(LocalDate.of(2016, Month.MARCH, 11).atTime(23, 49, 11));

    InternalGroupCreation groupCreation =
        InternalGroupCreation.builder()
            .setGroupUUID(groupUuid)
            .setNameKey(groupName)
            .setId(groupId)
            .build();
    GroupDelta groupDelta =
        GroupDelta.builder()
            .setName(AccountGroup.nameKey("Another name"))
            .setUpdatedOn(createdOn)
            .build();
    GroupConfig groupConfig = GroupConfig.createForNewGroup(projectName, repository, groupCreation);
    groupConfig.setGroupDelta(groupDelta, auditLogFormatter);

    PersonIdent authorIdent =
        new PersonIdent("Jane", "Jane@gerritcodereview.com", authorTimestamp, timeZone);
    try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
      metaDataUpdate.getCommitBuilder().setAuthor(authorIdent);
      groupConfig.commit(metaDataUpdate);
    }

    RevCommit revCommit = getLatestCommitForGroup(groupUuid);
    assertThat(revCommit.getAuthorIdent().getWhen()).isEqualTo(createdOn);
    assertThat(revCommit.getAuthorIdent().getTimeZone().getRawOffset())
        .isEqualTo(timeZone.getRawOffset());
  }

  @Test
  public void commitTimeMatchesDefaultUpdatedOnOfUpdatedGroup() throws Exception {
    // Git timestamps are only precise to the second.
    long testStartAsSecondsSinceEpoch = TimeUtil.nowTs().getTime() / 1000;

    createArbitraryGroup(groupUuid);
    GroupDelta groupDelta =
        GroupDelta.builder().setName(AccountGroup.nameKey("Another name")).build();
    updateGroup(groupUuid, groupDelta);

    RevCommit revCommit = getLatestCommitForGroup(groupUuid);
    assertThat(revCommit.getCommitTime()).isAtLeast((int) testStartAsSecondsSinceEpoch);
  }

  @Test
  public void commitTimeMatchesSpecifiedUpdatedOnOfUpdatedGroup() throws Exception {
    // Git timestamps are only precise to the second.
    long updatedOnAsSecondsSinceEpoch = 9082093;

    createArbitraryGroup(groupUuid);
    GroupDelta groupDelta =
        GroupDelta.builder()
            .setName(AccountGroup.nameKey("Another name"))
            .setUpdatedOn(new Timestamp(updatedOnAsSecondsSinceEpoch * 1000))
            .build();
    updateGroup(groupUuid, groupDelta);

    RevCommit revCommit = getLatestCommitForGroup(groupUuid);
    assertThat(revCommit.getCommitTime()).isEqualTo(updatedOnAsSecondsSinceEpoch);
  }

  @Test
  public void timestampOfCommitterMatchesSpecifiedUpdatedOnOfUpdatedGroup() throws Exception {
    Timestamp committerTimestamp =
        toTimestamp(LocalDate.of(2017, Month.DECEMBER, 13).atTime(15, 5, 27));
    Timestamp updatedOn = toTimestamp(LocalDate.of(2016, Month.MARCH, 11).atTime(23, 49, 11));

    createArbitraryGroup(groupUuid);
    GroupDelta groupDelta =
        GroupDelta.builder()
            .setName(AccountGroup.nameKey("Another name"))
            .setUpdatedOn(updatedOn)
            .build();
    GroupConfig groupConfig = GroupConfig.loadForGroup(projectName, repository, groupUuid);
    groupConfig.setGroupDelta(groupDelta, auditLogFormatter);

    PersonIdent committerIdent =
        new PersonIdent("Jane", "Jane@gerritcodereview.com", committerTimestamp, timeZone);
    try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
      metaDataUpdate.getCommitBuilder().setCommitter(committerIdent);
      groupConfig.commit(metaDataUpdate);
    }

    RevCommit revCommit = getLatestCommitForGroup(groupUuid);
    assertThat(revCommit.getCommitterIdent().getWhen()).isEqualTo(updatedOn);
    assertThat(revCommit.getCommitterIdent().getTimeZone().getRawOffset())
        .isEqualTo(timeZone.getRawOffset());
  }

  @Test
  public void timestampOfAuthorMatchesSpecifiedUpdatedOnOfUpdatedGroup() throws Exception {
    Timestamp authorTimestamp =
        toTimestamp(LocalDate.of(2017, Month.DECEMBER, 13).atTime(15, 5, 27));
    Timestamp updatedOn = toTimestamp(LocalDate.of(2016, Month.MARCH, 11).atTime(23, 49, 11));

    createArbitraryGroup(groupUuid);
    GroupDelta groupDelta =
        GroupDelta.builder()
            .setName(AccountGroup.nameKey("Another name"))
            .setUpdatedOn(updatedOn)
            .build();
    GroupConfig groupConfig = GroupConfig.loadForGroup(projectName, repository, groupUuid);
    groupConfig.setGroupDelta(groupDelta, auditLogFormatter);

    PersonIdent authorIdent =
        new PersonIdent("Jane", "Jane@gerritcodereview.com", authorTimestamp, timeZone);
    try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
      metaDataUpdate.getCommitBuilder().setAuthor(authorIdent);
      groupConfig.commit(metaDataUpdate);
    }

    RevCommit revCommit = getLatestCommitForGroup(groupUuid);
    assertThat(revCommit.getAuthorIdent().getWhen()).isEqualTo(updatedOn);
    assertThat(revCommit.getAuthorIdent().getTimeZone().getRawOffset())
        .isEqualTo(timeZone.getRawOffset());
  }

  @Test
  public void refStateOfLoadedGroupIsPopulatedWithCommitSha1() throws Exception {
    createArbitraryGroup(groupUuid);

    Optional<InternalGroup> group = loadGroup(groupUuid);

    RevCommit revCommit = getLatestCommitForGroup(groupUuid);
    assertThatGroup(group).value().refState().isEqualTo(revCommit.copy());
  }

  @Test
  public void groupCanBeLoadedAtASpecificRevision() throws Exception {
    createArbitraryGroup(groupUuid);

    AccountGroup.NameKey firstName = AccountGroup.nameKey("Bots");
    GroupDelta groupDelta1 = GroupDelta.builder().setName(firstName).build();
    updateGroup(groupUuid, groupDelta1);

    RevCommit commitAfterUpdate1 = getLatestCommitForGroup(groupUuid);

    GroupDelta groupDelta2 = GroupDelta.builder().setName(AccountGroup.nameKey("Robots")).build();
    updateGroup(groupUuid, groupDelta2);

    GroupConfig groupConfig =
        GroupConfig.loadForGroupSnapshot(
            projectName, repository, groupUuid, commitAfterUpdate1.copy());
    Optional<InternalGroup> group = groupConfig.getLoadedGroup();
    assertThatGroup(group).value().nameKey().isEqualTo(firstName);
    assertThatGroup(group).value().refState().isEqualTo(commitAfterUpdate1.copy());
  }

  @Test
  public void commitMessageOfNewGroupWithoutMembersOrSubgroupsContainsNoFooters() throws Exception {
    InternalGroupCreation groupCreation =
        getPrefilledGroupCreationBuilder().setGroupUUID(groupUuid).build();
    createGroup(groupCreation);

    RevCommit revCommit = getLatestCommitForGroup(groupUuid);
    assertThat(revCommit.getFullMessage()).isEqualTo("Create group");
  }

  @Test
  public void commitMessageOfNewGroupWithAdditionalNameSpecificationContainsNoFooters()
      throws Exception {
    InternalGroupCreation groupCreation =
        getPrefilledGroupCreationBuilder().setGroupUUID(groupUuid).build();
    GroupDelta groupDelta =
        GroupDelta.builder().setName(AccountGroup.nameKey("Another name")).build();
    createGroup(groupCreation, groupDelta);

    RevCommit revCommit = getLatestCommitForGroup(groupUuid);
    assertThat(revCommit.getFullMessage()).isEqualTo("Create group");
  }

  @Test
  public void commitMessageOfNewGroupWithMembersContainsFooters() throws Exception {
    Account account13 = createAccount(Account.id(13), "John");
    Account account7 = createAccount(Account.id(7), "Jane");
    ImmutableSet<Account> accounts = ImmutableSet.of(account13, account7);

    AuditLogFormatter auditLogFormatter =
        AuditLogFormatter.createBackedBy(accounts, ImmutableSet.of(), "server-id");

    InternalGroupCreation groupCreation =
        getPrefilledGroupCreationBuilder().setGroupUUID(groupUuid).build();
    GroupDelta groupDelta =
        GroupDelta.builder()
            .setMemberModification(members -> ImmutableSet.of(account13.id(), account7.id()))
            .build();

    GroupConfig groupConfig = GroupConfig.createForNewGroup(projectName, repository, groupCreation);
    groupConfig.setGroupDelta(groupDelta, auditLogFormatter);
    commit(groupConfig);

    RevCommit revCommit = getLatestCommitForGroup(groupUuid);
    assertThat(revCommit.getFullMessage())
        .isEqualTo("Create group\n\nAdd: Jane <7@server-id>\nAdd: John <13@server-id>");
  }

  @Test
  public void commitMessageOfNewGroupWithSubgroupsContainsFooters() throws Exception {
    GroupDescription.Basic group1 = createGroup(AccountGroup.uuid("129403"), "Bots");
    GroupDescription.Basic group2 = createGroup(AccountGroup.uuid("8903493"), "Verifiers");
    ImmutableSet<GroupDescription.Basic> groups = ImmutableSet.of(group1, group2);

    AuditLogFormatter auditLogFormatter =
        AuditLogFormatter.createBackedBy(ImmutableSet.of(), groups, "serverId");

    InternalGroupCreation groupCreation =
        getPrefilledGroupCreationBuilder().setGroupUUID(groupUuid).build();
    GroupDelta groupDelta =
        GroupDelta.builder()
            .setSubgroupModification(
                subgroups -> ImmutableSet.of(group1.getGroupUUID(), group2.getGroupUUID()))
            .build();
    GroupConfig groupConfig = GroupConfig.createForNewGroup(projectName, repository, groupCreation);
    groupConfig.setGroupDelta(groupDelta, auditLogFormatter);
    commit(groupConfig);

    RevCommit revCommit = getLatestCommitForGroup(groupUuid);
    assertThat(revCommit.getFullMessage())
        .isEqualTo("Create group\n\nAdd-group: Bots <129403>\nAdd-group: Verifiers <8903493>");
  }

  @Test
  public void commitMessageOfMemberAdditionContainsFooters() throws Exception {
    Account account13 = createAccount(Account.id(13), "John");
    Account account7 = createAccount(Account.id(7), "Jane");
    ImmutableSet<Account> accounts = ImmutableSet.of(account13, account7);

    createArbitraryGroup(groupUuid);

    AuditLogFormatter auditLogFormatter =
        AuditLogFormatter.createBackedBy(accounts, ImmutableSet.of(), "GerritServer1");

    GroupDelta groupDelta =
        GroupDelta.builder()
            .setMemberModification(members -> ImmutableSet.of(account13.id(), account7.id()))
            .build();
    updateGroup(groupUuid, groupDelta, auditLogFormatter);

    RevCommit revCommit = getLatestCommitForGroup(groupUuid);
    assertThat(revCommit.getFullMessage())
        .isEqualTo("Update group\n\nAdd: Jane <7@GerritServer1>\nAdd: John <13@GerritServer1>");
  }

  @Test
  public void commitMessageOfMemberRemovalContainsFooters() throws Exception {
    Account account13 = createAccount(Account.id(13), "John");
    Account account7 = createAccount(Account.id(7), "Jane");
    ImmutableSet<Account> accounts = ImmutableSet.of(account13, account7);

    createArbitraryGroup(groupUuid);

    AuditLogFormatter auditLogFormatter =
        AuditLogFormatter.createBackedBy(accounts, ImmutableSet.of(), "server-id");

    GroupDelta groupDelta1 =
        GroupDelta.builder()
            .setMemberModification(members -> ImmutableSet.of(account13.id(), account7.id()))
            .build();
    updateGroup(groupUuid, groupDelta1, auditLogFormatter);

    GroupDelta groupDelta2 =
        GroupDelta.builder()
            .setMemberModification(members -> ImmutableSet.of(account7.id()))
            .build();
    updateGroup(groupUuid, groupDelta2, auditLogFormatter);

    RevCommit revCommit = getLatestCommitForGroup(groupUuid);
    assertThat(revCommit.getFullMessage()).isEqualTo("Update group\n\nRemove: John <13@server-id>");
  }

  @Test
  public void commitMessageOfSubgroupAdditionContainsFooters() throws Exception {
    GroupDescription.Basic group1 = createGroup(AccountGroup.uuid("129403"), "Bots");
    GroupDescription.Basic group2 = createGroup(AccountGroup.uuid("8903493"), "Verifiers");
    ImmutableSet<GroupDescription.Basic> groups = ImmutableSet.of(group1, group2);

    createArbitraryGroup(groupUuid);

    AuditLogFormatter auditLogFormatter =
        AuditLogFormatter.createBackedBy(ImmutableSet.of(), groups, "serverId");

    GroupDelta groupDelta =
        GroupDelta.builder()
            .setSubgroupModification(
                subgroups -> ImmutableSet.of(group1.getGroupUUID(), group2.getGroupUUID()))
            .build();
    updateGroup(groupUuid, groupDelta, auditLogFormatter);

    RevCommit revCommit = getLatestCommitForGroup(groupUuid);
    assertThat(revCommit.getFullMessage())
        .isEqualTo("Update group\n\nAdd-group: Bots <129403>\nAdd-group: Verifiers <8903493>");
  }

  @Test
  public void commitMessageOfSubgroupRemovalContainsFooters() throws Exception {
    GroupDescription.Basic group1 = createGroup(AccountGroup.uuid("129403"), "Bots");
    GroupDescription.Basic group2 = createGroup(AccountGroup.uuid("8903493"), "Verifiers");
    ImmutableSet<GroupDescription.Basic> groups = ImmutableSet.of(group1, group2);

    createArbitraryGroup(groupUuid);

    AuditLogFormatter auditLogFormatter =
        AuditLogFormatter.createBackedBy(ImmutableSet.of(), groups, "serverId");

    GroupDelta groupDelta1 =
        GroupDelta.builder()
            .setSubgroupModification(
                subgroups -> ImmutableSet.of(group1.getGroupUUID(), group2.getGroupUUID()))
            .build();
    updateGroup(groupUuid, groupDelta1, auditLogFormatter);

    GroupDelta groupDelta2 =
        GroupDelta.builder()
            .setSubgroupModification(subgroups -> ImmutableSet.of(group1.getGroupUUID()))
            .build();
    updateGroup(groupUuid, groupDelta2, auditLogFormatter);

    RevCommit revCommit = getLatestCommitForGroup(groupUuid);
    assertThat(revCommit.getFullMessage())
        .isEqualTo("Update group\n\nRemove-group: Verifiers <8903493>");
  }

  @Test
  public void commitMessageOfGroupRenameContainsFooters() throws Exception {
    createArbitraryGroup(groupUuid);

    GroupDelta groupDelta1 = GroupDelta.builder().setName(AccountGroup.nameKey("Old name")).build();
    updateGroup(groupUuid, groupDelta1);

    GroupDelta groupDelta2 = GroupDelta.builder().setName(AccountGroup.nameKey("New name")).build();
    updateGroup(groupUuid, groupDelta2);

    RevCommit revCommit = getLatestCommitForGroup(groupUuid);
    assertThat(revCommit.getFullMessage())
        .isEqualTo("Update group\n\nRename from Old name to New name");
  }

  @Test
  public void commitMessageFootersCanBeMixed() throws Exception {
    Account account13 = createAccount(Account.id(13), "John");
    Account account7 = createAccount(Account.id(7), "Jane");
    ImmutableSet<Account> accounts = ImmutableSet.of(account13, account7);
    GroupDescription.Basic group1 = createGroup(AccountGroup.uuid("129403"), "Bots");
    GroupDescription.Basic group2 = createGroup(AccountGroup.uuid("8903493"), "Verifiers");
    ImmutableSet<GroupDescription.Basic> groups = ImmutableSet.of(group1, group2);

    createArbitraryGroup(groupUuid);

    AuditLogFormatter auditLogFormatter =
        AuditLogFormatter.createBackedBy(accounts, groups, "serverId");

    GroupDelta groupDelta1 =
        GroupDelta.builder()
            .setName(AccountGroup.nameKey("Old name"))
            .setMemberModification(members -> ImmutableSet.of(account7.id()))
            .setSubgroupModification(subgroups -> ImmutableSet.of(group2.getGroupUUID()))
            .build();
    updateGroup(groupUuid, groupDelta1, auditLogFormatter);

    GroupDelta groupDelta2 =
        GroupDelta.builder()
            .setName(AccountGroup.nameKey("New name"))
            .setMemberModification(members -> ImmutableSet.of(account13.id()))
            .setSubgroupModification(subgroups -> ImmutableSet.of(group1.getGroupUUID()))
            .build();
    updateGroup(groupUuid, groupDelta2, auditLogFormatter);

    RevCommit revCommit = getLatestCommitForGroup(groupUuid);
    assertThat(revCommit.getFullMessage())
        .isEqualTo(
            "Update group\n"
                + "\n"
                + "Add-group: Bots <129403>\n"
                + "Add: John <13@serverId>\n"
                + "Remove-group: Verifiers <8903493>\n"
                + "Remove: Jane <7@serverId>\n"
                + "Rename from Old name to New name");
  }

  private static Timestamp toTimestamp(LocalDateTime localDateTime) {
    return Timestamp.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
  }

  private void populateGroupConfig(AccountGroup.UUID uuid, String fileContent) throws Exception {
    testRepository
        .branch(RefNames.refsGroups(uuid))
        .commit()
        .message("Prepopulate group.config")
        .add(GroupConfig.GROUP_CONFIG_FILE, fileContent)
        .create();
  }

  private void populateMembersFile(AccountGroup.UUID uuid, String fileContent) throws Exception {
    testRepository
        .branch(RefNames.refsGroups(uuid))
        .commit()
        .message("Prepopulate members")
        .add(GroupConfig.MEMBERS_FILE, fileContent)
        .create();
  }

  private void populateSubgroupsFile(AccountGroup.UUID uuid, String fileContent) throws Exception {
    testRepository
        .branch(RefNames.refsGroups(uuid))
        .commit()
        .message("Prepopulate subgroups")
        .add(GroupConfig.SUBGROUPS_FILE, fileContent)
        .create();
  }

  private void createArbitraryGroup(AccountGroup.UUID uuid) throws Exception {
    InternalGroupCreation groupCreation =
        getPrefilledGroupCreationBuilder().setGroupUUID(uuid).build();
    createGroup(groupCreation);
  }

  private InternalGroupCreation.Builder getPrefilledGroupCreationBuilder() {
    return InternalGroupCreation.builder()
        .setGroupUUID(groupUuid)
        .setNameKey(groupName)
        .setId(groupId);
  }

  private Optional<InternalGroup> createGroup(InternalGroupCreation groupCreation)
      throws Exception {
    GroupConfig groupConfig = GroupConfig.createForNewGroup(projectName, repository, groupCreation);
    commit(groupConfig);
    return groupConfig.getLoadedGroup();
  }

  private Optional<InternalGroup> createGroup(
      InternalGroupCreation groupCreation, GroupDelta groupDelta) throws Exception {
    GroupConfig groupConfig = GroupConfig.createForNewGroup(projectName, repository, groupCreation);
    groupConfig.setGroupDelta(groupDelta, auditLogFormatter);
    commit(groupConfig);
    return groupConfig.getLoadedGroup();
  }

  private Optional<InternalGroup> updateGroup(AccountGroup.UUID uuid, GroupDelta groupDelta)
      throws Exception {
    return updateGroup(uuid, groupDelta, auditLogFormatter);
  }

  private Optional<InternalGroup> updateGroup(
      AccountGroup.UUID uuid, GroupDelta groupDelta, AuditLogFormatter auditLogFormatter)
      throws Exception {
    GroupConfig groupConfig = GroupConfig.loadForGroup(projectName, repository, uuid);
    groupConfig.setGroupDelta(groupDelta, auditLogFormatter);
    commit(groupConfig);
    return groupConfig.getLoadedGroup();
  }

  private Optional<InternalGroup> loadGroup(AccountGroup.UUID uuid) throws Exception {
    GroupConfig groupConfig = GroupConfig.loadForGroup(projectName, repository, uuid);
    return groupConfig.getLoadedGroup();
  }

  private void commit(GroupConfig groupConfig) throws IOException {
    try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
      groupConfig.commit(metaDataUpdate);
    }
  }

  private MetaDataUpdate createMetaDataUpdate() {
    PersonIdent serverIdent =
        new PersonIdent(
            "Gerrit Server", "noreply@gerritcodereview.com", TimeUtil.nowTs(), timeZone);

    MetaDataUpdate metaDataUpdate =
        new MetaDataUpdate(
            GitReferenceUpdated.DISABLED, Project.nameKey("Test Repository"), repository);
    metaDataUpdate.getCommitBuilder().setCommitter(serverIdent);
    metaDataUpdate.getCommitBuilder().setAuthor(serverIdent);
    return metaDataUpdate;
  }

  private RevCommit getLatestCommitForGroup(AccountGroup.UUID uuid) throws IOException {
    Ref ref = repository.exactRef(RefNames.refsGroups(uuid));
    assertWithMessage("Precondition: Assumed that ref for group " + uuid + " exists.")
        .that(ref.getObjectId())
        .isNotNull();

    try (RevWalk revWalk = new RevWalk(repository)) {
      return revWalk.parseCommit(ref.getObjectId());
    }
  }

  private static Account createAccount(Account.Id id, String name) {
    Account.Builder account = Account.builder(id, TimeUtil.nowTs());
    account.setFullName(name);
    return account.build();
  }

  private static GroupDescription.Basic createGroup(AccountGroup.UUID uuid, String name) {
    return new GroupDescription.Basic() {
      @Override
      public AccountGroup.UUID getGroupUUID() {
        return uuid;
      }

      @Override
      public String getName() {
        return name;
      }

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

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

  private static OptionalSubject<InternalGroupSubject, InternalGroup> assertThatGroup(
      Optional<InternalGroup> loadedGroup) {
    return assertThat(loadedGroup, internalGroups());
  }
}
