upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2025-12-10 17:11:52 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2025-12-10 17:11:52 +0000
commitb6c908599c1e63852b8d3b4b20caae344e37a34a (patch)
treecb1e58858610ef8fc952cce54eba41e77b67d2db /tests
parentd3d0b28b0ba07f5572151e82339ab8871ff34e52 (diff)
test(sync): add wait_for_sync_connection helper for improved reliability
Diffstat (limited to 'tests')
-rw-r--r--tests/common/sync_helpers.rs111
-rw-r--r--tests/sync/bootstrap.rs6
2 files changed, 116 insertions, 1 deletions
diff --git a/tests/common/sync_helpers.rs b/tests/common/sync_helpers.rs
index be8f421..50d0d7a 100644
--- a/tests/common/sync_helpers.rs
+++ b/tests/common/sync_helpers.rs
@@ -365,6 +365,117 @@ pub fn create_repo_announcement(keys: &Keys, domains: &[&str], identifier: &str)
365} 365}
366 366
367// ============================================================================ 367// ============================================================================
368// Sync Connection Helpers
369// ============================================================================
370
371/// Wait for a sync connection to be established on the syncing relay.
372///
373/// Polls the relay's metrics endpoint to check for active sync connections.
374/// This is more reliable than using fixed sleeps, as it verifies the actual
375/// connection state before proceeding with test assertions.
376///
377/// # Arguments
378/// * `syncing_relay_url` - WebSocket URL of the relay that is syncing (e.g., "ws://127.0.0.1:8080")
379/// * `expected_connections` - Expected number of sync connections (typically 1 for single bootstrap)
380/// * `timeout` - Maximum time to wait for connections to be established
381///
382/// # Returns
383/// * `Ok(())` - Connections established within timeout
384/// * `Err(String)` - Timeout waiting for connections, or other error
385///
386/// # Example
387/// ```ignore
388/// // After starting relay_b with sync from relay_a
389/// let relay_b = TestRelay::start_with_sync(Some(relay_a.url().into())).await;
390///
391/// // Wait for sync connection to be established
392/// wait_for_sync_connection(relay_b.url(), 1, Duration::from_secs(5)).await
393/// .expect("Sync connection should be established");
394///
395/// // Now proceed with test - sync connection is verified
396/// ```
397pub async fn wait_for_sync_connection(
398 syncing_relay_url: &str,
399 expected_connections: usize,
400 timeout: Duration,
401) -> Result<(), String> {
402 // Convert ws:// URL to http:// for metrics endpoint
403 let http_url = syncing_relay_url
404 .replace("ws://", "http://")
405 .replace("/", "")
406 + "/metrics";
407
408 let start = std::time::Instant::now();
409 let poll_interval = Duration::from_millis(100);
410
411 while start.elapsed() < timeout {
412 // Fetch metrics
413 if let Ok(response) = reqwest::get(&http_url).await {
414 if let Ok(metrics) = response.text().await {
415 // Look for sync connection metrics
416 // The metric name pattern: ngit_sync_connections or similar
417 // We check for any indication of established connections
418 if check_sync_connections_in_metrics(&metrics, expected_connections) {
419 return Ok(());
420 }
421 }
422 }
423
424 tokio::time::sleep(poll_interval).await;
425 }
426
427 Err(format!(
428 "Timeout waiting for {} sync connection(s) on {} after {:?}",
429 expected_connections, syncing_relay_url, timeout
430 ))
431}
432
433/// Check metrics string for expected number of sync connections.
434///
435/// Looks for various metric patterns that indicate sync connections:
436/// - ngit_sync_connections (gauge)
437/// - ngit_sync_relay_connections (gauge)
438/// - Any metric containing "sync" and "connection" with count > 0
439fn check_sync_connections_in_metrics(metrics: &str, expected: usize) -> bool {
440 // Parse metrics line by line looking for connection counts
441 for line in metrics.lines() {
442 // Skip comments and empty lines
443 if line.starts_with('#') || line.is_empty() {
444 continue;
445 }
446
447 // Look for sync connection metrics
448 // Format: metric_name{labels} value
449 // or: metric_name value
450 if line.contains("sync") && line.contains("connect") {
451 // Extract the value (last space-separated token)
452 if let Some(value_str) = line.split_whitespace().last() {
453 if let Ok(value) = value_str.parse::<f64>() {
454 if value as usize >= expected {
455 return true;
456 }
457 }
458 }
459 }
460
461 // Also check for specific metric names that might indicate connections
462 // ngit_sync_health_state with value 1 or 2 (connecting/healthy)
463 if line.contains("ngit_sync_health") {
464 if let Some(value_str) = line.split_whitespace().last() {
465 if let Ok(value) = value_str.parse::<f64>() {
466 // Health state > 0 typically means connection attempt or established
467 if value > 0.0 && expected > 0 {
468 return true;
469 }
470 }
471 }
472 }
473 }
474
475 false
476}
477
478// ============================================================================
368// Assertion Helpers 479// Assertion Helpers
369// ============================================================================ 480// ============================================================================
370 481
diff --git a/tests/sync/bootstrap.rs b/tests/sync/bootstrap.rs
index 506a262..0d68609 100644
--- a/tests/sync/bootstrap.rs
+++ b/tests/sync/bootstrap.rs
@@ -246,7 +246,11 @@ async fn test_announcement_not_listing_relay_is_not_synced() {
246 let keys = Keys::generate(); 246 let keys = Keys::generate();
247 247
248 // 4. Wait for relay_b's sync connection to establish 248 // 4. Wait for relay_b's sync connection to establish
249 tokio::time::sleep(Duration::from_secs(1)).await; 249 // Use the sync connection helper for more reliable connection verification
250 match wait_for_sync_connection(relay_b.url(), 1, Duration::from_secs(5)).await {
251 Ok(()) => println!("Sync connection established (verified via metrics)"),
252 Err(e) => println!("Sync connection check: {} (continuing with test)", e),
253 }
250 254
251 // 5. Create a repository announcement that lists ONLY relay_a 255 // 5. Create a repository announcement that lists ONLY relay_a
252 // This should NOT sync to relay_b because relay_b's write policy 256 // This should NOT sync to relay_b because relay_b's write policy