Skip to content

Replay the event contract corpus over a fake native driver - #484

Merged
TimelordUK merged 1 commit into
masterfrom
test/fake-native
Oct 17, 2026
Merged

TimelordUK merged 1 commit into
masterfrom
test/fake-native

Conversation

@TimelordUK

Copy link
Copy Markdown
Owner

Groundwork for the #479 cancel work. This tests the JS layer (queue, reader, notifier) deterministically, without a server.

What's here

Native recordings (test/contract/native-tap.js, capture.js --native). For each corpus scenario, this records what passes between the JS layer and the native driver: every call, every statement state change, and every result, in order. A log is kept only if its run's transcript matches the corpus. Connection strings and server host names are redacted. The logs live in test/contract/native/<name>.<platform>.json: 80 scenarios, about 580 KB, Windows only so far.

A replaying fake driver (test/common/fake-native.js). It answers each call JS makes with what the real driver answered. Results are released in causal order: a result waits until JS has made every call recorded before it, so a query whose recorded result is HY008 waits for the cancel, with no timestamps needed. Independently of the recording, it checks that the JS respects the driver:

  • overlap: a second call (a cancel apart) while one is in flight on the connection
  • after release: a call on a released statement
  • after close: a call after the connection is closed
  • diverged / unrecorded: a call the recording doesn't have next, or at all
  • stalled: JS waits on a result that waits on a call JS never makes

test/contract/replay.test.js runs every recorded scenario through the real ConnectionWrapper → DriverMgr → reader over the fake. The transcript must match the corpus, with no violations. That's 80 scenarios in about 17 s.

lib/connection.js now exports ConnectionWrapper. That's the only change to lib/.

Does it catch real bugs?

With 5.6.0's lib/reader.js, queue.js, driver.js and query-handler.js put back, it fails on every run:

Bug Reported as
pause/resume crash, #480 diverged: nextResultSet(0) made where the log has fetchRows next
loop after pausing on the last row after release: nextResultSet on statement 0
#481 overlap: query while query in flight
free delayed behind the next query stalled: JS waits on query; the log waits on releaseStatement

On the real driver, the crash showed up in about 1 run in 10.

Next

  • A timing explorer: the same recorded results, released in different orders relative to pause, resume and cancel.
  • A builder for native results a server can't produce on demand, such as an error from a fetch that was in flight when a pause landed.
  • Linux recordings (WSL Fedora), so the replay also runs on Linux CI. Until then it has nothing to run there.

Testing

  • npx mocha test/contract/replay.test.js: 81 passing, 17 s (Windows).
  • npx eslint on the new files: clean.

🤖 Generated with Claude Code

…m over a fake driver

capture.js --native records what passes between the JS layer and the native
driver for each scenario (native-tap.js): every call, state change and
result, in order, with connection strings and host names left out. A log is
kept only if its run matches the corpus.

test/common/fake-native.js replays such a log in place of the driver: each
call JS makes is answered with what the real driver answered, released in
causal order (a result waits until JS has made every call recorded before
it). It also checks that the JS respects the driver: overlapping calls,
calls on a released statement, calls after close, calls the recording does
not have, and stalls.

replay.test.js runs all 80 scenarios this way through the real JS layer, in
about 20 s and without a server; every transcript matches the corpus with no
violations. Against 5.6.0's lib/ it reports the pause crash (diverged:
nextResultSet where the log has fetchRows), #481 (overlap: query while query
in flight) and the late free (stalled), every run.

ConnectionWrapper is exported so that the fake can be put under the real
connection API.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@TimelordUK
TimelordUK merged commit 562f5e0 into master Oct 17, 2026
11 checks passed
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