Skip to content

Commit 882f22a

Browse files
authored
Cleanup/add some testing in wasmtime-fuzzing (#12038)
Share the fuzz-generator-helpers across more tests and add smoke tests for the dynamic/static component API tests too.
1 parent edeee6e commit 882f22a

File tree

7 files changed

+89
-98
lines changed

7 files changed

+89
-98
lines changed

crates/fuzzing/src/generators/component_types.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,3 +187,25 @@ where
187187

188188
Ok(())
189189
}
190+
191+
#[cfg(test)]
192+
mod tests {
193+
use super::*;
194+
use crate::test::test_n_times;
195+
use wasmtime_test_util::component_fuzz::{TestCase, Type};
196+
197+
#[test]
198+
fn static_api_smoke_test() {
199+
test_n_times(10, |(), u| {
200+
let case = TestCase {
201+
params: vec![&Type::S32, &Type::Bool, &Type::String],
202+
result: Some(&Type::String),
203+
encoding1: u.arbitrary()?,
204+
encoding2: u.arbitrary()?,
205+
};
206+
207+
let declarations = case.declarations();
208+
static_api_test::<(i32, bool, String), (String,)>(u, &declarations)
209+
});
210+
}
211+
}

crates/fuzzing/src/generators/stacks.rs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -404,21 +404,15 @@ impl Stacks {
404404
#[cfg(test)]
405405
mod tests {
406406
use super::*;
407-
use rand::prelude::*;
408407
use wasmparser::Validator;
409408

410409
#[test]
411410
fn stacks_generates_valid_wasm_modules() {
412-
let mut rng = SmallRng::seed_from_u64(0);
413-
let mut buf = vec![0; 2048];
414-
for _ in 0..1024 {
415-
rng.fill_bytes(&mut buf);
416-
let u = Unstructured::new(&buf);
417-
if let Ok(stacks) = Stacks::arbitrary_take_rest(u) {
418-
let wasm = stacks.wasm();
419-
validate(&wasm);
420-
}
421-
}
411+
crate::test::test_n_times(10, |stacks: Stacks, _u| {
412+
let wasm = stacks.wasm();
413+
validate(&wasm);
414+
Ok(())
415+
})
422416
}
423417

424418
fn validate(wasm: &[u8]) {

crates/fuzzing/src/lib.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,44 @@ pub fn init_fuzzing() {
2929
let _ = env_logger::try_init();
3030
});
3131
}
32+
33+
#[cfg(test)]
34+
mod test {
35+
use arbitrary::{Arbitrary, Unstructured};
36+
use rand::prelude::*;
37+
38+
pub fn gen_until_pass<T: for<'a> Arbitrary<'a>>(
39+
mut f: impl FnMut(T, &mut Unstructured<'_>) -> anyhow::Result<bool>,
40+
) -> bool {
41+
let mut rng = SmallRng::seed_from_u64(0);
42+
let mut buf = vec![0; 2048];
43+
let n = 3000;
44+
for _ in 0..n {
45+
rng.fill_bytes(&mut buf);
46+
let mut u = Unstructured::new(&buf);
47+
48+
if let Ok(config) = u.arbitrary() {
49+
if f(config, &mut u).unwrap() {
50+
return true;
51+
}
52+
}
53+
}
54+
false
55+
}
56+
57+
/// Runs `f` with random data until it returns `Ok(())` `iters` times.
58+
pub fn test_n_times<T: for<'a> Arbitrary<'a>>(
59+
iters: u32,
60+
mut f: impl FnMut(T, &mut Unstructured<'_>) -> arbitrary::Result<()>,
61+
) {
62+
let mut to_test = 0..iters;
63+
let ok = gen_until_pass(|a, b| {
64+
if f(a, b).is_ok() {
65+
Ok(to_test.next().is_none())
66+
} else {
67+
Ok(false)
68+
}
69+
});
70+
assert!(ok);
71+
}
72+
}

crates/fuzzing/src/oracles.rs

Lines changed: 6 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1369,45 +1369,9 @@ pub fn call_async(wasm: &[u8], config: &generators::Config, mut poll_amts: &[u32
13691369
#[cfg(test)]
13701370
mod tests {
13711371
use super::*;
1372-
use arbitrary::Unstructured;
1373-
use rand::prelude::*;
1372+
use crate::test::{gen_until_pass, test_n_times};
13741373
use wasmparser::{Validator, WasmFeatures};
13751374

1376-
fn gen_until_pass<T: for<'a> Arbitrary<'a>>(
1377-
mut f: impl FnMut(T, &mut Unstructured<'_>) -> Result<bool>,
1378-
) -> bool {
1379-
let mut rng = SmallRng::seed_from_u64(0);
1380-
let mut buf = vec![0; 2048];
1381-
let n = 3000;
1382-
for _ in 0..n {
1383-
rng.fill_bytes(&mut buf);
1384-
let mut u = Unstructured::new(&buf);
1385-
1386-
if let Ok(config) = u.arbitrary() {
1387-
if f(config, &mut u).unwrap() {
1388-
return true;
1389-
}
1390-
}
1391-
}
1392-
false
1393-
}
1394-
1395-
/// Runs `f` with random data until it returns `Ok(())` `iters` times.
1396-
fn test_n_times<T: for<'a> Arbitrary<'a>>(
1397-
iters: u32,
1398-
mut f: impl FnMut(T, &mut Unstructured<'_>) -> arbitrary::Result<()>,
1399-
) {
1400-
let mut to_test = 0..iters;
1401-
let ok = gen_until_pass(|a, b| {
1402-
if f(a, b).is_ok() {
1403-
Ok(to_test.next().is_none())
1404-
} else {
1405-
Ok(false)
1406-
}
1407-
});
1408-
assert!(ok);
1409-
}
1410-
14111375
// Test that the `gc_ops` fuzzer eventually runs the gc function in the host.
14121376
// We've historically had issues where this fuzzer accidentally wasn't fuzzing
14131377
// anything for a long time so this is an attempt to prevent that from happening
@@ -1501,4 +1465,9 @@ mod tests {
15011465
fn wast_smoke_test() {
15021466
test_n_times(50, |(), u| super::wast_test(u));
15031467
}
1468+
1469+
#[test]
1470+
fn dynamic_component_api_smoke_test() {
1471+
test_n_times(50, |(), u| super::dynamic_component_api_target(u));
1472+
}
15041473
}

crates/fuzzing/src/oracles/engine.rs

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -181,27 +181,16 @@ pub fn smoke_test_engine<T>(
181181
) where
182182
T: DiffEngine,
183183
{
184-
use rand::prelude::*;
185-
186-
let mut rng = SmallRng::seed_from_u64(0);
187-
let mut buf = vec![0; 2048];
188-
let n = 100;
189-
for _ in 0..n {
190-
rng.fill_bytes(&mut buf);
191-
let mut u = Unstructured::new(&buf);
192-
let mut config = match u.arbitrary::<Config>() {
193-
Ok(config) => config,
194-
Err(_) => continue,
195-
};
184+
crate::test::test_n_times(5, |mut config: Config, u| {
196185
// This will ensure that wasmtime, which uses this configuration
197186
// settings, can guaranteed instantiate a module.
198187
config.set_differential_config();
199188

200-
let mut engine = match mk_engine(&mut u, &mut config) {
189+
let mut engine = match mk_engine(u, &mut config) {
201190
Ok(engine) => engine,
202191
Err(e) => {
203192
println!("skip {e:?}");
204-
continue;
193+
return Ok(());
205194
}
206195
};
207196

@@ -240,8 +229,6 @@ pub fn smoke_test_engine<T>(
240229
}
241230
}
242231

243-
return;
244-
}
245-
246-
panic!("after {n} runs nothing ever ran, something is probably wrong");
232+
Ok(())
233+
})
247234
}

crates/fuzzing/src/oracles/memory.rs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -392,20 +392,13 @@ fn build_wasm(image: &HeapImage, offset: u32) -> Vec<u8> {
392392
#[cfg(test)]
393393
mod tests {
394394
use super::*;
395-
use arbitrary::{Arbitrary, Unstructured};
396-
use rand::prelude::*;
395+
use crate::test::test_n_times;
397396

398397
#[test]
399398
fn smoke_test_memory_access() {
400-
let mut rng = SmallRng::seed_from_u64(0);
401-
let mut buf = vec![0; 1024];
402-
403-
for _ in 0..1024 {
404-
rng.fill_bytes(&mut buf);
405-
let u = Unstructured::new(&buf);
406-
if let Ok(input) = MemoryAccesses::arbitrary_take_rest(u) {
407-
check_memory_accesses(input);
408-
}
409-
}
399+
test_n_times(50, |input: MemoryAccesses, _u| {
400+
check_memory_accesses(input);
401+
Ok(())
402+
})
410403
}
411404
}

crates/fuzzing/src/oracles/stacks.rs

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -138,30 +138,15 @@ fn assert_stack_matches(
138138
#[cfg(test)]
139139
mod tests {
140140
use super::*;
141-
use arbitrary::{Arbitrary, Unstructured};
142-
use rand::prelude::*;
141+
use crate::test::gen_until_pass;
143142

144143
const TARGET_STACK_DEPTH: usize = 10;
145144

146145
#[test]
147146
fn smoke_test() {
148-
let mut rng = SmallRng::seed_from_u64(0);
149-
let mut buf = vec![0; 2048];
150-
151-
for _ in 0..1024 {
152-
rng.fill_bytes(&mut buf);
153-
let u = Unstructured::new(&buf);
154-
if let Ok(stacks) = Stacks::arbitrary_take_rest(u) {
155-
let max_stack_depth = check_stacks(stacks);
156-
if max_stack_depth >= TARGET_STACK_DEPTH {
157-
return;
158-
}
159-
}
160-
}
161-
162-
panic!(
163-
"never generated a `Stacks` test case that reached {TARGET_STACK_DEPTH} \
164-
deep stack frames",
165-
);
147+
gen_until_pass(|stacks: Stacks, _u| {
148+
let max_stack_depth = check_stacks(stacks);
149+
Ok(max_stack_depth >= TARGET_STACK_DEPTH)
150+
});
166151
}
167152
}

0 commit comments

Comments
 (0)