mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-11-01 08:50:06 +00:00
Adapter patches
(tests)
This commit is contained in:
1 parent
4b4b418c61
commit
a6149b27c9
40 files changed
+894
-211
No files matched your search
@@ -0,0 +1,131 @@
|
||||
package art.arcane.iris.generation.runtime;
|
||||
|
||||
import art.arcane.iris.probe.StubPlatform;
|
||||
import art.arcane.iris.spi.IrisPlatforms;
|
||||
import art.arcane.iris.testsupport.IrisRuntimeState;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public final class ProbeBackgroundTasksTest {
|
||||
@Rule
|
||||
public final TemporaryFolder temporary = new TemporaryFolder();
|
||||
|
||||
@Before
|
||||
public void bindRuntime() {
|
||||
IrisPlatforms.bind(new StubPlatform(temporary.getRoot()));
|
||||
}
|
||||
|
||||
@After
|
||||
public void resetRuntime() {
|
||||
IrisRuntimeState.reset();
|
||||
StubPlatform.errorSink(null);
|
||||
}
|
||||
|
||||
@Test(timeout = 15_000L)
|
||||
public void waitsForTrackedContinuationBeforeReturning() throws Exception {
|
||||
EngineBackgroundTasks tasks = new EngineBackgroundTasks();
|
||||
tasks.openBackgroundTaskAdmission();
|
||||
CountDownLatch firstEntered = new CountDownLatch(1);
|
||||
CountDownLatch firstRelease = new CountDownLatch(1);
|
||||
CountDownLatch continuationEntered = new CountDownLatch(1);
|
||||
CountDownLatch continuationRelease = new CountDownLatch(1);
|
||||
try (ExecutorService closer = Executors.newSingleThreadExecutor()) {
|
||||
try {
|
||||
tasks.scheduleTrackedTask(() -> {
|
||||
awaitRelease(firstEntered, firstRelease);
|
||||
tasks.scheduleTrackedTask(() -> awaitRelease(continuationEntered, continuationRelease));
|
||||
});
|
||||
assertTrue(firstEntered.await(5, TimeUnit.SECONDS));
|
||||
Future<?> completion = startDrain(closer, tasks);
|
||||
assertThrows(TimeoutException.class, () -> completion.get(100, TimeUnit.MILLISECONDS));
|
||||
firstRelease.countDown();
|
||||
assertTrue(continuationEntered.await(5, TimeUnit.SECONDS));
|
||||
assertThrows(TimeoutException.class, () -> completion.get(100, TimeUnit.MILLISECONDS));
|
||||
continuationRelease.countDown();
|
||||
completion.get(5, TimeUnit.SECONDS);
|
||||
} finally {
|
||||
firstRelease.countDown();
|
||||
continuationRelease.countDown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(timeout = 15_000L)
|
||||
public void propagatesAnAsynchronousTrackedFailure() throws Exception {
|
||||
EngineBackgroundTasks tasks = new EngineBackgroundTasks();
|
||||
tasks.openBackgroundTaskAdmission();
|
||||
CountDownLatch entered = new CountDownLatch(1);
|
||||
CountDownLatch release = new CountDownLatch(1);
|
||||
IllegalStateException failure = new IllegalStateException("tracked generation failure");
|
||||
CountDownLatch reported = new CountDownLatch(1);
|
||||
StubPlatform.errorSink(error -> reported.countDown());
|
||||
try (ExecutorService closer = Executors.newSingleThreadExecutor()) {
|
||||
try {
|
||||
tasks.scheduleTrackedTask(() -> {
|
||||
awaitRelease(entered, release);
|
||||
throw failure;
|
||||
});
|
||||
assertTrue(entered.await(5, TimeUnit.SECONDS));
|
||||
Future<?> completion = startDrain(closer, tasks);
|
||||
assertThrows(TimeoutException.class, () -> completion.get(100, TimeUnit.MILLISECONDS));
|
||||
release.countDown();
|
||||
ExecutionException observed = assertThrows(ExecutionException.class,
|
||||
() -> completion.get(5, TimeUnit.SECONDS));
|
||||
assertSame(failure, observed.getCause().getCause().getCause());
|
||||
assertTrue(reported.await(5, TimeUnit.SECONDS));
|
||||
} finally {
|
||||
release.countDown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Future<?> startDrain(ExecutorService closer, EngineBackgroundTasks tasks) {
|
||||
AtomicReference<Thread> drainingThread = new AtomicReference<>();
|
||||
Future<?> completion = closer.submit(() -> {
|
||||
drainingThread.set(Thread.currentThread());
|
||||
ProbeBackgroundTasks.await(tasks);
|
||||
});
|
||||
long deadline = System.nanoTime() + TimeUnit.SECONDS.toNanos(5);
|
||||
while (System.nanoTime() < deadline) {
|
||||
Thread thread = drainingThread.get();
|
||||
if (thread != null && thread.getState() == Thread.State.TIMED_WAITING) {
|
||||
for (StackTraceElement frame : thread.getStackTrace()) {
|
||||
if (frame.getClassName().equals(EngineBackgroundTasks.class.getName())
|
||||
&& frame.getMethodName().equals("drainBackgroundTasks")) {
|
||||
return completion;
|
||||
}
|
||||
}
|
||||
}
|
||||
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(1));
|
||||
}
|
||||
throw new AssertionError("Probe barrier did not await its initial task");
|
||||
}
|
||||
|
||||
private static void awaitRelease(CountDownLatch entered, CountDownLatch release) {
|
||||
entered.countDown();
|
||||
try {
|
||||
assertTrue(release.await(5, TimeUnit.SECONDS));
|
||||
} catch (InterruptedException interruption) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new IllegalStateException(interruption);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -211,7 +211,7 @@ public final class ObjectContinuationProbeTest {
|
||||
assertArrayEquals(oldReceipt, SavedTerrainChunk.readReceipt(world.worldFolder().toPath(), 0, 0));
|
||||
assertEquals(originalActivation, reopened.resolveActivation(0, 0).activationId());
|
||||
assertTrue(reopened.semantics(1, 0).orElseThrow().objectKeys().contains(fixture.objectKey()));
|
||||
assertTrue("Generation must not report swallowed errors", RealPackProbeSupport.settleAndDrain().isEmpty());
|
||||
assertTrue("Generation must not report swallowed errors", RealPackProbeSupport.settleAndDrain(engine).isEmpty());
|
||||
} finally {
|
||||
engine.close();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
package art.arcane.iris.probe;
|
||||
|
||||
import art.arcane.iris.generation.concurrent.MultiBurst;
|
||||
import art.arcane.iris.generation.runtime.EngineEffectsProvider;
|
||||
import art.arcane.iris.generation.runtime.EnginePlatformHooks;
|
||||
import art.arcane.iris.generation.runtime.EngineWorldManagerProvider;
|
||||
import art.arcane.iris.generation.runtime.PreservationRegistry;
|
||||
import art.arcane.iris.spi.IrisPlatforms;
|
||||
import art.arcane.iris.spi.IrisServices;
|
||||
import art.arcane.iris.testsupport.IrisRuntimeState;
|
||||
import art.arcane.iris.testsupport.PlatformLeakGuard;
|
||||
import art.arcane.iris.world.task.J;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public final class RealPackProbeSupportBarrierTest {
|
||||
@AfterClass
|
||||
public static void resetRuntime() {
|
||||
IrisRuntimeState.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void closesOwnedRuntimeServicesAndPreservesUnrelatedServices() throws Exception {
|
||||
URL resource = RealPackProbeSupportBarrierTest.class.getResource("/seed-cohesion");
|
||||
assertNotNull(resource);
|
||||
IrisServices.register(String.class, "unrelated");
|
||||
try {
|
||||
try (RealPackProbeSupport.Workspace workspace = RealPackProbeSupport.openWorkspace(
|
||||
new File(resource.toURI()), "cohesion", "[workspace-cleanup]")) {
|
||||
assertNotNull(IrisServices.getOrNull(EngineEffectsProvider.class));
|
||||
}
|
||||
assertFalse(IrisPlatforms.isBound());
|
||||
assertNull(IrisServices.getOrNull(PreservationRegistry.class));
|
||||
assertNull(IrisServices.getOrNull(EngineWorldManagerProvider.class));
|
||||
assertNull(IrisServices.getOrNull(EngineEffectsProvider.class));
|
||||
assertNull(IrisServices.getOrNull(EnginePlatformHooks.class));
|
||||
assertEquals("unrelated", IrisServices.get(String.class));
|
||||
} finally {
|
||||
IrisServices.remove(String.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(timeout = 30_000L)
|
||||
public void waitsForCrossPoolContinuationsAndCollectsTheirErrors() throws Exception {
|
||||
URL resource = RealPackProbeSupportBarrierTest.class.getResource("/seed-cohesion");
|
||||
assertNotNull(resource);
|
||||
try (RealPackProbeSupport.Workspace workspace = RealPackProbeSupport.openWorkspace(
|
||||
new File(resource.toURI()), "cohesion", "[worker-barrier]");
|
||||
RealPackProbeSupport.EngineSession session = workspace.openEngine(1337L, false, "barrier")) {
|
||||
for (int repeat = 0; repeat < 40; repeat++) {
|
||||
verifyCrossPoolContinuation(session, MultiBurst.ioBurst, MultiBurst.hydrology);
|
||||
verifyCrossPoolContinuation(session, MultiBurst.hydrology, MultiBurst.ioBurst);
|
||||
}
|
||||
}
|
||||
PlatformLeakGuard.requireClean("closed real-pack workspace", "end");
|
||||
}
|
||||
|
||||
private static void verifyCrossPoolContinuation(RealPackProbeSupport.EngineSession session,
|
||||
MultiBurst first, MultiBurst second) throws Exception {
|
||||
IllegalStateException failure = new IllegalStateException("nested generation failure");
|
||||
CountDownLatch entered = new CountDownLatch(1);
|
||||
CountDownLatch release = new CountDownLatch(1);
|
||||
try {
|
||||
first.lazy(() -> {
|
||||
entered.countDown();
|
||||
try {
|
||||
assertTrue(release.await(5, TimeUnit.SECONDS));
|
||||
} catch (InterruptedException interruption) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new IllegalStateException(interruption);
|
||||
}
|
||||
Runnable failedTask = () -> {
|
||||
throw failure;
|
||||
};
|
||||
second.lazy(() -> first.lazy(() -> second.lazy(() -> J.a(failedTask))));
|
||||
});
|
||||
assertTrue(entered.await(5, TimeUnit.SECONDS));
|
||||
release.countDown();
|
||||
List<Throwable> reports = RealPackProbeSupport.settleAndDrain(session.engine());
|
||||
assertEquals(1, reports.size());
|
||||
assertSame(failure, reports.getFirst());
|
||||
assertTrue(RealPackProbeSupport.drainReported().isEmpty());
|
||||
} finally {
|
||||
release.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user