// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.acceptance.api.group;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.MoreCollectors.onlyElement;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
import static com.google.gerrit.acceptance.GitUtil.deleteRef;
import static com.google.gerrit.acceptance.GitUtil.fetch;
import static com.google.gerrit.acceptance.api.group.GroupAssert.assertGroupInfo;
import static com.google.gerrit.acceptance.rest.account.AccountAssert.assertAccountInfos;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allow;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowCapability;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowLabel;
import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static com.google.gerrit.truth.MapSubject.assertThatMap;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.truth.Correspondence;
import com.google.common.util.concurrent.AtomicLongMap;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.ExtensionRegistry;
import com.google.gerrit.acceptance.ExtensionRegistry.Registration;
import com.google.gerrit.acceptance.GitUtil;
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.ProjectResetter;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.Sandboxed;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.UseClockStep;
import com.google.gerrit.acceptance.config.GerritConfig;
import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.auth.ldap.FakeLdapGroupBackend;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.GroupReference;
import com.google.gerrit.entities.InternalGroup;
import com.google.gerrit.entities.LabelId;
import com.google.gerrit.entities.Permission;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.api.groups.GroupApi;
import com.google.gerrit.extensions.api.groups.GroupInput;
import com.google.gerrit.extensions.api.groups.Groups.ListRequest;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.GroupAuditEventInfo;
import com.google.gerrit.extensions.common.GroupAuditEventInfo.GroupMemberAuditEventInfo;
import com.google.gerrit.extensions.common.GroupAuditEventInfo.UserMemberAuditEventInfo;
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.common.GroupOptionsInfo;
import com.google.gerrit.extensions.events.GroupIndexedListener;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.extensions.restapi.Url;
import com.google.gerrit.server.ServerInitiated;
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.account.GroupIncludeCache;
import com.google.gerrit.server.account.GroupsSnapshotReader;
import com.google.gerrit.server.account.ServiceUserClassifier;
import com.google.gerrit.server.group.PeriodicGroupIndexer;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.group.db.GroupDelta;
import com.google.gerrit.server.group.db.Groups;
import com.google.gerrit.server.group.db.GroupsConsistencyChecker;
import com.google.gerrit.server.group.db.GroupsUpdate;
import com.google.gerrit.server.group.db.InternalGroupCreation;
import com.google.gerrit.server.index.group.GroupIndexer;
import com.google.gerrit.server.index.group.StalenessChecker;
import com.google.gerrit.server.notedb.Sequences;
import com.google.gerrit.server.util.MagicBranch;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.gerrit.testing.GerritJUnit.ThrowingRunnable;
import com.google.gerrit.truth.NullAwareCorrespondence;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Module;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.RemoteRefUpdate;
import org.junit.After;
import org.junit.Test;

@NoHttpd
@UseClockStep
public class GroupsIT extends AbstractDaemonTest {
  @Inject @ServerInitiated private GroupsUpdate groupsUpdate;
  @Inject private AccountOperations accountOperations;
  @Inject private GroupIncludeCache groupIncludeCache;
  @Inject private GroupIndexer groupIndexer;
  @Inject private GroupOperations groupOperations;
  @Inject private Groups groups;
  @Inject private GroupsConsistencyChecker consistencyChecker;
  @Inject private PeriodicGroupIndexer slaveGroupIndexer;
  @Inject private ProjectOperations projectOperations;
  @Inject private RequestScopeOperations requestScopeOperations;
  @Inject private Sequences seq;
  @Inject private StalenessChecker stalenessChecker;
  @Inject private ExtensionRegistry extensionRegistry;
  @Inject private GroupsSnapshotReader groupsSnapshotReader;

  @Override
  public Module createModule() {
    return new AbstractModule() {
      @Override
      protected void configure() {
        /** Binding a {@link FakeLdapGroupBackend} to test adding external groups * */
        DynamicSet.bind(binder(), GroupBackend.class).to(FakeLdapGroupBackend.class);
      }
    };
  }

  @After
  public void consistencyCheck() throws Exception {
    if (description.getAnnotation(IgnoreGroupInconsistencies.class) == null) {
      assertThat(consistencyChecker.check()).isEmpty();
    }
  }

  @Override
  protected ProjectResetter.Config resetProjects() {
    // Don't reset All-Users since deleting users makes groups inconsistent (e.g. groups would
    // contain members that no longer exist) and as result of this the group consistency checker
    // that is executed after each test would fail.
    return new ProjectResetter.Config().reset(allProjects, RefNames.REFS_CONFIG);
  }

  @Test
  public void systemGroupCanBeRetrievedFromIndex() throws Exception {
    List<GroupInfo> groupInfos = gApi.groups().query("name:Administrators").get();
    assertThat(groupInfos).isNotEmpty();
  }

  @Test
  public void addToNonExistingGroup_NotFound() throws Exception {
    assertThrows(
        ResourceNotFoundException.class,
        () -> gApi.groups().id("non-existing").addMembers("admin"));
  }

  @Test
  public void removeFromNonExistingGroup_NotFound() throws Exception {
    assertThrows(
        ResourceNotFoundException.class,
        () -> gApi.groups().id("non-existing").removeMembers("admin"));
  }

  @Test
  public void addRemoveMember() throws Exception {
    AccountGroup.UUID group = groupOperations.newGroup().create();

    gApi.groups().id(group.get()).addMembers("user1");
    assertMembers(group.get(), user);

    gApi.groups().id(group.get()).removeMembers("user1");
    ImmutableSet<Account.Id> members = groupOperations.group(group).get().members();
    assertThat(members).isEmpty();
  }

  @Test
  public void addExternalGroups() throws Exception {
    AccountGroup.UUID group1 = groupOperations.newGroup().create();
    AccountGroup.UUID group2 = groupOperations.newGroup().create();
    String g1RefName = RefNames.refsGroups(group1);
    String g2RefName = RefNames.refsGroups(group2);

    gApi.groups().id(group1.get()).addGroups("ldap:external_g1");
    gApi.groups().id(group2.get()).addGroups("ldap:external_g2");

    assertThat(groupIncludeCache.allExternalMembers())
        .containsAtLeastElementsIn(
            ImmutableList.of(
                AccountGroup.UUID.parse("ldap:external_g1"),
                AccountGroup.UUID.parse("ldap:external_g2")));

    assertThat(groupIncludeCache.parentGroupsOf(AccountGroup.UUID.parse("ldap:external_g1")))
        .containsExactly(group1);
    assertThat(groupIncludeCache.parentGroupsOf(AccountGroup.UUID.parse("ldap:external_g2")))
        .containsExactly(group2);

    GroupsSnapshotReader.Snapshot snapshot = groupsSnapshotReader.getSnapshot();

    gApi.groups().id(group1.get()).removeGroups("ldap:external_g1");

    GroupsSnapshotReader.Snapshot newSnapshot = groupsSnapshotReader.getSnapshot();

    /** Make sure groups snapshots are consistent */
    ObjectId g1ObjectId = getObjectIdFromSnapshot(snapshot, g1RefName);
    ObjectId g2ObjectId = getObjectIdFromSnapshot(snapshot, g2RefName);
    assertThat(snapshot.hash()).isNotEqualTo(newSnapshot.hash());
    assertThat(g1ObjectId).isNotEqualTo(getObjectIdFromSnapshot(newSnapshot, g1RefName));
    assertThat(g2ObjectId).isEqualTo(getObjectIdFromSnapshot(newSnapshot, g2RefName));
    assertThat(snapshot.groupsRefs().stream().map(Ref::getName).collect(toList()))
        .containsAtLeastElementsIn(ImmutableList.of(g1RefName, g2RefName));
    assertThat(newSnapshot.groupsRefs().stream().map(Ref::getName).collect(toList()))
        .containsAtLeastElementsIn(ImmutableList.of(g1RefName, g2RefName));

    /** GroupIncludeCache should return ldap:external_g2 only */
    assertThat(groupIncludeCache.allExternalMembers())
        .contains(AccountGroup.UUID.parse("ldap:external_g2"));

    /** Testing groups.getExternalGroups() with the old Snapshot */
    assertThat(groups.getExternalGroups(snapshot.groupsRefs()))
        .containsAtLeastElementsIn(
            ImmutableList.of(
                AccountGroup.UUID.parse("ldap:external_g1"),
                AccountGroup.UUID.parse("ldap:external_g2")));
  }

  private ObjectId getObjectIdFromSnapshot(GroupsSnapshotReader.Snapshot snapshot, String refName) {
    return snapshot.groupsRefs().stream()
        .filter(r -> r.getName().equals(refName))
        .map(Ref::getObjectId)
        .collect(onlyElement());
  }

