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