blob: fcf402319655a6b42cde04e986c46fe1dab19fc3 [file] [log] [blame]
// Copyright 2017 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 <lib/async-testing/dispatcher_stub.h>
#include <lib/async/cpp/receiver.h>
#include <zxtest/zxtest.h>
namespace {
class MockDispatcher : public async::DispatcherStub {
public:
enum class Op { NONE, QUEUE_PACKET };
zx_status_t QueuePacket(async_receiver_t* receiver, const zx_packet_user_t* data) override {
last_op = Op::QUEUE_PACKET;
last_receiver = receiver;
last_data = data;
return next_status;
}
Op last_op = Op::NONE;
async_receiver_t* last_receiver = nullptr;
const zx_packet_user_t* last_data = nullptr;
zx_status_t next_status = ZX_OK;
};
class Harness {
public:
Harness() { Reset(); }
void Reset() {
handler_ran = false;
last_receiver = nullptr;
last_status = ZX_ERR_INTERNAL;
last_data = nullptr;
}
void Handler(async_dispatcher_t* dispatcher, async::ReceiverBase* receiver, zx_status_t status,
const zx_packet_user_t* data) {
handler_ran = true;
last_receiver = receiver;
last_status = status;
last_data = data;
}
virtual async::ReceiverBase& receiver() = 0;
bool handler_ran;
async::ReceiverBase* last_receiver;
zx_status_t last_status;
const zx_packet_user_t* last_data;
};
class LambdaHarness : public Harness {
public:
async::ReceiverBase& receiver() override { return receiver_; }
private:
async::Receiver receiver_{
[this](async_dispatcher_t* dispatcher, async::Receiver* receiver, zx_status_t status,
const zx_packet_user_t* data) { Handler(dispatcher, receiver, status, data); }};
};
class MethodHarness : public Harness {
public:
async::ReceiverBase& receiver() override { return receiver_; }
private:
async::ReceiverMethod<Harness, &Harness::Handler> receiver_{this};
};
TEST(ReceiverTests, receiver_set_handler_test) {
{
async::Receiver receiver;
EXPECT_FALSE(receiver.has_handler());
receiver.set_handler([](async_dispatcher_t* dispatcher, async::Receiver* receiver,
zx_status_t status, const zx_packet_user_t* data) {});
EXPECT_TRUE(receiver.has_handler());
}
{
async::Receiver receiver([](async_dispatcher_t* dispatcher, async::Receiver* receiver,
zx_status_t status, const zx_packet_user_t* data) {});
EXPECT_TRUE(receiver.has_handler());
}
}
template <typename Harness>
void receiver_queue_packet_test() {
const zx_packet_user_t dummy_data{};
MockDispatcher dispatcher;
Harness harness;
harness.Reset();
dispatcher.next_status = ZX_OK;
EXPECT_EQ(ZX_OK, harness.receiver().QueuePacket(&dispatcher, nullptr), "queue, null data");
EXPECT_EQ(MockDispatcher::Op::QUEUE_PACKET, dispatcher.last_op);
EXPECT_NULL(dispatcher.last_data);
EXPECT_FALSE(harness.handler_ran);
harness.Reset();
dispatcher.next_status = ZX_ERR_BAD_STATE;
EXPECT_EQ(ZX_ERR_BAD_STATE, harness.receiver().QueuePacket(&dispatcher, nullptr),
"queue, null data");
EXPECT_EQ(MockDispatcher::Op::QUEUE_PACKET, dispatcher.last_op);
EXPECT_NULL(dispatcher.last_data);
EXPECT_FALSE(harness.handler_ran);
harness.Reset();
dispatcher.next_status = ZX_OK;
EXPECT_EQ(ZX_OK, harness.receiver().QueuePacket(&dispatcher, &dummy_data),
"queue, non-null data");
EXPECT_EQ(MockDispatcher::Op::QUEUE_PACKET, dispatcher.last_op);
EXPECT_EQ(&dummy_data, dispatcher.last_data);
EXPECT_FALSE(harness.handler_ran);
harness.Reset();
dispatcher.next_status = ZX_ERR_BAD_STATE;
EXPECT_EQ(ZX_ERR_BAD_STATE, harness.receiver().QueuePacket(&dispatcher, &dummy_data),
"queue, non-null data");
EXPECT_EQ(MockDispatcher::Op::QUEUE_PACKET, dispatcher.last_op);
EXPECT_EQ(&dummy_data, dispatcher.last_data);
EXPECT_FALSE(harness.handler_ran);
}
template <typename Harness>
void receiver_run_handler_test() {
const zx_packet_user_t dummy_data{};
MockDispatcher dispatcher;
Harness harness;
EXPECT_EQ(ZX_OK, harness.receiver().QueuePacket(&dispatcher, nullptr));
EXPECT_EQ(ZX_OK, harness.receiver().QueuePacket(&dispatcher, &dummy_data));
harness.Reset();
dispatcher.last_receiver->handler(&dispatcher, dispatcher.last_receiver, ZX_OK, nullptr);
EXPECT_TRUE(harness.handler_ran);
EXPECT_EQ(&harness.receiver(), harness.last_receiver);
EXPECT_EQ(ZX_OK, harness.last_status);
EXPECT_NULL(harness.last_data);
harness.Reset();
dispatcher.last_receiver->handler(&dispatcher, dispatcher.last_receiver, ZX_OK, &dummy_data);
EXPECT_TRUE(harness.handler_ran);
EXPECT_EQ(&harness.receiver(), harness.last_receiver);
EXPECT_EQ(ZX_OK, harness.last_status);
EXPECT_EQ(&dummy_data, harness.last_data);
}
TEST(ReceiverTests, unsupported_queue_packet_test) {
async::DispatcherStub dispatcher;
async_receiver_t receiver{};
EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, async_queue_packet(&dispatcher, &receiver, nullptr),
"valid args without data");
zx_packet_user_t data;
EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, async_queue_packet(&dispatcher, &receiver, &data),
"valid args with data");
}
} // namespace
TEST(ReceiverTests, receiver_queue_packet_test_LambdaHarness) {
receiver_queue_packet_test<LambdaHarness>();
}
TEST(ReceiverTests, receiver_queue_packet_test_MethodHarness) {
receiver_queue_packet_test<MethodHarness>();
}
TEST(ReceiverTests, receiver_run_handler_test_LambdaHarness) {
receiver_run_handler_test<LambdaHarness>();
}
TEST(ReceiverTests, receiver_run_handler_test_MethodHarness) {
receiver_run_handler_test<MethodHarness>();
}