Skip to content
This repository was archived by the owner on Oct 3, 2025. It is now read-only.

Commit 52bebfa

Browse files
feat: move wasm core testsuite to a seperate crate
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
1 parent 8eec592 commit 52bebfa

File tree

5 files changed

+280
-2
lines changed

5 files changed

+280
-2
lines changed

.gitmodules

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
[submodule "crates/tinywasm/tests/spec/testsuite"]
2-
path = crates/tinywasm/tests/spec/testsuite
1+
[submodule "crates/wasm-testsuite/data"]
2+
path = crates/wasm-testsuite/data
33
url = https://github.com/WebAssembly/testsuite.git

Cargo.lock

Lines changed: 149 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/wasm-testsuite/Cargo.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name="wasm-testsuite"
3+
version="0.0.1"
4+
description="Mirror of the WebAssembly core testsuite for use in testing WebAssembly implementations"
5+
edition.workspace=true
6+
license.workspace=true
7+
authors.workspace=true
8+
repository.workspace=true
9+
10+
[lib]
11+
path="lib.rs"
12+
13+
[package.metadata.workspaces]
14+
independent=true
15+
16+
[dependencies]
17+
rust-embed={version="8.1.0", features=["include-exclude"]}

crates/wasm-testsuite/lib.rs

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
//! This crate provides a way to access the WebAssembly spec testsuite.
2+
//!
3+
//! The testsuite is included as a git submodule and embedded into the binary.
4+
//!
5+
//! Generated from https://github.com/WebAssembly/testsuite
6+
7+
#![forbid(unsafe_code)]
8+
#![doc(test(
9+
no_crate_inject,
10+
attr(
11+
deny(warnings, rust_2018_idioms),
12+
allow(dead_code, unused_assignments, unused_variables)
13+
)
14+
))]
15+
#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms, unreachable_pub)]
16+
17+
use rust_embed::RustEmbed;
18+
use std::borrow::Cow;
19+
20+
#[derive(RustEmbed)]
21+
#[folder = "data/"]
22+
#[include = "*.wast"]
23+
struct Asset;
24+
25+
/// List of all proposals.
26+
/// This list is generated from the `proposals` folder in https://github.com/WebAssembly/testsuite
27+
#[rustfmt::skip]
28+
pub const PROPOSALS: &[&str] = &["annotations", "exception-handling", "memory64", "function-references", "multi-memory", "relaxed-simd", "tail-call", "threads", "extended-const", "gc"];
29+
30+
/// Get all test file names and their contents.
31+
///
32+
/// Proposals can be filtered by passing a list of proposal names.
33+
/// Valid proposal names are listed in [`PROPOSALS`].
34+
/// Returns an iterator over tuples of the form `(test_name, test_data)`.
35+
/// test_name is the name of the test file and the proposal name (if any), e.g. `annotations/br.wast`.
36+
pub fn get_tests(include_proposals: &[String]) -> impl Iterator<Item = (String, Cow<'static, [u8]>)> {
37+
let include_proposals = include_proposals.to_vec();
38+
39+
Asset::iter().filter_map(move |x| {
40+
let mut parts = x.split('/');
41+
match parts.next() {
42+
Some("proposals") => {
43+
let proposal = parts.next();
44+
let test_name = parts.next().unwrap_or_default();
45+
46+
if proposal.map_or(false, |p| include_proposals.contains(&p.to_string())) {
47+
let full_path = format!("{}/{}", proposal.unwrap_or_default(), test_name);
48+
let data = Asset::get(&x).unwrap().data;
49+
Some((full_path, data))
50+
} else {
51+
None
52+
}
53+
}
54+
Some(test_name) => {
55+
let data = Asset::get(&x).unwrap().data;
56+
Some((test_name.to_owned(), data))
57+
}
58+
None => None,
59+
}
60+
})
61+
}
62+
63+
/// Get the WAST file as a byte slice.
64+
///
65+
/// # Examples
66+
/// proposals: {proposal}/{test_name}.wast
67+
/// tests: {test_name}.wast
68+
pub fn get_wast(name: &str) -> Option<Cow<'_, [u8]>> {
69+
if !name.ends_with(".wast") {
70+
panic!("Expected .wast file. Got: {}", name);
71+
}
72+
73+
match name.contains('/') {
74+
true => Asset::get(&format!("proposals/{}", name)).map(|x| x.data),
75+
false => Asset::get(name).map(|x| x.data),
76+
}
77+
}
78+
79+
#[cfg(test)]
80+
mod tests {
81+
use std::collections::HashSet;
82+
83+
use super::*;
84+
85+
#[test]
86+
fn test_proposals() {
87+
let mut unique_proposals = HashSet::new();
88+
89+
// check that all proposals are present
90+
for proposal in Asset::iter() {
91+
if !proposal.starts_with("proposals/") {
92+
continue;
93+
}
94+
95+
let proposal = proposal.split('/').nth(1).unwrap();
96+
unique_proposals.insert(proposal.to_owned());
97+
// assert!(PROPOSALS.contains(&proposal));
98+
}
99+
println!("{:?}", unique_proposals);
100+
}
101+
102+
#[test]
103+
fn test_get_tests() {
104+
let tests = get_tests(&["annotations".to_owned()]);
105+
let tests: Vec<_> = tests.collect();
106+
println!("{:?}", tests.iter().map(|(name, _)| name).collect::<Vec<_>>());
107+
108+
// for (name, data) in tests {
109+
// println!("{}: {}", name, data.len());
110+
// }
111+
}
112+
}

0 commit comments

Comments
 (0)