/*
 * Copyright (C) 2015, Google Inc.
 * and other copyright owners as documented in the project's IP log.
 *
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Distribution License v1.0 which
 * accompanies this distribution, is reproduced below, and is
 * available at http://www.eclipse.org/org/documents/edl-v10.php
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 * - Neither the name of the Eclipse Foundation, Inc. nor the
 *   names of its contributors may be used to endorse or promote
 *   products derived from this software without specific prior
 *   written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.eclipse.jgit.internal.storage.pack;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.jgit.internal.storage.file.GcTestCase;
import org.eclipse.jgit.internal.storage.file.PackBitmapIndexBuilder;
import org.eclipse.jgit.internal.storage.pack.PackWriterBitmapPreparer.BitmapCommit;
import org.eclipse.jgit.junit.TestRepository.BranchBuilder;
import org.eclipse.jgit.junit.TestRepository.CommitBuilder;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.storage.pack.PackConfig;
import org.junit.Test;

public class GcCommitSelectionTest extends GcTestCase {

	@Test
	public void testBitmapSpansNoMerges() throws Exception {
		testBitmapSpansNoMerges(false);
	}

	@Test
	public void testBitmapSpansNoMergesWithTags() throws Exception {
		testBitmapSpansNoMerges(true);
	}

	private void testBitmapSpansNoMerges(boolean withTags) throws Exception {
		/*
		 * Commit counts -> expected bitmap counts for history without merges.
		 * The top 100 contiguous commits should always have bitmaps, and the
		 * "recent" bitmaps beyond that are spaced out every 100-200 commits.
		 * (Starting at 100, the next 100 commits are searched for a merge
		 * commit. Since one is not found, the spacing between commits is 200.
		 */
		int[][] bitmapCounts = { //
				{ 1, 1 }, { 50, 50 }, { 99, 99 }, { 100, 100 }, { 101, 100 },
				{ 200, 100 }, { 201, 100 }, { 299, 100 }, { 300, 101 },
				{ 301, 101 }, { 401, 101 }, { 499, 101 }, { 500, 102 }, };
		int currentCommits = 0;
		BranchBuilder bb = tr.branch("refs/heads/main");

		for (int[] counts : bitmapCounts) {
			int nextCommitCount = counts[0];
			int expectedBitmapCount = counts[1];
			assertTrue(nextCommitCount > currentCommits); // programming error
			for (int i = currentCommits; i < nextCommitCount; i++) {
				String str = "A" + i;
				RevCommit rc = bb.commit().message(str).add(str, str).create();
				if (withTags) {
					tr.lightweightTag(str, rc);
				}
			}
			currentCommits = nextCommitCount;

			gc.setPackExpireAgeMillis(0); // immediately delete old packs
			gc.setExpireAgeMillis(0);
			gc.gc();
			assertEquals(currentCommits * 3, // commit/tree/object
					gc.getStatistics().numberOfPackedObjects);
			assertEquals(currentCommits + " commits: ", expectedBitmapCount,
					gc.getStatistics().numberOfBitmaps);
		}
	}

	@Test
	public void testBitmapSpansWithMerges() throws Exception {
		/*
		 * Commits that are merged. Since 55 is in the oldest history it is
		 * never considered. Searching goes from oldest to newest so 115 is the
		 * first merge commit found. After that the range 116-216 is ignored so
		 * 175 is never considered.
		 */
		List<Integer> merges = Arrays.asList(Integer.valueOf(55),
				Integer.valueOf(115), Integer.valueOf(175),
				Integer.valueOf(235));
		/*
		 * Commit counts -> expected bitmap counts for history with merges. The
		 * top 100 contiguous commits should always have bitmaps, and the
		 * "recent" bitmaps beyond that are spaced out every 100-200 commits.
		 * Merges in the < 100 range have no effect and merges in the > 100
		 * range will only be considered for commit counts > 200.
		 */
		int[][] bitmapCounts = { //
				{ 1, 1 }, { 55, 55 }, { 56, 57 }, // +1 bitmap from branch A55
				{ 99, 100 }, // still +1 branch @55
				{ 100, 100 }, // 101 commits, only 100 newest
				{ 116, 100 }, // @55 still in 100 newest bitmaps
				{ 176, 101 }, // @55 branch tip is not in 100 newest
				{ 213, 101 }, // 216 commits, @115&@175 in 100 newest
				{ 214, 102 }, // @55 branch tip, merge @115, @177 in newest
				{ 236, 102 }, // all 4 merge points in history
				{ 273, 102 }, // 277 commits, @175&@235 in newest
				{ 274, 103 }, // @55, @115, merge @175, @235 in newest
				{ 334, 103 }, // @55,@115,@175, @235 in newest
				{ 335, 104 }, // @55,@115,@175, merge @235
				{ 435, 104 }, // @55,@115,@175,@235 tips
				{ 436, 104 }, // force @236
		};

		int currentCommits = 0;
		BranchBuilder bb = tr.branch("refs/heads/main");

		for (int[] counts : bitmapCounts) {
			int nextCommitCount = counts[0];
			int expectedBitmapCount = counts[1];
			assertTrue(nextCommitCount > currentCommits); // programming error
			for (int i = currentCommits; i < nextCommitCount; i++) {
				String str = "A" + i;
				if (!merges.contains(Integer.valueOf(i))) {
					bb.commit().message(str).add(str, str).create();
				} else {
					BranchBuilder bbN = tr.branch("refs/heads/A" + i);
					bb.commit().message(str).add(str, str)
							.parent(bbN.commit().create()).create();
				}
			}
			currentCommits = nextCommitCount;

			gc.setPackExpireAgeMillis(0); // immediately delete old packs
			gc.setExpireAgeMillis(0);
			gc.gc();
			assertEquals(currentCommits + " commits: ", expectedBitmapCount,
					gc.getStatistics().numberOfBitmaps);
		}
	}

	@Test
	public void testBitmapsForExcessiveBranches() throws Exception {
		int oneDayInSeconds = 60 * 60 * 24;

		// All of branch A is committed on day1
		BranchBuilder bbA = tr.branch("refs/heads/A");
		for (int i = 0; i < 1001; i++) {
			String msg = "A" + i;
			bbA.commit().message(msg).add(msg, msg).create();
		}
		// All of in branch B is committed on day91
		tr.tick(oneDayInSeconds * 90);
		BranchBuilder bbB = tr.branch("refs/heads/B");
		for (int i = 0; i < 1001; i++) {
			String msg = "B" + i;
			bbB.commit().message(msg).add(msg, msg).create();
		}
		// Create 100 other branches with a single commit
		for (int i = 0; i < 100; i++) {
			BranchBuilder bb = tr.branch("refs/heads/N" + i);
			String msg = "singlecommit" + i;
			bb.commit().message(msg).add(msg, msg).create();
		}
		// now is day92
		tr.tick(oneDayInSeconds);

		// Since there are no merges, commits in recent history are selected
		// every 200 commits.
		final int commitsForSparseBranch = 1 + (1001 / 200);
		final int commitsForFullBranch = 100 + (901 / 200);
		final int commitsForShallowBranches = 100;

		// Excessive branch history pruning, one old branch.
		gc.setPackExpireAgeMillis(0); // immediately delete old packs
		gc.setExpireAgeMillis(0);
		gc.gc();
		assertEquals(
				commitsForSparseBranch + commitsForFullBranch
						+ commitsForShallowBranches,
				gc.getStatistics().numberOfBitmaps);
	}

	@Test
	public void testSelectionOrderingWithChains() throws Exception {
		/*-
		 * Create a history like this, where 'N' is the number of seconds from
		 * the first commit in the branch:
		 *
		 *      ---o---o---o        commits b3,b5,b7
		 *     /            \
		 * o--o--o---o---o---o--o   commits m0,m1,m2,m4,m6,m8,m9
		 */
		BranchBuilder bb = tr.branch("refs/heads/main");
		RevCommit m0 = addCommit(bb, "m0");
		RevCommit m1 = addCommit(bb, "m1", m0);
		RevCommit m2 = addCommit(bb, "m2", m1);
		RevCommit b3 = addCommit(bb, "b3", m1);
		RevCommit m4 = addCommit(bb, "m4", m2);
		RevCommit b5 = addCommit(bb, "m5", b3);
		RevCommit m6 = addCommit(bb, "m6", m4);
		RevCommit b7 = addCommit(bb, "m7", b5);
		RevCommit m8 = addCommit(bb, "m8", m6, b7);
		RevCommit m9 = addCommit(bb, "m9", m8);

		List<RevCommit> commits = Arrays.asList(m0, m1, m2, b3, m4, b5, m6, b7,
				m8, m9);
		PackWriterBitmapPreparer preparer = newPreparer(
				Collections.singleton(m9), commits, new PackConfig());
		List<BitmapCommit> selection = new ArrayList<>(
				preparer.selectCommits(commits.size(), PackWriter.NONE));

		// Verify that the output is ordered by the separate "chains"
		String[] expected = { m0.name(), m1.name(), m2.name(), m4.name(),
				m6.name(), m8.name(), m9.name(), b3.name(), b5.name(),
				b7.name() };
		assertEquals(expected.length, selection.size());
		for (int i = 0; i < expected.length; i++) {
			assertEquals("Entry " + i, expected[i], selection.get(i).getName());
		}
	}

	private RevCommit addCommit(BranchBuilder bb, String msg,
			RevCommit... parents) throws Exception {
		CommitBuilder commit = bb.commit().message(msg).add(msg, msg).tick(1)
				.noParents();
		for (RevCommit parent : parents) {
			commit.parent(parent);
		}
		return commit.create();
	}

	@Test
	public void testDistributionOnMultipleBranches() throws Exception {
		BranchBuilder[] branches = { tr.branch("refs/heads/main"),
				tr.branch("refs/heads/a"), tr.branch("refs/heads/b"),
				tr.branch("refs/heads/c") };
		RevCommit[] tips = new RevCommit[branches.length];
		List<RevCommit> commits = createHistory(branches, tips);
		PackConfig config = new PackConfig();
		config.setBitmapContiguousCommitCount(1);
		config.setBitmapRecentCommitSpan(5);
		config.setBitmapDistantCommitSpan(20);
		config.setBitmapRecentCommitCount(100);
		Set<RevCommit> wants = new HashSet<>(Arrays.asList(tips));
		PackWriterBitmapPreparer preparer = newPreparer(wants, commits, config);
		List<BitmapCommit> selection = new ArrayList<>(
				preparer.selectCommits(commits.size(), PackWriter.NONE));
		Set<ObjectId> selected = new HashSet<>();
		for (BitmapCommit c : selection) {
			selected.add(c.toObjectId());
		}

		// Verify that each branch has uniform bitmap selection coverage
		for (RevCommit c : wants) {
			assertTrue(selected.contains(c.toObjectId()));
			int count = 1;
			int selectedCount = 1;
			RevCommit parent = c;
			while (parent.getParentCount() != 0) {
				parent = parent.getParent(0);
				count++;
				if (selected.contains(parent.toObjectId())) {
					selectedCount++;
				}
			}
			// The selection algorithm prefers merges and will look in the
			// current range plus the recent commit span before selecting a
			// commit. Since this history has no merges, we expect the recent
			// span should have 100/10=10 and distant commit spans should have
			// 100/25=4 per 100 commit range.
			int expectedCount = 10 + (count - 100 - 24) / 25;
			assertTrue(expectedCount <= selectedCount);
		}
	}

	private List<RevCommit> createHistory(BranchBuilder[] branches,
			RevCommit[] tips) throws Exception {
		/*-
		 * Create a history like this, where branches a, b and c branch off of the main branch
		 * at commits 100, 200 and 300, and where commit times move forward alternating between
		 * branches.
		 *
		 * o...o...o...o...o      commits root,m0,m1,...,m399
		 *      \   \   \
		 *       \   \   o...     commits branch_c,c300,c301,...,c399
		 *        \   \
		 *         \   o...o...   commits branch_b,b200,b201,...,b399
		 *          \
		 *           o...o...o... commits branch_a,b100,b101,...,a399
		 */
		List<RevCommit> commits = new ArrayList<>();
		String[] prefixes = { "m", "a", "b", "c" };
		int branchCount = branches.length;
		tips[0] = addCommit(commits, branches[0], "root");
		int counter = 0;

		for (int b = 0; b < branchCount; b++) {
			for (int i = 0; i < 100; i++, counter++) {
				for (int j = 0; j <= b; j++) {
					tips[j] = addCommit(commits, branches[j],
							prefixes[j] + counter);
				}
			}
			// Create a new branch from current value of the master branch
			if (b < branchCount - 1) {
				tips[b + 1] = addCommit(branches[b + 1],
						"branch_" + prefixes[b + 1], tips[0]);
			}
		}
		return commits;
	}

	private RevCommit addCommit(List<RevCommit> commits, BranchBuilder bb,
			String msg, RevCommit... parents) throws Exception {
		CommitBuilder commit = bb.commit().message(msg).add(msg, msg).tick(1);
		if (parents.length > 0) {
			commit.noParents();
			for (RevCommit parent : parents) {
				commit.parent(parent);
			}
		}
		RevCommit c = commit.create();
		commits.add(c);
		return c;
	}

	private PackWriterBitmapPreparer newPreparer(Set<RevCommit> wants,
			List<RevCommit> commits, PackConfig config) throws IOException {
		List<ObjectToPack> objects = new ArrayList<>(commits.size());
		for (RevCommit commit : commits) {
			objects.add(new ObjectToPack(commit, Constants.OBJ_COMMIT));
		}
		PackBitmapIndexBuilder builder = new PackBitmapIndexBuilder(objects);
		return new PackWriterBitmapPreparer(
				tr.getRepository().newObjectReader(), builder,
				NullProgressMonitor.INSTANCE, wants, config);
	}
}
