test: red for the enumerated family id rejected by load_family (#298)
Registry::load_family_members() exposes the bare name factor while
aura_runner::reproduce::load_family exact-matches only the derived C18
handle '{family}-{run}' — the natural list-then-reproduce workflow
dead-ends on its first attempt (found by the #295 fieldtest; predates
the extraction byte-identically). The test pins: the enumerated
identity of an unambiguous single-run family resolves through
load_family to the same family the canonical handle names.
refs #298
This commit is contained in:
@@ -232,3 +232,69 @@ pub fn reproduce_family(id: &str, env: &Env) -> Result<(), RunnerError> {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use aura_backtest::{RunMetrics, RunReport};
|
||||||
|
use aura_core::{Scalar, Timestamp};
|
||||||
|
use aura_engine::RunManifest;
|
||||||
|
use aura_registry::{FamilyKind, Registry};
|
||||||
|
|
||||||
|
use super::load_family;
|
||||||
|
|
||||||
|
/// A registry over a fresh per-test directory (the #258 tag-keyed pattern:
|
||||||
|
/// fixed name under the build-tree tmp anchor, pre-create wipe).
|
||||||
|
fn temp_registry(tag: &str) -> Registry {
|
||||||
|
let dir = std::path::Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/../../target/tmp"))
|
||||||
|
.join(format!("aura-runner-reproduce-{tag}"));
|
||||||
|
let _ = std::fs::remove_dir_all(&dir);
|
||||||
|
std::fs::create_dir_all(&dir).expect("create temp registry dir");
|
||||||
|
Registry::open(dir.join("runs.jsonl"))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// One minimal persisted member (the aura-registry test fixture shape).
|
||||||
|
fn minimal_report() -> RunReport {
|
||||||
|
RunReport {
|
||||||
|
manifest: RunManifest {
|
||||||
|
commit: "c".to_string(),
|
||||||
|
params: vec![("p".to_string(), Scalar::f64(1.0))],
|
||||||
|
defaults: vec![],
|
||||||
|
window: (Timestamp(1), Timestamp(2)),
|
||||||
|
seed: 0,
|
||||||
|
broker: "b".to_string(),
|
||||||
|
selection: None,
|
||||||
|
instrument: None,
|
||||||
|
topology_hash: None,
|
||||||
|
project: None,
|
||||||
|
},
|
||||||
|
metrics: RunMetrics { total_pips: 1.0, max_drawdown: 0.5, bias_sign_flips: 0, r: None },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// One id vocabulary across enumeration and reproduction (C18, #298): the
|
||||||
|
/// family-identity string a consumer lifts off the registry's own member
|
||||||
|
/// enumeration (`FamilyRunRecord.family`) resolves through the reproduce
|
||||||
|
/// lookup when it is unambiguous (a single stored run for the name), and
|
||||||
|
/// reaches the same family the canonical derived handle
|
||||||
|
/// (`"{family}-{run}"`, C18) names. Today the lookup exact-matches the
|
||||||
|
/// derived handle only, so the natural list-then-reproduce library
|
||||||
|
/// workflow dead-ends on `no such family`.
|
||||||
|
///
|
||||||
|
/// Deliberately NOT pinned here: the ambiguous case (a name with more
|
||||||
|
/// than one stored run) and name/handle collision precedence — those
|
||||||
|
/// semantics are the fix's to settle (refuse-don't-guess).
|
||||||
|
#[test]
|
||||||
|
fn load_family_accepts_the_enumerated_family_identity() {
|
||||||
|
let reg = temp_registry("enumerated-id");
|
||||||
|
reg.append_family("f", FamilyKind::Sweep, &[minimal_report()]).expect("append family");
|
||||||
|
|
||||||
|
let members = reg.load_family_members().expect("enumerate members");
|
||||||
|
let enumerated = members[0].family.clone();
|
||||||
|
let canonical = members[0].family_id();
|
||||||
|
|
||||||
|
let family = load_family(®, &enumerated).unwrap_or_else(|e| {
|
||||||
|
panic!("the enumerated family identity '{enumerated}' must resolve: {}", e.message)
|
||||||
|
});
|
||||||
|
assert_eq!(family.id, canonical);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user