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