test(bytes): add QuickCheck property tests - #4042
Merged
Merged
Conversation
Property families: - from_array/to_array/makei/from_iter/iter/iter2 roundtrips - concat associativity, empty identity, additive length/contents; repeat - views vs array-model slices, boundary/empty/full views, get_view rejection of invalid ranges, immutability of the parent - view-of-view offset composition (b[i:j][k:l] == b[i+k:i+l]) - shortlex Compare and lexicographic lexical_compare vs unsigned models, biased toward bytes >= 0x80 to expose signed-byte comparison bugs - hash consistency: equal Bytes, Bytes vs full view, equal-content views at different offsets in different backings - find/rev_find vs naive scans over a 0x7E-0x81 boundary alphabet, on owned bytes, aliased needles, and offset views; long needles driving the long-scanner/Rabin-Karp paths - has_prefix/has_suffix/chop_prefix/chop_suffix vs the model Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Collaborator
Coverage Report for CI Build 6040Warning Build has drifted: This PR's base is out of sync with its target branch, so coverage data may include unrelated changes. Coverage remained the same at 90.29%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new MoonBit QuickCheck test suite for Bytes / BytesView, using Array[Byte] as a reference model to validate a broad set of semantic properties (roundtrips, concatenation/repeat, view offset algebra, ordering/hash consistency, and search/prefix/suffix behavior) across backends.
Changes:
- Introduces model helper functions (
imod,pick_range, slice/ordering/search models) to define backend-independent expectations. - Adds property tests covering
Bytes/BytesViewconstruction, iteration/indexing, slicing/view composition, ordering semantics, hashing consistency, and search/prefix/suffix APIs. - Adds targeted generators (boundary-crossing alphabets and biased byte tweaks) to stress byte-sign boundaries and dense match patterns.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+330
to
+332
| let mutated = needle.copy() | ||
| mutated[imod(a, mutated.length())] = b'\x00' | ||
| let mb = Bytes::from_array(mutated) |
| let len = hay.length() | ||
| let ns = imod(a, len + 1) | ||
| // Prefer needles longer than the 32-byte short-pattern cutoff. | ||
| let ne = ns + imod(b, len - ns + 1) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
bytes/quickcheck_test.mbt: model-based QuickCheck property tests for immutableBytesandBytesView, checked against plainArray[Byte]reference implementations.moonbitlang/core/quickcheckwas already in the package'sfor "test"imports, so nomoon.pkgchange;.mbtiis untouched.Property families
from_array/to_arrayidentity;makeiagrees with its generating function;from_iter,iter,iter2,get/atall agree with indexed model reads (including out-of-boundsgetreturningNone).(a + b).to_array()equals model concatenation; length is additive; associativity;b""is a two-sided identity;repeat(n)equals n-fold concatenation.(start, end)including empty/full/boundary slices: view contents equal the model slice element-for-element;data()/start_offset()bookkeeping is exact; view-of-view composes asb[i:j][k:l] == b[i+k : i+l](verified both byEqand against the model slice, plus a third nesting level);get_viewmirrors the aborting slice on valid ranges and returnsNoneon negative start / end past length / start > end;to_ownedmaterializes exactly the viewed range; reading through views never disturbs the immutable parent.Compareis shortlex andlexical_compareis pure lexicographic, both validated against unsigned-byte models with generation biased toward bytes>= 0x80(where a signed-byte comparison bug would surface), plus an explicit0x7Fvs0x80boundary probe;a == biffcompare == 0iff equal arrays;equal_to_bytesagrees withEq.Byteshash equally;bs.hash() == bs[:].hash()(exercises the specialized non-JSBytes::hashfast path against theBytesViewhasher path); equal-content views at different offsets in different backing buffers hash equally.find/rev_findvs naive scans over a0x7E..0x81boundary alphabet, with needles sliced from the haystack (guaranteed hits), aliased needles viewing the same backing bytes, perturbed needles (model decides), searches inside offset views, empty-pattern semantics, and long needles over dense false-candidate haystacks to drive the long-scanner and Rabin–Karp fallback paths;has_prefix/has_suffix/chop_prefix/chop_suffixvs the model, including through nonzero-offset views.Verification
moon checkclean;moon info && moon fmtproduce no.mbtior formatting diffs.moon test -p moonbitlang/core/bytespasses on wasm-gc, wasm, js, native (148 tests each).max_size=200across backends before settling on the default seed — all passed.Bugs found
None. The stressed areas (view offset bookkeeping under nesting and aliasing, unsigned comparison above 0x80, per-backend SIMD/scalar/Rabin–Karp search paths, hash fast-path consistency) all behaved per their documented semantics on every backend.
🤖 Generated with Claude Code