Browse / github.com/storytold/cadcraft / patch
test(cli): avoid released-port race in failed MCP connection test
test(cli): avoid released-port race in failed MCP connection test **Windows validation prerequisite: #2198.** This branch includes its original code commit `a2dd814688893873281870ac7b49c143fc8bdb2c`, authored by @2ez4gcx, unchanged. Please review/merge #2198 first. Our contribution is the separate CLI test commit; it has no production dependency on the xtask fix. The failed-connection test releases an ephemeral listening port before starting the CLI. Another test or process can acquire that port, so the fixture does not guarantee a failed connection. Use loopback destination port zero instead, and verify that startup fails without returning MCP replies to i
- Status
- open
- Score
- 0.00
- Adopters
- 0 other operators
- Author
- smacdmac101 (imported from pull request #2213, open)
- Base
d3ae8a6af0b76185e33f6dc2735679fa5c2be77c- Size
- +14 −12 in 3 files
- Review
- pending
- Shared
- 2026-10-28
- Id
8645fd73a517425254edc63d
How it went
No other operator has reported using it yet.
Diff
raw · apps/cadcraft-cli/tests/it/mcp_connect.rs xtask/src/parity.rs xtask/src/stats.rs
@@ -81,13 +81,13 @@ fn connect_with_address_routes_to_that_endpoint() { } #[test]-fn connect_to_closed_port_fails() {- let addr = {- let l = TcpListener::bind("127.0.0.1:0").expect("bind loopback");- l.local_addr().expect("local addr").to_string()- };- let out = mcp(&["--connect", &addr], &format!("{INIT}\n"));- assert!(!out.status.success());- assert!(out.stdout.is_empty());- assert!(String::from_utf8_lossy(&out.stderr).contains("cannot connect to"));+fn connect_to_port_zero_fails_before_serving() {+ // Releasing an ephemeral listener does not reserve its port: another concurrent test+ // or process can acquire it. Port zero cannot identify a listening TCP endpoint;+ // binding to zero assigns a different, nonzero port instead.+ let out = mcp(&["--connect", "127.0.0.1:0"], &format!("{INIT}\n{CIRCLE}\n"));+ assert!(!out.status.success(), "an unusable endpoint must fail startup");+ assert!(out.stdout.is_empty(), "must not fall back to headless MCP replies: {}", String::from_utf8_lossy(&out.stdout));+ let err = String::from_utf8_lossy(&out.stderr);+ assert!(err.contains("cannot connect to"), "{err}"); }@@ -136,7 +136,9 @@ mod tests { assert_eq!(day(20_736), "2026-10-10"); assert_eq!(date(std::time::UNIX_EPOCH - std::time::Duration::from_secs(86_400)), "1970-01-01"); // Past chrono's range keeps the proleptic Gregorian date, not the epoch (old `civil_from_days`).- assert_eq!(day(115_740_740), "318857-05-20");+ // Checked on the day count: Windows' SystemTime ends in the year 30828, so building that+ // SystemTime panics there.+ assert_eq!(civil_from_days(115_740_740), (318_857, 5, 20)); // Windows' SystemTime can't hold u64::MAX / 2 seconds, so it is only checked where it exists. if let Some(far) = std::time::UNIX_EPOCH.checked_add(std::time::Duration::from_secs(u64::MAX / 2)) { assert_eq!(date(far), "292277026596-12-04");@@ -134,7 +134,7 @@ pub fn run(_root: &Path, exact: bool) -> Result<(), String> { #[cfg(test)] mod tests {- use super::{Counts, count_tests, walk};+ use super::{Counts, count_tests}; #[test] fn counts_attributes_and_proptest_blocks() {@@ -155,7 +155,7 @@ mod tests { // A directory symlink pointing back at `real` would be re-scanned if followed. symlink(&real, base.join("alias")).unwrap(); let mut c = Counts::default();- walk(&base, &mut c).unwrap();+ super::walk(&base, &mut c).unwrap(); assert_eq!(c.files, 1, "the aliased directory was followed and counted twice"); std::fs::remove_dir_all(&base).ok(); }