tests: exercise array getters
This commit is contained in:
@@ -102,10 +102,11 @@ impl HostMemory {
|
|||||||
out
|
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)
|
let available: Vec<MemArea> = Self::invert(exclude)
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|a| a.inside(size))
|
.flat_map(|a| a.inside(size))
|
||||||
|
.filter(|a| a.ptr % align == 0)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Just(available)
|
Just(available)
|
||||||
@@ -256,18 +257,18 @@ mod test {
|
|||||||
s2: u32,
|
s2: u32,
|
||||||
s3: u32,
|
s3: u32,
|
||||||
) -> BoxedStrategy<(MemArea, MemArea, MemArea)> {
|
) -> BoxedStrategy<(MemArea, MemArea, MemArea)> {
|
||||||
HostMemory::byte_slice_strat(s1, &MemAreas::new())
|
HostMemory::byte_slice_strat(s1, 1, &MemAreas::new())
|
||||||
.prop_flat_map(move |a1| {
|
.prop_flat_map(move |a1| {
|
||||||
(
|
(
|
||||||
Just(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)| {
|
.prop_flat_map(move |(a1, a2)| {
|
||||||
(
|
(
|
||||||
Just(a1),
|
Just(a1),
|
||||||
Just(a2),
|
Just(a2),
|
||||||
HostMemory::byte_slice_strat(s3, &MemAreas::from(&[a1, a2])),
|
HostMemory::byte_slice_strat(s3, 1, &MemAreas::from(&[a1, a2])),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.boxed()
|
.boxed()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use proptest::prelude::*;
|
use proptest::prelude::*;
|
||||||
use wiggle::{GuestMemory, GuestPtr};
|
use wiggle::{GuestMemory, GuestPtr, GuestType};
|
||||||
use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx};
|
use wiggle_test::{impl_errno, HostMemory, MemArea, MemAreas, WasiCtx};
|
||||||
|
|
||||||
wiggle::from_witx!({
|
wiggle::from_witx!({
|
||||||
witx: ["$CARGO_MANIFEST_DIR/tests/arrays.witx"],
|
witx: ["$CARGO_MANIFEST_DIR/tests/arrays.witx"],
|
||||||
@@ -208,3 +208,190 @@ proptest! {
|
|||||||
e.test()
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,3 +15,22 @@
|
|||||||
(result $error $errno)
|
(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)))
|
||||||
|
|||||||
@@ -125,7 +125,11 @@ impl MultiStringExercise {
|
|||||||
Just(a.clone()),
|
Just(a.clone()),
|
||||||
Just(b.clone()),
|
Just(b.clone()),
|
||||||
Just(c.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),
|
Just(return_ptr_loc),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -137,6 +141,7 @@ impl MultiStringExercise {
|
|||||||
Just(sa_ptr_loc),
|
Just(sa_ptr_loc),
|
||||||
HostMemory::byte_slice_strat(
|
HostMemory::byte_slice_strat(
|
||||||
b.len() as u32,
|
b.len() as u32,
|
||||||
|
1,
|
||||||
&MemAreas::from([sa_ptr_loc, return_ptr_loc]),
|
&MemAreas::from([sa_ptr_loc, return_ptr_loc]),
|
||||||
),
|
),
|
||||||
Just(return_ptr_loc),
|
Just(return_ptr_loc),
|
||||||
@@ -151,6 +156,7 @@ impl MultiStringExercise {
|
|||||||
Just(sb_ptr_loc),
|
Just(sb_ptr_loc),
|
||||||
HostMemory::byte_slice_strat(
|
HostMemory::byte_slice_strat(
|
||||||
c.len() as u32,
|
c.len() as u32,
|
||||||
|
1,
|
||||||
&MemAreas::from([sa_ptr_loc, sb_ptr_loc, return_ptr_loc]),
|
&MemAreas::from([sa_ptr_loc, sb_ptr_loc, return_ptr_loc]),
|
||||||
),
|
),
|
||||||
Just(return_ptr_loc),
|
Just(return_ptr_loc),
|
||||||
|
|||||||
@@ -473,6 +473,7 @@ impl SumArrayExercise {
|
|||||||
Just(inputs.clone()),
|
Just(inputs.clone()),
|
||||||
HostMemory::byte_slice_strat(
|
HostMemory::byte_slice_strat(
|
||||||
inputs.len() as u32,
|
inputs.len() as u32,
|
||||||
|
1,
|
||||||
&MemAreas::from([input_struct_loc, output_loc]),
|
&MemAreas::from([input_struct_loc, output_loc]),
|
||||||
),
|
),
|
||||||
Just(input_struct_loc.clone()),
|
Just(input_struct_loc.clone()),
|
||||||
|
|||||||
Reference in New Issue
Block a user