  @Test
  public void removeMember_nullInMemberInputDoesNotCauseFailure() throws Exception {
    AccountGroup.UUID group =
        groupOperations.newGroup().addMember(admin.id()).addMember(user.id()).create();
    gApi.groups().id(group.get()).removeMembers(user.id().toString(), null);
    ImmutableSet<Account.Id> members = groupOperations.group(group).get().members();
    assertThat(members).containsExactly(admin.id());
  }

  @Test
  public void removeMember_emptyStringInMemberInputDoesNotCauseFailure() throws Exception {
    AccountGroup.UUID group =
        groupOperations.newGroup().addMember(admin.id()).addMember(user.id()).create();
    gApi.groups().id(group.get()).removeMembers(user.id().toString(), "");
    ImmutableSet<Account.Id> members = groupOperations.group(group).get().members();
    assertThat(members).containsExactly(admin.id());
  }

  @Test
  public void cachedGroupsForMemberAreUpdatedOnMemberAdditionAndRemoval() throws Exception {
    String username = name("user");
    Account.Id accountId = accountOperations.newAccount().username(username).create();

    // Fill the cache for the observed account.
    groupIncludeCache.getGroupsWithMember(accountId);
    AccountGroup.UUID groupUuid = groupOperations.newGroup().create();

    gApi.groups().id(groupUuid.get()).addMembers(username);

    Collection<AccountGroup.UUID> groupsWithMemberAfterAddition =
        groupIncludeCache.getGroupsWithMember(accountId);
    assertThat(groupsWithMemberAfterAddition).contains(groupUuid);

    gApi.groups().id(groupUuid.get()).removeMembers(username);

    Collection<AccountGroup.UUID> groupsWithMemberAfterRemoval =
        groupIncludeCache.getGroupsWithMember(accountId);
    assertThat(groupsWithMemberAfterRemoval).doesNotContain(groupUuid);
  }

  @Test
  public void cachedGroupByNameIsUpdatedOnCreation() throws Exception {
    String newGroupName = name("newGroup");
    AccountGroup.NameKey nameKey = AccountGroup.nameKey(newGroupName);
    assertThat(groupCache.get(nameKey)).isEmpty();
    gApi.groups().create(newGroupName);
    assertThat(groupCache.get(nameKey)).isPresent();
  }

  @Test
  public void addExistingMember_OK() throws Exception {
    String g = "Administrators";
    assertMembers(g, admin);
    gApi.groups().id("Administrators").addMembers("admin");
    assertMembers(g, admin);
  }

  @Test
  public void addNonExistingMember_UnprocessableEntity() throws Exception {
    assertThrows(
        UnprocessableEntityException.class,
        () -> gApi.groups().id("Administrators").addMembers("non-existing"));
  }

  @Test
  public void addMultipleMembers() throws Exception {
    AccountGroup.UUID group = groupOperations.newGroup().create();

    String u1 = name("u1");
    accountOperations.newAccount().username(u1).create();
    String u2 = name("u2");
    accountOperations.newAccount().username(u2).create();

    gApi.groups().id(group.get()).addMembers(u1, u2);

    List<AccountInfo> members = gApi.groups().id(group.get()).members();
    assertThat(members)
        .comparingElementsUsing(getAccountToUsernameCorrespondence())
        .containsExactly(u1, u2);
  }

  @Test
  public void membersWithAtSignInUsernameCanBeAdded() throws Exception {
    AccountGroup.UUID group = groupOperations.newGroup().create();
    String usernameWithAt = name("u1@something");
    accountOperations.newAccount().username(usernameWithAt).create();

    gApi.groups().id(group.get()).addMembers(usernameWithAt);

    List<AccountInfo> members = gApi.groups().id(group.get()).members();
    assertThat(members)
        .comparingElementsUsing(getAccountToUsernameCorrespondence())
        .containsExactly(usernameWithAt);
  }

  @Test
  public void membersWithAtSignInUsernameAreNotConfusedWithSimilarUsernames() throws Exception {
    AccountGroup.UUID group = groupOperations.newGroup().create();
    String usernameWithAt = name("u1@something");
    accountOperations.newAccount().username(usernameWithAt).create();
    String usernameWithoutAt = name("u1something");
    accountOperations.newAccount().username(usernameWithoutAt).create();
    String usernameOnlyPrefix = name("u1");
    accountOperations.newAccount().username(usernameOnlyPrefix).create();
    String usernameOnlySuffix = name("something");
    accountOperations.newAccount().username(usernameOnlySuffix).create();

    gApi.groups()
        .id(group.get())
        .addMembers(usernameWithAt, usernameWithoutAt, usernameOnlyPrefix, usernameOnlySuffix);

    List<AccountInfo> members = gApi.groups().id(group.get()).members();
    assertThat(members)
        .comparingElementsUsing(getAccountToUsernameCorrespondence())
        .containsExactly(usernameWithAt, usernameWithoutAt, usernameOnlyPrefix, usernameOnlySuffix);
  }

  @Test
  public void includeRemoveGroup() throws Exception {
    AccountGroup.UUID parent = groupOperations.newGroup().create();
    AccountGroup.UUID group = groupOperations.newGroup().create();
    gApi.groups().id(parent.get()).addGroups(group.get());
    assertThat(groupOperations.group(parent).get().subgroups()).containsExactly(group);

    gApi.groups().id(parent.get()).removeGroups(group.get());
    assertThat(groupOperations.group(parent).get().subgroups()).isEmpty();
  }

  @Test
  public void includeExternalGroup() throws Exception {
    AccountGroup.UUID group = groupOperations.newGroup().create();
    String subgroupUuid = SystemGroupBackend.REGISTERED_USERS.get();
    gApi.groups().id(group.get()).addGroups(subgroupUuid);

    List<GroupInfo> subgroups = gApi.groups().id(group.get()).includedGroups();
    assertThat(subgroups).hasSize(1);
    assertThat(subgroups.get(0).id).isEqualTo(subgroupUuid.replace(":", "%3A"));
    assertThat(subgroups.get(0).name).isEqualTo("Registered Users");
    assertThat(subgroups.get(0).groupId).isNull();

    List<? extends GroupAuditEventInfo> auditEvents = gApi.groups().id(group.get()).auditLog();
    assertThat(auditEvents).hasSize(1);
    assertSubgroupAuditEvent(
        auditEvents.get(0), GroupAuditEventInfo.Type.ADD_GROUP, admin.id(), "Registered Users");
  }

  @Test
  public void includeExistingGroup_OK() throws Exception {
    AccountGroup.UUID parent = groupOperations.newGroup().create();
    AccountGroup.UUID group = groupOperations.newGroup().create();
    groupOperations.group(parent).forUpdate().addSubgroup(group);

    gApi.groups().id(parent.get()).addGroups(group.get());

    ImmutableSet<AccountGroup.UUID> subgroups = groupOperations.group(parent).get().subgroups();
    assertThat(subgroups).containsExactly(group);
  }

  @Test
  public void addMultipleIncludes() throws Exception {
    AccountGroup.UUID parent = groupOperations.newGroup().create();
    AccountGroup.UUID group1 = groupOperations.newGroup().create();
    AccountGroup.UUID group2 = groupOperations.newGroup().create();

    gApi.groups().id(parent.get()).addGroups(group1.get(), group2.get());

    ImmutableSet<AccountGroup.UUID> subgroups = groupOperations.group(parent).get().subgroups();
    assertThat(subgroups).containsExactly(group1, group2);
  }

  @Test
  public void createGroup() throws Exception {
    String newGroupName = name("newGroup");
    GroupInfo g = gApi.groups().create(newGroupName).get();
    assertGroupInfo(group(newGroupName), g);
  }

  @Test
  public void createGroupNameIsTrimmed() throws Exception {
    String newGroupName = name("newGroup");
    GroupInfo g = gApi.groups().create(" " + newGroupName + " ").get();
    assertGroupInfo(group(newGroupName), g);
  }

  @Test
  public void createDuplicateInternalGroupCaseSensitiveName_Conflict() throws Exception {
    String dupGroupName = name("dupGroup");
    gApi.groups().create(dupGroupName);
    ResourceConflictException thrown =
        assertThrows(ResourceConflictException.class, () -> gApi.groups().create(dupGroupName));
    assertThat(thrown).hasMessageThat().contains("group '" + dupGroupName + "' already exists");
  }

  @Test
  public void createDuplicateInternalGroupCaseInsensitiveName() throws Exception {
    String dupGroupName = name("dupGroupA");
    String dupGroupNameLowerCase = name("dupGroupA").toLowerCase();
    gApi.groups().create(dupGroupName);
    gApi.groups().create(dupGroupNameLowerCase);
    assertThat(gApi.groups().list().getAsMap().keySet()).contains(dupGroupName);
    assertThat(gApi.groups().list().getAsMap().keySet()).contains(dupGroupNameLowerCase);
  }

