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 15static 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 26static 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 142static 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 154static 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 164BEGIN_TEST_CASE(fifo_tests) 165RUN_TEST(basic_test) 166RUN_TEST(peer_closed_test) 167RUN_TEST(options_test) 168END_TEST_CASE(fifo_tests) 169 170#ifndef BUILD_COMBINED_TESTS 171int main(int argc, char** argv) { 172 return unittest_run_all_tests(argc, argv) ? 0 : -1; 173} 174#endif 175