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 <stdio.h> 7#include <threads.h> 8 9#include <lib/zx/timer.h> 10 11#include <fbl/type_support.h> 12 13#include <unistd.h> 14#include <unittest/unittest.h> 15 16static bool deadline_after() { 17 BEGIN_TEST; 18 auto then = zx_clock_get_monotonic(); 19 // The day we manage to boot and run this test in less than 1uS we need to fix this. 20 ASSERT_GT(then, 1000u); 21 22 auto one_hour_later = zx_deadline_after(ZX_HOUR(1)); 23 EXPECT_LT(then, one_hour_later); 24 25 zx_duration_t too_big = INT64_MAX - 100; 26 auto clamped = zx_deadline_after(too_big); 27 EXPECT_EQ(clamped, ZX_TIME_INFINITE); 28 29 EXPECT_LT(0, zx_deadline_after(10 * 365 * ZX_HOUR(24))); 30 EXPECT_LT(zx_deadline_after(ZX_TIME_INFINITE_PAST), 0); 31 END_TEST; 32} 33 34static bool timer_set_negative_deadline() { 35 BEGIN_TEST; 36 zx::timer timer; 37 ASSERT_EQ(zx::timer::create(0, ZX_CLOCK_MONOTONIC, &timer), ZX_OK); 38 zx::duration slack; 39 ASSERT_EQ(timer.set(zx::time(-1), slack), ZX_OK); 40 zx_signals_t pending; 41 ASSERT_EQ(timer.wait_one(ZX_TIMER_SIGNALED, zx::time::infinite(), &pending), ZX_OK); 42 ASSERT_EQ(pending, ZX_TIMER_SIGNALED); 43 END_TEST; 44} 45 46static bool timer_set_negative_deadline_max() { 47 BEGIN_TEST; 48 zx::timer timer; 49 ASSERT_EQ(zx::timer::create(0, ZX_CLOCK_MONOTONIC, &timer), ZX_OK); 50 zx::duration slack; 51 ASSERT_EQ(timer.set(zx::time(ZX_TIME_INFINITE_PAST), slack), ZX_OK); 52 zx_signals_t pending; 53 ASSERT_EQ(timer.wait_one(ZX_TIMER_SIGNALED, zx::time::infinite(), &pending), ZX_OK); 54 ASSERT_EQ(pending, ZX_TIMER_SIGNALED); 55 END_TEST; 56} 57 58static bool timer_set_negative_slack() { 59 BEGIN_TEST; 60 zx::timer timer; 61 ASSERT_EQ(zx::timer::create(0, ZX_CLOCK_MONOTONIC, &timer), ZX_OK); 62 ASSERT_EQ(timer.set(zx::time(), zx::duration(-1)), ZX_ERR_OUT_OF_RANGE); 63 END_TEST; 64} 65 66static bool basic_test() { 67 BEGIN_TEST; 68 zx::timer timer; 69 ASSERT_EQ(zx::timer::create(0, ZX_CLOCK_MONOTONIC, &timer), ZX_OK); 70 71 zx_signals_t pending; 72 EXPECT_EQ(timer.wait_one(ZX_TIMER_SIGNALED, zx::time(), &pending), ZX_ERR_TIMED_OUT); 73 EXPECT_EQ(pending, 0u); 74 75 for (int ix = 0; ix != 10; ++ix) { 76 const auto deadline_timer = zx::deadline_after(zx::msec(50)); 77 const auto deadline_wait = zx::deadline_after(zx::sec(1)); 78 // Timer should fire faster than the wait timeout. 79 ASSERT_EQ(timer.set(deadline_timer, zx::nsec(0)), ZX_OK); 80 81 EXPECT_EQ(timer.wait_one(ZX_TIMER_SIGNALED, deadline_wait, &pending), ZX_OK); 82 EXPECT_EQ(pending, ZX_TIMER_SIGNALED); 83 } 84 END_TEST; 85} 86 87static bool restart_test() { 88 BEGIN_TEST; 89 zx::timer timer; 90 ASSERT_EQ(zx::timer::create(0, ZX_CLOCK_MONOTONIC, &timer), ZX_OK); 91 92 zx_signals_t pending; 93 for (int ix = 0; ix != 10; ++ix) { 94 const auto deadline_timer = zx::deadline_after(zx::msec(500)); 95 const auto deadline_wait = zx::deadline_after(zx::msec(1)); 96 // Setting a timer already running is equivalent to a cancel + set. 97 ASSERT_EQ(timer.set(deadline_timer, zx::nsec(0)), ZX_OK); 98 99 EXPECT_EQ(timer.wait_one(ZX_TIMER_SIGNALED, deadline_wait, &pending), ZX_ERR_TIMED_OUT); 100 EXPECT_EQ(pending, 0u); 101 } 102 END_TEST; 103} 104 105static bool invalid_calls() { 106 BEGIN_TEST; 107 108 zx::timer timer; 109 ASSERT_EQ(zx::timer::create(0, ZX_CLOCK_UTC, &timer), ZX_ERR_INVALID_ARGS); 110 ASSERT_EQ(zx::timer::create(ZX_TIMER_SLACK_LATE + 1, ZX_CLOCK_UTC, &timer), ZX_ERR_INVALID_ARGS); 111 112 END_TEST; 113} 114 115static bool edge_cases() { 116 BEGIN_TEST; 117 118 zx::timer timer; 119 ASSERT_EQ(zx::timer::create(0, ZX_CLOCK_MONOTONIC, &timer), ZX_OK); 120 ASSERT_EQ(timer.set(zx::time(), zx::nsec(0)), ZX_OK); 121 122 END_TEST; 123} 124 125// furiously spin resetting the timer, trying to race with it going off to look for 126// race conditions. 127static bool restart_race() { 128 BEGIN_TEST; 129 130 const zx_time_t kTestDuration = ZX_SEC(5); 131 auto start = zx_clock_get_monotonic(); 132 133 zx::timer timer; 134 ASSERT_EQ(zx::timer::create(0, ZX_CLOCK_MONOTONIC, &timer), ZX_OK); 135 while (zx_clock_get_monotonic() - start < kTestDuration) { 136 ASSERT_EQ(timer.set(zx::deadline_after(zx::usec(100)), zx::nsec(0)), ZX_OK); 137 } 138 139 EXPECT_EQ(timer.cancel(), ZX_OK); 140 141 END_TEST; 142} 143 144// If the timer is already due at the moment it is started then the signal should be 145// asserted immediately. Likewise canceling the timer should immediately deassert 146// the signal. 147static bool signals_asserted_immediately() { 148 BEGIN_TEST; 149 zx::timer timer; 150 ASSERT_EQ(zx::timer::create(0, ZX_CLOCK_MONOTONIC, &timer), ZX_OK); 151 152 for (int i = 0; i < 100; i++) { 153 zx::time now = zx::clock::get_monotonic(); 154 155 EXPECT_EQ(timer.set(now, zx::nsec(0)), ZX_OK); 156 157 zx_signals_t pending; 158 EXPECT_EQ(timer.wait_one(ZX_TIMER_SIGNALED, zx::time(), &pending), ZX_OK); 159 EXPECT_EQ(pending, ZX_TIMER_SIGNALED); 160 161 EXPECT_EQ(timer.cancel(), ZX_OK); 162 163 EXPECT_EQ(timer.wait_one(ZX_TIMER_SIGNALED, zx::time(), &pending), ZX_ERR_TIMED_OUT); 164 EXPECT_EQ(pending, 0u); 165 } 166 167 END_TEST; 168} 169 170// This test is disabled because is flaky. The system might have a timer 171// nearby |deadline_1| or |deadline_2| and as such the test will fire 172// either earlier or later than expected. The precise behavior is still 173// tested by the "k timer tests" command. 174// 175// See ZX-1087 for the current owner. 176 177static bool coalesce_test(uint32_t mode) { 178 BEGIN_TEST; 179 // The second timer will coalesce to the first one for ZX_TIMER_SLACK_LATE 180 // but not for ZX_TIMER_SLACK_EARLY. This test is not precise because the 181 // system might have other timers that interfere with it. Precise tests are 182 // avaliable as kernel tests. 183 184 zx::timer timer_1; 185 ASSERT_EQ(zx::timer::create(0, ZX_CLOCK_MONOTONIC, &timer_1), ZX_OK); 186 zx::timer timer_2; 187 ASSERT_EQ(zx::timer::create(mode, ZX_CLOCK_MONOTONIC, &timer_2), ZX_OK); 188 189 zx_time_t start = zx_clock_get_monotonic(); 190 191 const auto deadline_1 = zx::time(start + ZX_MSEC(350)); 192 const auto deadline_2 = zx::time(start + ZX_MSEC(250)); 193 194 ASSERT_EQ(timer_1.set(deadline_1, zx::nsec(0)), ZX_OK); 195 ASSERT_EQ(timer_2.set(deadline_2, zx::msec(110)), ZX_OK); 196 197 zx_signals_t pending; 198 EXPECT_EQ(timer_2.wait_one(ZX_TIMER_SIGNALED, zx::time::infinite(), &pending), ZX_OK); 199 EXPECT_EQ(pending, ZX_TIMER_SIGNALED); 200 201 auto duration = zx_clock_get_monotonic() - start; 202 203 if (mode == ZX_TIMER_SLACK_LATE) { 204 EXPECT_GE(duration, ZX_MSEC(350)); 205 } else if (mode == ZX_TIMER_SLACK_EARLY) { 206 EXPECT_LE(duration, ZX_MSEC(345)); 207 } else { 208 assert(false); 209 } 210 END_TEST; 211} 212 213// Test is disabled, see coalesce_test(). 214static bool coalesce_test_early() { 215 return coalesce_test(ZX_TIMER_SLACK_EARLY); 216} 217 218// Test is disabled, see coalesce_test(). 219static bool coalesce_test_late() { 220 return coalesce_test(ZX_TIMER_SLACK_LATE); 221} 222 223BEGIN_TEST_CASE(timers_test) 224RUN_TEST(deadline_after) 225RUN_TEST(timer_set_negative_deadline) 226RUN_TEST(timer_set_negative_deadline_max) 227RUN_TEST(timer_set_negative_slack) 228RUN_TEST(invalid_calls) 229RUN_TEST(basic_test) 230// Disabled: RUN_TEST(coalesce_test_late) 231// Disabled: RUN_TEST(coalesce_test_early) 232RUN_TEST(restart_test) 233RUN_TEST(edge_cases) 234RUN_TEST(restart_race) 235RUN_TEST(signals_asserted_immediately) 236END_TEST_CASE(timers_test) 237 238int main(int argc, char** argv) { 239 bool success = unittest_run_all_tests(argc, argv); 240 return success ? 0 : -1; 241} 242