  @Test
  public void createDuplicateSystemGroupCaseSensitiveName_Conflict() throws Exception {
    String newGroupName = "Registered Users";
    ResourceConflictException thrown =
        assertThrows(ResourceConflictException.class, () -> gApi.groups().create(newGroupName));
    assertThat(thrown).hasMessageThat().contains("group 'Registered Users' already exists");
  }

  @Test
  public void createDuplicateSystemGroupCaseInsensitiveName_Conflict() throws Exception {
    String newGroupName = "registered users";
    ResourceConflictException thrown =
        assertThrows(ResourceConflictException.class, () -> gApi.groups().create(newGroupName));
    assertThat(thrown).hasMessageThat().contains("group 'Registered Users' already exists");
  }

  @Test
  @GerritConfig(name = "groups.global:Anonymous-Users.name", value = "All Users")
  public void createGroupWithConfiguredNameOfSystemGroup_Conflict() throws Exception {
    ResourceConflictException thrown =
        assertThrows(ResourceConflictException.class, () -> gApi.groups().create("all users"));
    assertThat(thrown).hasMessageThat().contains("group 'All Users' already exists");
  }

  @Test
  @GerritConfig(name = "groups.global:Anonymous-Users.name", value = "All Users")
  public void createGroupWithDefaultNameOfSystemGroup_Conflict() throws Exception {
    ResourceConflictException thrown =
        assertThrows(
            ResourceConflictException.class, () -> gApi.groups().create("anonymous users"));
    assertThat(thrown).hasMessageThat().contains("group name 'Anonymous Users' is reserved");
  }

  @Test
  public void createGroupWithUuid() throws Exception {
    AccountGroup.UUID uuid = AccountGroup.UUID.parse("4eb25d1cca562f53b9356117f33840706a36a349");
    GroupInput input = new GroupInput();
    input.uuid = uuid.get();
    input.name = name("new-group");
    GroupInfo info = gApi.groups().create(input).get();
    assertThat(info.name).isEqualTo(input.name);
    assertThat(info.id).isEqualTo(input.uuid);
  }

  @Test
  public void createGroupWithExistingUuid_Conflict() throws Exception {
    GroupInfo existingGroup = gApi.groups().create(name("new-group")).get();
    GroupInput input = new GroupInput();
    input.uuid = existingGroup.id;
    input.name = name("another-new-group");
    ResourceConflictException thrown =
        assertThrows(ResourceConflictException.class, () -> gApi.groups().create(input).get());
    assertThat(thrown)
        .hasMessageThat()
        .isEqualTo(String.format("group with UUID '%s' already exists", input.uuid));
  }

  @Test
  public void createGroupWithInvalidUuid_BadRequest() throws Exception {
    AccountGroup.UUID uuid = AccountGroup.UUID.parse("foo:bar");
    GroupInput input = new GroupInput();
    input.uuid = uuid.get();
    input.name = name("new-group");
    BadRequestException thrown =
        assertThrows(BadRequestException.class, () -> gApi.groups().create(input).get());
    assertThat(thrown)
        .hasMessageThat()
        .isEqualTo(String.format("invalid group UUID '%s'", input.uuid));
  }

  @Test
  public void createGroupWithProperties() throws Exception {
    GroupInput in = new GroupInput();
    in.name = name("newGroup");
    in.description = "Test description";
    in.visibleToAll = true;
    in.ownerId = adminGroupUuid().get();
    GroupInfo g = gApi.groups().create(in).detail();
    assertThat(g.description).isEqualTo(in.description);
    assertThat(g.options.visibleToAll).isEqualTo(in.visibleToAll);
    assertThat(g.ownerId).isEqualTo(in.ownerId);
  }

  @Test
  public void createGroupWithoutCapability_Forbidden() throws Exception {
    requestScopeOperations.setApiUser(user.id());
    assertThrows(AuthException.class, () -> gApi.groups().create(name("newGroup")));
  }

  // TODO(issue-15508): Migrate timestamp fields in *Info/*Input classes from type Timestamp to
  // Instant
  @SuppressWarnings("JdkObsolete")
  @Test
  public void createdOnFieldIsPopulatedForNewGroup() throws Exception {
    // NoteDb allows only second precision.
    Instant testStartTime = TimeUtil.truncateToSecond(TimeUtil.now());
    String newGroupName = name("newGroup");
    GroupInfo group = gApi.groups().create(newGroupName).get();

    assertThat(group.createdOn.toInstant()).isAtLeast(testStartTime);
  }

  @Test
  public void cachedGroupsForMemberAreUpdatedOnGroupCreation() throws Exception {
    Account.Id accountId = accountOperations.newAccount().create();

    // Fill the cache for the observed account.
    groupIncludeCache.getGroupsWithMember(accountId);

    GroupInput groupInput = new GroupInput();
    groupInput.name = name("Users");
    groupInput.members = ImmutableList.of(String.valueOf(accountId.get()));
    GroupInfo group = gApi.groups().create(groupInput).get();

    Collection<AccountGroup.UUID> groups = groupIncludeCache.getGroupsWithMember(accountId);
    assertThat(groups).containsExactly(AccountGroup.uuid(group.id));
  }

  @Test
  public void getGroup() throws Exception {
    InternalGroup adminGroup = adminGroup();
    testGetGroup(adminGroup.getGroupUUID().get(), adminGroup);
    testGetGroup(adminGroup.getName(), adminGroup);
    testGetGroup(adminGroup.getId().get(), adminGroup);
  }

  private void testGetGroup(Object id, InternalGroup expectedGroup) throws Exception {
    GroupInfo group = gApi.groups().id(id.toString()).get();
    assertGroupInfo(expectedGroup, group);
  }

  @Test
  @GerritConfig(name = "groups.global:Anonymous-Users.name", value = "All Users")
  public void getSystemGroupByConfiguredName() throws Exception {
    GroupReference anonymousUsersGroup = systemGroupBackend.getGroup(ANONYMOUS_USERS);
    assertThat(anonymousUsersGroup.getName()).isEqualTo("All Users");

    GroupInfo group = gApi.groups().id(anonymousUsersGroup.getUUID().get()).get();
    assertThat(group.name).isEqualTo(anonymousUsersGroup.getName());

    group = gApi.groups().id(anonymousUsersGroup.getName()).get();
    assertThat(group.id).isEqualTo(Url.encode(anonymousUsersGroup.getUUID().get()));
  }

  @Test
  public void getSystemGroupByDefaultName() throws Exception {
    GroupReference anonymousUsersGroup = systemGroupBackend.getGroup(ANONYMOUS_USERS);
    GroupInfo group = gApi.groups().id("Anonymous Users").get();
    assertThat(group.name).isEqualTo(anonymousUsersGroup.getName());
    assertThat(group.id).isEqualTo(Url.encode(anonymousUsersGroup.getUUID().get()));
  }

  @Test
  @GerritConfig(name = "groups.global:Anonymous-Users.name", value = "All Users")
  public void getSystemGroupByDefaultName_NotFound() throws Exception {
    assertThrows(ResourceNotFoundException.class, () -> gApi.groups().id("Anonymous-Users").get());
  }

  @Test
  public void groupIsCreatedForSpecifiedName() throws Exception {
    String name = name("Users");
    gApi.groups().create(name);

    assertThat(gApi.groups().id(name).name()).isEqualTo(name);
  }

  @Test
  public void groupCannotBeCreatedWithNameOfAnotherGroup() throws Exception {
    String name = name("Users");
    gApi.groups().create(name).get();

    assertThrows(ResourceConflictException.class, () -> gApi.groups().create(name));
  }

  @Test
  public void groupCanBeRenamed() throws Exception {
    String name = name("Name1");
    GroupInfo group = gApi.groups().create(name).get();

    String newName = name("Name2");
    gApi.groups().id(name).name(newName);
    assertThat(gApi.groups().id(group.id).name()).isEqualTo(newName);
  }

  @Test
  public void groupCanBeRenamedToItsCurrentName() throws Exception {
    String name = name("Users");
    GroupInfo group = gApi.groups().create(name).get();

    gApi.groups().id(group.id).name(name);
    assertThat(gApi.groups().id(group.id).name()).isEqualTo(name);
  }

  @Test
  public void groupCannotBeRenamedToNameOfAnotherGroup() throws Exception {
    String name1 = name("Name1");
    GroupInfo group1 = gApi.groups().create(name1).get();

    String name2 = name("Name2");
    gApi.groups().create(name2);
    assertThrows(ResourceConflictException.class, () -> gApi.groups().id(group1.id).name(name2));
  }

