test: red executable-spec for #264 cut 1 — aura data coverage reports month gaps
aura data coverage <SYMBOL> must print the archive's first/last present month and each interior missing-month range collapsed to one 'missing: YYYY-MM..YYYY-MM' line — the Copper failure mode (first/last check passes while the window start has no data) made visible before a campaign runs. Hostless RED over a new gapped synthetic-archive fixture (fresh_project_with_gapped_data); fails on the absent 'data' subcommand (clap exit 2), not on scaffolding. refs #264
This commit is contained in:
@@ -5,7 +5,7 @@ use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
mod common;
|
||||
use common::{fresh_project, fresh_project_with_data};
|
||||
use common::{fresh_project, fresh_project_with_data, fresh_project_with_gapped_data};
|
||||
|
||||
/// Path to the freshly-built `aura` binary (Cargo sets this env var for the test
|
||||
/// crate; the binary is named `aura` in `Cargo.toml`).
|
||||
@@ -5862,3 +5862,45 @@ fn shipped_r_meanrev_example_runs_end_to_end_via_aura_run() {
|
||||
assert!(stdout.contains("\"n_trades\":0"), "{stdout}");
|
||||
assert!(stdout.contains("\"total_pips\":0.0"), "{stdout}");
|
||||
}
|
||||
|
||||
/// Property (#264, coverage cut 1): `aura data coverage <SYMBOL>` surfaces the
|
||||
/// archive's month COVERAGE from the monthly file index — the first and last
|
||||
/// present month AND every interior missing-month range (a gap) — so the Copper
|
||||
/// failure mode is visible up front. Copper had files from 2016-08 but was
|
||||
/// missing 2018-01..2018-10, so a first/last-bounds check passed while a
|
||||
/// window opening in the hole had no data, aborting a multi-hour campaign
|
||||
/// mid-run; a per-symbol gap report would have caught it before the run. Over a
|
||||
/// hermetic synthetic archive whose `GAPSYM` has 2024-01..02 and 2024-05..06
|
||||
/// present and 2024-03..04 absent, the verb exits 0, frames the span by its
|
||||
/// first (2024-01) and last (2024-06) present month, and reports the interior
|
||||
/// hole as a single collapsed month-range line `missing: 2024-03..2024-04`
|
||||
/// (one line for the whole contiguous gap, as Copper's ten-month hole would be
|
||||
/// one line — not one line per missing month).
|
||||
#[test]
|
||||
fn data_coverage_reports_month_span_and_interior_gap_range() {
|
||||
let (cwd, _g) = fresh_project_with_gapped_data();
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args(["data", "coverage", "GAPSYM"])
|
||||
.current_dir(&cwd)
|
||||
.output()
|
||||
.expect("spawn aura data coverage");
|
||||
assert_eq!(
|
||||
out.status.code(),
|
||||
Some(0),
|
||||
"exit: {:?}, stderr: {}",
|
||||
out.status,
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
let stdout = String::from_utf8(out.stdout).expect("utf-8 stdout");
|
||||
// The interior gap is the headline — the Copper failure the verb exists to
|
||||
// surface — reported as one collapsed range for the whole contiguous hole.
|
||||
assert!(
|
||||
stdout.contains("missing: 2024-03..2024-04"),
|
||||
"interior gap month-range reported as one line: {stdout}"
|
||||
);
|
||||
// The span bounds frame the gap: first and last present month.
|
||||
assert!(
|
||||
stdout.contains("2024-01") && stdout.contains("2024-06"),
|
||||
"first (2024-01) and last (2024-06) present month reported: {stdout}"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -127,6 +127,26 @@ pub fn fresh_project_with_data() -> (PathBuf, FreshProject) {
|
||||
(root.clone(), FreshProject { root })
|
||||
}
|
||||
|
||||
/// Like [`fresh_project_with_data`], but the single symbol `GAPSYM` carries a
|
||||
/// DELIBERATE interior month gap: monthly files exist for 2024-01..2024-02 and
|
||||
/// 2024-05..2024-06, while 2024-03..2024-04 are absent. This is the Copper
|
||||
/// failure shape (#264 — files present at both ends while an interior window
|
||||
/// has no data, so a first/last-bounds check passes but a campaign aborts
|
||||
/// mid-run). For tests whose property is per-symbol month-gap reporting: the
|
||||
/// two `write_symbol_archive` calls write disjoint contiguous segments into the
|
||||
/// same `data/` dir (the second re-writes GAPSYM's identical geometry sidecar),
|
||||
/// leaving March and April as a real hole in the monthly file index.
|
||||
#[allow(dead_code)]
|
||||
pub fn fresh_project_with_gapped_data() -> (PathBuf, FreshProject) {
|
||||
let root = mint_tempdir();
|
||||
write_project_files(&root, Some("data"));
|
||||
let data_dir = root.join("data");
|
||||
std::fs::create_dir_all(&data_dir).expect("create synthetic gapped archive dir");
|
||||
synthetic_data::write_symbol_archive(&data_dir, "GAPSYM", (2024, 1), (2024, 2));
|
||||
synthetic_data::write_symbol_archive(&data_dir, "GAPSYM", (2024, 5), (2024, 6));
|
||||
(root.clone(), FreshProject { root })
|
||||
}
|
||||
|
||||
/// A scratch filesystem entry a test writes under the git-tracked
|
||||
/// demo-project fixture root (only `runs/` there is fixture-gitignored),
|
||||
/// removed on drop — including during a mid-test panic — so a failed
|
||||
|
||||
Reference in New Issue
Block a user