Seen once, on the features job of PR #552 (run 37125244069, cargo test -p termlens --no-default-features --features decode, tests/record.rs). the_asciicast_is_a_v2_header_and_one_full_repaint_per_frame failed at record.rs:138 with the two strings identical except for the header's timestamp, one second apart:
left (the written file): {"version": 2, "width": 40, "height": 6, "timestamp": 1791033084, "duration": 0.000704, …
right (the cast): {"version": 2, "width": 40, "height": 6, "timestamp": 1791033083, "duration": 0.000704, …
Cause. The header's timestamp is the wall clock at export, by design: to_asciicast calls SystemTime::now() each time (terminal.rs:870), and the_header_timestamp_is_the_export_time (record.rs:326-338) pins that. The failing test exports twice, to_asciicast() at line 116 and write_asciicast() at line 135, and asserts the two are byte-equal (record.rs:138). A second boundary between the two calls makes them differ. The window is the few milliseconds between the calls, so it is rare, but it is a test race, not a product bug: it has nothing to do with #552 (a two-line README change).
Reproduced deterministically with a temporary test that exports, sleeps 1.1 s, writes the file, and compares:
first ts=1791092098 written ts=1791092099 equal=false
equal once the timestamp is removed: true
So the only difference is the timestamp.
Fix. Compare with the timestamp taken out of both headers, so the test still says what it means (write_asciicast writes what to_asciicast produces) and no longer depends on the clock. A small helper in the test that removes , "timestamp": <digits> from the first line is enough; no regex needed. The test that pins the timestamp's meaning stays as it is. To make the old shape fail every time, add a 1.1 s sleep between the two exports in the test under the old comparison and watch it fail before the change.
No other test in crates/termlens/tests compares two exports; the other to_asciicast callers (record.rs:181, :233, :326) each export once.
Found while reviewing #552 and #553. Not blocking them: a re-run of the job is expected to pass.
Seen once, on the
featuresjob of PR #552 (run 37125244069,cargo test -p termlens --no-default-features --features decode,tests/record.rs).the_asciicast_is_a_v2_header_and_one_full_repaint_per_framefailed atrecord.rs:138with the two strings identical except for the header's timestamp, one second apart:Cause. The header's
timestampis the wall clock at export, by design:to_asciicastcallsSystemTime::now()each time (terminal.rs:870), andthe_header_timestamp_is_the_export_time(record.rs:326-338) pins that. The failing test exports twice,to_asciicast()at line 116 andwrite_asciicast()at line 135, and asserts the two are byte-equal (record.rs:138). A second boundary between the two calls makes them differ. The window is the few milliseconds between the calls, so it is rare, but it is a test race, not a product bug: it has nothing to do with #552 (a two-line README change).Reproduced deterministically with a temporary test that exports, sleeps 1.1 s, writes the file, and compares:
So the only difference is the timestamp.
Fix. Compare with the timestamp taken out of both headers, so the test still says what it means (
write_asciicastwrites whatto_asciicastproduces) and no longer depends on the clock. A small helper in the test that removes, "timestamp": <digits>from the first line is enough; no regex needed. The test that pins the timestamp's meaning stays as it is. To make the old shape fail every time, add a 1.1 s sleep between the two exports in the test under the old comparison and watch it fail before the change.No other test in
crates/termlens/testscompares two exports; the otherto_asciicastcallers (record.rs:181,:233,:326) each export once.Found while reviewing #552 and #553. Not blocking them: a re-run of the job is expected to pass.