  @Test
  public void renamedGroupCanBeLookedUpByNewName() throws Exception {
    String name = name("Name1");
    GroupInfo group = gApi.groups().create(name).get();

    String newName = name("Name2");
    gApi.groups().id(group.id).name(newName);

    GroupInfo foundGroup = gApi.groups().id(newName).get();
    assertThat(foundGroup.id).isEqualTo(group.id);
  }

  @Test
  public void oldNameOfRenamedGroupIsNotAccessibleAnymore() throws Exception {
    String name = name("Name1");
    GroupInfo group = gApi.groups().create(name).get();

    String newName = name("Name2");
    gApi.groups().id(group.id).name(newName);

    assertGroupDoesNotExist(name);
    assertThrows(ResourceNotFoundException.class, () -> gApi.groups().id(name).get());
  }

  @Test
  public void oldNameOfRenamedGroupIsFreeForUseAgain() throws Exception {
    String name = name("Name1");
    GroupInfo group1 = gApi.groups().create(name).get();

    String newName = name("Name2");
    gApi.groups().id(group1.id).name(newName);

    GroupInfo group2 = gApi.groups().create(name).get();
    assertThat(group2.id).isNotEqualTo(group1.id);
  }

  @Test
  public void groupDescription() throws Exception {
    String name = name("group");
    gApi.groups().create(name);

    // get description
    assertThat(gApi.groups().id(name).description()).isEmpty();

    // set description
    String desc = "New description for the group.";
    gApi.groups().id(name).description(desc);
    assertThat(gApi.groups().id(name).description()).isEqualTo(desc);

    // set description to null
    gApi.groups().id(name).description(null);
    assertThat(gApi.groups().id(name).description()).isEmpty();

    // set description to empty string
    gApi.groups().id(name).description("");
    assertThat(gApi.groups().id(name).description()).isEmpty();
  }

  @Test
  public void groupOptions() throws Exception {
    String name = name("group");
    gApi.groups().create(name);

    // get options
    assertThat(gApi.groups().id(name).options().visibleToAll).isNull();

    // set options
    GroupOptionsInfo options = new GroupOptionsInfo();
    options.visibleToAll = true;
    gApi.groups().id(name).options(options);
    assertThat(gApi.groups().id(name).options().visibleToAll).isTrue();
  }

  @Test
  public void groupOwner() throws Exception {
    String name = name("group");
    GroupInfo info = gApi.groups().create(name).get();
    String adminUUID = adminGroupUuid().get();
    String registeredUUID = SystemGroupBackend.REGISTERED_USERS.get();

    // get owner
    assertThat(Url.decode(gApi.groups().id(name).owner().id)).isEqualTo(info.id);

    // set owner by name
    gApi.groups().id(name).owner("Registered Users");
    assertThat(Url.decode(gApi.groups().id(name).owner().id)).isEqualTo(registeredUUID);

    // set owner by UUID
    gApi.groups().id(name).owner(adminUUID);
    assertThat(Url.decode(gApi.groups().id(name).owner().id)).isEqualTo(adminUUID);

    // set non existing owner
    assertThrows(
        UnprocessableEntityException.class,
        () -> gApi.groups().id(name).owner("Non-Existing Group"));
  }

  @Test
  public void listNonExistingGroupIncludes_NotFound() throws Exception {
    assertThrows(
        ResourceNotFoundException.class, () -> gApi.groups().id("non-existing").includedGroups());
  }

  @Test
  public void listEmptyGroupIncludes() throws Exception {
    AccountGroup.UUID gx = groupOperations.newGroup().create();
    assertThat(gApi.groups().id(gx.get()).includedGroups()).isEmpty();
  }

  @Test
  public void includeNonExistingGroup() throws Exception {
    AccountGroup.UUID gx = groupOperations.newGroup().create();
    assertThrows(
        UnprocessableEntityException.class,
        () -> gApi.groups().id(gx.get()).addGroups("non-existing"));
  }

  @Test
  public void listNonEmptyGroupIncludes() throws Exception {
    AccountGroup.UUID gz = groupOperations.newGroup().create();
    AccountGroup.UUID gy = groupOperations.newGroup().create();
    AccountGroup.UUID gx = groupOperations.newGroup().subgroups(gy, gz).create();

    List<GroupInfo> includes = gApi.groups().id(gx.get()).includedGroups();

    String gyName = groupOperations.group(gy).get().name();
    String gzName = groupOperations.group(gz).get().name();
    assertIncludes(includes, gyName, gzName);
  }

  @Test
  public void listOneIncludeMember() throws Exception {
    AccountGroup.UUID gy = groupOperations.newGroup().create();
    AccountGroup.UUID gx = groupOperations.newGroup().subgroups(gy).create();

    List<GroupInfo> includes = gApi.groups().id(gx.get()).includedGroups();

    String gyName = groupOperations.group(gy).get().name();
    assertIncludes(includes, gyName);
  }

  @Test
  public void listNonExistingGroupMembers_NotFound() throws Exception {
    assertThrows(ResourceNotFoundException.class, () -> gApi.groups().id("non-existing").members());
  }

  @Test
  public void listEmptyGroupMembers() throws Exception {
    AccountGroup.UUID group = groupOperations.newGroup().create();
    assertThat(gApi.groups().id(group.get()).members()).isEmpty();
  }

  @Test
  public void listNonEmptyGroupMembers() throws Exception {
    AccountGroup.UUID group = groupOperations.newGroup().create();
    String user1 = name("user1");
    accountOperations.newAccount().username(user1).create();
    String user2 = name("user2");
    accountOperations.newAccount().username(user2).create();
    gApi.groups().id(group.get()).addMembers(user1, user2);

    assertMembers(gApi.groups().id(group.get()).members(), user1, user2);
  }

  @Test
  public void listOneGroupMember() throws Exception {
    AccountGroup.UUID group = groupOperations.newGroup().create();
    String user = name("user1");
    accountOperations.newAccount().username(user).create();
    gApi.groups().id(group.get()).addMembers(user);

    assertMembers(gApi.groups().id(group.get()).members(), user);
  }

  @Test
  public void listGroupMembersRecursively() throws Exception {
    AccountGroup.UUID gx = groupOperations.newGroup().create();
    String ux = name("ux");
    accountOperations.newAccount().username(ux).create();
    gApi.groups().id(gx.get()).addMembers(ux);

    AccountGroup.UUID gy = groupOperations.newGroup().create();
    String uy = name("uy");
    accountOperations.newAccount().username(uy).create();
    gApi.groups().id(gy.get()).addMembers(uy);

    AccountGroup.UUID gz = groupOperations.newGroup().create();
    String uz = name("uz");
    accountOperations.newAccount().username(uz).create();
    gApi.groups().id(gz.get()).addMembers(uz);

    gApi.groups().id(gx.get()).addGroups(gy.get());
    gApi.groups().id(gy.get()).addGroups(gz.get());
    assertMembers(gApi.groups().id(gx.get()).members(), ux);
    assertMembers(gApi.groups().id(gx.get()).members(true), ux, uy, uz);
  }

  @Test
  public void usersSeeTheirDirectMembershipWhenListingMembersRecursively() throws Exception {
    AccountGroup.UUID group = groupOperations.newGroup().create();
    gApi.groups().id(group.get()).addMembers(user.username());

    requestScopeOperations.setApiUser(user.id());
    assertMembers(gApi.groups().id(group.get()).members(true), user.fullName());
  }

  @Test
  public void usersDoNotSeeTheirIndirectMembershipWhenListingMembersRecursively() throws Exception {
    AccountGroup.UUID group1 = groupOperations.newGroup().ownerGroupUuid(adminGroupUuid()).create();
    AccountGroup.UUID group2 = groupOperations.newGroup().ownerGroupUuid(adminGroupUuid()).create();
    gApi.groups().id(group1.get()).addGroups(group2.get());
    gApi.groups().id(group2.get()).addMembers(user.username());

    requestScopeOperations.setApiUser(user.id());
    List<AccountInfo> listedMembers = gApi.groups().id(group1.get()).members(true);

    assertMembers(listedMembers);
  }

  @Test
  public void adminsSeeTheirIndirectMembershipWhenListingMembersRecursively() throws Exception {
    AccountGroup.UUID ownerGroup = groupOperations.newGroup().create();
    AccountGroup.UUID group1 = groupOperations.newGroup().ownerGroupUuid(ownerGroup).create();
    AccountGroup.UUID group2 = groupOperations.newGroup().ownerGroupUuid(ownerGroup).create();
    gApi.groups().id(group1.get()).addGroups(group2.get());
    gApi.groups().id(group2.get()).addMembers(admin.username());

    List<AccountInfo> listedMembers = gApi.groups().id(group1.get()).members(true);

    assertMembers(listedMembers, admin.fullName());
  }

