Skip to content

Commit cbfb2ed

Browse files
committed
test(test_suite): add tests for Kernel::{set_time, adjust_time}
1 parent 65ae7db commit cbfb2ed

File tree

4 files changed

+287
-0
lines changed

4 files changed

+287
-0
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
//! Verifies that [`adjust_time`] maintains the absolute arrival times of
2+
//! timeouts.
3+
//!
4+
//! [`adjust_time`]: constance::kernel::Kernel::adjust_time
5+
//!
6+
//! 1. (`seq`: 0 → 1, 0ms) `task1` activates `task2` and `task3`.
7+
//! 2. (`seq`: 1 → 2, 0ms) `task2` starts sleeping, expecting to be woken up
8+
//! at system time 600ms.
9+
//! 3. (`seq`: 2 → 3, 0ms) `task3` starts sleeping, expecting to be woken up
10+
//! at system time 100ms.
11+
//! 4. (`seq`: 3 → 4, 0ms) `task1` changes the system time to 300ms using
12+
//! `adjust_time`.
13+
//! 5. (`seq`: 4 → 5, 300ms) `task3` wakes up, finding it's late by 200ms.
14+
//! 6. (`seq`: 5 → 6, 300ms) `task1` exits.
15+
//! 7. (`seq`: 6 → 7, 600ms) `tsak2` wakes up.
16+
//!
17+
use constance::{
18+
kernel::{Hunk, Task},
19+
prelude::*,
20+
time::{Duration, Time},
21+
};
22+
23+
use super::Driver;
24+
use crate::utils::SeqTracker;
25+
26+
pub struct App<System> {
27+
task2: Task<System>,
28+
task3: Task<System>,
29+
seq: Hunk<System, SeqTracker>,
30+
}
31+
32+
impl<System: Kernel> App<System> {
33+
constance::configure! {
34+
pub const fn new<D: Driver<Self>>(_: &mut CfgBuilder<System>) -> Self {
35+
new! { Task<_>, start = task1_body::<System, D>, priority = 3, active = true };
36+
let task2 = new! { Task<_>, start = task2_body::<System, D>, priority = 1 };
37+
let task3 = new! { Task<_>, start = task3_body::<System, D>, priority = 2 };
38+
39+
let seq = new! { Hunk<_, SeqTracker> };
40+
41+
App { task2, task3, seq }
42+
}
43+
}
44+
}
45+
46+
fn task1_body<System: Kernel, D: Driver<App<System>>>(_: usize) {
47+
D::app().seq.expect_and_replace(0, 1);
48+
System::set_time(Time::from_millis(0)).unwrap();
49+
D::app().task2.activate().unwrap();
50+
D::app().task3.activate().unwrap();
51+
D::app().seq.expect_and_replace(3, 4);
52+
53+
// Adjust the system time while `task2` and `task3` are sleeping.
54+
System::adjust_time(Duration::from_millis(300)).unwrap();
55+
// This will cause `task3` to wake up immediately.
56+
57+
D::app().seq.expect_and_replace(5, 6);
58+
}
59+
60+
fn task2_body<System: Kernel, D: Driver<App<System>>>(_: usize) {
61+
D::app().seq.expect_and_replace(1, 2);
62+
63+
// Start sleeping at system time 0ms
64+
System::sleep(Duration::from_millis(600)).unwrap();
65+
66+
D::app().seq.expect_and_replace(6, 7);
67+
68+
// Sleeping should conclude at system time 600ms
69+
let now = Time::from_millis(600);
70+
let now_got = System::time().unwrap();
71+
log::trace!("time = {:?} (expected = {:?})", now_got, now);
72+
73+
// `now <= now_got < now + timing_error`
74+
let delta = now_got.duration_since(now);
75+
assert!(!delta.unwrap().is_negative());
76+
assert!(delta.unwrap().as_millis() < 100);
77+
78+
D::success();
79+
}
80+
81+
fn task3_body<System: Kernel, D: Driver<App<System>>>(_: usize) {
82+
D::app().seq.expect_and_replace(2, 3);
83+
84+
// Start sleeping at system time 0ms
85+
System::sleep(Duration::from_millis(100)).unwrap();
86+
87+
D::app().seq.expect_and_replace(4, 5);
88+
89+
// Sleeping should conclude at system time 300ms (late by 200ms)
90+
// because it jumped to 300ms
91+
let now = Time::from_millis(300);
92+
let now_got = System::time().unwrap();
93+
log::trace!("time = {:?} (expected = {:?})", now_got, now);
94+
95+
// `now <= now_got < now + timing_error`
96+
let delta = now_got.duration_since(now);
97+
assert!(!delta.unwrap().is_negative());
98+
assert!(delta.unwrap().as_millis() < 100);
99+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//! Verifies the adjustable range of [`adjust_time`].
2+
use constance::{
3+
kernel::{AdjustTimeError, Hunk, Task, TIME_USER_HEADROOM},
4+
prelude::*,
5+
time::{Duration, Time},
6+
};
7+
8+
use super::Driver;
9+
use crate::utils::SeqTracker;
10+
11+
pub struct App<System> {
12+
task2: Task<System>,
13+
seq: Hunk<System, SeqTracker>,
14+
}
15+
16+
impl<System: Kernel> App<System> {
17+
constance::configure! {
18+
pub const fn new<D: Driver<Self>>(_: &mut CfgBuilder<System>) -> Self {
19+
new! { Task<_>, start = task1_body::<System, D>, priority = 3, active = true };
20+
let task2 = new! { Task<_>, start = task2_body::<System, D>, priority = 1 };
21+
22+
let seq = new! { Hunk<_, SeqTracker> };
23+
24+
App { task2, seq }
25+
}
26+
}
27+
}
28+
29+
fn task1_body<System: Kernel, D: Driver<App<System>>>(_: usize) {
30+
D::app().seq.expect_and_replace(0, 1);
31+
System::set_time(Time::from_millis(0)).unwrap();
32+
D::app().task2.activate().unwrap();
33+
D::app().seq.expect_and_replace(2, 3);
34+
35+
System::boost_priority().unwrap();
36+
37+
// `system_time += TIME_USER_HEADROOM + 1300ms`, which should fail because
38+
// `task2`'s timeout would be late by `300ms`
39+
log::debug!("system_time += TIME_USER_HEADROOM + 1300ms (should fail)");
40+
// TODO: `impl Add for Duration`
41+
assert_eq!(
42+
System::adjust_time(Duration::from_millis(1300 + TIME_USER_HEADROOM.as_millis())),
43+
Err(AdjustTimeError::BadObjectState),
44+
);
45+
46+
// `system_time += 500ms`, which should succeed because
47+
// `task2`'s timeout will not be late
48+
log::debug!("system_time += 500ms");
49+
System::adjust_time(Duration::from_millis(500)).unwrap();
50+
51+
// `system_time += 800ms`, which should succeed because
52+
// `task2`'s timeout will be only late by `300ms`
53+
log::debug!("system_time += 800ms");
54+
System::adjust_time(Duration::from_millis(800)).unwrap();
55+
56+
// `system_time -= 700ms`, which should succeed because the frontier will be
57+
// only away by `700ms`
58+
log::debug!("system_time -= 700ms");
59+
System::adjust_time(Duration::from_millis(-700)).unwrap();
60+
61+
// `system_time -= TIME_USER_HEADROOM`, which should fail because the
62+
// frontier would be away by `700ms + TIME_USER_HEADROOM`
63+
log::debug!("system_time -= TIME_USER_HEADROOM (should fail)");
64+
assert_eq!(
65+
System::adjust_time(Duration::from_millis(-TIME_USER_HEADROOM.as_millis())),
66+
Err(AdjustTimeError::BadObjectState),
67+
);
68+
69+
// `system_time -= TIME_USER_HEADROOM - 900ms`, which should succeed because the frontier will be
70+
// only away by `TIME_USER_HEADROOM - 200ms`
71+
log::debug!("system_time -= TIME_USER_HEADROOM - 900ms");
72+
System::adjust_time(Duration::from_millis(TIME_USER_HEADROOM.as_millis() - 900)).unwrap();
73+
74+
D::app().seq.expect_and_replace(3, 4);
75+
76+
unsafe { System::unboost_priority().unwrap() };
77+
}
78+
79+
fn task2_body<System: Kernel, D: Driver<App<System>>>(_: usize) {
80+
D::app().seq.expect_and_replace(1, 2);
81+
82+
// Create a timeout scheduled at 1000ms
83+
System::sleep(Duration::from_millis(1000)).unwrap();
84+
85+
D::app().seq.expect_and_replace(4, 5);
86+
87+
D::success();
88+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
//! Verifies that `set_time` maintains the relative arrival times of
2+
//! timeouts.
3+
//!
4+
//! [`set_time`]: constance::kernel::Kernel::set_time
5+
//!
6+
//! 1. (`seq`: 0 → 1, 0ms) `task1` activates `task2` and `task3`.
7+
//! 2. (`seq`: 1 → 2, 0ms) `task2` starts sleeping, expecting to be woken up
8+
//! at system time 300ms.
9+
//! 3. (`seq`: 2 → 3, 0ms) `task3` starts sleeping, expecting to be woken up
10+
//! at system time 100ms.
11+
//! 4. (`seq`: 3 → 4, 0ms) `task1` changes the system time to 300ms using
12+
//! `set_time`.
13+
//! 6. (`seq`: 4 → 5, 300ms) `task1` exits.
14+
//! 5. (`seq`: 5 → 6, 400ms) `task3` wakes up.
15+
//! 7. (`seq`: 6 → 7, 600ms) `tsak2` wakes up.
16+
//!
17+
use constance::{
18+
kernel::{Hunk, Task},
19+
prelude::*,
20+
time::{Duration, Time},
21+
};
22+
23+
use super::Driver;
24+
use crate::utils::SeqTracker;
25+
26+
pub struct App<System> {
27+
task2: Task<System>,
28+
task3: Task<System>,
29+
seq: Hunk<System, SeqTracker>,
30+
}
31+
32+
impl<System: Kernel> App<System> {
33+
constance::configure! {
34+
pub const fn new<D: Driver<Self>>(_: &mut CfgBuilder<System>) -> Self {
35+
new! { Task<_>, start = task1_body::<System, D>, priority = 3, active = true };
36+
let task2 = new! { Task<_>, start = task2_body::<System, D>, priority = 1 };
37+
let task3 = new! { Task<_>, start = task3_body::<System, D>, priority = 2 };
38+
39+
let seq = new! { Hunk<_, SeqTracker> };
40+
41+
App { task2, task3, seq }
42+
}
43+
}
44+
}
45+
46+
fn task1_body<System: Kernel, D: Driver<App<System>>>(_: usize) {
47+
D::app().seq.expect_and_replace(0, 1);
48+
System::set_time(Time::from_millis(0)).unwrap();
49+
D::app().task2.activate().unwrap();
50+
D::app().task3.activate().unwrap();
51+
D::app().seq.expect_and_replace(3, 4);
52+
53+
// Adjust the system time while `task2` and `task3` are sleeping.
54+
System::set_time(Time::from_millis(300)).unwrap();
55+
56+
D::app().seq.expect_and_replace(4, 5);
57+
}
58+
59+
fn task2_body<System: Kernel, D: Driver<App<System>>>(_: usize) {
60+
D::app().seq.expect_and_replace(1, 2);
61+
62+
// Start sleeping at system time 0ms
63+
System::sleep(Duration::from_millis(300)).unwrap();
64+
65+
D::app().seq.expect_and_replace(6, 7);
66+
67+
// Sleeping should conclude at system time 600ms
68+
let now = Time::from_millis(600);
69+
let now_got = System::time().unwrap();
70+
log::trace!("time = {:?} (expected = {:?})", now_got, now);
71+
72+
// `now <= now_got < now + timing_error`
73+
let delta = now_got.duration_since(now);
74+
assert!(!delta.unwrap().is_negative());
75+
assert!(delta.unwrap().as_millis() < 100);
76+
77+
D::success();
78+
}
79+
80+
fn task3_body<System: Kernel, D: Driver<App<System>>>(_: usize) {
81+
D::app().seq.expect_and_replace(2, 3);
82+
83+
// Start sleeping at system time 0ms
84+
System::sleep(Duration::from_millis(100)).unwrap();
85+
86+
D::app().seq.expect_and_replace(5, 6);
87+
88+
// Sleeping should conclude at system time 400ms
89+
let now = Time::from_millis(400);
90+
let now_got = System::time().unwrap();
91+
log::trace!("time = {:?} (expected = {:?})", now_got, now);
92+
93+
// `now <= now_got < now + timing_error`
94+
let delta = now_got.duration_since(now);
95+
assert!(!delta.unwrap().is_negative());
96+
assert!(delta.unwrap().as_millis() < 100);
97+
}

src/constance_test_suite/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,10 @@ pub mod kernel_tests {
162162
(mod task_park_reset {}, "task_park_reset"),
163163
(mod task_priority_boost_reset {}, "task_priority_boost_reset"),
164164
(mod task_queue_fifo {}, "task_queue_fifo"),
165+
(mod time_adjust_event {}, "time_adjust_event"),
166+
(mod time_adjust_limits {}, "time_adjust_limits"),
165167
(mod time_misc {}, "time_misc"),
168+
(mod time_set_event {}, "time_set_event"),
166169
(mod time_stress {}, "time_stress"),
167170
}
168171

0 commit comments

Comments
 (0)