// 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.server.group.SystemGroupBackend.REGISTERED_USERS;

import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.AcceptanceTestRequestScope;
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.PushOneCommit;
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.extensions.api.projects.BranchInput;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.config.AnonymousCowardName;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.git.ReceiveCommitsAdvertiseRefsHook;
import com.google.gerrit.server.git.SearchingChangeCacheImpl;
import com.google.gerrit.server.git.TagCache;
import com.google.gerrit.server.git.VisibleRefFilter;
import com.google.gerrit.server.notedb.ChangeNoteUtil;
import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.server.project.Util;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.testutil.DisabledReviewDb;
import com.google.gerrit.testutil.TestChanges;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.eclipse.jgit.junit.TestRepository;
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.junit.Before;
import org.junit.Test;

@NoHttpd
public class RefAdvertisementIT extends AbstractDaemonTest {
  @Inject private ProjectControl.GenericFactory projectControlFactory;

  @Inject @Nullable private SearchingChangeCacheImpl changeCache;

  @Inject private TagCache tagCache;

  @Inject private Provider<CurrentUser> userProvider;

  @Inject private ChangeNoteUtil noteUtil;

  @Inject @AnonymousCowardName private String anonymousCowardName;

  private AccountGroup.UUID admins;

  private ChangeData c1;
  private ChangeData c2;
  private ChangeData c3;
  private ChangeData c4;
  private String r1;
  private String r2;
  private String r3;
  private String r4;

  @Before
  public void setUp() throws Exception {
    admins = groupCache.get(new AccountGroup.NameKey("Administrators")).getGroupUUID();
    setUpPermissions();
    setUpChanges();
  }

  private void setUpPermissions() throws Exception {
    // Remove read permissions for all users besides admin. This method is
    // idempotent, so is safe to call on every test setup.
    ProjectConfig pc = projectCache.checkedGet(allProjects).getConfig();
    for (AccessSection sec : pc.getAccessSections()) {
      sec.removePermission(Permission.READ);
    }
    Util.allow(pc, Permission.READ, admins, "refs/*");
    saveProjectConfig(allProjects, pc);
  }

  private static String changeRefPrefix(Change.Id id) {
    String ps = new PatchSet.Id(id, 1).toRefName();
    return ps.substring(0, ps.length() - 1);
  }

  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.
    allow(Permission.SUBMIT, admins, "refs/for/refs/heads/*");
    PushOneCommit.Result mr =
        pushFactory.create(db, admin.getIdent(), testRepo).to("refs/for/master%submit");
    mr.assertOkStatus();
    c1 = mr.getChange();
    r1 = changeRefPrefix(c1.getId());
    PushOneCommit.Result br =
        pushFactory.create(db, admin.getIdent(), testRepo).to("refs/for/branch%submit");
    br.assertOkStatus();
    c2 = br.getChange();
    r2 = changeRefPrefix(c2.getId());

    // Second 2 changes are unmerged.
    mr = pushFactory.create(db, admin.getIdent(), testRepo).to("refs/for/master");
    mr.assertOkStatus();
    c3 = mr.getChange();
    r3 = changeRefPrefix(c3.getId());
    br = pushFactory.create(db, admin.getIdent(), testRepo).to("refs/for/branch");
    br.assertOkStatus();
    c4 = br.getChange();
    r4 = changeRefPrefix(c4.getId());

    try (Repository repo = repoManager.openRepository(project)) {
      // master-tag -> master
      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);