  @Test
  public void ownersSeeTheirIndirectMembershipWhenListingMembersRecursively() throws Exception {
    AccountGroup.UUID ownerGroup = groupOperations.newGroup().create();
    AccountGroup.UUID group1 = groupOperations.newGroup().ownerGroupUuid(ownerGroup).create();
    AccountGroup.UUID group2 = groupOperations.newGroup().ownerGroupUuid(ownerGroup).create();
    gApi.groups().id(group1.get()).addGroups(group2.get());
    gApi.groups().id(ownerGroup.get()).addMembers(user.username());
    gApi.groups().id(group2.get()).addMembers(user.username());

    requestScopeOperations.setApiUser(user.id());
    List<AccountInfo> listedMembers = gApi.groups().id(group1.get()).members(true);

    assertMembers(listedMembers, user.fullName());
  }

  @Test
  public void defaultGroupsCreated() throws Exception {
    Iterable<String> names = gApi.groups().list().getAsMap().keySet();
    assertThat(names)
        .containsAtLeast("Administrators", ServiceUserClassifier.SERVICE_USERS)
        .inOrder();
  }

  @Test
  public void listAllGroups() throws Exception {
    List<String> expectedGroups =
        groups.getAllGroupReferences().map(GroupReference::getName).sorted().collect(toList());
    assertThat(expectedGroups.size()).isAtLeast(2);
    assertThatMap(gApi.groups().list().getAsMap())
        .keys()
        .containsExactlyElementsIn(expectedGroups)
        .inOrder();
  }

  @Test
  public void getGroupsByOwner() throws Exception {
    AccountGroup.UUID parent = groupOperations.newGroup().ownerGroupUuid(adminGroupUuid()).create();
    List<AccountGroup.UUID> children =
        Arrays.asList(
            groupOperations.newGroup().ownerGroupUuid(parent).create(),
            groupOperations.newGroup().ownerGroupUuid(parent).create());

    // By UUID
    List<GroupInfo> owned = gApi.groups().list().withOwnedBy(parent.get()).get();
    assertThat(owned.stream().map(g -> AccountGroup.uuid(g.id)).collect(toList()))
        .containsExactlyElementsIn(children);

    // By name
    String parentName = groupOperations.group(parent).get().name();
    owned = gApi.groups().list().withOwnedBy(parentName).get();
    assertThat(owned.stream().map(g -> AccountGroup.uuid(g.id)).collect(toList()))
        .containsExactlyElementsIn(children);

    // By group that does not own any others
    owned = gApi.groups().list().withOwnedBy(owned.get(0).id).get();
    assertThat(owned).isEmpty();

    // By non-existing group
    UnprocessableEntityException thrown =
        assertThrows(
            UnprocessableEntityException.class,
            () -> gApi.groups().list().withOwnedBy("does-not-exist").get());
    assertThat(thrown).hasMessageThat().contains("Group Not Found: does-not-exist");
  }

  @Test
  public void onlyVisibleGroupsReturned() throws Exception {
    String newGroupName = name("newGroup");
    GroupInput in = new GroupInput();
    in.name = newGroupName;
    in.description = "a hidden group";
    in.visibleToAll = false;
    in.ownerId = adminGroupUuid().get();
    gApi.groups().create(in);

    requestScopeOperations.setApiUser(user.id());
    assertThatMap(gApi.groups().list().getAsMap()).keys().doesNotContain(newGroupName);

    requestScopeOperations.setApiUser(admin.id());
    gApi.groups().id(newGroupName).addMembers(user.username());

    requestScopeOperations.setApiUser(user.id());
    assertThatMap(gApi.groups().list().getAsMap()).keys().contains(newGroupName);
  }

  @Test
  public void suggestGroup() throws Exception {
    Map<String, GroupInfo> groups = gApi.groups().list().withSuggest("adm").getAsMap();
    assertThatMap(groups).keys().containsExactly("Administrators");
    assertBadRequest(gApi.groups().list().withSuggest("adm").withSubstring("foo"));
    assertBadRequest(gApi.groups().list().withSuggest("adm").withRegex("foo.*"));
    assertBadRequest(gApi.groups().list().withSuggest("adm").withUser("user"));
    assertBadRequest(gApi.groups().list().withSuggest("adm").withOwned(true));
    assertBadRequest(gApi.groups().list().withSuggest("adm").withVisibleToAll(true));
    assertBadRequest(gApi.groups().list().withSuggest("adm").withStart(1));
  }

  @Test
  public void withSubstring() throws Exception {
    String group = name("Abcdefghijklmnop");
    gApi.groups().create(group);

    // Choose a substring which isn't part of any group or test method within this class.
    String substring = "efghijk";
    Map<String, GroupInfo> groups = gApi.groups().list().withSubstring(substring).getAsMap();
    assertThatMap(groups).keys().containsExactly(group);

    groups = gApi.groups().list().withSubstring("abcdefghi").getAsMap();
    assertThatMap(groups).keys().containsExactly(group);

    String otherGroup = name("Abcdefghijklmnop2");
    gApi.groups().create(otherGroup);
    groups = gApi.groups().list().withSubstring(substring).getAsMap();
    assertThatMap(groups).keys().containsExactly(group, otherGroup);

    groups = gApi.groups().list().withSubstring("non-existing-substring").getAsMap();
    assertThat(groups).isEmpty();
  }

  @Test
  public void withRegex() throws Exception {
    Map<String, GroupInfo> groups = gApi.groups().list().withRegex("Admin.*").getAsMap();
    assertThatMap(groups).keys().containsExactly("Administrators");

    groups = gApi.groups().list().withRegex("admin.*").getAsMap();
    assertThat(groups).isEmpty();

    groups = gApi.groups().list().withRegex(".*istrators").getAsMap();
    assertThatMap(groups).keys().containsExactly("Administrators");

    assertBadRequest(gApi.groups().list().withRegex(".*istrators").withSubstring("s"));
  }

  @Test
  public void allGroupInfoFieldsSetCorrectly() throws Exception {
    InternalGroup adminGroup = adminGroup();
    Map<String, GroupInfo> groups = gApi.groups().list().addGroup(adminGroup.getName()).getAsMap();
    assertThatMap(groups).keys().containsExactly("Administrators");
    assertGroupInfo(adminGroup, Iterables.getOnlyElement(groups.values()));
  }

  @Test
  public void getAuditLog() throws Exception {
    GroupApi g = gApi.groups().create(name("group"));
    List<? extends GroupAuditEventInfo> auditEvents = g.auditLog();
    assertThat(auditEvents).hasSize(1);
    assertMemberAuditEvent(
        auditEvents.get(0), GroupAuditEventInfo.Type.ADD_USER, admin.id(), admin.id());

    g.addMembers(user.username());
    auditEvents = g.auditLog();
    assertThat(auditEvents).hasSize(2);
    assertMemberAuditEvent(
        auditEvents.get(0), GroupAuditEventInfo.Type.ADD_USER, admin.id(), user.id());

    g.removeMembers(user.username());
    auditEvents = g.auditLog();
    assertThat(auditEvents).hasSize(3);
    assertMemberAuditEvent(
        auditEvents.get(0), GroupAuditEventInfo.Type.REMOVE_USER, admin.id(), user.id());

    String otherGroup = name("otherGroup");
    gApi.groups().create(otherGroup);
    g.addGroups(otherGroup);
    auditEvents = g.auditLog();
    assertThat(auditEvents).hasSize(4);
    assertSubgroupAuditEvent(
        auditEvents.get(0), GroupAuditEventInfo.Type.ADD_GROUP, admin.id(), otherGroup);

    g.removeGroups(otherGroup);
    auditEvents = g.auditLog();
    assertThat(auditEvents).hasSize(5);
    assertSubgroupAuditEvent(
        auditEvents.get(0), GroupAuditEventInfo.Type.REMOVE_GROUP, admin.id(), otherGroup);

    // Add a removed member back again.
    g.addMembers(user.username());
    auditEvents = g.auditLog();
    assertThat(auditEvents).hasSize(6);
    assertMemberAuditEvent(
        auditEvents.get(0), GroupAuditEventInfo.Type.ADD_USER, admin.id(), user.id());

    // Add a removed group back again.
    g.addGroups(otherGroup);
    auditEvents = g.auditLog();
    assertThat(auditEvents).hasSize(7);
    assertSubgroupAuditEvent(
        auditEvents.get(0), GroupAuditEventInfo.Type.ADD_GROUP, admin.id(), otherGroup);

    Timestamp lastDate = null;
    for (GroupAuditEventInfo auditEvent : auditEvents) {
      if (lastDate != null) {
        assertThat(lastDate).isAtLeast(auditEvent.date);
      }
      lastDate = auditEvent.date;
    }
  }

