Browse Source

tests: exercise array getters

pull/2160/head
Pat Hickey 4 years ago
parent
commit
776f12ae3c
  1. 9
      crates/wiggle/test-helpers/src/lib.rs
  2. 191
      crates/wiggle/tests/arrays.rs
  3. 19
      crates/wiggle/tests/arrays.witx
  4. 8
      crates/wiggle/tests/strings.rs
  5. 1
      crates/wiggle/tests/structs.rs

9
crates/wiggle/test-helpers/src/lib.rs

@ -102,10 +102,11 @@ impl HostMemory {
out
}
pub fn byte_slice_strat(size: u32, exclude: &MemAreas) -> BoxedStrategy<MemArea> {
pub fn byte_slice_strat(size: u32, align: u32, exclude: &MemAreas) -> BoxedStrategy<MemArea> {
let available: Vec<MemArea> = 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()

191
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<i32, types::Errno> {
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<i32, types::Errno> {
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<Self> {
(prop::num::i32::ANY, prop::num::i32::ANY)
.prop_map(|(first, second)| types::PairInts { first, second })
.boxed()
}
}
#[derive(Debug)]
struct SumElementsExercise {
elements: Vec<types::PairInts>,
element_loc: MemArea,
return_loc: MemArea,
start_ix: u32,
end_ix: u32,
}
impl SumElementsExercise {
pub fn strat() -> BoxedStrategy<Self> {
(
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::<i32>(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::<i32>(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()
}
}

19
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)))

8
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),

1
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()),

Loading…
Cancel
Save