Browse Source

BatchRefUpdateTest: Accurately assert RefsChangedEvent(s) fired

Update tests to record the number of events fired post-setup and only
assert for events fired during BatchRefUpdate.execute. For tests which
use writeLooseRef to setup refs, create new tests which assert the
number of RefsChangedEvent(s) rather than updating the existing ones
to call RefDirectory.exactRef as it changes the code path.

Change-Id: I0187811628d179d9c7e874c9bb8a7ddb44dd9df4
Signed-off-by: Kaushik Lingarkar <quic_kaushikl@quicinc.com>
tags/v5.1.16.202106041830-r
Kaushik Lingarkar 3 years ago
parent
commit
294a99af25

+ 306
- 40
org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/BatchRefUpdateTest.java View File

assertRefs( assertRefs(
"refs/heads/master", A, "refs/heads/master", A,
"refs/heads/masters", B); "refs/heads/masters", B);
assertEquals(1, refsChangedEvents);
} else { } else {
assertResults(cmds, OK, REJECTED_NONFASTFORWARD); assertResults(cmds, OK, REJECTED_NONFASTFORWARD);
assertRefs( assertRefs(
"refs/heads/master", B, "refs/heads/master", B,
"refs/heads/masters", B); "refs/heads/masters", B);
assertEquals(2, refsChangedEvents);
} }
} }


@Test
public void simpleNoForceRefsChangedEvents() throws IOException {
writeLooseRef("refs/heads/master", A);
writeLooseRef("refs/heads/masters", B);
refdir.exactRef("refs/heads/master");
refdir.exactRef("refs/heads/masters");
int initialRefsChangedEvents = refsChangedEvents;

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));

assertEquals(atomic ? initialRefsChangedEvents
: initialRefsChangedEvents + 1, refsChangedEvents);
}

@Test @Test
public void simpleForce() throws IOException { public void simpleForce() throws IOException {
writeLooseRef("refs/heads/master", A); writeLooseRef("refs/heads/master", A);
assertRefs( assertRefs(
"refs/heads/master", B, "refs/heads/master", B,
"refs/heads/masters", A); "refs/heads/masters", A);
assertEquals(atomic ? 2 : 3, refsChangedEvents);
}

@Test
public void simpleForceRefsChangedEvents() throws IOException {
writeLooseRef("refs/heads/master", A);
writeLooseRef("refs/heads/masters", B);
refdir.exactRef("refs/heads/master");
refdir.exactRef("refs/heads/masters");
int initialRefsChangedEvents = refsChangedEvents;

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));

assertEquals(atomic ? initialRefsChangedEvents + 1
: initialRefsChangedEvents + 2, refsChangedEvents);
} }


@Test @Test


assertResults(cmds, OK); assertResults(cmds, OK);
assertRefs("refs/heads/master", A); assertRefs("refs/heads/master", A);
assertEquals(2, refsChangedEvents);
}

@Test
public void nonFastForwardDoesNotDoExpensiveMergeCheckRefsChangedEvents()
throws IOException {
writeLooseRef("refs/heads/master", B);
refdir.exactRef("refs/heads/master");
int initialRefsChangedEvents = refsChangedEvents;

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());
}

assertEquals(initialRefsChangedEvents + 1, refsChangedEvents);
} }


@Test @Test
assertRefs( assertRefs(
"refs/heads/master", A, "refs/heads/master", A,
"refs/heads/masters", B); "refs/heads/masters", B);
assertEquals(1, refsChangedEvents);
} else { } else {
// Non-atomic updates are applied in order: master succeeds, then master/x // Non-atomic updates are applied in order: master succeeds, then master/x
// fails due to conflict. // fails due to conflict.
assertRefs( assertRefs(
"refs/heads/master", B, "refs/heads/master", B,
"refs/heads/masters", B); "refs/heads/masters", B);
assertEquals(2, refsChangedEvents);
} }
} }


@Test
public void fileDirectoryConflictRefsChangedEvents() throws IOException {
writeLooseRef("refs/heads/master", A);
writeLooseRef("refs/heads/masters", B);
refdir.exactRef("refs/heads/master");
refdir.exactRef("refs/heads/masters");
int initialRefsChangedEvents = refsChangedEvents;

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);

assertEquals(atomic ? initialRefsChangedEvents
: initialRefsChangedEvents + 1, refsChangedEvents);
}

@Test @Test
public void conflictThanksToDelete() throws IOException { public void conflictThanksToDelete() throws IOException {
writeLooseRef("refs/heads/master", A); writeLooseRef("refs/heads/master", A);
assertRefs( assertRefs(
"refs/heads/master", B, "refs/heads/master", B,
"refs/heads/masters/x", A); "refs/heads/masters/x", A);
if (atomic) {
assertEquals(2, refsChangedEvents);
} else {
// The non-atomic case actually produces 5 events, but that's an
// implementation detail. We expect at least 4 events, one for the
// initial read due to writeLooseRef(), and then one for each
// successful ref update.
assertTrue(refsChangedEvents >= 4);
}
}

@Test
public void conflictThanksToDeleteRefsChangedEvents() throws IOException {
writeLooseRef("refs/heads/master", A);
writeLooseRef("refs/heads/masters", B);
refdir.exactRef("refs/heads/master");
refdir.exactRef("refs/heads/masters");
int initialRefsChangedEvents = refsChangedEvents;

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));

assertEquals(atomic ? initialRefsChangedEvents + 1
: initialRefsChangedEvents + 3, refsChangedEvents);
} }


@Test @Test
if (atomic) { if (atomic) {
assertResults(cmds, REJECTED_MISSING_OBJECT, TRANSACTION_ABORTED); assertResults(cmds, REJECTED_MISSING_OBJECT, TRANSACTION_ABORTED);
assertRefs("refs/heads/master", A); assertRefs("refs/heads/master", A);
assertEquals(1, refsChangedEvents);
} else { } else {
assertResults(cmds, REJECTED_MISSING_OBJECT, OK); assertResults(cmds, REJECTED_MISSING_OBJECT, OK);
assertRefs( assertRefs(
"refs/heads/master", A, "refs/heads/master", A,
"refs/heads/foo2", B); "refs/heads/foo2", B);
assertEquals(2, refsChangedEvents);
} }
} }


@Test
public void updateToMissingObjectRefsChangedEvents() throws IOException {
writeLooseRef("refs/heads/master", A);
refdir.exactRef("refs/heads/master");
int initialRefsChangedEvents = refsChangedEvents;

ObjectId bad = ObjectId
.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
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);

assertEquals(atomic ? initialRefsChangedEvents
: initialRefsChangedEvents + 1, refsChangedEvents);
}

@Test @Test
public void addMissingObject() throws IOException { public void addMissingObject() throws IOException {
writeLooseRef("refs/heads/master", A); writeLooseRef("refs/heads/master", A);
if (atomic) { if (atomic) {
assertResults(cmds, TRANSACTION_ABORTED, REJECTED_MISSING_OBJECT); assertResults(cmds, TRANSACTION_ABORTED, REJECTED_MISSING_OBJECT);
assertRefs("refs/heads/master", A); assertRefs("refs/heads/master", A);
assertEquals(1, refsChangedEvents);
} else { } else {
assertResults(cmds, OK, REJECTED_MISSING_OBJECT); assertResults(cmds, OK, REJECTED_MISSING_OBJECT);
assertRefs("refs/heads/master", B); assertRefs("refs/heads/master", B);
assertEquals(2, refsChangedEvents);
} }
} }


@Test
public void addMissingObjectRefsChangedEvents() throws IOException {
writeLooseRef("refs/heads/master", A);
refdir.exactRef("refs/heads/master");
int initialRefsChangedEvents = refsChangedEvents;

ObjectId bad = ObjectId
.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
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);

assertEquals(atomic ? initialRefsChangedEvents
: initialRefsChangedEvents + 1, refsChangedEvents);
}

