Improve BatchRefUpdateTest readability

* Factor out helpers for setting up and executing updates.
* Use common assert methods, with a special enum type that papers over
  the fact that there is no ReceiveCommand.Result for transaction
  aborted.
* Static import ReceiveCommand.Type constants.
* Add blank lines to separate repo setup, update execution, and asserts.

Change-Id: Ic3717f94331abfc7ae3e92065f3fe32026bf7cea
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/BatchRefUpdateTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/BatchRefUpdateTest.java
index 3cfc82d..06c47ac 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/BatchRefUpdateTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/BatchRefUpdateTest.java
@@ -43,22 +43,35 @@
 
 package org.eclipse.jgit.internal.storage.file;
 
+import static org.eclipse.jgit.internal.storage.file.BatchRefUpdateTest.Result.LOCK_FAILURE;
+import static org.eclipse.jgit.internal.storage.file.BatchRefUpdateTest.Result.OK;
+import static org.eclipse.jgit.internal.storage.file.BatchRefUpdateTest.Result.REJECTED_MISSING_OBJECT;
+import static org.eclipse.jgit.internal.storage.file.BatchRefUpdateTest.Result.REJECTED_NONFASTFORWARD;
+import static org.eclipse.jgit.internal.storage.file.BatchRefUpdateTest.Result.TRANSACTION_ABORTED;
 import static org.eclipse.jgit.lib.ObjectId.zeroId;
+import static org.eclipse.jgit.transport.ReceiveCommand.Type.CREATE;
+import static org.eclipse.jgit.transport.ReceiveCommand.Type.DELETE;
+import static org.eclipse.jgit.transport.ReceiveCommand.Type.UPDATE;
+import static org.eclipse.jgit.transport.ReceiveCommand.Type.UPDATE_NONFASTFORWARD;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import java.io.File;
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Predicate;
 
 import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
 import org.eclipse.jgit.junit.StrictWorkMonitor;
 import org.eclipse.jgit.junit.TestRepository;
 import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.BatchRefUpdate;
+import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.NullProgressMonitor;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.Ref;
@@ -103,43 +116,26 @@
 		B = repo.commit(repo.getRevWalk().parseCommit(A));
 	}
 
-	private BatchRefUpdate newBatchUpdate() {
-		BatchRefUpdate u = refdir.newBatchUpdate();
-		if (atomic) {
-			assertTrue(u.isAtomic());
-		} else {
-			u.setAtomic(false);
-		}
-		return u;
-	}
-
 	@Test
 	public void simpleNoForce() throws IOException {
 		writeLooseRef("refs/heads/master", A);
 		writeLooseRef("refs/heads/masters", B);
-		List<ReceiveCommand> commands = Arrays.asList(
-				new ReceiveCommand(A, B, "refs/heads/master",
-						ReceiveCommand.Type.UPDATE),
-				new ReceiveCommand(B, A, "refs/heads/masters",
-						ReceiveCommand.Type.UPDATE_NONFASTFORWARD));
-		BatchRefUpdate batchUpdate = newBatchUpdate();
-		batchUpdate.addCommand(commands);
-		batchUpdate.execute(new RevWalk(diskRepo), new StrictWorkMonitor());
-		Map<String, Ref> refs = refdir.getRefs(RefDatabase.ALL);
-		assertEquals(ReceiveCommand.Result.REJECTED_NONFASTFORWARD, commands
-				.get(1).getResult());
+
+		List<ReceiveCommand> cmds = Arrays.asList(
+				new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
+				new ReceiveCommand(B, A, "refs/heads/masters", UPDATE_NONFASTFORWARD));
+		execute(newBatchUpdate(cmds));
+
 		if (atomic) {
-			assertTrue(ReceiveCommand.isTransactionAborted(commands.get(0)));
-			assertEquals("[HEAD, refs/heads/master, refs/heads/masters]", refs
-					.keySet().toString());
-			assertEquals(A.getId(), refs.get("refs/heads/master").getObjectId());
-			assertEquals(B.getId(), refs.get("refs/heads/masters").getObjectId());
+			assertResults(cmds, TRANSACTION_ABORTED, REJECTED_NONFASTFORWARD);
+			assertRefs(
+					"refs/heads/master", A,
+					"refs/heads/masters", B);
 		} else {
-			assertEquals(ReceiveCommand.Result.OK, commands.get(0).getResult());
-			assertEquals("[HEAD, refs/heads/master, refs/heads/masters]", refs
-					.keySet().toString());
-			assertEquals(B.getId(), refs.get("refs/heads/master").getObjectId());
-			assertEquals(B.getId(), refs.get("refs/heads/masters").getObjectId());
+			assertResults(cmds, OK, REJECTED_NONFASTFORWARD);
+			assertRefs(
+					"refs/heads/master", B,
+					"refs/heads/masters", B);
 		}
 	}
 
