Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/wiggle/tests/flags.rs
1692 views
1
use proptest::prelude::*;
2
use wiggle::{GuestMemory, GuestPtr};
3
use wiggle_test::{HostMemory, MemArea, WasiCtx, impl_errno};
4
5
wiggle::from_witx!({
6
witx: ["tests/flags.witx"],
7
});
8
9
impl_errno!(types::Errno);
10
11
impl<'a> flags::Flags for WasiCtx<'a> {
12
fn configure_car(
13
&mut self,
14
memory: &mut GuestMemory<'_>,
15
old_config: types::CarConfig,
16
other_config_ptr: GuestPtr<types::CarConfig>,
17
) -> Result<types::CarConfig, types::Errno> {
18
let other_config = memory.read(other_config_ptr).map_err(|e| {
19
eprintln!("old_config_ptr error: {e}");
20
types::Errno::InvalidArg
21
})?;
22
Ok(old_config ^ other_config)
23
}
24
}
25
26
fn car_config_strat() -> impl Strategy<Value = types::CarConfig> {
27
(1u8..=types::CarConfig::all().into())
28
.prop_map(|v| {
29
types::CarConfig::try_from(v).expect("invalid value for types::CarConfig flag")
30
})
31
.boxed()
32
}
33
34
#[derive(Debug)]
35
struct ConfigureCarExercise {
36
old_config: types::CarConfig,
37
other_config: types::CarConfig,
38
other_config_by_ptr: MemArea,
39
return_ptr_loc: MemArea,
40
}
41
42
impl ConfigureCarExercise {
43
pub fn strat() -> BoxedStrategy<Self> {
44
(
45
car_config_strat(),
46
car_config_strat(),
47
HostMemory::mem_area_strat(4),
48
HostMemory::mem_area_strat(4),
49
)
50
.prop_map(
51
|(old_config, other_config, other_config_by_ptr, return_ptr_loc)| Self {
52
old_config,
53
other_config,
54
other_config_by_ptr,
55
return_ptr_loc,
56
},
57
)
58
.prop_filter("non-overlapping ptrs", |e| {
59
MemArea::non_overlapping_set(&[e.other_config_by_ptr, e.return_ptr_loc])
60
})
61
.boxed()
62
}
63
64
pub fn test(&self) {
65
let mut ctx = WasiCtx::new();
66
let mut host_memory = HostMemory::new();
67
let mut memory = host_memory.guest_memory();
68
69
// Populate input ptr
70
memory
71
.write(
72
GuestPtr::new(self.other_config_by_ptr.ptr),
73
self.other_config,
74
)
75
.expect("deref ptr mut to CarConfig");
76
77
let res = flags::configure_car(
78
&mut ctx,
79
&mut memory,
80
self.old_config.bits() as i32,
81
self.other_config_by_ptr.ptr as i32,
82
self.return_ptr_loc.ptr as i32,
83
)
84
.unwrap();
85
assert_eq!(res, types::Errno::Ok as i32, "configure car errno");
86
87
let res_config = memory
88
.read(GuestPtr::<types::CarConfig>::new(self.return_ptr_loc.ptr))
89
.expect("deref to CarConfig value");
90
91
assert_eq!(
92
self.old_config ^ self.other_config,
93
res_config,
94
"returned CarConfig should be an XOR of inputs"
95
);
96
}
97
}
98
proptest! {
99
#[test]
100
fn configure_car(e in ConfigureCarExercise::strat()) {
101
e.test()
102
}
103
}
104
105
#[test]
106
fn flags_fmt() {
107
let empty = format!("{}", types::CarConfig::empty());
108
assert_eq!(empty, "CarConfig(CarConfig(0x0) (0x0))");
109
let one_flag = format!("{}", types::CarConfig::AWD);
110
assert_eq!(one_flag, "CarConfig(CarConfig(AWD) (0x2))");
111
let two_flags = format!("{}", types::CarConfig::AUTOMATIC | types::CarConfig::SUV);
112
assert_eq!(two_flags, "CarConfig(CarConfig(AUTOMATIC | SUV) (0x5))");
113
let all = format!("{}", types::CarConfig::all());
114
assert_eq!(all, "CarConfig(CarConfig(AUTOMATIC | AWD | SUV) (0x7))");
115
}
116
117