1// Copyright 2018 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 <assert.h>
6#include <errno.h>
7#include <fcntl.h>
8#include <inttypes.h>
9#include <stdlib.h>
10#include <string.h>
11#include <unistd.h>
12
13#include <fbl/algorithm.h>
14#include <zircon/device/sysinfo.h>
15#include <zircon/process.h>
16#include <zircon/processargs.h>
17#include <zircon/status.h>
18#include <zircon/syscalls.h>
19#include <zircon/syscalls/port.h>
20#include <zircon/threads.h>
21#include <test-utils/test-utils.h>
22#include <unittest/unittest.h>
23
24static int thread_func(void* arg);
25
26// argv[0]
27static char* program_path;
28
29// We have to poll a thread's state as there is no way to wait for it to
30// transition states. Wait this amount of time. Generally the thread won't
31// take very long so this is a compromise between polling too frequently and
32// waiting too long.
33constexpr zx_duration_t THREAD_BLOCKED_WAIT_DURATION = ZX_MSEC(1);
34
35static const char test_child_name[] = "test-child";
36
37// The maximum number of handles we send with send_msg_with_handles.
38constexpr uint32_t MAX_NUM_MSG_HANDLES = 2;
39
40// The number of handles used in the wait-many test.
41constexpr uint32_t NUM_WAIT_MANY_HANDLES = MAX_NUM_MSG_HANDLES;
42
43const zx_port_packet_t port_test_packet = {
44    .key = 42u,
45    .type = ZX_PKT_TYPE_USER,
46    .status = -42,
47    { .user = { .u64 = { 1, 2, 3, 4 } } }
48};
49
50const zx_time_t interrupt_signaled_timestamp = 12345;
51
52enum MessageType : uint32_t {
53    MSG_DONE,
54    MSG_PASS,
55    MSG_FAIL,
56    MSG_PROCEED,
57    MSG_THREAD_HANDLE_REQUEST,
58    MSG_THREAD_HANDLE_RESPONSE,
59    MSG_SLEEP_TEST,
60    MSG_FUTEX_TEST,
61    MSG_PORT_TEST,
62    MSG_CHANNEL_TEST,
63    MSG_WAIT_ONE_TEST,
64    MSG_WAIT_MANY_TEST,
65    MSG_INTERRUPT_TEST,
66};
67
68struct Message {
69    MessageType type;
70    uint32_t num_handles;
71    zx_handle_t handles[MAX_NUM_MSG_HANDLES];
72};
73
74static zx_status_t get_root_resource(zx_handle_t* root_resource) {
75    int fd = open("/dev/misc/sysinfo", O_RDWR);
76    if (fd < 0) {
77        unittest_printf("ERROR: Cannot open sysinfo: %d/%s\n",
78                        errno, strerror(errno));
79        return ZX_ERR_NOT_FOUND;
80    }
81
82    ssize_t n = ioctl_sysinfo_get_root_resource(fd, root_resource);
83    close(fd);
84    if (n != sizeof(*root_resource)) {
85        if (n < 0) {
86            unittest_printf("ERROR: Cannot obtain root resource: %zd/%s\n",
87                            n, zx_status_get_string(static_cast<zx_status_t>(n)));
88            return (zx_status_t)n;
89        } else {
90            unittest_printf("ERROR: Cannot obtain root resource (%zd != %zd)\n",
91                            n, sizeof(root_resource));
92            return ZX_ERR_NOT_FOUND;
93        }
94    }
95    return ZX_OK;
96}
97
98static void send_msg_with_handles(zx_handle_t channel, MessageType type,
99                                  zx_handle_t* optional_handles, uint32_t num_handles) {
100    uint32_t data = type;
101    unittest_printf("sending message %d on handle %u, with %u handles\n",
102                    type, channel, num_handles);
103    tu_channel_write(channel, 0, &data, sizeof(data), optional_handles, num_handles);
104}
105
106static void send_msg(zx_handle_t channel, MessageType type) {
107    send_msg_with_handles(channel, type, nullptr, 0);
108}
109
110static bool recv_msg(zx_handle_t channel, Message* msg) {
111    unittest_printf("waiting for message on handle %u\n", channel);
112
113    if (!tu_channel_wait_readable(channel)) {
114        unittest_printf("peer closed while trying to read message\n");
115        return false;
116    }
117
118    uint32_t data;
119    uint32_t num_bytes = sizeof(data);
120    tu_channel_read(channel, 0, &data, &num_bytes, &msg->handles[0], &msg->num_handles);
121    if (num_bytes != sizeof(data)) {
122        unittest_printf("ERROR: unexpected message size, %u != %zu\n",
123                        num_bytes, sizeof(data));
124        return false;
125    }
126
127    msg->type = static_cast<MessageType>(data);
128    unittest_printf("received message %u\n", msg->type);
129    return true;
130}
131
132static bool recv_specific_msg(zx_handle_t channel, MessageType expected_type) {
133    Message msg;
134    ASSERT_TRUE(recv_msg(channel, &msg));
135    ASSERT_EQ(msg.type, expected_type);
136    return true;
137}
138
139static void do_msg_thread_handle_request(zx_handle_t channel, const Message* msg) {
140    if (msg->num_handles != 0) {
141        unittest_printf("ERROR: wrong number handles\n");
142        send_msg(channel, MSG_FAIL);
143        return;
144    }
145    auto self = zx_thread_self();
146    send_msg_with_handles(channel, MSG_THREAD_HANDLE_RESPONSE, &self, 1);
147}
148
149static void do_msg_sleep_test(zx_handle_t channel, const Message* msg) {
150    if (msg->num_handles != 0) {
151        unittest_printf("ERROR: wrong number handles\n");
152        // There's no point in sending MSG_FAIL here as the test can never
153        // receive MSG_PASS.
154        return;
155    }
156    zx_nanosleep(ZX_TIME_INFINITE);
157    /* NOTREACHED */
158}
159
160static void do_msg_futex_test(zx_handle_t channel, const Message* msg) {
161    if (msg->num_handles != 0) {
162        unittest_printf("ERROR: wrong number handles\n");
163        // There's no point in sending MSG_FAIL here as the test can never
164        // receive MSG_PASS.
165        return;
166    }
167
168    int futex_value = 0;
169    zx_status_t __UNUSED status = zx_futex_wait(&futex_value, 0, ZX_TIME_INFINITE);
170    /* NOTREACHED*/
171}
172
173static void do_msg_port_test(zx_handle_t channel, const Message* msg) {
174    if (msg->num_handles != 1) {
175        unittest_printf("ERROR: wrong number handles\n");
176        send_msg(channel, MSG_FAIL);
177        return;
178    }
179
180    auto port = msg->handles[0];
181    zx_port_packet_t packet;
182    auto status = zx_port_wait(port, ZX_TIME_INFINITE, &packet);
183    tu_handle_close(port);
184    if (status != ZX_OK) {
185        unittest_printf("ERROR: port_wait failed: %d/%s\n", status,
186                        zx_status_get_string(status));
187        send_msg(channel, MSG_FAIL);
188        return;
189    }
190
191    if (packet.key != port_test_packet.key ||
192        packet.type != port_test_packet.type ||
193        packet.status != port_test_packet.status ||
194        memcmp(&packet.user, &port_test_packet.user, sizeof(zx_port_packet_t::user)) != 0) {
195        unittest_printf("ERROR: bad data in packet\n");
196        send_msg(channel, MSG_FAIL);
197        return;
198    }
199
200    send_msg(channel, MSG_PASS);
201}
202
203static void do_msg_channel_test(zx_handle_t channel, const Message* msg) {
204    if (msg->num_handles != 1) {
205        unittest_printf_critical("ERROR: wrong number handles\n");
206        send_msg(channel, MSG_FAIL);
207        return;
208    }
209
210    auto test_channel = msg->handles[0];
211    uint32_t write_data = 0xdeadbeef;
212    uint32_t read_data;
213    zx_channel_call_args_t args = {
214        .wr_bytes = &write_data,
215        .wr_handles = nullptr,
216        .rd_bytes = &read_data,
217        .rd_handles = nullptr,
218        .wr_num_bytes = sizeof(write_data),
219        .wr_num_handles = 0,
220        .rd_num_bytes = sizeof(read_data),
221        .rd_num_handles = 0,
222    };
223
224    uint32_t actual_num_bytes = 0;
225    uint32_t actual_num_handles = 0;
226    auto status = zx_channel_call(test_channel, 0, ZX_TIME_INFINITE, &args,
227                                  &actual_num_bytes, &actual_num_handles);
228    tu_handle_close(test_channel);
229    if (status == ZX_ERR_PEER_CLOSED) {
230        // ok
231    } else {
232        unittest_printf_critical("ERROR: channel_call didn't get PEER_CLOSED: %d/%s\n",
233                        status, zx_status_get_string(status));
234        send_msg(channel, MSG_FAIL);
235        return;
236    }
237
238    send_msg(channel, MSG_PASS);
239}
240
241static void do_msg_wait_one_test(zx_handle_t channel, const Message* msg) {
242    if (msg->num_handles != 1) {
243        unittest_printf("ERROR: wrong number handles\n");
244        send_msg(channel, MSG_FAIL);
245        return;
246    }
247
248    // The test waits for this to make sure it doesn't see us blocked waiting
249    // for a Message. This is sent for wait_one and wait_many so that we don't
250    // have to know which one is used to wait for messages.
251    send_msg(channel, MSG_PROCEED);
252
253    zx_signals_t observed = 0u;
254    auto status = zx_object_wait_one(msg->handles[0], ZX_EVENTPAIR_PEER_CLOSED,
255                                     ZX_TIME_INFINITE, &observed);
256    tu_handle_close(msg->handles[0]);
257    if (status != ZX_OK) {
258        unittest_printf("ERROR: wait_one failed: %d/%s\n", status,
259                        zx_status_get_string(status));
260        send_msg(channel, MSG_FAIL);
261        return;
262    }
263
264    if (!(observed & ZX_EVENTPAIR_PEER_CLOSED)) {
265        unittest_printf("ERROR: ZX_EVENTPAIR_PEER_CLOSED not observed\n");
266        send_msg(channel, MSG_FAIL);
267        return;
268    }
269
270    send_msg(channel, MSG_PASS);
271}
272
273static void do_msg_wait_many_test(zx_handle_t channel, const Message* msg) {
274    if (msg->num_handles != NUM_WAIT_MANY_HANDLES) {
275        unittest_printf("ERROR: wrong number handles\n");
276        send_msg(channel, MSG_FAIL);
277        return;
278    }
279
280    // The test waits for this to make sure it doesn't see us blocked waiting
281    // for a Message. This is sent for wait_one and wait_many so that we don't
282    // have to know which one is used to wait for messages.
283    send_msg(channel, MSG_PROCEED);
284
285    uint32_t num_handles = NUM_WAIT_MANY_HANDLES;
286    zx_wait_item_t items[num_handles];
287    for (uint32_t i = 0; i < num_handles; ++i) {
288        items[i].handle = msg->handles[i];
289        items[i].waitfor = ZX_EVENTPAIR_PEER_CLOSED;
290    }
291    auto status = zx_object_wait_many(&items[0], num_handles, ZX_TIME_INFINITE);
292    for (uint32_t i = 0; i < num_handles; ++i) {
293        tu_handle_close(msg->handles[i]);
294    }
295    if (status != ZX_OK) {
296        unittest_printf("ERROR: wait_many failed: %d/%s\n", status,
297                        zx_status_get_string(status));
298        send_msg(channel, MSG_FAIL);
299        return;
300    }
301
302    // At least one of the handles should have gotten PEER_CLOSED.
303    bool got_peer_closed = false;
304    for (uint32_t i = 0; i < num_handles; ++i) {
305        if (items[i].pending & ZX_EVENTPAIR_PEER_CLOSED) {
306            got_peer_closed = true;
307            break;
308        }
309    }
310    if (!got_peer_closed) {
311        unittest_printf("ERROR: ZX_EVENTPAIR_PEER_CLOSED not observed\n");
312        send_msg(channel, MSG_FAIL);
313        return;
314    }
315
316    send_msg(channel, MSG_PASS);
317}
318
319static void do_msg_interrupt_test(zx_handle_t channel, const Message* msg) {
320    if (msg->num_handles != 1) {
321        unittest_printf("ERROR: wrong number handles\n");
322        send_msg(channel, MSG_FAIL);
323        return;
324    }
325
326    auto interrupt = msg->handles[0];
327    zx_time_t timestamp;
328    auto status = zx_interrupt_wait(interrupt, &timestamp);
329    tu_handle_close(interrupt);
330    if (status != ZX_OK) {
331        unittest_printf("ERROR: interrupt_wait failed: %d/%s\n", status,
332                        zx_status_get_string(status));
333        send_msg(channel, MSG_FAIL);
334        return;
335    }
336
337    if (timestamp != interrupt_signaled_timestamp) {
338        unittest_printf("ERROR: interrupt timestamp mismatch\n");
339        send_msg(channel, MSG_FAIL);
340        return;
341    }
342
343    send_msg(channel, MSG_PASS);
344}
345
346static void msg_loop(zx_handle_t channel) {
347    bool my_done_tests = false;
348
349    while (!my_done_tests) {
350        Message msg;
351        msg.num_handles = static_cast<uint32_t>(fbl::count_of(msg.handles));
352        if (!recv_msg(channel, &msg)) {
353            unittest_printf("ERROR: while receiving msg\n");
354            return;
355        }
356
357        switch (msg.type) {
358        case MSG_DONE:
359            my_done_tests = true;
360            break;
361        case MSG_THREAD_HANDLE_REQUEST:
362            do_msg_thread_handle_request(channel, &msg);
363            break;
364        case MSG_SLEEP_TEST:
365            do_msg_sleep_test(channel, &msg);
366            break;
367        case MSG_FUTEX_TEST:
368            do_msg_futex_test(channel, &msg);
369            break;
370        case MSG_PORT_TEST:
371            do_msg_port_test(channel, &msg);
372            break;
373        case MSG_CHANNEL_TEST:
374            do_msg_channel_test(channel, &msg);
375            break;
376        case MSG_WAIT_ONE_TEST:
377            do_msg_wait_one_test(channel, &msg);
378            break;
379        case MSG_WAIT_MANY_TEST:
380            do_msg_wait_many_test(channel, &msg);
381            break;
382        case MSG_INTERRUPT_TEST:
383            do_msg_interrupt_test(channel, &msg);
384            break;
385        default:
386            unittest_printf("ERROR: unknown message received: %u\n", msg.type);
387            break;
388        }
389    }
390}
391
392static int thread_func(void* arg) {
393    unittest_printf("test thread starting\n");
394    zx_handle_t msg_channel = (zx_handle_t) (uintptr_t) arg;
395    msg_loop(msg_channel);
396    unittest_printf("test thread exiting\n");
397    tu_handle_close(msg_channel);
398    return 0;
399}
400
401static void __NO_RETURN test_child(void) {
402    unittest_printf("Test child starting.\n");
403    zx_handle_t channel = zx_take_startup_handle(PA_USER0);
404    if (channel == ZX_HANDLE_INVALID)
405        tu_fatal("zx_take_startup_handle", ZX_ERR_BAD_HANDLE - 1000);
406    msg_loop(channel);
407    unittest_printf("Test child exiting.\n");
408    exit(0);
409}
410
411static launchpad_t* setup_test_child(zx_handle_t job, const char* arg,
412                                     zx_handle_t* out_channel) {
413    unittest_printf("Starting test child %s.\n", arg);
414    zx_handle_t our_channel, their_channel;
415    tu_channel_create(&our_channel, &their_channel);
416    const char* test_child_path = program_path;
417    const char verbosity_string[] =
418        { 'v', '=', static_cast<char>(utest_verbosity_level + '0'), '\0' };
419    const char* const argv[] = {
420        test_child_path,
421        arg,
422        verbosity_string,
423    };
424    int argc = fbl::count_of(argv);
425    zx_handle_t handles[1] = { their_channel };
426    uint32_t handle_ids[1] = { PA_USER0 };
427    *out_channel = our_channel;
428    launchpad_t* lp = tu_launch_fdio_init(job, test_child_name, argc, argv,
429                                          NULL, 1, handles, handle_ids);
430    unittest_printf("Test child setup.\n");
431    return lp;
432}
433
434static void start_test_child(zx_handle_t job, const char* arg,
435                             zx_handle_t* out_child, zx_handle_t* out_channel) {
436    launchpad_t* lp = setup_test_child(job, arg, out_channel);
437    *out_child = tu_launch_fdio_fini(lp);
438    unittest_printf("Test child started.\n");
439}
440
441static bool get_child_thread(zx_handle_t channel, zx_handle_t* thread) {
442    send_msg(channel, MSG_THREAD_HANDLE_REQUEST);
443    Message msg;
444    ASSERT_TRUE(recv_msg(channel, &msg));
445    EXPECT_EQ(msg.type, MSG_THREAD_HANDLE_RESPONSE);
446    EXPECT_EQ(msg.num_handles, 1u);
447    *thread = msg.handles[0];
448    return true;
449}
450
451// Wait for |thread| to enter blocked state |reason|.
452// We wait forever and let Unittest's watchdog handle errors.
453
454static void wait_thread_blocked(zx_handle_t thread, uint32_t reason) {
455    while (true) {
456        auto state = tu_thread_get_state(thread);
457        if (state == reason)
458            break;
459        zx_nanosleep(zx_deadline_after(THREAD_BLOCKED_WAIT_DURATION));
460    }
461}
462
463// Terminate |process| by killing it and wait for it to exit.
464
465static void terminate_process(zx_handle_t process) {
466    tu_task_kill(process);
467    tu_process_wait_signaled(process);
468}
469
470static bool sleeping_test() {
471    BEGIN_TEST;
472
473    // Start a new process.
474    zx_handle_t child, channel;
475    start_test_child(zx_job_default(), test_child_name, &child, &channel);
476    zx_handle_t thread;
477    ASSERT_TRUE(get_child_thread(channel, &thread));
478
479    send_msg(channel, MSG_SLEEP_TEST);
480
481    // There is no good way to do this test without having the child
482    // sleep forever and then kill it: There's no way to interrupt the sleep,
483    // and there's no good value for the amount of time to sleep.
484    wait_thread_blocked(thread, ZX_THREAD_STATE_BLOCKED_SLEEPING);
485
486    terminate_process(child);
487
488    END_TEST;
489}
490
491static bool futex_test() {
492    BEGIN_TEST;
493
494    // Start a new process.
495    zx_handle_t child, channel;
496    start_test_child(zx_job_default(), test_child_name, &child, &channel);
497    zx_handle_t thread;
498    ASSERT_TRUE(get_child_thread(channel, &thread));
499
500    send_msg_with_handles(channel, MSG_FUTEX_TEST, nullptr, 0);
501
502    wait_thread_blocked(thread, ZX_THREAD_STATE_BLOCKED_FUTEX);
503
504    terminate_process(child);
505
506    END_TEST;
507}
508
509static bool port_test() {
510    BEGIN_TEST;
511
512    // Start a new process.
513    zx_handle_t child, channel;
514    start_test_child(zx_job_default(), test_child_name, &child, &channel);
515    zx_handle_t thread;
516    ASSERT_TRUE(get_child_thread(channel, &thread));
517
518    zx_handle_t port;
519    ASSERT_EQ(zx_port_create(0, &port), ZX_OK);
520    zx_handle_t port_dupe = tu_handle_duplicate(port);
521
522    send_msg_with_handles(channel, MSG_PORT_TEST, &port_dupe, 1);
523
524    wait_thread_blocked(thread, ZX_THREAD_STATE_BLOCKED_PORT);
525
526    // Wake the child up.
527    EXPECT_EQ(zx_port_queue(port, &port_test_packet), ZX_OK);
528
529    // The child sends a pass/fail message back as extra verification that
530    // things went correctly on that side.
531    ASSERT_TRUE(recv_specific_msg(channel, MSG_PASS));
532
533    tu_handle_close(port);
534    terminate_process(child);
535
536    END_TEST;
537}
538
539static bool channel_test() {
540    BEGIN_TEST;
541
542    // Start a new process.
543    zx_handle_t child, channel;
544    start_test_child(zx_job_default(), test_child_name, &child, &channel);
545    zx_handle_t thread;
546    ASSERT_TRUE(get_child_thread(channel, &thread));
547
548    zx_handle_t our_channel, their_channel;
549    ASSERT_EQ(zx_channel_create(0, &our_channel, &their_channel), ZX_OK);
550
551    send_msg_with_handles(channel, MSG_CHANNEL_TEST, &their_channel, 1);
552
553    wait_thread_blocked(thread, ZX_THREAD_STATE_BLOCKED_CHANNEL);
554
555    // Wake the child up.
556    tu_handle_close(our_channel);
557
558    // The child sends a pass/fail message back as extra verification that
559    // things went correctly on that side.
560    ASSERT_TRUE(recv_specific_msg(channel, MSG_PASS));
561
562    terminate_process(child);
563
564    END_TEST;
565}
566
567static bool wait_one_test() {
568    BEGIN_TEST;
569
570    // Start a new process.
571    zx_handle_t child, channel;
572    start_test_child(zx_job_default(), test_child_name, &child, &channel);
573    zx_handle_t thread;
574    ASSERT_TRUE(get_child_thread(channel, &thread));
575
576    zx_handle_t h[2];
577    ASSERT_EQ(zx_eventpair_create(0, &h[0], &h[1]), ZX_OK);
578
579    send_msg_with_handles(channel, MSG_WAIT_ONE_TEST, &h[1], 1);
580
581    // Don't continue until we see MSG_PROCEED, that tells us the child has
582    // received the message and isn't in a wait_one/wait_many syscall.
583    ASSERT_TRUE(recv_specific_msg(channel, MSG_PROCEED));
584
585    wait_thread_blocked(thread, ZX_THREAD_STATE_BLOCKED_WAIT_ONE);
586
587    // Wake the child up.
588    tu_handle_close(h[0]);
589
590    // The child sends a pass/fail message back as extra verification that
591    // things went correctly on that side.
592    ASSERT_TRUE(recv_specific_msg(channel, MSG_PASS));
593
594    terminate_process(child);
595
596    END_TEST;
597}
598
599static bool wait_many_test() {
600    BEGIN_TEST;
601
602    // Start a new process.
603    zx_handle_t child, channel;
604    start_test_child(zx_job_default(), test_child_name, &child, &channel);
605    zx_handle_t thread;
606    ASSERT_TRUE(get_child_thread(channel, &thread));
607
608    uint32_t num_handles = NUM_WAIT_MANY_HANDLES;
609    zx_handle_t h[2][num_handles];
610    for (uint32_t i = 0; i < num_handles; ++i) {
611        ASSERT_EQ(zx_eventpair_create(0, &h[0][i], &h[1][i]), ZX_OK);
612    }
613
614    send_msg_with_handles(channel, MSG_WAIT_MANY_TEST, &h[1][0], num_handles);
615
616    // Don't continue until we see MSG_PROCEED, that tells us the child has
617    // received the message and isn't in a wait_one/wait_many syscall.
618    ASSERT_TRUE(recv_specific_msg(channel, MSG_PROCEED));
619
620    wait_thread_blocked(thread, ZX_THREAD_STATE_BLOCKED_WAIT_MANY);
621
622    // Wake the child up.
623    for (uint32_t i = 0; i < num_handles; ++i) {
624        tu_handle_close(h[0][i]);
625    }
626
627    // The child sends a pass/fail message back as extra verification that
628    // things went correctly on that side.
629    ASSERT_TRUE(recv_specific_msg(channel, MSG_PASS));
630
631    terminate_process(child);
632
633    END_TEST;
634}
635
636static bool interrupt_test() {
637    BEGIN_TEST;
638
639    // Start a new process.
640    zx_handle_t child, channel;
641    start_test_child(zx_job_default(), test_child_name, &child, &channel);
642    zx_handle_t thread;
643    ASSERT_TRUE(get_child_thread(channel, &thread));
644
645    zx_handle_t resource;
646    ASSERT_EQ(get_root_resource(&resource), ZX_OK);
647
648    zx_handle_t interrupt;
649    ASSERT_EQ(zx_interrupt_create(resource, 0, ZX_INTERRUPT_VIRTUAL, &interrupt),
650              ZX_OK);
651    zx_handle_t interrupt_dupe = tu_handle_duplicate(interrupt);
652
653    send_msg_with_handles(channel, MSG_INTERRUPT_TEST, &interrupt_dupe, 1);
654
655    wait_thread_blocked(thread, ZX_THREAD_STATE_BLOCKED_INTERRUPT);
656
657    // Wake the child up.
658    EXPECT_EQ(zx_interrupt_trigger(interrupt, 0, interrupt_signaled_timestamp), ZX_OK);
659
660    // The child sends a pass/fail message back as extra verification that
661    // things went correctly on that side.
662    ASSERT_TRUE(recv_specific_msg(channel, MSG_PASS));
663
664    tu_handle_close(interrupt);
665    terminate_process(child);
666
667    END_TEST;
668}
669
670BEGIN_TEST_CASE(thread_state_tests)
671// ZX_THREAD_STATE_BLOCKED_EXCEPTION is tested in utest/exception.
672// There's a lot of support logic and there's no reason to duplicate it here.
673RUN_TEST(sleeping_test);
674RUN_TEST(futex_test);
675RUN_TEST(port_test);
676RUN_TEST(channel_test);
677RUN_TEST(wait_one_test);
678RUN_TEST(wait_many_test);
679RUN_TEST(interrupt_test);
680END_TEST_CASE(thread_state_tests)
681
682static void scan_argv(int argc, char** argv) {
683    for (int i = 1; i < argc; ++i) {
684        if (strncmp(argv[i], "v=", 2) == 0) {
685            int verbosity = atoi(argv[i] + 2);
686            unittest_set_verbosity_level(verbosity);
687        }
688    }
689}
690
691int main(int argc, char **argv) {
692    program_path = argv[0];
693    scan_argv(argc, argv);
694
695    if (argc >= 2) {
696        if (strcmp(argv[1], test_child_name) == 0) {
697            test_child();
698            return 0;
699        }
700    }
701
702    bool success = unittest_run_all_tests(argc, argv);
703
704    return success ? 0 : -1;
705}
706