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