@Test @Test
public void oneNonExistentRef() throws IOException { public void oneNonExistentRef() throws IOException {
List<ReceiveCommand> cmds = Arrays.asList( List<ReceiveCommand> cmds = Arrays.asList(
if (atomic) { if (atomic) {
assertResults(cmds, LOCK_FAILURE, TRANSACTION_ABORTED); assertResults(cmds, LOCK_FAILURE, TRANSACTION_ABORTED);
assertRefs("refs/heads/master", A); assertRefs("refs/heads/master", A);
assertEquals(1, refsChangedEvents);
} else { } else {
assertResults(cmds, LOCK_FAILURE, OK); assertResults(cmds, LOCK_FAILURE, OK);
assertRefs( assertRefs(
"refs/heads/master", A, "refs/heads/master", A,
"refs/heads/foo2", B); "refs/heads/foo2", B);
assertEquals(2, refsChangedEvents);
} }
} }


@Test
public void oneRefWrongOldValueRefsChangedEvents() throws IOException {
writeLooseRef("refs/heads/master", A);
refdir.exactRef("refs/heads/master");
int initialRefsChangedEvents = refsChangedEvents;

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));

assertEquals(atomic ? initialRefsChangedEvents
: initialRefsChangedEvents + 1, refsChangedEvents);
}

@Test @Test
public void nonExistentRef() throws IOException { public void nonExistentRef() throws IOException {
writeLooseRef("refs/heads/master", A); writeLooseRef("refs/heads/master", A);
if (atomic) { if (atomic) {
assertResults(cmds, TRANSACTION_ABORTED, LOCK_FAILURE); assertResults(cmds, TRANSACTION_ABORTED, LOCK_FAILURE);
assertRefs("refs/heads/master", A); assertRefs("refs/heads/master", A);
assertEquals(1, refsChangedEvents);
} else { } else {
assertResults(cmds, OK, LOCK_FAILURE); assertResults(cmds, OK, LOCK_FAILURE);
assertRefs("refs/heads/master", B); assertRefs("refs/heads/master", B);
assertEquals(2, refsChangedEvents);
} }
} }


@Test
public void nonExistentRefRefsChangedEvents() throws IOException {
writeLooseRef("refs/heads/master", A);
refdir.exactRef("refs/heads/master");
int initialRefsChangedEvents = refsChangedEvents;

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));

assertEquals(atomic ? initialRefsChangedEvents
: initialRefsChangedEvents + 1, refsChangedEvents);
}

