From 6397062ee99084000c5476206e9256bd1d2b7ef4 Mon Sep 17 00:00:00 2001 From: Vyncint Ng <115854244+vyncint@users.noreply.github.com> Date: Sun, 4 Oct 2026 13:03:13 +0700 Subject: [PATCH] test: compare the written asciicast with the exported one apart from the clock `the_asciicast_is_a_v2_header_and_one_full_repaint_per_frame` exported the recording twice, once to a string and once through write_asciicast, and asserted the two were byte-equal. The header's `timestamp` is the wall clock at export, on purpose, and another test pins that, so a second boundary falling between the two exports made the test fail with two strings identical except for a value one second apart. The features job on PR 552 saw it once. Both exports now go through a small helper that removes the header's timestamp before they are compared, and a guard asserts the helper removed something so the comparison cannot go vacuous. No sleep is added: the suite allows two, and the fix needs none. Checked three ways, each undone afterwards. The old assertion with a 1.1 s pause between the exports fails with CI's exact message. The new one passes under the same pause. The new one still fails when write_asciicast writes something else (a renamed header key). The file passes with default, decode, serde and all features, and twelve repeats. Closes #555 Signed-off-by: Vyncint Ng <115854244+vyncint@users.noreply.github.com> --- crates/termlens/tests/record.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/crates/termlens/tests/record.rs b/crates/termlens/tests/record.rs index 35728a0..a1df3a4 100644 --- a/crates/termlens/tests/record.rs +++ b/crates/termlens/tests/record.rs @@ -19,6 +19,22 @@ fn emit(builder: termlens::TerminalBuilder, steps: &[&str]) -> termlens::Result< common::spawn_emit(builder.size(40, 6).timeout(Duration::from_secs(10)), steps) } +/// The cast with its header's `"timestamp"` key taken out. +/// +/// The key is the wall clock at *export* — `the_header_timestamp_is_the_export_time` +/// pins that — so two exports of one recording are the same document except +/// where a second boundary fell between them, which failed the file-equals- +/// string comparison on a CI runner (#555). What that comparison is about is +/// everything else. +fn without_timestamp(cast: &str) -> String { + let (header, events) = cast.split_once('\n').expect("a header line, then events"); + let Some((before, rest)) = header.split_once(", \"timestamp\": ") else { + return cast.to_owned(); + }; + let digits = rest.bytes().take_while(u8::is_ascii_digit).count(); + format!("{before}{}\n{events}", &rest[digits..]) +} + #[test] #[cfg_attr( windows, @@ -135,7 +151,13 @@ fn the_asciicast_is_a_v2_header_and_one_full_repaint_per_frame() -> termlens::Re frames.write_asciicast(&path)?; let written = std::fs::read_to_string(&path)?; let _ = std::fs::remove_file(&path); - assert_eq!(written, cast); + // The same document, not the same second: `write_asciicast` exports again. + assert_ne!( + without_timestamp(&cast), + cast, + "the helper must remove something, or the comparison below proves nothing" + ); + assert_eq!(without_timestamp(&written), without_timestamp(&cast)); t.send(Key::Enter)?; assert!(t.wait_exit()?.success()); Ok(())