  /**
   * {@code @Sandboxed} is used by this test because it deletes a group reference which introduces
   * an inconsistency for the group storage. Once group deletion is supported, this test should be
   * updated to use the API instead.
   */
  @Test
  @Sandboxed
  @IgnoreGroupInconsistencies
  public void getAuditLogAfterDeletingASubgroup() throws Exception {
    GroupInfo parentGroup = gApi.groups().create(name("parent-group")).get();

    // Creates a subgroup and adds it to "parent-group" as a subgroup.
    GroupInfo subgroup = gApi.groups().create(name("sub-group")).get();
    gApi.groups().id(parentGroup.id).addGroups(subgroup.id);

    // Deletes the subgroup.
    deleteGroupRef(subgroup.id);

    List<? extends GroupAuditEventInfo> auditEvents = gApi.groups().id(parentGroup.id).auditLog();
    assertThat(auditEvents).hasSize(2);
    // Verify the unavailable subgroup's name is null.
    assertSubgroupAuditEvent(
        auditEvents.get(0), GroupAuditEventInfo.Type.ADD_GROUP, admin.id(), null);
  }

  private void deleteGroupRef(String groupId) throws Exception {
    AccountGroup.UUID uuid = AccountGroup.uuid(groupId);
    try (Repository repo = repoManager.openRepository(allUsers)) {
      RefUpdate ru = repo.updateRef(RefNames.refsGroups(uuid));
      ru.setForceUpdate(true);
      ru.setNewObjectId(ObjectId.zeroId());
      assertThat(ru.delete()).isEqualTo(RefUpdate.Result.FORCED);
    }

    // Reindex the group.
    gApi.groups().id(uuid.get()).index();

    // Verify "sub-group" has been deleted.
    assertThrows(ResourceNotFoundException.class, () -> gApi.groups().id(uuid.get()).get());
  }

  // reindex is tested by {@link AbstractQueryGroupsTest#reindex}
  @Test
  public void reindexPermissions() throws Exception {
    TestAccount groupOwner = accountCreator.user2();
    GroupInput in = new GroupInput();
    in.name = name("group");
    in.members = Stream.of(groupOwner).map(u -> u.id().toString()).collect(toList());
    in.visibleToAll = true;
    GroupInfo group = gApi.groups().create(in).get();

    // admin can reindex any group
    requestScopeOperations.setApiUser(admin.id());
    gApi.groups().id(group.id).index();

    // group owner can reindex own group (group is owned by itself)
    requestScopeOperations.setApiUser(groupOwner.id());
    gApi.groups().id(group.id).index();

    // user cannot reindex any group
    requestScopeOperations.setApiUser(user.id());
    AuthException thrown =
        assertThrows(AuthException.class, () -> gApi.groups().id(group.id).index());
    assertThat(thrown).hasMessageThat().contains("not allowed to index group");
  }

  @Test
  public void pushToGroupBranchIsRejectedForAllUsersRepo() throws Exception {
    assertPushToGroupBranch(
        allUsers, RefNames.refsGroups(adminGroupUuid()), "group update not allowed");
  }

  @Test
  public void pushToDeletedGroupBranchIsRejectedForAllUsersRepo() throws Exception {
    // refs/deleted-groups is only visible with ACCESS_DATABASE
    projectOperations
        .allProjectsForUpdate()
        .add(allowCapability(GlobalCapability.ACCESS_DATABASE).group(REGISTERED_USERS))
        .update();
    String groupRef =
        RefNames.refsDeletedGroups(AccountGroup.uuid(gApi.groups().create(name("foo")).get().id));
    createBranch(allUsers, groupRef);
    assertPushToGroupBranch(allUsers, groupRef, "group update not allowed");
  }

  @Test
  public void pushToGroupNamesBranchIsRejectedForAllUsersRepo() throws Exception {
    // refs/meta/group-names isn't usually available for fetch, so grant ACCESS_DATABASE
    projectOperations
        .allProjectsForUpdate()
        .add(allowCapability(GlobalCapability.ACCESS_DATABASE).group(REGISTERED_USERS))
        .update();
    assertPushToGroupBranch(allUsers, RefNames.REFS_GROUPNAMES, "group update not allowed");
  }

  @Test
  public void pushToGroupsBranchForNonAllUsersRepo() throws Exception {
    assertCreateGroupBranch(project);
    String groupRef =
        RefNames.refsGroups(AccountGroup.uuid(gApi.groups().create(name("foo")).get().id));
    createBranch(project, groupRef);
    assertPushToGroupBranch(project, groupRef, null);
  }

  @Test
  public void pushToDeletedGroupsBranchForNonAllUsersRepo() throws Exception {
    assertCreateGroupBranch(project);
    String groupRef =
        RefNames.refsDeletedGroups(AccountGroup.uuid(gApi.groups().create(name("foo")).get().id));
    createBranch(project, groupRef);
    assertPushToGroupBranch(project, groupRef, null);
  }

  @Test
  public void pushToGroupNamesBranchForNonAllUsersRepo() throws Exception {
    createBranch(project, RefNames.REFS_GROUPNAMES);
    assertPushToGroupBranch(project, RefNames.REFS_GROUPNAMES, null);
  }

