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 <fuchsia/crash/c/fidl.h>
6 #include <string.h>
7 #include <threads.h>
8 #include <zircon/fidl.h>
9 #include <zircon/syscalls.h>
10 
11 #include <unittest/unittest.h>
12 
crash_server(void * ctx)13 static int crash_server(void* ctx) {
14     zx_handle_t server = *(zx_handle_t*)ctx;
15     zx_status_t status = ZX_OK;
16 
17     while (status == ZX_OK) {
18         zx_signals_t observed;
19         status = zx_object_wait_one(
20             server, ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED,
21             ZX_TIME_INFINITE, &observed);
22         if ((observed & ZX_CHANNEL_READABLE) != 0) {
23             ASSERT_EQ(ZX_OK, status, "");
24             char msg[1024];
25             zx_handle_t handles[ZX_CHANNEL_MAX_MSG_HANDLES];
26             uint32_t actual_bytes = 0u;
27             uint32_t actual_handles = 0u;
28             status = zx_channel_read(server, 0, msg, handles,
29                                      sizeof(msg), ZX_CHANNEL_MAX_MSG_HANDLES,
30                                      &actual_bytes, &actual_handles);
31             ASSERT_EQ(ZX_OK, status, "");
32             ASSERT_GE(actual_bytes, sizeof(fidl_message_header_t), "");
33             ASSERT_EQ(actual_handles, 3u, "");
34             zx_handle_close_many(handles, actual_handles);
35             fidl_message_header_t* req = (fidl_message_header_t*)msg;
36             fuchsia_crash_AnalyzerHandleNativeExceptionResponse response;
37             memset(&response, 0, sizeof(response));
38             response.hdr.txid = req->txid;
39             response.hdr.ordinal = req->ordinal;
40             response.status = ZX_OK;
41             status = zx_channel_write(server, 0, &response, sizeof(response), NULL, 0);
42             ASSERT_EQ(ZX_OK, status, "");
43         } else {
44             break;
45         }
46     }
47 
48     zx_handle_close(server);
49     return 0;
50 }
51 
crash_analyzer_test(void)52 static bool crash_analyzer_test(void) {
53     BEGIN_TEST;
54 
55     zx_handle_t client, server;
56     zx_status_t status = zx_channel_create(0, &client, &server);
57     ASSERT_EQ(ZX_OK, status, "");
58 
59     thrd_t thread;
60     int rv = thrd_create(&thread, crash_server, &server);
61     ASSERT_EQ(thrd_success, rv, "");
62 
63     zx_handle_t h0, h1;
64     status = zx_eventpair_create(0, &h0, &h1);
65     ASSERT_EQ(ZX_OK, status, "");
66 
67     zx_handle_t port;
68     ASSERT_EQ(ZX_OK, zx_port_create(0, &port), "");
69 
70     zx_status_t out_status;
71     status = fuchsia_crash_AnalyzerHandleNativeException(client, h0, h1, port, &out_status);
72     ASSERT_EQ(ZX_OK, status, "");
73     ASSERT_EQ(ZX_OK, out_status, "");
74 
75     status = zx_handle_close(client);
76     ASSERT_EQ(ZX_OK, status, "");
77 
78     int result = 0;
79     rv = thrd_join(thread, &result);
80     ASSERT_EQ(thrd_success, rv, "");
81 
82     END_TEST;
83 }
84 
85 BEGIN_TEST_CASE(client_tests)
86 RUN_NAMED_TEST("fuchsia.crash.Analyzer test", crash_analyzer_test)
87 END_TEST_CASE(client_tests);
88