From c7c6e76f9b93e10bfb56a5a4e96edd165b1af334 Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Tue, 26 Jan 2021 07:11:24 -0800 Subject: [PATCH] fuzzing: Add tests for dummy import generation (#2604) --- crates/fuzzing/src/oracles/dummy.rs | 229 ++++++++++++++++++++++++++++ crates/wasmtime/src/types.rs | 4 +- 2 files changed, 231 insertions(+), 2 deletions(-) diff --git a/crates/fuzzing/src/oracles/dummy.rs b/crates/fuzzing/src/oracles/dummy.rs index 561a8fb329..f49cee8c5b 100644 --- a/crates/fuzzing/src/oracles/dummy.rs +++ b/crates/fuzzing/src/oracles/dummy.rs @@ -349,3 +349,232 @@ fn wat_ty(ty: &ValType) -> &'static str { ValType::FuncRef => "funcref", } } + +#[cfg(test)] +mod tests { + use super::*; + use std::collections::HashSet; + + fn store() -> Store { + let mut config = Config::default(); + config.wasm_module_linking(true); + config.wasm_multi_memory(true); + let engine = wasmtime::Engine::new(&config); + Store::new(&engine) + } + + #[test] + fn dummy_table_import() { + let store = store(); + let table = dummy_table( + &store, + TableType::new(ValType::ExternRef, Limits::at_least(10)), + ); + assert_eq!(table.size(), 10); + for i in 0..10 { + assert!(table.get(i).unwrap().unwrap_externref().is_none()); + } + } + + #[test] + fn dummy_global_import() { + let store = store(); + let global = dummy_global(&store, GlobalType::new(ValType::I32, Mutability::Const)); + assert_eq!(global.val_type(), ValType::I32); + assert_eq!(global.mutability(), Mutability::Const); + } + + #[test] + fn dummy_memory_import() { + let store = store(); + let memory = dummy_memory(&store, MemoryType::new(Limits::at_least(1))); + assert_eq!(memory.size(), 1); + } + + #[test] + fn dummy_function_import() { + let store = store(); + let func_ty = FuncType::new(vec![ValType::I32], vec![ValType::I64]); + let func = dummy_func(&store, func_ty.clone()); + assert_eq!(func.ty(), func_ty); + } + + #[test] + fn dummy_instance_import() { + let store = store(); + + let mut instance_ty = InstanceType::new(); + + // Functions. + instance_ty.add_named_export("func0", FuncType::new(vec![ValType::I32], vec![]).into()); + instance_ty.add_named_export("func1", FuncType::new(vec![], vec![ValType::I64]).into()); + + // Globals. + instance_ty.add_named_export( + "global0", + GlobalType::new(ValType::I32, Mutability::Const).into(), + ); + instance_ty.add_named_export( + "global1", + GlobalType::new(ValType::I64, Mutability::Var).into(), + ); + + // Tables. + instance_ty.add_named_export( + "table0", + TableType::new(ValType::ExternRef, Limits::at_least(1)).into(), + ); + instance_ty.add_named_export( + "table1", + TableType::new(ValType::ExternRef, Limits::at_least(1)).into(), + ); + + // Memories. + instance_ty.add_named_export("memory0", MemoryType::new(Limits::at_least(1)).into()); + instance_ty.add_named_export("memory1", MemoryType::new(Limits::at_least(1)).into()); + + // Modules. + instance_ty.add_named_export("module0", ModuleType::new().into()); + instance_ty.add_named_export("module1", ModuleType::new().into()); + + // Instances. + instance_ty.add_named_export("instance0", InstanceType::new().into()); + instance_ty.add_named_export("instance1", InstanceType::new().into()); + + let instance = dummy_instance(&store, instance_ty.clone()); + + let mut expected_exports = vec![ + "func0", + "func1", + "global0", + "global1", + "table0", + "table1", + "memory0", + "memory1", + "module0", + "module1", + "instance0", + "instance1", + ] + .into_iter() + .collect::>(); + for exp in instance.ty().exports() { + let was_expected = expected_exports.remove(exp.name()); + assert!(was_expected); + } + assert!(expected_exports.is_empty()); + } + + #[test] + fn dummy_module_import() { + let store = store(); + + let mut module_ty = ModuleType::new(); + + // Multiple exported and imported functions. + module_ty.add_named_export("func0", FuncType::new(vec![ValType::I32], vec![]).into()); + module_ty.add_named_export("func1", FuncType::new(vec![], vec![ValType::I64]).into()); + module_ty.add_named_import( + "func2", + None, + FuncType::new(vec![ValType::I64], vec![]).into(), + ); + module_ty.add_named_import( + "func3", + None, + FuncType::new(vec![], vec![ValType::I32]).into(), + ); + + // Multiple exported and imported globals. + module_ty.add_named_export( + "global0", + GlobalType::new(ValType::I32, Mutability::Const).into(), + ); + module_ty.add_named_export( + "global1", + GlobalType::new(ValType::I64, Mutability::Var).into(), + ); + module_ty.add_named_import( + "global2", + None, + GlobalType::new(ValType::I32, Mutability::Var).into(), + ); + module_ty.add_named_import( + "global3", + None, + GlobalType::new(ValType::I64, Mutability::Const).into(), + ); + + // Multiple exported and imported tables. + module_ty.add_named_export( + "table0", + TableType::new(ValType::ExternRef, Limits::at_least(1)).into(), + ); + module_ty.add_named_export( + "table1", + TableType::new(ValType::ExternRef, Limits::at_least(1)).into(), + ); + module_ty.add_named_import( + "table2", + None, + TableType::new(ValType::ExternRef, Limits::at_least(1)).into(), + ); + module_ty.add_named_import( + "table3", + None, + TableType::new(ValType::ExternRef, Limits::at_least(1)).into(), + ); + + // Multiple exported and imported memories. + module_ty.add_named_export("memory0", MemoryType::new(Limits::at_least(1)).into()); + module_ty.add_named_export("memory1", MemoryType::new(Limits::at_least(1)).into()); + module_ty.add_named_import("memory2", None, MemoryType::new(Limits::at_least(1)).into()); + module_ty.add_named_import("memory3", None, MemoryType::new(Limits::at_least(1)).into()); + + // An exported and an imported module. + module_ty.add_named_export("module0", ModuleType::new().into()); + module_ty.add_named_import("module1", None, ModuleType::new().into()); + + // An exported and an imported instance. + module_ty.add_named_export("instance0", InstanceType::new().into()); + module_ty.add_named_import("instance1", None, InstanceType::new().into()); + + // Create the module. + let module = dummy_module(&store, module_ty); + + // Check that we have the expected exports. + assert!(module.get_export("func0").is_some()); + assert!(module.get_export("func1").is_some()); + assert!(module.get_export("global0").is_some()); + assert!(module.get_export("global1").is_some()); + assert!(module.get_export("table0").is_some()); + assert!(module.get_export("table1").is_some()); + assert!(module.get_export("memory0").is_some()); + assert!(module.get_export("memory1").is_some()); + assert!(module.get_export("instance0").is_some()); + assert!(module.get_export("module0").is_some()); + + // Check that we have the exported imports. + let mut expected_imports = vec![ + "func2", + "func3", + "global2", + "global3", + "table2", + "table3", + "memory2", + "memory3", + "instance1", + "module1", + ] + .into_iter() + .collect::>(); + for imp in module.imports() { + assert!(imp.name().is_none()); + let was_expected = expected_imports.remove(imp.module()); + assert!(was_expected); + } + assert!(expected_imports.is_empty()); + } +} diff --git a/crates/wasmtime/src/types.rs b/crates/wasmtime/src/types.rs index fe2915402b..5a090d794c 100644 --- a/crates/wasmtime/src/types.rs +++ b/crates/wasmtime/src/types.rs @@ -466,12 +466,12 @@ impl ModuleType { } /// Adds a new export to this `ModuleType`. - pub(crate) fn add_named_export(&mut self, name: &str, ty: ExternType) { + pub fn add_named_export(&mut self, name: &str, ty: ExternType) { self.exports.push((name.to_string(), ty)); } /// Adds a new import to this `ModuleType`. - pub(crate) fn add_named_import(&mut self, module: &str, field: Option<&str>, ty: ExternType) { + pub fn add_named_import(&mut self, module: &str, field: Option<&str>, ty: ExternType) { self.imports .push((module.to_string(), field.map(|f| f.to_string()), ty)); }