Skip to content

test: introduce jetCheck property-based testing - #284

Merged
magnusp merged 5 commits into
mainfrom
test/property-based-testing
Oct 31, 2026
Merged

magnusp merged 5 commits into
mainfrom
test/property-based-testing

Conversation

@magnusp

@magnusp magnusp commented Oct 31, 2026

Copy link
Copy Markdown
Owner

Description

Introduce jetCheck 0.3.0 as the property-based testing library for the unit lanes. The pilot covers six seams that the recent refactors extracted:

  • statement splitting and local placeholder counting;
  • SQLite REAL, LONG, DOUBLE and date-time text round trips;
  • URL parsing and metadata credential redaction;
  • declared-type parsing and AUTOINCREMENT detection;
  • the connection transaction and savepoint lifecycle, as a model-based ImperativeCommand scenario;
  • differential encode/decode agreement between the Direct and Jackson Hrana JSON codecs, including 64-bit integers and base64 blobs.

jetCheck was chosen over QuickTheories because it has first-class stateful testing, an active release history (0.3.0, 2026), and rechecking(...) reproduction tokens. The comparison and suite conventions are documented in docs/property-based-testing.md.

The properties found two defects, both fixed here with named regression tests:

  • LibsqlUrlParser leaked a NumberFormatException for a non-numeric connectTimeout or busyTimeout.
  • metadataUrl removed only the first user:pass@ segment, so repeated user info was not fully redacted and redaction was not idempotent.

The malformed declared-precision case (DECIMAL(abc)) is left unchanged because LibsqlResultSetMetaDataTest currently pins the NumberFormatException. The property generator is restricted to valid declared text, and the decision is recorded in the doc.

No tracking issue; this is a testing-infrastructure spike rather than a feature.

Type of Change

  • Bug fix (non-breaking change fixing an issue)
  • New feature (non-breaking change adding functionality)
  • Breaking change (fix or feature causing existing functionality to not work as expected)
  • Documentation update
  • Refactoring / tooling / CI improvement

Checklist

  • My code follows the code style of this project (./mvnw spotless:check).
  • I have added tests that prove my fix is effective or that my feature works.
  • All new and existing tests passed (./mvnw clean verify).
  • I have updated documentation where appropriate.

Verification

  • DOCKER_CONFIG="$PWD/libsql-conformance/src/test/docker-config" ./mvnw clean verify — BUILD SUCCESS, including the unit, integration and conformance lanes.
  • ./mvnw spotless:check — BUILD SUCCESS.
  • The property suites were run five times with fresh random seeds after the fixes.
  • CI runs the Java 25 and 26 matrix and the xerial control probe.

Follow-ups

These are intentionally out of scope for this PR and recorded in the doc:

  • xerial differential oracle, with an Appendix-B quarantine list;
  • the Appendix B source-by-target matrix property for JdbcValueConverter;
  • lifecycle failure injection for stale batons, expired streams and transaction-end server errors.

Long.parseLong let a NumberFormatException escape LibsqlUrlParser.parse
for a non-numeric connectTimeout or busyTimeout. A property test found
the empty-query-value case. Wrap the conversion so the JDBC boundary
reports a SQLException with the parameter name and keeps the cause.
Pin org.jetbrains:jetCheck 0.3.0 and declare it test-scoped in the
JDBC and Hrana codec modules. It stays out of runtime and shaded
artifacts.
The USER_INFO pattern removed only the first user:pass@ segment, so a
URL such as http://user:pass@user:pass@host kept a credential in the
result of a second redaction. Consume through the last @ before the
path, query or fragment instead. A property test found the case.
Cover the statement splitter, SQLite text conversions, URL parsing,
metadata text, the two Hrana JSON codecs, and the connection
transaction lifecycle. The lifecycle suite uses jetCheck's
ImperativeCommand scenario support, so command generation, replay,
shrinking and the failure log belong to the library.

jetCheck has no 64-bit or array generator, so the suites compose a
long from two ints and map lists to byte arrays. Text generators stay
on BMP code points because jetCheck's string generator is char-based;
supplementary text is covered by constants.
@magnusp
magnusp merged commit 6893f3e into main Oct 31, 2026
6 checks passed
@magnusp
magnusp deleted the test/property-based-testing branch October 31, 2026 17:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant