Latest Results
test(core): add property-based round-trip tests (#632)
The integration tests round-trip fixed inputs at the default level and
at a handful of chunk sizes, so bugs that depend on where a chunk
boundary falls, on a particular level or on the dictionary contents
could go unnoticed.
Add proptest as a dev-dependency of comprs-core and a test that
generates inputs of up to 32 KiB mixing noise with runs, repeated
patterns and text-like data, chunk-size sequences of 1 to 4095 bytes,
levels over each format's range (gzip, deflate and brotli 0-9, zstd -5
to 19) and dictionaries. For every format, including the zstd and
brotli dictionary variants, it checks that chunked context compression
followed by one-shot decompression, and one-shot compression followed
by chunked context decompression, return the input. It also checks
that one-shot and chunked context decompression both fail on a random
strict, non-empty prefix of a stream written by the one-shot encoder
or the stream context. Every format marks where its single stream or
frame ends and both kinds of decoder reject input that stops before
it, so no prefix is exempt.
Each property runs 64 cases; the three take about 3 s in a debug
build. proptest 1.11 supports Rust 1.85, below the declared MSRV, and
adds no duplicate crate versions.
Closes #538
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DRi2Qu5rPjQSDBcR8xmkSS build(wasm): shrink the WASM binary and report its real size (#622)
* build(wasm): compile the browser binary for size and drop wasm-opt
The browser binary was built with the release profile of the native
addon (opt-level 3), and the wasm-opt step that was meant to shrink it
never ran in CI, because the wasm-bindgen jobs do not install binaryen
and scripts/optimize-wasm.js skipped it silently. 2.0.2 shipped a
2.2 MB binary that nothing had optimized for size.
Build it with a wasm-release profile that inherits the release profile
(fat LTO, one codegen unit) with opt-level "s". Sizes in bytes, with
gzip and brotli from Node.js's zlib:
build raw gzip -9 brotli 11
opt-level 3 2,367,039 925,309 621,379
opt-level "s" 1,866,742 792,050 545,262
opt-level "z" 1,774,624 754,445 527,674
"s" downloads 14% smaller with gzip and 12% with brotli. In a short
benchmark of every codec on 1 MiB of JavaScript source, brotli
compression becomes about 40% slower, brotli decompression 30%, gzip
decompression 20% and LZ4 compression 10%; zstd, gzip compression and
LZ4 decompression keep their speed. "z" would save 3-5% more but halve
LZ4 throughput and slow zstd compression by 30%.
wasm-opt is gone rather than fixed: every level of it (-O1 to -O3, -Os,
-Oz) shrinks the raw binary by 4-11% but makes the gzip download 1-3%
and the brotli download 1-5% larger, whatever the opt-level. None of
its individual passes saves more than 0.2% with gzip, which does not
pay for a pinned binaryen download in CI and for contributors.
Refs #586
Refs #342
* ci(wasm): report the gzip size of the browser binary and budget it
The size report showed only the raw size of comprs-wasm_bg.wasm, in
whole KB, while browsers download it compressed, and nothing failed
when it grew. Its PR comment also passed `comment-tag` to
create-or-update-comment, which has no such input, so every push added
another comment.
scripts/wasm-size.mjs (`pnpm run size:wasm`) now reports the raw, gzip
(level 9) and brotli (quality 11) sizes in bytes, and fails when the raw
or gzip size is over its budget: 1,925,000 and 815,000 bytes, a few
percent over the current build. A build with the 2.0.2 setting,
opt-level 3, fails it by 442,039 and 110,309 bytes. The brotli size has
no budget, as it moves by several percent with unrelated changes at
quality 11.
The build-wasm-bindgen job runs the check after uploading the binary,
puts the report in the step summary, and the report-wasm-size job posts
it on the pull request, also when it is over budget, editing the comment
of earlier runs through a marker.
Closes #586
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DRi2Qu5rPjQSDBcR8xmkSS test(core): add property-based round-trip tests
The integration tests round-trip fixed inputs at the default level and
at a handful of chunk sizes, so bugs that depend on where a chunk
boundary falls, on a particular level or on the dictionary contents
could go unnoticed.
Add proptest as a dev-dependency of comprs-core and a test that
generates inputs of up to 32 KiB mixing noise with runs, repeated
patterns and text-like data, chunk-size sequences of 1 to 4095 bytes,
levels over each format's range (gzip, deflate and brotli 0-9, zstd -5
to 19) and dictionaries. For every format, including the zstd and
brotli dictionary variants, it checks that chunked context compression
followed by one-shot decompression, and one-shot compression followed
by chunked context decompression, return the input. It also checks
that one-shot and chunked context decompression both fail on a random
strict, non-empty prefix of a stream written by the one-shot encoder
or the stream context. Every format marks where its single stream or
frame ends and both kinds of decoder reject input that stops before
it, so no prefix is exempt.
Each property runs 64 cases; the three take about 3 s in a debug
build. proptest 1.11 supports Rust 1.85, below the declared MSRV, and
adds no duplicate crate versions.
Closes #538
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DRi2Qu5rPjQSDBcR8xmkSStest/issue-538-core-lib-proptest test(core): exercise the comprs-core api in integration tests (#630)
* test(core): exercise the comprs-core api in integration tests
Most Rust tests called flate2, brotli, zstd or lz4_flex directly, so a
change in comprs-core or a behaviour change in a dependency could pass
cargo test unnoticed. Several public paths had no Rust coverage at all:
the gzip, deflate, brotli and lz4 compress contexts, gzip::read_header
with fields comprs does not write, and the argument checks of the
decompress contexts.
Add integration tests under crates/core-lib/tests, which reach only the
public API:
- contexts.rs drives every compress and decompress context (gzip,
deflate, brotli, brotli dict, zstd, zstd dict, lz4) at chunk sizes 1,
7, 4096 and the whole input, checks flush output, use after finish
(also after a failed finish), level validation, and an output limit of
n and n-1 bytes for one chunk that expands 1000-fold.
- one_shot.rs checks every *_with_capacity function at n and n-1 bytes,
empty input, truncation, the handling of data after the first stream
per format, that zstd level 0 is level 3, and detect routing.
- gzip_header.rs round-trips compress_with_header through read_header
and reads a hand-built header with an extra field, a comment and
non-UTF-8 bytes.
- validate.rs covers validate_capacity, validate_max_output_size, the
maxOutputSize argument of every decompress context and the public
IntArg bounds with NaN, infinities, fractions and huge values.
Making a gzip level above 9 valid, or turning a size limit check from >
into >=, now fails these tests. They take about 3 seconds.
Refs #538
* test(core): drop unit tests that only exercise upstream crates
38 unit tests built flate2, brotli, zstd or lz4_flex encoders and
decoders themselves and never called comprs-core, so no change in this
crate could make them fail: the round-trip, empty-input and frame-magic
tests of every format, the five *_take_read_to_end_* tests that wrapped
a flate2 decoder in Take instead of calling decompress_with_limit, the
gzip header tests that used GzBuilder and GzDecoder::header(), and
zstd's level_zero_uses_default, which never compared level 0 with the
default level. The integration tests now cover what they meant to test.
Rewrite the ones that check something of comprs' own against its API
instead: the level ordering tests of gzip, brotli and zstd, which now
also round-trip every brotli quality, zstd's negative and maximum
levels, and the dictionary tests, which now check that the dictionary
shrinks the output and is needed to decode it.
Refs #538
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DRi2Qu5rPjQSDBcR8xmkSS ci(wasm): report the gzip size of the browser binary and budget it
The size report showed only the raw size of comprs-wasm_bg.wasm, in
whole KB, while browsers download it compressed, and nothing failed
when it grew. Its PR comment also passed `comment-tag` to
create-or-update-comment, which has no such input, so every push added
another comment.
scripts/wasm-size.mjs (`pnpm run size:wasm`) now reports the raw, gzip
(level 9) and brotli (quality 11) sizes in bytes, and fails when the raw
or gzip size is over its budget: 1,925,000 and 815,000 bytes, a few
percent over the current build. A build with the 2.0.2 setting,
opt-level 3, fails it by 442,039 and 110,309 bytes. The brotli size has
no budget, as it moves by several percent with unrelated changes at
quality 11.
The build-wasm-bindgen job runs the check after uploading the binary,
puts the report in the step summary, and the report-wasm-size job posts
it on the pull request, also when it is over budget, editing the comment
of earlier runs through a marker.
Closes #586
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DRi2Qu5rPjQSDBcR8xmkSS Latest Branches
0%
renovate/lock-file-maintenance-rust-dependencies 0%
renovate/rust-dependencies 0%
renovate/napi-rs-toolchain © 2026 CodSpeed Technology