1// Copyright 2016 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 <string.h>
6
7#include <zircon/syscalls.h>
8#include <zircon/syscalls/object.h>
9#include <unittest/unittest.h>
10
11static void check_signals_state(zx_handle_t h, zx_signals_t satisfied) {
12    zx_signals_t pending = 0;
13    EXPECT_EQ(zx_object_wait_one(h, 0u, 0u, &pending), ZX_ERR_TIMED_OUT, "wrong wait result");
14    EXPECT_EQ(pending, satisfied, "wrong satisfied state");
15}
16
17static bool create_test(void) {
18    BEGIN_TEST;
19
20    {
21        zx_handle_t h[2] = {ZX_HANDLE_INVALID, ZX_HANDLE_INVALID};
22        ASSERT_EQ(zx_eventpair_create(0, &h[0], &h[1]), ZX_OK, "eventpair_create failed");
23        ASSERT_NE(h[0], ZX_HANDLE_INVALID, "invalid handle from eventpair_create");
24        ASSERT_NE(h[1], ZX_HANDLE_INVALID, "invalid handle from eventpair_create");
25
26        zx_info_handle_basic_t info[2] = {};
27        zx_status_t status = zx_object_get_info(h[0], ZX_INFO_HANDLE_BASIC, &info[0], sizeof(info[0]), NULL, NULL);
28        ASSERT_EQ(status, ZX_OK, "");
29        EXPECT_EQ(info[0].rights,
30                  ZX_RIGHTS_BASIC | ZX_RIGHT_READ |
31                  ZX_RIGHT_WRITE | ZX_RIGHT_SIGNAL | ZX_RIGHT_SIGNAL_PEER,
32                  "wrong rights");
33        EXPECT_EQ(info[0].type, (uint32_t)ZX_OBJ_TYPE_EVENTPAIR, "wrong type");
34        status = zx_object_get_info(h[1], ZX_INFO_HANDLE_BASIC, &info[1], sizeof(info[1]), NULL, NULL);
35        ASSERT_EQ(status, ZX_OK, "");
36        EXPECT_EQ(info[1].rights,
37                  ZX_RIGHTS_BASIC | ZX_RIGHT_READ |
38                  ZX_RIGHT_WRITE | ZX_RIGHT_SIGNAL | ZX_RIGHT_SIGNAL_PEER,
39                  "wrong rights");
40        EXPECT_EQ(info[1].type, (uint32_t)ZX_OBJ_TYPE_EVENTPAIR, "wrong type");
41
42
43        // Check that koids line up.
44        ASSERT_NE(info[0].koid, 0u, "zero koid!");
45        ASSERT_NE(info[0].related_koid, 0u, "zero peer koid!");
46        ASSERT_NE(info[1].koid, 0u, "zero koid!");
47        ASSERT_NE(info[1].related_koid, 0u, "zero peer koid!");
48        ASSERT_EQ(info[0].koid, info[1].related_koid, "mismatched koids!");
49        ASSERT_EQ(info[1].koid, info[0].related_koid, "mismatched koids!");
50
51        EXPECT_EQ(zx_handle_close(h[0]), ZX_OK, "failed to close event pair handle");
52        EXPECT_EQ(zx_handle_close(h[1]), ZX_OK, "failed to close event pair handle");
53    }
54
55    // Currently no flags are supported.
56    {
57        zx_handle_t h[2] = {ZX_HANDLE_INVALID, ZX_HANDLE_INVALID};
58        EXPECT_EQ(zx_eventpair_create(1u, &h[0], &h[1]), ZX_ERR_NOT_SUPPORTED, "eventpair_create failed to fail");
59        EXPECT_EQ(h[0], ZX_HANDLE_INVALID, "valid handle from failed eventpair_create?");
60        EXPECT_EQ(h[1], ZX_HANDLE_INVALID, "valid handle from failed eventpair_create?");
61    }
62
63    END_TEST;
64}
65
66static bool signal_test(void) {
67    BEGIN_TEST;
68    zx_handle_t h[2] = {ZX_HANDLE_INVALID, ZX_HANDLE_INVALID};
69    ASSERT_EQ(zx_eventpair_create(0, &h[0], &h[1]), ZX_OK, "eventpair_create failed");
70    ASSERT_NE(h[0], ZX_HANDLE_INVALID, "invalid handle from eventpair_create");
71    ASSERT_NE(h[1], ZX_HANDLE_INVALID, "invalid handle from eventpair_create");
72
73    check_signals_state(h[0], 0u);
74    check_signals_state(h[1], 0u);
75
76    EXPECT_EQ(zx_object_signal(h[0], 0u, ZX_USER_SIGNAL_0), ZX_OK, "object_signal failed");
77    check_signals_state(h[1], 0u);
78    check_signals_state(h[0], ZX_USER_SIGNAL_0);
79
80    EXPECT_EQ(zx_object_signal(h[0], ZX_USER_SIGNAL_0, 0u), ZX_OK, "object_signal failed");
81    check_signals_state(h[1], 0u);
82    check_signals_state(h[0], 0u);
83
84    EXPECT_EQ(zx_handle_close(h[0]), ZX_OK, "failed to close event pair handle");
85    check_signals_state(h[1], ZX_EVENTPAIR_PEER_CLOSED);
86    EXPECT_EQ(zx_handle_close(h[1]), ZX_OK, "failed to close event pair handle");
87    END_TEST;
88}
89
90static bool signal_peer_test(void) {
91    BEGIN_TEST;
92
93    zx_handle_t h[2] = {ZX_HANDLE_INVALID, ZX_HANDLE_INVALID};
94    ASSERT_EQ(zx_eventpair_create(0, &h[0], &h[1]), ZX_OK, "eventpair_create failed");
95    ASSERT_NE(h[0], ZX_HANDLE_INVALID, "invalid handle from eventpair_create");
96    ASSERT_NE(h[1], ZX_HANDLE_INVALID, "invalid handle from eventpair_create");
97
98    EXPECT_EQ(zx_object_signal_peer(h[0], 0u, ZX_USER_SIGNAL_0), ZX_OK, "object_signal failed");
99    check_signals_state(h[0], 0u);
100    check_signals_state(h[1], ZX_USER_SIGNAL_0);
101
102    EXPECT_EQ(zx_object_signal_peer(h[1], 0u, ZX_USER_SIGNAL_1 | ZX_USER_SIGNAL_2), ZX_OK,
103              "object_signal failed");
104    check_signals_state(h[0], ZX_USER_SIGNAL_1 | ZX_USER_SIGNAL_2);
105    check_signals_state(h[1], ZX_USER_SIGNAL_0);
106
107    EXPECT_EQ(zx_object_signal_peer(h[0], ZX_USER_SIGNAL_0, ZX_USER_SIGNAL_3 | ZX_USER_SIGNAL_4),
108              ZX_OK, "object_signal failed");
109    check_signals_state(h[0], ZX_USER_SIGNAL_1 | ZX_USER_SIGNAL_2);
110    check_signals_state(h[1], ZX_USER_SIGNAL_3 | ZX_USER_SIGNAL_4);
111
112    EXPECT_EQ(zx_handle_close(h[0]), ZX_OK, "failed to close event pair handle");
113
114    // Signaled flags should remain satisfied but now should now also get peer closed (and
115    // unsignaled flags should be unsatisfiable).
116    check_signals_state(h[1],
117        ZX_EVENTPAIR_PEER_CLOSED | ZX_USER_SIGNAL_3 | ZX_USER_SIGNAL_4);
118
119    EXPECT_EQ(zx_handle_close(h[1]), ZX_OK, "failed to close event pair handle");
120
121    END_TEST;
122}
123
124static bool signal_peer_closed_test(void) {
125    BEGIN_TEST;
126
127    zx_handle_t eventpair[2];
128    ASSERT_EQ(zx_eventpair_create(0, &eventpair[0], &eventpair[1]), ZX_OK, "");
129    ASSERT_EQ(zx_handle_close(eventpair[1]), ZX_OK, "");
130    ASSERT_EQ(zx_object_signal_peer(eventpair[0], 0u, ZX_USER_SIGNAL_0), ZX_ERR_PEER_CLOSED, "");
131    ASSERT_EQ(zx_handle_close(eventpair[0]), ZX_OK, "");
132
133    END_TEST;
134}
135
136BEGIN_TEST_CASE(eventpair_tests)
137RUN_TEST(create_test)
138RUN_TEST(signal_test)
139RUN_TEST(signal_peer_test)
140RUN_TEST(signal_peer_closed_test)
141END_TEST_CASE(eventpair_tests)
142
143#ifndef BUILD_COMBINED_TESTS
144int main(int argc, char** argv) {
145    return unittest_run_all_tests(argc, argv) ? 0 : -1;
146}
147#endif
148