@@ -147,85 +143,65 @@
 	public void simpleForce() throws IOException {
 		writeLooseRef("refs/heads/master", A);
 		writeLooseRef("refs/heads/masters", B);
-		List<ReceiveCommand> commands = Arrays.asList(
-				new ReceiveCommand(A, B, "refs/heads/master",
-						ReceiveCommand.Type.UPDATE),
-				new ReceiveCommand(B, A, "refs/heads/masters",
-						ReceiveCommand.Type.UPDATE_NONFASTFORWARD));
-		BatchRefUpdate batchUpdate = newBatchUpdate();
-		batchUpdate.setAllowNonFastForwards(true);
-		batchUpdate.addCommand(commands);
-		batchUpdate.execute(new RevWalk(diskRepo), new StrictWorkMonitor());
-		Map<String, Ref> refs = refdir.getRefs(RefDatabase.ALL);
-		assertEquals(ReceiveCommand.Result.OK, commands.get(0).getResult());
-		assertEquals(ReceiveCommand.Result.OK, commands.get(1).getResult());
-		assertEquals("[HEAD, refs/heads/master, refs/heads/masters]", refs
-				.keySet().toString());
-		assertEquals(B.getId(), refs.get("refs/heads/master").getObjectId());
-		assertEquals(A.getId(), refs.get("refs/heads/masters").getObjectId());
+
+		List<ReceiveCommand> cmds = Arrays.asList(
+				new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
+				new ReceiveCommand(B, A, "refs/heads/masters", UPDATE_NONFASTFORWARD));
+		execute(newBatchUpdate(cmds).setAllowNonFastForwards(true));
+
+		assertResults(cmds, OK, OK);
+		assertRefs(
+				"refs/heads/master", B,
+				"refs/heads/masters", A);
 	}
 
 	@Test
 	public void nonFastForwardDoesNotDoExpensiveMergeCheck() throws IOException {
 		writeLooseRef("refs/heads/master", B);
-		List<ReceiveCommand> commands = Arrays.asList(
-				new ReceiveCommand(B, A, "refs/heads/master",
-						ReceiveCommand.Type.UPDATE_NONFASTFORWARD));
-		BatchRefUpdate batchUpdate = newBatchUpdate();
-		batchUpdate.setAllowNonFastForwards(true);
-		batchUpdate.addCommand(commands);
-		batchUpdate.execute(new RevWalk(diskRepo) {
-			@Override
-			public boolean isMergedInto(RevCommit base, RevCommit tip) {
-				throw new AssertionError("isMergedInto() should not be called");
-			}
-		}, new StrictWorkMonitor());
-		Map<String, Ref> refs = refdir.getRefs(RefDatabase.ALL);
-		assertEquals(ReceiveCommand.Result.OK, commands.get(0).getResult());
-		assertEquals(A.getId(), refs.get("refs/heads/master").getObjectId());
+
+		List<ReceiveCommand> cmds = Arrays.asList(
+				new ReceiveCommand(B, A, "refs/heads/master", UPDATE_NONFASTFORWARD));
+		try (RevWalk rw = new RevWalk(diskRepo) {
+					@Override
+					public boolean isMergedInto(RevCommit base, RevCommit tip) {
+						throw new AssertionError("isMergedInto() should not be called");
+					}
+				}) {
+			newBatchUpdate(cmds)
+					.setAllowNonFastForwards(true)
+					.execute(rw, new StrictWorkMonitor());
+		}
+
+		assertResults(cmds, OK);
+		assertRefs("refs/heads/master", A);
 	}
 
 	@Test
 	public void fileDirectoryConflict() throws IOException {
 		writeLooseRef("refs/heads/master", A);
 		writeLooseRef("refs/heads/masters", B);
-		List<ReceiveCommand> commands = Arrays.asList(
-				new ReceiveCommand(A, B, "refs/heads/master",
-						ReceiveCommand.Type.UPDATE),
-				new ReceiveCommand(zeroId(), A, "refs/heads/master/x",
-						ReceiveCommand.Type.CREATE),
-				new ReceiveCommand(zeroId(), A, "refs/heads",
-						ReceiveCommand.Type.CREATE));
-		BatchRefUpdate batchUpdate = newBatchUpdate();
-		batchUpdate.setAllowNonFastForwards(true);
-		batchUpdate.addCommand(commands);
-		batchUpdate
-				.execute(new RevWalk(diskRepo), NullProgressMonitor.INSTANCE);
-		Map<String, Ref> refs = refdir.getRefs(RefDatabase.ALL);
+
+		List<ReceiveCommand> cmds = Arrays.asList(
+				new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
+				new ReceiveCommand(zeroId(), A, "refs/heads/master/x", CREATE),
+				new ReceiveCommand(zeroId(), A, "refs/heads", CREATE));
+		execute(newBatchUpdate(cmds).setAllowNonFastForwards(true), false);
 
 		if (atomic) {
 			// Atomic update sees that master and master/x are conflicting, then marks
 			// the first one in the list as LOCK_FAILURE and aborts the rest.
-			assertEquals(ReceiveCommand.Result.LOCK_FAILURE,
-					commands.get(0).getResult());
-			assertTrue(ReceiveCommand.isTransactionAborted(commands.get(1)));
-			assertTrue(ReceiveCommand.isTransactionAborted(commands.get(2)));
-			assertEquals("[HEAD, refs/heads/master, refs/heads/masters]", refs
-					.keySet().toString());
-			assertEquals(A.getId(), refs.get("refs/heads/master").getObjectId());
-			assertEquals(B.getId(), refs.get("refs/heads/masters").getObjectId());
+			assertResults(cmds,
+					LOCK_FAILURE, TRANSACTION_ABORTED, TRANSACTION_ABORTED);
+			assertRefs(
+					"refs/heads/master", A,
+					"refs/heads/masters", B);
 		} else {
 			// Non-atomic updates are applied in order: master succeeds, then master/x
 			// fails due to conflict.
-			assertEquals(ReceiveCommand.Result.OK, commands.get(0).getResult());
-			assertEquals(ReceiveCommand.Result.LOCK_FAILURE, commands.get(1)
-					.getResult());
-			assertEquals(ReceiveCommand.Result.LOCK_FAILURE, commands.get(2)
-					.getResult());
-			assertEquals("[HEAD, refs/heads/master, refs/heads/masters]", refs
-					.keySet().toString());
-			assertEquals(B.getId(), refs.get("refs/heads/master").getObjectId());
-			assertEquals(B.getId(), refs.get("refs/heads/masters").getObjectId());
+			assertResults(cmds, OK, LOCK_FAILURE, LOCK_FAILURE);
+			assertRefs(
+					"refs/heads/master", B,
+					"refs/heads/masters", B);
 		}
 	}
 
