diff --git a/runtime-rpc/src/test/java/org/capnproto/RpcTest.java b/runtime-rpc/src/test/java/org/capnproto/RpcTest.java index df8fa0f..4fcbac6 100644 --- a/runtime-rpc/src/test/java/org/capnproto/RpcTest.java +++ b/runtime-rpc/src/test/java/org/capnproto/RpcTest.java @@ -30,6 +30,8 @@ import java.util.HashMap; import java.util.Map; import java.util.Queue; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.atomic.AtomicBoolean; public class RpcTest { @@ -472,5 +474,36 @@ public class RpcTest { Assert.assertEquals(4, call4.join().getN()); Assert.assertEquals(5, call5.join().getN()); } + + @org.junit.Test + public void testCallBrokenPromise() throws ExecutionException, InterruptedException { + var context = new TestContext(bootstrapFactory); + var client = new Test.TestMoreStuff.Client(context.connect(Test.TestSturdyRefObjectId.Tag.TEST_MORE_STUFF)); + + var paf = new CompletableFuture(); + + { + var req = client.holdRequest(); + req.getParams().setCap(new Test.TestInterface.Client(paf)); + req.send().join(); + } + + AtomicBoolean returned = new AtomicBoolean(false); + + var req = client.callHeldRequest().send().exceptionallyCompose(exc -> { + returned.set(true); + return CompletableFuture.failedFuture(exc); + }).thenAccept(results -> { + returned.set(true); + }); + + Assert.assertFalse(returned.get()); + + paf.completeExceptionally(new Exception("foo")); + Assert.assertTrue(returned.get()); + + // Verify that we are still connected + getCallSequence(client, 1).get(); + } } diff --git a/runtime-rpc/src/test/java/org/capnproto/RpcTestUtil.java b/runtime-rpc/src/test/java/org/capnproto/RpcTestUtil.java index 2770c93..73e1d45 100644 --- a/runtime-rpc/src/test/java/org/capnproto/RpcTestUtil.java +++ b/runtime-rpc/src/test/java/org/capnproto/RpcTestUtil.java @@ -102,8 +102,9 @@ class RpcTestUtil { static class TestMoreStuffImpl extends Test.TestMoreStuff.Server { - final Counter callCount; - final Counter handleCount; + private final Counter callCount; + private final Counter handleCount; + private Test.TestInterface.Client clientToHold; public TestMoreStuffImpl(Counter callCount, Counter handleCount) { this.callCount = callCount; @@ -164,6 +165,34 @@ class RpcTestUtil { }); }); } + + @Override + protected CompletableFuture hold(CallContext context) { + this.callCount.inc(); + var params = context.getParams(); + this.clientToHold = params.getCap(); + return READY_NOW; + } + + @Override + protected CompletableFuture callHeld(CallContext context) { + this.callCount.inc(); + var request = this.clientToHold.fooRequest(); + request.getParams().setI(123); + request.getParams().setJ(true); + return request.send().thenAccept(response -> { + Assert.assertEquals("foo", response.getX().toString()); + context.getResults().setS("bar"); + }); + } + + @Override + protected CompletableFuture getHeld(CallContext context) { + this.callCount.inc(); + var result = context.getResults(); + result.setCap(this.clientToHold); + return READY_NOW; + } } static class TestTailCalleeImpl extends Test.TestTailCallee.Server {