Skip to content

Commit a733c16

Browse files
committed
test(test_suite): add tests for constance::sync::Mutex
1 parent 743d06f commit a733c16

File tree

3 files changed

+204
-0
lines changed

3 files changed

+204
-0
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//! Checks miscellaneous properties of [`constance::sync::Mutex`].
2+
use constance::{
3+
kernel::{cfg::CfgBuilder, Hunk, Task},
4+
prelude::*,
5+
sync::mutex::Mutex,
6+
};
7+
8+
use super::Driver;
9+
use crate::utils::SeqTracker;
10+
11+
pub struct App<System> {
12+
task2: Task<System>,
13+
mutex: Mutex<System, u32>,
14+
seq: Hunk<System, SeqTracker>,
15+
}
16+
17+
impl<System: Kernel> App<System> {
18+
pub const fn new<D: Driver<Self>>(b: &mut CfgBuilder<System>) -> Self {
19+
Task::build()
20+
.start(task1_body::<System, D>)
21+
.priority(2)
22+
.active(true)
23+
.finish(b);
24+
let task2 = Task::build()
25+
.start(task2_body::<System, D>)
26+
.priority(1)
27+
.active(false)
28+
.finish(b);
29+
30+
let mutex = Mutex::new(b);
31+
32+
let seq = Hunk::<_, SeqTracker>::build().finish(b);
33+
34+
App { task2, mutex, seq }
35+
}
36+
}
37+
38+
fn task1_body<System: Kernel, D: Driver<App<System>>>(_: usize) {
39+
let app = D::app();
40+
41+
app.seq.expect_and_replace(0, 1);
42+
43+
{
44+
let mut lock = app.mutex.lock().unwrap();
45+
app.task2.activate().unwrap(); // giving the control to `task2`
46+
47+
// back from `task2`, which is being blocked...
48+
app.seq.expect_and_replace(2, 3);
49+
*lock = 42;
50+
51+
// release the lock and let `task2` continue. the control will return to
52+
// here when `task2` completes
53+
}
54+
55+
app.seq.expect_and_replace(5, 6);
56+
57+
assert_eq!(*app.mutex.lock().unwrap(), 56);
58+
59+
D::success();
60+
}
61+
62+
fn task2_body<System: Kernel, D: Driver<App<System>>>(_: usize) {
63+
let app = D::app();
64+
65+
app.seq.expect_and_replace(1, 2);
66+
67+
{
68+
let mut lock = app.mutex.lock().unwrap(); // blocks because `task1` has lock
69+
70+
// preempts `task1` when it releases the lock
71+
app.seq.expect_and_replace(3, 4);
72+
assert_eq!(*lock, 42);
73+
*lock = 56;
74+
}
75+
76+
app.seq.expect_and_replace(4, 5);
77+
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
//! Checks miscellaneous properties of [`constance::sync::Mutex`].
2+
use constance::{
3+
kernel::{cfg::CfgBuilder, Hunk, InterruptHandler, InterruptLine, Task},
4+
prelude::*,
5+
sync::mutex::{self, Mutex},
6+
};
7+
8+
use super::Driver;
9+
use crate::utils::SeqTracker;
10+
11+
pub struct App<System> {
12+
int: Option<InterruptLine<System>>,
13+
eg1: Mutex<System, u32>,
14+
eg2: Mutex<System, u32>,
15+
seq: Hunk<System, SeqTracker>,
16+
}
17+
18+
impl<System: Kernel> App<System> {
19+
pub const fn new<D: Driver<Self>>(b: &mut CfgBuilder<System>) -> Self {
20+
Task::build()
21+
.start(task_body::<System, D>)
22+
.priority(2)
23+
.active(true)
24+
.finish(b);
25+
let eg1 = Mutex::new(b);
26+
let eg2 = Mutex::new(b);
27+
28+
let int = if let (&[int_line, ..], &[int_pri, ..]) =
29+
(D::INTERRUPT_LINES, D::INTERRUPT_PRIORITIES)
30+
{
31+
InterruptHandler::build()
32+
.line(int_line)
33+
.start(isr::<System, D>)
34+
.finish(b);
35+
36+
Some(
37+
InterruptLine::build()
38+
.line(int_line)
39+
.enabled(true)
40+
.priority(int_pri)
41+
.finish(b),
42+
)
43+
} else {
44+
None
45+
};
46+
47+
let seq = Hunk::<_, SeqTracker>::build().finish(b);
48+
49+
App { eg1, eg2, int, seq }
50+
}
51+
}
52+
53+
fn task_body<System: Kernel, D: Driver<App<System>>>(_: usize) {
54+
let app = D::app();
55+
56+
app.seq.expect_and_replace(0, 1);
57+
58+
if let Some(int) = app.int {
59+
int.pend().unwrap();
60+
} else {
61+
log::warn!("No interrupt lines defined, skipping a portion of the test");
62+
app.seq.expect_and_replace(1, 2);
63+
}
64+
65+
// CPU Lock active
66+
System::acquire_cpu_lock().unwrap();
67+
assert_eq!(app.eg1.lock().err(), Some(mutex::LockError::BadContext));
68+
assert_eq!(
69+
app.eg1.try_lock().err(),
70+
Some(mutex::TryLockError::BadContext),
71+
);
72+
unsafe { System::release_cpu_lock().unwrap() };
73+
74+
// Smoke test
75+
drop(app.eg1.lock());
76+
drop(app.eg1.lock());
77+
{
78+
let _eg1 = app.eg1.lock();
79+
drop(app.eg2.lock());
80+
drop(app.eg2.lock());
81+
}
82+
83+
drop(app.eg1.try_lock());
84+
drop(app.eg1.try_lock());
85+
86+
// Double lock
87+
{
88+
let _eg1 = app.eg1.lock();
89+
assert_eq!(
90+
app.eg1.try_lock().err(),
91+
Some(mutex::TryLockError::WouldBlock),
92+
);
93+
assert_eq!(
94+
app.eg1.try_lock().err(),
95+
Some(mutex::TryLockError::WouldBlock),
96+
);
97+
}
98+
99+
// Inner data
100+
*app.eg1.lock().unwrap() = 0x12345678;
101+
*app.eg1.try_lock().unwrap() += 1;
102+
*app.eg2.lock().unwrap() = 0x87654321;
103+
*app.eg2.try_lock().unwrap() -= 1;
104+
105+
assert_eq!(*app.eg1.lock().unwrap(), 0x12345679);
106+
assert_eq!(*app.eg2.lock().unwrap(), 0x87654320);
107+
108+
assert_eq!(unsafe { *app.eg1.get_ptr() }, 0x12345679);
109+
assert_eq!(unsafe { *app.eg2.get_ptr() }, 0x87654320);
110+
111+
D::success();
112+
}
113+
114+
fn isr<System: Kernel, D: Driver<App<System>>>(_: usize) {
115+
let app = D::app();
116+
117+
app.seq.expect_and_replace(1, 2);
118+
119+
// Non-task context
120+
assert_eq!(app.eg1.lock().err(), Some(mutex::LockError::BadContext));
121+
assert_eq!(
122+
app.eg1.try_lock().err(),
123+
Some(mutex::TryLockError::BadContext),
124+
);
125+
}

src/constance_test_suite/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@ pub mod kernel_tests {
191191
(mod startup_hook_disallowed_services {}, "startup_hook_disallowed_services"),
192192
(mod startup_hook_pend_interrupt {}, "startup_hook_pend_interrupt"),
193193
(mod startup_hook_priority {}, "startup_hook_priority"),
194+
(mod sync_mutex_lock_and_dispatch {}, "sync_mutex_lock_and_dispatch"),
195+
(mod sync_mutex_misc {}, "sync_mutex_misc"),
194196
(mod task_activate_and_dispatch {}, "task_activate_and_dispatch"),
195197
(mod task_activate_and_do_not_dispatch {}, "task_activate_and_do_not_dispatch"),
196198
(mod task_cpu_lock_reset {}, "task_cpu_lock_reset"),

0 commit comments

Comments
 (0)