Skip to content

Commit 211974d

Browse files
committed
test(control-plane): de-flake auth-link integration tests
The auth-link integration tests failed intermittently in CI (a different `test_link_*` test each run, always at the same two assertion sites, and on `main` too) under slow, heavily-parallel jobs such as the llvm-cov coverage run. Two independent causes: 1. Wrong-link race. `auth_link()` matched the first link sourced from *either* the connector or the protected group, but `wait_auth_link()` then asserts the source is the connector. During reconciliation a transient protected-sourced link can reach the target status first, tripping the assertion. Select the connector-sourced link directly so transient links are skipped and the loop keeps polling for the one every caller actually expects. 2. Timeouts too tight under instrumentation. Reconciliation occasionally needs longer than 30s/15s when the runner is saturated (llvm-cov, parallel matrix), causing `wait_*` timeout panics. Double DEFAULT_TIMEOUT (30->60s) and SHORT_TIMEOUT (15->30s); the happy path returns immediately, so passing tests are unaffected. No production code changes; test-only. Signed-off-by: Luca Muscariello <muscariello@ieee.org>
1 parent 74bef97 commit 211974d

1 file changed

Lines changed: 14 additions & 10 deletions

File tree

crates/control-plane/tests/integration_test.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,11 @@ const LINK_APPLIED: i32 = 2;
5656
/// Node status constants.
5757
const NODE_CONNECTED: i32 = 1;
5858

59-
/// Default timeout for waiting on async conditions.
60-
const DEFAULT_TIMEOUT: Duration = Duration::from_secs(30);
61-
const SHORT_TIMEOUT: Duration = Duration::from_secs(15);
59+
/// Default timeout for waiting on async conditions. Generous headroom so the
60+
/// reconciler has time to converge under slow, heavily-parallel CI runs
61+
/// (e.g. `llvm-cov` instrumentation); the happy path returns immediately.
62+
const DEFAULT_TIMEOUT: Duration = Duration::from_secs(60);
63+
const SHORT_TIMEOUT: Duration = Duration::from_secs(30);
6264

6365
/// Per-group registration secrets (each group has its own secret for isolation).
6466
const TEST_GROUP_SECRETS: &[(&str, &str)] = &[
@@ -1890,13 +1892,15 @@ struct AuthLinkNodes {
18901892
}
18911893

18921894
async fn auth_link(client: &mut NbClient) -> Option<LinkEntry> {
1893-
collect_links(client, "", "").await.into_iter().find(|l| {
1894-
!l.deleted
1895-
&& matches!(
1896-
l.source_node_id.split('/').next(),
1897-
Some(AUTH_GROUP_CONNECTOR) | Some(AUTH_GROUP_PROTECTED)
1898-
)
1899-
})
1895+
// Select the connector-sourced link specifically. During reconciliation a
1896+
// transient link sourced from the protected node can briefly appear; matching
1897+
// it here would intermittently trip `wait_auth_link`'s
1898+
// `source_node_id == AUTH_CONNECTOR_ID` assertion. Every caller expects the
1899+
// connector link, so wait for exactly that one.
1900+
collect_links(client, "", "")
1901+
.await
1902+
.into_iter()
1903+
.find(|l| !l.deleted && l.source_node_id == AUTH_CONNECTOR_ID)
19001904
}
19011905

19021906
async fn wait_auth_link(client: &mut NbClient, timeout: Duration, status: i32, msg: Option<&str>) {

0 commit comments

Comments
 (0)