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, ×tamp); 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