changeset 472:2a0b09eec376

Tests for issue 31
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Wed, 11 Jul 2012 21:46:28 +0200
parents 7bcfbc255f48
children 5c09a9f2e073
files cmdline/org/tmatesoft/hg/console/Main.java src/org/tmatesoft/hg/internal/RevisionDescendants.java test/org/tmatesoft/hg/test/TestAuxUtilities.java
diffstat 3 files changed, 76 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/cmdline/org/tmatesoft/hg/console/Main.java	Wed Jul 11 20:40:47 2012 +0200
+++ b/cmdline/org/tmatesoft/hg/console/Main.java	Wed Jul 11 21:46:28 2012 +0200
@@ -108,14 +108,13 @@
 //		m.checkWalkFileRevisions();
 //		m.checkSubProgress();
 //		m.checkFileFlags();
-		m.testMqManager();
-//		m.testRevisionDescendants();
+//		m.testMqManager();
 //		m.dumpPhases();
 //		m.buildFileLog();
 //		m.testConsoleLog();
 //		m.testTreeTraversal();
 //		m.testRevisionMap();
-		m.testSubrepos();
+//		m.testSubrepos();
 //		m.testReadWorkingCopy();
 //		m.testParents();
 //		m.testEffectiveFileLog();
@@ -159,25 +158,6 @@
 	}
 	
 	
-	// -R {junit-test-repos}/branches-1
-	private void testRevisionDescendants() throws Exception {
-		int[] roots = new int[] {0, 1, 2, 3, 4, 5};
-		RevisionDescendants[] result = new RevisionDescendants[roots.length];
-		for (int i = 0; i < roots.length; i++) {
-			result[i] = new RevisionDescendants(hgRepo, roots[i]);
-			result[i].build();
-		}
-		for (int i = 0; i < roots.length; i++) {
-			System.out.printf("For root %d descendats are:", roots[i]);
-			for (int j = roots[i], x = hgRepo.getChangelog().getLastRevision(); j <= x; j++) {
-				if (result[i].isDescendant(j)) {
-					System.out.printf("%3d ", j);
-				}
-			}
-			System.out.printf(", isEmpty:%b\n", !result[i].hasDescendants());
-		}
-	}
-	
 	// -R ${system_property:user.home}/hg/test-phases/
 	// TODO as junit test
 	private void dumpPhases() throws Exception {
--- a/src/org/tmatesoft/hg/internal/RevisionDescendants.java	Wed Jul 11 20:40:47 2012 +0200
+++ b/src/org/tmatesoft/hg/internal/RevisionDescendants.java	Wed Jul 11 21:46:28 2012 +0200
@@ -95,6 +95,13 @@
 		return descendants.nextSetBit(rootRevIndex+1) != -1;
 	}
 
