diff options
Diffstat (limited to 'crates/wasm-testsuite')
3 files changed, 235 insertions, 6 deletions
diff --git a/crates/wasm-testsuite/lib.rs b/crates/wasm-testsuite/lib.rs index 1f42664..12bf459 100644 --- a/crates/wasm-testsuite/lib.rs +++ b/crates/wasm-testsuite/lib.rs @@ -12,13 +12,18 @@ use std::borrow::Cow; #[derive(RustEmbed)] #[folder = "data/"] #[include = "*.wast"] -struct Asset; +struct OfficialTests; + +#[derive(RustEmbed)] +#[folder = "tests/"] +#[include = "*.wast"] +struct CustomTests; /// List of all supported proposals. Can be used to filter tests. /// /// Includes all proposals from <https://github.com/WebAssembly/testsuite/tree/master/proposals> #[rustfmt::skip] -pub const PROPOSALS: &[&str] = &["annotations", "exception-handling", "extended-const", "function-references", "gc", "memory64", "multi-memory", "relaxed-simd", "tail-call", "threads"]; +pub const PROPOSALS: &[&str] = &["annotations", "exception-handling", "extended-const", "function-references", "gc", "memory64", "multi-memory", "relaxed-simd", "tail-call", "threads", "custom-page-sizes"]; /// List of all tests that apply to the MVP (V1) spec /// Note that the tests are still for the latest spec, so the latest version of Wast is used. @@ -35,7 +40,7 @@ pub const SIMD_TESTS: &[&str] = &["simd_address.wast", "simd_align.wast", "simd_ /// List of all tests that apply to a specific proposal. pub fn get_proposal_tests(proposal: &str) -> impl Iterator<Item = String> + '_ { - Asset::iter().filter_map(move |x| { + OfficialTests::iter().chain(CustomTests::iter()).filter_map(move |x| { let mut parts = x.split('/'); if parts.next() == Some("proposals") && parts.next() == Some(proposal) { Some(format!("{}/{}", proposal, parts.next().unwrap_or_default())) @@ -50,8 +55,10 @@ pub fn get_test_wast(name: &str) -> Option<Cow<'static, [u8]>> { assert!(name.ends_with(".wast"), "Expected .wast file. Got: {name}"); match name.contains('/') { - true => Asset::get(&format!("proposals/{name}")).map(|x| x.data), - false => Asset::get(name).map(|x| x.data), + true => OfficialTests::get(&format!("proposals/{name}")) + .or_else(|| CustomTests::get(&format!("proposals/{name}"))) + .map(|x| x.data), + false => OfficialTests::get(name).or_else(|| CustomTests::get(name)).map(|x| x.data), } } @@ -66,7 +73,7 @@ mod tests { let mut unique_proposals = HashSet::new(); // check that all proposals are present - for proposal in Asset::iter() { + for proposal in OfficialTests::iter() { if !proposal.starts_with("proposals/") { continue; } diff --git a/crates/wasm-testsuite/tests/proposals/custom-page-sizes/custom-page-sizes-invalid.wast b/crates/wasm-testsuite/tests/proposals/custom-page-sizes/custom-page-sizes-invalid.wast new file mode 100644 index 0000000..150f58b --- /dev/null +++ b/crates/wasm-testsuite/tests/proposals/custom-page-sizes/custom-page-sizes-invalid.wast @@ -0,0 +1,112 @@ +;; from https://github.com/WebAssembly/custom-page-sizes/blob/main/test/core/custom-page-sizes/custom-page-sizes-invalid.wast + +;; Page size that is not a power of two. +(assert_malformed + (module quote "(memory 0 (pagesize 3))") + "invalid custom page size" +) + +;; Power-of-two page sizes that are not 1 or 64KiB. +(assert_invalid + (module (memory 0 (pagesize 2))) + "invalid custom page size" +) +(assert_invalid + (module (memory 0 (pagesize 4))) + "invalid custom page size" +) +(assert_invalid + (module (memory 0 (pagesize 8))) + "invalid custom page size" +) +(assert_invalid + (module (memory 0 (pagesize 16))) + "invalid custom page size" +) +(assert_invalid + (module (memory 0 (pagesize 32))) + "invalid custom page size" +) +(assert_invalid + (module (memory 0 (pagesize 64))) + "invalid custom page size" +) +(assert_invalid + (module (memory 0 (pagesize 128))) + "invalid custom page size" +) +(assert_invalid + (module (memory 0 (pagesize 256))) + "invalid custom page size" +) +(assert_invalid + (module (memory 0 (pagesize 512))) + "invalid custom page size" +) +(assert_invalid + (module (memory 0 (pagesize 1024))) + "invalid custom page size" +) +(assert_invalid + (module (memory 0 (pagesize 2048))) + "invalid custom page size" +) +(assert_invalid + (module (memory 0 (pagesize 4096))) + "invalid custom page size" +) +(assert_invalid + (module (memory 0 (pagesize 8192))) + "invalid custom page size" +) +(assert_invalid + (module (memory 0 (pagesize 16384))) + "invalid custom page size" +) +(assert_invalid + (module (memory 0 (pagesize 32768))) + "invalid custom page size" +) + +;; Power-of-two page size that is larger than 64KiB. +(assert_invalid + (module (memory 0 (pagesize 0x20000))) + "invalid custom page size" +) + +;; Power of two page size that cannot fit in a u64 to exercise checks against +;; shift overflow. +(assert_malformed + (module binary + "\00asm" "\01\00\00\00" + "\05\04\01" ;; Memory section + + ;; memory 0 + "\08" ;; flags w/ custom page size + "\00" ;; minimum = 0 + "\41" ;; pagesize = 2**65 + ) + "invalid custom page size" +) + +;; Importing a memory with the wrong page size. + +(module $m + (memory (export "small-pages-memory") 0 (pagesize 1)) + (memory (export "large-pages-memory") 0 (pagesize 65536)) +) +(register "m" $m) + +(assert_unlinkable + (module + (memory (import "m" "small-pages-memory") 0 (pagesize 65536)) + ) + "incompatible import type" +) + +(assert_unlinkable + (module + (memory (import "m" "large-pages-memory") 0 (pagesize 1)) + ) + "incompatible import type" +) diff --git a/crates/wasm-testsuite/tests/proposals/custom-page-sizes/custom-page-sizes.wast b/crates/wasm-testsuite/tests/proposals/custom-page-sizes/custom-page-sizes.wast new file mode 100644 index 0000000..f59d52b --- /dev/null +++ b/crates/wasm-testsuite/tests/proposals/custom-page-sizes/custom-page-sizes.wast @@ -0,0 +1,110 @@ +;; from https://github.com/WebAssembly/custom-page-sizes/blob/main/test/core/custom-page-sizes/custom-page-sizes.wast + +;; Check all the valid custom page sizes. +(module (memory 1 (pagesize 1))) +(module (memory 1 (pagesize 65536))) + +;; Check them all again with maximums specified. +(module (memory 1 2 (pagesize 1))) +(module (memory 1 2 (pagesize 65536))) + +;; Check the behavior of memories with page size 1. +(module + (memory 0 (pagesize 1)) + (func (export "size") (result i32) + memory.size + ) + (func (export "grow") (param i32) (result i32) + (memory.grow (local.get 0)) + ) + (func (export "load") (param i32) (result i32) + (i32.load8_u (local.get 0)) + ) + (func (export "store") (param i32 i32) + (i32.store8 (local.get 0) (local.get 1)) + ) +) + +(assert_return (invoke "size") (i32.const 0)) +(assert_trap (invoke "load" (i32.const 0)) "out of bounds memory access") + +(assert_return (invoke "grow" (i32.const 65536)) (i32.const 0)) +(assert_return (invoke "size") (i32.const 65536)) +(assert_return (invoke "load" (i32.const 65535)) (i32.const 0)) +(assert_return (invoke "store" (i32.const 65535) (i32.const 1))) +(assert_return (invoke "load" (i32.const 65535)) (i32.const 1)) +(assert_trap (invoke "load" (i32.const 65536)) "out of bounds memory access") + +(assert_return (invoke "grow" (i32.const 65536)) (i32.const 65536)) +(assert_return (invoke "size") (i32.const 131072)) +(assert_return (invoke "load" (i32.const 131071)) (i32.const 0)) +(assert_return (invoke "store" (i32.const 131071) (i32.const 1))) +(assert_return (invoke "load" (i32.const 131071)) (i32.const 1)) +(assert_trap (invoke "load" (i32.const 131072)) "out of bounds memory access") + +;; Although smaller page sizes let us get to memories larger than 2**16 pages, +;; we can't do that with the default page size, even if we explicitly state it +;; as a custom page size. +(module + (memory 0 (pagesize 65536)) + (func (export "size") (result i32) + memory.size + ) + (func (export "grow") (param i32) (result i32) + (memory.grow (local.get 0)) + ) +) +(assert_return (invoke "size") (i32.const 0)) +(assert_return (invoke "grow" (i32.const 65537)) (i32.const -1)) +(assert_return (invoke "size") (i32.const 0)) + +;; Can copy between memories of different page sizes. +(module + (memory $small 10 (pagesize 1)) + (memory $large 1 (pagesize 65536)) + + (data (memory $small) (i32.const 0) "\11\22\33\44") + (data (memory $large) (i32.const 0) "\55\66\77\88") + + (func (export "copy-small-to-large") (param i32 i32 i32) + (memory.copy $large $small (local.get 0) (local.get 1) (local.get 2)) + ) + + (func (export "copy-large-to-small") (param i32 i32 i32) + (memory.copy $small $large (local.get 0) (local.get 1) (local.get 2)) + ) + + (func (export "load8-small") (param i32) (result i32) + (i32.load8_u $small (local.get 0)) + ) + + (func (export "load8-large") (param i32) (result i32) + (i32.load8_u $large (local.get 0)) + ) +) + +(assert_return (invoke "copy-small-to-large" (i32.const 6) (i32.const 0) (i32.const 2))) +(assert_return (invoke "load8-large" (i32.const 6)) (i32.const 0x11)) +(assert_return (invoke "load8-large" (i32.const 7)) (i32.const 0x22)) + +(assert_return (invoke "copy-large-to-small" (i32.const 4) (i32.const 1) (i32.const 3))) +(assert_return (invoke "load8-small" (i32.const 4)) (i32.const 0x66)) +(assert_return (invoke "load8-small" (i32.const 5)) (i32.const 0x77)) +(assert_return (invoke "load8-small" (i32.const 6)) (i32.const 0x88)) + +;; Can link together modules that export and import memories with custom page +;; sizes. + +(module $m + (memory (export "small-pages-memory") 0 (pagesize 1)) + (memory (export "large-pages-memory") 0 (pagesize 65536)) +) +(register "m" $m) + +(module + (memory (import "m" "small-pages-memory") 0 (pagesize 1)) +) + +(module + (memory (import "m" "large-pages-memory") 0 (pagesize 65536)) +) |
