1 // Copyright 2017 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 <stdbool.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <threads.h>
10 #include <unistd.h>
11
12 #include <zircon/syscalls.h>
13 #include <unittest/unittest.h>
14
get_signals(zx_handle_t h)15 static zx_signals_t get_signals(zx_handle_t h) {
16 zx_signals_t pending;
17 zx_status_t status = zx_object_wait_one(h, 0xFFFFFFFF, 0u, &pending);
18 if ((status != ZX_OK) && (status != ZX_ERR_TIMED_OUT)) {
19 return 0xFFFFFFFF;
20 }
21 return pending;
22 }
23
24 #define EXPECT_SIGNALS(h, s) EXPECT_EQ(get_signals(h), s, "")
25
basic_test(void)26 static bool basic_test(void) {
27 BEGIN_TEST;
28 zx_handle_t a, b;
29 uint64_t n[8] = { 1, 2, 3, 4, 5, 6, 7, 8};
30 enum { ELEM_SZ = sizeof(n[0]) };
31
32 // ensure parameter validation works
33 EXPECT_EQ(zx_fifo_create(0, 0, 0, &a, &b), ZX_ERR_OUT_OF_RANGE, ""); // too small
34 EXPECT_EQ(zx_fifo_create(35, 32, 0, &a, &b), ZX_ERR_OUT_OF_RANGE, ""); // not power of two
35 EXPECT_EQ(zx_fifo_create(128, 33, 0, &a, &b), ZX_ERR_OUT_OF_RANGE, ""); // too large
36 EXPECT_EQ(zx_fifo_create(0, 0, 1, &a, &b), ZX_ERR_OUT_OF_RANGE, ""); // invalid options
37
38 // simple 8 x 8 fifo
39 EXPECT_EQ(zx_fifo_create(8, ELEM_SZ, 0, &a, &b), ZX_OK, "");
40 EXPECT_SIGNALS(a, ZX_FIFO_WRITABLE);
41 EXPECT_SIGNALS(b, ZX_FIFO_WRITABLE);
42
43 // Check that koids line up.
44 zx_info_handle_basic_t info[2] = {};
45 zx_status_t status = zx_object_get_info(a, ZX_INFO_HANDLE_BASIC, &info[0], sizeof(info[0]), NULL, NULL);
46 ASSERT_EQ(status, ZX_OK, "");
47 status = zx_object_get_info(b, ZX_INFO_HANDLE_BASIC, &info[1], sizeof(info[1]), NULL, NULL);
48 ASSERT_EQ(status, ZX_OK, "");
49 ASSERT_NE(info[0].koid, 0u, "zero koid!");
50 ASSERT_NE(info[0].related_koid, 0u, "zero peer koid!");
51 ASSERT_NE(info[1].koid, 0u, "zero koid!");
52 ASSERT_NE(info[1].related_koid, 0u, "zero peer koid!");
53 ASSERT_EQ(info[0].koid, info[1].related_koid, "mismatched koids!");
54 ASSERT_EQ(info[1].koid, info[0].related_koid, "mismatched koids!");
55
56 // should not be able to read any entries from an empty fifo
57 size_t actual;
58 EXPECT_EQ(zx_fifo_read(a, ELEM_SZ, n, 8, &actual), ZX_ERR_SHOULD_WAIT, "");
59
60 // not allowed to read or write zero elements
61 EXPECT_EQ(zx_fifo_read(a, ELEM_SZ, n, 0, &actual), ZX_ERR_OUT_OF_RANGE, "");
62 EXPECT_EQ(zx_fifo_write(a, ELEM_SZ, n, 0, &actual), ZX_ERR_OUT_OF_RANGE, "");
63
64 // element size must match
65 EXPECT_EQ(zx_fifo_read(a, ELEM_SZ + 1, n, 8, &actual), ZX_ERR_OUT_OF_RANGE, "");
66 EXPECT_EQ(zx_fifo_write(a, ELEM_SZ + 1, n, 8, &actual), ZX_ERR_OUT_OF_RANGE, "");
67
68 // should be able to write all entries into empty fifo
69 ASSERT_EQ(zx_fifo_write(a, ELEM_SZ, n, 8, &actual), ZX_OK, "");
70 ASSERT_EQ(actual, 8u, "");
71 EXPECT_SIGNALS(b, ZX_FIFO_READABLE | ZX_FIFO_WRITABLE);
72
73 // should be able to write no entries into a full fifo
74 ASSERT_EQ(zx_fifo_write(a, ELEM_SZ, n, 8, &actual), ZX_ERR_SHOULD_WAIT, "");
75 EXPECT_SIGNALS(a, 0u);
76
77 // read half the entries, make sure they're what we expect
78 memset(n, 0, sizeof(n));
79 EXPECT_EQ(zx_fifo_read(b, ELEM_SZ, n, 4, &actual), ZX_OK, "");
80 ASSERT_EQ(actual, 4u, "");
81 ASSERT_EQ(n[0], 1u, "");
82 ASSERT_EQ(n[1], 2u, "");
83 ASSERT_EQ(n[2], 3u, "");
84 ASSERT_EQ(n[3], 4u, "");
85
86 // should be writable again now
87 EXPECT_SIGNALS(a, ZX_FIFO_WRITABLE);
88
89 // write some more, wrapping to the front again
90 n[0] = 9u;
91 n[1] = 10u;
92 ASSERT_EQ(zx_fifo_write(a, ELEM_SZ, n, 2, &actual), ZX_OK, "");
93 ASSERT_EQ(actual, 2u, "");
94
95 // read across the wrap, test partial read
96 ASSERT_EQ(zx_fifo_read(b, ELEM_SZ, n, 8, &actual), ZX_OK, "");
97 ASSERT_EQ(actual, 6u, "");
98 ASSERT_EQ(n[0], 5u, "");
99 ASSERT_EQ(n[1], 6u, "");
100 ASSERT_EQ(n[2], 7u, "");
101 ASSERT_EQ(n[3], 8u, "");
102 ASSERT_EQ(n[4], 9u, "");
103 ASSERT_EQ(n[5], 10u, "");
104
105 // should no longer be readable
106 EXPECT_SIGNALS(b, ZX_FIFO_WRITABLE);
107
108 // write across the wrap
109 n[0] = 11u; n[1] = 12u; n[2] = 13u; n[3] = 14u; n[4] = 15u;
110 ASSERT_EQ(zx_fifo_write(a, ELEM_SZ, n, 5, &actual), ZX_OK, "");
111 ASSERT_EQ(actual, 5u, "");
112
113 // partial write test
114 n[0] = 16u; n[1] = 17u; n[2] = 18u;
115 ASSERT_EQ(zx_fifo_write(a, ELEM_SZ, n, 5, &actual), ZX_OK, "");
116 ASSERT_EQ(actual, 3u, "");
117
118 // small reads
119 for (unsigned i = 0; i < 8; i++) {
120 ASSERT_EQ(zx_fifo_read(b, ELEM_SZ, n, 1, &actual), ZX_OK, "");
121 ASSERT_EQ(actual, 1u, "");
122 ASSERT_EQ(n[0], 11u + i, "");
123 }
124
125 // write and then close, verify we can read written entries before
126 // receiving ZX_ERR_PEER_CLOSED.
127 n[0] = 19u;
128 ASSERT_EQ(zx_fifo_write(b, ELEM_SZ, n, 1, &actual), ZX_OK, "");
129 ASSERT_EQ(actual, 1u, "");
130 zx_handle_close(b);
131 EXPECT_SIGNALS(a, ZX_FIFO_READABLE | ZX_FIFO_PEER_CLOSED);
132 ASSERT_EQ(zx_fifo_read(a, ELEM_SZ, n, 8, &actual), ZX_OK, "");
133 ASSERT_EQ(actual, 1u, "");
134 EXPECT_SIGNALS(a, ZX_FIFO_PEER_CLOSED);
135 ASSERT_EQ(zx_fifo_read(a, ELEM_SZ, n, 8, &actual), ZX_ERR_PEER_CLOSED, "");
136
137 zx_handle_close(a);
138
139 END_TEST;
140 }
141
peer_closed_test(void)142 static bool peer_closed_test(void) {
143 BEGIN_TEST;
144
145 zx_handle_t fifo[2];
146 ASSERT_EQ(zx_fifo_create(16, 16, 0, &fifo[0], &fifo[1]), ZX_OK, "");
147 ASSERT_EQ(zx_handle_close(fifo[1]), ZX_OK, "");
148 ASSERT_EQ(zx_object_signal_peer(fifo[0], 0u, ZX_USER_SIGNAL_0), ZX_ERR_PEER_CLOSED, "");
149 ASSERT_EQ(zx_handle_close(fifo[0]), ZX_OK, "");
150
151 END_TEST;
152 }
153
options_test(void)154 static bool options_test(void) {
155 BEGIN_TEST;
156
157 zx_handle_t fifos[2];
158 ASSERT_EQ(zx_fifo_create(23, 8, 8, &fifos[0], &fifos[1]),
159 ZX_ERR_OUT_OF_RANGE, "");
160
161 END_TEST;
162 }
163
164 BEGIN_TEST_CASE(fifo_tests)
RUN_TEST(basic_test)165 RUN_TEST(basic_test)
166 RUN_TEST(peer_closed_test)
167 RUN_TEST(options_test)
168 END_TEST_CASE(fifo_tests)
169
170 #ifndef BUILD_COMBINED_TESTS
171 int main(int argc, char** argv) {
172 return unittest_run_all_tests(argc, argv) ? 0 : -1;
173 }
174 #endif
175