blob: 7a8768d75a25f9c24afdfd3f90accb9204a9a21d [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use fidl_fuchsia_fakeclock_test::ExampleMarker;
use fidl_fuchsia_testing::{DeadlineEventType, FakeClockControlMarker, Increment};
use fuchsia_async as fasync;
use fuchsia_component::client::connect_to_protocol;
use fuchsia_zircon as zx;
use named_timer::DeadlineId;
const DEADLINE_NAME: DeadlineId<'static> = DeadlineId::new("fake-clock-example", "deadline");
const ONE_DAY: zx::Duration = zx::Duration::from_hours(24);
const ONE_MILLIS: zx::Duration = zx::Duration::from_millis(1);
const ONE_HOUR: zx::Duration = zx::Duration::from_hours(1);
#[fasync::run_singlethreaded(test)]
async fn test_pause_advance() {
let fake_time = connect_to_protocol::<FakeClockControlMarker>()
.expect("failed to connect to FakeClockControl");
let example =
connect_to_protocol::<ExampleMarker>().expect("failed to connect to Example service");
// When time is paused, querying for time twice should give the same result.
let () = fake_time.pause().await.expect("failed to pause time");
let now_1 = example.get_monotonic().await.expect("get_monotonic failed");
let now_2 = example.get_monotonic().await.expect("get_monotonic failed");
assert_eq!(now_1, now_2);
// Set a 24 hour timer then advance time 24 hours. The timer should complete.
let long_timeout = zx::Time::from_nanos(now_1) + ONE_DAY;
let long_wait_fut = example.wait_until(long_timeout.into_nanos());
let () = fake_time
.advance(&Increment::Determined(ONE_DAY.into_nanos()))
.await
.expect("advance failed")
.expect("advance returned error");
let () = long_wait_fut.await.expect("wait_until failed");
assert_eq!(
example.get_monotonic().await.expect("get_monotonic failed"),
long_timeout.into_nanos()
);
// Test named deadlines.
// First, we set a stop point to detect when a timer is set, then resume time.
let (deadline_set_event, deadline_set_server) = zx::EventPair::create();
let () = fake_time
.add_stop_point(&DEADLINE_NAME.into(), DeadlineEventType::Set, deadline_set_server)
.await
.expect("add_stop_point failed")
.expect("add_stop_point returned error");
let () = fake_time
.resume_with_increments(
ONE_MILLIS.into_nanos(),
&Increment::Determined(ONE_MILLIS.into_nanos()),
)
.await
.expect("resume_with_increments failed")
.expect("resume_with_increments returned error");
// Make a request that causes the timer to be set, and wait for the timer to be set.
let long_wait_fut = example.wait_for(ONE_DAY.into_nanos());
assert_eq!(
fasync::OnSignals::new(&deadline_set_event, zx::Signals::EVENTPAIR_SIGNALED)
.await
.expect("waiting for timer set failed")
& !zx::Signals::EVENTPAIR_PEER_CLOSED,
zx::Signals::EVENTPAIR_SIGNALED
);
// Time should now be stopped.
let now_1 = example.get_monotonic().await.expect("get_monotonic failed");
let now_2 = example.get_monotonic().await.expect("get_monotonic failed");
assert_eq!(now_1, now_2);
// We now register a stop point to trigger when the timer expires, and run time fast.
let (deadline_expire_event, deadline_expire_server) = zx::EventPair::create();
let () = fake_time
.add_stop_point(&DEADLINE_NAME.into(), DeadlineEventType::Expired, deadline_expire_server)
.await
.expect("add_stop_point failed")
.expect("add_stop_point returned error");
let () = fake_time
.resume_with_increments(
ONE_MILLIS.into_nanos(),
&Increment::Determined(ONE_HOUR.into_nanos()),
)
.await
.expect("resume_with_increments failed")
.expect("resume_with_increments returned error");
// Wait for the timer to expire. The timer in the component under test should complete.
assert_eq!(
fasync::OnSignals::new(&deadline_expire_event, zx::Signals::EVENTPAIR_SIGNALED)
.await
.expect("waiting for timer expired failed")
& !zx::Signals::EVENTPAIR_PEER_CLOSED,
zx::Signals::EVENTPAIR_SIGNALED
);
let () = long_wait_fut.await.expect("wait_for failed");
// A day should've passed.
let now_3 = example.get_monotonic().await.expect("get_monotonic failed");
assert!(now_3 >= now_2 + ONE_DAY.into_nanos());
}