// 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.server.git;

import static com.google.common.truth.Truth.assertThat;

import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.SortedSetMultimap;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;

import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevSort;
import org.eclipse.jgit.revwalk.RevWalk;
import org.junit.Before;
import org.junit.Test;

public class GroupCollectorTest {
  private TestRepository<?> tr;

  @Before
  public void setUp() throws Exception {
    tr = new TestRepository<>(
        new InMemoryRepository(new DfsRepositoryDescription("repo")));
  }

  @Test
  public void commitWhoseParentIsUninterestingGetsNewGroup() throws Exception {
    RevCommit branchTip = tr.commit().create();
    RevCommit a = tr.commit().parent(branchTip).create();

    SortedSetMultimap<ObjectId, String> groups = collectGroups(
        newWalk(a, branchTip),
        patchSets(),
        groups());

    assertThat(groups).containsEntry(a, a.name());
  }

  @Test
  public void commitWhoseParentIsNewPatchSetGetsParentsGroup()
      throws Exception {
    RevCommit branchTip = tr.commit().create();
    RevCommit a = tr.commit().parent(branchTip).create();
    RevCommit b = tr.commit().parent(a).create();

    SortedSetMultimap<ObjectId, String> groups = collectGroups(
        newWalk(b, branchTip),
        patchSets(),
        groups());

    assertThat(groups).containsEntry(a, a.name());
    assertThat(groups).containsEntry(b, a.name());
  }

  @Test
  public void commitWhoseParentIsExistingPatchSetGetsParentsGroup()
      throws Exception {
    RevCommit branchTip = tr.commit().create();
    RevCommit a = tr.commit().parent(branchTip).create();
    RevCommit b = tr.commit().parent(a).create();

    String group = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
    SortedSetMultimap<ObjectId, String> groups = collectGroups(
        newWalk(b, branchTip),
        patchSets().put(a, psId(1, 1)),
        groups().put(psId(1, 1), group));

    assertThat(groups).containsEntry(a, group);
    assertThat(groups).containsEntry(b, group);
  }

  @Test
  public void commitWhoseParentIsExistingPatchSetWithNoGroup()
      throws Exception {
    RevCommit branchTip = tr.commit().create();
    RevCommit a = tr.commit().parent(branchTip).create();
    RevCommit b = tr.commit().parent(a).create();

    SortedSetMultimap<ObjectId, String> groups = collectGroups(
        newWalk(b, branchTip),
        patchSets().put(a, psId(1, 1)),
        groups());

    assertThat(groups).containsEntry(a, a.name());
    assertThat(groups).containsEntry(b, a.name());
  }

  @Test
  public void mergeCommitAndNewParentsAllGetSameGroup() throws Exception {
    RevCommit branchTip = tr.commit().create();
    RevCommit a = tr.commit().parent(branchTip).create();
    RevCommit b = tr.commit().parent(branchTip).create();
    RevCommit m = tr.commit().parent(a).parent(b).create();

    SortedSetMultimap<ObjectId, String> groups = collectGroups(
        newWalk(m, branchTip),
        patchSets(),
        groups());

    assertThat(groups).containsEntry(a, a.name());
    assertThat(groups).containsEntry(b, a.name());
    assertThat(groups).containsEntry(m, a.name());
  }

  @Test
  public void mergeCommitWhereOneParentHasExistingGroup() throws Exception {
    RevCommit branchTip = tr.commit().create();
    RevCommit a = tr.commit().parent(branchTip).create();
    RevCommit b = tr.commit().parent(branchTip).create();
    RevCommit m = tr.commit().parent(a).parent(b).create();

    String group = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
    SortedSetMultimap<ObjectId, String> groups = collectGroups(
        newWalk(m, branchTip),
        patchSets().put(b, psId(1, 1)),
        groups().put(psId(1, 1), group));

    // Merge commit and other parent get the existing group.
    assertThat(groups).containsEntry(a, group);
    assertThat(groups).containsEntry(b, group);
    assertThat(groups).containsEntry(m, group);
  }

