job_queue: test error truncation as the pure fn it is

error_is_truncated submitted a DAG, claimed its head, failed it with a
long string and read the error back out of a snapshot -- four moving
parts to observe one `&str -> String`. The DAG round-trip it depended on
is covered by its own tests either way.

Testing truncate_error directly also reaches the case the round-trip
never could: the cap is a byte length, so a multibyte char straddling it
would panic the slice. That boundary scan is the only non-obvious line
in the function and it had no coverage at all -- the old test used a
repeated ASCII 'x', where byte and char offsets coincide.

Also drops a stale claim from insert_job's doc: it has not recorded a
per-node node_rt since that map was deleted.
This commit is contained in:
atlas 2026-08-02 19:24:52 +02:00 committed by mara
commit a59ad5ce3f
2 changed files with 25 additions and 14 deletions

View file

@ -148,8 +148,7 @@ fn outcome_of(result: Result<(), String>) -> Outcome {
}
}
/// Insert a declared `job` into the shared graph and record its per-node
/// `node_rt`, returning the inserted ids.
/// Insert a declared `job` into the shared graph, returning the inserted ids.
///
/// A node that declared no parent hangs under `group_parent` — the DAG
/// container for a template, the emitting node for a runtime-appended

View file

@ -1690,18 +1690,30 @@ fn history_evicts_oldest_terminals_past_flat_cap() {
}
#[test]
fn error_is_truncated() {
let q = JobQueue::new(1);
let id = submit(&q, rebuild("agent-a", "r"));
let c = claim_one(&q);
q.complete_node(c.node_id, Err("x".repeat(5000)));
let snap = q.snapshot();
let err = snap.iter().find(|d| d.id == id).expect("dag").nodes[0]
.error
.clone()
.expect("error stored");
assert!(err.chars().count() <= 2001, "truncated + ellipsis");
assert!(err.ends_with('…'));
fn error_truncation_cuts_on_a_char_boundary() {
// `truncate_error` is a pure `&str -> String`. This used to submit a DAG,
// claim its head, fail it with a long string and read the error back out of
// a snapshot — four moving parts to observe one transform, and the DAG
// round-trip is covered by its own tests either way.
//
// Testing it directly also reaches the case the round-trip never did: the
// cap is a **byte** length, so a multibyte char straddling it would panic
// the slice. That boundary scan is the only non-obvious line in the fn and
// it had no coverage at all.
assert_eq!(
truncate_error("short"),
"short",
"under the cap is untouched"
);
let ascii = truncate_error(&"x".repeat(5000));
assert!(ascii.ends_with('…'));
assert!(ascii.len() <= MAX_ERROR_LEN + '…'.len_utf8());
// 'é' is 2 bytes, so the 2000-byte cap lands mid-char.
let multibyte = truncate_error(&"é".repeat(5000));
assert!(multibyte.ends_with('…'));
assert!(multibyte.len() <= MAX_ERROR_LEN + '…'.len_utf8());
}
// ---- template shapes ----