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 <unittest/unittest.h>
6
7 #include <zircon/syscalls.h>
8 #include <zircon/syscalls/object.h>
9
10 #define kNumEventpairs 4u
11 #define kGap 2u
12
handle_close_many_test(void)13 static bool handle_close_many_test(void) {
14 BEGIN_TEST;
15
16 // Layout: 0 1 2 3 : 0 1 2 3
17 zx_handle_t eventpairs[kNumEventpairs * 2];
18
19 for (size_t idx = 0u; idx < kNumEventpairs; ++idx) {
20 ASSERT_EQ(zx_eventpair_create(0u, &eventpairs[idx], &eventpairs[idx + kNumEventpairs]), ZX_OK, "");
21 }
22
23 ASSERT_EQ(zx_handle_close_many(&eventpairs[0u], kNumEventpairs), ZX_OK, "");
24
25 // Assert that every handle in the preceding close call was in
26 // fact closed, by waiting on the PEER_CLOSED signal.
27 for (size_t idx = kNumEventpairs; idx < 8u; ++idx) {
28 zx_signals_t signals;
29 ASSERT_EQ(zx_object_wait_one(eventpairs[idx], ZX_EVENTPAIR_PEER_CLOSED,
30 0u, &signals), ZX_OK, "");
31 ASSERT_EQ(signals & ZX_EVENTPAIR_PEER_CLOSED, ZX_EVENTPAIR_PEER_CLOSED, "");
32 }
33
34 ASSERT_EQ(zx_handle_close_many(&eventpairs[kNumEventpairs], kNumEventpairs), ZX_OK, "");
35
36 END_TEST;
37 }
38
handle_close_many_invalid_test(void)39 static bool handle_close_many_invalid_test(void) {
40 BEGIN_TEST;
41
42 // Layout: 0 1 2 3 : invalid invalid : 0 1 2 3
43 zx_handle_t eventpairs[kNumEventpairs * 2 + kGap];
44
45 for (size_t idx = 0u; idx < kNumEventpairs; ++idx) {
46 ASSERT_EQ(zx_eventpair_create(0u, &eventpairs[idx],
47 &eventpairs[idx + kNumEventpairs + kGap]), ZX_OK, "");
48 }
49 eventpairs[kNumEventpairs] = ZX_HANDLE_INVALID;
50 eventpairs[kNumEventpairs + 1] = ZX_HANDLE_INVALID;
51
52 ASSERT_EQ(zx_handle_close_many(&eventpairs[0u], kNumEventpairs + kGap), ZX_OK, "");
53
54 // Assert that every handle in the preceding close call was in
55 // fact closed, by waiting on the PEER_CLOSED signal.
56 for (size_t idx = kNumEventpairs + kGap; idx < 10u; ++idx) {
57 zx_signals_t signals;
58 ASSERT_EQ(zx_object_wait_one(eventpairs[idx], ZX_EVENTPAIR_PEER_CLOSED,
59 0u, &signals), ZX_OK, "");
60 ASSERT_EQ(signals & ZX_EVENTPAIR_PEER_CLOSED, ZX_EVENTPAIR_PEER_CLOSED, "");
61 }
62
63 ASSERT_EQ(zx_handle_close_many(&eventpairs[kNumEventpairs + kGap], kNumEventpairs), ZX_OK, "");
64
65 END_TEST;
66 }
67
handle_close_many_duplicate_test(void)68 static bool handle_close_many_duplicate_test(void) {
69 BEGIN_TEST;
70
71 // Layout: 0 1 0 1 2 3 : 0 1 2 3
72 zx_handle_t eventpairs[kNumEventpairs * 2 + kGap];
73
74 for (size_t idx = kGap; idx < kGap + kNumEventpairs; ++idx) {
75 ASSERT_EQ(zx_eventpair_create(0u, &eventpairs[idx],
76 &eventpairs[idx + kNumEventpairs]), ZX_OK, "");
77 }
78 // Duplicate the values at the start.
79 eventpairs[0u] = eventpairs[kGap];
80 eventpairs[1u] = eventpairs[kGap + 1u];
81
82 // Note that this returns an error value: the duplicated handles
83 // can't be closed twice. Despite this, all handles were closed.
84 ASSERT_EQ(zx_handle_close_many(&eventpairs[0u], kNumEventpairs + kGap), ZX_ERR_BAD_HANDLE, "");
85
86 // Assert that every handle in the preceding close call was in
87 // fact closed, by waiting on the PEER_CLOSED signal.
88 for (size_t idx = kNumEventpairs + kGap; idx < 10u; ++idx) {
89 zx_signals_t signals;
90 ASSERT_EQ(zx_object_wait_one(eventpairs[idx], ZX_EVENTPAIR_PEER_CLOSED,
91 0u, &signals), ZX_OK, "");
92 ASSERT_EQ(signals & ZX_EVENTPAIR_PEER_CLOSED, ZX_EVENTPAIR_PEER_CLOSED, "");
93 }
94
95 ASSERT_EQ(zx_handle_close_many(&eventpairs[kNumEventpairs + kGap], kNumEventpairs), ZX_OK, "");
96
97 END_TEST;
98 }
99
100 BEGIN_TEST_CASE(handle_close_tests)
RUN_TEST(handle_close_many_test)101 RUN_TEST(handle_close_many_test)
102 RUN_TEST(handle_close_many_invalid_test)
103 RUN_TEST(handle_close_many_duplicate_test)
104 END_TEST_CASE(handle_close_tests)
105
106 #ifndef BUILD_COMBINED_TESTS
107 int main(int argc, char** argv) {
108 return unittest_run_all_tests(argc, argv) ? 0 : -1;
109 }
110 #endif
111