/*
 * Copyright (C) 2010, 2014 Christian Halstrick <christian.halstrick@sap.com>
 * 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.revplot;

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

import java.util.HashSet;
import java.util.Set;

import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalkTestCase;
import org.junit.Test;

public class PlotCommitListTest extends RevWalkTestCase {

	class CommitListAssert {
		private PlotCommitList<PlotLane> pcl;
		private PlotCommit<PlotLane> current;
		private int nextIndex = 0;

		CommitListAssert(PlotCommitList<PlotLane> pcl) {
			this.pcl = pcl;
		}

		public CommitListAssert commit(RevCommit id) {
			assertTrue("Unexpected end of list at pos#"+nextIndex, pcl.size()>nextIndex);
			current = pcl.get(nextIndex++);
			assertEquals("Expected commit not found at pos#" + (nextIndex - 1),
					id.getId(), current.getId());
			return this;
		}

		public CommitListAssert lanePos(int pos) {
			PlotLane lane = current.getLane();
			assertEquals("Position of lane of commit #" + (nextIndex - 1)
					+ " not as expected.", pos, lane.getPosition());
			return this;
		}

		public int getLanePos() {
			return current.getLane().position;
		}

		/**
		 * Checks that the current position is valid and consumes this position.
		 *
		 * @param allowedPositions
		 * @return this
		 */
		public CommitListAssert lanePos(Set<Integer> allowedPositions) {
			PlotLane lane = current.getLane();
			@SuppressWarnings("boxing")
			boolean found = allowedPositions.remove(lane.getPosition());
			assertTrue("Position of lane of commit #" + (nextIndex - 1)
					+ " not as expected. Expecting one of: " + allowedPositions + " Actual: "+ lane.getPosition(), found);
			return this;
		}

		public CommitListAssert nrOfPassingLanes(int lanes) {
			assertEquals("Number of passing lanes of commit #"
					+ (nextIndex - 1)
					+ " not as expected.", lanes, current.passingLanes.length);
			return this;
		}

		public CommitListAssert parents(RevCommit... parents) {
			assertEquals("Number of parents of commit #" + (nextIndex - 1)
					+ " not as expected.", parents.length,
					current.getParentCount());
			for (int i = 0; i < parents.length; i++)
				assertEquals("Unexpected parent of commit #" + (nextIndex - 1),
						parents[i], current.getParent(i));
			return this;
		}

		public CommitListAssert noMoreCommits() {
			assertEquals("Unexpected size of list", nextIndex, pcl.size());
			return this;
		}
	}

	private static Set<Integer> asSet(int... numbers) {
		Set<Integer> result = new HashSet<>();
		for (int n : numbers)
			result.add(Integer.valueOf(n));
		return result;
	}

	@Test
	public void testLinear() throws Exception {
		final RevCommit a = commit();
		final RevCommit b = commit(a);
		final RevCommit c = commit(b);

		PlotWalk pw = new PlotWalk(db);
		pw.markStart(pw.lookupCommit(c.getId()));

		PlotCommitList<PlotLane> pcl = new PlotCommitList<>();
		pcl.source(pw);
		pcl.fillTo(Integer.MAX_VALUE);

		CommitListAssert test = new CommitListAssert(pcl);
		test.commit(c).lanePos(0).parents(b);
		test.commit(b).lanePos(0).parents(a);
		test.commit(a).lanePos(0).parents();
		test.noMoreCommits();
	}

	@Test
	public void testMerged() throws Exception {
		final RevCommit a = commit();
		final RevCommit b = commit(a);
		final RevCommit c = commit(a);
		final RevCommit d = commit(b, c);

		PlotWalk pw = new PlotWalk(db);
		pw.markStart(pw.lookupCommit(d.getId()));

		PlotCommitList<PlotLane> pcl = new PlotCommitList<>();
		pcl.source(pw);
		pcl.fillTo(Integer.MAX_VALUE);

		CommitListAssert test = new CommitListAssert(pcl);
		test.commit(d).lanePos(0).parents(b, c);
		test.commit(c).lanePos(1).parents(a);
		test.commit(b).lanePos(0).parents(a);
		test.commit(a).lanePos(0).parents();
		test.noMoreCommits();
	}

	@Test
	public void testSideBranch() throws Exception {
		final RevCommit a = commit();
		final RevCommit b = commit(a);
		final RevCommit c = commit(a);

		PlotWalk pw = new PlotWalk(db);
		pw.markStart(pw.lookupCommit(b.getId()));
		pw.markStart(pw.lookupCommit(c.getId()));

		PlotCommitList<PlotLane> pcl = new PlotCommitList<>();
		pcl.source(pw);
		pcl.fillTo(Integer.MAX_VALUE);

		Set<Integer> childPositions = asSet(0, 1);
		CommitListAssert test = new CommitListAssert(pcl);
		test.commit(c).lanePos(childPositions).parents(a);
		test.commit(b).lanePos(childPositions).parents(a);
		test.commit(a).lanePos(0).parents();
		test.noMoreCommits();
	}

	@Test
	public void test2SideBranches() throws Exception {
		final RevCommit a = commit();
		final RevCommit b = commit(a);
		final RevCommit c = commit(a);
		final RevCommit d = commit(a);

		PlotWalk pw = new PlotWalk(db);
		pw.markStart(pw.lookupCommit(b.getId()));
		pw.markStart(pw.lookupCommit(c.getId()));
		pw.markStart(pw.lookupCommit(d.getId()));

		PlotCommitList<PlotLane> pcl = new PlotCommitList<>();
		pcl.source(pw);
		pcl.fillTo(Integer.MAX_VALUE);

		Set<Integer> childPositions = asSet(0, 1, 2);
		CommitListAssert test = new CommitListAssert(pcl);
		test.commit(d).lanePos(childPositions).parents(a);
		test.commit(c).lanePos(childPositions).parents(a);
		test.commit(b).lanePos(childPositions).parents(a);
		test.commit(a).lanePos(0).parents();
		test.noMoreCommits();
	}

	@Test
	public void testBug300282_1() throws Exception {
		final RevCommit a = commit();
		final RevCommit b = commit(a);
		final RevCommit c = commit(a);
		final RevCommit d = commit(a);
		final RevCommit e = commit(a);
		final RevCommit f = commit(a);
		final RevCommit g = commit(f);

		PlotWalk pw = new PlotWalk(db);
		// TODO: when we add unnecessary commit's as tips (e.g. a commit which
		// is a parent of another tip) the walk will return those commits twice.
		// Find out why!
		// pw.markStart(pw.lookupCommit(a.getId()));
		pw.markStart(pw.lookupCommit(b.getId()));
		pw.markStart(pw.lookupCommit(c.getId()));
		pw.markStart(pw.lookupCommit(d.getId()));
		pw.markStart(pw.lookupCommit(e.getId()));
		// pw.markStart(pw.lookupCommit(f.getId()));
		pw.markStart(pw.lookupCommit(g.getId()));

		PlotCommitList<PlotLane> pcl = new PlotCommitList<>();
		pcl.source(pw);
		pcl.fillTo(Integer.MAX_VALUE);

		Set<Integer> childPositions = asSet(0, 1, 2, 3, 4);
		CommitListAssert test = new CommitListAssert(pcl);
		int posG = test.commit(g).lanePos(childPositions).parents(f)
				.getLanePos();
		test.commit(f).lanePos(posG).parents(a);

		test.commit(e).lanePos(childPositions).parents(a);
		test.commit(d).lanePos(childPositions).parents(a);
		test.commit(c).lanePos(childPositions).parents(a);
		test.commit(b).lanePos(childPositions).parents(a);
		test.commit(a).lanePos(0).parents();
		test.noMoreCommits();
	}

	@Test
	public void testBug368927() throws Exception {
		final RevCommit a = commit();
		final RevCommit b = commit(a);
		final RevCommit c = commit(b);
		final RevCommit d = commit(b);
		final RevCommit e = commit(c);
		final RevCommit f = commit(e, d);
		final RevCommit g = commit(a);
		final RevCommit h = commit(f);
		final RevCommit i = commit(h);

		PlotWalk pw = new PlotWalk(db);
		pw.markStart(pw.lookupCommit(i.getId()));
		pw.markStart(pw.lookupCommit(g.getId()));

		PlotCommitList<PlotLane> pcl = new PlotCommitList<>();
		pcl.source(pw);
		pcl.fillTo(Integer.MAX_VALUE);
		Set<Integer> childPositions = asSet(0, 1);
		CommitListAssert test = new CommitListAssert(pcl);
		int posI = test.commit(i).lanePos(childPositions).parents(h)
				.getLanePos();
		test.commit(h).lanePos(posI).parents(f);
		test.commit(g).lanePos(childPositions).parents(a);
		test.commit(f).lanePos(posI).parents(e, d);
		test.commit(e).lanePos(posI).parents(c);
		test.commit(d).lanePos(2).parents(b);
		test.commit(c).lanePos(posI).parents(b);
		test.commit(b).lanePos(posI).parents(a);
		test.commit(a).lanePos(0).parents();
	}

	// test the history of the egit project between 9fdaf3c1 and e76ad9170f
	@Test
	public void testEgitHistory() throws Exception {
		final RevCommit merge_fix = commit();
		final RevCommit add_simple = commit(merge_fix);
		final RevCommit remove_unused = commit(merge_fix);
		final RevCommit merge_remove = commit(add_simple, remove_unused);
		final RevCommit resolve_handler = commit(merge_fix);
		final RevCommit clear_repositorycache = commit(merge_remove);
		final RevCommit add_Maven = commit(clear_repositorycache);
		final RevCommit use_remote = commit(clear_repositorycache);
		final RevCommit findToolBar_layout = commit(clear_repositorycache);
		final RevCommit merge_add_Maven = commit(findToolBar_layout, add_Maven);
		final RevCommit update_eclipse_iplog = commit(merge_add_Maven);
		final RevCommit changeset_implementation = commit(clear_repositorycache);
		final RevCommit merge_use_remote = commit(update_eclipse_iplog,
				use_remote);
		final RevCommit disable_source = commit(merge_use_remote);
		final RevCommit update_eclipse_iplog2 = commit(merge_use_remote);
		final RevCommit merge_disable_source = commit(update_eclipse_iplog2,
				disable_source);
		final RevCommit merge_changeset_implementation = commit(
				merge_disable_source, changeset_implementation);
		final RevCommit clone_operation = commit(merge_changeset_implementation);
		final RevCommit update_eclipse = commit(add_Maven);
		final RevCommit merge_resolve_handler = commit(clone_operation,
				resolve_handler);
		final RevCommit disable_comment = commit(clone_operation);
		final RevCommit merge_disable_comment = commit(merge_resolve_handler,
				disable_comment);
		final RevCommit fix_broken = commit(merge_disable_comment);
		final RevCommit add_a_clear = commit(fix_broken);
		final RevCommit merge_update_eclipse = commit(add_a_clear,
				update_eclipse);
		final RevCommit sort_roots = commit(merge_update_eclipse);
		final RevCommit fix_logged_npe = commit(merge_changeset_implementation);
		final RevCommit merge_fixed_logged_npe = commit(sort_roots,
				fix_logged_npe);

		PlotWalk pw = new PlotWalk(db);
		pw.markStart(pw.lookupCommit(merge_fixed_logged_npe.getId()));

		PlotCommitList<PlotLane> pcl = new PlotCommitList<>();
		pcl.source(pw);
		pcl.fillTo(Integer.MAX_VALUE);

		CommitListAssert test = new CommitListAssert(pcl);

		// Note: all positions of side branches are rather arbitrary, but some
		// may not overlap. Testing for the positions yielded by the current
		// implementation, which was manually checked to not overlap.
		final int mainPos = 0;
		test.commit(merge_fixed_logged_npe).parents(sort_roots, fix_logged_npe)
				.lanePos(mainPos);
		test.commit(fix_logged_npe).parents(merge_changeset_implementation)
				.lanePos(1);
		test.commit(sort_roots).parents(merge_update_eclipse).lanePos(mainPos);
		test.commit(merge_update_eclipse).parents(add_a_clear, update_eclipse)
				.lanePos(mainPos);
		test.commit(add_a_clear).parents(fix_broken).lanePos(mainPos);
		test.commit(fix_broken).parents(merge_disable_comment).lanePos(mainPos);
		test.commit(merge_disable_comment)
				.parents(merge_resolve_handler, disable_comment)
				.lanePos(mainPos);
		test.commit(disable_comment).parents(clone_operation).lanePos(2);
		test.commit(merge_resolve_handler)
				.parents(clone_operation, resolve_handler).lanePos(mainPos);
		test.commit(update_eclipse).parents(add_Maven).lanePos(3);
		test.commit(clone_operation).parents(merge_changeset_implementation)
				.lanePos(mainPos);
		test.commit(merge_changeset_implementation)
				.parents(merge_disable_source, changeset_implementation)
				.lanePos(mainPos);
		test.commit(merge_disable_source)
				.parents(update_eclipse_iplog2, disable_source)
				.lanePos(mainPos);
		test.commit(update_eclipse_iplog2).parents(merge_use_remote)
				.lanePos(mainPos);
		test.commit(disable_source).parents(merge_use_remote).lanePos(1);
		test.commit(merge_use_remote).parents(update_eclipse_iplog, use_remote)
				.lanePos(mainPos);
		test.commit(changeset_implementation).parents(clear_repositorycache)
				.lanePos(2);
		test.commit(update_eclipse_iplog).parents(merge_add_Maven)
				.lanePos(mainPos);
		test.commit(merge_add_Maven).parents(findToolBar_layout, add_Maven)
				.lanePos(mainPos);
		test.commit(findToolBar_layout).parents(clear_repositorycache)
				.lanePos(mainPos);
		test.commit(use_remote).parents(clear_repositorycache).lanePos(1);
		test.commit(add_Maven).parents(clear_repositorycache).lanePos(3);
		test.commit(clear_repositorycache).parents(merge_remove)
				.lanePos(mainPos);
		test.commit(resolve_handler).parents(merge_fix).lanePos(4);
		test.commit(merge_remove).parents(add_simple, remove_unused)
				.lanePos(mainPos);
		test.commit(remove_unused).parents(merge_fix).lanePos(1);
		test.commit(add_simple).parents(merge_fix).lanePos(mainPos);
		test.commit(merge_fix).parents().lanePos(mainPos);
		test.noMoreCommits();
	}

	// test a history where a merge commit has two time the same parent
	@Test
	public void testDuplicateParents() throws Exception {
		final RevCommit m1 = commit();
		final RevCommit m2 = commit(m1);
		final RevCommit m3 = commit(m2, m2);

		final RevCommit s1 = commit(m2);
		final RevCommit s2 = commit(s1);

		PlotWalk pw = new PlotWalk(db);
		pw.markStart(pw.lookupCommit(m3));
		pw.markStart(pw.lookupCommit(s2));
		PlotCommitList<PlotLane> pcl = new PlotCommitList<>();
		pcl.source(pw);
		pcl.fillTo(Integer.MAX_VALUE);

		CommitListAssert test = new CommitListAssert(pcl);
		test.commit(s2).nrOfPassingLanes(0);
		test.commit(s1).nrOfPassingLanes(0);
		test.commit(m3).nrOfPassingLanes(1);
		test.commit(m2).nrOfPassingLanes(0);
		test.commit(m1).nrOfPassingLanes(0);
		test.noMoreCommits();
	}

	/**
	 * The graph shows the problematic original positioning. Due to this some
	 * lanes are no straight lines here, but they are with the new layout code)
	 *
	 * <pre>
	 * a5
	 * | \
	 * |  a4
	 * | /
	 * a3
	 * |
	 * |  e
	 * |    \
	 * |     |
	 * |  b3 |
	 * |  |  d
	 * |  |/
	 * | /|
	 * |/ |
	 * a2 |
	 * |  b2
	 * |    \
	 * |  c |
	 * | /  /
	 * |/ b1
	 * a1
	 * </pre>
	 *
	 * @throws Exception
	 */
	@Test
	public void testBug419359() throws Exception {
		// this may not be the exact situation of bug 419359 but it shows
		// similar behavior
		final RevCommit a1 = commit();
		final RevCommit b1 = commit();
		final RevCommit c = commit(a1);
		final RevCommit b2 = commit(b1);
		final RevCommit a2 = commit(a1);
		final RevCommit d = commit(a2);
		final RevCommit b3 = commit(b2);
		final RevCommit e = commit(d);
		final RevCommit a3 = commit(a2);
		final RevCommit a4 = commit(a3);
		final RevCommit a5 = commit(a3, a4);

		PlotWalk pw = new PlotWalk(db);
		pw.markStart(pw.lookupCommit(b3.getId()));
		pw.markStart(pw.lookupCommit(c.getId()));
		pw.markStart(pw.lookupCommit(e.getId()));
		pw.markStart(pw.lookupCommit(a5.getId()));

		PlotCommitList<PlotLane> pcl = new PlotCommitList<>();
		pcl.source(pw);
		pcl.fillTo(Integer.MAX_VALUE);

		// test that the commits b1, b2 and b3 are on the same position
		int bPos = pcl.get(9).lane.position; // b1
		assertEquals("b2 is an a different position", bPos,
				pcl.get(7).lane.position);
		assertEquals("b3 is on a different position", bPos,
				pcl.get(4).lane.position);

		// test that nothing blocks the connections between b1, b2 and b3
		assertNotEquals("b lane is blocked by c", bPos,
				pcl.get(8).lane.position);
		assertNotEquals("b lane is blocked by a2", bPos,
				pcl.get(6).lane.position);
		assertNotEquals("b lane is blocked by d", bPos,
				pcl.get(5).lane.position);
	}

	/**
	 * <pre>
	 *    b3
	 * a4 |
	 * | \|
	 * |  b2
	 * a3 |
	 * | \|
	 * a2 |
	 * |  b1
	 * | /
	 * a1
	 * </pre>
	 *
	 * @throws Exception
	 */
	@Test
	public void testMultipleMerges() throws Exception {
		final RevCommit a1 = commit();
		final RevCommit b1 = commit(a1);
		final RevCommit a2 = commit(a1);
		final RevCommit a3 = commit(a2, b1);
		final RevCommit b2 = commit(b1);
		final RevCommit a4 = commit(a3, b2);
		final RevCommit b3 = commit(b2);

		PlotWalk pw = new PlotWalk(db);
		pw.markStart(pw.lookupCommit(a4));
		pw.markStart(pw.lookupCommit(b3));
		PlotCommitList<PlotLane> pcl = new PlotCommitList<>();
		pcl.source(pw);
		pcl.fillTo(Integer.MAX_VALUE);

		Set<Integer> positions = asSet(0, 1);
		CommitListAssert test = new CommitListAssert(pcl);
		int posB = test.commit(b3).lanePos(positions).getLanePos();
		int posA = test.commit(a4).lanePos(positions).getLanePos();
		test.commit(b2).lanePos(posB);
		test.commit(a3).lanePos(posA);
		test.commit(a2).lanePos(posA);
		test.commit(b1).lanePos(posB);
		test.commit(a1).lanePos(posA);
		test.noMoreCommits();
	}

	/**
	 * <pre>
	 * a4
	 * |   b3
	 * a3  |
	 * | \\|
	 * |   |\\
	 * |   b2||
	 * a2  | //
	 * |   b1
	 * | /
	 * a1
	 * </pre>
	 *
	 * @throws Exception
	 */
	@Test
	public void testMergeBlockedBySelf() throws Exception {
		final RevCommit a1 = commit();
		final RevCommit b1 = commit(a1);
		final RevCommit a2 = commit(a1);
		final RevCommit b2 = commit(b1); // blocks merging arc
		final RevCommit a3 = commit(a2, b1);
		final RevCommit b3 = commit(b2);
		final RevCommit a4 = commit(a3);

		PlotWalk pw = new PlotWalk(db);
		pw.markStart(pw.lookupCommit(a4));
		pw.markStart(pw.lookupCommit(b3));
		PlotCommitList<PlotLane> pcl = new PlotCommitList<>();
		pcl.source(pw);
		pcl.fillTo(Integer.MAX_VALUE);

		Set<Integer> positions = asSet(0, 1);
		CommitListAssert test = new CommitListAssert(pcl);
		int posA = test.commit(a4).lanePos(positions).getLanePos();
		int posB = test.commit(b3).lanePos(positions).getLanePos();
		test.commit(a3).lanePos(posA);
		test.commit(b2).lanePos(posB);
		test.commit(a2).lanePos(posA);
		// b1 is not repositioned, uses "detour lane"
		// (drawn as a double arc in the ascii graph above)
		test.commit(b1).lanePos(posB);
		test.commit(a1).lanePos(posA);
		test.noMoreCommits();
	}

	/**
	 * <pre>
	 *      b2
	 * a4   |
	 * |  \ |
	 * a3  \|
	 * | \  |
	 * |  c |
	 * | /  |
	 * a2   |
	 * |    b1
	 *     /
	 * |  /
	 * a1
	 * </pre>
	 *
	 * @throws Exception
	 */
	@Test
	public void testMergeBlockedByOther() throws Exception {
		final RevCommit a1 = commit();
		final RevCommit b1 = commit(a1);
		final RevCommit a2 = commit(a1);
		final RevCommit c = commit(a2);// blocks merging arc
		final RevCommit a3 = commit(a2, c);
		final RevCommit a4 = commit(a3, b1);
		final RevCommit b2 = commit(b1);

		PlotWalk pw = new PlotWalk(db);
		pw.markStart(pw.lookupCommit(a4));
		pw.markStart(pw.lookupCommit(b2));
		pw.markStart(pw.lookupCommit(c));
		PlotCommitList<PlotLane> pcl = new PlotCommitList<>();
		pcl.source(pw);
		pcl.fillTo(Integer.MAX_VALUE);

		Set<Integer> positions = asSet(0, 1, 2);
		CommitListAssert test = new CommitListAssert(pcl);
		int posB = test.commit(b2).lanePos(positions).getLanePos();
		int posA = test.commit(a4).lanePos(positions).getLanePos();
		test.commit(a3).lanePos(posA);
		test.commit(c).lanePos(positions);
		test.commit(a2).lanePos(posA);
		test.commit(b1).lanePos(posB); // repositioned to go around c
		test.commit(a1).lanePos(posA);
		test.noMoreCommits();
	}

	/**
	 * <pre>
	 *     b1
	 * a3  |
	 * |   |
	 * a2  |
	 * -- processing stops here --
	 * |  /
	 * a1
	 * </pre>
	 *
	 * @throws Exception
	 */
	@Test
	public void testDanglingCommitShouldContinueLane() throws Exception {
		final RevCommit a1 = commit();
		final RevCommit a2 = commit(a1);
		final RevCommit a3 = commit(a2);
		final RevCommit b1 = commit(a1);

		PlotWalk pw = new PlotWalk(db);
		pw.markStart(pw.lookupCommit(a3));
		pw.markStart(pw.lookupCommit(b1));
		PlotCommitList<PlotLane> pcl = new PlotCommitList<>();
		pcl.source(pw);
		pcl.fillTo(2); // don't process a1

		Set<Integer> positions = asSet(0, 1);
		CommitListAssert test = new CommitListAssert(pcl);
		PlotLane laneB = test.commit(b1).lanePos(positions).current.getLane();
		int posA = test.commit(a3).lanePos(positions).getLanePos();
		test.commit(a2).lanePos(posA);
		assertArrayEquals(
				"Although the parent of b1, a1, is not processed yet, the b lane should still be drawn",
				new PlotLane[] { laneB }, test.current.passingLanes);
		test.noMoreCommits();
	}

	@Test
	public void testTwoRoots1() throws Exception {
		final RevCommit a = commit();
		final RevCommit b = commit();

		PlotWalk pw = new PlotWalk(db);
		pw.markStart(pw.lookupCommit(a));
		pw.markStart(pw.lookupCommit(b));
		PlotCommitList<PlotLane> pcl = new PlotCommitList<>();
		pcl.source(pw);
		pcl.fillTo(Integer.MAX_VALUE);

		CommitListAssert test = new CommitListAssert(pcl);
		test.commit(b).lanePos(0);
		test.commit(a).lanePos(0);
		test.noMoreCommits();
	}

	@Test
	public void testTwoRoots2() throws Exception {
		final RevCommit a = commit();
		final RevCommit b1 = commit();
		final RevCommit b2 = commit(b1);

		PlotWalk pw = new PlotWalk(db);
		pw.markStart(pw.lookupCommit(a));
		pw.markStart(pw.lookupCommit(b2));
		PlotCommitList<PlotLane> pcl = new PlotCommitList<>();
		pcl.source(pw);
		pcl.fillTo(Integer.MAX_VALUE);

		CommitListAssert test = new CommitListAssert(pcl);
		test.commit(b2).lanePos(0);
		test.commit(b1).lanePos(0);
		test.commit(a).lanePos(0);
		test.noMoreCommits();
	}
}
