summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock35
-rw-r--r--Cargo.toml1
-rw-r--r--crates/cli/Cargo.toml4
-rw-r--r--crates/parser/Cargo.toml4
-rw-r--r--crates/tinywasm/Cargo.toml8
-rw-r--r--crates/tinywasm/tests/mvp.rs285
-rw-r--r--crates/types/Cargo.toml2
-rw-r--r--crates/wasm-testsuite/Cargo.toml2
8 files changed, 46 insertions, 295 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 928d192..3f070ac 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -323,6 +323,12 @@ dependencies = [
]
[[package]]
+name = "itoa"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
+
+[[package]]
name = "leb128"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -557,6 +563,12 @@ dependencies = [
]
[[package]]
+name = "ryu"
+version = "1.0.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
+
+[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -592,6 +604,17 @@ dependencies = [
]
[[package]]
+name = "serde_json"
+version = "1.0.108"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
name = "sha2"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -662,11 +685,13 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tinywasm"
-version = "0.0.3"
+version = "0.0.4"
dependencies = [
"eyre",
"log",
"owo-colors",
+ "serde",
+ "serde_json",
"tinywasm-parser",
"tinywasm-types",
"wasm-testsuite",
@@ -675,7 +700,7 @@ dependencies = [
[[package]]
name = "tinywasm-cli"
-version = "0.0.3"
+version = "0.0.4"
dependencies = [
"argh",
"color-eyre",
@@ -687,7 +712,7 @@ dependencies = [
[[package]]
name = "tinywasm-parser"
-version = "0.0.3"
+version = "0.0.4"
dependencies = [
"log",
"tinywasm-types",
@@ -696,7 +721,7 @@ dependencies = [
[[package]]
name = "tinywasm-types"
-version = "0.0.3"
+version = "0.0.4"
dependencies = [
"log",
"rkyv",
@@ -759,7 +784,7 @@ dependencies = [
[[package]]
name = "wasm-testsuite"
-version = "0.1.0"
+version = "0.2.0"
dependencies = [
"rust-embed",
]
diff --git a/Cargo.toml b/Cargo.toml
index f339078..72d3b29 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,6 +4,7 @@ default-members=["crates/cli"]
resolver="2"
[workspace.package]
+version="0.0.4"
edition="2021"
license="MIT OR Apache-2.0"
authors=["Henry Gressmann <mail@henrygressmann.de>"]
diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml
index 0ac9559..be3c699 100644
--- a/crates/cli/Cargo.toml
+++ b/crates/cli/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name="tinywasm-cli"
-version="0.0.3"
+version.workspace=true
description="TinyWasm CLI"
edition.workspace=true
license.workspace=true
@@ -14,7 +14,7 @@ path="src/bin.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-tinywasm={version="0.0.3", path="../tinywasm", features=["std", "parser"]}
+tinywasm={version="0.0.4", path="../tinywasm", features=["std", "parser"]}
argh="0.1"
color-eyre={version="0.6", default-features=false}
log="0.4"
diff --git a/crates/parser/Cargo.toml b/crates/parser/Cargo.toml
index 28c2675..386c142 100644
--- a/crates/parser/Cargo.toml
+++ b/crates/parser/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name="tinywasm-parser"
-version="0.0.3"
+version.workspace=true
description="TinyWasm parser"
edition.workspace=true
license.workspace=true
@@ -12,7 +12,7 @@ repository.workspace=true
# TODO: create dependency free parser
wasmparser={version="0.100", package="wasmparser-nostd", default-features=false}
log={version="0.4", optional=true}
-tinywasm-types={version="0.0.3", path="../types"}
+tinywasm-types={version="0.0.4", path="../types"}
[features]
default=["std", "logging"]
diff --git a/crates/tinywasm/Cargo.toml b/crates/tinywasm/Cargo.toml
index 8c9ea50..e4d6ba5 100644
--- a/crates/tinywasm/Cargo.toml
+++ b/crates/tinywasm/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name="tinywasm"
-version="0.0.3"
+version.workspace=true
description="A tiny WebAssembly interpreter"
edition.workspace=true
license.workspace=true
@@ -14,14 +14,16 @@ path="src/lib.rs"
[dependencies]
log={version="0.4", optional=true}
-tinywasm-parser={version="0.0.3", path="../parser", default-features=false, optional=true}
-tinywasm-types={version="0.0.3", path="../types", default-features=false}
+tinywasm-parser={version="0.0.4", path="../parser", default-features=false, optional=true}
+tinywasm-types={version="0.0.4", path="../types", default-features=false}
[dev-dependencies]
wasm-testsuite={path="../wasm-testsuite"}
wast={version="69.0"}
owo-colors={version="3.5"}
eyre={version="0.6"}
+serde_json={version="1.0"}
+serde={version="1.0", features=["derive"]}
[features]
default=["std", "parser", "logging"]
diff --git a/crates/tinywasm/tests/mvp.rs b/crates/tinywasm/tests/mvp.rs
index 9331c02..66b6b2e 100644
--- a/crates/tinywasm/tests/mvp.rs
+++ b/crates/tinywasm/tests/mvp.rs
@@ -1,140 +1,15 @@
-use std::{
- collections::BTreeMap,
- fmt::{Debug, Formatter},
-};
+mod testsuite;
use eyre::{eyre, Result};
-use log::debug;
-use tinywasm_types::TinyWasmModule;
-use wast::{
- lexer::Lexer,
- parser::{self, ParseBuffer},
- QuoteWat, Wast,
-};
-
-fn parse_module(mut module: wast::core::Module) -> Result<TinyWasmModule> {
- let parser = tinywasm_parser::Parser::new();
- Ok(parser.parse_module_bytes(module.encode().expect("failed to encode module"))?)
-}
+use testsuite::TestSuite;
#[test]
#[ignore]
fn test_mvp() -> Result<()> {
let mut test_suite = TestSuite::new();
+ test_suite.run(wasm_testsuite::MVP_TESTS)?;
- wasm_testsuite::MVP_TESTS.iter().for_each(|group| {
- let test_group = test_suite.test_group(group);
-
- let wast = wasm_testsuite::get_test_wast(group).expect("failed to get test wast");
- let wast = std::str::from_utf8(&wast).expect("failed to convert wast to utf8");
-
- let mut lexer = Lexer::new(wast);
- // we need to allow confusing unicode characters since they are technically valid wasm
- lexer.allow_confusing_unicode(true);
-
- let buf = ParseBuffer::new_with_lexer(lexer).expect("failed to create parse buffer");
- let wast_data = parser::parse::<Wast>(&buf).expect("failed to parse wat");
-
- let mut last_module: Option<TinyWasmModule> = None;
- for (i, directive) in wast_data.directives.into_iter().enumerate() {
- let span = directive.span();
- use wast::WastDirective::*;
- let name = format!("{}-{}", group, i);
-
- match directive {
- // TODO: needs to support more binary sections
- Wat(QuoteWat::Wat(wast::Wat::Module(module))) => {
- let result = std::panic::catch_unwind(|| parse_module(module))
- .map_err(|e| eyre!("failed to parse module: {:?}", e))
- .and_then(|res| res);
-
- match &result {
- Err(_) => last_module = None,
- Ok(m) => last_module = Some(m.clone()),
- }
-
- test_group.add_result(&format!("{}-parse", name), span, result.map(|_| ()));
- }
-
- // these all pass already :)
- AssertMalformed {
- span,
- module: QuoteWat::Wat(wast::Wat::Module(module)),
- message: _,
- } => {
- let res = std::panic::catch_unwind(|| parse_module(module).map(|_| ()));
- test_group.add_result(
- &format!("{}-malformed", name),
- span,
- match res {
- Ok(Ok(_)) => Err(eyre!("expected module to be malformed")),
- Err(_) | Ok(Err(_)) => Ok(()),
- },
- );
- }
- AssertReturn { span, exec, results } => {
- let Some(module) = last_module.as_ref() else {
- // println!("no module found for assert_return: {:?}", exec);
- continue;
- };
-
- let res: Result<Result<()>, _> = std::panic::catch_unwind(|| {
- let mut store = tinywasm::Store::new();
- let module = tinywasm::Module::from(module);
- let instance = module.instantiate(&mut store)?;
-
- use wast::WastExecute::*;
- let invoke = match exec {
- Wat(_) => return Result::Ok(()), // not used by the testsuite
- Get { module: _, global: _ } => return Result::Ok(()),
- Invoke(invoke) => invoke,
- };
-
- let args = invoke
- .args
- .into_iter()
- .map(wastarg2tinywasmvalue)
- .collect::<Result<Vec<_>>>()?;
- let res = instance.get_func(&store, invoke.name)?.call(&mut store, &args)?;
- let expected = results
- .into_iter()
- .map(wastret2tinywasmvalue)
- .collect::<Result<Vec<_>>>()?;
-
- if res.len() != expected.len() {
- return Result::Err(eyre!("expected {} results, got {}", expected.len(), res.len()));
- }
-
- for (i, (res, expected)) in res.iter().zip(expected).enumerate() {
- if res != &expected {
- return Result::Err(eyre!("result {} did not match: {:?} != {:?}", i, res, expected));
- }
- }
-
- Ok(())
- });
-
- let res = match res {
- Err(e) => Err(eyre!("test panicked: {:?}", e)),
- Ok(Err(e)) => Err(e),
- Ok(Ok(())) => Ok(()),
- };
-
- test_group.add_result(&format!("{}-return", name), span, res);
- }
- Invoke(m) => {
- debug!("invoke: {:?}", m);
- }
- // _ => test_group.add_result(
- // &format!("{}-unknown", name),
- // span,
- // Err(Error::Other("test not implemented".to_string())),
- // ),
- // TODO: implement more test directives
- _ => {}
- }
- }
- });
+ test_suite.save_csv("./tests/mvp.csv", env!("CARGO_PKG_VERSION").trim_end())?;
if test_suite.failed() {
eprintln!("\n\nfailed one or more tests:\n{:#?}", test_suite);
@@ -144,155 +19,3 @@ fn test_mvp() -> Result<()> {
Ok(())
}
}
-
-fn wastarg2tinywasmvalue(arg: wast::WastArg) -> Result<tinywasm_types::WasmValue> {
- let wast::WastArg::Core(arg) = arg else {
- return Err(eyre!("unsupported arg type"));
- };
-
- use tinywasm_types::WasmValue;
- use wast::core::WastArgCore::*;
- Ok(match arg {
- F32(f) => WasmValue::F32(f32::from_bits(f.bits)),
- F64(f) => WasmValue::F64(f64::from_bits(f.bits)),
- I32(i) => WasmValue::I32(i),
- I64(i) => WasmValue::I64(i),
- _ => return Err(eyre!("unsupported arg type")),
- })
-}
-
-fn wastret2tinywasmvalue(arg: wast::WastRet) -> Result<tinywasm_types::WasmValue> {
- let wast::WastRet::Core(arg) = arg else {
- return Err(eyre!("unsupported arg type"));
- };
-
- use tinywasm_types::WasmValue;
- use wast::core::WastRetCore::*;
- Ok(match arg {
- F32(f) => nanpattern2tinywasmvalue(f)?,
- F64(f) => nanpattern2tinywasmvalue(f)?,
- I32(i) => WasmValue::I32(i),
- I64(i) => WasmValue::I64(i),
- _ => return Err(eyre!("unsupported arg type")),
- })
-}
-
-enum Bits {
- U32(u32),
- U64(u64),
-}
-trait FloatToken {
- fn bits(&self) -> Bits;
-}
-impl FloatToken for wast::token::Float32 {
- fn bits(&self) -> Bits {
- Bits::U32(self.bits)
- }
-}
-impl FloatToken for wast::token::Float64 {
- fn bits(&self) -> Bits {
- Bits::U64(self.bits)
- }
-}
-
-fn nanpattern2tinywasmvalue<T>(arg: wast::core::NanPattern<T>) -> Result<tinywasm_types::WasmValue>
-where
- T: FloatToken,
-{
- use wast::core::NanPattern::*;
- Ok(match arg {
- CanonicalNan => tinywasm_types::WasmValue::F32(f32::NAN),
- ArithmeticNan => tinywasm_types::WasmValue::F32(f32::NAN),
- Value(v) => match v.bits() {
- Bits::U32(v) => tinywasm_types::WasmValue::F32(f32::from_bits(v)),
- Bits::U64(v) => tinywasm_types::WasmValue::F64(f64::from_bits(v)),
- },
- })
-}
-
-struct TestSuite(BTreeMap<String, TestGroup>);
-
-impl TestSuite {
- fn new() -> Self {
- Self(BTreeMap::new())
- }
-
- fn failed(&self) -> bool {
- self.0.values().any(|group| group.stats().1 > 0)
- }
-
- fn test_group(&mut self, name: &str) -> &mut TestGroup {
- self.0.entry(name.to_string()).or_insert_with(TestGroup::new)
- }
-}
-
-impl Debug for TestSuite {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- use owo_colors::OwoColorize;
- let mut total_passed = 0;
- let mut total_failed = 0;
-
- for (group_name, group) in &self.0 {
- let (group_passed, group_failed) = group.stats();
- total_passed += group_passed;
- total_failed += group_failed;
-
- writeln!(f, "{}", group_name.bold().underline())?;
- writeln!(f, " Tests Passed: {}", group_passed.to_string().green())?;
- writeln!(f, " Tests Failed: {}", group_failed.to_string().red())?;
-
- // for (test_name, test) in &group.tests {
- // write!(f, " {}: ", test_name.bold())?;
- // match &test.result {
- // Ok(()) => {
- // writeln!(f, "{}", "Passed".green())?;
- // }
- // Err(e) => {
- // writeln!(f, "{}", "Failed".red())?;
- // // writeln!(f, "Error: {:?}", e)?;
- // }
- // }
- // writeln!(f, " Span: {:?}", test.span)?;
- // }
- }
-
- writeln!(f, "\n{}", "Total Test Summary:".bold().underline())?;
- writeln!(f, " Total Tests: {}", (total_passed + total_failed))?;
- writeln!(f, " Total Passed: {}", total_passed.to_string().green())?;
- writeln!(f, " Total Failed: {}", total_failed.to_string().red())?;
- Ok(())
- }
-}
-
-struct TestGroup {
- tests: BTreeMap<String, TestCase>,
-}
-
-impl TestGroup {
- fn new() -> Self {
- Self { tests: BTreeMap::new() }
- }
-
- fn stats(&self) -> (usize, usize) {
- let mut passed_count = 0;
- let mut failed_count = 0;
-
- for test in self.tests.values() {
- match test.result {
- Ok(()) => passed_count += 1,
- Err(_) => failed_count += 1,
- }
- }
-
- (passed_count, failed_count)
- }
-
- fn add_result(&mut self, name: &str, span: wast::token::Span, result: Result<()>) {
- self.tests.insert(name.to_string(), TestCase { result, _span: span });
- }
-}
-
-struct TestCase {
- result: Result<()>,
- _span: wast::token::Span,
-}
diff --git a/crates/types/Cargo.toml b/crates/types/Cargo.toml
index 3e4ed15..bc6769a 100644
--- a/crates/types/Cargo.toml
+++ b/crates/types/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name="tinywasm-types"
-version="0.0.3"
+version.workspace=true
description="TinyWasm types"
edition.workspace=true
license.workspace=true
diff --git a/crates/wasm-testsuite/Cargo.toml b/crates/wasm-testsuite/Cargo.toml
index 30a4e58..3e6d647 100644
--- a/crates/wasm-testsuite/Cargo.toml
+++ b/crates/wasm-testsuite/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name="wasm-testsuite"
-version="0.1.0"
+version="0.2.0"
description="Mirror of the WebAssembly core testsuite for use in testing WebAssembly implementations"
license="Apache-2.0"
readme="README.md"