1#![cfg(target_os = "none")]
2#![no_std]
3
4extern crate alloc;
5extern crate sparreal_rt;
6
7use core::{
8 ptr::slice_from_raw_parts,
9 sync::atomic::{AtomicBool, Ordering},
10 time::Duration,
11};
12
13use alloc::{format, string::String, sync::Arc};
14
15pub use bare_test_macros::tests;
16pub use sparreal_rt::*;
17
18mod test_case;
19
20#[sparreal_rt::entry]
21fn main() -> ! {
22 println!("begin test");
23
24 for test in test_case_list() {
25 println!(
26 "Run test: {}{}",
27 test.name,
28 if test.timeout_ms > 0 {
29 format!(" (timeout: {} ms)", test.timeout_ms)
30 } else {
31 String::new()
32 }
33 );
34 let finished = Arc::new(AtomicBool::new(false));
35 let f2 = finished.clone();
36 if test.timeout_ms > 0 {
37 sparreal_rt::os::time::one_shot_after(
38 Duration::from_millis(test.timeout_ms),
39 move || {
40 if !f2.load(Ordering::SeqCst) {
41 panic!("test {} timeout", test.name);
42 }
43 },
44 )
45 .unwrap();
46 }
47
48 (test.test_fn)();
49 finished.store(true, Ordering::SeqCst);
50
51 println!("test {} passed", test.name);
52 }
53
54 println!("All tests passed");
55}
56
57#[repr(C)]
58#[derive(Clone)]
59pub struct TestCase {
60 pub name: &'static str,
61 pub timeout_ms: u64,
62 pub test_fn: fn(),
63}
64
65fn test_case_list() -> test_case::Iter<'static> {
66 unsafe extern "C" {
67 fn _stest_case();
68 fn _etest_case();
69 }
70
71 let data = _stest_case as *const () as usize as *const u8;
72 let len = _etest_case as *const () as usize - _stest_case as *const () as usize;
73
74 let list = test_case::ListRef::from_raw(unsafe { &*slice_from_raw_parts(data, len) });
75
76 list.iter()
77}