reftable: bulk operation unit tests

Add more test cases that cover larger collections of
references, verifying every reference is accessible
both by scan and by seek.

Change-Id: Icada59fdcfc92a4634f6df61baaebb1c37b75d98
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java
index f8276b3..5c19af3 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java
@@ -273,6 +273,62 @@
 		}
 	}
 
+	@SuppressWarnings("boxing")
+	@Test
+	public void indexScan() throws IOException {
+		List<Ref> refs = new ArrayList<>();
+		for (int i = 1; i <= 5670; i++) {
+			refs.add(ref(String.format("refs/heads/%04d", i), i));
+		}
+
+		byte[] table = write(refs);
+		assertTrue(stats.refIndexLevels() > 0);
+		assertTrue(stats.refIndexSize() > 0);
+		assertScan(refs, read(table));
+	}
+
+	@SuppressWarnings("boxing")
+	@Test
+	public void indexSeek() throws IOException {
+		List<Ref> refs = new ArrayList<>();
+		for (int i = 1; i <= 5670; i++) {
+			refs.add(ref(String.format("refs/heads/%04d", i), i));
+		}
+
+		byte[] table = write(refs);
+		assertTrue(stats.refIndexLevels() > 0);
+		assertTrue(stats.refIndexSize() > 0);
+		assertSeek(refs, read(table));
+	}
+
+	@SuppressWarnings("boxing")
+	@Test
+	public void noIndexScan() throws IOException {
+		List<Ref> refs = new ArrayList<>();
+		for (int i = 1; i <= 567; i++) {
+			refs.add(ref(String.format("refs/heads/%03d", i), i));
+		}
+
+		byte[] table = write(refs);
+		assertEquals(0, stats.refIndexLevels());
+		assertEquals(0, stats.refIndexSize());
+		assertEquals(table.length, stats.totalBytes());
+		assertScan(refs, read(table));
+	}
+
+	@SuppressWarnings("boxing")
+	@Test
+	public void noIndexSeek() throws IOException {
+		List<Ref> refs = new ArrayList<>();
+		for (int i = 1; i <= 567; i++) {
+			refs.add(ref(String.format("refs/heads/%03d", i), i));
+		}
+
+		byte[] table = write(refs);
+		assertEquals(0, stats.refIndexLevels());
+		assertSeek(refs, read(table));
+	}
+
 	public void unpeeledDoesNotWrite() {
 		try {
 			write(new ObjectIdRef.Unpeeled(PACKED, MASTER, id(1)));
@@ -312,6 +368,32 @@
 	}
 
 
+	private static void assertScan(List<Ref> refs, Reftable t)
+			throws IOException {
+		try (RefCursor rc = t.allRefs()) {
+			for (Ref exp : refs) {
+				assertTrue("has " + exp.getName(), rc.next());
+				Ref act = rc.getRef();
+				assertEquals(exp.getName(), act.getName());
+				assertEquals(exp.getObjectId(), act.getObjectId());
+			}
+			assertFalse(rc.next());
+		}
+	}
+
+	private static void assertSeek(List<Ref> refs, Reftable t)
+			throws IOException {
+		for (Ref exp : refs) {
+			try (RefCursor rc = t.seekRef(exp.getName())) {
+				assertTrue("has " + exp.getName(), rc.next());
+				Ref act = rc.getRef();
+				assertEquals(exp.getName(), act.getName());
+				assertEquals(exp.getObjectId(), act.getObjectId());
+				assertFalse(rc.next());
+			}
+		}
+	}
+
 	private static Ref ref(String name, int id) {
 		return new ObjectIdRef.PeeledNonTag(PACKED, name, id(id));
 	}