blob: 223296fa7adabf8af3c9c682b20e9509739408c5 [file] [log] [blame]
// 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.
#ifndef SRC_LIB_FIDL_CODEC_FIDL_CODEC_TEST_H_
#define SRC_LIB_FIDL_CODEC_FIDL_CODEC_TEST_H_
#include <fuchsia/sys/cpp/fidl.h>
#include <sdk/lib/fidl/cpp/binding.h>
#include "src/lib/fidl_codec/library_loader.h"
namespace fidl_codec {
// Stolen from //sdk/lib/fidl/cpp/test/async_loop_for_test.{h,cc}; cc
// is not public
class AsyncLoopForTestImpl;
class AsyncLoopForTest {
public:
// The AsyncLoopForTest constructor should also call
// async_set_default_dispatcher() with the chosen dispatcher implementation.
AsyncLoopForTest();
~AsyncLoopForTest();
// This call matches the behavior of async_loop_run_until_idle().
zx_status_t RunUntilIdle();
// This call matches the behavior of async_loop_run().
zx_status_t Run();
// Returns the underlying async_t.
async_dispatcher_t* dispatcher();
private:
std::unique_ptr<AsyncLoopForTestImpl> impl_;
};
class AsyncLoopForTestImpl {
public:
AsyncLoopForTestImpl() : loop_(&kAsyncLoopConfigAttachToCurrentThread) {}
~AsyncLoopForTestImpl() = default;
async::Loop* loop() { return &loop_; }
private:
async::Loop loop_;
};
// The fidl_codec tests work the following way:
// 1) Create a channel.
// 2) Bind an interface pointer to the client side of that channel.
// 3) Listen at the other end of the channel for the message.
// 4) Convert the message to JSON using the JSON message converter, and check
// that the results look as expected.
// This binds |invoke| to one end of a channel, invokes it, and drops the wire
// format bits it picks up off the other end into |message|.
template <class T>
void InterceptRequest(fidl::HLCPPIncomingMessage& message,
std::function<void(fidl::InterfacePtr<T>&)> invoke) {
AsyncLoopForTest loop;
zx::channel h1, h2;
EXPECT_EQ(ZX_OK, zx::channel::create(0, &h1, &h2));
fidl::InterfacePtr<T> ptr;
int error_count = 0;
ptr.set_error_handler([&error_count](zx_status_t status) {
EXPECT_EQ(ZX_ERR_INVALID_ARGS, status);
++error_count;
});
EXPECT_EQ(ZX_OK, ptr.Bind(std::move(h1)));
invoke(ptr);
loop.RunUntilIdle();
EXPECT_EQ(ZX_OK, message.Read(h2.get(), 0));
}
// This creates two channels and sends an `epitaph` on one, and reads the resulting
// bytes from the other into `message`.
template <class T>
void InterceptEpitaphResponse(fidl::HLCPPIncomingMessage& message, zx_status_t epitaph) {
AsyncLoopForTest loop;
zx::channel h1, h2;
EXPECT_EQ(ZX_OK, zx::channel::create(0, &h1, &h2));
// Create a Binding so that we can call Close. The implementation pointer is
// not needed, since no actual method calls are being invoked.
fidl::Binding<T> binding(nullptr, fidl::InterfaceRequest<T>(std::move(h1)));
binding.Close(epitaph);
loop.RunUntilIdle();
EXPECT_EQ(ZX_OK, message.Read(h2.get(), 0));
}
LibraryLoader* GetLoader();
} // namespace fidl_codec
#endif // SRC_LIB_FIDL_CODEC_FIDL_CODEC_TEST_H_