1 use proptest::prelude::*;
2 use std::convert::TryFrom;
3 use wiggle::GuestMemory;
4 use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx};
5
6 wiggle::from_witx!({
7 witx: ["tests/ints.witx"],
8 ctx: WasiCtx,
9 });
10
11 impl_errno!(types::Errno, types::GuestErrorConversion);
12
13 impl<'a> ints::Ints for WasiCtx<'a> {
cookie_cutter(&self, init_cookie: types::Cookie) -> Result<types::Bool, types::Errno>14 fn cookie_cutter(&self, init_cookie: types::Cookie) -> Result<types::Bool, types::Errno> {
15 let res = if init_cookie == types::Cookie::START {
16 types::Bool::True
17 } else {
18 types::Bool::False
19 };
20 Ok(res)
21 }
22 }
23
cookie_strat() -> impl Strategy<Value = types::Cookie>24 fn cookie_strat() -> impl Strategy<Value = types::Cookie> {
25 (0..std::u64::MAX)
26 .prop_map(|x| types::Cookie::try_from(x).expect("within range of cookie"))
27 .boxed()
28 }
29
30 #[derive(Debug)]
31 struct CookieCutterExercise {
32 cookie: types::Cookie,
33 return_ptr_loc: MemArea,
34 }
35
36 impl CookieCutterExercise {
strat() -> BoxedStrategy<Self>37 pub fn strat() -> BoxedStrategy<Self> {
38 (cookie_strat(), HostMemory::mem_area_strat(4))
39 .prop_map(|(cookie, return_ptr_loc)| Self {
40 cookie,
41 return_ptr_loc,
42 })
43 .boxed()
44 }
45
test(&self)46 pub fn test(&self) {
47 let ctx = WasiCtx::new();
48 let host_memory = HostMemory::new();
49
50 let res = ints::cookie_cutter(
51 &ctx,
52 &host_memory,
53 self.cookie.into(),
54 self.return_ptr_loc.ptr as i32,
55 );
56 assert_eq!(res, types::Errno::Ok.into(), "cookie cutter errno");
57
58 let is_cookie_start = host_memory
59 .ptr::<types::Bool>(self.return_ptr_loc.ptr)
60 .read()
61 .expect("deref to Bool value");
62
63 assert_eq!(
64 if is_cookie_start == types::Bool::True {
65 true
66 } else {
67 false
68 },
69 self.cookie == types::Cookie::START,
70 "returned Bool should test if input was Cookie::START",
71 );
72 }
73 }
74 proptest! {
75 #[test]
76 fn cookie_cutter(e in CookieCutterExercise::strat()) {
77 e.test()
78 }
79 }
80