From c31aecbacf3224049b72661152de482cf405f14d Mon Sep 17 00:00:00 2001 From: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com> Date: Sun, 16 Aug 2026 14:26:49 +0800 Subject: [PATCH] test(config): hold that a hand-edited config is clamped as it is read Deleting `cfg.sanitize()` from the load path left the whole suite green. `sanitize_clamps_degenerate_font_metrics` holds what the function does; nothing held that the loader calls it. The file is the one place these values arrive unchecked -- the settings page has its own bounds -- so a zero font size, or a NaN, or the `ui_font_size` whose comment warns that the whole chrome is a multiple of it, reaches the layout from here or from nowhere. The test writes such a file, loads it, and checks what comes back; deleting the call fails it on the zero. Two neighbours in the same sweep are already held: the quarantine that parks a corrupt file before defaults are handed back is caught by three tests, and the startup stale-endpoint removal by two. One gap is left open deliberately. Removing `note_unknown_keys` from the same function is caught by nothing, but its only effect is a warning -- the typo'd key falls back to its default either way -- and catching it needs a global logger installed from a test, which in a suite this parallel is a worse thing to own than the gap. --- crates/tty7-core/src/core/config.rs | 40 +++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/crates/tty7-core/src/core/config.rs b/crates/tty7-core/src/core/config.rs index bfbe3a93..5fc04a53 100644 --- a/crates/tty7-core/src/core/config.rs +++ b/crates/tty7-core/src/core/config.rs @@ -2239,6 +2239,46 @@ mod tests { let _ = std::fs::remove_file(&path); } + /// A hand-edited config is clamped on the way in, not just in theory. + /// + /// `sanitize_clamps_degenerate_font_metrics` holds what `sanitize` does; + /// nothing held that the load path calls it, and deleting `cfg.sanitize()` + /// there left the whole suite green. The file is the one place these + /// values arrive unchecked — the settings page has its own bounds — so a + /// zero font size or a NaN reaches the layout from here or nowhere. + #[test] + fn a_hand_edited_config_is_clamped_as_it_is_read() { + let _guard = lock_config_file(); + pin_config_dir(); + let path = Config::path().expect("pinned config dir"); + clear_quarantines(&path); + std::fs::write( + &path, + r#"{"font_size": 0.0, "line_height": 900.0, "ui_font_size": 1e9}"#, + ) + .unwrap(); + + let (loaded, outcome) = Config::load_with_outcome(); + assert_eq!(outcome, LoadOutcome::Parsed, "the file is valid JSON"); + assert_eq!( + loaded.font_size, + Config::default().font_size, + "a zero font size is not a size to draw with" + ); + assert!( + loaded.line_height <= LINE_HEIGHT_MAX, + "line_height {} was let through", + loaded.line_height + ); + assert!( + loaded.ui_font_size <= UI_FONT_SIZE_MAX, + "ui_font_size {} was let through, and the whole chrome is a multiple of it", + loaded.ui_font_size + ); + + let _ = std::fs::remove_file(&path); + } + #[test] fn a_corrupt_config_is_kept_aside_and_never_overwritten() { let _guard = lock_config_file();