// Copyright (C) 2014 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.git;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.acceptance.GitUtil.fetch;
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.deny;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.permissionKey;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
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.ImmutableMap;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.GerritConfig;
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Patch;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.api.changes.DraftInput;
import com.google.gerrit.extensions.api.groups.GroupInput;
import com.google.gerrit.extensions.api.projects.BranchInput;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.git.receive.ReceiveCommitsAdvertiseRefsHookChain;
import com.google.gerrit.server.git.receive.testing.TestRefAdvertiser;
import com.google.gerrit.server.notedb.ChangeNoteUtil;
import com.google.gerrit.server.notedb.Sequences;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackend.RefFilterOptions;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.testing.ConfigSuite;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
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.transport.AdvertiseRefsHook;
import org.eclipse.jgit.transport.ReceivePack;
import org.junit.Before;
import org.junit.Test;

@NoHttpd
public class RefAdvertisementIT extends AbstractDaemonTest {
  @Inject private AllUsersName allUsersName;
  @Inject private ChangeNoteUtil noteUtil;
  @Inject private PermissionBackend permissionBackend;
  @Inject private ProjectOperations projectOperations;
  @Inject private RequestScopeOperations requestScopeOperations;

  private AccountGroup.UUID admins;
  private AccountGroup.UUID nonInteractiveUsers;

  private RevCommit rcMaster;
  private RevCommit rcBranch;

  private ChangeData cd1;
  private String psRef1;
  private String metaRef1;

  private ChangeData cd2;
  private String psRef2;
  private String metaRef2;

  private ChangeData cd3;
  private String psRef3;
  private String metaRef3;

  private ChangeData cd4;
  private String psRef4;
  private String metaRef4;

  @ConfigSuite.Config
  public static Config enableFullRefEvaluation() {
    Config cfg = new Config();
    cfg.setBoolean("auth", null, "skipFullRefEvaluationIfAllRefsAreVisible", false);
    return cfg;
  }

  @Before
  public void setUp() throws Exception {
    admins = adminGroupUuid();
    nonInteractiveUsers = groupUuid("Non-Interactive Users");
    setUpPermissions();
    setUpChanges();
  }

  // This method is idempotent, so it is safe to call it on every test setup.
  private void setUpPermissions() throws Exception {
    // Remove read permissions for all users besides admin.
    try (ProjectConfigUpdate u = updateProject(allProjects)) {
      for (AccessSection sec : u.getConfig().getAccessSections()) {
        sec.removePermission(Permission.READ);
      }
      u.save();
    }
    projectOperations
        .allProjectsForUpdate()
        .add(allow(Permission.READ).ref("refs/*").group(admins))
        .update();

    // Remove all read permissions on All-Users.
    try (ProjectConfigUpdate u = updateProject(allUsers)) {
      for (AccessSection sec : u.getConfig().getAccessSections()) {
        sec.removePermission(Permission.READ);
      }
      u.save();
    }
  }

