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-testutils/dispatcher_stub.h>
6 #include <lib/async/cpp/wait.h>
7 #include <unittest/unittest.h>
8
9 namespace {
10
11 const zx_handle_t dummy_handle = static_cast<zx_handle_t>(1);
12 const zx_signals_t dummy_trigger = ZX_USER_SIGNAL_0;
13 const zx_packet_signal_t dummy_signal{
14 .trigger = dummy_trigger,
15 .observed = ZX_USER_SIGNAL_0 | ZX_USER_SIGNAL_1,
16 .count = 0u,
17 .reserved0 = 0u,
18 .reserved1 = 0u};
19
20 class MockDispatcher : public async::DispatcherStub {
21 public:
22 enum class Op {
23 NONE,
24 BEGIN_WAIT,
25 CANCEL_WAIT,
26 };
27
BeginWait(async_wait_t * wait)28 zx_status_t BeginWait(async_wait_t* wait) override {
29 last_op = Op::BEGIN_WAIT;
30 last_wait = wait;
31 return next_status;
32 }
33
CancelWait(async_wait_t * wait)34 zx_status_t CancelWait(async_wait_t* wait) override {
35 last_op = Op::CANCEL_WAIT;
36 last_wait = wait;
37 return next_status;
38 }
39
40 Op last_op = Op::NONE;
41 async_wait_t* last_wait = nullptr;
42 zx_status_t next_status = ZX_OK;
43 };
44
45 class Harness {
46 public:
Harness()47 Harness() { Reset(); }
48
Reset()49 void Reset() {
50 handler_ran = false;
51 last_wait = nullptr;
52 last_status = ZX_ERR_INTERNAL;
53 last_signal = nullptr;
54 }
55
Handler(async_dispatcher_t * dispatcher,async::WaitBase * wait,zx_status_t status,const zx_packet_signal_t * signal)56 void Handler(async_dispatcher_t* dispatcher, async::WaitBase* wait, zx_status_t status,
57 const zx_packet_signal_t* signal) {
58 handler_ran = true;
59 last_wait = wait;
60 last_status = status;
61 last_signal = signal;
62 }
63
64 virtual async::WaitBase& wait() = 0;
65
66 bool handler_ran;
67 async::WaitBase* last_wait;
68 zx_status_t last_status;
69 const zx_packet_signal_t* last_signal;
70 };
71
72 class LambdaHarness : public Harness {
73 public:
LambdaHarness(zx_handle_t object=ZX_HANDLE_INVALID,zx_signals_t trigger=ZX_SIGNAL_NONE)74 LambdaHarness(zx_handle_t object = ZX_HANDLE_INVALID,
75 zx_signals_t trigger = ZX_SIGNAL_NONE)
76 : wait_{object, trigger,
77 [this](async_dispatcher_t* dispatcher, async::Wait* wait, zx_status_t status,
78 const zx_packet_signal_t* signal) {
79 Handler(dispatcher, wait, status, signal);
80 }} {}
81
wait()82 async::WaitBase& wait() override { return wait_; }
83
84 private:
85 async::Wait wait_;
86 };
87
88 class MethodHarness : public Harness {
89 public:
MethodHarness(zx_handle_t object=ZX_HANDLE_INVALID,zx_signals_t trigger=ZX_SIGNAL_NONE)90 MethodHarness(zx_handle_t object = ZX_HANDLE_INVALID,
91 zx_signals_t trigger = ZX_SIGNAL_NONE)
92 : wait_{this, object, trigger} {}
93
wait()94 async::WaitBase& wait() override { return wait_; }
95
96 private:
97 async::WaitMethod<Harness, &Harness::Handler> wait_;
98 };
99
wait_set_handler_test()100 bool wait_set_handler_test() {
101 BEGIN_TEST;
102
103 {
104 async::Wait wait;
105 EXPECT_FALSE(wait.has_handler());
106 EXPECT_FALSE(wait.is_pending());
107
108 wait.set_handler([](async_dispatcher_t* dispatcher, async::Wait* wait, zx_status_t status,
109 const zx_packet_signal_t* signal) {});
110 EXPECT_TRUE(wait.has_handler());
111 }
112
113 {
114 async::Wait wait(ZX_HANDLE_INVALID, ZX_SIGNAL_NONE,
115 [](async_dispatcher_t* dispatcher, async::Wait* wait, zx_status_t status,
116 const zx_packet_signal_t* signal) {});
117 EXPECT_TRUE(wait.has_handler());
118 EXPECT_FALSE(wait.is_pending());
119 }
120
121 END_TEST;
122 }
123
124 template <typename Harness>
wait_properties_test()125 bool wait_properties_test() {
126 BEGIN_TEST;
127
128 Harness harness;
129
130 EXPECT_EQ(ZX_HANDLE_INVALID, harness.wait().object());
131 harness.wait().set_object(dummy_handle);
132 EXPECT_EQ(dummy_handle, harness.wait().object());
133
134 EXPECT_EQ(ZX_SIGNAL_NONE, harness.wait().trigger());
135 harness.wait().set_trigger(dummy_trigger);
136 EXPECT_EQ(dummy_trigger, harness.wait().trigger());
137
138 END_TEST;
139 }
140
141 template <typename Harness>
wait_begin_test()142 bool wait_begin_test() {
143 BEGIN_TEST;
144
145 MockDispatcher dispatcher;
146
147 {
148 Harness harness(dummy_handle, dummy_trigger);
149 EXPECT_FALSE(harness.wait().is_pending());
150
151 dispatcher.next_status = ZX_OK;
152 EXPECT_EQ(ZX_OK, harness.wait().Begin(&dispatcher));
153 EXPECT_TRUE(harness.wait().is_pending());
154 EXPECT_EQ(MockDispatcher::Op::BEGIN_WAIT, dispatcher.last_op);
155 EXPECT_EQ(dummy_handle, dispatcher.last_wait->object);
156 EXPECT_EQ(dummy_trigger, dispatcher.last_wait->trigger);
157 EXPECT_FALSE(harness.handler_ran);
158
159 harness.Reset();
160 dispatcher.last_op = MockDispatcher::Op::NONE;
161 EXPECT_EQ(ZX_ERR_ALREADY_EXISTS, harness.wait().Begin(&dispatcher));
162 EXPECT_EQ(MockDispatcher::Op::NONE, dispatcher.last_op);
163 EXPECT_FALSE(harness.handler_ran);
164 }
165 EXPECT_EQ(MockDispatcher::Op::CANCEL_WAIT, dispatcher.last_op);
166
167 {
168 Harness harness(dummy_handle, dummy_trigger);
169 EXPECT_FALSE(harness.wait().is_pending());
170
171 dispatcher.next_status = ZX_ERR_BAD_STATE;
172 EXPECT_EQ(ZX_ERR_BAD_STATE, harness.wait().Begin(&dispatcher));
173 EXPECT_EQ(MockDispatcher::Op::BEGIN_WAIT, dispatcher.last_op);
174 EXPECT_FALSE(harness.wait().is_pending());
175 EXPECT_FALSE(harness.handler_ran);
176 }
177 EXPECT_EQ(MockDispatcher::Op::BEGIN_WAIT, dispatcher.last_op);
178
179 END_TEST;
180 }
181
182 template <typename Harness>
wait_cancel_test()183 bool wait_cancel_test() {
184 BEGIN_TEST;
185
186 MockDispatcher dispatcher;
187
188 {
189 Harness harness(dummy_handle, dummy_trigger);
190 EXPECT_FALSE(harness.wait().is_pending());
191
192 EXPECT_EQ(ZX_ERR_NOT_FOUND, harness.wait().Cancel());
193 EXPECT_EQ(MockDispatcher::Op::NONE, dispatcher.last_op);
194 EXPECT_FALSE(harness.wait().is_pending());
195
196 EXPECT_EQ(ZX_OK, harness.wait().Begin(&dispatcher));
197 EXPECT_EQ(MockDispatcher::Op::BEGIN_WAIT, dispatcher.last_op);
198 EXPECT_TRUE(harness.wait().is_pending());
199
200 EXPECT_EQ(ZX_OK, harness.wait().Cancel());
201 EXPECT_EQ(MockDispatcher::Op::CANCEL_WAIT, dispatcher.last_op);
202 EXPECT_FALSE(harness.wait().is_pending());
203
204 dispatcher.last_op = MockDispatcher::Op::NONE;
205 EXPECT_EQ(ZX_ERR_NOT_FOUND, harness.wait().Cancel());
206 EXPECT_EQ(MockDispatcher::Op::NONE, dispatcher.last_op);
207 EXPECT_FALSE(harness.wait().is_pending());
208 }
209 EXPECT_EQ(MockDispatcher::Op::NONE, dispatcher.last_op);
210
211 END_TEST;
212 }
213
214 template <typename Harness>
wait_run_handler_test()215 bool wait_run_handler_test() {
216 BEGIN_TEST;
217
218 MockDispatcher dispatcher;
219
220 {
221 Harness harness(dummy_handle, dummy_trigger);
222 EXPECT_FALSE(harness.wait().is_pending());
223
224 EXPECT_EQ(ZX_OK, harness.wait().Begin(&dispatcher));
225 EXPECT_EQ(MockDispatcher::Op::BEGIN_WAIT, dispatcher.last_op);
226 EXPECT_TRUE(harness.wait().is_pending());
227
228 harness.Reset();
229 dispatcher.last_wait->handler(&dispatcher, dispatcher.last_wait, ZX_OK, &dummy_signal);
230 EXPECT_TRUE(harness.handler_ran);
231 EXPECT_EQ(&harness.wait(), harness.last_wait);
232 EXPECT_EQ(ZX_OK, harness.last_status);
233 EXPECT_EQ(&dummy_signal, harness.last_signal);
234 EXPECT_FALSE(harness.wait().is_pending());
235
236 dispatcher.last_op = MockDispatcher::Op::NONE;
237 EXPECT_EQ(ZX_ERR_NOT_FOUND, harness.wait().Cancel());
238 EXPECT_EQ(MockDispatcher::Op::NONE, dispatcher.last_op);
239 EXPECT_FALSE(harness.wait().is_pending());
240 }
241 EXPECT_EQ(MockDispatcher::Op::NONE, dispatcher.last_op);
242
243 END_TEST;
244 }
245
unsupported_begin_wait_test()246 bool unsupported_begin_wait_test() {
247 BEGIN_TEST;
248
249 async::DispatcherStub dispatcher;
250 async_wait_t wait{};
251 EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, async_begin_wait(&dispatcher, &wait), "valid args");
252
253 END_TEST;
254 }
255
unsupported_cancel_wait_test()256 bool unsupported_cancel_wait_test() {
257 BEGIN_TEST;
258
259 async::DispatcherStub dispatcher;
260 async_wait_t wait{};
261 EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, async_cancel_wait(&dispatcher, &wait), "valid args");
262
263 END_TEST;
264 }
265
266 } // namespace
267
268 BEGIN_TEST_CASE(wait_tests)
269 RUN_TEST(wait_set_handler_test)
270 RUN_TEST((wait_properties_test<LambdaHarness>))
271 RUN_TEST((wait_properties_test<MethodHarness>))
272 RUN_TEST((wait_begin_test<LambdaHarness>))
273 RUN_TEST((wait_begin_test<MethodHarness>))
274 RUN_TEST((wait_cancel_test<LambdaHarness>))
275 RUN_TEST((wait_cancel_test<MethodHarness>))
276 RUN_TEST((wait_run_handler_test<LambdaHarness>))
277 RUN_TEST((wait_run_handler_test<MethodHarness>))
278 RUN_TEST(unsupported_begin_wait_test)
279 RUN_TEST(unsupported_cancel_wait_test)
280 END_TEST_CASE(wait_tests)
281