Path: blob/main/crates/wiggle/tests/atoms_async.rs
3101 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);1314impl<'a> atoms::Atoms for WasiCtx<'a> {15async fn int_float_args(16&mut self,17_memory: &mut GuestMemory<'_>,18an_int: u32,19an_float: f32,20) -> Result<(), types::Errno> {21println!("INT FLOAT ARGS: {an_int} {an_float}");22Ok(())23}24async fn double_int_return_float(25&mut self,26_memory: &mut GuestMemory<'_>,27an_int: u32,28) -> Result<types::AliasToFloat, types::Errno> {29Ok((an_int as f32) * 2.0)30}31}3233// There's nothing meaningful to test here - this just demonstrates the test machinery3435#[derive(Debug)]36struct IntFloatExercise {37pub an_int: u32,38pub an_float: f32,39}4041impl IntFloatExercise {42pub fn test(&self) {43let mut ctx = WasiCtx::new();44let mut host_memory = HostMemory::new();45let mut memory = host_memory.guest_memory();4647let e = run(atoms::int_float_args(48&mut ctx,49&mut memory,50self.an_int as i32,51self.an_float,52))53.unwrap();5455assert_eq!(e, types::Errno::Ok as i32, "int_float_args error");56}5758pub fn strat() -> BoxedStrategy<Self> {59(prop::num::u32::ANY, prop::num::f32::ANY)60.prop_map(|(an_int, an_float)| IntFloatExercise { an_int, an_float })61.boxed()62}63}6465proptest! {66#[test]67fn int_float_exercise(e in IntFloatExercise::strat()) {68e.test()69}70}71#[derive(Debug)]72struct DoubleIntExercise {73pub input: u32,74pub return_loc: MemArea,75}7677impl DoubleIntExercise {78pub fn test(&self) {79let mut ctx = WasiCtx::new();80let mut host_memory = HostMemory::new();81let mut memory = host_memory.guest_memory();8283let e = run(atoms::double_int_return_float(84&mut ctx,85&mut memory,86self.input as i32,87self.return_loc.ptr as i32,88))89.unwrap();9091let return_val = memory92.read(GuestPtr::<types::AliasToFloat>::new(self.return_loc.ptr))93.expect("failed to read return");94assert_eq!(e, types::Errno::Ok as i32, "errno");95assert_eq!(return_val, (self.input as f32) * 2.0, "return val");96}9798pub fn strat() -> BoxedStrategy<Self> {99(prop::num::u32::ANY, HostMemory::mem_area_strat(4))100.prop_map(|(input, return_loc)| DoubleIntExercise { input, return_loc })101.boxed()102}103}104105proptest! {106#[test]107fn double_int_return_float(e in DoubleIntExercise::strat()) {108e.test()109}110}111112fn run<F: Future>(future: F) -> F::Output {113let mut f = Pin::from(Box::new(future));114let waker = dummy_waker();115let mut cx = Context::from_waker(&waker);116loop {117match f.as_mut().poll(&mut cx) {118Poll::Ready(val) => break val,119Poll::Pending => {}120}121}122}123124fn dummy_waker() -> Waker {125return unsafe { Waker::from_raw(clone(5 as *const _)) };126127unsafe fn clone(ptr: *const ()) -> RawWaker {128assert_eq!(ptr as usize, 5);129const VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop);130RawWaker::new(ptr, &VTABLE)131}132133unsafe fn wake(ptr: *const ()) {134assert_eq!(ptr as usize, 5);135}136137unsafe fn wake_by_ref(ptr: *const ()) {138assert_eq!(ptr as usize, 5);139}140141unsafe fn drop(ptr: *const ()) {142assert_eq!(ptr as usize, 5);143}144}145146147