Radish alpha
h
rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
Radicle Heartwood Protocol & Stack
Radicle
Git
node/test: Add timeouts to functions that wait
Open lorenz opened 2 months ago

The two functions connect and converge used in tests potentially loop forever. Add timeout mechanisms to both.

1 file changed +43 -16 90cf37c4 db5ec5dc
modified crates/radicle-node/src/test/node.rs
@@ -6,6 +6,7 @@ use std::{
    collections::{BTreeMap, BTreeSet},
    fs, io, iter, net, process, thread, time,
    time::Duration,
+
    time::SystemTime,
};

use crossbeam_channel as chan;
@@ -106,22 +107,37 @@ impl<G: Signer<Signature> + cyphernet::Ecdh> NodeHandle<G> {
            .connect(remote.id, remote.addr.into(), ConnectOptions::default())
            .ok();

-
        local_events
-
            .iter()
-
            .find(|e| {
-
                matches!(
-
                    e, Event::PeerConnected { nid } if nid == &remote.id
-
                )
-
            })
-
            .unwrap();
-
        remote_events
-
            .iter()
-
            .find(|e| {
-
                matches!(
-
                    e, Event::PeerConnected { nid } if nid == &self.id
-
                )
-
            })
-
            .unwrap();
+
        // This timeout is rather arbitrary. The main point is to avoid waiting
+
        // indefinitely, but to also give slow CI enough time to settle.
+
        const TIMEOUT: Duration = Duration::from_secs(60);
+

+
        log::debug!(target: "test", "Waiting {:?} for node {} to be connected to peer {} (direction 1/2).", TIMEOUT, self.id, remote.id);
+
        if let Err(err) = local_events.wait(
+
            |event| match event {
+
                Event::PeerConnected { nid } if *nid == remote.id => Some(()),
+
                _ => None,
+
            },
+
            TIMEOUT,
+
        ) {
+
            panic!(
+
                "Failed to connect node {} to peer {} within {:?}: {err}",
+
                self.id, remote.id, TIMEOUT
+
            );
+
        }
+

+
        log::debug!(target: "test", "Waiting {:?} for node {} to be connected to peer {} (direction 2/2).", TIMEOUT, remote.id, self.id);
+
        if let Err(err) = remote_events.wait(
+
            |event| match event {
+
                Event::PeerConnected { nid } if *nid == self.id => Some(()),
+
                _ => None,
+
            },
+
            TIMEOUT,
+
        ) {
+
            panic!(
+
                "Failed to connect node {} to peer {} within {:?}: {err}",
+
                remote.id, self.id, TIMEOUT
+
            );
+
        }

        self
    }
@@ -577,6 +593,12 @@ pub fn converge<'a, G: Signer<Signature> + cyphernet::Ecdh + 'static>(
        }
    }

+
    // This timeout is rather arbitrary. The main point is to avoid waiting
+
    // indefinitely, but to also give slow CI enough time to settle.
+
    const TIMEOUT_DURATION: Duration = Duration::from_secs(30);
+

+
    let timeout = SystemTime::now() + TIMEOUT_DURATION;
+

    // Then, while there are nodes remaining to converge, check each node to see if
    // its routing table has all routes. If so, remove it from the remaining nodes.
    while !remaining.is_empty() {
@@ -594,6 +616,11 @@ pub fn converge<'a, G: Signer<Signature> + cyphernet::Ecdh + 'static>(
            true
        });
        thread::sleep(Duration::from_millis(100));
+

+
        if SystemTime::now() > timeout {
+
            log::warn!(target: "test", "Nodes did not converge within {:?}. Remaining nodes: {:?}", TIMEOUT_DURATION, remaining.keys());
+
            break;
+
        }
    }
    all_routes
}