  @Test
  public void mergeCommitWhereBothParentsHaveDifferentGroups()
      throws Exception {
    RevCommit branchTip = tr.commit().create();
    RevCommit a = tr.commit().parent(branchTip).create();
    RevCommit b = tr.commit().parent(branchTip).create();
    RevCommit m = tr.commit().parent(a).parent(b).create();

    String group1 = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
    String group2 = "1234567812345678123456781234567812345678";
    SortedSetMultimap<ObjectId, String> groups = collectGroups(
        newWalk(m, branchTip),
        patchSets()
            .put(a, psId(1, 1))
            .put(b, psId(2, 1)),
        groups()
            .put(psId(1, 1), group1)
            .put(psId(2, 1), group2));

    assertThat(groups).containsEntry(a, group1);
    assertThat(groups).containsEntry(b, group2);
    // Merge commit gets joined group of parents.
    assertThat(groups.asMap())
        .containsEntry(m, ImmutableSet.of(group1, group2));
  }

  @Test
  public void mergeCommitMergesGroupsFromParent() throws Exception {
    RevCommit branchTip = tr.commit().create();
    RevCommit a = tr.commit().parent(branchTip).create();
    RevCommit b = tr.commit().parent(branchTip).create();
    RevCommit m = tr.commit().parent(a).parent(b).create();

    String group1 = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
    String group2a = "1234567812345678123456781234567812345678";
    String group2b = "ef123456ef123456ef123456ef123456ef123456";
    SortedSetMultimap<ObjectId, String> groups = collectGroups(
        newWalk(m, branchTip),
        patchSets()
            .put(a, psId(1, 1))
            .put(b, psId(2, 1)),
        groups()
            .put(psId(1, 1), group1)
            .put(psId(2, 1), group2a)
            .put(psId(2, 1), group2b));

    assertThat(groups).containsEntry(a, group1);
    assertThat(groups.asMap())
        .containsEntry(b, ImmutableSet.of(group2a, group2b));
    // Joined parent groups are split and resorted.
    assertThat(groups.asMap())
        .containsEntry(m, ImmutableSet.of(group1, group2a, group2b));
  }

  @Test
  public void mergeCommitWithOneUninterestingParentAndOtherParentIsExisting()
      throws Exception {
    RevCommit branchTip = tr.commit().create();
    RevCommit a = tr.commit().parent(branchTip).create();
    RevCommit m = tr.commit().parent(branchTip).parent(a).create();

    String group = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
    SortedSetMultimap<ObjectId, String> groups = collectGroups(
        newWalk(m, branchTip),
        patchSets().put(a, psId(1, 1)),
        groups().put(psId(1, 1), group));

    assertThat(groups).containsEntry(a, group);
    assertThat(groups).containsEntry(m, group);
  }

  @Test
  public void mergeCommitWithOneUninterestingParentAndOtherParentIsNew()
      throws Exception {
    RevCommit branchTip = tr.commit().create();
    RevCommit a = tr.commit().parent(branchTip).create();
    RevCommit m = tr.commit().parent(branchTip).parent(a).create();

    SortedSetMultimap<ObjectId, String> groups = collectGroups(
        newWalk(m, branchTip),
        patchSets(),
        groups());

    assertThat(groups).containsEntry(a, a.name());
    assertThat(groups).containsEntry(m, a.name());
  }

  @Test
  public void multipleMergeCommitsInHistoryAllResolveToSameGroup()
      throws Exception {
    RevCommit branchTip = tr.commit().create();
    RevCommit a = tr.commit().parent(branchTip).create();
    RevCommit b = tr.commit().parent(branchTip).create();
    RevCommit c = tr.commit().parent(branchTip).create();
    RevCommit m1 = tr.commit().parent(b).parent(c).create();
    RevCommit m2 = tr.commit().parent(a).parent(m1).create();

    SortedSetMultimap<ObjectId, String> groups = collectGroups(
        newWalk(m2, branchTip),
        patchSets(),
        groups());

    assertThat(groups).containsEntry(a, a.name());
    assertThat(groups).containsEntry(b, a.name());
    assertThat(groups).containsEntry(c, a.name());
    assertThat(groups).containsEntry(m1, a.name());
    assertThat(groups).containsEntry(m2, a.name());
  }

