1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <lib/async/cpp/receiver.h>
6
7 #include <lib/async-testutils/dispatcher_stub.h>
8 #include <unittest/unittest.h>
9
10 namespace {
11
12 class MockDispatcher : public async::DispatcherStub {
13 public:
14 enum class Op {
15 NONE,
16 QUEUE_PACKET
17 };
18
QueuePacket(async_receiver_t * receiver,const zx_packet_user_t * data)19 zx_status_t QueuePacket(async_receiver_t* receiver,
20 const zx_packet_user_t* data) override {
21 last_op = Op::QUEUE_PACKET;
22 last_receiver = receiver;
23 last_data = data;
24 return next_status;
25 }
26
27 Op last_op = Op::NONE;
28 async_receiver_t* last_receiver = nullptr;
29 const zx_packet_user_t* last_data = nullptr;
30 zx_status_t next_status = ZX_OK;
31 };
32
33 class Harness {
34 public:
Harness()35 Harness() { Reset(); }
36
Reset()37 void Reset() {
38 handler_ran = false;
39 last_receiver = nullptr;
40 last_status = ZX_ERR_INTERNAL;
41 last_data = nullptr;
42 }
43
Handler(async_dispatcher_t * dispatcher,async::ReceiverBase * receiver,zx_status_t status,const zx_packet_user_t * data)44 void Handler(async_dispatcher_t* dispatcher, async::ReceiverBase* receiver,
45 zx_status_t status, const zx_packet_user_t* data) {
46 handler_ran = true;
47 last_receiver = receiver;
48 last_status = status;
49 last_data = data;
50 }
51
52 virtual async::ReceiverBase& receiver() = 0;
53
54 bool handler_ran;
55 async::ReceiverBase* last_receiver;
56 zx_status_t last_status;
57 const zx_packet_user_t* last_data;
58 };
59
60 class LambdaHarness : public Harness {
61 public:
receiver()62 async::ReceiverBase& receiver() override { return receiver_; }
63
64 private:
65 async::Receiver receiver_{[this](async_dispatcher_t* dispatcher, async::Receiver* receiver,
__anon9477f0080202() 66 zx_status_t status, const zx_packet_user_t* data) {
67 Handler(dispatcher, receiver, status, data);
68 }};
69 };
70
71 class MethodHarness : public Harness {
72 public:
receiver()73 async::ReceiverBase& receiver() override { return receiver_; }
74
75 private:
76 async::ReceiverMethod<Harness, &Harness::Handler> receiver_{this};
77 };
78
receiver_set_handler_test()79 bool receiver_set_handler_test() {
80 BEGIN_TEST;
81
82 {
83 async::Receiver receiver;
84 EXPECT_FALSE(receiver.has_handler());
85
86 receiver.set_handler([](async_dispatcher_t* dispatcher, async::Receiver* receiver,
87 zx_status_t status, const zx_packet_user_t* data) {});
88 EXPECT_TRUE(receiver.has_handler());
89 }
90
91 {
92 async::Receiver receiver([](async_dispatcher_t* dispatcher, async::Receiver* receiver,
93 zx_status_t status, const zx_packet_user_t* data) {});
94 EXPECT_TRUE(receiver.has_handler());
95 }
96
97 END_TEST;
98 }
99
100 template <typename Harness>
receiver_queue_packet_test()101 bool receiver_queue_packet_test() {
102 BEGIN_TEST;
103
104 const zx_packet_user_t dummy_data{};
105 MockDispatcher dispatcher;
106 Harness harness;
107
108 harness.Reset();
109 dispatcher.next_status = ZX_OK;
110 EXPECT_EQ(ZX_OK, harness.receiver().QueuePacket(&dispatcher, nullptr), "queue, null data");
111 EXPECT_EQ(MockDispatcher::Op::QUEUE_PACKET, dispatcher.last_op);
112 EXPECT_NULL(dispatcher.last_data);
113 EXPECT_FALSE(harness.handler_ran);
114
115 harness.Reset();
116 dispatcher.next_status = ZX_ERR_BAD_STATE;
117 EXPECT_EQ(ZX_ERR_BAD_STATE, harness.receiver().QueuePacket(&dispatcher, nullptr), "queue, null data");
118 EXPECT_EQ(MockDispatcher::Op::QUEUE_PACKET, dispatcher.last_op);
119 EXPECT_NULL(dispatcher.last_data);
120 EXPECT_FALSE(harness.handler_ran);
121
122 harness.Reset();
123 dispatcher.next_status = ZX_OK;
124 EXPECT_EQ(ZX_OK, harness.receiver().QueuePacket(&dispatcher, &dummy_data), "queue, non-null data");
125 EXPECT_EQ(MockDispatcher::Op::QUEUE_PACKET, dispatcher.last_op);
126 EXPECT_EQ(&dummy_data, dispatcher.last_data);
127 EXPECT_FALSE(harness.handler_ran);
128
129 harness.Reset();
130 dispatcher.next_status = ZX_ERR_BAD_STATE;
131 EXPECT_EQ(ZX_ERR_BAD_STATE, harness.receiver().QueuePacket(&dispatcher, &dummy_data), "queue, non-null data");
132 EXPECT_EQ(MockDispatcher::Op::QUEUE_PACKET, dispatcher.last_op);
133 EXPECT_EQ(&dummy_data, dispatcher.last_data);
134 EXPECT_FALSE(harness.handler_ran);
135
136 END_TEST;
137 }
138
139 template <typename Harness>
receiver_run_handler_test()140 bool receiver_run_handler_test() {
141 BEGIN_TEST;
142
143 const zx_packet_user_t dummy_data{};
144 MockDispatcher dispatcher;
145 Harness harness;
146
147 EXPECT_EQ(ZX_OK, harness.receiver().QueuePacket(&dispatcher, nullptr));
148 EXPECT_EQ(ZX_OK, harness.receiver().QueuePacket(&dispatcher, &dummy_data));
149
150 harness.Reset();
151 dispatcher.last_receiver->handler(&dispatcher, dispatcher.last_receiver, ZX_OK, nullptr);
152 EXPECT_TRUE(harness.handler_ran);
153 EXPECT_EQ(&harness.receiver(), harness.last_receiver);
154 EXPECT_EQ(ZX_OK, harness.last_status);
155 EXPECT_NULL(harness.last_data);
156
157 harness.Reset();
158 dispatcher.last_receiver->handler(&dispatcher, dispatcher.last_receiver, ZX_OK, &dummy_data);
159 EXPECT_TRUE(harness.handler_ran);
160 EXPECT_EQ(&harness.receiver(), harness.last_receiver);
161 EXPECT_EQ(ZX_OK, harness.last_status);
162 EXPECT_EQ(&dummy_data, harness.last_data);
163
164 END_TEST;
165 }
166
unsupported_queue_packet_test()167 bool unsupported_queue_packet_test() {
168 BEGIN_TEST;
169
170 async::DispatcherStub dispatcher;
171 async_receiver_t receiver{};
172 EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, async_queue_packet(&dispatcher, &receiver, nullptr), "valid args without data");
173 zx_packet_user_t data;
174 EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, async_queue_packet(&dispatcher, &receiver, &data), "valid args with data");
175
176 END_TEST;
177 }
178
179 } // namespace
180
181 BEGIN_TEST_CASE(receiver_tests)
182 RUN_TEST(receiver_set_handler_test)
183 RUN_TEST((receiver_queue_packet_test<LambdaHarness>))
184 RUN_TEST((receiver_queue_packet_test<MethodHarness>))
185 RUN_TEST((receiver_run_handler_test<LambdaHarness>))
186 RUN_TEST((receiver_run_handler_test<MethodHarness>))
187 RUN_TEST(unsupported_queue_packet_test)
188 END_TEST_CASE(receiver_tests)
189