@Test @Test
public void noRefLog() throws IOException { public void noRefLog() throws IOException {
writeRef("refs/heads/master", A); writeRef("refs/heads/master", A);
int initialRefsChangedEvents = refsChangedEvents;


Map<String, ReflogEntry> oldLogs = Map<String, ReflogEntry> oldLogs =
getLastReflogs("refs/heads/master", "refs/heads/branch"); getLastReflogs("refs/heads/master", "refs/heads/branch");
assertRefs( assertRefs(
"refs/heads/master", B, "refs/heads/master", B,
"refs/heads/branch", B); "refs/heads/branch", B);
assertEquals(atomic ? 2 : 3, refsChangedEvents);
assertEquals(atomic ? initialRefsChangedEvents + 1
: initialRefsChangedEvents + 2, refsChangedEvents);
assertReflogUnchanged(oldLogs, "refs/heads/master"); assertReflogUnchanged(oldLogs, "refs/heads/master");
assertReflogUnchanged(oldLogs, "refs/heads/branch"); assertReflogUnchanged(oldLogs, "refs/heads/branch");
} }
public void reflogDefaultIdent() throws IOException { public void reflogDefaultIdent() throws IOException {
writeRef("refs/heads/master", A); writeRef("refs/heads/master", A);
writeRef("refs/heads/branch2", A); writeRef("refs/heads/branch2", A);
int initialRefsChangedEvents = refsChangedEvents;


Map<String, ReflogEntry> oldLogs = getLastReflogs( Map<String, ReflogEntry> oldLogs = getLastReflogs(
"refs/heads/master", "refs/heads/branch1", "refs/heads/branch2"); "refs/heads/master", "refs/heads/branch1", "refs/heads/branch2");
"refs/heads/master", B, "refs/heads/master", B,
"refs/heads/branch1", B, "refs/heads/branch1", B,
"refs/heads/branch2", A); "refs/heads/branch2", A);
assertEquals(atomic ? 3 : 4, refsChangedEvents);
assertEquals(atomic ? initialRefsChangedEvents + 1
: initialRefsChangedEvents + 2, refsChangedEvents);
assertReflogEquals( assertReflogEquals(
reflog(A, B, new PersonIdent(diskRepo), "a reflog"), reflog(A, B, new PersonIdent(diskRepo), "a reflog"),
getLastReflog("refs/heads/master")); getLastReflog("refs/heads/master"));
public void reflogAppendStatusNoMessage() throws IOException { public void reflogAppendStatusNoMessage() throws IOException {
writeRef("refs/heads/master", A); writeRef("refs/heads/master", A);
writeRef("refs/heads/branch1", B); writeRef("refs/heads/branch1", B);
int initialRefsChangedEvents = refsChangedEvents;


List<ReceiveCommand> cmds = Arrays.asList( List<ReceiveCommand> cmds = Arrays.asList(
new ReceiveCommand(A, B, "refs/heads/master", UPDATE), new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
"refs/heads/master", B, "refs/heads/master", B,
"refs/heads/branch1", A, "refs/heads/branch1", A,
"refs/heads/branch2", A); "refs/heads/branch2", A);
assertEquals(atomic ? 3 : 5, refsChangedEvents);
assertEquals(atomic ? initialRefsChangedEvents + 1
: initialRefsChangedEvents + 3,
refsChangedEvents);
assertReflogEquals( assertReflogEquals(
// Always forced; setAllowNonFastForwards(true) bypasses the check. // Always forced; setAllowNonFastForwards(true) bypasses the check.
reflog(A, B, new PersonIdent(diskRepo), "forced-update"), reflog(A, B, new PersonIdent(diskRepo), "forced-update"),
@Test @Test
public void reflogAppendStatusFastForward() throws IOException { public void reflogAppendStatusFastForward() throws IOException {
writeRef("refs/heads/master", A); writeRef("refs/heads/master", A);
int initialRefsChangedEvents = refsChangedEvents;


List<ReceiveCommand> cmds = Arrays.asList( List<ReceiveCommand> cmds = Arrays.asList(
new ReceiveCommand(A, B, "refs/heads/master", UPDATE)); new ReceiveCommand(A, B, "refs/heads/master", UPDATE));


assertResults(cmds, OK); assertResults(cmds, OK);
assertRefs("refs/heads/master", B); assertRefs("refs/heads/master", B);
assertEquals(2, refsChangedEvents);
assertEquals(initialRefsChangedEvents + 1, refsChangedEvents);
assertReflogEquals( assertReflogEquals(
reflog(A, B, new PersonIdent(diskRepo), "fast-forward"), reflog(A, B, new PersonIdent(diskRepo), "fast-forward"),
getLastReflog("refs/heads/master")); getLastReflog("refs/heads/master"));
@Test @Test
public void reflogAppendStatusWithMessage() throws IOException { public void reflogAppendStatusWithMessage() throws IOException {
writeRef("refs/heads/master", A); writeRef("refs/heads/master", A);
int initialRefsChangedEvents = refsChangedEvents;


List<ReceiveCommand> cmds = Arrays.asList( List<ReceiveCommand> cmds = Arrays.asList(
new ReceiveCommand(A, B, "refs/heads/master", UPDATE), new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
assertRefs( assertRefs(
"refs/heads/master", B, "refs/heads/master", B,
"refs/heads/branch", A); "refs/heads/branch", A);
assertEquals(atomic ? 2 : 3, refsChangedEvents);
assertEquals(atomic ? initialRefsChangedEvents + 1
: initialRefsChangedEvents + 2, refsChangedEvents);
assertReflogEquals( assertReflogEquals(
reflog(A, B, new PersonIdent(diskRepo), "a reflog: fast-forward"), reflog(A, B, new PersonIdent(diskRepo), "a reflog: fast-forward"),
getLastReflog("refs/heads/master")); getLastReflog("refs/heads/master"));
@Test @Test
public void reflogCustomIdent() throws IOException { public void reflogCustomIdent() throws IOException {
writeRef("refs/heads/master", A); writeRef("refs/heads/master", A);
int initialRefsChangedEvents = refsChangedEvents;


List<ReceiveCommand> cmds = Arrays.asList( List<ReceiveCommand> cmds = Arrays.asList(
new ReceiveCommand(A, B, "refs/heads/master", UPDATE), new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
.setRefLogIdent(ident)); .setRefLogIdent(ident));


assertResults(cmds, OK, OK); assertResults(cmds, OK, OK);
assertEquals(atomic ? 2 : 3, refsChangedEvents);
assertEquals(atomic ? initialRefsChangedEvents + 1
: initialRefsChangedEvents + 2, refsChangedEvents);
assertRefs( assertRefs(
"refs/heads/master", B, "refs/heads/master", B,
"refs/heads/branch", B); "refs/heads/branch", B);
public void reflogDelete() throws IOException { public void reflogDelete() throws IOException {
writeRef("refs/heads/master", A); writeRef("refs/heads/master", A);
writeRef("refs/heads/branch", A); writeRef("refs/heads/branch", A);
int initialRefsChangedEvents = refsChangedEvents;

assertEquals( assertEquals(
2, getLastReflogs("refs/heads/master", "refs/heads/branch").size()); 2, getLastReflogs("refs/heads/master", "refs/heads/branch").size());




assertResults(cmds, OK, OK); assertResults(cmds, OK, OK);
assertRefs("refs/heads/branch", B); assertRefs("refs/heads/branch", B);
assertEquals(atomic ? 3 : 4, refsChangedEvents);
assertEquals(atomic ? initialRefsChangedEvents + 1
: initialRefsChangedEvents + 2, refsChangedEvents);
assertNull(getLastReflog("refs/heads/master")); assertNull(getLastReflog("refs/heads/master"));
assertReflogEquals( assertReflogEquals(
reflog(A, B, new PersonIdent(diskRepo), "a reflog"), reflog(A, B, new PersonIdent(diskRepo), "a reflog"),
@Test @Test
public void reflogFileDirectoryConflict() throws IOException { public void reflogFileDirectoryConflict() throws IOException {
writeRef("refs/heads/master", A); writeRef("refs/heads/master", A);
int initialRefsChangedEvents = refsChangedEvents;


List<ReceiveCommand> cmds = Arrays.asList( List<ReceiveCommand> cmds = Arrays.asList(
new ReceiveCommand(A, zeroId(), "refs/heads/master", DELETE), new ReceiveCommand(A, zeroId(), "refs/heads/master", DELETE),


assertResults(cmds, OK, OK); assertResults(cmds, OK, OK);
assertRefs("refs/heads/master/x", A); assertRefs("refs/heads/master/x", A);
assertEquals(atomic ? 2 : 3, refsChangedEvents);
assertEquals(atomic ? initialRefsChangedEvents + 1
: initialRefsChangedEvents + 2, refsChangedEvents);
assertNull(getLastReflog("refs/heads/master")); assertNull(getLastReflog("refs/heads/master"));
assertReflogEquals( assertReflogEquals(
reflog(zeroId(), A, new PersonIdent(diskRepo), "a reflog"), reflog(zeroId(), A, new PersonIdent(diskRepo), "a reflog"),
@Test @Test
public void reflogOnLockFailure() throws IOException { public void reflogOnLockFailure() throws IOException {
writeRef("refs/heads/master", A); writeRef("refs/heads/master", A);
int initialRefsChangedEvents = refsChangedEvents;


Map<String, ReflogEntry> oldLogs = Map<String, ReflogEntry> oldLogs =
getLastReflogs("refs/heads/master", "refs/heads/branch"); getLastReflogs("refs/heads/master", "refs/heads/branch");


if (atomic) { if (atomic) {
assertResults(cmds, TRANSACTION_ABORTED, LOCK_FAILURE); assertResults(cmds, TRANSACTION_ABORTED, LOCK_FAILURE);
assertEquals(1, refsChangedEvents);
assertEquals(initialRefsChangedEvents, refsChangedEvents);
assertReflogUnchanged(oldLogs, "refs/heads/master"); assertReflogUnchanged(oldLogs, "refs/heads/master");
assertReflogUnchanged(oldLogs, "refs/heads/branch"); assertReflogUnchanged(oldLogs, "refs/heads/branch");
} else { } else {
assertResults(cmds, OK, LOCK_FAILURE); assertResults(cmds, OK, LOCK_FAILURE);
assertEquals(2, refsChangedEvents);
assertEquals(initialRefsChangedEvents + 1, refsChangedEvents);
assertReflogEquals( assertReflogEquals(
reflog(A, B, new PersonIdent(diskRepo), "a reflog"), reflog(A, B, new PersonIdent(diskRepo), "a reflog"),
getLastReflog("refs/heads/master")); getLastReflog("refs/heads/master"));
@Test @Test
public void overrideRefLogMessage() throws Exception { public void overrideRefLogMessage() throws Exception {
writeRef("refs/heads/master", A); writeRef("refs/heads/master", A);
int initialRefsChangedEvents = refsChangedEvents;


List<ReceiveCommand> cmds = Arrays.asList( List<ReceiveCommand> cmds = Arrays.asList(
new ReceiveCommand(A, B, "refs/heads/master", UPDATE), new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
.setRefLogMessage("a reflog", true)); .setRefLogMessage("a reflog", true));


assertResults(cmds, OK, OK); assertResults(cmds, OK, OK);
assertEquals(atomic ? 2 : 3, refsChangedEvents);
assertEquals(atomic ? initialRefsChangedEvents + 1
: initialRefsChangedEvents + 2, refsChangedEvents);
assertReflogEquals( assertReflogEquals(
reflog(A, B, ident, "custom log"), reflog(A, B, ident, "custom log"),
getLastReflog("refs/heads/master"), getLastReflog("refs/heads/master"),
@Test @Test
public void overrideDisableRefLog() throws Exception { public void overrideDisableRefLog() throws Exception {
writeRef("refs/heads/master", A); writeRef("refs/heads/master", A);
int initialRefsChangedEvents = refsChangedEvents;


Map<String, ReflogEntry> oldLogs = Map<String, ReflogEntry> oldLogs =
getLastReflogs("refs/heads/master", "refs/heads/branch"); getLastReflogs("refs/heads/master", "refs/heads/branch");
execute(newBatchUpdate(cmds).setRefLogMessage("a reflog", true)); execute(newBatchUpdate(cmds).setRefLogMessage("a reflog", true));


assertResults(cmds, OK, OK); assertResults(cmds, OK, OK);
assertEquals(atomic ? 2 : 3, refsChangedEvents);
assertEquals(atomic ? initialRefsChangedEvents + 1
: initialRefsChangedEvents + 2, refsChangedEvents);
assertReflogUnchanged(oldLogs, "refs/heads/master"); assertReflogUnchanged(oldLogs, "refs/heads/master");
assertReflogEquals( assertReflogEquals(
reflog(zeroId(), B, new PersonIdent(diskRepo), "a reflog: created"), reflog(zeroId(), B, new PersonIdent(diskRepo), "a reflog: created"),
if (atomic) { if (atomic) {
assertResults(cmds, LOCK_FAILURE, TRANSACTION_ABORTED); assertResults(cmds, LOCK_FAILURE, TRANSACTION_ABORTED);
assertRefs("refs/heads/master", A); assertRefs("refs/heads/master", A);
assertEquals(1, refsChangedEvents);
} else { } else {
// Only operates on loose refs, doesn't care that packed-refs is locked. // Only operates on loose refs, doesn't care that packed-refs is locked.
assertResults(cmds, OK, OK); assertResults(cmds, OK, OK);
assertRefs( assertRefs(
"refs/heads/master", B, "refs/heads/master", B,
"refs/heads/branch", B); "refs/heads/branch", B);
assertEquals(3, refsChangedEvents);
} }
} finally { } finally {
myLock.unlock(); myLock.unlock();
} }
} }


@Test
public void packedRefsLockFailureRefsChangedEvents() throws Exception {
writeLooseRef("refs/heads/master", A);
refdir.exactRef("refs/heads/master");
int initialRefsChangedEvents = refsChangedEvents;

List<ReceiveCommand> cmds = Arrays.asList(
new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
new ReceiveCommand(zeroId(), B, "refs/heads/branch", CREATE));

LockFile myLock = refdir.lockPackedRefs();
try {
execute(newBatchUpdate(cmds).setAllowNonFastForwards(true));

assertEquals(
atomic ? initialRefsChangedEvents
: initialRefsChangedEvents + 2,
refsChangedEvents);
} finally {
myLock.unlock();
}
}

@Test @Test
public void oneRefLockFailure() throws Exception { public void oneRefLockFailure() throws Exception {
writeLooseRef("refs/heads/master", A); writeLooseRef("refs/heads/master", A);
if (atomic) { if (atomic) {
assertResults(cmds, TRANSACTION_ABORTED, LOCK_FAILURE); assertResults(cmds, TRANSACTION_ABORTED, LOCK_FAILURE);
assertRefs("refs/heads/master", A); assertRefs("refs/heads/master", A);
assertEquals(1, refsChangedEvents);
} else { } else {
assertResults(cmds, OK, LOCK_FAILURE); assertResults(cmds, OK, LOCK_FAILURE);
assertRefs( assertRefs(
"refs/heads/branch", B, "refs/heads/branch", B,
"refs/heads/master", A); "refs/heads/master", A);
assertEquals(2, refsChangedEvents);
} }
} finally { } finally {
myLock.unlock(); myLock.unlock();
} }
} }


@Test
public void oneRefLockFailureRefsChangedEvents() throws Exception {
writeLooseRef("refs/heads/master", A);
refdir.exactRef("refs/heads/master");
int initialRefsChangedEvents = refsChangedEvents;

List<ReceiveCommand> cmds = Arrays.asList(
new ReceiveCommand(zeroId(), B, "refs/heads/branch", CREATE),
new ReceiveCommand(A, B, "refs/heads/master", UPDATE));

LockFile myLock = new LockFile(refdir.fileFor("refs/heads/master"));
assertTrue(myLock.lock());
try {
execute(newBatchUpdate(cmds).setAllowNonFastForwards(true));

assertEquals(
atomic ? initialRefsChangedEvents
: initialRefsChangedEvents + 1,
refsChangedEvents);
} finally {
myLock.unlock();
}
}

@Test @Test
public void singleRefUpdateDoesNotRequirePackedRefsLock() throws Exception { public void singleRefUpdateDoesNotRequirePackedRefsLock() throws Exception {
writeLooseRef("refs/heads/master", A); writeLooseRef("refs/heads/master", A);


assertFalse(getLockFile("refs/heads/master").exists()); assertFalse(getLockFile("refs/heads/master").exists());
assertResults(cmds, OK); assertResults(cmds, OK);
assertEquals(2, refsChangedEvents);
assertRefs("refs/heads/master", B); assertRefs("refs/heads/master", B);
} finally { } finally {
myLock.unlock(); myLock.unlock();
} }
} }


@Test
public void singleRefUpdateDoesNotRequirePackedRefsLockRefsChangedEvents()
throws Exception {
writeLooseRef("refs/heads/master", A);
refdir.exactRef("refs/heads/master");
int initialRefsChangedEvents = refsChangedEvents;

List<ReceiveCommand> cmds = Arrays
.asList(new ReceiveCommand(A, B, "refs/heads/master", UPDATE));

LockFile myLock = refdir.lockPackedRefs();
try {
execute(newBatchUpdate(cmds).setAllowNonFastForwards(true));

assertEquals(initialRefsChangedEvents + 1, refsChangedEvents);
} finally {
myLock.unlock();
}
}

@Test @Test
public void atomicUpdateRespectsInProcessLock() throws Exception { public void atomicUpdateRespectsInProcessLock() throws Exception {
assumeTrue(atomic); assumeTrue(atomic);
"refs/heads/branch", B); "refs/heads/branch", B);
} }


@Test
public void atomicUpdateRespectsInProcessLockRefsChangedEvents()
throws Exception {
assumeTrue(atomic);

writeLooseRef("refs/heads/master", A);
refdir.exactRef("refs/heads/master");
int initialRefsChangedEvents = refsChangedEvents;

List<ReceiveCommand> cmds = Arrays.asList(
new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
new ReceiveCommand(zeroId(), B, "refs/heads/branch", CREATE));

Thread t = new Thread(() -> {
try {
execute(newBatchUpdate(cmds).setAllowNonFastForwards(true));
} catch (Exception e) {
throw new RuntimeException(e);
}
});

ReentrantLock l = refdir.inProcessPackedRefsLock;
l.lock();
try {
t.start();
long timeoutSecs = 10;

// Hold onto the lock until we observe the worker thread has
// attempted to
// acquire it.
while (l.getQueueLength() == 0) {
Thread.sleep(3);
}

// Once we unlock, the worker thread should finish the update
// promptly.
l.unlock();
t.join(SECONDS.toMillis(timeoutSecs));
} finally {
if (l.isHeldByCurrentThread()) {
l.unlock();
}
}

assertEquals(initialRefsChangedEvents + 1, refsChangedEvents);
}

private void setLogAllRefUpdates(boolean enable) throws Exception { private void setLogAllRefUpdates(boolean enable) throws Exception {
StoredConfig cfg = diskRepo.getConfig(); StoredConfig cfg = diskRepo.getConfig();
cfg.load(); cfg.load();

Loading…
Cancel
Save