  private void assertPushToGroupBranch(
      Project.NameKey project, String groupRefName, String expectedErrorOnUpdate) throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.CREATE).ref(RefNames.REFS_GROUPS + "*").group(REGISTERED_USERS))
        .add(allow(Permission.PUSH).ref(RefNames.REFS_GROUPS + "*").group(REGISTERED_USERS))
        .add(
            allow(Permission.CREATE)
                .ref(RefNames.REFS_DELETED_GROUPS + "*")
                .group(REGISTERED_USERS))
        .add(allow(Permission.PUSH).ref(RefNames.REFS_DELETED_GROUPS + "*").group(REGISTERED_USERS))
        .add(allow(Permission.PUSH).ref(RefNames.REFS_GROUPNAMES).group(REGISTERED_USERS))
        .update();

    TestRepository<InMemoryRepository> repo = cloneProject(project);

    // update existing branch
    fetch(repo, groupRefName + ":groupRef");
    repo.reset("groupRef");
    PushOneCommit.Result r =
        pushFactory
            .create(admin.newIdent(), repo, "Update group", "arbitraryFile.txt", "some content")
            .to(groupRefName);
    if (expectedErrorOnUpdate != null) {
      r.assertErrorStatus(expectedErrorOnUpdate);
    } else {
      r.assertOkStatus();
    }
  }

  private void assertCreateGroupBranch(Project.NameKey project) throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.CREATE).ref(RefNames.REFS_GROUPS + "*").group(REGISTERED_USERS))
        .add(allow(Permission.PUSH).ref(RefNames.REFS_GROUPS + "*").group(REGISTERED_USERS))
        .update();
    TestRepository<InMemoryRepository> repo = cloneProject(project);
    PushOneCommit.Result r =
        pushFactory
            .create(admin.newIdent(), repo, "Update group", "arbitraryFile.txt", "some content")
            .setParents(ImmutableList.of())
            .to(RefNames.REFS_GROUPS + name("bar"));
    r.assertOkStatus();
  }

  @Test
  public void pushToGroupBranchForReviewForAllUsersRepoIsRejectedOnSubmitForGroupFiles()
      throws Throwable {
    String error = "update to group files (group.config, members, subgroups) not allowed";
    pushToGroupBranchForReviewAndSubmit(
        allUsers, RefNames.refsGroups(adminGroupUuid()), "group.config", error);
    pushToGroupBranchForReviewAndSubmit(
        allUsers, RefNames.refsGroups(adminGroupUuid()), "members", error);
    pushToGroupBranchForReviewAndSubmit(
        allUsers, RefNames.refsGroups(adminGroupUuid()), "subgroups", error);
    pushToGroupBranchForReviewAndSubmit(
        allUsers, RefNames.refsGroups(adminGroupUuid()), "destinations/myreviews", null);
  }

  @Test
  public void pushToGroupBranchForReviewForNonAllUsersRepoAndSubmit() throws Throwable {
    String groupRef = RefNames.refsGroups(adminGroupUuid());
    createBranch(project, groupRef);
    pushToGroupBranchForReviewAndSubmit(project, groupRef, "group.config", null);
  }

  @Test
  public void pushCustomInheritanceForAllUsersFails() throws Exception {
    TestRepository<InMemoryRepository> repo = cloneProject(allUsers);
    GitUtil.fetch(repo, RefNames.REFS_CONFIG + ":" + RefNames.REFS_CONFIG);
    repo.reset(RefNames.REFS_CONFIG);
    String config =
        gApi.projects()
            .name(allUsers.get())
            .branch(RefNames.REFS_CONFIG)
            .file("project.config")
            .asString();

    Config cfg = new Config();
    cfg.fromText(config);
    cfg.setString("access", null, "inheritFrom", project.get());
    config = cfg.toText();

    PushOneCommit.Result r =
        pushFactory
            .create(admin.newIdent(), repo, "Subject", "project.config", config)
            .to(RefNames.REFS_CONFIG);
    r.assertErrorStatus("invalid project configuration");
    r.assertMessage("All-Users must inherit from All-Projects");
  }

  @Test
  public void cannotCreateGroupBranch() throws Exception {
    testCannotCreateGroupBranch(
        RefNames.REFS_GROUPS + "*", RefNames.refsGroups(AccountGroup.uuid(name("foo"))));
  }

  @Test
  public void cannotCreateDeletedGroupBranch() throws Exception {
    testCannotCreateGroupBranch(
        RefNames.REFS_DELETED_GROUPS + "*",
        RefNames.refsDeletedGroups(AccountGroup.uuid(name("foo"))));
  }

  @Test
  @IgnoreGroupInconsistencies
  public void cannotCreateGroupNamesBranch() throws Exception {
    // Use ProjectResetter to restore the group names ref
    try (ProjectResetter resetter =
        projectResetter
            .builder()
            .build(new ProjectResetter.Config().reset(allUsers, RefNames.REFS_GROUPNAMES))) {
      // Manually delete group names ref
      try (Repository repo = repoManager.openRepository(allUsers);
          RevWalk rw = new RevWalk(repo)) {
        RevCommit commit = rw.parseCommit(repo.exactRef(RefNames.REFS_GROUPNAMES).getObjectId());
        RefUpdate updateRef = repo.updateRef(RefNames.REFS_GROUPNAMES);
        updateRef.setExpectedOldObjectId(commit.toObjectId());
        updateRef.setNewObjectId(ObjectId.zeroId());
        updateRef.setForceUpdate(true);
        assertThat(updateRef.delete()).isEqualTo(RefUpdate.Result.FORCED);
      }

      // refs/meta/group-names is only visible with ACCESS_DATABASE
      projectOperations
          .allProjectsForUpdate()
          .add(allowCapability(GlobalCapability.ACCESS_DATABASE).group(REGISTERED_USERS))
          .update();

      testCannotCreateGroupBranch(RefNames.REFS_GROUPNAMES, RefNames.REFS_GROUPNAMES);
    }
  }

  private void testCannotCreateGroupBranch(String refPattern, String groupRef) throws Exception {
    projectOperations
        .project(allUsers)
        .forUpdate()
        .add(allow(Permission.CREATE).ref(refPattern).group(adminGroupUuid()))
        .add(allow(Permission.PUSH).ref(refPattern).group(adminGroupUuid()))
        .update();

    TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
    PushOneCommit.Result r = pushFactory.create(admin.newIdent(), allUsersRepo).to(groupRef);
    r.assertErrorStatus();
    assertThat(r.getMessage()).contains("Not allowed to create group branch.");

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

  @Test
  public void cannotDeleteGroupBranch() throws Exception {
    testCannotDeleteGroupBranch(RefNames.REFS_GROUPS + "*", RefNames.refsGroups(adminGroupUuid()));
  }

  @Test
  public void cannotDeleteDeletedGroupBranch() throws Exception {
    // refs/deleted-groups is only visible with ACCESS_DATABASE
    projectOperations
        .allProjectsForUpdate()
        .add(allowCapability(GlobalCapability.ACCESS_DATABASE).group(REGISTERED_USERS))
        .update();
    String groupRef = RefNames.refsDeletedGroups(AccountGroup.uuid(name("foo")));
    createBranch(allUsers, groupRef);
    testCannotDeleteGroupBranch(RefNames.REFS_DELETED_GROUPS + "*", groupRef);
  }

  @Test
  public void cannotDeleteGroupNamesBranch() throws Exception {
    // refs/meta/group-names is only visible with ACCESS_DATABASE
    projectOperations
        .allProjectsForUpdate()
        .add(allowCapability(GlobalCapability.ACCESS_DATABASE).group(REGISTERED_USERS))
        .update();

    testCannotDeleteGroupBranch(RefNames.REFS_GROUPNAMES, RefNames.REFS_GROUPNAMES);
  }

  private void testCannotDeleteGroupBranch(String refPattern, String groupRef) throws Exception {
    projectOperations
        .project(allUsers)
        .forUpdate()
        .add(allow(Permission.DELETE).ref(refPattern).group(REGISTERED_USERS).force(true))
        .update();

    TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
    PushResult r = deleteRef(allUsersRepo, groupRef);
    RemoteRefUpdate refUpdate = r.getRemoteUpdate(groupRef);
    assertThat(refUpdate.getStatus()).isEqualTo(RemoteRefUpdate.Status.REJECTED_OTHER_REASON);
    assertThat(refUpdate.getMessage()).contains("Not allowed to delete group branch.");

    try (Repository repo = repoManager.openRepository(allUsers)) {
      assertThat(repo.exactRef(groupRef)).isNotNull();
    }
  }

  @Test
  public void defaultPermissionsOnGroupBranches() throws Exception {
    assertPermissions(
        allUsers, groupRef(REGISTERED_USERS), RefNames.REFS_GROUPS + "*", true, Permission.READ);
  }

  @Test
  @IgnoreGroupInconsistencies
  public void stalenessChecker() throws Exception {
    // Newly created group is not stale
    GroupInfo groupInfo = gApi.groups().create(name("foo")).get();
    AccountGroup.UUID groupUuid = AccountGroup.uuid(groupInfo.id);
    assertThat(stalenessChecker.check(groupUuid).isStale()).isFalse();

    // Manual update makes index document stale
    String groupRef = RefNames.refsGroups(groupUuid);
    try (Repository repo = repoManager.openRepository(allUsers);
        RevWalk rw = new RevWalk(repo)) {
      RevCommit commit = rw.parseCommit(repo.exactRef(groupRef).getObjectId());
      ObjectId emptyCommit = createCommit(repo, commit.getFullMessage(), commit.getTree());
      RefUpdate updateRef = repo.updateRef(groupRef);
      updateRef.setExpectedOldObjectId(commit.toObjectId());
      updateRef.setNewObjectId(emptyCommit);
      assertThat(updateRef.forceUpdate()).isEqualTo(RefUpdate.Result.FORCED);
    }
    assertStaleGroupAndReindex(groupUuid);

    // Manually delete group
    try (Repository repo = repoManager.openRepository(allUsers);
        RevWalk rw = new RevWalk(repo)) {
      RevCommit commit = rw.parseCommit(repo.exactRef(groupRef).getObjectId());
      RefUpdate updateRef = repo.updateRef(groupRef);
      updateRef.setExpectedOldObjectId(commit.toObjectId());
      updateRef.setNewObjectId(ObjectId.zeroId());
      updateRef.setForceUpdate(true);
      assertThat(updateRef.delete()).isEqualTo(RefUpdate.Result.FORCED);
    }
    assertStaleGroupAndReindex(groupUuid);
  }

  @Test
  @Sandboxed
  public void groupsOfUserCanBeListedInSlaveMode() throws Exception {
    GroupInput groupInput = new GroupInput();
    groupInput.name = name("contributors");
    groupInput.members = ImmutableList.of(user.username());
    gApi.groups().create(groupInput).get();
    restartAsSlave();

    requestScopeOperations.setApiUser(user.id());
    List<GroupInfo> groups = gApi.groups().list().withUser(user.username()).get();
    ImmutableList<String> groupNames =
        groups.stream().map(group -> group.name).collect(toImmutableList());
    assertThat(groupNames).contains(groupInput.name);
  }

  @Test
  @Sandboxed
  @GerritConfig(name = "index.scheduledIndexer.enabled", value = "false")
  @GerritConfig(name = "index.autoReindexIfStale", value = "false")
  @IgnoreGroupInconsistencies
  public void reindexGroupsInSlaveMode() throws Exception {
    List<AccountGroup.UUID> expectedGroups =
        groups.getAllGroupReferences().map(GroupReference::getUUID).collect(toList());
    assertThat(expectedGroups.size()).isAtLeast(2);

    // Restart the server as slave, on startup of the slave all groups are indexed.
    restartAsSlave();

    GroupIndexedCounter groupIndexedCounter = new GroupIndexedCounter();
    try (Registration registration = extensionRegistry.newRegistration().add(groupIndexedCounter)) {
      // Running the reindexer right after startup should not need to reindex any group since
      // reindexing was already done on startup.
      slaveGroupIndexer.run();
      groupIndexedCounter.assertNoReindex();

      // Create a group without updating the cache or index,
      // then run the reindexer -> only the new group is reindexed.
      String groupName = "foo";
      AccountGroup.UUID groupUuid = AccountGroup.uuid(groupName + "-UUID");
      groupsUpdate.createGroupInNoteDb(
          InternalGroupCreation.builder()
              .setGroupUUID(groupUuid)
              .setNameKey(AccountGroup.nameKey(groupName))
              .setId(AccountGroup.id(seq.nextGroupId()))
              .build(),
          GroupDelta.builder().build());
      slaveGroupIndexer.run();
      groupIndexedCounter.assertReindexOf(groupUuid);

      // Update a group without updating the cache or index,
      // then run the reindexer -> only the updated group is reindexed.
      groupsUpdate.updateGroupInNoteDb(
          groupUuid, GroupDelta.builder().setDescription("bar").build());
      slaveGroupIndexer.run();
      groupIndexedCounter.assertReindexOf(groupUuid);

      // Delete a group  without updating the cache or index,
      // then run the reindexer -> only the deleted group is reindexed.
      try (Repository repo = repoManager.openRepository(allUsers)) {
        RefUpdate u = repo.updateRef(RefNames.refsGroups(groupUuid));
        u.setForceUpdate(true);
        assertThat(u.delete()).isEqualTo(RefUpdate.Result.FORCED);
      }
      slaveGroupIndexer.run();
      groupIndexedCounter.assertReindexOf(groupUuid);
    }
  }

  @Test
  @Sandboxed
  @GerritConfig(name = "index.scheduledIndexer.runOnStartup", value = "false")
  @GerritConfig(name = "index.scheduledIndexer.enabled", value = "false")
  @GerritConfig(name = "index.autoReindexIfStale", value = "false")
  @IgnoreGroupInconsistencies
  public void disabledReindexGroupsOnStartupSlaveMode() throws Exception {
    List<AccountGroup.UUID> expectedGroups =
        groups.getAllGroupReferences().map(GroupReference::getUUID).collect(toList());
    assertThat(expectedGroups.size()).isAtLeast(2);

    restartAsSlave();

    GroupIndexedCounter groupIndexedCounter = new GroupIndexedCounter();
    try (Registration registration = extensionRegistry.newRegistration().add(groupIndexedCounter)) {
      // No group indexing happened on startup. All groups should be reindexed now.
      slaveGroupIndexer.run();
      groupIndexedCounter.assertReindexOf(expectedGroups);
    }
  }

  private static Correspondence<AccountInfo, String> getAccountToUsernameCorrespondence() {
    return NullAwareCorrespondence.transforming(
        accountInfo -> accountInfo.username, "has username");
  }

  private void assertStaleGroupAndReindex(AccountGroup.UUID groupUuid) throws IOException {
    // Evict group from cache to be sure that we use the index state for staleness checks.
    groupCache.evict(groupUuid);
    assertThat(stalenessChecker.check(groupUuid).isStale()).isTrue();

    // Reindex fixes staleness
    groupIndexer.index(groupUuid);
    assertThat(stalenessChecker.check(groupUuid).isStale()).isFalse();
  }

  private void pushToGroupBranchForReviewAndSubmit(
      Project.NameKey project, String groupRef, String fileName, String expectedError)
      throws Throwable {
    projectOperations
        .project(project)
        .forUpdate()
        .add(
            allowLabel(LabelId.CODE_REVIEW)
                .ref(RefNames.REFS_GROUPS + "*")
                .group(REGISTERED_USERS)
                .range(-2, 2))
        .add(allow(Permission.SUBMIT).ref(RefNames.REFS_GROUPS + "*").group(REGISTERED_USERS))
        .update();

    TestRepository<InMemoryRepository> repo = cloneProject(project);
    fetch(repo, groupRef + ":groupRef");
    repo.reset("groupRef");

    PushOneCommit.Result r =
        pushFactory
            .create(admin.newIdent(), repo, "Update group config", fileName, "some content")
            .to(MagicBranch.NEW_CHANGE + groupRef);
    r.assertOkStatus();
    assertThat(r.getChange().change().getDest().branch()).isEqualTo(groupRef);
    gApi.changes().id(r.getChangeId()).current().review(ReviewInput.approve());

    ThrowingRunnable submit = () -> gApi.changes().id(r.getChangeId()).current().submit();
    if (expectedError != null) {
      Throwable thrown = assertThrows(ResourceConflictException.class, submit);
      assertThat(thrown).hasMessageThat().contains(expectedError);
    } else {
      submit.run();
    }
  }

  private void createBranch(Project.NameKey project, String ref) throws IOException {
    try (Repository r = repoManager.openRepository(project);
        ObjectInserter oi = r.newObjectInserter();
        RevWalk rw = new RevWalk(r)) {
      ObjectId emptyCommit = createCommit(r, "Test change");
      RefUpdate updateRef = r.updateRef(ref);
      updateRef.setExpectedOldObjectId(ObjectId.zeroId());
      updateRef.setNewObjectId(emptyCommit);
      assertThat(updateRef.update(rw)).isEqualTo(RefUpdate.Result.NEW);
    }
  }

  private ObjectId createCommit(Repository repo, String commitMessage) throws IOException {
    return createCommit(repo, commitMessage, null);
  }

  private ObjectId createCommit(Repository repo, String commitMessage, @Nullable ObjectId treeId)
      throws IOException {
    try (ObjectInserter oi = repo.newObjectInserter()) {
      if (treeId == null) {
        treeId = oi.insert(Constants.OBJ_TREE, new byte[] {});
      }

      PersonIdent ident = new PersonIdent(serverIdent.get(), TimeUtil.now());
      CommitBuilder cb = new CommitBuilder();
      cb.setTreeId(treeId);
      cb.setCommitter(ident);
      cb.setAuthor(ident);
      cb.setMessage(commitMessage);

      ObjectId commit = oi.insert(cb);
      oi.flush();
      return commit;
    }
  }

  private void assertMemberAuditEvent(
      GroupAuditEventInfo info,
      GroupAuditEventInfo.Type expectedType,
      Account.Id expectedUser,
      Account.Id expectedMember) {
    assertThat(info.user._accountId).isEqualTo(expectedUser.get());
    assertThat(info.type).isEqualTo(expectedType);
    assertThat(info).isInstanceOf(UserMemberAuditEventInfo.class);
    assertThat(((UserMemberAuditEventInfo) info).member._accountId).isEqualTo(expectedMember.get());
  }

  private void assertSubgroupAuditEvent(
      GroupAuditEventInfo info,
      GroupAuditEventInfo.Type expectedType,
      Account.Id expectedUser,
      String expectedMemberGroupName) {
    assertThat(info.user._accountId).isEqualTo(expectedUser.get());
    assertThat(info.type).isEqualTo(expectedType);
    assertThat(info).isInstanceOf(GroupMemberAuditEventInfo.class);
    assertThat(((GroupMemberAuditEventInfo) info).member.name).isEqualTo(expectedMemberGroupName);
  }

  private void assertMembers(String group, TestAccount... expectedMembers) throws Exception {
    assertMembers(
        gApi.groups().id(group).members(),
        TestAccount.names(expectedMembers).toArray(new String[0]));
    assertAccountInfos(Arrays.asList(expectedMembers), gApi.groups().id(group).members());
  }

  private void assertMembers(Iterable<AccountInfo> members, String... expectedNames) {
    assertThat(Iterables.transform(members, i -> i.name))
        .containsExactlyElementsIn(Arrays.asList(expectedNames))
        .inOrder();
  }

  private static void assertIncludes(List<GroupInfo> includes, String... expectedNames) {
    List<String> names = includes.stream().map(i -> i.name).collect(toImmutableList());
    assertThat(names).containsExactlyElementsIn(Arrays.asList(expectedNames));
    assertThat(names).isInOrder();
  }

  private void assertBadRequest(ListRequest req) throws Exception {
    assertThrows(BadRequestException.class, () -> req.get());
  }

  @Target({METHOD})
  @Retention(RUNTIME)
  private @interface IgnoreGroupInconsistencies {}

  /** Checks if a group is indexed the correct number of times. */
  private static class GroupIndexedCounter implements GroupIndexedListener {
    private final AtomicLongMap<String> countsByGroup = AtomicLongMap.create();

    @Override
    public void onGroupIndexed(String uuid) {
      countsByGroup.incrementAndGet(uuid);
    }

    void clear() {
      countsByGroup.clear();
    }

    void assertReindexOf(AccountGroup.UUID groupUuid) {
      assertReindexOf(ImmutableList.of(groupUuid));
    }

    void assertReindexOf(List<AccountGroup.UUID> groupUuids) {
      Map<String, Long> expected = groupUuids.stream().collect(toMap(u -> u.get(), u -> 1L));
      assertThat(countsByGroup.asMap()).containsExactlyEntriesIn(expected);
      clear();
    }

    void assertNoReindex() {
      assertThat(countsByGroup.asMap()).isEmpty();
    }
  }
}