      // branch-tag -> branch
      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);
    }
  }

  @Test
  public void uploadPackAllRefsVisibleNoRefsMetaConfig() throws Exception {
    ProjectConfig cfg = projectCache.checkedGet(project).getConfig();
    Util.allow(cfg, Permission.READ, REGISTERED_USERS, "refs/*");
    Util.allow(cfg, Permission.READ, admins, RefNames.REFS_CONFIG);
    Util.doNotInherit(cfg, Permission.READ, RefNames.REFS_CONFIG);
    saveProjectConfig(project, cfg);

    setApiUser(user);
    assertUploadPackRefs(
        "HEAD",
        r1 + "1",
        r1 + "meta",
        r2 + "1",
        r2 + "meta",
        r3 + "1",
        r3 + "meta",
        r4 + "1",
        r4 + "meta",
        "refs/heads/branch",
        "refs/heads/master",
        "refs/tags/branch-tag",
        "refs/tags/master-tag");
  }

  @Test
  public void uploadPackAllRefsVisibleWithRefsMetaConfig() throws Exception {
    allow(Permission.READ, REGISTERED_USERS, "refs/*");
    allow(Permission.READ, REGISTERED_USERS, RefNames.REFS_CONFIG);

    assertUploadPackRefs(
        "HEAD",
        r1 + "1",
        r1 + "meta",
        r2 + "1",
        r2 + "meta",
        r3 + "1",
        r3 + "meta",
        r4 + "1",
        r4 + "meta",
        "refs/heads/branch",
        "refs/heads/master",
        RefNames.REFS_CONFIG,
        "refs/tags/branch-tag",
        "refs/tags/master-tag");
  }

  @Test
  public void uploadPackSubsetOfBranchesVisibleIncludingHead() throws Exception {
    allow(Permission.READ, REGISTERED_USERS, "refs/heads/master");
    deny(Permission.READ, REGISTERED_USERS, "refs/heads/branch");

    setApiUser(user);
    assertUploadPackRefs(
        "HEAD",
        r1 + "1",
        r1 + "meta",
        r3 + "1",
        r3 + "meta",
        "refs/heads/master",
        "refs/tags/master-tag");
  }

  @Test
  public void uploadPackSubsetOfBranchesVisibleNotIncludingHead() throws Exception {
    deny(Permission.READ, REGISTERED_USERS, "refs/heads/master");
    allow(Permission.READ, REGISTERED_USERS, "refs/heads/branch");

    setApiUser(user);
    assertUploadPackRefs(
        r2 + "1",
        r2 + "meta",
        r4 + "1",
        r4 + "meta",
        "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");
  }

  @Test
  public void uploadPackSubsetOfBranchesVisibleWithEdit() throws Exception {
    allow(Permission.READ, REGISTERED_USERS, "refs/heads/master");
    deny(Permission.READ, REGISTERED_USERS, "refs/heads/branch");

    Change c = notesFactory.createChecked(db, project, c1.getId()).getChange();
    String changeId = c.getKey().get();

    // Admin's edit is not visible.
    setApiUser(admin);
    gApi.changes().id(changeId).edit().create();

    // User's edit is visible.
    setApiUser(user);
    gApi.changes().id(changeId).edit().create();

    assertUploadPackRefs(
        "HEAD",
        r1 + "1",
        r1 + "meta",
        r3 + "1",
        r3 + "meta",
        "refs/heads/master",
        "refs/tags/master-tag",
        "refs/users/01/1000001/edit-" + c1.getId() + "/1");
  }

  @Test
  public void uploadPackSubsetOfRefsVisibleWithAccessDatabase() throws Exception {
    allowGlobalCapabilities(REGISTERED_USERS, GlobalCapability.ACCESS_DATABASE);
    try {
      deny(Permission.READ, REGISTERED_USERS, "refs/heads/master");
      allow(Permission.READ, REGISTERED_USERS, "refs/heads/branch");

      String changeId = c1.change().getKey().get();
      setApiUser(admin);
      gApi.changes().id(changeId).edit().create();
      setApiUser(user);

      assertUploadPackRefs(
          // Change 1 is visible due to accessDatabase capability, even though
          // refs/heads/master is not.
          r1 + "1",
          r1 + "meta",
          r2 + "1",
          r2 + "meta",
          r3 + "1",
          r3 + "meta",
          r4 + "1",
          r4 + "meta",
          "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-" + c1.getId() + "/1");
    } finally {
      removeGlobalCapabilities(REGISTERED_USERS, GlobalCapability.ACCESS_DATABASE);
    }
  }

  @Test
  public void uploadPackDraftRefs() throws Exception {
    allow(Permission.READ, REGISTERED_USERS, "refs/heads/*");

    PushOneCommit.Result br =
        pushFactory.create(db, admin.getIdent(), testRepo).to("refs/drafts/master");
    br.assertOkStatus();
    Change.Id c5 = br.getChange().getId();
    String r5 = changeRefPrefix(c5);

    // Only admin can see admin's draft change (5).
    setApiUser(admin);
    assertUploadPackRefs(
        "HEAD",
        r1 + "1",
        r1 + "meta",
        r2 + "1",
        r2 + "meta",
        r3 + "1",
        r3 + "meta",
        r4 + "1",
        r4 + "meta",
        r5 + "1",
        r5 + "meta",
        "refs/heads/branch",
        "refs/heads/master",
        RefNames.REFS_CONFIG,
        "refs/tags/branch-tag",
        "refs/tags/master-tag");

    // user can't.
    setApiUser(user);
    assertUploadPackRefs(
        "HEAD",
        r1 + "1",
        r1 + "meta",
        r2 + "1",
        r2 + "meta",
        r3 + "1",
        r3 + "meta",
        r4 + "1",
        r4 + "meta",
        "refs/heads/branch",
        "refs/heads/master",
        "refs/tags/branch-tag",
        "refs/tags/master-tag");
  }

  @Test
  public void uploadPackNoSearchingChangeCacheImpl() throws Exception {
    allow(Permission.READ, REGISTERED_USERS, "refs/heads/*");

    setApiUser(user);
    try (Repository repo = repoManager.openRepository(project)) {
      assertRefs(
          repo,
          new VisibleRefFilter(tagCache, notesFactory, null, repo, projectControl(), db, true),
          // Can't use stored values from the index so DB must be enabled.
          false,
          "HEAD",
          r1 + "1",
          r1 + "meta",
          r2 + "1",
          r2 + "meta",
          r3 + "1",
          r3 + "meta",
          r4 + "1",
          r4 + "meta",
          "refs/heads/branch",
          "refs/heads/master",
          "refs/tags/branch-tag",
          "refs/tags/master-tag");
    }
  }

  @Test
  public void uploadPackSequencesWithAccessDatabase() throws Exception {
    assume().that(notesMigration.readChangeSequence()).isTrue();
    try (Repository repo = repoManager.openRepository(allProjects)) {
      setApiUser(user);
      assertRefs(repo, newFilter(db, repo, allProjects), true);

      allowGlobalCapabilities(REGISTERED_USERS, GlobalCapability.ACCESS_DATABASE);
      try {
        setApiUser(user);
        assertRefs(repo, newFilter(db, repo, allProjects), true, "refs/sequences/changes");
      } finally {
        removeGlobalCapabilities(REGISTERED_USERS, GlobalCapability.ACCESS_DATABASE);
      }
    }
  }

  @Test
  public void receivePackListsOpenChangesAsAdditionalHaves() throws Exception {
    ReceiveCommitsAdvertiseRefsHook.Result r = getReceivePackRefs();
    assertThat(r.allRefs().keySet())
        .containsExactly(
            // meta refs are excluded even when NoteDb is enabled.
            "HEAD",
            "refs/heads/branch",
            "refs/heads/master",
            "refs/meta/config",
            "refs/tags/branch-tag",
            "refs/tags/master-tag");
    assertThat(r.additionalHaves()).containsExactly(obj(c3, 1), obj(c4, 1));
  }

  @Test
  public void receivePackRespectsVisibilityOfOpenChanges() throws Exception {
    allow(Permission.READ, REGISTERED_USERS, "refs/heads/master");
    deny(Permission.READ, REGISTERED_USERS, "refs/heads/branch");
    setApiUser(user);

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

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

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

      if (notesMigration.changePrimaryStorage() == PrimaryStorage.REVIEW_DB) {
        PatchSet ps = TestChanges.newPatchSet(psId, rev, admin.getId());
        db.patchSets().insert(Collections.singleton(ps));
        db.changes().update(Collections.singleton(c));
      }

      if (notesMigration.commitChangeWrites()) {
        PersonIdent committer = serverIdent.get();
        PersonIdent author =
            noteUtil.newIdent(
                accountCache.get(admin.getId()).getAccount(),
                committer.getWhen(),
                committer,
                anonymousCowardName);
        tr.branch(RefNames.changeMetaRef(c3.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(db, c.getProject(), c.getId());
    }

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

  /**
   * Assert that refs seen by a non-admin user match expected.
   *
   * @param expectedWithMeta expected refs, in order. If NoteDb is disabled by the configuration,
   *     any NoteDb refs (i.e. ending in "/meta") are removed from the expected list before
   *     comparing to the actual results.
   * @throws Exception
   */
  private void assertUploadPackRefs(String... expectedWithMeta) throws Exception {
    try (Repository repo = repoManager.openRepository(project)) {
      assertRefs(
          repo,
          new VisibleRefFilter(
              tagCache,
              notesFactory,
              changeCache,
              repo,
              projectControl(),
              new DisabledReviewDb(),
              true),
          true,
          expectedWithMeta);
    }
  }

  private void assertRefs(
      Repository repo, VisibleRefFilter filter, boolean disableDb, String... expectedWithMeta)
      throws Exception {
    List<String> expected = new ArrayList<>(expectedWithMeta.length);
    for (String r : expectedWithMeta) {
      if (notesMigration.writeChanges() || !r.endsWith(RefNames.META_SUFFIX)) {
        expected.add(r);
      }
    }

    AcceptanceTestRequestScope.Context ctx = null;
    if (disableDb) {
      ctx = disableDb();
    }
    try {
      Map<String, Ref> all = repo.getAllRefs();
      assertThat(filter.filter(all, false).keySet()).containsExactlyElementsIn(expected);
    } finally {
      if (disableDb) {
        enableDb(ctx);
      }
    }
  }

  private ReceiveCommitsAdvertiseRefsHook.Result getReceivePackRefs() throws Exception {
    ReceiveCommitsAdvertiseRefsHook hook =
        new ReceiveCommitsAdvertiseRefsHook(queryProvider, project);
    try (Repository repo = repoManager.openRepository(project)) {
      return hook.advertiseRefs(repo.getAllRefs());
    }
  }

  private ProjectControl projectControl() throws Exception {
    return projectControlFactory.controlFor(project, userProvider.get());
  }

  private VisibleRefFilter newFilter(ReviewDb db, Repository repo, Project.NameKey project)
      throws Exception {
    return new VisibleRefFilter(
        tagCache,
        notesFactory,
        null,
        repo,
        projectControlFactory.controlFor(project, userProvider.get()),
        db,
        true);
  }

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