Path: blob/main/crates/wiggle/tests/atoms_async.rs
1692 views
use proptest::prelude::*;1use std::future::Future;2use std::pin::Pin;3use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};4use wiggle::{GuestMemory, GuestPtr};5use wiggle_test::{HostMemory, MemArea, WasiCtx, impl_errno};67wiggle::from_witx!({8witx: ["tests/atoms.witx"],9async: *,10});1112impl_errno!(types::Errno);1314#[wiggle::async_trait]15impl<'a> atoms::Atoms for WasiCtx<'a> {16async fn int_float_args(17&mut self,18_memory: &mut GuestMemory<'_>,19an_int: u32,20an_float: f32,21) -> Result<(), types::Errno> {22println!("INT FLOAT ARGS: {an_int} {an_float}");23Ok(())24}25async fn double_int_return_float(26&mut self,27_memory: &mut GuestMemory<'_>,28an_int: u32,29) -> Result<types::AliasToFloat, types::Errno> {30Ok((an_int as f32) * 2.0)31}32}3334// There's nothing meaningful to test here - this just demonstrates the test machinery3536#[derive(Debug)]37struct IntFloatExercise {38pub an_int: u32,39pub an_float: f32,40}4142impl IntFloatExercise {43pub fn test(&self) {44let mut ctx = WasiCtx::new();45let mut host_memory = HostMemory::new();46let mut memory = host_memory.guest_memory();4748let e = run(atoms::int_float_args(49&mut ctx,50&mut memory,51self.an_int as i32,52self.an_float,53))54.unwrap();5556assert_eq!(e, types::Errno::Ok as i32, "int_float_args error");57}5859pub fn strat() -> BoxedStrategy<Self> {60(prop::num::u32::ANY, prop::num::f32::ANY)61.prop_map(|(an_int, an_float)| IntFloatExercise { an_int, an_float })62.boxed()63}64}6566proptest! {67#[test]68fn int_float_exercise(e in IntFloatExercise::strat()) {69e.test()70}71}72#[derive(Debug)]73struct DoubleIntExercise {74pub input: u32,75pub return_loc: MemArea,76}7778impl DoubleIntExercise {79pub fn test(&self) {80let mut ctx = WasiCtx::new();81let mut host_memory = HostMemory::new();82let mut memory = host_memory.guest_memory();8384let e = run(atoms::double_int_return_float(85&mut ctx,86&mut memory,87self.input as i32,88self.return_loc.ptr as i32,89))90.unwrap();9192let return_val = memory93.read(GuestPtr::<types::AliasToFloat>::new(self.return_loc.ptr))94.expect("failed to read return");95assert_eq!(e, types::Errno::Ok as i32, "errno");96assert_eq!(return_val, (self.input as f32) * 2.0, "return val");97}9899pub fn strat() -> BoxedStrategy<Self> {100(prop::num::u32::ANY, HostMemory::mem_area_strat(4))101.prop_map(|(input, return_loc)| DoubleIntExercise { input, return_loc })102.boxed()103}104}105106proptest! {107#[test]108fn double_int_return_float(e in DoubleIntExercise::strat()) {109e.test()110}111}112113fn run<F: Future>(future: F) -> F::Output {114let mut f = Pin::from(Box::new(future));115let waker = dummy_waker();116let mut cx = Context::from_waker(&waker);117loop {118match f.as_mut().poll(&mut cx) {119Poll::Ready(val) => break val,120Poll::Pending => {}121}122}123}124125fn dummy_waker() -> Waker {126return unsafe { Waker::from_raw(clone(5 as *const _)) };127128unsafe fn clone(ptr: *const ()) -> RawWaker {129assert_eq!(ptr as usize, 5);130const VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop);131RawWaker::new(ptr, &VTABLE)132}133134unsafe fn wake(ptr: *const ()) {135assert_eq!(ptr as usize, 5);136}137138unsafe fn wake_by_ref(ptr: *const ()) {139assert_eq!(ptr as usize, 5);140}141142unsafe fn drop(ptr: *const ()) {143assert_eq!(ptr as usize, 5);144}145}146147148