cli

Command-line interface for Radroots
git clone https://radroots.dev/git/cli.git
Log | Files | Refs | README | LICENSE

commit 1e5bb50839fb3c7265959639b9b32e9c3c58667f
parent 04d6c5ab14bae58bf5a135e9384044150e167654
Author: triesap <tyson@radroots.org>
Date:   Tue, 30 Jun 2026 23:54:51 +0000

tests: harden CLI status guards

- split migrated trade status source ranges
- guard relay refresh status coverage
- reject removed status and root alias tokens
- prove the CLI migrated-path guard lane

Diffstat:
Msrc/runtime/sdk.rs | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 111 insertions(+), 2 deletions(-)

diff --git a/src/runtime/sdk.rs b/src/runtime/sdk.rs @@ -931,10 +931,30 @@ mod tests { required_tokens: &["session.sdk().sync().push_outbox", "PushOutboxRequest::new"], }, MigratedCliPathGuard { - label: "order status", + label: "order public status", path: "src/runtime/order.rs", start: "pub fn status(\n config: &RuntimeConfig", - end: "fn sdk_order_status_from_relay_receipt(", + end: "fn decide_trade_via_sdk(", + required_tokens: &["TradeStatusRequest::parse", "session.sdk().trades().status"], + }, + MigratedCliPathGuard { + label: "order locator status helper", + path: "src/runtime/order.rs", + start: "fn trade_status_for_locator(", + end: "fn inventory_commitments_from_status(", + required_tokens: &[ + "TradeStatusRequest::new(locator)", + "session.block_on(", + ".sdk()", + ".trades()", + ".status(TradeStatusRequest::new(locator))", + ], + }, + MigratedCliPathGuard { + label: "order relay refresh status", + path: "src/runtime/order.rs", + start: "fn sdk_order_status_from_relay_receipt(", + end: "enum OrderStatusRecord", required_tokens: &["TradeStatusRequest::parse", "session.sdk().trades().status"], }, MigratedCliPathGuard { @@ -1058,6 +1078,17 @@ mod tests { "build_job_feedback_tags", "KIND_TRADE_TRANSITION_PROOF", "KIND_JOB_FEEDBACK", + "status_client(", + "TradeStatusClient", + "TradeValidationClient", + ]; + + const REMOVED_SDK_ROOT_TRADE_ALIAS_NAMES: &[&str] = &[ + "trade_buyer", + "trade_seller", + "trade_status", + "trade_resync", + "trade_validation", ]; #[test] @@ -1254,6 +1285,29 @@ mod tests { } } + #[test] + fn migrated_path_root_alias_scanner_preserves_status_helpers() { + assert!( + root_trade_alias_findings( + "allowed", + "fn trade_status_for_locator() { RadrootsSdkError::trade_status_limit_invalid(0, 1, 100); }", + ) + .is_empty() + ); + + let findings = root_trade_alias_findings( + "forbidden", + "sdk.trade_status (request); RadrootsClient::trade_resync(&sdk);", + ); + + for alias in ["trade_status", "trade_resync"] { + assert!( + findings.iter().any(|finding| finding.contains(alias)), + "migrated path root alias scanner must reject `{alias}`" + ); + } + } + fn collect_rs_files(dir: &Path, files: &mut Vec<PathBuf>) { for entry in fs::read_dir(dir).expect("read dir") { let path = entry.expect("entry").path(); @@ -1353,6 +1407,61 @@ mod tests { "{label} contains disallowed migrated-path token `{token}`" ); } + + let findings = root_trade_alias_findings(label, source); + assert!( + findings.is_empty(), + "{label} contains removed SDK root trade aliases:\n{}", + findings.join("\n") + ); + } + + fn root_trade_alias_findings(label: &str, source: &str) -> Vec<String> { + let mut findings = Vec::new(); + + for alias in REMOVED_SDK_ROOT_TRADE_ALIAS_NAMES { + for (index, _) in source.match_indices(alias) { + let before = source[..index].chars().next_back(); + let after_index = index + alias.len(); + let after = source[after_index..].chars().next(); + + if before.is_some_and(is_rust_identifier_character) + || after.is_some_and(is_rust_identifier_character) + { + continue; + } + + if source[after_index..] + .chars() + .find(|character| !character.is_whitespace()) + != Some('(') + { + continue; + } + + let prefix = source[..index].trim_end(); + if prefix.ends_with('.') || prefix.ends_with("::") { + findings.push(format!( + "{label}:{} uses removed SDK root trade alias `{alias}`", + line_number(source, index) + )); + } + } + } + + findings + } + + fn is_rust_identifier_character(character: char) -> bool { + character == '_' || character.is_ascii_alphanumeric() + } + + fn line_number(source: &str, index: usize) -> usize { + source[..index] + .bytes() + .filter(|byte| *byte == b'\n') + .count() + + 1 } fn sample_config(root: &Path, relays: Vec<String>) -> RuntimeConfig {