forked from bytecodealliance/wasmtime
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
finish factoring tests (bytecodealliance#17)
* atoms in one test unit * factor out pointers test * factor structs into separate test unit * factor out arrays, flags * finally, separate into strings and ints
- Loading branch information
Showing
19 changed files
with
1,148 additions
and
1,062 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,247 @@ | ||
use proptest::prelude::*; | ||
use wiggle_runtime::{GuestArray, GuestError, GuestPtr, GuestPtrMut}; | ||
use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx}; | ||
|
||
wiggle_generate::from_witx!({ | ||
witx: ["tests/arrays.witx"], | ||
ctx: WasiCtx, | ||
}); | ||
|
||
impl_errno!(types::Errno); | ||
|
||
impl arrays::Arrays for WasiCtx { | ||
fn reduce_excuses( | ||
&mut self, | ||
excuses: &types::ConstExcuseArray, | ||
) -> Result<types::Excuse, types::Errno> { | ||
let last = wiggle_runtime::GuestTypeClone::read_from_guest( | ||
&excuses | ||
.iter() | ||
.last() | ||
.expect("input array is non-empty") | ||
.expect("valid ptr to ptr"), | ||
) | ||
.expect("valid ptr to some Excuse value"); | ||
Ok(*last.as_ref().expect("dereferencing ptr should succeed")) | ||
} | ||
|
||
fn populate_excuses(&mut self, excuses: &types::ExcuseArray) -> Result<(), types::Errno> { | ||
for excuse in excuses.iter() { | ||
let ptr_to_ptr = | ||
wiggle_runtime::GuestTypeClone::read_from_guest(&excuse.expect("valid ptr to ptr")) | ||
.expect("valid ptr to some Excuse value"); | ||
let mut ptr = ptr_to_ptr | ||
.as_ref_mut() | ||
.expect("dereferencing mut ptr should succeed"); | ||
*ptr = types::Excuse::Sleeping; | ||
} | ||
Ok(()) | ||
} | ||
} | ||
|
||
#[derive(Debug)] | ||
struct ReduceExcusesExcercise { | ||
excuse_values: Vec<types::Excuse>, | ||
excuse_ptr_locs: Vec<MemArea>, | ||
array_ptr_loc: MemArea, | ||
array_len_loc: MemArea, | ||
return_ptr_loc: MemArea, | ||
} | ||
|
||
impl ReduceExcusesExcercise { | ||
pub fn strat() -> BoxedStrategy<Self> { | ||
(1..256u32) | ||
.prop_flat_map(|len| { | ||
let len_usize = len as usize; | ||
( | ||
proptest::collection::vec(excuse_strat(), len_usize..=len_usize), | ||
proptest::collection::vec(HostMemory::mem_area_strat(4), len_usize..=len_usize), | ||
HostMemory::mem_area_strat(4 * len), | ||
HostMemory::mem_area_strat(4), | ||
HostMemory::mem_area_strat(4), | ||
) | ||
}) | ||
.prop_map( | ||
|(excuse_values, excuse_ptr_locs, array_ptr_loc, array_len_loc, return_ptr_loc)| { | ||
Self { | ||
excuse_values, | ||
excuse_ptr_locs, | ||
array_ptr_loc, | ||
array_len_loc, | ||
return_ptr_loc, | ||
} | ||
}, | ||
) | ||
.prop_filter("non-overlapping pointers", |e| { | ||
let mut all = vec![&e.array_ptr_loc, &e.array_len_loc, &e.return_ptr_loc]; | ||
all.extend(e.excuse_ptr_locs.iter()); | ||
MemArea::non_overlapping_set(&all) | ||
}) | ||
.boxed() | ||
} | ||
|
||
pub fn test(&self) { | ||
let mut ctx = WasiCtx::new(); | ||
let mut host_memory = HostMemory::new(); | ||
let mut guest_memory = host_memory.guest_memory(); | ||
|
||
// Populate memory with pointers to generated Excuse values | ||
for (&excuse, ptr) in self.excuse_values.iter().zip(self.excuse_ptr_locs.iter()) { | ||
*guest_memory | ||
.ptr_mut(ptr.ptr) | ||
.expect("ptr mut to Excuse value") | ||
.as_ref_mut() | ||
.expect("deref ptr mut to Excuse value") = excuse; | ||
} | ||
|
||
// Populate array length info | ||
*guest_memory | ||
.ptr_mut(self.array_len_loc.ptr) | ||
.expect("ptr to array len") | ||
.as_ref_mut() | ||
.expect("deref ptr mut to array len") = self.excuse_ptr_locs.len() as u32; | ||
|
||
// Populate the array with pointers to generated Excuse values | ||
{ | ||
let mut next: GuestPtrMut<'_, GuestPtr<types::Excuse>> = guest_memory | ||
.ptr_mut(self.array_ptr_loc.ptr) | ||
.expect("ptr to array mut"); | ||
for ptr in &self.excuse_ptr_locs { | ||
next.write_ptr_to_guest( | ||
&guest_memory | ||
.ptr::<types::Excuse>(ptr.ptr) | ||
.expect("ptr to Excuse value"), | ||
); | ||
next = next.elem(1).expect("increment ptr by 1"); | ||
} | ||
} | ||
|
||
let res = arrays::reduce_excuses( | ||
&mut ctx, | ||
&mut guest_memory, | ||
self.array_ptr_loc.ptr as i32, | ||
self.array_len_loc.ptr as i32, | ||
self.return_ptr_loc.ptr as i32, | ||
); | ||
|
||
assert_eq!(res, types::Errno::Ok.into(), "reduce excuses errno"); | ||
|
||
let expected = *self | ||
.excuse_values | ||
.last() | ||
.expect("generated vec of excuses should be non-empty"); | ||
let given: types::Excuse = *guest_memory | ||
.ptr(self.return_ptr_loc.ptr) | ||
.expect("ptr to returned value") | ||
.as_ref() | ||
.expect("deref ptr to returned value"); | ||
assert_eq!(expected, given, "reduce excuses return val"); | ||
} | ||
} | ||
proptest! { | ||
#[test] | ||
fn reduce_excuses(e in ReduceExcusesExcercise::strat()) { | ||
e.test() | ||
} | ||
} | ||
|
||
fn excuse_strat() -> impl Strategy<Value = types::Excuse> { | ||
prop_oneof![ | ||
Just(types::Excuse::DogAte), | ||
Just(types::Excuse::Traffic), | ||
Just(types::Excuse::Sleeping), | ||
] | ||
.boxed() | ||
} | ||
|
||
#[derive(Debug)] | ||
struct PopulateExcusesExcercise { | ||
array_ptr_loc: MemArea, | ||
array_len_loc: MemArea, | ||
elements: Vec<MemArea>, | ||
} | ||
|
||
impl PopulateExcusesExcercise { | ||
pub fn strat() -> BoxedStrategy<Self> { | ||
(1..256u32) | ||
.prop_flat_map(|len| { | ||
let len_usize = len as usize; | ||
( | ||
HostMemory::mem_area_strat(4 * len), | ||
HostMemory::mem_area_strat(4), | ||
proptest::collection::vec(HostMemory::mem_area_strat(4), len_usize..=len_usize), | ||
) | ||
}) | ||
.prop_map(|(array_ptr_loc, array_len_loc, elements)| Self { | ||
array_ptr_loc, | ||
array_len_loc, | ||
elements, | ||
}) | ||
.prop_filter("non-overlapping pointers", |e| { | ||
let mut all = vec![&e.array_ptr_loc, &e.array_len_loc]; | ||
all.extend(e.elements.iter()); | ||
MemArea::non_overlapping_set(&all) | ||
}) | ||
.boxed() | ||
} | ||
|
||
pub fn test(&self) { | ||
let mut ctx = WasiCtx::new(); | ||
let mut host_memory = HostMemory::new(); | ||
let mut guest_memory = host_memory.guest_memory(); | ||
|
||
// Populate array length info | ||
*guest_memory | ||
.ptr_mut(self.array_len_loc.ptr) | ||
.expect("ptr mut to array len") | ||
.as_ref_mut() | ||
.expect("deref ptr mut to array len") = self.elements.len() as u32; | ||
|
||
// Populate array with valid pointers to Excuse type in memory | ||
{ | ||
let mut next: GuestPtrMut<'_, GuestPtrMut<types::Excuse>> = guest_memory | ||
.ptr_mut(self.array_ptr_loc.ptr) | ||
.expect("ptr mut to the first element of array"); | ||
for ptr in &self.elements { | ||
next.write_ptr_to_guest( | ||
&guest_memory | ||
.ptr_mut::<types::Excuse>(ptr.ptr) | ||
.expect("ptr mut to Excuse value"), | ||
); | ||
next = next.elem(1).expect("increment ptr by 1"); | ||
} | ||
} | ||
|
||
let res = arrays::populate_excuses( | ||
&mut ctx, | ||
&mut guest_memory, | ||
self.array_ptr_loc.ptr as i32, | ||
self.array_len_loc.ptr as i32, | ||
); | ||
assert_eq!(res, types::Errno::Ok.into(), "populate excuses errno"); | ||
|
||
let arr: GuestArray<'_, GuestPtr<'_, types::Excuse>> = guest_memory | ||
.ptr(self.array_ptr_loc.ptr) | ||
.expect("ptr to the first element of array") | ||
.array(self.elements.len() as u32) | ||
.expect("as array"); | ||
for el in arr.iter() { | ||
let ptr_to_ptr = | ||
wiggle_runtime::GuestTypeClone::read_from_guest(&el.expect("valid ptr to ptr")) | ||
.expect("valid ptr to some Excuse value"); | ||
assert_eq!( | ||
*ptr_to_ptr | ||
.as_ref() | ||
.expect("dereferencing ptr to some Excuse value"), | ||
types::Excuse::Sleeping, | ||
"element should equal Excuse::Sleeping" | ||
); | ||
} | ||
} | ||
} | ||
proptest! { | ||
#[test] | ||
fn populate_excuses(e in PopulateExcusesExcercise::strat()) { | ||
e.test() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
(use "errno.witx") | ||
(use "excuse.witx") | ||
|
||
(typename $const_excuse_array (array (@witx const_pointer $excuse))) | ||
(typename $excuse_array (array (@witx pointer $excuse))) | ||
|
||
(module $arrays | ||
(@interface func (export "reduce_excuses") | ||
(param $excuses $const_excuse_array) | ||
(result $error $errno) | ||
(result $reduced $excuse) | ||
) | ||
(@interface func (export "populate_excuses") | ||
(param $excuses $excuse_array) | ||
(result $error $errno) | ||
) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
use proptest::prelude::*; | ||
use wiggle_runtime::{GuestError, GuestRef}; | ||
use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx}; | ||
|
||
wiggle_generate::from_witx!({ | ||
witx: ["tests/atoms.witx"], | ||
ctx: WasiCtx, | ||
}); | ||
|
||
impl_errno!(types::Errno); | ||
|
||
impl atoms::Atoms for WasiCtx { | ||
fn int_float_args(&mut self, an_int: u32, an_float: f32) -> Result<(), types::Errno> { | ||
println!("INT FLOAT ARGS: {} {}", an_int, an_float); | ||
Ok(()) | ||
} | ||
fn double_int_return_float(&mut self, an_int: u32) -> Result<f32, types::Errno> { | ||
Ok((an_int as f32) * 2.0) | ||
} | ||
} | ||
|
||
// There's nothing meaningful to test here - this just demonstrates the test machinery | ||
|
||
#[derive(Debug)] | ||
struct IntFloatExercise { | ||
pub an_int: u32, | ||
pub an_float: f32, | ||
} | ||
|
||
impl IntFloatExercise { | ||
pub fn test(&self) { | ||
let mut ctx = WasiCtx::new(); | ||
let mut host_memory = HostMemory::new(); | ||
let mut guest_memory = host_memory.guest_memory(); | ||
|
||
let e = atoms::int_float_args( | ||
&mut ctx, | ||
&mut guest_memory, | ||
self.an_int as i32, | ||
self.an_float, | ||
); | ||
|
||
assert_eq!(e, types::Errno::Ok.into(), "int_float_args error"); | ||
} | ||
|
||
pub fn strat() -> BoxedStrategy<Self> { | ||
(prop::num::u32::ANY, prop::num::f32::ANY) | ||
.prop_map(|(an_int, an_float)| IntFloatExercise { an_int, an_float }) | ||
.boxed() | ||
} | ||
} | ||
|
||
proptest! { | ||
#[test] | ||
fn int_float_exercise(e in IntFloatExercise::strat()) { | ||
e.test() | ||
} | ||
} | ||
#[derive(Debug)] | ||
struct DoubleIntExercise { | ||
pub input: u32, | ||
pub return_loc: MemArea, | ||
} | ||
|
||
impl DoubleIntExercise { | ||
pub fn test(&self) { | ||
let mut ctx = WasiCtx::new(); | ||
let mut host_memory = HostMemory::new(); | ||
let mut guest_memory = host_memory.guest_memory(); | ||
|
||
let e = atoms::double_int_return_float( | ||
&mut ctx, | ||
&mut guest_memory, | ||
self.input as i32, | ||
self.return_loc.ptr as i32, | ||
); | ||
|
||
let return_val: GuestRef<f32> = guest_memory | ||
.ptr(self.return_loc.ptr) | ||
.expect("return loc ptr") | ||
.as_ref() | ||
.expect("return val ref"); | ||
assert_eq!(e, types::Errno::Ok.into(), "errno"); | ||
assert_eq!(*return_val, (self.input as f32) * 2.0, "return val"); | ||
} | ||
|
||
pub fn strat() -> BoxedStrategy<Self> { | ||
(prop::num::u32::ANY, HostMemory::mem_area_strat(4)) | ||
.prop_map(|(input, return_loc)| DoubleIntExercise { input, return_loc }) | ||
.boxed() | ||
} | ||
} | ||
|
||
proptest! { | ||
#[test] | ||
fn double_int_return_float(e in DoubleIntExercise::strat()) { | ||
e.test() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
(use "errno.witx") | ||
|
||
(module $atoms | ||
(@interface func (export "int_float_args") | ||
(param $an_int u32) | ||
(param $an_float f32) | ||
(result $error $errno)) | ||
(@interface func (export "double_int_return_float") | ||
(param $an_int u32) | ||
(result $error $errno) | ||
(result $doubled_it f32)) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
(typename $excuse | ||
(enum u8 | ||
$dog_ate | ||
$traffic | ||
$sleeping)) | ||
|
Oops, something went wrong.