Commit 559a592b authored by Kenton Varda's avatar Kenton Varda

Fix dynamic pipelining on 'Capability' type.

Fixes #336
parent a5a0bc6c
...@@ -338,6 +338,49 @@ TEST(Capability, DynamicClientPipelining) { ...@@ -338,6 +338,49 @@ TEST(Capability, DynamicClientPipelining) {
EXPECT_EQ(1, chainedCallCount); EXPECT_EQ(1, chainedCallCount);
} }
TEST(Capability, DynamicClientPipelineAnyCap) {
kj::EventLoop loop;
kj::WaitScope waitScope(loop);
int callCount = 0;
int chainedCallCount = 0;
DynamicCapability::Client client =
test::TestPipeline::Client(kj::heap<TestPipelineImpl>(callCount));
auto request = client.newRequest("getAnyCap");
request.set("n", 234);
request.set("inCap", test::TestInterface::Client(kj::heap<TestInterfaceImpl>(chainedCallCount)));
auto promise = request.send();
auto outAnyCap = promise.get("outBox").releaseAs<DynamicStruct>()
.get("cap").releaseAs<DynamicCapability>();
EXPECT_EQ(Schema::from<Capability>(), outAnyCap.getSchema());
auto outCap = outAnyCap.castAs<DynamicCapability>(Schema::from<test::TestInterface>());
auto pipelineRequest = outCap.newRequest("foo");
pipelineRequest.set("i", 321);
auto pipelinePromise = pipelineRequest.send();
auto pipelineRequest2 = outCap.castAs<test::TestExtends>().graultRequest();
auto pipelinePromise2 = pipelineRequest2.send();
promise = nullptr; // Just to be annoying, drop the original promise.
EXPECT_EQ(0, callCount);
EXPECT_EQ(0, chainedCallCount);
auto response = pipelinePromise.wait(waitScope);
EXPECT_EQ("bar", response.get("x").as<Text>());
auto response2 = pipelinePromise2.wait(waitScope);
checkTestMessage(response2);
EXPECT_EQ(3, callCount);
EXPECT_EQ(1, chainedCallCount);
}
// ======================================================================================= // =======================================================================================
class TestInterfaceDynamicImpl final: public DynamicCapability::Server { class TestInterfaceDynamicImpl final: public DynamicCapability::Server {
......
...@@ -388,6 +388,18 @@ DynamicValue::Pipeline DynamicStruct::Pipeline::get(StructSchema::Field field) { ...@@ -388,6 +388,18 @@ DynamicValue::Pipeline DynamicStruct::Pipeline::get(StructSchema::Field field) {
return DynamicCapability::Client(type.asInterface(), return DynamicCapability::Client(type.asInterface(),
typeless.getPointerField(slot.getOffset()).asCap()); typeless.getPointerField(slot.getOffset()).asCap());
case schema::Type::ANY_POINTER:
switch (type.whichAnyPointerKind()) {
case schema::Type::AnyPointer::Unconstrained::STRUCT:
return DynamicStruct::Pipeline(StructSchema(),
typeless.getPointerField(slot.getOffset()));
case schema::Type::AnyPointer::Unconstrained::CAPABILITY:
return DynamicCapability::Client(Capability::Client(
typeless.getPointerField(slot.getOffset()).asCap()));
default:
KJ_FAIL_REQUIRE("Can only pipeline on struct and interface fields.");
}
default: default:
KJ_FAIL_REQUIRE("Can only pipeline on struct and interface fields."); KJ_FAIL_REQUIRE("Can only pipeline on struct and interface fields.");
} }
......
...@@ -952,6 +952,29 @@ kj::Promise<void> TestPipelineImpl::getCap(GetCapContext context) { ...@@ -952,6 +952,29 @@ kj::Promise<void> TestPipelineImpl::getCap(GetCapContext context) {
}); });
} }
kj::Promise<void> TestPipelineImpl::getAnyCap(GetAnyCapContext context) {
++callCount;
auto params = context.getParams();
EXPECT_EQ(234, params.getN());
auto cap = params.getInCap();
context.releaseParams();
auto request = cap.castAs<test::TestInterface>().fooRequest();
request.setI(123);
request.setJ(true);
return request.send().then(
[this,KJ_CPCAP(context)](Response<test::TestInterface::FooResults>&& response) mutable {
EXPECT_EQ("foo", response.getX());
auto result = context.getResults();
result.setS("bar");
result.initOutBox().setCap(kj::heap<TestExtendsImpl>(callCount));
});
}
kj::Promise<void> TestCallOrderImpl::getCallSequence(GetCallSequenceContext context) { kj::Promise<void> TestCallOrderImpl::getCallSequence(GetCallSequenceContext context) {
auto result = context.getResults(); auto result = context.getResults();
result.setN(count++); result.setN(count++);
......
...@@ -213,6 +213,7 @@ public: ...@@ -213,6 +213,7 @@ public:
TestPipelineImpl(int& callCount); TestPipelineImpl(int& callCount);
kj::Promise<void> getCap(GetCapContext context) override; kj::Promise<void> getCap(GetCapContext context) override;
kj::Promise<void> getAnyCap(GetAnyCapContext context) override;
private: private:
int& callCount; int& callCount;
......
...@@ -782,10 +782,14 @@ interface TestExtends2 extends(TestExtends) {} ...@@ -782,10 +782,14 @@ interface TestExtends2 extends(TestExtends) {}
interface TestPipeline { interface TestPipeline {
getCap @0 (n: UInt32, inCap :TestInterface) -> (s: Text, outBox :Box); getCap @0 (n: UInt32, inCap :TestInterface) -> (s: Text, outBox :Box);
testPointers @1 (cap :TestInterface, obj :AnyPointer, list :List(TestInterface)) -> (); testPointers @1 (cap :TestInterface, obj :AnyPointer, list :List(TestInterface)) -> ();
getAnyCap @2 (n: UInt32, inCap :Capability) -> (s: Text, outBox :AnyBox);
struct Box { struct Box {
cap @0 :TestInterface; cap @0 :TestInterface;
} }
struct AnyBox {
cap @0 :Capability;
}
} }
interface TestCallOrder { interface TestCallOrder {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment