c0re's queue tests no longer drive the scheduler
The last two claim-driven tests were both arranging node states to observe something that never needed a run: `settled_dag_leaves_the_snapshot_despite_its_skipped_branch` completed all seven nodes of a rebuild to assert the DAG left the snapshot. That is one predicate over a list of states. `shown_on_wire` is it, split out of `dag_view`, and the cases can now be named rather than arranged — including the empty set, the one input where "any" and "all" disagree. It takes states rather than projected nodes so the caller skips projecting what it is about to discard; a `NodeView` costs a `build_logs` lookup. `failed_node_cancels_downstream_but_afterany_reconcile_runs` asserted three unrelated things from one arranged failure: the cascade (hive_jobq's, and already tested there), the wire filter (now `shown_on_wire`), and the roll-up. `DagView::rollup_state` lives in hive-host-sock, which had no tests at all — it does now, next to the invariant, covering the ordering its own doc comment says has silently disagreed with the frontend before. With nothing left claiming, `Claimed` / `ClaimReady` / `CompleteNode` / `claim_one` / `settle_rebuild_tail` are deleted. Claim/complete sites in `job_queue/tests.rs`: 109 -> 0. jobq narrows to match: `settle` is gone (it was a `claim_one` loop returning a Vec, and its only callers were tests — it lives in the test module now), `claim_one` is private, and `complete_growing` is `pub(crate)`. `claim_next` is the whole run-loop surface. `complete` stays `pub` for one caller, noted at the definition: `submit` completes a group root with no logic of its own so it parks in `Finishing` and its children unblock. That is a statement about the node, not an event to report, and it wants to be expressible at insert time.
This commit is contained in:
parent
ab5744a2bd
commit
e646656c92
4 changed files with 334 additions and 266 deletions
|
|
@ -206,3 +206,106 @@ impl DagView {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use chrono::Utc;
|
||||
|
||||
use super::{DagView, NodeView, Source, State};
|
||||
|
||||
/// A node set carrying nothing but the states — the only input
|
||||
/// `rollup_state` reads.
|
||||
fn dag(states: &[State]) -> DagView {
|
||||
DagView {
|
||||
id: 1,
|
||||
source: Source::Manual,
|
||||
reason: "test".to_owned(),
|
||||
created_at: Utc::now(),
|
||||
started_at: None,
|
||||
finished_at: None,
|
||||
nodes: states
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, &state)| NodeView {
|
||||
id: i as u64,
|
||||
agent: "a".to_owned(),
|
||||
kind: "reconcile".to_owned(),
|
||||
deps: Vec::new(),
|
||||
state,
|
||||
started_at: None,
|
||||
finished_at: None,
|
||||
error: None,
|
||||
approval_id: None,
|
||||
inputs: Vec::new(),
|
||||
build_log_id: None,
|
||||
parent: None,
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_failure_outranks_everything_and_skipped_counts_for_nothing() {
|
||||
// The case this replaces used to be arranged in hive-c0re by running a
|
||||
// rebuild until its Prebuild failed. Only the states ever mattered.
|
||||
assert_eq!(
|
||||
dag(&[State::Done, State::Failed, State::Skipped]).rollup_state(),
|
||||
State::Failed
|
||||
);
|
||||
// A failure wins even against a node still going — the DAG's verdict
|
||||
// is already decided.
|
||||
assert_eq!(
|
||||
dag(&[State::Running, State::Failed]).rollup_state(),
|
||||
State::Failed
|
||||
);
|
||||
// Skipped is an expected part of a healthy run: an outcome-branched
|
||||
// DAG always leaves one branch untaken, so counting it would make
|
||||
// every successful DAG roll up non-Done.
|
||||
assert_eq!(
|
||||
dag(&[State::Done, State::Skipped]).rollup_state(),
|
||||
State::Done
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cancelled_outranks_running_and_pending() {
|
||||
// A cancelled DAG still has its weak-edged tail node to run, so
|
||||
// Pending-then-Running would flicker back at the operator who just
|
||||
// cancelled it and read as "the cancel didn't take".
|
||||
assert_eq!(
|
||||
dag(&[State::Cancelled, State::Pending]).rollup_state(),
|
||||
State::Cancelled
|
||||
);
|
||||
assert_eq!(
|
||||
dag(&[State::Cancelled, State::Running]).rollup_state(),
|
||||
State::Cancelled
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn finishing_still_counts_as_running() {
|
||||
// The node's own work is done but its sub-nodes are still going, so
|
||||
// the DAG is in flight. A parent parked in Finishing is the normal
|
||||
// shape of a subtree mid-run, not an edge case.
|
||||
assert_eq!(
|
||||
dag(&[State::Finishing, State::Pending]).rollup_state(),
|
||||
State::Running
|
||||
);
|
||||
assert_eq!(
|
||||
dag(&[State::Running, State::Pending]).rollup_state(),
|
||||
State::Running
|
||||
);
|
||||
assert_eq!(
|
||||
dag(&[State::Done, State::Pending]).rollup_state(),
|
||||
State::Pending
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_empty_node_set_reads_done() {
|
||||
// Every node Done means every node is filtered off the wire, so this
|
||||
// is what a finished DAG actually looks like to a consumer that has
|
||||
// one in hand at all.
|
||||
assert_eq!(dag(&[]).rollup_state(), State::Done);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue