test(strconv): add QuickCheck property tests - #4035
Conversation
Property tests for string<->number conversion: - parse_double bitwise-inverts Double::to_string for doubles built from arbitrary 64-bit patterns (subnormals, extreme exponents, infinities), and for uniform doubles in [0, 1]. Negative zero is exempted from the bitwise requirement because the ECMAScript-style to_string renders it as "0" on every backend. - Full-range 64-bit and 32-bit integer round-trips through decimal strings, plus agreement between the integer parsers and parse_double / to_double on the same string (correct rounding at 19-20 digits). - Radix round-trip in every base 2..=36 for Int64 and UInt64. - Underscores between digits never change the parsed value. - A stray non-numeric character (including whitespace) is always rejected, prepended or appended. - Structured [-]digits[.digits][e[-]digits] strings never panic: they parse to a value whose own rendering reparses to the same bits, or fail with a range error only for genuinely huge exponents. Integer inputs are assembled from arbitrary bytes because the built-in Arbitrary instances are size-bounded and never reach the interesting regions. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR adds specification-style QuickCheck property tests to the strconv package, aiming to validate correctness and rounding behavior of string↔number conversions across wide and adversarial input spaces (including full-range integer values, arbitrary double bit patterns, radix parsing, underscores, and invalid decoration).
Changes:
- Added
strconv/quickcheck_test.mbtwith multiple property-based tests forparse_double, integer parsers, radix parsing, underscore handling, and decoration rejection. - Added a test-only dependency on
moonbitlang/core/quickcheckinstrconv/moon.pkg.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| strconv/quickcheck_test.mbt | Introduces QuickCheck properties covering round-trips, parser agreement, radix behavior, underscore transparency, invalid decoration rejection, and structured fuzzing. |
| strconv/moon.pkg | Adds quickcheck as a test-only import to enable the new property tests. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| } | ||
| } | ||
| Err(_) => with_exp && exp > 250 | ||
| } |
| test "quickcheck: parse_bool inverts to_string" { | ||
| @quickcheck.check((b : Bool) => @strconv.parse_bool(b.to_string()) == b) | ||
| } |
Coverage Report for CI Build 6036Warning 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 |
Adds
strconv/quickcheck_test.mbtwith specification-quality property tests for string↔number conversion, following the pattern ofhashmap/quickcheck_test.mbt.Properties covered
parse_double(d.to_string())is bitwise equal todfor doubles built from arbitrary 64-bit patterns — covering subnormals, extreme exponents and infinities that the size-bounded built-inArbitraryinstances never reach — plus a second run over uniform doubles in[0, 1]to exercise the fast path densely. NaN is excluded viafilter; negative zero gets a documented exemption (see below).parse_int64/parse_uint64invertto_stringover the whole 64-bit range (values assembled from arbitrary bytes),parse_int/parse_uintover the 32-bit range, with and without explicitbase=10, and with an explicit leading+.parse_doubleagrees exactly withInt::to_double, and withInt64/UInt64::to_doubleat 19–20 significant digits, where both sides must round to nearest identically (exercises the slow path).to_string(radix=b)followed byparse_*(base=b)is the identity for every base 2..=36, signed and unsigned.parse_uint64andparse_double.parse_intandparse_doublefail.[-]digits[.digits][e[-]digits]strings never panic; they either parse to a value whose own rendering reparses to the same bits (printing fixed point), or raise a range error, which the property only permits for genuinely huge exponents (underflow must flush to zero silently).Counts are bumped to 300–500 per property; all pass on
wasm-gc,wasm,js, andnative.Note: negative zero
parse_double("-0")correctly returns-0.0, butDouble::to_stringfollows the ECMAScript number-to-string algorithm on every backend (ryu_to_stringreturns"0"forval == 0.0, which matches-0.0), so the sign bit cannot survive a trip through the string. The round-trip and fixed-point properties therefore carve out exactly this case (and require the reparse to yield exactly+0.0), rather than weakening the bitwise requirement anywhere else. No bugs were found instrconvitself.strconv/moon.pkggains a test-only import ofmoonbitlang/core/quickcheck; no.mbtichanges.🤖 Generated with Claude Code