fix(test): tie preference writer hold to shutdown phase
Release / release (push) Failing after 30m13s
Release / release (push) Failing after 30m13s
This commit is contained in:
1 parent
e54896cb38
commit
9f0c18bcf2
1 file changed
+32
-7
@@ -80,6 +80,14 @@ class PreferenceLifecycleNativeTest {
|
||||
}
|
||||
|
||||
@Test void registeredAuraExportQueuedAtShutdownMustBeAcknowledgedBeforeRestart() throws Exception {
|
||||
queuedAuraShutdown(false);
|
||||
}
|
||||
|
||||
@Test void realQueuedAuraWriterStaysHeldPastFormerDeadlineUntilActualClose() throws Exception {
|
||||
queuedAuraShutdown(true);
|
||||
}
|
||||
|
||||
private void queuedAuraShutdown(boolean delayClosing) throws Exception {
|
||||
try (var f = new FantasyStickLifecycleNativeTest.Fixture(data)) {
|
||||
f.plugin.setEnabled(true);
|
||||
var actor = new FantasyStickLifecycleNativeTest.Actor(data);
|
||||
@@ -93,10 +101,12 @@ class PreferenceLifecycleNativeTest {
|
||||
var release = new java.util.concurrent.CountDownLatch(1);
|
||||
var blocked = worker.submit(() -> {
|
||||
entered.countDown();
|
||||
try { assertTrue(release.await(5, TimeUnit.SECONDS)); }
|
||||
try { release.await(); }
|
||||
catch (InterruptedException failure) { Thread.currentThread().interrupt(); throw new AssertionError(failure); }
|
||||
});
|
||||
CompletableFuture<Void> releasing = null;
|
||||
var cleanupRequested = new java.util.concurrent.atomic.AtomicBoolean();
|
||||
Throwable primary = null;
|
||||
try {
|
||||
assertTrue(entered.await(5, TimeUnit.SECONDS));
|
||||
assertTrue(f.playerCommand.getExecutor().onCommand(actor.player, f.playerCommand,
|
||||
@@ -108,14 +118,20 @@ class PreferenceLifecycleNativeTest {
|
||||
var original = preferences.pendingEvents().getFirst();
|
||||
assertTrue(changes().isEmpty(), "The real writer is held before export, not a fabricated sink result");
|
||||
assertArrayEquals(inventory, actor.core.snapshot());
|
||||
if (delayClosing) {
|
||||
assertThrows(java.util.concurrent.TimeoutException.class, () -> blocked.get(6, TimeUnit.SECONDS),
|
||||
"The real queued writer must remain held before any close request, even past the former five-second test deadline");
|
||||
assertFalse((Boolean) FantasyStickLifecycleNativeTest.Fixture.field(log, "closing"));
|
||||
assertTrue(changes().isEmpty()); assertFalse(preferences.pendingEvents().isEmpty());
|
||||
}
|
||||
releasing = CompletableFuture.runAsync(() -> {
|
||||
long deadline = System.nanoTime() + TimeUnit.SECONDS.toNanos(5);
|
||||
while (!(Boolean) FantasyStickLifecycleNativeTest.Fixture.field(log, "closing")
|
||||
&& System.nanoTime() < deadline) java.util.concurrent.locks.LockSupport.parkNanos(100_000);
|
||||
assertTrue((Boolean) FantasyStickLifecycleNativeTest.Fixture.field(log, "closing"));
|
||||
release.countDown();
|
||||
&& !cleanupRequested.get()) java.util.concurrent.locks.LockSupport.parkNanos(100_000);
|
||||
if (!cleanupRequested.get()) release.countDown();
|
||||
});
|
||||
f.plugin.setEnabled(false);
|
||||
assertTrue((Boolean) FantasyStickLifecycleNativeTest.Fixture.field(log, "closing"),
|
||||
"Actual orderly native shutdown must request writer close before its queued acknowledgement");
|
||||
releasing.get(5, TimeUnit.SECONDS); blocked.get(5, TimeUnit.SECONDS);
|
||||
preferences.drained().toCompletableFuture().get(5, TimeUnit.SECONDS);
|
||||
assertEquals(1, changes().size(), "Orderly writer shutdown exports the queued accepted native change");
|
||||
@@ -134,9 +150,18 @@ class PreferenceLifecycleNativeTest {
|
||||
f.plugin.setEnabled(false); f.awaitWorkers();
|
||||
assertEquals(java.util.List.of(exported), changes(),
|
||||
"Orderly restart cannot create a second export or recapture the acknowledged original payload");
|
||||
} catch (Exception | AssertionError failure) {
|
||||
primary = failure; throw failure;
|
||||
} finally {
|
||||
release.countDown(); blocked.get(5, TimeUnit.SECONDS);
|
||||
if (releasing != null) releasing.get(5, TimeUnit.SECONDS);
|
||||
cleanupRequested.set(true); release.countDown();
|
||||
var completions = new java.util.ArrayList<java.util.concurrent.Future<?>>(); completions.add(blocked);
|
||||
if (releasing != null) completions.add(releasing);
|
||||
Exception cleanupFailure = null;
|
||||
for (var completion : completions) {
|
||||
try { completion.get(5, TimeUnit.SECONDS); }
|
||||
catch (Exception failure) { if (cleanupFailure == null) cleanupFailure = failure; else cleanupFailure.addSuppressed(failure); }
|
||||
}
|
||||
if (cleanupFailure != null) { if (primary == null) throw cleanupFailure; primary.addSuppressed(cleanupFailure); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user