  @Test
  public void mergeCommitWithDuplicatedParentGetsParentsGroup()
      throws Exception {
    RevCommit branchTip = tr.commit().create();
    RevCommit a = tr.commit().parent(branchTip).create();
    RevCommit m = tr.commit().parent(a).parent(a).create();
    tr.getRevWalk().parseBody(m);
    assertThat(m.getParentCount()).isEqualTo(2);
    assertThat(m.getParent(0)).isEqualTo(m.getParent(1));

    SortedSetMultimap<ObjectId, String> groups = collectGroups(
        newWalk(m, branchTip),
        patchSets(),
        groups());

    assertThat(groups).containsEntry(a, a.name());
    assertThat(groups).containsEntry(m, a.name());
  }

  @Test
  public void mergeCommitWithOneNewParentAndTwoExistingPatchSets()
      throws Exception {
    RevCommit branchTip = tr.commit().create();
    RevCommit a = tr.commit().parent(branchTip).create();
    RevCommit b = tr.commit().parent(branchTip).create();
    RevCommit c = tr.commit().parent(b).create();
    RevCommit m = tr.commit().parent(a).parent(c).create();

    String group1 = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
    String group2 = "1234567812345678123456781234567812345678";
    SortedSetMultimap<ObjectId, String> groups = collectGroups(
        newWalk(m, branchTip),
        patchSets()
            .put(a, psId(1, 1))
            .put(b, psId(2, 1)),
        groups()
            .put(psId(1, 1), group1)
            .put(psId(2, 1), group2));

    assertThat(groups).containsEntry(a, group1);
    assertThat(groups).containsEntry(b, group2);
    assertThat(groups).containsEntry(c, group2);
    assertThat(groups.asMap())
        .containsEntry(m, ImmutableSet.of(group1, group2));
  }

  @Test
  public void collectGroupsForMultipleTipsInParallel() throws Exception {
    RevCommit branchTip = tr.commit().create();
    RevCommit a = tr.commit().parent(branchTip).create();
    RevCommit b = tr.commit().parent(a).create();
    RevCommit c = tr.commit().parent(branchTip).create();
    RevCommit d = tr.commit().parent(c).create();

    RevWalk rw = newWalk(b, branchTip);
    rw.markStart(rw.parseCommit(d));
    // Schema upgrade case: all commits are existing patch sets, but none have
    // groups assigned yet.
    SortedSetMultimap<ObjectId, String> groups = collectGroups(
        rw,
        patchSets()
            .put(branchTip, psId(1, 1))
            .put(a, psId(2, 1))
            .put(b, psId(3, 1))
            .put(c, psId(4, 1))
            .put(d, psId(5, 1)),
        groups());

    assertThat(groups).containsEntry(a, a.name());
    assertThat(groups).containsEntry(b, a.name());
    assertThat(groups).containsEntry(c, c.name());
    assertThat(groups).containsEntry(d, c.name());
  }

  // TODO(dborowitz): Tests for octopus merges.

  private static PatchSet.Id psId(int c, int p) {
    return new PatchSet.Id(new Change.Id(c), p);
  }

  private RevWalk newWalk(ObjectId start, ObjectId branchTip) throws Exception {
    // Match RevWalk conditions from ReceiveCommits.
    RevWalk rw = new RevWalk(tr.getRepository());
    rw.sort(RevSort.TOPO);
    rw.sort(RevSort.REVERSE, true);
    rw.markStart(rw.parseCommit(start));
    rw.markUninteresting(rw.parseCommit(branchTip));
    return rw;
  }

  private static SortedSetMultimap<ObjectId, String> collectGroups(
      RevWalk rw,
      ImmutableListMultimap.Builder<ObjectId, PatchSet.Id> patchSetsBySha,
      ImmutableListMultimap.Builder<PatchSet.Id, String> groupLookup)
      throws Exception {
    GroupCollector gc =
        new GroupCollector(patchSetsBySha.build(), groupLookup.build());
    RevCommit c;
    while ((c = rw.next()) != null) {
      gc.visit(c);
    }
    return gc.getGroups();
  }

  // Helper methods for constructing various map arguments, to avoid lots of
  // type specifications.
  private static ImmutableListMultimap.Builder<ObjectId, PatchSet.Id>
      patchSets() {
    return ImmutableListMultimap.builder();
  }

  private static ImmutableListMultimap.Builder<PatchSet.Id, String> groups() {
    return ImmutableListMultimap.builder();
  }
}
