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 <stdio.h> 7#include <unistd.h> 8 9#include <lib/fzl/time.h> 10#include <lib/fzl/fifo.h> 11#include <fbl/algorithm.h> 12#include <unittest/unittest.h> 13#include <zircon/syscalls.h> 14 15namespace { 16 17template <typename T> 18bool AlmostEqual(T t0, T t1, T e) { 19 BEGIN_HELPER; 20 21 char buf[128]; 22 snprintf(buf, sizeof(buf), "%zu != %zu (within error of %zu)", t0, t1, e); 23 ASSERT_TRUE(fbl::min(t0, t1) + e >= fbl::max(t0, t1), buf); 24 25 END_HELPER; 26} 27 28bool TickConverter(zx::ticks ticks, zx::ticks err) { 29 BEGIN_HELPER; 30 ASSERT_TRUE(AlmostEqual(ticks.get(), fzl::NsToTicks(fzl::TicksToNs(ticks)).get(), err.get())); 31 ASSERT_TRUE(AlmostEqual(ticks.get(), ns_to_ticks(ticks_to_ns(ticks.get())), err.get())); 32 END_HELPER; 33} 34 35bool NsConverter(zx::duration ns, zx::duration err) { 36 BEGIN_HELPER; 37 ASSERT_TRUE(AlmostEqual(ns.get(), fzl::TicksToNs(fzl::NsToTicks(ns)).get(), err.get())); 38 ASSERT_TRUE(AlmostEqual(ns.get(), ticks_to_ns(ns_to_ticks(ns.get())), err.get())); 39 END_HELPER; 40} 41 42bool TimeTest() { 43 BEGIN_TEST; 44 45 zx::ticks tps = zx::ticks::per_second(); 46 zx::duration nps = zx::sec(1); 47 48 // The following tests check converting from: 49 // - ticks --> nanoseconds --> ticks 50 // - nanoseconds --> ticks --> nanoseconds 51 // 52 // This conversion is inherently lossy if the number of ticks/ns (or 53 // ns/tick) is not an exact integer -- which is almost always the case. 54 // 55 // To convert N nanoseconds to ticks, we'd logically multiply by 56 // "ticks/sec" / "ns/second". However, by converting N into the ticks 57 // equivalent T, we may be losing the fractional component of this number: N 58 // may actually be represented by T +/- a partial tick. 59 // 60 // In most situations, where ticks are higher precision than nanoseconds, 61 // there will actually be even more loss in the other direction: when 62 // converting from ticks to nanoseconds, we may potentially lose as many as 63 // "ticks/second / ns/second" ticks. 64 // 65 // To ensure our error margins account for this loss, where we lose 66 // minimally a "partial unit" and maximally an integer ratio of the units, 67 // we calculate acceptable loss as: 68 // 69 // loss = max(1 + ratio, 1) 70 // 71 // Where we add one to the ratio to "round up to the nearest integer ratio" while 72 // doing the conversion. 73 zx::ticks tick_loss = fbl::max(zx::ticks(1 + (tps.get() / nps.get())), 74 zx::ticks(1)); 75 zx::duration duration_loss = fbl::max(zx::duration(1 + (nps.get() / tps.get())), 76 zx::duration(1)); 77 78 ASSERT_TRUE(TickConverter(zx::ticks(0), zx::ticks(0))); 79 ASSERT_TRUE(TickConverter(zx::ticks(50), tick_loss)); 80 ASSERT_TRUE(TickConverter(zx::ticks(100), tick_loss)); 81 ASSERT_TRUE(TickConverter(zx::ticks(100000), tick_loss)); 82 ASSERT_TRUE(TickConverter(zx::ticks(1000000000), tick_loss)); 83 ASSERT_TRUE(TickConverter(zx::ticks(10000000000000), tick_loss)); 84 85 ASSERT_TRUE(NsConverter(zx::duration(0), zx::duration(0))); 86 ASSERT_TRUE(NsConverter(zx::duration(50), duration_loss)); 87 ASSERT_TRUE(NsConverter(zx::duration(100), duration_loss)); 88 ASSERT_TRUE(NsConverter(zx::duration(100000), duration_loss)); 89 ASSERT_TRUE(NsConverter(zx::duration(1000000000), duration_loss)); 90 ASSERT_TRUE(NsConverter(zx::duration(10000000000000), duration_loss)); 91 92 END_TEST; 93} 94 95bool FifoTest() { 96 BEGIN_TEST; 97 98 // Default constructor 99 { 100 fzl::fifo<int> invalid; 101 ASSERT_EQ(invalid.get_handle(), ZX_HANDLE_INVALID); 102 } 103 104 // Move constructors, reset() and release() 105 { 106 zx::fifo zx_fifo_0, zx_fifo_1; 107 zx_status_t status = zx::fifo::create(4, 4, 0, &zx_fifo_0, &zx_fifo_1); 108 ASSERT_EQ(status, ZX_OK); 109 zx_handle_t handle_0 = zx_fifo_0.get(); 110 ASSERT_NE(handle_0, ZX_HANDLE_INVALID); 111 112 fzl::fifo<int> moved_fifo(fbl::move(zx_fifo_0)); 113 ASSERT_EQ(moved_fifo.get_handle(), handle_0); 114 ASSERT_EQ(zx_fifo_0.get(), ZX_HANDLE_INVALID); 115 116 fzl::fifo<int> moved_again(fbl::move(moved_fifo)); 117 ASSERT_EQ(moved_again.get_handle(), handle_0); 118 ASSERT_EQ(moved_fifo.get_handle(), ZX_HANDLE_INVALID); 119 120 zx::handle opaque_handle(moved_again.release()); 121 fzl::fifo<int> from_opaque(fbl::move(opaque_handle)); 122 ASSERT_EQ(from_opaque.get_handle(), handle_0); 123 ASSERT_EQ(opaque_handle.get(), ZX_HANDLE_INVALID); 124 125 from_opaque.reset(); 126 ASSERT_EQ(from_opaque.get_handle(), ZX_HANDLE_INVALID); 127 } 128 129 // Create, read, write 130 131 fzl::fifo<int64_t, char[8]> fifo_0; 132 fzl::fifo<char[8], int64_t> fifo_1; 133 134 { 135 zx_status_t status = fzl::create_fifo(4, 0, &fifo_0, &fifo_1); 136 ASSERT_EQ(status, ZX_OK); 137 } 138 139 { 140 const int64_t numbers[2] = {10, -20}; 141 size_t actual = 0; 142 zx_status_t status = fifo_0.write(numbers, 2, &actual); 143 ASSERT_EQ(status, ZX_OK); 144 ASSERT_EQ(actual, 2); 145 } 146 147 { 148 int64_t numbers[3] = { 0, 0, 0 }; 149 size_t actual = 0; 150 zx_status_t status = fifo_1.read(numbers, 3, &actual); 151 ASSERT_EQ(status, ZX_OK); 152 ASSERT_EQ(actual, 2); 153 ASSERT_EQ(numbers[0], 10); 154 ASSERT_EQ(numbers[1], -20); 155 } 156 157 { 158 char str[8] = "hi fifo"; 159 zx_status_t status = fifo_1.write_one(str); 160 ASSERT_EQ(status, ZX_OK); 161 } 162 163 { 164 char str[8] = "......."; 165 zx_status_t status = fifo_0.read_one(&str); 166 ASSERT_EQ(status, ZX_OK); 167 ASSERT_STR_EQ("hi fifo", str); 168 } 169 170 // Signal & wait_one 171 { 172 fifo_0.signal(0, ZX_USER_SIGNAL_0); 173 zx_signals_t pending = 0; 174 fifo_0.wait_one(ZX_USER_SIGNAL_0, zx::deadline_after(zx::sec(1)), &pending); 175 ASSERT_TRUE(pending & ZX_USER_SIGNAL_0); 176 } 177 178 // Replace 179 { 180 fzl::fifo<int64_t, char[8]> replaced; 181 fifo_0.replace(0, &replaced); 182 ASSERT_EQ(fifo_0.get_handle(), ZX_HANDLE_INVALID); 183 ASSERT_NE(replaced.get_handle(), ZX_HANDLE_INVALID); 184 } 185 186 END_TEST; 187} 188 189} // namespace 190 191BEGIN_TEST_CASE(libfzl_tests) 192RUN_TEST(TimeTest) 193RUN_TEST(FifoTest) 194END_TEST_CASE(libfzl_tests) 195