+	/**
+	 * Tells whether specified revision is on a descent line from the root revision.
+	 * <p>NOTE, root revision itself is considered to be its own descendant.
+	 * 
+	 * @param revisionIndex revision index to check, shall pass {@link #isCandidate(int)}
+	 * @return <code>true</code> if revision is descendant of or is the same as root revision
+	 */
 	public boolean isDescendant(int revisionIndex) {
 		assert isCandidate(revisionIndex);
 		int ix = revisionIndex - rootRevIndex;
--- a/test/org/tmatesoft/hg/test/TestAuxUtilities.java	Wed Jul 11 20:40:47 2012 +0200
+++ b/test/org/tmatesoft/hg/test/TestAuxUtilities.java	Wed Jul 11 21:46:28 2012 +0200
@@ -16,6 +16,8 @@
  */
 package org.tmatesoft.hg.test;
 
+import static java.lang.Integer.toBinaryString;
+import static org.junit.Assert.*;
 import static org.tmatesoft.hg.repo.HgRepository.TIP;
 import static org.tmatesoft.hg.util.Path.CompareResult.*;
 
@@ -30,6 +32,7 @@
 import org.tmatesoft.hg.core.Nodeid;
 import org.tmatesoft.hg.internal.ArrayHelper;
 import org.tmatesoft.hg.internal.PathScope;
+import org.tmatesoft.hg.internal.RevisionDescendants;
 import org.tmatesoft.hg.repo.HgChangelog;
 import org.tmatesoft.hg.repo.HgChangelog.RawChangeset;
 import org.tmatesoft.hg.repo.HgDataFile;
@@ -63,14 +66,14 @@
 		String[] result = initial.clone();
 		ah.sort(result);
 		String[] restored = restore(result, ah.getReverse());
-		Assert.assertArrayEquals(initial, restored);
+		assertArrayEquals(initial, restored);
 		//
 		// few elements are on the right place from the very start and do not shift during sort.
 		// make sure for them we've got correct reversed indexes as well
 		initial = new String[] {"d", "h", "c", "b", "k", "i", "a", "r", "e", "w" };
 		ah.sort(result = initial.clone());
 		restored = restore(result, ah.getReverse());
-		Assert.assertArrayEquals(initial, restored);
+		assertArrayEquals(initial, restored);
 	}
 
 	private static String[] restore(String[] sorted, int[] sortReverse) {
@@ -236,9 +239,9 @@
 			int i = 0;
 
 			public void next(int localRevision, Nodeid revision, int linkedRevision) {
-				Assert.assertEquals(i++, localRevision);
-				Assert.assertEquals(fileNode.getChangesetRevisionIndex(localRevision), linkedRevision);
-				Assert.assertEquals(fileNode.getRevision(localRevision), revision);
+				assertEquals(i++, localRevision);
+				assertEquals(fileNode.getChangesetRevisionIndex(localRevision), linkedRevision);
+				assertEquals(fileNode.getRevision(localRevision), revision);
 			}
 		});
 		class ParentInspectorCheck implements HgDataFile.ParentInspector {
@@ -254,11 +257,11 @@
 			}
 
 			public void next(int localRevision, Nodeid revision, int parent1, int parent2, Nodeid nidParent1, Nodeid nidParent2) {
-				Assert.assertEquals(i++, localRevision);
+				assertEquals(i++, localRevision);
 				all[c++] = revision;
-				Assert.assertNotNull(revision);
-				Assert.assertFalse(localRevision == 0 && (parent1 != -1 || parent2 != -1));
-				Assert.assertFalse(localRevision > 0 && parent1 == -1 && parent2 == -1);
+				assertNotNull(revision);
+				assertFalse(localRevision == 0 && (parent1 != -1 || parent2 != -1));
+				assertFalse(localRevision > 0 && parent1 == -1 && parent2 == -1);
 				if (parent1 != -1) {
 					Assert.assertNotNull(nidParent1);
 					if (parent1 >= start) {
@@ -280,6 +283,61 @@
 		fileNode.indexWalk(1, 3, new ParentInspectorCheck(1, 3));
 	}
 
+	/*
+	 * This test checks not only RevisionDescendants class, but also
+	 * Revlog.indexWalk implementation defect, aka:
+	 * Issue 31: Revlog#walk doesn't handle ParentInspector correctly with start revision other than 0, fails with AIOOBE
+	 */
+	@Test
+	public void testRevisionDescendants() throws Exception {
+		HgRepository hgRepo = Configuration.get().find("branches-1");
+		int[] roots = new int[] {0, 1, 2, 3, 4, 5};
+		// 0: all revisions are descendants, 17 total.
+		// 1: 2, 4, 7, 8, 9
+		// 2: 7, 8, 9 
+		// 3: 5,6, 10-16
+		// 4: no children
+		// 5: 6, 10-16
+		// array values represent bit mask, '1' for revision that shall re reported as descendant
+		// least significant bit is revision 0, and so on, so that 1<<revision points to bit in the bitmask
+		int[] descendantBitset = new int[] { 0x01FFFF, 0x0396, 0x0384, 0x01FC68, 0x010, 0x01FC60 };
+		RevisionDescendants[] result = new RevisionDescendants[roots.length];
+		for (int i = 0; i < roots.length; i++) {
+			result[i] = new RevisionDescendants(hgRepo, roots[i]);
+			result[i].build();
+		}
+		/*
+		for (int i = 0; i < roots.length; i++) {
+			System.out.printf("For root %d descendats are:", roots[i]);
+			for (int j = roots[i], x = hgRepo.getChangelog().getLastRevision(); j <= x; j++) {
+				if (result[i].isDescendant(j)) {
+					System.out.printf("%3d ", j);
+				}
+			}
+			System.out.printf(", isEmpty:%b\n", !result[i].hasDescendants());
+		}
+		*/
+		for (int i = 0; i < roots.length; i++) {
+			System.out.printf("%s & %s = 0x%x\n", toBinaryString(descendantBitset[i]), toBinaryString(~(1<<roots[i])), descendantBitset[i] & ~(1<<roots[i]));
+			if ((descendantBitset[i] & ~(1<<roots[i])) != 0) {
+				assertTrue(result[i].hasDescendants());
+			} else {
+				assertFalse(result[i].hasDescendants());
+			}
+			for (int j = roots[i], x = hgRepo.getChangelog().getLastRevision(); j <= x; j++) {
+				int bit = 1<<j;
+				boolean shallBeDescendant = (descendantBitset[i] & bit) != 0;
+				String m = String.format("Check rev %d from root %d. Bit %s in %s, shallBeDescendant:%b", j, roots[i], toBinaryString(bit), toBinaryString(descendantBitset[i]), shallBeDescendant);
+				if (result[i].isDescendant(j)) {
+					assertTrue(m, shallBeDescendant);
+				} else {
+					assertFalse(m, shallBeDescendant);
+				}
+			}
+		}
+	}
+
+
 	@Test
 	@Ignore("just a dump for now, to compare values visually")
 	public void testRepositoryConfig() throws Exception {