Merge pull request #16 from kubkon/pch/factor_tests
Start factoring tests
This commit is contained in:
@@ -9,11 +9,13 @@ wiggle-generate = { path = "crates/generate" }
|
|||||||
wiggle-runtime = { path = "crates/runtime" }
|
wiggle-runtime = { path = "crates/runtime" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
wiggle-test = { path = "crates/test" }
|
||||||
proptest = "0.9"
|
proptest = "0.9"
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
"crates/generate",
|
"crates/generate",
|
||||||
"crates/runtime"
|
"crates/runtime",
|
||||||
|
"crates/test",
|
||||||
]
|
]
|
||||||
exclude = ["crates/WASI"]
|
exclude = ["crates/WASI"]
|
||||||
|
|||||||
2
crates/test/.gitignore
vendored
Normal file
2
crates/test/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
target
|
||||||
|
Cargo.lock
|
||||||
9
crates/test/Cargo.toml
Normal file
9
crates/test/Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[package]
|
||||||
|
name = "wiggle-test"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Pat Hickey <phickey@fastly.com>", "Jakub Konka <kubkon@jakubkonka.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
wiggle-runtime = { path = "../runtime" }
|
||||||
|
proptest = "0.9"
|
||||||
127
crates/test/src/lib.rs
Normal file
127
crates/test/src/lib.rs
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
use proptest::prelude::*;
|
||||||
|
use wiggle_runtime::GuestMemory;
|
||||||
|
|
||||||
|
#[repr(align(4096))]
|
||||||
|
pub struct HostMemory {
|
||||||
|
buffer: [u8; 4096],
|
||||||
|
}
|
||||||
|
impl HostMemory {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
HostMemory { buffer: [0; 4096] }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn guest_memory<'a>(&'a mut self) -> GuestMemory<'a> {
|
||||||
|
GuestMemory::new(self.buffer.as_mut_ptr(), self.buffer.len() as u32)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mem_area_strat(align: u32) -> BoxedStrategy<MemArea> {
|
||||||
|
prop::num::u32::ANY
|
||||||
|
.prop_filter_map("needs to fit in memory", move |p| {
|
||||||
|
let p_aligned = p - (p % align); // Align according to argument
|
||||||
|
let ptr = p_aligned % 4096; // Put inside memory
|
||||||
|
if ptr + align < 4096 {
|
||||||
|
Some(MemArea { ptr, len: align })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.boxed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct MemArea {
|
||||||
|
pub ptr: u32,
|
||||||
|
pub len: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MemArea {
|
||||||
|
// This code is a whole lot like the Region::overlaps func thats at the core of the code under
|
||||||
|
// test.
|
||||||
|
// So, I implemented this one with std::ops::Range so it is less likely I wrote the same bug in two
|
||||||
|
// places.
|
||||||
|
pub fn overlapping(&self, b: &Self) -> bool {
|
||||||
|
// a_range is all elems in A
|
||||||
|
let a_range = std::ops::Range {
|
||||||
|
start: self.ptr,
|
||||||
|
end: self.ptr + self.len, // std::ops::Range is open from the right
|
||||||
|
};
|
||||||
|
// b_range is all elems in B
|
||||||
|
let b_range = std::ops::Range {
|
||||||
|
start: b.ptr,
|
||||||
|
end: b.ptr + b.len,
|
||||||
|
};
|
||||||
|
// No element in B is contained in A:
|
||||||
|
for b_elem in b_range.clone() {
|
||||||
|
if a_range.contains(&b_elem) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// No element in A is contained in B:
|
||||||
|
for a_elem in a_range {
|
||||||
|
if b_range.contains(&a_elem) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pub fn non_overlapping_set(areas: &[&Self]) -> bool {
|
||||||
|
// A is all areas
|
||||||
|
for (i, a) in areas.iter().enumerate() {
|
||||||
|
// (A, B) is every pair of areas
|
||||||
|
for b in areas[i + 1..].iter() {
|
||||||
|
if a.overlapping(b) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
#[test]
|
||||||
|
fn hostmemory_is_aligned() {
|
||||||
|
let mut h = HostMemory::new();
|
||||||
|
assert_eq!(h.buffer.as_mut_ptr() as usize % 4096, 0);
|
||||||
|
let mut h = Box::new(HostMemory::new());
|
||||||
|
assert_eq!(h.buffer.as_mut_ptr() as usize % 4096, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
use wiggle_runtime::GuestError;
|
||||||
|
|
||||||
|
pub struct WasiCtx {
|
||||||
|
pub guest_errors: Vec<GuestError>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WasiCtx {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
guest_errors: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errno is used as a first return value in the functions above, therefore
|
||||||
|
// it must implement GuestErrorType with type Context = WasiCtx.
|
||||||
|
// The context type should let you do logging or debugging or whatever you need
|
||||||
|
// with these errors. We just push them to vecs.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! impl_errno {
|
||||||
|
( $errno:ty ) => {
|
||||||
|
impl wiggle_runtime::GuestErrorType for $errno {
|
||||||
|
type Context = WasiCtx;
|
||||||
|
fn success() -> $errno {
|
||||||
|
<$errno>::Ok
|
||||||
|
}
|
||||||
|
fn from_error(e: GuestError, ctx: &mut WasiCtx) -> $errno {
|
||||||
|
eprintln!("GUEST ERROR: {:?}", e);
|
||||||
|
ctx.guest_errors.push(e);
|
||||||
|
types::Errno::InvalidArg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
8
tests/errno.witx
Normal file
8
tests/errno.witx
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
(typename $errno
|
||||||
|
(enum u32
|
||||||
|
$ok
|
||||||
|
$invalid_arg
|
||||||
|
$dont_want_to
|
||||||
|
$physically_unable
|
||||||
|
$picket_line))
|
||||||
|
|
||||||
159
tests/main.rs
159
tests/main.rs
@@ -1,33 +1,18 @@
|
|||||||
use proptest::prelude::*;
|
use proptest::prelude::*;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use wiggle_runtime::{
|
use wiggle_runtime::{
|
||||||
GuestArray, GuestError, GuestErrorType, GuestMemory, GuestPtr, GuestPtrMut, GuestRef,
|
GuestArray, GuestError, GuestPtr, GuestPtrMut, GuestRef, GuestRefMut, GuestString,
|
||||||
GuestRefMut, GuestString,
|
|
||||||
};
|
};
|
||||||
|
use wiggle_test::{impl_errno, HostMemory, MemArea, WasiCtx};
|
||||||
|
|
||||||
wiggle_generate::from_witx!({
|
wiggle_generate::from_witx!({
|
||||||
witx: ["tests/test.witx"],
|
witx: ["tests/test.witx"],
|
||||||
ctx: WasiCtx,
|
ctx: WasiCtx,
|
||||||
});
|
});
|
||||||
|
|
||||||
pub struct WasiCtx {
|
impl_errno!(types::Errno);
|
||||||
guest_errors: Vec<GuestError>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WasiCtx {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
guest_errors: vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl foo::Foo for WasiCtx {
|
impl foo::Foo for WasiCtx {
|
||||||
fn bar(&mut self, an_int: u32, an_float: f32) -> Result<(), types::Errno> {
|
|
||||||
println!("BAR: {} {}", an_int, an_float);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn baz(
|
fn baz(
|
||||||
&mut self,
|
&mut self,
|
||||||
input1: types::Excuse,
|
input1: types::Excuse,
|
||||||
@@ -153,108 +138,6 @@ impl foo::Foo for WasiCtx {
|
|||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Errno is used as a first return value in the functions above, therefore
|
|
||||||
// it must implement GuestErrorType with type Context = WasiCtx.
|
|
||||||
// The context type should let you do logging or debugging or whatever you need
|
|
||||||
// with these errors. We just push them to vecs.
|
|
||||||
impl GuestErrorType for types::Errno {
|
|
||||||
type Context = WasiCtx;
|
|
||||||
fn success() -> types::Errno {
|
|
||||||
types::Errno::Ok
|
|
||||||
}
|
|
||||||
fn from_error(e: GuestError, ctx: &mut WasiCtx) -> types::Errno {
|
|
||||||
eprintln!("GUEST ERROR: {:?}", e);
|
|
||||||
ctx.guest_errors.push(e);
|
|
||||||
types::Errno::InvalidArg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(align(4096))]
|
|
||||||
struct HostMemory {
|
|
||||||
buffer: [u8; 4096],
|
|
||||||
}
|
|
||||||
impl HostMemory {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
HostMemory { buffer: [0; 4096] }
|
|
||||||
}
|
|
||||||
pub fn as_mut_ptr(&mut self) -> *mut u8 {
|
|
||||||
self.buffer.as_mut_ptr()
|
|
||||||
}
|
|
||||||
pub fn len(&self) -> usize {
|
|
||||||
self.buffer.len()
|
|
||||||
}
|
|
||||||
pub fn mem_area_strat(align: u32) -> BoxedStrategy<MemArea> {
|
|
||||||
prop::num::u32::ANY
|
|
||||||
.prop_filter_map("needs to fit in memory", move |p| {
|
|
||||||
let p_aligned = p - (p % align); // Align according to argument
|
|
||||||
let ptr = p_aligned % 4096; // Put inside memory
|
|
||||||
if ptr + align < 4096 {
|
|
||||||
Some(MemArea { ptr, len: align })
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.boxed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct MemArea {
|
|
||||||
ptr: u32,
|
|
||||||
len: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
// This code is a whole lot like the Region::overlaps func thats at the core of the code under
|
|
||||||
// test.
|
|
||||||
// So, I implemented this one with std::ops::Range so it is less likely I wrote the same bug in two
|
|
||||||
// places.
|
|
||||||
fn overlapping(a: &MemArea, b: &MemArea) -> bool {
|
|
||||||
// a_range is all elems in A
|
|
||||||
let a_range = std::ops::Range {
|
|
||||||
start: a.ptr,
|
|
||||||
end: a.ptr + a.len, // std::ops::Range is open from the right
|
|
||||||
};
|
|
||||||
// b_range is all elems in B
|
|
||||||
let b_range = std::ops::Range {
|
|
||||||
start: b.ptr,
|
|
||||||
end: b.ptr + b.len,
|
|
||||||
};
|
|
||||||
// No element in B is contained in A:
|
|
||||||
for b_elem in b_range.clone() {
|
|
||||||
if a_range.contains(&b_elem) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// No element in A is contained in B:
|
|
||||||
for a_elem in a_range {
|
|
||||||
if b_range.contains(&a_elem) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn non_overlapping_set(areas: &[&MemArea]) -> bool {
|
|
||||||
// A is all areas
|
|
||||||
for (i, a) in areas.iter().enumerate() {
|
|
||||||
// (A, B) is every pair of areas
|
|
||||||
for b in areas[i + 1..].iter() {
|
|
||||||
if overlapping(a, b) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn hostmemory_is_aligned() {
|
|
||||||
let mut h = HostMemory::new();
|
|
||||||
assert_eq!(h.as_mut_ptr() as usize % 4096, 0);
|
|
||||||
let mut h = Box::new(HostMemory::new());
|
|
||||||
assert_eq!(h.as_mut_ptr() as usize % 4096, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct BatExercise {
|
struct BatExercise {
|
||||||
pub input: u32,
|
pub input: u32,
|
||||||
@@ -265,7 +148,7 @@ impl BatExercise {
|
|||||||
pub fn test(&self) {
|
pub fn test(&self) {
|
||||||
let mut ctx = WasiCtx::new();
|
let mut ctx = WasiCtx::new();
|
||||||
let mut host_memory = HostMemory::new();
|
let mut host_memory = HostMemory::new();
|
||||||
let mut guest_memory = GuestMemory::new(host_memory.as_mut_ptr(), host_memory.len() as u32);
|
let mut guest_memory = host_memory.guest_memory();
|
||||||
|
|
||||||
let bat_err = foo::bat(
|
let bat_err = foo::bat(
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
@@ -352,7 +235,7 @@ impl BazExercise {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
.prop_filter("non-overlapping pointers", |e| {
|
.prop_filter("non-overlapping pointers", |e| {
|
||||||
non_overlapping_set(&[
|
MemArea::non_overlapping_set(&[
|
||||||
&e.input2_loc,
|
&e.input2_loc,
|
||||||
&e.input3_loc,
|
&e.input3_loc,
|
||||||
&e.input4_loc,
|
&e.input4_loc,
|
||||||
@@ -364,7 +247,7 @@ impl BazExercise {
|
|||||||
pub fn test(&self) {
|
pub fn test(&self) {
|
||||||
let mut ctx = WasiCtx::new();
|
let mut ctx = WasiCtx::new();
|
||||||
let mut host_memory = HostMemory::new();
|
let mut host_memory = HostMemory::new();
|
||||||
let mut guest_memory = GuestMemory::new(host_memory.as_mut_ptr(), host_memory.len() as u32);
|
let mut guest_memory = host_memory.guest_memory();
|
||||||
|
|
||||||
*guest_memory
|
*guest_memory
|
||||||
.ptr_mut(self.input2_loc.ptr)
|
.ptr_mut(self.input2_loc.ptr)
|
||||||
@@ -454,7 +337,7 @@ impl SumOfPairExercise {
|
|||||||
return_loc,
|
return_loc,
|
||||||
})
|
})
|
||||||
.prop_filter("non-overlapping pointers", |e| {
|
.prop_filter("non-overlapping pointers", |e| {
|
||||||
non_overlapping_set(&[&e.input_loc, &e.return_loc])
|
MemArea::non_overlapping_set(&[&e.input_loc, &e.return_loc])
|
||||||
})
|
})
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
@@ -462,7 +345,7 @@ impl SumOfPairExercise {
|
|||||||
pub fn test(&self) {
|
pub fn test(&self) {
|
||||||
let mut ctx = WasiCtx::new();
|
let mut ctx = WasiCtx::new();
|
||||||
let mut host_memory = HostMemory::new();
|
let mut host_memory = HostMemory::new();
|
||||||
let mut guest_memory = GuestMemory::new(host_memory.as_mut_ptr(), host_memory.len() as u32);
|
let mut guest_memory = host_memory.guest_memory();
|
||||||
|
|
||||||
*guest_memory
|
*guest_memory
|
||||||
.ptr_mut(self.input_loc.ptr)
|
.ptr_mut(self.input_loc.ptr)
|
||||||
@@ -542,7 +425,7 @@ impl SumPairPtrsExercise {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
.prop_filter("non-overlapping pointers", |e| {
|
.prop_filter("non-overlapping pointers", |e| {
|
||||||
non_overlapping_set(&[
|
MemArea::non_overlapping_set(&[
|
||||||
&e.input_first_loc,
|
&e.input_first_loc,
|
||||||
&e.input_second_loc,
|
&e.input_second_loc,
|
||||||
&e.input_struct_loc,
|
&e.input_struct_loc,
|
||||||
@@ -554,7 +437,7 @@ impl SumPairPtrsExercise {
|
|||||||
pub fn test(&self) {
|
pub fn test(&self) {
|
||||||
let mut ctx = WasiCtx::new();
|
let mut ctx = WasiCtx::new();
|
||||||
let mut host_memory = HostMemory::new();
|
let mut host_memory = HostMemory::new();
|
||||||
let mut guest_memory = GuestMemory::new(host_memory.as_mut_ptr(), host_memory.len() as u32);
|
let mut guest_memory = host_memory.guest_memory();
|
||||||
|
|
||||||
*guest_memory
|
*guest_memory
|
||||||
.ptr_mut(self.input_first_loc.ptr)
|
.ptr_mut(self.input_first_loc.ptr)
|
||||||
@@ -643,7 +526,7 @@ impl ReduceExcusesExcercise {
|
|||||||
.prop_filter("non-overlapping pointers", |e| {
|
.prop_filter("non-overlapping pointers", |e| {
|
||||||
let mut all = vec![&e.array_ptr_loc, &e.array_len_loc, &e.return_ptr_loc];
|
let mut all = vec![&e.array_ptr_loc, &e.array_len_loc, &e.return_ptr_loc];
|
||||||
all.extend(e.excuse_ptr_locs.iter());
|
all.extend(e.excuse_ptr_locs.iter());
|
||||||
non_overlapping_set(&all)
|
MemArea::non_overlapping_set(&all)
|
||||||
})
|
})
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
@@ -651,7 +534,7 @@ impl ReduceExcusesExcercise {
|
|||||||
pub fn test(&self) {
|
pub fn test(&self) {
|
||||||
let mut ctx = WasiCtx::new();
|
let mut ctx = WasiCtx::new();
|
||||||
let mut host_memory = HostMemory::new();
|
let mut host_memory = HostMemory::new();
|
||||||
let mut guest_memory = GuestMemory::new(host_memory.as_mut_ptr(), host_memory.len() as u32);
|
let mut guest_memory = host_memory.guest_memory();
|
||||||
|
|
||||||
// Populate memory with pointers to generated Excuse values
|
// Populate memory with pointers to generated Excuse values
|
||||||
for (&excuse, ptr) in self.excuse_values.iter().zip(self.excuse_ptr_locs.iter()) {
|
for (&excuse, ptr) in self.excuse_values.iter().zip(self.excuse_ptr_locs.iter()) {
|
||||||
@@ -739,7 +622,7 @@ impl PopulateExcusesExcercise {
|
|||||||
.prop_filter("non-overlapping pointers", |e| {
|
.prop_filter("non-overlapping pointers", |e| {
|
||||||
let mut all = vec![&e.array_ptr_loc, &e.array_len_loc];
|
let mut all = vec![&e.array_ptr_loc, &e.array_len_loc];
|
||||||
all.extend(e.elements.iter());
|
all.extend(e.elements.iter());
|
||||||
non_overlapping_set(&all)
|
MemArea::non_overlapping_set(&all)
|
||||||
})
|
})
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
@@ -747,7 +630,7 @@ impl PopulateExcusesExcercise {
|
|||||||
pub fn test(&self) {
|
pub fn test(&self) {
|
||||||
let mut ctx = WasiCtx::new();
|
let mut ctx = WasiCtx::new();
|
||||||
let mut host_memory = HostMemory::new();
|
let mut host_memory = HostMemory::new();
|
||||||
let mut guest_memory = GuestMemory::new(host_memory.as_mut_ptr(), host_memory.len() as u32);
|
let mut guest_memory = host_memory.guest_memory();
|
||||||
|
|
||||||
// Populate array length info
|
// Populate array length info
|
||||||
*guest_memory
|
*guest_memory
|
||||||
@@ -838,7 +721,7 @@ impl ConfigureCarExercise {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
.prop_filter("non-overlapping ptrs", |e| {
|
.prop_filter("non-overlapping ptrs", |e| {
|
||||||
non_overlapping_set(&[&e.other_config_by_ptr, &e.return_ptr_loc])
|
MemArea::non_overlapping_set(&[&e.other_config_by_ptr, &e.return_ptr_loc])
|
||||||
})
|
})
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
@@ -846,7 +729,7 @@ impl ConfigureCarExercise {
|
|||||||
pub fn test(&self) {
|
pub fn test(&self) {
|
||||||
let mut ctx = WasiCtx::new();
|
let mut ctx = WasiCtx::new();
|
||||||
let mut host_memory = HostMemory::new();
|
let mut host_memory = HostMemory::new();
|
||||||
let mut guest_memory = GuestMemory::new(host_memory.as_mut_ptr(), host_memory.len() as u32);
|
let mut guest_memory = host_memory.guest_memory();
|
||||||
|
|
||||||
// Populate input ptr
|
// Populate input ptr
|
||||||
*guest_memory
|
*guest_memory
|
||||||
@@ -916,7 +799,11 @@ impl HelloStringExercise {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
.prop_filter("non-overlapping pointers", |e| {
|
.prop_filter("non-overlapping pointers", |e| {
|
||||||
non_overlapping_set(&[&e.string_ptr_loc, &e.string_len_loc, &e.return_ptr_loc])
|
MemArea::non_overlapping_set(&[
|
||||||
|
&e.string_ptr_loc,
|
||||||
|
&e.string_len_loc,
|
||||||
|
&e.return_ptr_loc,
|
||||||
|
])
|
||||||
})
|
})
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
@@ -924,7 +811,7 @@ impl HelloStringExercise {
|
|||||||
pub fn test(&self) {
|
pub fn test(&self) {
|
||||||
let mut ctx = WasiCtx::new();
|
let mut ctx = WasiCtx::new();
|
||||||
let mut host_memory = HostMemory::new();
|
let mut host_memory = HostMemory::new();
|
||||||
let mut guest_memory = GuestMemory::new(host_memory.as_mut_ptr(), host_memory.len() as u32);
|
let mut guest_memory = host_memory.guest_memory();
|
||||||
|
|
||||||
// Populate string length
|
// Populate string length
|
||||||
*guest_memory
|
*guest_memory
|
||||||
@@ -993,7 +880,7 @@ impl CookieCutterExercise {
|
|||||||
pub fn test(&self) {
|
pub fn test(&self) {
|
||||||
let mut ctx = WasiCtx::new();
|
let mut ctx = WasiCtx::new();
|
||||||
let mut host_memory = HostMemory::new();
|
let mut host_memory = HostMemory::new();
|
||||||
let mut guest_memory = GuestMemory::new(host_memory.as_mut_ptr(), host_memory.len() as u32);
|
let mut guest_memory = host_memory.guest_memory();
|
||||||
|
|
||||||
let res = foo::cookie_cutter(
|
let res = foo::cookie_cutter(
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
|
|||||||
@@ -1,10 +1,4 @@
|
|||||||
(typename $errno
|
(use "errno.witx")
|
||||||
(enum u32
|
|
||||||
$ok
|
|
||||||
$invalid_arg
|
|
||||||
$dont_want_to
|
|
||||||
$physically_unable
|
|
||||||
$picket_line))
|
|
||||||
|
|
||||||
(typename $excuse
|
(typename $excuse
|
||||||
(enum u8
|
(enum u8
|
||||||
@@ -44,10 +38,6 @@
|
|||||||
(typename $excuse_array (array (@witx pointer $excuse)))
|
(typename $excuse_array (array (@witx pointer $excuse)))
|
||||||
|
|
||||||
(module $foo
|
(module $foo
|
||||||
(@interface func (export "bar")
|
|
||||||
(param $an_int u32)
|
|
||||||
(param $an_float f32)
|
|
||||||
(result $error $errno))
|
|
||||||
(@interface func (export "baz")
|
(@interface func (export "baz")
|
||||||
(param $an_excuse $excuse)
|
(param $an_excuse $excuse)
|
||||||
(param $an_excuse_by_reference (@witx pointer $excuse))
|
(param $an_excuse_by_reference (@witx pointer $excuse))
|
||||||
|
|||||||
55
tests/trivial.rs
Normal file
55
tests/trivial.rs
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
use proptest::prelude::*;
|
||||||
|
use wiggle_runtime::GuestError;
|
||||||
|
use wiggle_test::{impl_errno, HostMemory, WasiCtx};
|
||||||
|
|
||||||
|
wiggle_generate::from_witx!({
|
||||||
|
witx: ["tests/trivial.witx"],
|
||||||
|
ctx: WasiCtx,
|
||||||
|
});
|
||||||
|
|
||||||
|
impl_errno!(types::Errno);
|
||||||
|
|
||||||
|
impl trivial::Trivial 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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 = trivial::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()
|
||||||
|
}
|
||||||
|
}
|
||||||
8
tests/trivial.witx
Normal file
8
tests/trivial.witx
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
(use "errno.witx")
|
||||||
|
|
||||||
|
(module $trivial
|
||||||
|
(@interface func (export "int_float_args")
|
||||||
|
(param $an_int u32)
|
||||||
|
(param $an_float f32)
|
||||||
|
(result $error $errno))
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user