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 <fcntl.h>
7 #include <stdio.h>
8 #include <unistd.h>
9
10 #include <lib/fzl/time.h>
11 #include <lib/zx/bti.h>
12 #include <lib/zx/channel.h>
13 #include <lib/zx/debuglog.h>
14 #include <lib/zx/event.h>
15 #include <lib/zx/eventpair.h>
16 #include <lib/zx/fifo.h>
17 #include <lib/zx/guest.h>
18 #include <lib/zx/handle.h>
19 #include <lib/zx/interrupt.h>
20 #include <lib/zx/job.h>
21 #include <lib/zx/log.h>
22 #include <lib/zx/port.h>
23 #include <lib/zx/process.h>
24 #include <lib/zx/socket.h>
25 #include <lib/zx/thread.h>
26 #include <lib/zx/time.h>
27 #include <lib/zx/timer.h>
28 #include <lib/zx/vmar.h>
29 #include <unittest/unittest.h>
30 #include <zircon/syscalls.h>
31 #include <zircon/syscalls/object.h>
32 #include <zircon/syscalls/port.h>
33
34 template <typename Handle>
duplicating(const Handle & handle)35 bool duplicating(const Handle& handle) {
36 BEGIN_TEST;
37
38 zx_status_t expected_status = ZX_OK;
39 if (!zx::object_traits<Handle>::supports_duplication) {
40 expected_status = ZX_ERR_ACCESS_DENIED;
41 }
42
43 zx_handle_t copy = ZX_HANDLE_INVALID;
44 zx_status_t status = zx_handle_duplicate(handle.get(), ZX_RIGHT_SAME_RIGHTS, ©);
45 if (copy != ZX_HANDLE_INVALID) {
46 zx_handle_close(copy);
47 }
48
49 ASSERT_EQ(status, expected_status);
50
51 END_TEST;
52 }
53
54 template <typename Handle>
user_signaling(const Handle & handle)55 bool user_signaling(const Handle& handle) {
56 BEGIN_TEST;
57
58 zx_status_t expected_status = ZX_OK;
59 if (!zx::object_traits<Handle>::supports_user_signal) {
60 expected_status = ZX_ERR_ACCESS_DENIED;
61 }
62
63 zx_handle_t copy = ZX_HANDLE_INVALID;
64 zx_status_t status = zx_object_signal(handle.get(), 0u, ZX_USER_SIGNAL_0);
65 if (copy != ZX_HANDLE_INVALID) {
66 zx_handle_close(copy);
67 }
68
69 ASSERT_EQ(status, expected_status);
70
71 END_TEST;
72 }
73
74 template <typename Handle>
waiting(const Handle & handle)75 bool waiting(const Handle& handle) {
76 BEGIN_TEST;
77
78 zx_status_t expected_status = ZX_OK;
79 if (!zx::object_traits<Handle>::supports_wait) {
80 expected_status = ZX_ERR_ACCESS_DENIED;
81 }
82
83 zx_handle_t copy = ZX_HANDLE_INVALID;
84 zx_status_t status = zx_object_wait_one(handle.get(), ZX_USER_SIGNAL_0, 0u, nullptr);
85 if (copy != ZX_HANDLE_INVALID) {
86 zx_handle_close(copy);
87 }
88
89 ASSERT_EQ(status, expected_status);
90
91 END_TEST;
92 }
93
94 template <typename Handle>
peering(const Handle & handle)95 bool peering(const Handle& handle) {
96 BEGIN_TEST;
97
98 zx_status_t expected_status = ZX_OK;
99 if (!zx::object_traits<Handle>::has_peer_handle) {
100 expected_status = ZX_ERR_ACCESS_DENIED;
101 }
102
103 zx_status_t status = zx_object_signal_peer(handle.get(), 0u, ZX_USER_SIGNAL_0);
104
105 ASSERT_EQ(status, expected_status);
106
107 END_TEST;
108 }
109
traits_test()110 bool traits_test() {
111 BEGIN_TEST;
112
113 {
114 zx::event event;
115 ASSERT_EQ(zx::event::create(0u, &event), ZX_OK);
116 duplicating(event);
117 user_signaling(event);
118 waiting(event);
119 peering(event);
120 }
121
122 {
123 zx::thread thread;
124 ASSERT_EQ(zx::thread::create(*zx::process::self(), "", 0u, 0u, &thread), ZX_OK);
125 duplicating(thread);
126 user_signaling(thread);
127 waiting(thread);
128 peering(thread);
129 }
130
131 {
132 zx::process process;
133 zx::vmar vmar;
134 ASSERT_EQ(zx::process::create(*zx::job::default_job(), "", 0u, 0u, &process, &vmar), ZX_OK);
135 duplicating(process);
136 user_signaling(process);
137 waiting(process);
138 peering(process);
139 }
140
141 {
142 zx::job job;
143 ASSERT_EQ(zx::job::create(*zx::job::default_job(), 0u, &job), ZX_OK);
144 duplicating(job);
145 user_signaling(job);
146 waiting(job);
147 peering(job);
148 }
149
150 {
151 zx::vmo vmo;
152 ASSERT_EQ(zx::vmo::create(4096u, 0u, &vmo), ZX_OK);
153 duplicating(vmo);
154 user_signaling(vmo);
155 waiting(vmo);
156 peering(vmo);
157 }
158
159 {
160 // Creating a zx::bti is too hard in a generic testing
161 // environment. Instead, we just assert it's got the traits we
162 // want.
163 ASSERT_EQ(zx::object_traits<zx::bti>::supports_duplication, true);
164 ASSERT_EQ(zx::object_traits<zx::bti>::supports_user_signal, true);
165 ASSERT_EQ(zx::object_traits<zx::bti>::supports_wait, true);
166 ASSERT_EQ(zx::object_traits<zx::bti>::has_peer_handle, false);
167 }
168
169 {
170 // Creating a zx::resource is too hard in a generic testing
171 // environment. Instead, we just assert it's got the traits we
172 // want.
173 ASSERT_EQ(zx::object_traits<zx::resource>::supports_duplication, true);
174 ASSERT_EQ(zx::object_traits<zx::resource>::supports_user_signal, true);
175 ASSERT_EQ(zx::object_traits<zx::resource>::supports_wait, true);
176 ASSERT_EQ(zx::object_traits<zx::resource>::has_peer_handle, false);
177 }
178
179 {
180 zx::timer timer;
181 ASSERT_EQ(zx::timer::create(0u, ZX_CLOCK_MONOTONIC, &timer), ZX_OK);
182 duplicating(timer);
183 user_signaling(timer);
184 waiting(timer);
185 peering(timer);
186 }
187
188 {
189 zx::channel channel, channel2;
190 ASSERT_EQ(zx::channel::create(0u, &channel, &channel2), ZX_OK);
191 duplicating(channel);
192 user_signaling(channel);
193 waiting(channel);
194 peering(channel);
195 }
196
197 {
198 zx::eventpair eventpair, eventpair2;
199 ASSERT_EQ(zx::eventpair::create(0u, &eventpair, &eventpair2), ZX_OK);
200 duplicating(eventpair);
201 user_signaling(eventpair);
202 waiting(eventpair);
203 peering(eventpair);
204 }
205
206 {
207 zx::fifo fifo, fifo2;
208 ASSERT_EQ(zx::fifo::create(16u, 16u, 0u, &fifo, &fifo2), ZX_OK);
209 duplicating(fifo);
210 user_signaling(fifo);
211 waiting(fifo);
212 peering(fifo);
213 }
214
215 {
216 zx::log log;
217 ASSERT_EQ(zx::log::create(0u, &log), ZX_OK);
218 duplicating(log);
219 user_signaling(log);
220 waiting(log);
221 peering(log);
222 }
223
224 {
225 zx::debuglog debuglog;
226 ASSERT_EQ(zx::debuglog::create(zx::resource(), 0u, &debuglog), ZX_OK);
227 duplicating(debuglog);
228 user_signaling(debuglog);
229 waiting(debuglog);
230 peering(debuglog);
231 }
232
233 {
234 // Creating a zx::pmt is too hard in a generic testing
235 // environment. Instead, we just assert it's got the traits we
236 // want.
237 ASSERT_EQ(zx::object_traits<zx::pmt>::supports_duplication, false);
238 ASSERT_EQ(zx::object_traits<zx::pmt>::supports_user_signal, false);
239 ASSERT_EQ(zx::object_traits<zx::pmt>::supports_wait, false);
240 ASSERT_EQ(zx::object_traits<zx::pmt>::has_peer_handle, false);
241 }
242
243 {
244 zx::socket socket, socket2;
245 ASSERT_EQ(zx::socket::create(0u, &socket, &socket2), ZX_OK);
246 duplicating(socket);
247 user_signaling(socket);
248 waiting(socket);
249 peering(socket);
250 }
251
252 {
253 zx::port port;
254 ASSERT_EQ(zx::port::create(0u, &port), ZX_OK);
255 duplicating(port);
256 user_signaling(port);
257 waiting(port);
258 peering(port);
259 }
260
261 {
262 zx::vmar vmar;
263 uintptr_t addr;
264 ASSERT_EQ(zx::vmar::root_self()->allocate(0u, 4096u, 0u, &vmar, &addr), ZX_OK);
265 duplicating(vmar);
266 user_signaling(vmar);
267 waiting(vmar);
268 peering(vmar);
269 }
270
271 {
272 // Creating a zx::interrupt is too hard in a generic testing
273 // environment. Instead, we just assert it's got the traits we
274 // want.
275 ASSERT_EQ(zx::object_traits<zx::interrupt>::supports_duplication, true);
276 ASSERT_EQ(zx::object_traits<zx::interrupt>::supports_user_signal, false);
277 ASSERT_EQ(zx::object_traits<zx::interrupt>::supports_wait, true);
278 ASSERT_EQ(zx::object_traits<zx::interrupt>::has_peer_handle, false);
279 }
280
281 {
282 // Creating a zx::guest is too hard in a generic testing
283 // environment. Instead, we just assert it's got the traits we
284 // want.
285 ASSERT_EQ(zx::object_traits<zx::guest>::supports_duplication, true);
286 ASSERT_EQ(zx::object_traits<zx::guest>::supports_user_signal, false);
287 ASSERT_EQ(zx::object_traits<zx::guest>::supports_wait, false);
288 ASSERT_EQ(zx::object_traits<zx::guest>::has_peer_handle, false);
289 }
290
291 {
292 // Creating a zx::iommu is too hard in a generic testing
293 // environment. Instead, we just assert it's got the traits we
294 // want.
295 ASSERT_EQ(zx::object_traits<zx::resource>::supports_duplication, true);
296 ASSERT_EQ(zx::object_traits<zx::resource>::supports_user_signal, true);
297 ASSERT_EQ(zx::object_traits<zx::resource>::supports_wait, true);
298 ASSERT_EQ(zx::object_traits<zx::resource>::has_peer_handle, false);
299 }
300
301 END_TEST;
302 }
303
304 BEGIN_TEST_CASE(libzx_traits_tests)
305
306 RUN_TEST(traits_test)
307
308 END_TEST_CASE(libzx_traits_tests)
309