From 4eeee5dc3bafb27f92e85c2ad16a2ee291b2d198 Mon Sep 17 00:00:00 2001 From: EnRaiha <15997552+EnRaiha@users.noreply.github.com> Date: Sun, 27 Sep 2026 23:56:46 +0800 Subject: [PATCH] test(codec): ignore the zstd encoder tests on wasm32 rather than abort the suite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `nodedb-codec` gates its codec by target already: C libzstd off wasm, ruzstd on it (`Cargo.toml:31-36`), and `compress_native`'s wasm arm is an explicit stub returning `CompressFailed` (`src/zstd_codec.rs:312-320`). The eight tests that call `encode`/`encode_with_level` therefore panic, and on `wasm32-wasip1` a panic aborts the process: the binary dies at the first one and reports nothing after it. The stub is a design choice rather than a missing dependency: ruzstd 0.9 ships an encoder (`ruzstd::encoding`) this crate has not adopted, and the C library would need a C-to-WASM toolchain. Wiring up either one changes what the wasm build does and is a change of its own; this commit only stops the absent encoder from killing the suite. No fallback exists in this crate — `pipeline` propagates `CompressFailed` for `ColumnCodec::Zstd`. The stub's own comments said it was a fallback that encodes "a minimal Zstd frame", which it never did; they now describe the stub. They are gated with `#[cfg_attr(target_arch = "wasm32", ignore = "…")]` rather than `#[cfg(not(target_arch = "wasm32"))]`. The attribute keeps them compiled and listed by `--list` on that target, so the gap is visible in the run instead of absent from it, and they keep running natively. Red arm, with the four tests other changes own skipped: $ cargo test --profile ci --target wasm32-wasip1 -p nodedb-codec -- <4 skips> test zstd_codec::tests::better_ratio_than_lz4 ... Error: failed to run main module exit 134 Green arm, same command: test result: ok. 252 passed; 0 failed; 8 ignored; 0 measured; 4 filtered out Each ignored test prints its reason: test zstd_codec::tests::empty_data ... ignored, nodedb-codec has no wasm encoder: encode() returns CompressFailed Native is unchanged at 263 passed, 0 failed, 0 ignored. The module's other four tests stay live on both targets: three are decode-side, and `streaming_input_limit_precedes_buffer_growth` drives the encoder's declared-limit check, which rejects before any encoder work. Why an in-source ignore and not a `--skip` list in the consumer: the gap is categorical — the target has no encoder at all, not a threshold that moves — and a named skip in someone else's workflow records it as a number rather than as a property of this crate. fmt clean; clippy clean for this crate on native and on `wasm32-wasip1`. --- nodedb-codec/src/zstd_codec.rs | 52 ++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/nodedb-codec/src/zstd_codec.rs b/nodedb-codec/src/zstd_codec.rs index d97222e02..7edc9effb 100644 --- a/nodedb-codec/src/zstd_codec.rs +++ b/nodedb-codec/src/zstd_codec.rs @@ -303,17 +303,16 @@ fn decompress_native(frame: &[u8], expected_size: usize) -> Result, Code Ok(output) } -// WASM: use ruzstd for decompression. Compression on WASM uses a simple -// fallback (ruzstd is decode-only; if full Zstd encoding is needed on WASM, -// we'd need the zstd crate compiled to WASM via C-to-WASM toolchain). -// For Pattern C (Lite-local), cold compression happens infrequently, so -// we fall back to LZ4 encoding on WASM and only support Zstd decoding. +// WASM: decoding uses ruzstd. Encoding returns `CompressFailed`: the C library is +// not built for this target and ruzstd's encoder is not adopted here, so a wasm +// caller that needs compression picks another codec. Adopting `ruzstd::encoding` +// is a change of its own; getting the C library there would need a C-to-WASM +// toolchain. #[cfg(target_arch = "wasm32")] fn compress_native(_data: &[u8], _level: i32) -> Result, CodecError> { - // ruzstd is decode-only. On WASM, we encode using a minimal Zstd frame. - // For production WASM builds that need Zstd encoding, compile the C zstd - // library to WASM. For now, return an error directing callers to use LZ4. + // No encoder is wired up here. This is a stub, not a fallback: it encodes + // nothing, and the error below is what every caller sees. Err(CodecError::CompressFailed { detail: "Zstd encoding not available on WASM — use LZ4 codec instead".into(), }) @@ -431,7 +430,16 @@ impl ZstdDecoder { mod tests { use super::*; + // The eight encoder tests are ignored on `wasm32` rather than removed: + // `compress_native` returns `CompressFailed` there by design, so `encode` + // cannot succeed. `cfg_attr(ignore)` keeps them running natively and visible + // in `--list` on wasm; the tests that do not encode stay live on both. + #[test] + #[cfg_attr( + target_arch = "wasm32", + ignore = "nodedb-codec has no wasm encoder: encode() returns CompressFailed" + )] fn empty_data() { let encoded = encode(&[]).unwrap(); let decoded = decode(&encoded).unwrap(); @@ -439,6 +447,10 @@ mod tests { } #[test] + #[cfg_attr( + target_arch = "wasm32", + ignore = "nodedb-codec has no wasm encoder: encode() returns CompressFailed" + )] fn small_data_roundtrip() { let data = b"hello world, zstd compression test"; let encoded = encode(data).unwrap(); @@ -447,6 +459,10 @@ mod tests { } #[test] + #[cfg_attr( + target_arch = "wasm32", + ignore = "nodedb-codec has no wasm encoder: encode() returns CompressFailed" + )] fn large_data_roundtrip() { let line = "2024-01-15 ERROR database connection timeout host=db-prod-01 retry=3\n"; let data: Vec = line.as_bytes().repeat(1000); @@ -462,6 +478,10 @@ mod tests { } #[test] + #[cfg_attr( + target_arch = "wasm32", + ignore = "nodedb-codec has no wasm encoder: encode() returns CompressFailed" + )] fn high_compression_level() { let data: Vec = (0..10_000).map(|i| (i % 256) as u8).collect(); let default_encoded = encode(&data).unwrap(); @@ -476,6 +496,10 @@ mod tests { } #[test] + #[cfg_attr( + target_arch = "wasm32", + ignore = "nodedb-codec has no wasm encoder: encode() returns CompressFailed" + )] fn header_metadata() { let data = vec![42u8; 1000]; let encoded = encode_with_level(&data, 7).unwrap(); @@ -485,6 +509,10 @@ mod tests { } #[test] + #[cfg_attr( + target_arch = "wasm32", + ignore = "nodedb-codec has no wasm encoder: encode() returns CompressFailed" + )] fn better_ratio_than_lz4() { // Structured data where Zstd should beat LZ4. let mut data = Vec::new(); @@ -552,6 +580,10 @@ mod tests { } #[test] + #[cfg_attr( + target_arch = "wasm32", + ignore = "nodedb-codec has no wasm encoder: encode() returns CompressFailed" + )] fn streaming_encoder() { let parts: Vec<&[u8]> = vec![b"part one ", b"part two ", b"part three"]; let full: Vec = parts.iter().flat_map(|p| p.iter().copied()).collect(); @@ -585,6 +617,10 @@ mod tests { } #[test] + #[cfg_attr( + target_arch = "wasm32", + ignore = "nodedb-codec has no wasm encoder: encode() returns CompressFailed" + )] fn level_clamping() { let data = b"test data for clamping"; // Level 0 → clamped to 1, level 99 → clamped to 22.