From 776f12ae3c0c21e8cda0b7c251c998d35ef0a1c0 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Thu, 3 Sep 2020 16:41:10 -0700 Subject: [PATCH] tests: exercise array getters --- crates/wiggle/test-helpers/src/lib.rs | 9 +- crates/wiggle/tests/arrays.rs | 191 +++++++++++++++++++++++++- crates/wiggle/tests/arrays.witx | 19 +++ crates/wiggle/tests/strings.rs | 8 +- crates/wiggle/tests/structs.rs | 1 + 5 files changed, 221 insertions(+), 7 deletions(-) diff --git a/crates/wiggle/test-helpers/src/lib.rs b/crates/wiggle/test-helpers/src/lib.rs index 7c9f8840ef..6164e4f92f 100644 --- a/crates/wiggle/test-helpers/src/lib.rs +++ b/crates/wiggle/test-helpers/src/lib.rs @@ -102,10 +102,11 @@ impl HostMemory { out } - pub fn byte_slice_strat(size: u32, exclude: &MemAreas) -> BoxedStrategy { + pub fn byte_slice_strat(size: u32, align: u32, exclude: &MemAreas) -> BoxedStrategy { let available: Vec = Self::invert(exclude) .iter() .flat_map(|a| a.inside(size)) + .filter(|a| a.ptr % align == 0) .collect(); Just(available) @@ -256,18 +257,18 @@ mod test { s2: u32, s3: u32, ) -> BoxedStrategy<(MemArea, MemArea, MemArea)> { - HostMemory::byte_slice_strat(s1, &MemAreas::new()) + HostMemory::byte_slice_strat(s1, 1, &MemAreas::new()) .prop_flat_map(move |a1| { ( Just(a1), - HostMemory::byte_slice_strat(s2, &MemAreas::from(&[a1])), + HostMemory::byte_slice_strat(s2, 1, &MemAreas::from(&[a1])), ) }) .prop_flat_map(move |(a1, a2)| { ( Just(a1), Just(a2), - HostMemory::byte_slice_strat(s3, &MemAreas::from(&[a1, a2])), + HostMemory::byte_slice_strat(s3, 1, &MemAreas::from(&[a1, a2])), ) }) .boxed() diff --git a/crates/wiggle/tests/arrays.rs b/crates/wiggle/tests/arrays.rs index 9bfad46e7b..5f660fce69 100644 --- a/crates/wiggle/tests/arrays.rs +++ b/crates/wiggle/tests/arrays.rs @@ -1,6 +1,6 @@ use proptest::prelude::*; -use wiggle::{GuestMemory, GuestPtr}; -use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx}; +use wiggle::{GuestMemory, GuestPtr, GuestType}; +use wiggle_test::{impl_errno, HostMemory, MemArea, MemAreas, WasiCtx}; wiggle::from_witx!({ witx: ["$CARGO_MANIFEST_DIR/tests/arrays.witx"], @@ -208,3 +208,190 @@ proptest! { e.test() } } + +impl<'a> array_traversal::ArrayTraversal for WasiCtx<'a> { + fn sum_of_element( + &self, + elements: &GuestPtr<[types::PairInts]>, + index: u32, + ) -> Result { + let elem_ptr = elements.get(index).ok_or(types::Errno::InvalidArg)?; + let pair = elem_ptr.read().map_err(|_| types::Errno::DontWantTo)?; + Ok(pair.first.wrapping_add(pair.second)) + } + fn sum_of_elements( + &self, + elements: &GuestPtr<[types::PairInts]>, + start: u32, + end: u32, + ) -> Result { + let elem_range = elements + .get_range(start..end) + .ok_or(types::Errno::InvalidArg)?; + let mut sum: i32 = 0; + for e in elem_range.iter() { + let pair = e + .map_err(|_| types::Errno::DontWantTo)? + .read() + .map_err(|_| types::Errno::PhysicallyUnable)?; + sum = sum.wrapping_add(pair.first).wrapping_add(pair.second); + } + Ok(sum) + } +} + +impl types::PairInts { + pub fn strat() -> BoxedStrategy { + (prop::num::i32::ANY, prop::num::i32::ANY) + .prop_map(|(first, second)| types::PairInts { first, second }) + .boxed() + } +} + +#[derive(Debug)] +struct SumElementsExercise { + elements: Vec, + element_loc: MemArea, + return_loc: MemArea, + start_ix: u32, + end_ix: u32, +} + +impl SumElementsExercise { + pub fn strat() -> BoxedStrategy { + ( + prop::collection::vec(types::PairInts::strat(), 1..256), + HostMemory::mem_area_strat(4), + ) + .prop_flat_map(|(elements, return_loc)| { + let len = elements.len() as u32; + ( + Just(elements), + HostMemory::byte_slice_strat( + len * types::PairInts::guest_size(), + types::PairInts::guest_size(), + &MemAreas::from([return_loc]), + ), + Just(return_loc), + 0..len, + 0..len, + ) + }) + .prop_map( + |(elements, element_loc, return_loc, start_ix, end_ix)| SumElementsExercise { + elements, + element_loc, + return_loc, + start_ix, + end_ix, + }, + ) + .boxed() + } + pub fn test(&self) { + let ctx = WasiCtx::new(); + let host_memory = HostMemory::new(); + + // Populate array + let ptr = host_memory + .ptr::<[types::PairInts]>((self.element_loc.ptr, self.elements.len() as u32)); + for (ptr, val) in ptr.iter().zip(&self.elements) { + ptr.expect("should be valid pointer") + .write(val.clone()) + .expect("failed to write value"); + } + + let res = array_traversal::sum_of_element( + &ctx, + &host_memory, + self.element_loc.ptr as i32, + self.elements.len() as i32, + self.start_ix as i32, + self.return_loc.ptr as i32, + ); + assert_eq!(res, types::Errno::Ok.into(), "sum_of_element errno"); + let result_ptr = host_memory.ptr::(self.return_loc.ptr); + let result = result_ptr.read().expect("read result"); + + let e = self + .elements + .get(self.start_ix as usize) + .expect("start_ix must be in bounds"); + assert_eq!(result, e.first.wrapping_add(e.second), "sum of element"); + + // Off the end of the array: + let res = array_traversal::sum_of_element( + &ctx, + &host_memory, + self.element_loc.ptr as i32, + self.elements.len() as i32, + self.elements.len() as i32, + self.return_loc.ptr as i32, + ); + assert_eq!( + res, + types::Errno::InvalidArg.into(), + "out of bounds sum_of_element errno" + ); + + let res = array_traversal::sum_of_elements( + &ctx, + &host_memory, + self.element_loc.ptr as i32, + self.elements.len() as i32, + self.start_ix as i32, + self.end_ix as i32, + self.return_loc.ptr as i32, + ); + if self.start_ix <= self.end_ix { + assert_eq!( + res, + types::Errno::Ok.into(), + "expected ok sum_of_elements errno" + ); + let result_ptr = host_memory.ptr::(self.return_loc.ptr); + let result = result_ptr.read().expect("read result"); + + let mut expected_sum: i32 = 0; + for elem in self + .elements + .get(self.start_ix as usize..self.end_ix as usize) + .unwrap() + .iter() + { + expected_sum = expected_sum + .wrapping_add(elem.first) + .wrapping_add(elem.second); + } + assert_eq!(result, expected_sum, "sum of elements"); + } else { + assert_eq!( + res, + types::Errno::InvalidArg.into(), + "expected error out-of-bounds sum_of_elements" + ); + } + + // Index an array off the end of the array: + let res = array_traversal::sum_of_elements( + &ctx, + &host_memory, + self.element_loc.ptr as i32, + self.elements.len() as i32, + self.start_ix as i32, + self.elements.len() as i32 + 1, + self.return_loc.ptr as i32, + ); + assert_eq!( + res, + types::Errno::InvalidArg.into(), + "out of bounds sum_of_elements errno" + ); + } +} +proptest! { + #[test] + fn sum_elements(e in SumElementsExercise::strat()) { + e.test() + } +} diff --git a/crates/wiggle/tests/arrays.witx b/crates/wiggle/tests/arrays.witx index e8a81cee95..4b6a1f14c5 100644 --- a/crates/wiggle/tests/arrays.witx +++ b/crates/wiggle/tests/arrays.witx @@ -15,3 +15,22 @@ (result $error $errno) ) ) + +(typename $pair_ints + (struct + (field $first s32) + (field $second s32))) + +(module $array_traversal + (@interface func (export "sum_of_element") + (param $elements (array $pair_ints)) + (param $index (@witx usize)) + (result $error $errno) + (result $sum s32)) + + (@interface func (export "sum_of_elements") + (param $elements (array $pair_ints)) + (param $start (@witx usize)) + (param $end (@witx usize)) + (result $error $errno) + (result $sum s32))) diff --git a/crates/wiggle/tests/strings.rs b/crates/wiggle/tests/strings.rs index e68a569ed6..cff55d92d0 100644 --- a/crates/wiggle/tests/strings.rs +++ b/crates/wiggle/tests/strings.rs @@ -125,7 +125,11 @@ impl MultiStringExercise { Just(a.clone()), Just(b.clone()), Just(c.clone()), - HostMemory::byte_slice_strat(a.len() as u32, &MemAreas::from([return_ptr_loc])), + HostMemory::byte_slice_strat( + a.len() as u32, + 1, + &MemAreas::from([return_ptr_loc]), + ), Just(return_ptr_loc), ) }) @@ -137,6 +141,7 @@ impl MultiStringExercise { Just(sa_ptr_loc), HostMemory::byte_slice_strat( b.len() as u32, + 1, &MemAreas::from([sa_ptr_loc, return_ptr_loc]), ), Just(return_ptr_loc), @@ -151,6 +156,7 @@ impl MultiStringExercise { Just(sb_ptr_loc), HostMemory::byte_slice_strat( c.len() as u32, + 1, &MemAreas::from([sa_ptr_loc, sb_ptr_loc, return_ptr_loc]), ), Just(return_ptr_loc), diff --git a/crates/wiggle/tests/structs.rs b/crates/wiggle/tests/structs.rs index ad2e43a2db..27b7b865c1 100644 --- a/crates/wiggle/tests/structs.rs +++ b/crates/wiggle/tests/structs.rs @@ -473,6 +473,7 @@ impl SumArrayExercise { Just(inputs.clone()), HostMemory::byte_slice_strat( inputs.len() as u32, + 1, &MemAreas::from([input_struct_loc, output_loc]), ), Just(input_struct_loc.clone()),