cannam@132: // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors cannam@132: // Licensed under the MIT License: cannam@132: // cannam@132: // Permission is hereby granted, free of charge, to any person obtaining a copy cannam@132: // of this software and associated documentation files (the "Software"), to deal cannam@132: // in the Software without restriction, including without limitation the rights cannam@132: // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell cannam@132: // copies of the Software, and to permit persons to whom the Software is cannam@132: // furnished to do so, subject to the following conditions: cannam@132: // cannam@132: // The above copyright notice and this permission notice shall be included in cannam@132: // all copies or substantial portions of the Software. cannam@132: // cannam@132: // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR cannam@132: // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, cannam@132: // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE cannam@132: // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER cannam@132: // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, cannam@132: // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN cannam@132: // THE SOFTWARE. cannam@132: cannam@132: #ifndef CAPNP_TEST_UTIL_H_ cannam@132: #define CAPNP_TEST_UTIL_H_ cannam@132: cannam@132: #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) cannam@132: #pragma GCC system_header cannam@132: #endif cannam@132: cannam@132: #include cannam@132: #include cannam@132: #include "blob.h" cannam@132: #include cannam@132: cannam@132: #if !CAPNP_LITE cannam@132: #include "dynamic.h" cannam@132: #endif // !CAPNP_LITE cannam@132: cannam@132: #if KJ_NO_EXCEPTIONS cannam@132: #undef EXPECT_ANY_THROW cannam@132: #define EXPECT_ANY_THROW(code) EXPECT_DEATH(code, ".") cannam@132: #endif cannam@132: cannam@132: #define EXPECT_NONFATAL_FAILURE(code) \ cannam@132: EXPECT_TRUE(kj::runCatchingExceptions([&]() { code; }) != nullptr); cannam@132: cannam@132: #ifdef KJ_DEBUG cannam@132: #define EXPECT_DEBUG_ANY_THROW EXPECT_ANY_THROW cannam@132: #else cannam@132: #define EXPECT_DEBUG_ANY_THROW(EXP) cannam@132: #endif cannam@132: cannam@132: // TODO(cleanup): Auto-generate stringification functions for union discriminants. cannam@132: namespace capnproto_test { cannam@132: namespace capnp { cannam@132: namespace test { cannam@132: inline kj::String KJ_STRINGIFY(TestUnion::Union0::Which which) { cannam@132: return kj::str(static_cast(which)); cannam@132: } cannam@132: inline kj::String KJ_STRINGIFY(TestUnion::Union1::Which which) { cannam@132: return kj::str(static_cast(which)); cannam@132: } cannam@132: inline kj::String KJ_STRINGIFY(TestUnion::Union2::Which which) { cannam@132: return kj::str(static_cast(which)); cannam@132: } cannam@132: inline kj::String KJ_STRINGIFY(TestUnion::Union3::Which which) { cannam@132: return kj::str(static_cast(which)); cannam@132: } cannam@132: inline kj::String KJ_STRINGIFY(TestUnnamedUnion::Which which) { cannam@132: return kj::str(static_cast(which)); cannam@132: } cannam@132: inline kj::String KJ_STRINGIFY(TestGroups::Groups::Which which) { cannam@132: return kj::str(static_cast(which)); cannam@132: } cannam@132: inline kj::String KJ_STRINGIFY(TestInterleavedGroups::Group1::Which which) { cannam@132: return kj::str(static_cast(which)); cannam@132: } cannam@132: } // namespace test cannam@132: } // namespace capnp cannam@132: } // namespace capnproto_test cannam@132: cannam@132: namespace capnp { cannam@132: namespace _ { // private cannam@132: cannam@132: inline Data::Reader data(const char* str) { cannam@132: return Data::Reader(reinterpret_cast(str), strlen(str)); cannam@132: } cannam@132: cannam@132: namespace test = capnproto_test::capnp::test; cannam@132: cannam@132: // We don't use "using namespace" to pull these in because then things would still compile cannam@132: // correctly if they were generated in the global namespace. cannam@132: using ::capnproto_test::capnp::test::TestAllTypes; cannam@132: using ::capnproto_test::capnp::test::TestDefaults; cannam@132: using ::capnproto_test::capnp::test::TestEnum; cannam@132: using ::capnproto_test::capnp::test::TestUnion; cannam@132: using ::capnproto_test::capnp::test::TestUnionDefaults; cannam@132: using ::capnproto_test::capnp::test::TestNestedTypes; cannam@132: using ::capnproto_test::capnp::test::TestUsing; cannam@132: using ::capnproto_test::capnp::test::TestListDefaults; cannam@132: cannam@132: void initTestMessage(TestAllTypes::Builder builder); cannam@132: void initTestMessage(TestDefaults::Builder builder); cannam@132: void initTestMessage(TestListDefaults::Builder builder); cannam@132: cannam@132: void checkTestMessage(TestAllTypes::Builder builder); cannam@132: void checkTestMessage(TestDefaults::Builder builder); cannam@132: void checkTestMessage(TestListDefaults::Builder builder); cannam@132: cannam@132: void checkTestMessage(TestAllTypes::Reader reader); cannam@132: void checkTestMessage(TestDefaults::Reader reader); cannam@132: void checkTestMessage(TestListDefaults::Reader reader); cannam@132: cannam@132: void checkTestMessageAllZero(TestAllTypes::Builder builder); cannam@132: void checkTestMessageAllZero(TestAllTypes::Reader reader); cannam@132: cannam@132: #if !CAPNP_LITE cannam@132: void initDynamicTestMessage(DynamicStruct::Builder builder); cannam@132: void initDynamicTestLists(DynamicStruct::Builder builder); cannam@132: void checkDynamicTestMessage(DynamicStruct::Builder builder); cannam@132: void checkDynamicTestLists(DynamicStruct::Builder builder); cannam@132: void checkDynamicTestMessage(DynamicStruct::Reader reader); cannam@132: void checkDynamicTestLists(DynamicStruct::Reader reader); cannam@132: void checkDynamicTestMessageAllZero(DynamicStruct::Builder builder); cannam@132: void checkDynamicTestMessageAllZero(DynamicStruct::Reader reader); cannam@132: #endif // !CAPNP_LITE cannam@132: cannam@132: template cannam@132: inline void checkElement(T a, T b) { cannam@132: EXPECT_EQ(a, b); cannam@132: } cannam@132: cannam@132: template <> cannam@132: inline void checkElement(float a, float b) { cannam@132: EXPECT_FLOAT_EQ(a, b); cannam@132: } cannam@132: cannam@132: template <> cannam@132: inline void checkElement(double a, double b) { cannam@132: EXPECT_DOUBLE_EQ(a, b); cannam@132: } cannam@132: cannam@132: template cannam@132: void checkList(T reader, std::initializer_list expected) { cannam@132: ASSERT_EQ(expected.size(), reader.size()); cannam@132: for (uint i = 0; i < expected.size(); i++) { cannam@132: checkElement(expected.begin()[i], reader[i]); cannam@132: } cannam@132: } cannam@132: cannam@132: template cannam@132: void checkList(T reader, std::initializer_list expected) { cannam@132: ASSERT_EQ(expected.size(), reader.size()); cannam@132: for (uint i = 0; i < expected.size(); i++) { cannam@132: checkElement(expected.begin()[i], reader[i]); cannam@132: } cannam@132: } cannam@132: cannam@132: inline void checkList(List::Reader reader, cannam@132: std::initializer_list expectedData, cannam@132: std::initializer_list expectedPointers) { cannam@132: ASSERT_EQ(expectedData.size(), reader.size()); cannam@132: for (uint i = 0; i < expectedData.size(); i++) { cannam@132: EXPECT_EQ(expectedData.begin()[i], reader[i].getOld1()); cannam@132: EXPECT_EQ(expectedPointers.begin()[i], reader[i].getOld2()); cannam@132: } cannam@132: } cannam@132: cannam@132: // Hack because as<>() is a template-parameter-dependent lookup everywhere below... cannam@132: #define as template as cannam@132: cannam@132: template void expectPrimitiveEq(T a, T b) { EXPECT_EQ(a, b); } cannam@132: inline void expectPrimitiveEq(float a, float b) { EXPECT_FLOAT_EQ(a, b); } cannam@132: inline void expectPrimitiveEq(double a, double b) { EXPECT_DOUBLE_EQ(a, b); } cannam@132: inline void expectPrimitiveEq(Text::Reader a, Text::Builder b) { EXPECT_EQ(a, b); } cannam@132: inline void expectPrimitiveEq(Data::Reader a, Data::Builder b) { EXPECT_EQ(a, b); } cannam@132: cannam@132: #if !CAPNP_LITE cannam@132: template cannam@132: void checkList(T reader, std::initializer_list> expected) { cannam@132: auto list = reader.as(); cannam@132: ASSERT_EQ(expected.size(), list.size()); cannam@132: for (uint i = 0; i < expected.size(); i++) { cannam@132: expectPrimitiveEq(expected.begin()[i], list[i].as()); cannam@132: } cannam@132: cannam@132: auto typed = reader.as>(); cannam@132: ASSERT_EQ(expected.size(), typed.size()); cannam@132: for (uint i = 0; i < expected.size(); i++) { cannam@132: expectPrimitiveEq(expected.begin()[i], typed[i]); cannam@132: } cannam@132: } cannam@132: #endif // !CAPNP_LITE cannam@132: cannam@132: #undef as cannam@132: cannam@132: // ======================================================================================= cannam@132: // Interface implementations. cannam@132: cannam@132: #if !CAPNP_LITE cannam@132: cannam@132: class TestInterfaceImpl final: public test::TestInterface::Server { cannam@132: public: cannam@132: TestInterfaceImpl(int& callCount); cannam@132: cannam@132: kj::Promise foo(FooContext context) override; cannam@132: cannam@132: kj::Promise baz(BazContext context) override; cannam@132: cannam@132: private: cannam@132: int& callCount; cannam@132: }; cannam@132: cannam@132: class TestExtendsImpl final: public test::TestExtends2::Server { cannam@132: public: cannam@132: TestExtendsImpl(int& callCount); cannam@132: cannam@132: kj::Promise foo(FooContext context) override; cannam@132: cannam@132: kj::Promise grault(GraultContext context) override; cannam@132: cannam@132: private: cannam@132: int& callCount; cannam@132: }; cannam@132: cannam@132: class TestPipelineImpl final: public test::TestPipeline::Server { cannam@132: public: cannam@132: TestPipelineImpl(int& callCount); cannam@132: cannam@132: kj::Promise getCap(GetCapContext context) override; cannam@132: cannam@132: private: cannam@132: int& callCount; cannam@132: }; cannam@132: cannam@132: class TestCallOrderImpl final: public test::TestCallOrder::Server { cannam@132: public: cannam@132: kj::Promise getCallSequence(GetCallSequenceContext context) override; cannam@132: cannam@132: private: cannam@132: uint count = 0; cannam@132: }; cannam@132: cannam@132: class TestTailCallerImpl final: public test::TestTailCaller::Server { cannam@132: public: cannam@132: TestTailCallerImpl(int& callCount); cannam@132: cannam@132: kj::Promise foo(FooContext context) override; cannam@132: cannam@132: private: cannam@132: int& callCount; cannam@132: }; cannam@132: cannam@132: class TestTailCalleeImpl final: public test::TestTailCallee::Server { cannam@132: public: cannam@132: TestTailCalleeImpl(int& callCount); cannam@132: cannam@132: kj::Promise foo(FooContext context) override; cannam@132: cannam@132: private: cannam@132: int& callCount; cannam@132: }; cannam@132: cannam@132: class TestMoreStuffImpl final: public test::TestMoreStuff::Server { cannam@132: public: cannam@132: TestMoreStuffImpl(int& callCount, int& handleCount); cannam@132: cannam@132: kj::Promise getCallSequence(GetCallSequenceContext context) override; cannam@132: cannam@132: kj::Promise callFoo(CallFooContext context) override; cannam@132: cannam@132: kj::Promise callFooWhenResolved(CallFooWhenResolvedContext context) override; cannam@132: cannam@132: kj::Promise neverReturn(NeverReturnContext context) override; cannam@132: cannam@132: kj::Promise hold(HoldContext context) override; cannam@132: cannam@132: kj::Promise callHeld(CallHeldContext context) override; cannam@132: cannam@132: kj::Promise getHeld(GetHeldContext context) override; cannam@132: cannam@132: kj::Promise echo(EchoContext context) override; cannam@132: cannam@132: kj::Promise expectCancel(ExpectCancelContext context) override; cannam@132: cannam@132: kj::Promise getHandle(GetHandleContext context) override; cannam@132: cannam@132: kj::Promise getNull(GetNullContext context) override; cannam@132: cannam@132: private: cannam@132: int& callCount; cannam@132: int& handleCount; cannam@132: test::TestInterface::Client clientToHold = nullptr; cannam@132: cannam@132: kj::Promise loop(uint depth, test::TestInterface::Client cap, ExpectCancelContext context); cannam@132: }; cannam@132: cannam@132: class TestCapDestructor final: public test::TestInterface::Server { cannam@132: // Implementation of TestInterface that notifies when it is destroyed. cannam@132: cannam@132: public: cannam@132: TestCapDestructor(kj::Own>&& fulfiller) cannam@132: : fulfiller(kj::mv(fulfiller)), impl(dummy) {} cannam@132: cannam@132: ~TestCapDestructor() { cannam@132: fulfiller->fulfill(); cannam@132: } cannam@132: cannam@132: kj::Promise foo(FooContext context) { cannam@132: return impl.foo(context); cannam@132: } cannam@132: cannam@132: private: cannam@132: kj::Own> fulfiller; cannam@132: int dummy = 0; cannam@132: TestInterfaceImpl impl; cannam@132: }; cannam@132: cannam@132: #endif // !CAPNP_LITE cannam@132: cannam@132: } // namespace _ (private) cannam@132: } // namespace capnp cannam@132: cannam@132: #endif // TEST_UTIL_H_