//! Gated integration test for the M1-window upper-bound contract (Gitea #23). //! //! Property under protection: an *unbounded* upper bound is expressible through //! `load_m1_window` and is non-panicking — it must yield exactly the bars a //! finite sane bound covering the same data would. The underlying //! `data_server::stream_m1_windowed` already takes `Option` per bound //! (`None` = unbounded, skipping the coarse `unix_ms_to_year_month` file //! filter). The aura wrapper must thread that `Option` through so callers can //! express "to the end of history" without reaching for a sentinel — the //! natural `i64::MAX` sentinel panics in chrono's `from_timestamp_millis` //! inside the data-server file filter (`records.rs:28`). //! //! Skips with a note where the local Pepperstone archive is absent, so //! `cargo test --workspace` stays green anywhere; it exercises the real //! ingestion path where data exists. The trigger is minimized to the latest //! single AAPL.US month so the unbounded read stays a few thousand bars. use std::sync::Arc; use aura_ingest::load_m1_window; use data_server::{DataServer, DEFAULT_DATA_PATH}; #[test] fn unbounded_upper_bound_matches_finite_sane_bound() { let server = Arc::new(DataServer::new(DEFAULT_DATA_PATH)); if !server.has_symbol("AAPL.US") { eprintln!("skip: no local data at {DEFAULT_DATA_PATH} (symbol AAPL.US absent)"); return; // hermetic elsewhere; exercises the real path where files exist } // Minimal trigger: start at the latest archived month so "to the end of // history" resolves to one small tail file, not the full multi-year set. // 2026-05-01 00:00:00 UTC in inclusive Unix-ms. let from_ms = 1_777_996_800_000_i64; // A finite sane upper bound far past any real bar (2035-01-01), the // workaround the #23 reporter used in place of the panicking i64::MAX. let sane_upper = 2_051_222_400_000_i64; // The reference: a finite bound that covers all remaining bars. let bounded = load_m1_window(&server, "AAPL.US", Some(from_ms), Some(sane_upper)) .expect("AAPL.US has data from 2026-05 onward"); assert!(!bounded.ts.is_empty(), "tail window resolved to zero bars"); // The behaviour #23 asks for: an unbounded upper bound (`None`) must be // expressible and must NOT panic — today the wrapper hardcodes `Some(..)`, // so this is unrepresentable, and the only sentinel a caller can pass // (`i64::MAX`) panics upstream in `unix_ms_to_year_month`. let unbounded = load_m1_window(&server, "AAPL.US", Some(from_ms), None) .expect("unbounded upper bound yields the same data as the sane finite bound"); // Same data, bar-for-bar: an open upper bound is exactly "no upper filter". assert_eq!( unbounded, bounded, "unbounded upper bound must equal the finite sane bound covering the same tail" ); }