From b7d323f60966484e7a4d7041f1626f6f87594d69 Mon Sep 17 00:00:00 2001 From: arvidn Date: Sun, 1 Mar 2026 16:52:20 +0100 Subject: [PATCH 1/4] add support for wasm32 including tests and CI --- .github/workflows/build-test.yml | 21 +++++++++++++ Cargo.lock | 51 ++++++++++++++++++++++++++++++++ Cargo.toml | 6 ++++ rust-toolchain.toml | 1 + src/allocator.rs | 4 +++ src/chia_dialect.rs | 2 ++ src/more_ops.rs | 5 ++++ src/number.rs | 2 ++ src/op_utils.rs | 2 ++ src/run_program.rs | 2 ++ src/serde/bitset.rs | 2 ++ src/serde/de_br.rs | 2 ++ src/serde/de_tree.rs | 2 ++ src/serde/incremental.rs | 2 ++ src/serde/intern.rs | 2 ++ src/serde/object_cache.rs | 2 ++ src/serde/parse_atom.rs | 2 ++ src/serde/path_builder.rs | 2 ++ src/serde/read_cache_lookup.rs | 2 ++ src/serde/ser.rs | 2 ++ src/serde/ser_br.rs | 2 ++ src/serde/serialized_length.rs | 2 ++ src/serde/test.rs | 2 ++ src/serde/test_intern.rs | 2 ++ src/serde/tools.rs | 2 ++ src/serde/tree_cache.rs | 2 ++ src/serde/write_atom.rs | 2 ++ src/test_ops.rs | 35 ++++++++++++++++++++-- src/tests.rs | 2 ++ src/traverse_path.rs | 2 ++ src/treehash.rs | 2 ++ 31 files changed, 168 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index e2dadbed4..3590f01c2 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -203,6 +203,27 @@ jobs: - name: build run: cargo +nightly fuzz list | xargs -I "%" sh -c "cargo +nightly fuzz run % -- -max_total_time=30 || exit 255" + wasm_tests: + name: WASM tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 1 + - name: Set up Rust + uses: dtolnay/rust-toolchain@1.92.0 + with: + targets: wasm32-unknown-unknown + - name: Install wasm-bindgen-cli + shell: bash + run: | + WASM_BINDGEN_VERSION=$(cargo tree -p wasm-bindgen --depth 0 --target wasm32-unknown-unknown 2>/dev/null | head -1 | sed 's/.*v//') + cargo install wasm-bindgen-cli --version "$WASM_BINDGEN_VERSION" + - name: cargo test (default) + run: cargo test -p clvmr --target wasm32-unknown-unknown --release + env: + CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER: wasm-bindgen-test-runner + unit_tests: name: Unit tests runs-on: ${{ matrix.os }} diff --git a/Cargo.lock b/Cargo.lock index ede9a5ecd..a3efe9771 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -357,6 +357,7 @@ dependencies = [ "chia-bls", "chia-sha2 0.34.0", "criterion", + "getrandom", "hex", "hex-literal", "k256", @@ -370,6 +371,7 @@ dependencies = [ "sha1", "sha3", "thiserror", + "wasm-bindgen-test", ] [[package]] @@ -717,8 +719,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -930,6 +934,16 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "minicov" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4869b6a491569605d66d3952bcdf03df789e5b536e5f0cf7758a7f08a55ae24d" +dependencies = [ + "cc", + "walkdir", +] + [[package]] name = "num-bigint" version = "0.4.6" @@ -1681,6 +1695,19 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.100" @@ -1713,6 +1740,30 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-bindgen-test" +version = "0.3.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66c8d5e33ca3b6d9fa3b4676d774c5778031d27a578c2b007f905acf816152c3" +dependencies = [ + "js-sys", + "minicov", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test-macro", +] + +[[package]] +name = "wasm-bindgen-test-macro" +version = "0.3.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17d5042cc5fa009658f9a7333ef24291b1291a25b6382dd68862a7f3b969f69b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "web-sys" version = "0.3.77" diff --git a/Cargo.toml b/Cargo.toml index bf5cd3916..e7eb7c129 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -97,6 +97,12 @@ rstest = { workspace = true } criterion = { workspace = true } hex = { workspace = true } +[target.'cfg(target_arch = "wasm32")'.dependencies] +getrandom = { workspace = true, features = ["js"] } + +[target.'cfg(target_arch = "wasm32")'.dev-dependencies] +wasm-bindgen-test = "0.3" + [[bench]] name = "run-program" harness = false diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 1a2165581..6bf52465e 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,4 @@ [toolchain] channel = "1.92.0" components = ["rustfmt", "clippy"] +targets = ["wasm32-unknown-unknown"] diff --git a/src/allocator.rs b/src/allocator.rs index fadce1836..16ab06bdd 100644 --- a/src/allocator.rs +++ b/src/allocator.rs @@ -1076,6 +1076,8 @@ impl Allocator { mod tests { use super::*; use rstest::rstest; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; #[test] fn test_atom_eq_1() { @@ -2458,6 +2460,8 @@ mod debug_tests { use chia_bls::PublicKey; use chia_bls::Signature; use rstest::rstest; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; fn new_node(a: &mut Allocator, case: u8) -> (NodePtr, usize) { match case { diff --git a/src/chia_dialect.rs b/src/chia_dialect.rs index 21491c657..e056a6a96 100644 --- a/src/chia_dialect.rs +++ b/src/chia_dialect.rs @@ -281,6 +281,8 @@ impl Dialect for ChiaDialect { mod tests { use super::*; use bitflags::Flags; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; #[test] fn no_overlapping_flags() { diff --git a/src/more_ops.rs b/src/more_ops.rs index d3c80f810..5562465ae 100644 --- a/src/more_ops.rs +++ b/src/more_ops.rs @@ -5,6 +5,9 @@ use std::ops::BitAndAssign; use std::ops::BitOrAssign; use std::ops::BitXorAssign; +#[cfg(all(test, target_arch = "wasm32"))] +use wasm_bindgen_test::wasm_bindgen_test as test; + use crate::allocator::{Allocator, NodePtr, NodeVisitor, SExp, len_for_value}; use crate::cost::{Cost, check_cost}; use crate::error::EvalErr; @@ -1089,6 +1092,8 @@ pub fn op_modpow(a: &mut Allocator, input: NodePtr, max_cost: Cost) -> Response mod tests { use super::*; use rstest::rstest; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; fn test_sha256_atom(buf: &[u8]) { let mut a = Allocator::new(); diff --git a/src/number.rs b/src/number.rs index 0220ac5d9..9f4a08bcc 100644 --- a/src/number.rs +++ b/src/number.rs @@ -17,6 +17,8 @@ pub fn number_from_u8(v: &[u8]) -> Number { #[cfg(test)] mod tests { use num_bigint::{BigUint, Sign}; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; use super::*; diff --git a/src/op_utils.rs b/src/op_utils.rs index 933bdcec8..5c5875199 100644 --- a/src/op_utils.rs +++ b/src/op_utils.rs @@ -258,6 +258,8 @@ pub fn int_atom(a: &Allocator, args: NodePtr, op_name: &str) -> Result<(Number, #[cfg(test)] mod tests { use rstest::rstest; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; use super::*; diff --git a/src/run_program.rs b/src/run_program.rs index 91726722b..23b5784c9 100644 --- a/src/run_program.rs +++ b/src/run_program.rs @@ -558,6 +558,8 @@ pub fn run_program_with_counters<'a, D: Dialect>( #[cfg(test)] mod tests { use super::*; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; use crate::chia_dialect::ClvmFlags; use crate::test_ops::parse_exp; diff --git a/src/serde/bitset.rs b/src/serde/bitset.rs index 89facdb1e..c62fa05f8 100644 --- a/src/serde/bitset.rs +++ b/src/serde/bitset.rs @@ -41,6 +41,8 @@ impl BitSet { #[cfg(test)] mod tests { use super::*; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; #[test] fn test_visited_nodes() { diff --git a/src/serde/de_br.rs b/src/serde/de_br.rs index fcaf611af..3538cbca0 100644 --- a/src/serde/de_br.rs +++ b/src/serde/de_br.rs @@ -206,6 +206,8 @@ pub fn traverse_path_with_vec( #[cfg(test)] mod tests { use crate::test_ops::node_eq; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; use super::*; use rstest::rstest; diff --git a/src/serde/de_tree.rs b/src/serde/de_tree.rs index b5620f62c..38c2b5418 100644 --- a/src/serde/de_tree.rs +++ b/src/serde/de_tree.rs @@ -221,6 +221,8 @@ pub fn parse_triples( #[cfg(test)] mod tests { use super::*; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; use hex::FromHex; use std::io::Cursor; diff --git a/src/serde/incremental.rs b/src/serde/incremental.rs index cd8c7185a..2f31e5c02 100644 --- a/src/serde/incremental.rs +++ b/src/serde/incremental.rs @@ -140,6 +140,8 @@ mod tests { node_from_bytes, node_from_bytes_backrefs, node_to_bytes, node_to_bytes_backrefs, }; use hex_literal::hex; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; #[test] fn test_simple_incremental() { diff --git a/src/serde/intern.rs b/src/serde/intern.rs index 26c87a209..cbd752716 100644 --- a/src/serde/intern.rs +++ b/src/serde/intern.rs @@ -132,6 +132,8 @@ pub fn intern(allocator: &Allocator, node: NodePtr) -> Result { #[cfg(test)] mod tests { use super::*; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; #[test] fn test_intern_single_atom() { diff --git a/src/serde/object_cache.rs b/src/serde/object_cache.rs index 930c93c20..196c96168 100644 --- a/src/serde/object_cache.rs +++ b/src/serde/object_cache.rs @@ -139,6 +139,8 @@ pub fn serialized_length( #[cfg(test)] mod tests { use super::*; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; use hex::FromHex; use std::cmp::max; diff --git a/src/serde/parse_atom.rs b/src/serde/parse_atom.rs index d2d98251a..8ae2a7fed 100644 --- a/src/serde/parse_atom.rs +++ b/src/serde/parse_atom.rs @@ -100,6 +100,8 @@ mod tests { use super::*; use crate::serde::write_atom::write_atom; use rstest::rstest; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; #[rstest] // single-byte length prefix diff --git a/src/serde/path_builder.rs b/src/serde/path_builder.rs index 8667fe90c..468280386 100644 --- a/src/serde/path_builder.rs +++ b/src/serde/path_builder.rs @@ -122,6 +122,8 @@ mod tests { use crate::serde::serialized_length_atom; use hex; use rstest::rstest; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; fn build_path<'a>(a: &'a Bump, input: &[u8]) -> PathBuilder<'a> { let mut path = PathBuilder::default(); diff --git a/src/serde/read_cache_lookup.rs b/src/serde/read_cache_lookup.rs index ad896f2ac..799531ce3 100644 --- a/src/serde/read_cache_lookup.rs +++ b/src/serde/read_cache_lookup.rs @@ -238,6 +238,8 @@ fn reversed_path_to_vec_u8(path: &BitSlice) -> Vec { #[cfg(test)] mod tests { use super::*; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; #[test] fn test_path_to_vec_u8() { diff --git a/src/serde/ser.rs b/src/serde/ser.rs index b2416b258..6e9129e92 100644 --- a/src/serde/ser.rs +++ b/src/serde/ser.rs @@ -74,6 +74,8 @@ pub fn node_to_bytes(a: &Allocator, node: NodePtr) -> Result> { mod tests { use super::*; use crate::error::EvalErr; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; #[test] fn test_serialize_limit() { diff --git a/src/serde/ser_br.rs b/src/serde/ser_br.rs index 744667287..9ce38cc2f 100644 --- a/src/serde/ser_br.rs +++ b/src/serde/ser_br.rs @@ -92,6 +92,8 @@ mod tests { use super::*; use crate::error::EvalErr; use crate::serde::node_to_bytes_backrefs; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; #[test] fn test_serialize_limit() { diff --git a/src/serde/serialized_length.rs b/src/serde/serialized_length.rs index a00b8a55d..ea88be5c8 100644 --- a/src/serde/serialized_length.rs +++ b/src/serde/serialized_length.rs @@ -45,6 +45,8 @@ pub fn atom_length_bits(num_bits: u64) -> Option { mod tests { use super::*; use rstest::rstest; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; #[rstest] #[case(&[], 1)] diff --git a/src/serde/test.rs b/src/serde/test.rs index cac505a79..8d120e3fb 100644 --- a/src/serde/test.rs +++ b/src/serde/test.rs @@ -1,4 +1,6 @@ use hex::FromHex; +#[cfg(target_arch = "wasm32")] +use wasm_bindgen_test::wasm_bindgen_test as test; use crate::allocator::Allocator; use crate::serde::{ diff --git a/src/serde/test_intern.rs b/src/serde/test_intern.rs index 698f0ceb1..841499be4 100644 --- a/src/serde/test_intern.rs +++ b/src/serde/test_intern.rs @@ -6,6 +6,8 @@ use crate::serde::node_from_bytes_backrefs; use crate::serde::node_to_bytes; use crate::serde::object_cache::{ObjectCache, treehash}; use rstest::rstest; +#[cfg(target_arch = "wasm32")] +use wasm_bindgen_test::wasm_bindgen_test as test; fn treehash_for_node(allocator: &Allocator, node: NodePtr) -> Bytes32 { let mut object_cache = ObjectCache::new(treehash); diff --git a/src/serde/tools.rs b/src/serde/tools.rs index f89feae37..ad8d63c45 100644 --- a/src/serde/tools.rs +++ b/src/serde/tools.rs @@ -243,6 +243,8 @@ mod tests { use crate::serde::node_from_bytes_backrefs; use hex::FromHex; use rstest::rstest; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; #[test] fn test_tree_hash_max_single_byte() { diff --git a/src/serde/tree_cache.rs b/src/serde/tree_cache.rs index b69c84964..31587f1a2 100644 --- a/src/serde/tree_cache.rs +++ b/src/serde/tree_cache.rs @@ -582,6 +582,8 @@ impl TreeCache { mod tests { use super::*; use rstest::rstest; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; #[test] fn test_basic_tree() { diff --git a/src/serde/write_atom.rs b/src/serde/write_atom.rs index 4eb02913a..fda7132da 100644 --- a/src/serde/write_atom.rs +++ b/src/serde/write_atom.rs @@ -60,6 +60,8 @@ pub fn write_atom(f: &mut W, atom: &[u8]) -> Result<()> { #[cfg(test)] mod tests { use super::*; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; #[test] fn test_write_atom_encoding_prefix_with_size() { diff --git a/src/test_ops.rs b/src/test_ops.rs index f1654f06c..687728f39 100644 --- a/src/test_ops.rs +++ b/src/test_ops.rs @@ -208,6 +208,8 @@ pub fn node_eq(allocator: &Allocator, s1: NodePtr, s2: NodePtr) -> bool { #[cfg(test)] mod tests { use super::*; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; #[cfg(feature = "pre-eval")] use crate::chia_dialect::{ChiaDialect, ClvmFlags}; @@ -273,9 +275,37 @@ mod tests { #[case("test-keccak256")] #[case("test-keccak256-generated")] fn test_ops(#[case] filename: &str) { - use std::fs::read_to_string; + #[cfg(not(target_arch = "wasm32"))] + let test_cases = { + use std::fs::read_to_string; + let path = format!("op-tests/{filename}.txt"); + read_to_string(path).expect("test file not found") + }; - let filename = format!("op-tests/{filename}.txt"); + #[cfg(target_arch = "wasm32")] + let test_cases: &str = match filename { + "test-core-ops" => include_str!("../op-tests/test-core-ops.txt"), + "test-more-ops" => include_str!("../op-tests/test-more-ops.txt"), + "test-bls-ops" => include_str!("../op-tests/test-bls-ops.txt"), + "test-blspy-g1" => include_str!("../op-tests/test-blspy-g1.txt"), + "test-blspy-g2" => include_str!("../op-tests/test-blspy-g2.txt"), + "test-blspy-hash" => include_str!("../op-tests/test-blspy-hash.txt"), + "test-blspy-pairing" => include_str!("../op-tests/test-blspy-pairing.txt"), + "test-blspy-verify" => include_str!("../op-tests/test-blspy-verify.txt"), + "test-bls-zk" => include_str!("../op-tests/test-bls-zk.txt"), + "test-secp-verify" => include_str!("../op-tests/test-secp-verify.txt"), + "test-secp256k1" => include_str!("../op-tests/test-secp256k1.txt"), + "test-secp256r1" => include_str!("../op-tests/test-secp256r1.txt"), + "test-modpow" => include_str!("../op-tests/test-modpow.txt"), + "test-sha256" => include_str!("../op-tests/test-sha256.txt"), + "test-sha256tree" => include_str!("../op-tests/test-sha256tree.txt"), + "test-sha256tree-hash" => include_str!("../op-tests/test-sha256tree-hash.txt"), + "test-keccak256" => include_str!("../op-tests/test-keccak256.txt"), + "test-keccak256-generated" => { + include_str!("../op-tests/test-keccak256-generated.txt") + } + _ => panic!("unknown test file: {filename}"), + }; let funs = HashMap::from([ ("i", op_if as Opf), @@ -335,7 +365,6 @@ mod tests { ]); println!("Test cases from: {filename}"); - let test_cases = read_to_string(filename).expect("test file not found"); for t in test_cases.split('\n') { let t = t.trim(); if t.is_empty() { diff --git a/src/tests.rs b/src/tests.rs index f05eeb7c2..00363a8ba 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -2,6 +2,8 @@ use super::allocator::{Allocator, NodePtr}; use super::serde::node_from_bytes; use super::serde::node_to_bytes; use super::test_ops::node_eq; +#[cfg(target_arch = "wasm32")] +use wasm_bindgen_test::wasm_bindgen_test as test; fn test_serialize_roundtrip(a: &mut Allocator, n: NodePtr) { let vec = node_to_bytes(a, n).unwrap(); diff --git a/src/traverse_path.rs b/src/traverse_path.rs index 8499d8fe1..e93bdfa58 100644 --- a/src/traverse_path.rs +++ b/src/traverse_path.rs @@ -112,6 +112,8 @@ pub fn traverse_path_fast(allocator: &Allocator, mut node_index: u32, args: Node #[cfg(test)] mod tests { use super::*; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; #[test] fn test_msb_mask() { diff --git a/src/treehash.rs b/src/treehash.rs index ef1e80a9a..7bfe61452 100644 --- a/src/treehash.rs +++ b/src/treehash.rs @@ -97,6 +97,8 @@ pub fn tree_hash_costed(a: &mut Allocator, node: NodePtr, cost_remaining: Cost) #[cfg(test)] mod tests { use super::*; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::wasm_bindgen_test as test; fn test_sha256_atom(buf: &[u8]) { let hash = tree_hash_atom(buf); From 68742dfaa946440bbc320d4408fdd015f9a09192 Mon Sep 17 00:00:00 2001 From: arvidn Date: Sun, 1 Mar 2026 17:15:32 +0100 Subject: [PATCH 2/4] address 32 bit usize --- src/serde/parse_atom.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/serde/parse_atom.rs b/src/serde/parse_atom.rs index 8ae2a7fed..362a7df17 100644 --- a/src/serde/parse_atom.rs +++ b/src/serde/parse_atom.rs @@ -41,7 +41,8 @@ pub fn decode_size_with_offset(f: &mut R, initial_b: u8) -> Result<(u8, atom_size <<= 8; atom_size += *b as u64; } - if atom_size >= 0x400000000 { + // we assume atom sizes fit in usize, usize is 32 bits on wasm + if atom_size >= 0x80000000 { return Err(EvalErr::SerializationError); } Ok((atom_start_offset as u8, atom_size)) @@ -58,13 +59,14 @@ fn parse_atom_ptr<'a>(f: &'a mut Cursor<&[u8]>, first_byte: u8) -> Result<&'a [u let pos = f.position() as usize; &f.get_ref()[pos - 1..pos] } else { - let blob_size = decode_size(f, first_byte)?; - let pos = f.position() as usize; - if f.get_ref().len() < pos + blob_size as usize { + let blob_size = usize::try_from(decode_size(f, first_byte)?) + .map_err(|_| EvalErr::SerializationError)?; + let pos = usize::try_from(f.position()).map_err(|_| EvalErr::SerializationError)?; + if f.get_ref().len() < pos + blob_size { return Err(EvalErr::SerializationError); } f.seek(SeekFrom::Current(blob_size as i64))?; - &f.get_ref()[pos..(pos + blob_size as usize)] + &f.get_ref()[pos..(pos + blob_size)] }; Ok(blob) } @@ -110,11 +112,10 @@ mod tests { #[case(0b11001111, &[0xaa], (2, 0xfaa))] // this is *just* within what we support // Still a very large blob, probably enough for a DoS attack - #[case(0b11111100, &[0x3, 0xff, 0xff, 0xff, 0xff], (6, 0x3ffffffff))] + #[case(0b11111000, &[0x7f, 0xff, 0xff, 0xff], (5, 0x7fffffff))] #[case(0b11011111, &[0], (2, 0x1f00))] #[case(0b11101111, &[0, 0], (3, 0xf0000))] #[case(0b11110111, &[0, 0, 0], (4, 0x7000000))] - #[case(0b11111011, &[0, 0, 0, 0], (5, 0x300000000))] fn test_decode_size_success( #[case] first_b: u8, #[case] stream: &[u8], @@ -137,6 +138,7 @@ mod tests { // the stream is truncated #[case(0b11111100, &[0x4, 0, 0, 0], "bad encoding")] // atoms are too large + #[case(0b11111011, &[0, 0, 0, 0], "bad encoding")] #[case(0b11111101, &[0, 0, 0, 0, 0], "bad encoding")] #[case(0b11111110, &[0x80, 0, 0, 0, 0, 0], "bad encoding")] #[case(0b11111111, &[0x80, 0, 0, 0, 0, 0, 0], "bad encoding")] From 6e0a8536bf2f922dd7b3edd8fd92655dd52e473d Mon Sep 17 00:00:00 2001 From: arvidn Date: Wed, 4 Mar 2026 13:29:58 +0100 Subject: [PATCH 3/4] rayon doesn't work on wasm32, which is used by criterion. So benchmarks won't work on wasm32 --- Cargo.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e7eb7c129..71b178487 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -94,9 +94,11 @@ thiserror = "1.0.69" [dev-dependencies] rstest = { workspace = true } -criterion = { workspace = true } hex = { workspace = true } +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] +criterion = { workspace = true } + [target.'cfg(target_arch = "wasm32")'.dependencies] getrandom = { workspace = true, features = ["js"] } From 94c2221fa6b798ba7b52e0967eabad39055707ba Mon Sep 17 00:00:00 2001 From: arvidn Date: Wed, 4 Mar 2026 16:39:04 +0100 Subject: [PATCH 4/4] address tests for wasm32 --- src/allocator.rs | 99 ++++++++++++++++++++-------------- src/lib.rs | 13 +++++ src/more_ops.rs | 24 ++++----- src/op_utils.rs | 37 +++++++------ src/run_program.rs | 8 ++- src/serde/de_br.rs | 10 ++-- src/serde/parse_atom.rs | 13 +++-- src/serde/path_builder.rs | 5 +- src/serde/serialized_length.rs | 6 +-- src/serde/test_intern.rs | 4 +- src/serde/tools.rs | 26 ++++----- src/serde/tree_cache.rs | 8 +-- src/test_ops.rs | 12 ++--- 13 files changed, 144 insertions(+), 121 deletions(-) diff --git a/src/allocator.rs b/src/allocator.rs index 16ab06bdd..e1e5f4532 100644 --- a/src/allocator.rs +++ b/src/allocator.rs @@ -1076,10 +1076,8 @@ impl Allocator { mod tests { use super::*; use rstest::rstest; - #[cfg(target_arch = "wasm32")] - use wasm_bindgen_test::wasm_bindgen_test as test; - #[test] + #[crate::wasm_compat::test] fn test_atom_eq_1() { // these are a bunch of different representations of 1 // make sure they all compare equal @@ -1137,7 +1135,7 @@ mod tests { assert!(a.atom_eq(a5, a5)); } - #[test] + #[crate::wasm_compat::test] fn test_atom_eq_minus_1() { // these are a bunch of different representations of -1 // make sure they all compare equal @@ -1171,7 +1169,7 @@ mod tests { assert!(a.atom_eq(a3, a3)); } - #[test] + #[crate::wasm_compat::test] fn test_atom_eq() { let mut a = Allocator::new(); let a0 = a.nil(); @@ -1217,7 +1215,7 @@ mod tests { assert!(!a.atom_eq(a4, a5)); } - #[test] + #[crate::wasm_compat::test] #[should_panic] fn test_atom_eq_pair1() { let mut a = Allocator::new(); @@ -1226,7 +1224,7 @@ mod tests { a.atom_eq(pair, a0); } - #[test] + #[crate::wasm_compat::test] #[should_panic] fn test_atom_eq_pair2() { let mut a = Allocator::new(); @@ -1235,7 +1233,7 @@ mod tests { a.atom_eq(a0, pair); } - #[test] + #[crate::wasm_compat::test] #[should_panic] fn test_atom_len_pair() { let mut a = Allocator::new(); @@ -1244,7 +1242,7 @@ mod tests { a.atom_len(pair); } - #[test] + #[crate::wasm_compat::test] #[should_panic] fn test_number_pair() { let mut a = Allocator::new(); @@ -1254,7 +1252,7 @@ mod tests { } #[cfg(not(feature = "allocator-debug"))] - #[test] + #[crate::wasm_compat::test] #[should_panic] fn test_invalid_node_ptr_type() { let node = NodePtr(3 << NODE_PTR_IDX_BITS); @@ -1263,14 +1261,14 @@ mod tests { } #[cfg(debug_assertions)] - #[test] + #[crate::wasm_compat::test] #[should_panic] fn test_node_ptr_overflow() { NodePtr::new(ObjectType::Bytes, NODE_PTR_IDX_MASK as usize + 1); } #[cfg(debug_assertions)] - #[test] + #[crate::wasm_compat::test] #[should_panic] fn test_invalid_small_number() { let mut a = Allocator::new(); @@ -1278,6 +1276,7 @@ mod tests { } #[rstest] + #[crate::wasm_compat::test] #[case(0, 0)] #[case(1, 1)] #[case(0x7f, 1)] @@ -1292,7 +1291,7 @@ mod tests { assert_eq!(len_for_value(val), len); } - #[test] + #[crate::wasm_compat::test] fn test_nil() { let a = Allocator::new(); assert_eq!(a.atom(a.nil()).as_ref(), b""); @@ -1301,14 +1300,14 @@ mod tests { assert_eq!(a.nil(), NodePtr::NIL); } - #[test] + #[crate::wasm_compat::test] fn test_one() { let a = Allocator::new(); assert_eq!(a.atom(a.one()).as_ref(), b"\x01"); assert_eq!(a.sexp(a.one()), SExp::Atom); } - #[test] + #[crate::wasm_compat::test] fn test_allocate_atom() { let mut a = Allocator::new(); let atom = a.new_atom(b"foobar").unwrap(); @@ -1316,7 +1315,7 @@ mod tests { assert_eq!(a.sexp(atom), SExp::Atom); } - #[test] + #[crate::wasm_compat::test] fn test_allocate_pair() { let mut a = Allocator::new(); let atom1 = a.new_atom(b"foo").unwrap(); @@ -1329,7 +1328,7 @@ mod tests { assert_eq!(a.sexp(pair2), SExp::Pair(pair, pair)); } - #[test] + #[crate::wasm_compat::test] fn test_allocate_heap_limit() { let mut a = Allocator::new_limited(6); // we can't allocate 6 bytes @@ -1338,14 +1337,14 @@ mod tests { let _atom = a.new_atom(b"fooba").unwrap(); } - #[test] + #[crate::wasm_compat::test] fn test_new_atom_heap_limit() { let mut a = Allocator::new_limited(6); assert_eq!(a.new_atom(b"foobar").unwrap_err(), EvalErr::OutOfMemory); a.new_atom(b"fooba").unwrap(); } - #[test] + #[crate::wasm_compat::test] fn test_new_atom_small_value_heap_limit() { // small-atom-eligible values still count against the heap // ghost_heap starts at 1, so with limit=1 there are 0 bytes available @@ -1353,7 +1352,7 @@ mod tests { assert_eq!(a.new_atom(&[1]).unwrap_err(), EvalErr::OutOfMemory); } - #[test] + #[crate::wasm_compat::test] fn test_new_small_number_heap_limit() { let mut a = Allocator::new_limited(1); assert_eq!(a.new_small_number(1).unwrap_err(), EvalErr::OutOfMemory); @@ -1361,13 +1360,13 @@ mod tests { a.new_small_number(0).unwrap(); } - #[test] + #[crate::wasm_compat::test] fn test_new_number_small_path_heap_limit() { let mut a = Allocator::new_limited(1); assert_eq!(a.new_number(1.into()).unwrap_err(), EvalErr::OutOfMemory); } - #[test] + #[crate::wasm_compat::test] fn test_new_number_large_path_heap_limit() { // 0xff_ffff_ffff -> [0, 0xff, 0xff, 0xff, 0xff] = 5 bytes, limit allows 4 let mut a = Allocator::new_limited(5); @@ -1377,7 +1376,7 @@ mod tests { ); } - #[test] + #[crate::wasm_compat::test] fn test_new_g1_heap_limit() { let g1_bytes = hex::decode(VALID_G1).unwrap(); let g1 = G1Element::from_bytes(g1_bytes.as_slice().try_into().unwrap()).unwrap(); @@ -1389,7 +1388,7 @@ mod tests { Allocator::new_limited(49).new_g1(g1).unwrap(); } - #[test] + #[crate::wasm_compat::test] fn test_new_g2_heap_limit() { let g2_bytes = hex::decode(VALID_G2).unwrap(); let g2 = G2Element::from_bytes(g2_bytes.as_slice().try_into().unwrap()).unwrap(); @@ -1401,7 +1400,7 @@ mod tests { Allocator::new_limited(97).new_g2(g2).unwrap(); } - #[test] + #[crate::wasm_compat::test] fn test_new_concat_heap_limit() { let mut a = Allocator::new_limited(5); let atom = a.new_atom(&[0x80]).unwrap(); // 1 real heap byte (negative, not a small atom) @@ -1413,7 +1412,7 @@ mod tests { a.new_concat(3, &[atom, atom, atom]).unwrap(); } - #[test] + #[crate::wasm_compat::test] fn test_allocate_atom_limit() { let mut a = Allocator::new(); @@ -1426,7 +1425,7 @@ mod tests { assert_eq!(a.ghost_atoms, MAX_NUM_ATOMS); } - #[test] + #[crate::wasm_compat::test] fn test_allocate_small_number_limit() { let mut a = Allocator::new(); @@ -1439,7 +1438,7 @@ mod tests { assert_eq!(a.ghost_atoms, MAX_NUM_ATOMS); } - #[test] + #[crate::wasm_compat::test] fn test_allocate_substr_limit() { let mut a = Allocator::new(); @@ -1453,7 +1452,7 @@ mod tests { assert_eq!(a.ghost_atoms, MAX_NUM_ATOMS); } - #[test] + #[crate::wasm_compat::test] fn test_allocate_concat_limit() { let mut a = Allocator::new(); @@ -1467,7 +1466,7 @@ mod tests { assert_eq!(a.ghost_atoms, MAX_NUM_ATOMS); } - #[test] + #[crate::wasm_compat::test] fn test_allocate_pair_limit() { let mut a = Allocator::new(); let atom = a.new_atom(b"foo").unwrap(); @@ -1482,7 +1481,7 @@ mod tests { assert_eq!(a.add_ghost_pair(1).unwrap_err(), EvalErr::TooManyPairs); } - #[test] + #[crate::wasm_compat::test] fn test_ghost_pair_limit() { let mut a = Allocator::new(); let atom = a.new_atom(b"foo").unwrap(); @@ -1494,7 +1493,7 @@ mod tests { assert_eq!(a.add_ghost_pair(1).unwrap_err(), EvalErr::TooManyPairs); } - #[test] + #[crate::wasm_compat::test] fn test_substr() { let mut a = Allocator::new(); let atom = a.new_atom(b"foobar").unwrap(); @@ -1543,7 +1542,7 @@ mod tests { )); } - #[test] + #[crate::wasm_compat::test] fn test_substr_small_number() { let mut a = Allocator::new(); let atom = a.new_atom(b"a\x80").unwrap(); @@ -1589,7 +1588,7 @@ mod tests { )); } - #[test] + #[crate::wasm_compat::test] fn test_concat_launder_small_number() { let mut a = Allocator::new(); let atom1 = a.new_small_number(42).expect("new_small_number"); @@ -1609,7 +1608,7 @@ mod tests { assert_eq!(a.atom(atom2).as_ref(), &[42]); } - #[test] + #[crate::wasm_compat::test] fn test_concat() { let mut a = Allocator::new(); let atom1 = a.new_atom(b"f").unwrap(); @@ -1664,7 +1663,7 @@ mod tests { assert_eq!(a.new_concat(1, &[atom1]).unwrap(), atom1); } - #[test] + #[crate::wasm_compat::test] fn test_concat_large() { let mut a = Allocator::new(); let atom1 = a.new_atom(b"foo").unwrap(); @@ -1702,7 +1701,7 @@ mod tests { )); } - #[test] + #[crate::wasm_compat::test] fn test_sexp() { let mut a = Allocator::new(); let atom1 = a.new_atom(b"f").unwrap(); @@ -1714,7 +1713,7 @@ mod tests { assert_eq!(a.sexp(pair), SExp::Pair(atom1, atom2)); } - #[test] + #[crate::wasm_compat::test] fn test_concat_limit() { // the Allocator::one() is always allocated and uses 1 byte of heap let mut a = Allocator::new_limited(9); @@ -1736,6 +1735,7 @@ mod tests { } #[rstest] + #[crate::wasm_compat::test] #[case(0.into(), &[])] #[case(1.into(), &[1])] #[case((-1).into(), &[0xff])] @@ -1762,7 +1762,7 @@ mod tests { assert_eq!(number_from_u8(expected), num); } - #[test] + #[crate::wasm_compat::test] fn test_checkpoints() { let mut a = Allocator::new(); @@ -1811,6 +1811,7 @@ mod tests { type TestFun = fn(&Allocator, NodePtr) -> EvalErr; #[rstest] + #[crate::wasm_compat::test] #[case(test_g1, 0, "atom is not G1 size, 48 bytes")] #[case(test_g1, 3, "atom is not G1 size, 48 bytes")] #[case(test_g1, 47, "atom is not G1 size, 48 bytes")] @@ -1831,6 +1832,7 @@ mod tests { } #[rstest] + #[crate::wasm_compat::test] #[case(test_g1, "pair found, expected G1 point")] #[case(test_g2, "pair found, expected G2 point")] fn test_point_atom_pair(#[case] fun: TestFun, #[case] expected: &str) { @@ -1841,6 +1843,7 @@ mod tests { } #[rstest] + #[crate::wasm_compat::test] #[case( "\ 97f1d3a73197d7942695638c4fa9ac0f\ @@ -1882,6 +1885,7 @@ e28f75bb8f1c7c42c39a8c5529bf0f4e" } #[rstest] + #[crate::wasm_compat::test] #[case( "\ 93e02b6052719f607dacd3a088274f65\ @@ -2028,6 +2032,7 @@ c6c886f6b57ec72a6178288c47c33577\ */ #[rstest] + #[crate::wasm_compat::test] // round trip empty buffer #[case(EMPTY, make_buf, check_buf)] #[case(EMPTY, make_buf, check_number)] @@ -2104,6 +2109,7 @@ c6c886f6b57ec72a6178288c47c33577\ } #[rstest] + #[crate::wasm_compat::test] #[case(&[], 0)] #[case(&[1], 1)] #[case(&[1,2], 2)] @@ -2116,6 +2122,7 @@ c6c886f6b57ec72a6178288c47c33577\ } #[rstest] + #[crate::wasm_compat::test] #[case(0.into(), 0)] #[case(42.into(), 1)] #[case(127.into(), 1)] @@ -2131,6 +2138,7 @@ c6c886f6b57ec72a6178288c47c33577\ } #[rstest] + #[crate::wasm_compat::test] #[case( "\ 97f1d3a73197d7942695638c4fa9ac0f\ @@ -2154,6 +2162,7 @@ e28f75bb8f1c7c42c39a8c5529bf0f4e", } #[rstest] + #[crate::wasm_compat::test] #[case( "\ 93e02b6052719f607dacd3a088274f65\ @@ -2184,6 +2193,7 @@ c6c886f6b57ec72a6178288c47c33577\ } #[rstest] + #[crate::wasm_compat::test] #[case(0.into())] #[case(1.into())] #[case(0x7f.into())] @@ -2234,6 +2244,7 @@ c6c886f6b57ec72a6178288c47c33577\ } #[rstest] + #[crate::wasm_compat::test] #[case(0)] #[case(1)] #[case(0x7f)] @@ -2260,6 +2271,7 @@ c6c886f6b57ec72a6178288c47c33577\ } #[rstest] + #[crate::wasm_compat::test] #[case(0.into(), true)] #[case(1.into(), true)] #[case(0x3ffffff.into(), true)] @@ -2300,6 +2312,7 @@ c6c886f6b57ec72a6178288c47c33577\ } #[rstest] + #[crate::wasm_compat::test] #[case(0u64, &[])] #[case(1, &[1])] #[case(0x7f, &[0x7f])] @@ -2333,6 +2346,7 @@ c6c886f6b57ec72a6178288c47c33577\ } #[rstest] + #[crate::wasm_compat::test] #[case(0i64, &[])] #[case(1, &[1])] #[case(0x7f, &[0x7f])] @@ -2366,6 +2380,7 @@ c6c886f6b57ec72a6178288c47c33577\ } #[rstest] + #[crate::wasm_compat::test] // redundant leading zeros are not canoncial #[case(&[0x00], false)] #[case(&[0x00, 0x7f], false)] @@ -2396,6 +2411,7 @@ c6c886f6b57ec72a6178288c47c33577\ } #[rstest] + #[crate::wasm_compat::test] // redundant leading zeros are not canoncial #[case(&[0x00], None)] #[case(&[0x00, 0x7f], None)] @@ -2427,6 +2443,7 @@ c6c886f6b57ec72a6178288c47c33577\ } #[rstest] + #[crate::wasm_compat::test] // 0 is encoded as an empty string #[case(&[0], "0", &[])] #[case(&[1], "1", &[1])] @@ -2460,8 +2477,6 @@ mod debug_tests { use chia_bls::PublicKey; use chia_bls::Signature; use rstest::rstest; - #[cfg(target_arch = "wasm32")] - use wasm_bindgen_test::wasm_bindgen_test as test; fn new_node(a: &mut Allocator, case: u8) -> (NodePtr, usize) { match case { @@ -2538,6 +2553,7 @@ mod debug_tests { } #[rstest] + #[crate::wasm_compat::test] #[should_panic(expected = "using a NodePtr on the wrong Allocator")] fn mixing_allocators( #[values(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)] create_case: u8, @@ -2551,6 +2567,7 @@ mod debug_tests { } #[rstest] + #[crate::wasm_compat::test] #[should_panic(expected = "was invalidated by restore_checkpoint()")] fn invalidating_node( #[values(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)] create_case: u8, diff --git a/src/lib.rs b/src/lib.rs index b0c582cb4..275b1a163 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,6 +34,19 @@ pub use run_program::run_program_with_pre_eval; #[cfg(feature = "counters")] pub use run_program::Counters; +// rstest only detects alternative test attributes whose last path segment is +// `test`. Re-exporting the right test macro under that name lets us write +// `#[crate::wasm_compat::test]` on rstest functions and have it resolve to +// `#[wasm_bindgen_test]` on wasm32 or the standard `#[test]` everywhere else. +#[cfg(test)] +pub(crate) mod wasm_compat { + #[cfg(target_arch = "wasm32")] + pub use wasm_bindgen_test::wasm_bindgen_test as test; + + #[cfg(not(target_arch = "wasm32"))] + pub use std::prelude::v1::test; +} + #[cfg(test)] mod tests; diff --git a/src/more_ops.rs b/src/more_ops.rs index 5562465ae..a5734cf5d 100644 --- a/src/more_ops.rs +++ b/src/more_ops.rs @@ -5,9 +5,6 @@ use std::ops::BitAndAssign; use std::ops::BitOrAssign; use std::ops::BitXorAssign; -#[cfg(all(test, target_arch = "wasm32"))] -use wasm_bindgen_test::wasm_bindgen_test as test; - use crate::allocator::{Allocator, NodePtr, NodeVisitor, SExp, len_for_value}; use crate::cost::{Cost, check_cost}; use crate::error::EvalErr; @@ -115,7 +112,8 @@ fn limb_test_helper(bytes: &[u8]) { assert_eq!(limbs_for_int(&bigint), expected); } -#[test] +#[cfg(test)] +#[crate::wasm_compat::test] fn test_limbs_for_int() { limb_test_helper(&[]); limb_test_helper(&[0x1]); @@ -272,7 +270,8 @@ fn test_op_unknown(buf: &[u8], a: &mut Allocator, n: NodePtr) -> Response { op_unknown(a, buf, n, 1000000) } -#[test] +#[cfg(test)] +#[crate::wasm_compat::test] fn test_unknown_op_reserved() { let mut a = Allocator::new(); @@ -310,7 +309,8 @@ fn test_unknown_op_reserved() { ); } -#[test] +#[cfg(test)] +#[crate::wasm_compat::test] fn test_lenient_mode_last_bits() { let mut a = Allocator::new(); @@ -793,7 +793,8 @@ fn test_shift( op(a, args, 10000000 as Cost) } -#[test] +#[cfg(test)] +#[crate::wasm_compat::test] fn test_op_ash() { let mut a = Allocator::new(); @@ -847,7 +848,8 @@ pub fn op_lsh(a: &mut Allocator, input: NodePtr, _max_cost: Cost) -> Response { Ok(malloc_cost(a, cost, r)) } -#[test] +#[cfg(test)] +#[crate::wasm_compat::test] fn test_op_lsh() { let mut a = Allocator::new(); @@ -1092,9 +1094,6 @@ pub fn op_modpow(a: &mut Allocator, input: NodePtr, max_cost: Cost) -> Response mod tests { use super::*; use rstest::rstest; - #[cfg(target_arch = "wasm32")] - use wasm_bindgen_test::wasm_bindgen_test as test; - fn test_sha256_atom(buf: &[u8]) { let mut a = Allocator::new(); let mut args = a.nil(); @@ -1120,7 +1119,7 @@ mod tests { assert_eq!(actual_cost, cost); } - #[test] + #[crate::wasm_compat::test] fn sha256_small_values() { test_sha256_atom(&[]); for val in 0..255 { @@ -1137,6 +1136,7 @@ mod tests { } #[rstest] + #[crate::wasm_compat::test] #[case::sha(op_sha256, 28, 11, None)] #[case::sha(op_sha256, 28, 12, Some(EvalErr::CostExceeded))] #[case::add(op_add, 27, 3, None)] diff --git a/src/op_utils.rs b/src/op_utils.rs index 5c5875199..6ac7fd32b 100644 --- a/src/op_utils.rs +++ b/src/op_utils.rs @@ -257,13 +257,10 @@ pub fn int_atom(a: &Allocator, args: NodePtr, op_name: &str) -> Result<(Number, #[cfg(test)] mod tests { - use rstest::rstest; - #[cfg(target_arch = "wasm32")] - use wasm_bindgen_test::wasm_bindgen_test as test; - use super::*; + use rstest::rstest; - #[test] + #[crate::wasm_compat::test] fn test_get_args() { let mut a = Allocator::new(); let a0 = a.new_number(42.into()).unwrap(); @@ -309,7 +306,7 @@ mod tests { ); } - #[test] + #[crate::wasm_compat::test] fn test_get_varargs() { let mut a = Allocator::new(); let a0 = a.new_number(42.into()).unwrap(); @@ -357,7 +354,7 @@ mod tests { ); } - #[test] + #[crate::wasm_compat::test] fn test_nilp() { let mut a = Allocator::new(); let a0 = a.new_number(42.into()).unwrap(); @@ -374,7 +371,7 @@ mod tests { assert!(nilp(&a, a5)); } - #[test] + #[crate::wasm_compat::test] fn test_first() { let mut a = Allocator::new(); let a0 = a.new_number(42.into()).unwrap(); @@ -389,7 +386,7 @@ mod tests { ); } - #[test] + #[crate::wasm_compat::test] fn test_rest() { let mut a = Allocator::new(); let a0 = a.new_number(42.into()).unwrap(); @@ -402,6 +399,7 @@ mod tests { } #[rstest] + #[crate::wasm_compat::test] #[case(0.into(), (0.into(), 0))] #[case(1.into(), (1.into(), 1))] #[case(42.into(), (42.into(), 1))] @@ -414,7 +412,7 @@ mod tests { assert_eq!(int_atom(&a, a0, "test").unwrap(), expected); } - #[test] + #[crate::wasm_compat::test] fn test_int_atom_failure() { let mut a = Allocator::new(); let a0 = a.new_number(42.into()).unwrap(); @@ -427,7 +425,7 @@ mod tests { ); } - #[test] + #[crate::wasm_compat::test] fn test_atom_len() { let mut a = Allocator::new(); @@ -447,6 +445,7 @@ mod tests { // u32, 4 bytes #[rstest] + #[crate::wasm_compat::test] #[case(&[0], 0)] #[case(&[0,0,0,1], 1)] #[case(&[0,0xff,0xff,0xff,0xff], 0xffffffff)] @@ -465,6 +464,7 @@ mod tests { // u32, 4 bytes #[rstest] + #[crate::wasm_compat::test] #[case(&[0xff,0xff,0xff,0xff], "test requires positive int arg")] #[case(&[0xff], "test requires positive int arg")] #[case(&[0x80], "test requires positive int arg")] @@ -482,6 +482,7 @@ mod tests { // u32, 4 bytes #[rstest] + #[crate::wasm_compat::test] #[case(&[0x00,0x7f,0xff,0xff], "test requires u32 arg with no leading zeros")] #[case(&[0x00, 0x00, 0x01], "test requires u32 arg with no leading zeros")] #[case(&[0xff,0xff,0xff,0xff], "test requires positive int arg")] @@ -499,7 +500,7 @@ mod tests { ); } - #[test] + #[crate::wasm_compat::test] fn test_uint_atom_4_pair() { use crate::allocator::Allocator; let mut a = Allocator::new(); @@ -516,6 +517,7 @@ mod tests { // u64, 8 bytes #[rstest] + #[crate::wasm_compat::test] #[case(&[0], 0)] #[case(&[0,0,0,1], 1)] #[case(&[0,0xff,0xff,0xff,0xff], 0xffffffff)] @@ -538,6 +540,7 @@ mod tests { // u64, 8 bytes #[rstest] + #[crate::wasm_compat::test] #[case(&[0xff,0xff,0xff,0xff],"test requires positive int arg")] #[case(&[0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff], "test requires positive int arg")] #[case(&[0xff], "test requires positive int arg")] @@ -554,7 +557,7 @@ mod tests { ); } - #[test] + #[crate::wasm_compat::test] fn test_uint_atom_8_pair() { use crate::allocator::Allocator; let mut a = Allocator::new(); @@ -569,7 +572,7 @@ mod tests { ); } - #[test] + #[crate::wasm_compat::test] fn test_u32_from_u8() { assert_eq!(u32_from_u8(&[]), Some(0)); assert_eq!(u32_from_u8(&[0xcc]), Some(0xcc)); @@ -595,7 +598,7 @@ mod tests { assert_eq!(u32_from_u8(&[0x7d, 0xcc, 0x55, 0x88, 0xf3]), None); } - #[test] + #[crate::wasm_compat::test] fn test_i32_from_u8() { assert_eq!(i32_from_u8(&[]), Some(0)); assert_eq!(i32_from_u8(&[0xcc]), Some(-52)); @@ -622,7 +625,7 @@ mod tests { assert_eq!(i32_from_u8(&[0x7d, 0xcc, 0x55, 0x88, 0xf3]), None); } - #[test] + #[crate::wasm_compat::test] fn test_u64_from_bytes() { assert_eq!(u64_from_bytes(&[]), 0); assert_eq!(u64_from_bytes(&[0xcc]), 0xcc); @@ -647,7 +650,7 @@ mod tests { ); } - #[test] + #[crate::wasm_compat::test] fn test_i32_atom() { let mut a = Allocator::new(); diff --git a/src/run_program.rs b/src/run_program.rs index 23b5784c9..42d29c782 100644 --- a/src/run_program.rs +++ b/src/run_program.rs @@ -558,9 +558,6 @@ pub fn run_program_with_counters<'a, D: Dialect>( #[cfg(test)] mod tests { use super::*; - #[cfg(target_arch = "wasm32")] - use wasm_bindgen_test::wasm_bindgen_test as test; - use crate::chia_dialect::ClvmFlags; use crate::test_ops::parse_exp; @@ -1386,7 +1383,7 @@ mod tests { } } - #[test] + #[crate::wasm_compat::test] fn test_run_program() { for t in TEST_CASES { run_test_case(t); @@ -1405,6 +1402,7 @@ mod tests { // raises the exception. // This property is relied on for the non-mempool and fork-not-activated cases. #[rstest] + #[crate::wasm_compat::test] // make sure we can execute the coinid operator under softfork 0 // this program raises an exception if the computed coin ID matches the // expected @@ -1605,7 +1603,7 @@ mod tests { } #[cfg(feature = "counters")] - #[test] + #[crate::wasm_compat::test] fn test_counters() { use crate::chia_dialect::ChiaDialect; diff --git a/src/serde/de_br.rs b/src/serde/de_br.rs index 3538cbca0..7ddd228c5 100644 --- a/src/serde/de_br.rs +++ b/src/serde/de_br.rs @@ -205,16 +205,14 @@ pub fn traverse_path_with_vec( #[cfg(test)] mod tests { - use crate::test_ops::node_eq; - #[cfg(target_arch = "wasm32")] - use wasm_bindgen_test::wasm_bindgen_test as test; - use super::*; + use crate::test_ops::node_eq; use rstest::rstest; use hex::FromHex; #[rstest] + #[crate::wasm_compat::test] // ("foobar" "foobar") #[case( "ff86666f6f626172ff86666f6f62617280", @@ -270,7 +268,7 @@ mod tests { assert_eq!(expected_hash, ch); } - #[test] + #[crate::wasm_compat::test] fn test_counters() { use crate::allocator::Allocator; @@ -293,7 +291,7 @@ mod tests { assert_eq!(pair_count, old_pair_count); } - #[test] + #[crate::wasm_compat::test] fn test_traverse_path_with_vec() { use crate::allocator::Allocator; diff --git a/src/serde/parse_atom.rs b/src/serde/parse_atom.rs index 362a7df17..3b1412a90 100644 --- a/src/serde/parse_atom.rs +++ b/src/serde/parse_atom.rs @@ -102,10 +102,8 @@ mod tests { use super::*; use crate::serde::write_atom::write_atom; use rstest::rstest; - #[cfg(target_arch = "wasm32")] - use wasm_bindgen_test::wasm_bindgen_test as test; - #[rstest] + #[crate::wasm_compat::test] // single-byte length prefix #[case(0b10100000, &[], (1, 0x20))] // two-byte length prefix @@ -127,6 +125,7 @@ mod tests { } #[rstest] + #[crate::wasm_compat::test] // this is an atom length-prefix 0xffffffffffff, or (2^48 - 1). // We don't support atoms this large and we should fail before attempting to // allocate this much memory @@ -153,7 +152,7 @@ mod tests { } #[cfg(debug_assertions)] - #[test] + #[crate::wasm_compat::test] #[should_panic] fn test_decode_size_panic() { let mut stream = Cursor::new(&[0x4, 0, 0, 0]); @@ -161,7 +160,7 @@ mod tests { } #[cfg(not(debug_assertions))] - #[test] + #[crate::wasm_compat::test] fn test_decode_size_panic() { let mut stream = Cursor::new(&[0x4, 0, 0, 0]); assert_eq!( @@ -192,7 +191,7 @@ mod tests { check_parse_atom(&blob, expected_atom); } - #[test] + #[crate::wasm_compat::test] fn test_parse_atom() { check_parse_atom_str("80", ""); // try "00", "01", "02", ..., "7f" @@ -218,7 +217,7 @@ mod tests { } } - #[test] + #[crate::wasm_compat::test] fn test_truncated_parse_atom() { // the stream is truncated let first = 0b11111100; diff --git a/src/serde/path_builder.rs b/src/serde/path_builder.rs index 468280386..d04485672 100644 --- a/src/serde/path_builder.rs +++ b/src/serde/path_builder.rs @@ -122,9 +122,6 @@ mod tests { use crate::serde::serialized_length_atom; use hex; use rstest::rstest; - #[cfg(target_arch = "wasm32")] - use wasm_bindgen_test::wasm_bindgen_test as test; - fn build_path<'a>(a: &'a Bump, input: &[u8]) -> PathBuilder<'a> { let mut path = PathBuilder::default(); // keep in mind that paths are built in reverse order (starting from the @@ -144,6 +141,7 @@ mod tests { } #[rstest] + #[crate::wasm_compat::test] #[case(&[1], "01")] #[case(&[1,0], "02")] #[case(&[1,0,0], "04")] @@ -170,6 +168,7 @@ mod tests { } #[rstest] + #[crate::wasm_compat::test] #[case(0)] #[case(1)] #[case(6)] diff --git a/src/serde/serialized_length.rs b/src/serde/serialized_length.rs index ea88be5c8..a4a33e2b7 100644 --- a/src/serde/serialized_length.rs +++ b/src/serde/serialized_length.rs @@ -45,10 +45,8 @@ pub fn atom_length_bits(num_bits: u64) -> Option { mod tests { use super::*; use rstest::rstest; - #[cfg(target_arch = "wasm32")] - use wasm_bindgen_test::wasm_bindgen_test as test; - #[rstest] + #[crate::wasm_compat::test] #[case(&[], 1)] #[case(&[1], 1)] #[case(&[0x7f], 1)] @@ -62,6 +60,7 @@ mod tests { } #[rstest] + #[crate::wasm_compat::test] #[case(0, 1)] #[case(1, 2)] #[case(0x7f, 2)] @@ -77,6 +76,7 @@ mod tests { } #[rstest] + #[crate::wasm_compat::test] #[case(0, Some(1))] #[case(1, Some(1))] #[case(7, Some(1))] diff --git a/src/serde/test_intern.rs b/src/serde/test_intern.rs index 841499be4..df94d5743 100644 --- a/src/serde/test_intern.rs +++ b/src/serde/test_intern.rs @@ -6,9 +6,6 @@ use crate::serde::node_from_bytes_backrefs; use crate::serde::node_to_bytes; use crate::serde::object_cache::{ObjectCache, treehash}; use rstest::rstest; -#[cfg(target_arch = "wasm32")] -use wasm_bindgen_test::wasm_bindgen_test as test; - fn treehash_for_node(allocator: &Allocator, node: NodePtr) -> Bytes32 { let mut object_cache = ObjectCache::new(treehash); *object_cache @@ -72,6 +69,7 @@ fn test_hex_interning(hex: &str, expected_atoms: usize, expected_pairs: usize) - // ======================================================== #[rstest] +#[crate::wasm_compat::test] #[case("01", 1, 0)] // Simple atom 1: 1 atom, 0 pairs #[case("0a", 1, 0)] // Atom 10: 1 atom, 0 pairs #[case("ff0101", 1, 1)] // (1 . 1): 1 atom (deduplicated), 1 pair diff --git a/src/serde/tools.rs b/src/serde/tools.rs index ad8d63c45..8f2f63f2e 100644 --- a/src/serde/tools.rs +++ b/src/serde/tools.rs @@ -243,10 +243,7 @@ mod tests { use crate::serde::node_from_bytes_backrefs; use hex::FromHex; use rstest::rstest; - #[cfg(target_arch = "wasm32")] - use wasm_bindgen_test::wasm_bindgen_test as test; - - #[test] + #[crate::wasm_compat::test] fn test_tree_hash_max_single_byte() { let mut ctx = Sha256::new(); ctx.update([1_u8]); @@ -258,7 +255,7 @@ mod tests { ); } - #[test] + #[crate::wasm_compat::test] fn test_tree_hash_one() { let mut ctx = Sha256::new(); ctx.update([1_u8]); @@ -270,7 +267,7 @@ mod tests { ); } - #[test] + #[crate::wasm_compat::test] fn test_tree_hash_zero() { let mut ctx = Sha256::new(); ctx.update([1_u8]); @@ -282,7 +279,7 @@ mod tests { ); } - #[test] + #[crate::wasm_compat::test] fn test_tree_hash_nil() { let mut ctx = Sha256::new(); ctx.update([1_u8]); @@ -293,7 +290,7 @@ mod tests { ); } - #[test] + #[crate::wasm_compat::test] fn test_tree_hash_overlong() { let mut cursor = Cursor::<&[u8]>::new(&[0x8f, 0xff]); let e = tree_hash_from_stream(&mut cursor).unwrap_err(); @@ -315,7 +312,7 @@ mod tests { // print(bytes(a).hex()) // print(a.get_tree_hash().hex()) - #[test] + #[crate::wasm_compat::test] fn test_tree_hash_list() { // this is the list (1 (2 (3 (4 (5 ()))))) let buf = Vec::from_hex("ff01ff02ff03ff04ff0580").unwrap(); @@ -327,7 +324,7 @@ mod tests { ); } - #[test] + #[crate::wasm_compat::test] fn test_tree_hash_tree() { // this is the tree ((1, 2), (3, 4)) let buf = Vec::from_hex("ffff0102ff0304").unwrap(); @@ -339,7 +336,7 @@ mod tests { ); } - #[test] + #[crate::wasm_compat::test] fn test_tree_hash_tree_large_atom() { // this is the tree ((1, 2), (3, b"foobar")) let buf = Vec::from_hex("ffff0102ff0386666f6f626172").unwrap(); @@ -351,7 +348,7 @@ mod tests { ); } - #[test] + #[crate::wasm_compat::test] fn test_serialized_length_from_bytes_trusted() { assert_eq!( serialized_length_from_bytes_trusted(&[0x7f, 0x00, 0x00, 0x00]).unwrap(), @@ -396,7 +393,7 @@ mod tests { ); } - #[test] + #[crate::wasm_compat::test] fn test_serialized_length_from_bytes() { assert_eq!( serialized_length_from_bytes(&[0x7f, 0x00, 0x00, 0x00]).unwrap(), @@ -437,6 +434,7 @@ mod tests { } #[rstest] + #[crate::wasm_compat::test] // ("foobar" "foobar") #[case("ff86666f6f626172ff86666f6f62617280")] // ("foobar" "foobar") @@ -588,6 +586,7 @@ ae5c3c40c50832a7aecc0b3ba4646568a00c01289c45e1f03b2b488080808080" } #[rstest] + #[crate::wasm_compat::test] #[case("c000")] #[case("c03f")] #[case("e00000")] @@ -618,6 +617,7 @@ ae5c3c40c50832a7aecc0b3ba4646568a00c01289c45e1f03b2b488080808080" } #[rstest] + #[crate::wasm_compat::test] #[case("c040", 66)] #[case("e02000", 8195)] #[case("f0100000", 1048580)] diff --git a/src/serde/tree_cache.rs b/src/serde/tree_cache.rs index 31587f1a2..ec7ec5eac 100644 --- a/src/serde/tree_cache.rs +++ b/src/serde/tree_cache.rs @@ -582,10 +582,7 @@ impl TreeCache { mod tests { use super::*; use rstest::rstest; - #[cfg(target_arch = "wasm32")] - use wasm_bindgen_test::wasm_bindgen_test as test; - - #[test] + #[crate::wasm_compat::test] fn test_basic_tree() { let mut a = Allocator::new(); // build this test tree: @@ -674,6 +671,7 @@ mod tests { } #[rstest] + #[crate::wasm_compat::test] #[case(0, Some(vec![0b10]))] #[case(1, Some(vec![0b100]))] #[case(2, Some(vec![0b1000]))] @@ -718,6 +716,7 @@ mod tests { } #[rstest] + #[crate::wasm_compat::test] #[case(0, Some(vec![0b10]))] #[case(1, Some(vec![0b101]))] #[case(2, Some(vec![0b1011]))] @@ -763,6 +762,7 @@ mod tests { } #[rstest] + #[crate::wasm_compat::test] #[case(0, Some(vec![0b10]))] #[case(1, Some(vec![0b100]))] #[case(2, Some(vec![0b1000]))] diff --git a/src/test_ops.rs b/src/test_ops.rs index 687728f39..589eaf54d 100644 --- a/src/test_ops.rs +++ b/src/test_ops.rs @@ -208,9 +208,6 @@ pub fn node_eq(allocator: &Allocator, s1: NodePtr, s2: NodePtr) -> bool { #[cfg(test)] mod tests { use super::*; - #[cfg(target_arch = "wasm32")] - use wasm_bindgen_test::wasm_bindgen_test as test; - #[cfg(feature = "pre-eval")] use crate::chia_dialect::{ChiaDialect, ClvmFlags}; @@ -256,6 +253,7 @@ mod tests { } #[rstest] + #[crate::wasm_compat::test] #[case("test-core-ops")] #[case("test-more-ops")] #[case("test-bls-ops")] @@ -395,7 +393,7 @@ mod tests { } } - #[test] + #[crate::wasm_compat::test] fn test_single_argument_raise_atom() { let mut allocator = Allocator::new(); let a1 = allocator.new_atom(&[65]).unwrap(); @@ -404,7 +402,7 @@ mod tests { assert_eq!(result.unwrap_err(), EvalErr::Raise(a1)); } - #[test] + #[crate::wasm_compat::test] fn test_single_argument_raise_pair() { let mut allocator = Allocator::new(); let a1 = allocator.new_atom(&[65]).unwrap(); @@ -419,7 +417,7 @@ mod tests { assert_eq!(result.unwrap_err(), EvalErr::Raise(args)); } - #[test] + #[crate::wasm_compat::test] fn test_multi_argument_raise() { let mut allocator = Allocator::new(); let a1 = allocator.new_atom(&[65]).unwrap(); @@ -453,7 +451,7 @@ mod tests { // Ensure pre_eval_f and post_eval_f are working as expected. #[cfg(feature = "pre-eval")] - #[test] + #[crate::wasm_compat::test] fn test_pre_eval_and_post_eval() { let mut allocator = Allocator::new();