  // Building the following:
  //   rcMaster (c1 master master-tag) <-- rcBranch (c2 branch branch-tag)
  //      \                                    \
  //    (c3_open)                            (c4_open)
  //
  private void setUpChanges() throws Exception {
    gApi.projects().name(project.get()).branch("branch").create(new BranchInput());

    // First 2 changes are merged, which means the tags pointing to them are
    // visible.
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.SUBMIT).ref("refs/for/refs/heads/*").group(admins))
        .update();

    //   rcMaster (c1 master)
    PushOneCommit.Result mr =
        pushFactory.create(admin.newIdent(), testRepo).to("refs/for/master%submit");
    mr.assertOkStatus();
    cd1 = mr.getChange();
    rcMaster = mr.getCommit();
    psRef1 = cd1.currentPatchSet().id().toRefName();
    metaRef1 = RefNames.changeMetaRef(cd1.getId());

    //   rcMaster (c1 master) <-- rcBranch (c2 branch)
    PushOneCommit.Result br =
        pushFactory.create(admin.newIdent(), testRepo).to("refs/for/branch%submit");
    br.assertOkStatus();
    cd2 = br.getChange();
    rcBranch = br.getCommit();
    psRef2 = cd2.currentPatchSet().id().toRefName();
    metaRef2 = RefNames.changeMetaRef(cd2.getId());

    // Second 2 changes are unmerged.
    //   rcMaster (c1 master) <-- rcBranch (c2 branch)
    //      \
    //    (c3_open)
    //
    mr = pushFactory.create(admin.newIdent(), testRepo).to("refs/for/master");
    mr.assertOkStatus();
    cd3 = mr.getChange();
    psRef3 = cd3.currentPatchSet().id().toRefName();
    metaRef3 = RefNames.changeMetaRef(cd3.getId());

    //   rcMaster (c1 master) <-- rcBranch (c2 branch)
    //      \                        \
    //     (c3_open)                (c4_open)
    br = pushFactory.create(admin.newIdent(), testRepo).to("refs/for/branch");
    br.assertOkStatus();
    cd4 = br.getChange();
    psRef4 = cd4.currentPatchSet().id().toRefName();
    metaRef4 = RefNames.changeMetaRef(cd4.getId());

    try (Repository repo = repoManager.openRepository(project)) {
      //   rcMaster (c1 master master-tag) <-- rcBranch (c2 branch)
      //       \                                  \
      //     (c3_open)                          (c4_open)
      RefUpdate mtu = repo.updateRef("refs/tags/master-tag");
      mtu.setExpectedOldObjectId(ObjectId.zeroId());
      mtu.setNewObjectId(repo.exactRef("refs/heads/master").getObjectId());
      assertThat(mtu.update()).isEqualTo(RefUpdate.Result.NEW);

      //   rcMaster (c1 master master-tag) <-- rcBranch (c2 branch branch-tag)
      //       \                                  \
      //     (c3_open)                          (c4_open)
      RefUpdate btu = repo.updateRef("refs/tags/branch-tag");
      btu.setExpectedOldObjectId(ObjectId.zeroId());
      btu.setNewObjectId(repo.exactRef("refs/heads/branch").getObjectId());
      assertThat(btu.update()).isEqualTo(RefUpdate.Result.NEW);

      // Create a tag for the tree of the commit on 'master'
      // tree-tag -> master.tree
      RefUpdate ttu = repo.updateRef("refs/tags/tree-tag");
      ttu.setExpectedOldObjectId(ObjectId.zeroId());
      ttu.setNewObjectId(rcMaster.getTree().toObjectId());
      assertThat(ttu.update()).isEqualTo(RefUpdate.Result.NEW);
    }
  }

  @Test
  @GerritConfig(name = "auth.skipFullRefEvaluationIfAllRefsAreVisible", value = "false")
  public void uploadPackAllRefsVisibleNoRefsMetaConfig() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/*").group(REGISTERED_USERS))
        .add(allow(Permission.READ).ref(RefNames.REFS_CONFIG).group(admins))
        .setExclusiveGroup(permissionKey(Permission.READ).ref(RefNames.REFS_CONFIG), true)
        .update();

    requestScopeOperations.setApiUser(user.id());
    assertUploadPackRefs(
        "HEAD",
        psRef1,
        metaRef1,
        psRef2,
        metaRef2,
        psRef3,
        metaRef3,
        psRef4,
        metaRef4,
        "refs/heads/branch",
        "refs/heads/master",
        "refs/tags/branch-tag",
        "refs/tags/master-tag");
    // tree-tag not visible. See comment in subsetOfBranchesVisibleIncludingHead.
  }

  @Test
  @GerritConfig(name = "auth.skipFullRefEvaluationIfAllRefsAreVisible", value = "true")
  public void uploadPackAllRefsVisibleNoRefsMetaConfigSkipFullRefEval() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/*").group(REGISTERED_USERS))
        .add(allow(Permission.READ).ref(RefNames.REFS_CONFIG).group(admins))
        .setExclusiveGroup(permissionKey(Permission.READ).ref(RefNames.REFS_CONFIG), true)
        .update();

    requestScopeOperations.setApiUser(user.id());
    assertUploadPackRefs(
        "HEAD",
        psRef1,
        metaRef1,
        psRef2,
        metaRef2,
        psRef3,
        metaRef3,
        psRef4,
        metaRef4,
        "refs/heads/branch",
        "refs/heads/master",
        "refs/tags/branch-tag",
        "refs/tags/master-tag",
        "refs/tags/tree-tag");
  }

  @Test
  public void uploadPackAllRefsVisibleWithRefsMetaConfig() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/*").group(REGISTERED_USERS))
        .add(allow(Permission.READ).ref(RefNames.REFS_CONFIG).group(REGISTERED_USERS))
        .update();

    assertUploadPackRefs(
        "HEAD",
        psRef1,
        metaRef1,
        psRef2,
        metaRef2,
        psRef3,
        metaRef3,
        psRef4,
        metaRef4,
        "refs/heads/branch",
        "refs/heads/master",
        RefNames.REFS_CONFIG,
        "refs/tags/branch-tag",
        "refs/tags/master-tag",
        "refs/tags/tree-tag");
  }

  @Test
  public void grantReadOnRefsTagsIsNoOp() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/tags/*").group(REGISTERED_USERS))
        .update();

    requestScopeOperations.setApiUser(user.id());
    assertUploadPackRefs(); // We expect no refs returned
  }

  @Test
  public void uploadPackSubsetOfBranchesVisibleIncludingHead() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/heads/master").group(REGISTERED_USERS))
        .add(deny(Permission.READ).ref("refs/heads/branch").group(REGISTERED_USERS))
        .update();

    requestScopeOperations.setApiUser(user.id());
    assertUploadPackRefs(
        "HEAD", psRef1, metaRef1, psRef3, metaRef3, "refs/heads/master", "refs/tags/master-tag");
    // tree-tag is not visible because we don't look at trees reachable from
    // refs
  }

  @Test
  public void uploadPackSubsetOfBranchesVisibleNotIncludingHead() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(deny(Permission.READ).ref("refs/heads/master").group(REGISTERED_USERS))
        .add(allow(Permission.READ).ref("refs/heads/branch").group(REGISTERED_USERS))
        .update();

    requestScopeOperations.setApiUser(user.id());
    assertUploadPackRefs(
        psRef2,
        metaRef2,
        psRef4,
        metaRef4,
        "refs/heads/branch",
        "refs/tags/branch-tag",
        // master branch is not visible but master-tag is reachable from branch
        // (since PushOneCommit always bases changes on each other).
        "refs/tags/master-tag");
    // tree-tag not visible. See comment in subsetOfBranchesVisibleIncludingHead.
  }

  @Test
  public void uploadPackSubsetOfBranchesVisibleWithEdit() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/heads/master").group(REGISTERED_USERS))
        .update();

    // Admin's edit is not visible.
    requestScopeOperations.setApiUser(admin.id());
    gApi.changes().id(cd3.getId().get()).edit().create();

    // User's edit is visible.
    requestScopeOperations.setApiUser(user.id());
    gApi.changes().id(cd3.getId().get()).edit().create();

    assertUploadPackRefs(
        "HEAD",
        psRef1,
        metaRef1,
        psRef3,
        metaRef3,
        "refs/heads/master",
        "refs/tags/master-tag",
        "refs/users/01/1000001/edit-" + cd3.getId() + "/1");
    // tree-tag not visible. See comment in subsetOfBranchesVisibleIncludingHead.
  }

  @Test
  public void uploadPackSubsetOfBranchesAndEditsVisibleWithViewPrivateChanges() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/heads/master").group(REGISTERED_USERS))
        .add(allow(Permission.VIEW_PRIVATE_CHANGES).ref("refs/*").group(REGISTERED_USERS))
        .update();

    // Admin's edit on change3 is visible.
    requestScopeOperations.setApiUser(admin.id());
    gApi.changes().id(cd3.getId().get()).edit().create();

    // Admin's edit on change4 is not visible since user cannot see the change.
    gApi.changes().id(cd4.getId().get()).edit().create();

    // User's edit is visible.
    requestScopeOperations.setApiUser(user.id());
    gApi.changes().id(cd3.getId().get()).edit().create();

    assertUploadPackRefs(
        "HEAD",
        psRef1,
        metaRef1,
        psRef3,
        metaRef3,
        "refs/heads/master",
        "refs/tags/master-tag",
        "refs/users/00/1000000/edit-" + cd3.getId() + "/1",
        "refs/users/01/1000001/edit-" + cd3.getId() + "/1");
    // tree-tag not visible. See comment in subsetOfBranchesVisibleIncludingHead.
  }

  @Test
  public void uploadPackSubsetOfRefsVisibleWithAccessDatabase() throws Exception {
    projectOperations
        .allProjectsForUpdate()
        .add(allowCapability(GlobalCapability.ACCESS_DATABASE).group(REGISTERED_USERS))
        .update();
    projectOperations
        .project(project)
        .forUpdate()
        .add(deny(Permission.READ).ref("refs/heads/master").group(REGISTERED_USERS))
        .add(allow(Permission.READ).ref("refs/heads/branch").group(REGISTERED_USERS))
        .update();

    requestScopeOperations.setApiUser(admin.id());
    gApi.changes().id(cd3.getId().get()).edit().create();
    requestScopeOperations.setApiUser(user.id());

    assertUploadPackRefs(
        // Change 1 is visible due to accessDatabase capability, even though
        // refs/heads/master is not.
        psRef1,
        metaRef1,
        psRef2,
        metaRef2,
        psRef3,
        metaRef3,
        psRef4,
        metaRef4,
        "refs/heads/branch",
        "refs/tags/branch-tag",
        // See comment in subsetOfBranchesVisibleNotIncludingHead.
        "refs/tags/master-tag",
        // All edits are visible due to accessDatabase capability.
        "refs/users/00/1000000/edit-" + cd3.getId() + "/1");
    // tree-tag not visible. See comment in subsetOfBranchesVisibleIncludingHead.
  }

  @Test
  public void uploadPackNoSearchingChangeCacheImplMaster() throws Exception {
    uploadPackNoSearchingChangeCacheImpl();
  }

  @Test
  @GerritConfig(name = "container.slave", value = "true")
  public void uploadPackNoSearchingChangeCacheImplSlave() throws Exception {
    uploadPackNoSearchingChangeCacheImpl();
  }

  private void uploadPackNoSearchingChangeCacheImpl() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/heads/*").group(REGISTERED_USERS))
        .update();

    requestScopeOperations.setApiUser(user.id());
    assertRefs(
        project,
        user,
        // Can't use stored values from the index so DB must be enabled.
        false,
        "HEAD",
        psRef1,
        metaRef1,
        psRef2,
        metaRef2,
        psRef3,
        metaRef3,
        psRef4,
        metaRef4,
        "refs/heads/branch",
        "refs/heads/master",
        "refs/tags/branch-tag",
        "refs/tags/master-tag");
    // tree-tag not visible. See comment in subsetOfBranchesVisibleIncludingHead.
  }

  @Test
  public void uploadPackSequencesWithAccessDatabase() throws Exception {
    assertRefs(allProjects, user, true);

    projectOperations
        .allProjectsForUpdate()
        .add(allowCapability(GlobalCapability.ACCESS_DATABASE).group(REGISTERED_USERS))
        .update();
    assertRefs(allProjects, user, true, "refs/sequences/changes");
  }

  @Test
  public void uploadPackAllRefsAreVisibleOrphanedTag() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/*").group(REGISTERED_USERS))
        .update();
    // Delete the pending change on 'branch' and 'branch' itself so that the tag gets orphaned
    gApi.changes().id(cd4.getId().get()).delete();
    gApi.projects().name(project.get()).branch("refs/heads/branch").delete();

    requestScopeOperations.setApiUser(user.id());
    assertUploadPackRefs(
        "HEAD",
        "refs/meta/config",
        psRef1,
        metaRef1,
        psRef2,
        metaRef2,
        psRef3,
        metaRef3,
        "refs/heads/master",
        "refs/tags/branch-tag",
        "refs/tags/master-tag",
        "refs/tags/tree-tag");
  }

  @Test
  public void uploadPackSubsetRefsVisibleOrphanedTagInvisible() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/heads/branch").group(REGISTERED_USERS))
        .update();
    // Create a tag for the pending change on 'branch' so that the tag is orphaned
    try (Repository repo = repoManager.openRepository(project)) {
      // change4-tag -> psRef4
      RefUpdate ctu = repo.updateRef("refs/tags/change4-tag");
      ctu.setExpectedOldObjectId(ObjectId.zeroId());
      ctu.setNewObjectId(repo.exactRef(psRef4).getObjectId());
      assertThat(ctu.update()).isEqualTo(RefUpdate.Result.NEW);
    }

    requestScopeOperations.setApiUser(user.id());
    assertUploadPackRefs(
        psRef2,
        metaRef2,
        psRef4,
        metaRef4,
        "refs/heads/branch",
        "refs/tags/branch-tag",
        // See comment in subsetOfBranchesVisibleNotIncludingHead.
        "refs/tags/master-tag");
  }

  // first  ls-remote: rcMaster (c1 master)
  // second ls-remote: rcMaster (c1 master) <- newchange1 (master-newtag)
  @Test
  public void uploadPackNewCommitOrphanTagInvisible() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/heads/branch").group(REGISTERED_USERS))
        .update();

    requestScopeOperations.setApiUser(user.id());

    // rcMaster (c1 master)
    assertUploadPackRefs(
        psRef2,
        metaRef2,
        psRef4,
        metaRef4,
        "refs/heads/branch",
        "refs/tags/branch-tag",
        // See comment in subsetOfBranchesVisibleNotIncludingHead.
        "refs/tags/master-tag");

    try (Repository repo = repoManager.openRepository(project)) {
      PushOneCommit.Result r =
          pushFactory.create(admin.newIdent(), testRepo).setParent(rcMaster).to("refs/for/master");
      r.assertOkStatus();

      // rcMaster (c1 master) <- newchange1 (master-newtag)
      RefUpdate btu = repo.updateRef("refs/tags/master-newtag");
      btu.setExpectedOldObjectId(ObjectId.zeroId());
      btu.setNewObjectId(r.getCommit());
      assertThat(btu.update()).isEqualTo(RefUpdate.Result.NEW);
    }

    assertUploadPackRefs(
        psRef2,
        metaRef2,
        psRef4,
        metaRef4,
        "refs/heads/branch",
        "refs/tags/branch-tag",
        // See comment in subsetOfBranchesVisibleNotIncludingHead.
        "refs/tags/master-tag");
  }

  // first  ls-remote: rcBranch (c2) <- newcommit1                 <- newcommit2 (branch)
  // second ls-remote: rcBranch (c2) <- newcommit1 (branch-newtag) <- newcommit2 (branch)
  @Test
  public void uploadPackNewReachableTagVisible() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/heads/branch").group(REGISTERED_USERS))
        .update();

    requestScopeOperations.setApiUser(user.id());

    try (Repository repo = repoManager.openRepository(project)) {
      // c2 <- newcommit1 (branch)
      PushOneCommit.Result r =
          pushFactory
              .create(admin.newIdent(), testRepo)
              .setParent(rcBranch)
              .to("refs/heads/branch");
      r.assertOkStatus();
      RevCommit tagRc = r.getCommit();

      // c2 <- newcommit1 <- newcommit2 (branch)
      r = pushFactory.create(admin.newIdent(), testRepo).setParent(tagRc).to("refs/heads/branch");
      r.assertOkStatus();

      assertUploadPackRefs(
          psRef2,
          metaRef2,
          psRef4,
          metaRef4,
          "refs/heads/branch",
          "refs/tags/branch-tag",
          // See comment in subsetOfBranchesVisibleNotIncludingHead.
          "refs/tags/master-tag");

      // c2 <- newcommit1 (branch-newtag) <- newcommit2 (branch)
      RefUpdate btu = repo.updateRef("refs/tags/branch-newtag");
      btu.setExpectedOldObjectId(ObjectId.zeroId());
      btu.setNewObjectId(tagRc);
      assertThat(btu.update()).isEqualTo(RefUpdate.Result.NEW);
    }

    assertUploadPackRefs(
        psRef2,
        metaRef2,
        psRef4,
        metaRef4,
        "refs/heads/branch",
        "refs/tags/branch-tag",
        "refs/tags/branch-newtag",
        // See comment in subsetOfBranchesVisibleNotIncludingHead.
        "refs/tags/master-tag");
  }

  // first  ls-remote: rcBranch (c2) <- newcommit1 (branch)
  // second ls-remote: rcBranch (c2) <- newcommit1                 <- newcommit2 (branch)
  // third  ls-remote: rcBranch (c2) <- newcommit1 (branch-newtag) <- newcommit2 (branch)
  @Test
  public void uploadPackBranchFFNewTagOldBranchVisible() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/heads/branch").group(REGISTERED_USERS))
        .update();

    requestScopeOperations.setApiUser(user.id());

    try (Repository repo = repoManager.openRepository(project)) {
      // rcBranch (c2) <- newcommit1 (branch)
      PushOneCommit.Result r =
          pushFactory
              .create(admin.newIdent(), testRepo)
              .setParent(rcBranch)
              .to("refs/heads/branch");
      r.assertOkStatus();
      RevCommit tagRc = r.getCommit();

      assertUploadPackRefs(
          psRef2,
          metaRef2,
          psRef4,
          metaRef4,
          "refs/heads/branch",
          "refs/tags/branch-tag",
          // See comment in subsetOfBranchesVisibleNotIncludingHead.
          "refs/tags/master-tag");

      // rcBranch (c2) <- newcommit1 <- newcommit2 (branch)
      r = pushFactory.create(admin.newIdent(), testRepo).setParent(tagRc).to("refs/heads/branch");
      r.assertOkStatus();

      // rcBranch (c2) <- newcommit1 (branch-newtag) <- newcommit2 (branch)
      RefUpdate btu = repo.updateRef("refs/tags/branch-newtag");
      btu.setExpectedOldObjectId(ObjectId.zeroId());
      btu.setNewObjectId(tagRc);
      assertThat(btu.update()).isEqualTo(RefUpdate.Result.NEW);
    }

    assertUploadPackRefs(
        psRef2,
        metaRef2,
        psRef4,
        metaRef4,
        "refs/heads/branch",
        "refs/tags/branch-tag",
        "refs/tags/branch-newtag",
        // See comment in subsetOfBranchesVisibleNotIncludingHead.
        "refs/tags/master-tag");
  }

  // first  ls-remote: rcBranch (c2)        <- newcommit1 (branch-oldtag) <- newcommit2 (branch)
  // second ls-remote: rcBranch (c2 branch) <- newcommit1 (branch-oldtag)
  @Test
  public void uploadPackBranchRewindMakeTagUnreachableInVisible() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/heads/branch").group(REGISTERED_USERS))
        .update();

    requestScopeOperations.setApiUser(user.id());

    try (Repository repo = repoManager.openRepository(project)) {
      // rcBranch (c2) <- newcommit1 (branch)
      PushOneCommit.Result r =
          pushFactory
              .create(admin.newIdent(), testRepo)
              .setParent(rcBranch)
              .to("refs/heads/branch");
      r.assertOkStatus();
      RevCommit tagRc = r.getCommit();

      // rcBranch (c2) <- newcommit1 <- newcommit2 (branch)
      r = pushFactory.create(admin.newIdent(), testRepo).setParent(tagRc).to("refs/heads/branch");
      r.assertOkStatus();
      RevCommit bRc = r.getCommit();

      // rcBranch (c2) <- newcommit1 (branch-oldtag) <- newcommit2 (branch)
      RefUpdate btu = repo.updateRef("refs/tags/branch-oldtag");
      btu.setExpectedOldObjectId(ObjectId.zeroId());
      btu.setNewObjectId(tagRc);
      assertThat(btu.update()).isEqualTo(RefUpdate.Result.NEW);

      assertUploadPackRefs(
          psRef2,
          metaRef2,
          psRef4,
          metaRef4,
          "refs/heads/branch",
          "refs/tags/branch-tag",
          "refs/tags/branch-oldtag",
          // See comment in subsetOfBranchesVisibleNotIncludingHead.
          "refs/tags/master-tag");

      // rcBranch (c2 branch) <- newcommit1 (branch-oldtag) <- newcommit2
      btu = repo.updateRef("refs/heads/branch");
      btu.setExpectedOldObjectId(bRc);
      btu.setNewObjectId(rcBranch);
      btu.setForceUpdate(true);
      assertThat(btu.update()).isEqualTo(RefUpdate.Result.FORCED);
    }

    assertUploadPackRefs(
        psRef2,
        metaRef2,
        psRef4,
        metaRef4,
        "refs/heads/branch",
        "refs/tags/branch-tag",
        // See comment in subsetOfBranchesVisibleNotIncludingHead.
        "refs/tags/master-tag");
  }

  // first  ls-remote: rcBranch (c2 branch) <- newcommit1 (new-tag)
  // second ls-remote: rcBranch (c2 branch) <- newcommit1 (new-tag) <- newcommit2 (new-branch)
  @Test
  public void uploadPackCreateBranchTagReachableVisible() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/heads/new-branch").group(REGISTERED_USERS))
        .add(allow(Permission.PUSH).ref("refs/tags/*").group(REGISTERED_USERS))
        .update();

    requestScopeOperations.setApiUser(user.id());

    try (Repository repo = repoManager.openRepository(project)) {
      // rcBranch (c2 branch) <- newcommit1 (branch-newtag)
      PushOneCommit.Result r =
          pushFactory
              .create(admin.newIdent(), testRepo)
              .setParent(rcBranch)
              .to("refs/tags/new-tag");
      r.assertOkStatus();
      RevCommit tagRc = r.getCommit();

      assertUploadPackRefs();

      // rcBranch (c2) <- newcommit1 (branch-newtag) <- newcommit2 (branch)
      r =
          pushFactory
              .create(admin.newIdent(), testRepo)
              .setParent(tagRc)
              .to("refs/heads/new-branch");
      r.assertOkStatus();
    }

    assertUploadPackRefs(
        "refs/heads/new-branch",
        "refs/tags/branch-tag",
        "refs/tags/master-tag",
        "refs/tags/new-tag");
  }

  // first  ls-remote: rcBranch (c2 branch)               <- newcommit1 (updated-tag)
  // second ls-remote: rcBranch (c2 branch updated-tag)
  @Test
  public void uploadPackTagUpdatedReachableVisible() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/heads/branch").group(REGISTERED_USERS))
        .add(allow(Permission.PUSH).ref("refs/tags/*").group(REGISTERED_USERS))
        .update();

    requestScopeOperations.setApiUser(user.id());

    try (Repository repo = repoManager.openRepository(project)) {
      // rcBranch (c2 branch) <- newcommit1 (updated-tag)
      PushOneCommit.Result r =
          pushFactory
              .create(admin.newIdent(), testRepo)
              .setParent(rcBranch)
              .to("refs/tags/updated-tag");
      r.assertOkStatus();
      RevCommit tagRc = r.getCommit();

      assertUploadPackRefs(
          psRef2,
          metaRef2,
          psRef4,
          metaRef4,
          "refs/heads/branch",
          "refs/tags/branch-tag",
          "refs/tags/master-tag");

      // rcBranch (c2 branch updated-tag)
      RefUpdate btu = repo.updateRef("refs/tags/updated-tag");
      btu.setExpectedOldObjectId(tagRc);
      btu.setNewObjectId(rcBranch);
      btu.setForceUpdate(true);
      assertThat(btu.update()).isEqualTo(RefUpdate.Result.FORCED);
    }

    assertUploadPackRefs(
        psRef2,
        metaRef2,
        psRef4,
        metaRef4,
        "refs/heads/branch",
        "refs/tags/branch-tag",
        "refs/tags/master-tag",
        "refs/tags/updated-tag");
  }

  // first  ls-remote: rcBranch (c2 branch updated-tag)
  // second ls-remote: rcBranch (c2 branch)             <- newcommit1 (updated-tag)
  @Test
  public void uploadPackTagUpdatedUnreachableInvisible() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/heads/branch").group(REGISTERED_USERS))
        .add(allow(Permission.PUSH).ref("refs/tags/*").group(REGISTERED_USERS))
        .update();

    requestScopeOperations.setApiUser(user.id());

    try (Repository repo = repoManager.openRepository(project)) {
      // rcBranch (c2 branch updated-tag)
      RefUpdate btu = repo.updateRef("refs/tags/updated-tag");
      btu.setExpectedOldObjectId(ObjectId.zeroId());
      btu.setNewObjectId(rcBranch);
      assertThat(btu.update()).isEqualTo(RefUpdate.Result.NEW);

      assertUploadPackRefs(
          psRef2,
          metaRef2,
          psRef4,
          metaRef4,
          "refs/heads/branch",
          "refs/tags/branch-tag",
          "refs/tags/master-tag",
          "refs/tags/updated-tag");

      // rcBranch (c2 branch) <- newcommit1 (updated-tag)
      PushOneCommit.Result r =
          pushFactory
              .create(admin.newIdent(), testRepo)
              .setParent(rcBranch)
              .to("refs/tags/updated-tag");
      r.assertOkStatus();
    }

    assertUploadPackRefs(
        psRef2,
        metaRef2,
        psRef4,
        metaRef4,
        "refs/heads/branch",
        "refs/tags/branch-tag",
        "refs/tags/master-tag");
  }

  // first  ls-remote: rcBranch (c2 branch branch-tag)
  // second ls-remote: rcBranch (c2 branch)
  @Test
  public void uploadPackTagDeleted() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/heads/branch").group(REGISTERED_USERS))
        .add(allow(Permission.DELETE).ref("refs/tags/branch-tag").group(REGISTERED_USERS))
        .add(allow(Permission.PUSH).ref("refs/tags/branch-tag").group(REGISTERED_USERS))
        .update();

    requestScopeOperations.setApiUser(user.id());

    // rcBranch (c2 branch branch-tag)
    assertUploadPackRefs(
        psRef2,
        metaRef2,
        psRef4,
        metaRef4,
        "refs/heads/branch",
        "refs/tags/branch-tag",
        "refs/tags/master-tag");

    // rcBranch (c2 branch)
    try (Repository repo = repoManager.openRepository(project)) {
      RefUpdate btu = repo.updateRef("refs/tags/branch-tag");
      btu.setExpectedOldObjectId(rcBranch);
      btu.setNewObjectId(ObjectId.zeroId());
      btu.setForceUpdate(true);
      assertThat(btu.delete()).isEqualTo(RefUpdate.Result.FORCED);
    }

    assertUploadPackRefs(
        psRef2, metaRef2, psRef4, metaRef4, "refs/heads/branch", "refs/tags/master-tag");
  }

  // first  ls-remote: rcBranch (c2 branch) <- newcommit1 (new-tag) <- newcommit2 (new-branch)
  // second ls-remote: rcBranch (c2 branch) <- newcommit1 (new-tag)
  @Test
  public void uploadPackBranchDeleteTagUnreachableInvisible() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/heads/branch").group(REGISTERED_USERS))
        .add(allow(Permission.READ).ref("refs/heads/new-branch").group(REGISTERED_USERS))
        .add(allow(Permission.DELETE).ref("refs/heads/new-branch").group(REGISTERED_USERS))
        .add(allow(Permission.PUSH).ref("refs/tags/*").group(REGISTERED_USERS))
        .update();

    requestScopeOperations.setApiUser(user.id());

    try (Repository repo = repoManager.openRepository(project)) {
      // rcBranch (branch) <- newcommit1 (new-tag)
      PushOneCommit.Result r =
          pushFactory
              .create(admin.newIdent(), testRepo)
              .setParent(rcBranch)
              .to("refs/tags/new-tag");
      r.assertOkStatus();
      RevCommit tagRc = r.getCommit();

      // rcBranch (c2 branch) <- newcommit1 (new-tag) <- newcommit2 (new-branch)
      r =
          pushFactory
              .create(admin.newIdent(), testRepo)
              .setParent(tagRc)
              .to("refs/heads/new-branch");
      r.assertOkStatus();
    }

    assertUploadPackRefs(
        psRef2,
        metaRef2,
        psRef4,
        metaRef4,
        "refs/heads/branch",
        "refs/tags/branch-tag",
        "refs/heads/new-branch",
        "refs/tags/new-tag",
        "refs/tags/master-tag");

    // rcBranch (c2 branch) <- newcommit1 (new-tag)
    gApi.projects().name(project.get()).branch("refs/heads/new-branch").delete();

    assertUploadPackRefs(
        psRef2,
        metaRef2,
        psRef4,
        metaRef4,
        "refs/heads/branch",
        "refs/tags/branch-tag",
        "refs/tags/master-tag");
  }

  @Test
  public void receivePackListsOpenChangesAsAdditionalHaves() throws Exception {
    TestRefAdvertiser.Result r = getReceivePackRefs();
    assertThat(r.allRefs().keySet())
        .containsExactly(
            // meta refs are excluded
            "refs/heads/branch",
            "refs/heads/master",
            "refs/meta/config",
            "refs/tags/branch-tag",
            "refs/tags/master-tag",
            "refs/tags/tree-tag");
    assertThat(r.additionalHaves()).containsExactly(obj(cd3, 1), obj(cd4, 1));
  }

  @Test
  public void receivePackRespectsVisibilityOfOpenChanges() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/heads/master").group(REGISTERED_USERS))
        .add(deny(Permission.READ).ref("refs/heads/branch").group(REGISTERED_USERS))
        .update();
    requestScopeOperations.setApiUser(user.id());

    assertThat(getReceivePackRefs().additionalHaves()).containsExactly(obj(cd3, 1));
  }

  @Test
  public void receivePackListsOnlyLatestPatchSet() throws Exception {
    testRepo.reset(obj(cd3, 1));
    PushOneCommit.Result r = amendChange(cd3.change().getKey().get());
    r.assertOkStatus();
    cd3 = r.getChange();
    assertThat(getReceivePackRefs().additionalHaves()).containsExactly(obj(cd3, 2), obj(cd4, 1));
  }

  @Test
  public void receivePackOmitsMissingObject() throws Exception {
    String rev = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
    try (Repository repo = repoManager.openRepository(project);
        TestRepository<Repository> tr = new TestRepository<>(repo)) {
      String subject = "Subject for missing commit";
      Change c = new Change(cd3.change());
      PatchSet.Id psId = PatchSet.id(cd3.getId(), 2);
      c.setCurrentPatchSet(psId, subject, c.getOriginalSubject());

      PersonIdent committer = serverIdent.get();
      PersonIdent author =
          noteUtil.newIdent(getAccount(admin.id()), committer.getWhen(), committer);
      tr.branch(RefNames.changeMetaRef(cd3.getId()))
          .commit()
          .author(author)
          .committer(committer)
          .message(
              "Update patch set "
                  + psId.get()
                  + "\n"
                  + "\n"
                  + "Patch-set: "
                  + psId.get()
                  + "\n"
                  + "Commit: "
                  + rev
                  + "\n"
                  + "Subject: "
                  + subject
                  + "\n")
          .create();
      indexer.index(c.getProject(), c.getId());
    }

    assertThat(getReceivePackRefs().additionalHaves()).containsExactly(obj(cd4, 1));
  }

  @Test
  public void advertisedReferencesDontShowUserBranchWithoutRead() throws Exception {
    TestRepository<?> userTestRepository = cloneProject(allUsers, user);
    try (Git git = userTestRepository.git()) {
      assertThat(getUserRefs(git)).isEmpty();
    }
  }

  @Test
  public void advertisedReferencesOmitUserBranchesOfOtherUsers() throws Exception {
    projectOperations
        .project(allUsersName)
        .forUpdate()
        .add(allow(Permission.READ).ref(RefNames.REFS_USERS + "*").group(REGISTERED_USERS))
        .update();
    TestRepository<?> userTestRepository = cloneProject(allUsers, user);
    try (Git git = userTestRepository.git()) {
      assertThat(getUserRefs(git))
          .containsExactly(RefNames.REFS_USERS_SELF, RefNames.refsUsers(user.id()));
    }
  }

  @Test
  public void advertisedReferencesIncludeAllUserBranchesWithAccessDatabase() throws Exception {
    projectOperations
        .allProjectsForUpdate()
        .add(allowCapability(GlobalCapability.ACCESS_DATABASE).group(REGISTERED_USERS))
        .update();
    TestRepository<?> userTestRepository = cloneProject(allUsers, user);
    try (Git git = userTestRepository.git()) {
      assertThat(getUserRefs(git))
          .containsExactly(
              RefNames.REFS_USERS_SELF,
              RefNames.refsUsers(user.id()),
              RefNames.refsUsers(admin.id()));
    }
  }

  @Test
  public void advertisedReferencesDontShowGroupBranchToOwnerWithoutRead() throws Exception {
    createSelfOwnedGroup("Foos", user);
    TestRepository<?> userTestRepository = cloneProject(allUsers, user);
    try (Git git = userTestRepository.git()) {
      assertThat(getGroupRefs(git)).isEmpty();
    }
  }

  @Test
  public void advertisedReferencesOmitGroupBranchesOfNonOwnedGroups() throws Exception {
    projectOperations
        .project(allUsersName)
        .forUpdate()
        .add(allow(Permission.READ).ref(RefNames.REFS_GROUPS + "*").group(REGISTERED_USERS))
        .update();
    AccountGroup.UUID users = createGroup("Users", admins, user);
    AccountGroup.UUID foos = createGroup("Foos", users);
    AccountGroup.UUID bars = createSelfOwnedGroup("Bars", user);
    TestRepository<?> userTestRepository = cloneProject(allUsers, user);
    try (Git git = userTestRepository.git()) {
      assertThat(getGroupRefs(git))
          .containsExactly(RefNames.refsGroups(foos), RefNames.refsGroups(bars));
    }
  }

  @Test
  public void advertisedReferencesIncludeAllGroupBranchesWithAccessDatabase() throws Exception {
    projectOperations
        .allProjectsForUpdate()
        .add(allowCapability(GlobalCapability.ACCESS_DATABASE).group(REGISTERED_USERS))
        .update();
    AccountGroup.UUID users = createGroup("Users", admins);
    TestRepository<?> userTestRepository = cloneProject(allUsers, user);
    try (Git git = userTestRepository.git()) {
      assertThat(getGroupRefs(git))
          .containsExactly(
              RefNames.refsGroups(admins),
              RefNames.refsGroups(nonInteractiveUsers),
              RefNames.refsGroups(users));
    }
  }

  @Test
  public void advertisedReferencesIncludeAllGroupBranchesForAdmins() throws Exception {
    projectOperations
        .project(allUsersName)
        .forUpdate()
        .add(allow(Permission.READ).ref(RefNames.REFS_GROUPS + "*").group(REGISTERED_USERS))
        .update();
    projectOperations
        .allProjectsForUpdate()
        .add(allowCapability(GlobalCapability.ADMINISTRATE_SERVER).group(REGISTERED_USERS))
        .update();
    AccountGroup.UUID users = createGroup("Users", admins);
    TestRepository<?> userTestRepository = cloneProject(allUsers, user);
    try (Git git = userTestRepository.git()) {
      assertThat(getGroupRefs(git))
          .containsExactly(
              RefNames.refsGroups(admins),
              RefNames.refsGroups(nonInteractiveUsers),
              RefNames.refsGroups(users));
    }
  }

  @Test
  public void advertisedReferencesOmitNoteDbNotesBranches() throws Exception {
    projectOperations
        .project(allUsersName)
        .forUpdate()
        .add(allow(Permission.READ).ref(RefNames.REFS + "*").group(REGISTERED_USERS))
        .update();
    TestRepository<?> userTestRepository = cloneProject(allUsers, user);
    try (Git git = userTestRepository.git()) {
      assertThat(getRefs(git)).containsNoneOf(RefNames.REFS_EXTERNAL_IDS, RefNames.REFS_GROUPNAMES);
    }
  }

  @Test
  public void advertisedReferencesOmitPrivateChangesOfOtherUsers() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/heads/master").group(REGISTERED_USERS))
        .update();

    TestRepository<?> userTestRepository = cloneProject(project, user);
    try (Git git = userTestRepository.git()) {
      String change3RefName = cd3.currentPatchSet().refName();
      assertWithMessage("Precondition violated").that(getRefs(git)).contains(change3RefName);

      gApi.changes().id(cd3.getId().get()).setPrivate(true, null);
      assertThat(getRefs(git)).doesNotContain(change3RefName);
    }
  }

  @Test
  public void advertisedReferencesIncludePrivateChangesWhenAllRefsMayBeRead() throws Exception {
    assume()
        .that(baseConfig.getBoolean("auth", "skipFullRefEvaluationIfAllRefsAreVisible", true))
        .isTrue();
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/*").group(REGISTERED_USERS))
        .update();

    TestRepository<?> userTestRepository = cloneProject(project, user);
    try (Git git = userTestRepository.git()) {
      String change3RefName = cd3.currentPatchSet().refName();
      assertWithMessage("Precondition violated").that(getRefs(git)).contains(change3RefName);

      gApi.changes().id(cd3.getId().get()).setPrivate(true, null);
      assertThat(getRefs(git)).contains(change3RefName);
    }
  }

  @Test
  @GerritConfig(name = "auth.skipFullRefEvaluationIfAllRefsAreVisible", value = "false")
  public void advertisedReferencesOmitPrivateChangesOfOtherUsersWhenShortcutDisabled()
      throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/*").group(REGISTERED_USERS))
        .update();

    TestRepository<?> userTestRepository = cloneProject(project, user);
    try (Git git = userTestRepository.git()) {
      String change3RefName = cd3.currentPatchSet().refName();
      assertWithMessage("Precondition violated").that(getRefs(git)).contains(change3RefName);

      gApi.changes().id(cd3.getId().get()).setPrivate(true, null);
      assertThat(getRefs(git)).doesNotContain(change3RefName);
    }
  }

  @Test
  public void advertisedReferencesOmitDraftCommentRefsOfOtherUsers() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/*").group(REGISTERED_USERS))
        .update();
    projectOperations
        .project(allUsersName)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/*").group(REGISTERED_USERS))
        .update();

    requestScopeOperations.setApiUser(user.id());
    DraftInput draftInput = new DraftInput();
    draftInput.line = 1;
    draftInput.message = "nit: trailing whitespace";
    draftInput.path = Patch.COMMIT_MSG;
    gApi.changes().id(cd3.getId().get()).current().createDraft(draftInput);
    String draftCommentRef = RefNames.refsDraftComments(cd3.getId(), user.id());

    // user can see the draft comment ref of the own draft comment
    assertThat(lsRemote(allUsersName, user)).contains(draftCommentRef);

    // user2 can't see the draft comment ref of user's draft comment
    assertThat(lsRemote(allUsersName, accountCreator.user2())).doesNotContain(draftCommentRef);
  }

  @Test
  public void advertisedReferencesOmitStarredChangesRefsOfOtherUsers() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/*").group(REGISTERED_USERS))
        .update();
    projectOperations
        .project(allUsersName)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/*").group(REGISTERED_USERS))
        .update();

    requestScopeOperations.setApiUser(user.id());
    gApi.accounts().self().starChange(cd3.getId().toString());
    String starredChangesRef = RefNames.refsStarredChanges(cd3.getId(), user.id());

    // user can see the starred changes ref of the own star
    assertThat(lsRemote(allUsersName, user)).contains(starredChangesRef);

    // user2 can't see the starred changes ref of admin's star
    assertThat(lsRemote(allUsersName, accountCreator.user2())).doesNotContain(starredChangesRef);
  }

  @Test
  public void hideMetadata() throws Exception {
    projectOperations
        .allProjectsForUpdate()
        .add(allowCapability(GlobalCapability.ACCESS_DATABASE).group(REGISTERED_USERS))
        .update();
    // create change
    TestRepository<?> allUsersRepo = cloneProject(allUsers);
    fetch(allUsersRepo, RefNames.REFS_USERS_SELF + ":userRef");
    allUsersRepo.reset("userRef");
    PushOneCommit.Result mr =
        pushFactory
            .create(admin.newIdent(), allUsersRepo)
            .to("refs/for/" + RefNames.REFS_USERS_SELF);
    mr.assertOkStatus();

    List<String> expectedNonMetaRefs =
        ImmutableList.of(
            RefNames.refsUsers(admin.id()),
            RefNames.refsUsers(user.id()),
            RefNames.REFS_EXTERNAL_IDS,
            RefNames.REFS_GROUPNAMES,
            RefNames.refsGroups(admins),
            RefNames.refsGroups(nonInteractiveUsers),
            RefNames.REFS_SEQUENCES + Sequences.NAME_ACCOUNTS,
            RefNames.REFS_SEQUENCES + Sequences.NAME_GROUPS,
            RefNames.REFS_CONFIG,
            Constants.HEAD);

    List<String> expectedMetaRefs =
        new ArrayList<>(ImmutableList.of(mr.getPatchSetId().toRefName()));
    expectedMetaRefs.add(RefNames.changeMetaRef(mr.getChange().getId()));

    List<String> expectedAllRefs = new ArrayList<>(expectedNonMetaRefs);
    expectedAllRefs.addAll(expectedMetaRefs);

    try (Repository repo = repoManager.openRepository(allUsers)) {
      Map<String, Ref> all = getAllRefs(repo);

      PermissionBackend.ForProject forProject = newFilter(allUsers, admin);
      assertThat(forProject.filter(all, repo, RefFilterOptions.defaults()).keySet())
          .containsExactlyElementsIn(expectedAllRefs);
      assertThat(
              forProject
                  .filter(all, repo, RefFilterOptions.builder().setFilterMeta(true).build())
                  .keySet())
          .containsExactlyElementsIn(expectedNonMetaRefs);
    }
  }

  @Test
  public void fetchSingleChangeWithoutIndexAccess() throws Exception {
    PushOneCommit.Result change = createChange();
    String patchSetRef = change.getPatchSetId().toRefName();
    try (AutoCloseable ignored = disableChangeIndex();
        Repository repo = repoManager.openRepository(project)) {
      Map<String, Ref> singleRef = ImmutableMap.of(patchSetRef, repo.exactRef(patchSetRef));
      Map<String, Ref> filteredRefs =
          permissionBackend
              .user(user(admin))
              .project(project)
              .filter(singleRef, repo, RefFilterOptions.defaults());
      assertThat(filteredRefs).isEqualTo(singleRef);
    }
  }

  private List<String> lsRemote(Project.NameKey p, TestAccount a) throws Exception {
    TestRepository<?> testRepository = cloneProject(p, a);
    try (Git git = testRepository.git()) {
      return git.lsRemote().call().stream().map(Ref::getName).collect(toList());
    }
  }

  private List<String> getRefs(Git git) throws Exception {
    return getRefs(git, x -> true);
  }

  private List<String> getUserRefs(Git git) throws Exception {
    return getRefs(git, RefNames::isRefsUsers);
  }

  private List<String> getGroupRefs(Git git) throws Exception {
    return getRefs(git, RefNames::isRefsGroups);
  }

  private List<String> getRefs(Git git, Predicate<String> predicate) throws Exception {
    return git.lsRemote().call().stream().map(Ref::getName).filter(predicate).collect(toList());
  }

  /**
   * Assert that refs seen by a non-admin user match the expected refs.
   *
   * @param expectedRefs expected refs.
   * @throws Exception
   */
  private void assertUploadPackRefs(String... expectedRefs) throws Exception {
    assertRefs(project, user, true, expectedRefs);
  }

  private void assertRefs(
      Project.NameKey project, TestAccount user, boolean disableDb, String... expectedRefs)
      throws Exception {
    AutoCloseable ctx = null;
    if (disableDb) {
      ctx = disableNoteDb();
    }
    try {
      assertThat(lsRemote(project, user)).containsExactlyElementsIn(expectedRefs);
    } finally {
      if (disableDb) {
        ctx.close();
      }
    }
  }

  private TestRefAdvertiser.Result getReceivePackRefs() throws Exception {
    try (Repository repo = repoManager.openRepository(project)) {
      AdvertiseRefsHook adv =
          ReceiveCommitsAdvertiseRefsHookChain.createForTest(
              queryProvider, project, identifiedUserFactory.create(admin.id()));
      ReceivePack rp = new ReceivePack(repo);
      rp.setAdvertiseRefsHook(adv);
      TestRefAdvertiser advertiser = new TestRefAdvertiser(repo);
      rp.sendAdvertisedRefs(advertiser);
      return advertiser.result();
    }
  }

  private PermissionBackend.ForProject newFilter(Project.NameKey project, TestAccount u) {
    return permissionBackend.user(user(u)).project(project);
  }

  private static ObjectId obj(ChangeData cd, int psNum) throws Exception {
    PatchSet.Id psId = PatchSet.id(cd.getId(), psNum);
    PatchSet ps = cd.patchSet(psId);
    assertWithMessage("%s not found in %s", psId, cd.patchSets()).that(ps).isNotNull();
    return ps.commitId();
  }

  private AccountGroup.UUID createSelfOwnedGroup(String name, TestAccount... members)
      throws RestApiException {
    return createGroup(name, null, members);
  }

  private AccountGroup.UUID createGroup(
      String name, @Nullable AccountGroup.UUID ownerGroup, TestAccount... members)
      throws RestApiException {
    GroupInput groupInput = new GroupInput();
    groupInput.name = name(name);
    groupInput.ownerId = ownerGroup != null ? ownerGroup.get() : null;
    groupInput.members =
        Arrays.stream(members).map(m -> String.valueOf(m.id().get())).collect(toList());
    return AccountGroup.uuid(gApi.groups().create(groupInput).get().id);
  }

  private static Map<String, Ref> getAllRefs(Repository repo) throws IOException {
    return repo.getRefDatabase().getRefs().stream()
        .collect(toMap(Ref::getName, Function.identity()));
  }
}
