| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <inttypes.h> |
| #include <lib/fidl-utils/bind.h> |
| #include <zircon/fidl.h> |
| #include <zircon/types.h> |
| |
| #include <type_traits> |
| |
| #include <fidl/test/fidlutils/c/fidl.h> |
| #include <zxtest/zxtest.h> |
| |
| namespace { |
| class BaseClass { |
| public: |
| zx_status_t SimpleFnWithReply(uint64_t, fidl_txn_t*) { return ZX_OK; } |
| zx_status_t SimpleFnWithoutReply(uint64_t) { return ZX_OK; } |
| zx_status_t ConstFnWithReply(uint64_t, fidl_txn_t*) const { return ZX_OK; } |
| zx_status_t ConstFnWithoutReply(uint64_t) const { return ZX_OK; } |
| zx_status_t VolatileFnWithReply(uint64_t, fidl_txn_t*) volatile { return ZX_OK; } |
| zx_status_t VolatileFnWithoutReply(uint64_t) volatile { return ZX_OK; } |
| |
| zx_status_t OverloadedFnWithReply(uint64_t, fidl_txn_t*) { return ZX_OK; } |
| |
| // This should not be called |
| zx_status_t OverloadedFnWithReply(uint64_t) { return ZX_ERR_INTERNAL; } |
| |
| zx_status_t OverloadedFnWithoutReply(uint64_t) { return ZX_OK; } |
| |
| // This should not be called |
| zx_status_t OverloadedFnWithoutReply(uint64_t, fidl_txn_t*) { return ZX_ERR_INTERNAL; } |
| |
| virtual zx_status_t VirtualFnWithReply(uint64_t magic_number, fidl_txn_t*) { |
| EXPECT_EQ(magic_number, MAGIC_NUMBER); |
| return ZX_OK; |
| } |
| |
| virtual zx_status_t VirtualFnWithoutReply(uint64_t magic_number) { |
| EXPECT_EQ(magic_number, MAGIC_NUMBER); |
| return ZX_OK; |
| } |
| |
| constexpr static uint64_t MAGIC_NUMBER = 42; |
| }; |
| |
| class DerivedClass : BaseClass { |
| public: |
| virtual zx_status_t VirtualFnWithReply(uint64_t magic_number, fidl_txn_t*) override { |
| EXPECT_EQ(magic_number, MAGIC_NUMBER); |
| return ZX_OK; |
| } |
| |
| virtual zx_status_t VirtualFnWithoutReply(uint64_t magic_number) override { |
| EXPECT_EQ(magic_number, MAGIC_NUMBER); |
| return ZX_OK; |
| } |
| |
| constexpr static uint64_t MAGIC_NUMBER = 183; |
| }; |
| |
| using BaseBinder = fidl::Binder<BaseClass>; |
| using DerivedBinder = fidl::Binder<DerivedClass>; |
| |
| // Compile-time checks |
| static_assert( |
| std::is_same<decltype(fidl_test_fidlutils_BindingTestsProtocol_ops_t::FunctionWithReply), |
| zx_status_t (*)(void*, uint64_t, fidl_txn_t*)>::value, |
| "Unexpected signature for C binding of BindingTestsProtocol::FunctionWithReply"); |
| static_assert( |
| std::is_same<decltype(fidl_test_fidlutils_BindingTestsProtocol_ops_t::FunctionWithoutReply), |
| zx_status_t (*)(void*, uint64_t)>::value, |
| "Unexpected signature for C binding of BindingTestsProtocol::FunctionWithoutReply"); |
| |
| TEST(BindingTests, SimpleBindMemberTest) { |
| BaseClass base; |
| void* base_ctx = &base; |
| fidl_txn_t dummy_txn; |
| |
| fidl_test_fidlutils_BindingTestsProtocol_ops_t ops = { |
| .FunctionWithReply = BaseBinder::BindMember<&BaseClass::SimpleFnWithReply>, |
| .FunctionWithoutReply = BaseBinder::BindMember<&BaseClass::SimpleFnWithoutReply>, |
| }; |
| |
| EXPECT_EQ(ops.FunctionWithReply(base_ctx, BaseClass::MAGIC_NUMBER, &dummy_txn), ZX_OK); |
| EXPECT_EQ(ops.FunctionWithoutReply(base_ctx, BaseClass::MAGIC_NUMBER), ZX_OK); |
| } |
| |
| TEST(BindingTests, ConstBindMemberTest) { |
| BaseClass base; |
| void* base_ctx = &base; |
| fidl_txn_t dummy_txn; |
| |
| fidl_test_fidlutils_BindingTestsProtocol_ops_t ops = { |
| .FunctionWithReply = BaseBinder::BindMember<&BaseClass::ConstFnWithReply>, |
| .FunctionWithoutReply = BaseBinder::BindMember<&BaseClass::ConstFnWithoutReply>, |
| }; |
| |
| EXPECT_EQ(ops.FunctionWithReply(base_ctx, BaseClass::MAGIC_NUMBER, &dummy_txn), ZX_OK); |
| EXPECT_EQ(ops.FunctionWithoutReply(base_ctx, BaseClass::MAGIC_NUMBER), ZX_OK); |
| } |
| |
| TEST(BindingTests, VolatileBindMemberTest) { |
| BaseClass base; |
| void* base_ctx = &base; |
| fidl_txn_t dummy_txn; |
| |
| fidl_test_fidlutils_BindingTestsProtocol_ops_t ops = { |
| .FunctionWithReply = BaseBinder::BindMember<&BaseClass::VolatileFnWithReply>, |
| .FunctionWithoutReply = BaseBinder::BindMember<&BaseClass::VolatileFnWithoutReply>, |
| }; |
| |
| EXPECT_EQ(ops.FunctionWithReply(base_ctx, BaseClass::MAGIC_NUMBER, &dummy_txn), ZX_OK); |
| EXPECT_EQ(ops.FunctionWithoutReply(base_ctx, BaseClass::MAGIC_NUMBER), ZX_OK); |
| } |
| |
| TEST(BindingTests, OverloadedBindMemberTest) { |
| BaseClass base; |
| void* base_ctx = &base; |
| fidl_txn_t dummy_txn; |
| |
| fidl_test_fidlutils_BindingTestsProtocol_ops_t ops = { |
| .FunctionWithReply = BaseBinder::BindMember<zx_status_t(uint64_t, fidl_txn_t*), |
| &BaseClass::OverloadedFnWithReply>, |
| .FunctionWithoutReply = |
| BaseBinder::BindMember<zx_status_t(uint64_t), &BaseClass::OverloadedFnWithoutReply>, |
| }; |
| |
| EXPECT_EQ(ops.FunctionWithReply(base_ctx, BaseClass::MAGIC_NUMBER, &dummy_txn), ZX_OK); |
| EXPECT_EQ(ops.FunctionWithoutReply(base_ctx, BaseClass::MAGIC_NUMBER), ZX_OK); |
| } |
| |
| TEST(BindingTests, VirtualBindMemberTest) { |
| BaseClass base; |
| DerivedClass derived; |
| void* base_ctx = &base; |
| void* derived_ctx = &derived; |
| fidl_txn_t dummy_txn; |
| |
| fidl_test_fidlutils_BindingTestsProtocol_ops_t base_ops = { |
| .FunctionWithReply = BaseBinder::BindMember<&BaseClass::VirtualFnWithReply>, |
| .FunctionWithoutReply = BaseBinder::BindMember<&BaseClass::VirtualFnWithoutReply>, |
| }; |
| fidl_test_fidlutils_BindingTestsProtocol_ops_t derived_ops = { |
| .FunctionWithReply = DerivedBinder::BindMember<&DerivedClass::VirtualFnWithReply>, |
| .FunctionWithoutReply = DerivedBinder::BindMember<&DerivedClass::VirtualFnWithoutReply>, |
| }; |
| |
| EXPECT_EQ(base_ops.FunctionWithReply(base_ctx, BaseClass::MAGIC_NUMBER, &dummy_txn), ZX_OK); |
| EXPECT_EQ(base_ops.FunctionWithoutReply(base_ctx, BaseClass::MAGIC_NUMBER), ZX_OK); |
| |
| EXPECT_EQ(derived_ops.FunctionWithReply(derived_ctx, DerivedClass::MAGIC_NUMBER, &dummy_txn), |
| ZX_OK); |
| EXPECT_EQ(derived_ops.FunctionWithoutReply(derived_ctx, DerivedClass::MAGIC_NUMBER), ZX_OK); |
| } |
| |
| } // namespace |