@@ -233,170 +209,205 @@
 	public void conflictThanksToDelete() throws IOException {
 		writeLooseRef("refs/heads/master", A);
 		writeLooseRef("refs/heads/masters", B);
-		List<ReceiveCommand> commands = Arrays.asList(
-				new ReceiveCommand(A, B, "refs/heads/master",
-						ReceiveCommand.Type.UPDATE),
-				new ReceiveCommand(zeroId(), A, "refs/heads/masters/x",
-						ReceiveCommand.Type.CREATE),
-				new ReceiveCommand(B, zeroId(), "refs/heads/masters",
-						ReceiveCommand.Type.DELETE));
-		BatchRefUpdate batchUpdate = newBatchUpdate();
-		batchUpdate.setAllowNonFastForwards(true);
-		batchUpdate.addCommand(commands);
-		batchUpdate.execute(new RevWalk(diskRepo), new StrictWorkMonitor());
-		Map<String, Ref> refs = refdir.getRefs(RefDatabase.ALL);
-		assertEquals(ReceiveCommand.Result.OK, commands.get(0).getResult());
-		assertEquals(ReceiveCommand.Result.OK, commands.get(1).getResult());
-		assertEquals(ReceiveCommand.Result.OK, commands.get(2).getResult());
-		assertEquals("[HEAD, refs/heads/master, refs/heads/masters/x]", refs
-				.keySet().toString());
-		assertEquals(A.getId(), refs.get("refs/heads/masters/x").getObjectId());
+
+		List<ReceiveCommand> cmds = Arrays.asList(
+				new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
+				new ReceiveCommand(zeroId(), A, "refs/heads/masters/x", CREATE),
+				new ReceiveCommand(B, zeroId(), "refs/heads/masters", DELETE));
+		execute(newBatchUpdate(cmds).setAllowNonFastForwards(true));
+
+		assertResults(cmds, OK, OK, OK);
+		assertRefs(
+				"refs/heads/master", B,
+				"refs/heads/masters/x", A);
 	}
 
 	@Test
 	public void updateToMissingObject() throws IOException {
 		writeLooseRef("refs/heads/master", A);
+
 		ObjectId bad =
 				ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
-		List<ReceiveCommand> commands = Arrays.asList(
-				new ReceiveCommand(A, bad, "refs/heads/master",
-						ReceiveCommand.Type.UPDATE),
-				new ReceiveCommand(zeroId(), B, "refs/heads/foo2",
-						ReceiveCommand.Type.CREATE));
-		BatchRefUpdate batchUpdate = newBatchUpdate();
-		batchUpdate.setAllowNonFastForwards(true);
-		batchUpdate.addCommand(commands);
-		batchUpdate.execute(new RevWalk(diskRepo), NullProgressMonitor.INSTANCE);
-		Map<String, Ref> refs = refdir.getRefs(RefDatabase.ALL);
-		assertEquals(ReceiveCommand.Result.REJECTED_MISSING_OBJECT,
-				commands.get(0).getResult());
+		List<ReceiveCommand> cmds = Arrays.asList(
+				new ReceiveCommand(A, bad, "refs/heads/master", UPDATE),
+				new ReceiveCommand(zeroId(), B, "refs/heads/foo2", CREATE));
+		execute(newBatchUpdate(cmds).setAllowNonFastForwards(true), false);
 
 		if (atomic) {
-			assertTrue(ReceiveCommand.isTransactionAborted(commands.get(1)));
-			assertEquals("[HEAD, refs/heads/master]", refs.keySet()
-					.toString());
-			assertEquals(A.getId(), refs.get("refs/heads/master").getObjectId());
+			assertResults(cmds, REJECTED_MISSING_OBJECT, TRANSACTION_ABORTED);
+			assertRefs("refs/heads/master", A);
 		} else {
-			assertEquals(ReceiveCommand.Result.OK, commands.get(1).getResult());
-			assertEquals("[HEAD, refs/heads/foo2, refs/heads/master]", refs.keySet()
-					.toString());
-			assertEquals(A.getId(), refs.get("refs/heads/master").getObjectId());
-			assertEquals(B.getId(), refs.get("refs/heads/foo2").getObjectId());
+			assertResults(cmds, REJECTED_MISSING_OBJECT, OK);
+			assertRefs(
+					"refs/heads/master", A,
+					"refs/heads/foo2", B);
 		}
 	}
 
 	@Test
 	public void addMissingObject() throws IOException {
 		writeLooseRef("refs/heads/master", A);
+
 		ObjectId bad =
 				ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
-		List<ReceiveCommand> commands = Arrays.asList(
-				new ReceiveCommand(A, B, "refs/heads/master",
-						ReceiveCommand.Type.UPDATE),
-				new ReceiveCommand(zeroId(), bad, "refs/heads/foo2",
-						ReceiveCommand.Type.CREATE));
-		BatchRefUpdate batchUpdate = newBatchUpdate();
-		batchUpdate.setAllowNonFastForwards(true);
-		batchUpdate.addCommand(commands);
-		batchUpdate.execute(new RevWalk(diskRepo), NullProgressMonitor.INSTANCE);
-		Map<String, Ref> refs = refdir.getRefs(RefDatabase.ALL);
-		assertEquals(ReceiveCommand.Result.REJECTED_MISSING_OBJECT,
-				commands.get(1).getResult());
+		List<ReceiveCommand> cmds = Arrays.asList(
+				new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
+				new ReceiveCommand(zeroId(), bad, "refs/heads/foo2", CREATE));
+		execute(newBatchUpdate(cmds).setAllowNonFastForwards(true), false);
 
 		if (atomic) {
-			assertTrue(ReceiveCommand.isTransactionAborted(commands.get(0)));
-			assertEquals("[HEAD, refs/heads/master]", refs.keySet().toString());
-			assertEquals(A.getId(), refs.get("refs/heads/master").getObjectId());
+			assertResults(cmds, TRANSACTION_ABORTED, REJECTED_MISSING_OBJECT);
+			assertRefs("refs/heads/master", A);
 		} else {
-			assertEquals(ReceiveCommand.Result.OK, commands.get(0).getResult());
-			assertEquals("[HEAD, refs/heads/master]", refs.keySet()
-					.toString());
-			assertEquals(B.getId(), refs.get("refs/heads/master").getObjectId());
+			assertResults(cmds, OK, REJECTED_MISSING_OBJECT);
+			assertRefs("refs/heads/master", B);
 		}
 	}
 
 	@Test
 	public void oneNonExistentRef() throws IOException {
-		List<ReceiveCommand> commands = Arrays.asList(
-				new ReceiveCommand(A, B, "refs/heads/foo1",
-						ReceiveCommand.Type.UPDATE),
-				new ReceiveCommand(zeroId(), B, "refs/heads/foo2",
-						ReceiveCommand.Type.CREATE));
-		BatchRefUpdate batchUpdate = newBatchUpdate();
-		batchUpdate.setAllowNonFastForwards(true);
-		batchUpdate.addCommand(commands);
-		batchUpdate.execute(new RevWalk(diskRepo), new StrictWorkMonitor());
-		Map<String, Ref> refs = refdir.getRefs(RefDatabase.ALL);
-		assertEquals(ReceiveCommand.Result.LOCK_FAILURE,
-				commands.get(0).getResult());
+		List<ReceiveCommand> cmds = Arrays.asList(
+				new ReceiveCommand(A, B, "refs/heads/foo1", UPDATE),
+				new ReceiveCommand(zeroId(), B, "refs/heads/foo2", CREATE));
+		execute(newBatchUpdate(cmds).setAllowNonFastForwards(true));
 
 		if (atomic) {
-			assertTrue(ReceiveCommand.isTransactionAborted(commands.get(1)));
-			assertEquals("[]", refs.keySet().toString());
+			assertResults(cmds, LOCK_FAILURE, TRANSACTION_ABORTED);
+			assertRefs();
 		} else {
-			assertEquals(ReceiveCommand.Result.OK, commands.get(1).getResult());
-			assertEquals("[refs/heads/foo2]", refs.keySet().toString());
-			assertEquals(B.getId(), refs.get("refs/heads/foo2").getObjectId());
+			assertResults(cmds, LOCK_FAILURE, OK);
+			assertRefs("refs/heads/foo2", B);
 		}
 	}
 
 	@Test
 	public void oneRefWrongOldValue() throws IOException {
 		writeLooseRef("refs/heads/master", A);
-		List<ReceiveCommand> commands = Arrays.asList(
-				new ReceiveCommand(B, B, "refs/heads/master",
-						ReceiveCommand.Type.UPDATE),
-				new ReceiveCommand(zeroId(), B, "refs/heads/foo2",
-						ReceiveCommand.Type.CREATE));
-		BatchRefUpdate batchUpdate = newBatchUpdate();
-		batchUpdate.setAllowNonFastForwards(true);
-		batchUpdate.addCommand(commands);
-		batchUpdate.execute(new RevWalk(diskRepo), new StrictWorkMonitor());
-		Map<String, Ref> refs = refdir.getRefs(RefDatabase.ALL);
-		assertEquals(ReceiveCommand.Result.LOCK_FAILURE,
-				commands.get(0).getResult());
+
+		List<ReceiveCommand> cmds = Arrays.asList(
+				new ReceiveCommand(B, B, "refs/heads/master", UPDATE),
+				new ReceiveCommand(zeroId(), B, "refs/heads/foo2", CREATE));
+		execute(newBatchUpdate(cmds).setAllowNonFastForwards(true));
 
 		if (atomic) {
-			assertTrue(ReceiveCommand.isTransactionAborted(commands.get(1)));
-			assertEquals("[HEAD, refs/heads/master]", refs.keySet().toString());
-			assertEquals(A.getId(), refs.get("refs/heads/master").getObjectId());
+			assertResults(cmds, LOCK_FAILURE, TRANSACTION_ABORTED);
+			assertRefs("refs/heads/master", A);
 		} else {
-			assertEquals(ReceiveCommand.Result.OK, commands.get(1).getResult());
-			assertEquals("[HEAD, refs/heads/foo2, refs/heads/master]", refs
-					.keySet().toString());
-			assertEquals(A.getId(), refs.get("refs/heads/master").getObjectId());
-			assertEquals(B.getId(), refs.get("refs/heads/foo2").getObjectId());
+			assertResults(cmds, LOCK_FAILURE, OK);
+			assertRefs(
+					"refs/heads/master", A,
+					"refs/heads/foo2", B);
 		}
 	}
 
 	@Test
 	public void nonExistentRef() throws IOException {
 		writeLooseRef("refs/heads/master", A);
-		List<ReceiveCommand> commands = Arrays.asList(
-				new ReceiveCommand(A, B, "refs/heads/master",
-						ReceiveCommand.Type.UPDATE),
-				new ReceiveCommand(A, zeroId(), "refs/heads/foo2",
-						ReceiveCommand.Type.DELETE));
-		BatchRefUpdate batchUpdate = newBatchUpdate();
-		batchUpdate.setAllowNonFastForwards(true);
-		batchUpdate.addCommand(commands);
-		batchUpdate.execute(new RevWalk(diskRepo), new StrictWorkMonitor());
-		Map<String, Ref> refs = refdir.getRefs(RefDatabase.ALL);
-		assertEquals(ReceiveCommand.Result.LOCK_FAILURE,
-				commands.get(1).getResult());
+
+		List<ReceiveCommand> cmds = Arrays.asList(
+				new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
+				new ReceiveCommand(A, zeroId(), "refs/heads/foo2", DELETE));
+		execute(newBatchUpdate(cmds).setAllowNonFastForwards(true));
 
 		if (atomic) {
-			assertTrue(ReceiveCommand.isTransactionAborted(commands.get(0)));
-			assertEquals("[HEAD, refs/heads/master]", refs.keySet().toString());
-			assertEquals(A.getId(), refs.get("refs/heads/master").getObjectId());
+			assertResults(cmds, TRANSACTION_ABORTED, LOCK_FAILURE);
+			assertRefs("refs/heads/master", A);
 		} else {
-			assertEquals(ReceiveCommand.Result.OK, commands.get(0).getResult());
-			assertEquals("[HEAD, refs/heads/master]", refs.keySet().toString());
-			assertEquals(B.getId(), refs.get("refs/heads/master").getObjectId());
+			assertResults(cmds, OK, LOCK_FAILURE);
+			assertRefs("refs/heads/master", B);
 		}
 	}
 
 	private void writeLooseRef(String name, AnyObjectId id) throws IOException {
 		write(new File(diskRepo.getDirectory(), name), id.name() + "\n");
 	}
+
+	private BatchRefUpdate newBatchUpdate(List<ReceiveCommand> cmds) {
+		BatchRefUpdate u = refdir.newBatchUpdate();
+		if (atomic) {
+			assertTrue(u.isAtomic());
+		} else {
+			u.setAtomic(false);
+		}
+		u.addCommand(cmds);
+		return u;
+	}
+
+	private void execute(BatchRefUpdate u) throws IOException {
+		execute(u, false);
+	}
+
+	private void execute(BatchRefUpdate u, boolean strictWork) throws IOException {
+		try (RevWalk rw = new RevWalk(diskRepo)) {
+			u.execute(rw,
+					strictWork ? new StrictWorkMonitor() : NullProgressMonitor.INSTANCE);
+		}
+	}
+
+	private void assertRefs(Object... args) throws IOException {
+		if (args.length % 2 != 0) {
+			throw new IllegalArgumentException(
+					"expected even number of args: " + Arrays.toString(args));
+		}
+
+		Map<String, AnyObjectId> expected = new LinkedHashMap<>();
+		for (int i = 0; i < args.length; i += 2) {
+			expected.put((String) args[i], (AnyObjectId) args[i + 1]);
+		}
+
+		Map<String, Ref> refs = refdir.getRefs(RefDatabase.ALL);
+		Ref actualHead = refs.remove(Constants.HEAD);
+		if (actualHead != null) {
+			String actualLeafName = actualHead.getLeaf().getName();
+			assertEquals(
+					"expected HEAD to point to refs/heads/master, got: " + actualLeafName,
+					"refs/heads/master", actualLeafName);
+			AnyObjectId expectedMaster = expected.get("refs/heads/master");
+			assertNotNull("expected master ref since HEAD exists", expectedMaster);
+			assertEquals(expectedMaster, actualHead.getObjectId());
+		}
+
+		Map<String, AnyObjectId> actual = new LinkedHashMap<>();
+		refs.forEach((n, r) -> actual.put(n, r.getObjectId()));
+
+		assertEquals(expected.keySet(), actual.keySet());
+		actual.forEach((n, a) -> assertEquals(n, expected.get(n), a));
+	}
+
+	enum Result {
+		OK(ReceiveCommand.Result.OK),
+		LOCK_FAILURE(ReceiveCommand.Result.LOCK_FAILURE),
+		REJECTED_NONFASTFORWARD(ReceiveCommand.Result.REJECTED_NONFASTFORWARD),
+		REJECTED_MISSING_OBJECT(ReceiveCommand.Result.REJECTED_MISSING_OBJECT),
+		TRANSACTION_ABORTED(ReceiveCommand::isTransactionAborted);
+
+		final Predicate<? super ReceiveCommand> p;
+
+		private Result(Predicate<? super ReceiveCommand> p) {
+			this.p = p;
+		}
+
+		private Result(ReceiveCommand.Result result) {
+			this(c -> c.getResult() == result);
+		}
+	}
+
+	private void assertResults(
+			List<ReceiveCommand> cmds, Result... expected) {
+		if (expected.length != cmds.size()) {
+			throw new IllegalArgumentException(
+					"expected " + cmds.size() + " result args");
+		}
+		for (int i = 0; i < cmds.size(); i++) {
+			ReceiveCommand c = cmds.get(i);
+			Result r = expected[i];
+			assertTrue(
+					String.format(
+							"result of command (%d) should be %s: %s %s%s",
+							Integer.valueOf(i), r, c,
+							c.getResult(),
+							c.getMessage() != null ? " (" + c.getMessage() + ")" : ""),
+					r.p.test(c));
+		}
+	}
 }