rings-core 0.20.0

Chord DHT implementation with ICE
Documentation
use rings_transport::core::transport::WebrtcConnectionState;

use super::test_stabilization::replace_observed_topology;
use crate::dht::successor::SuccessorReader;
use crate::ecc::SecretKey;
use crate::error::Result;
use crate::tests::default::prepare_node;
use crate::tests::default::wait_for_msgs;
use crate::tests::manually_establish_connection;

async fn assert_unavailable_successor_fails_over(
    state: WebrtcConnectionState,
    data_channel_open: Option<bool>,
) -> Result<()> {
    let node1 = prepare_node(SecretKey::random()).await;
    let node2 = prepare_node(SecretKey::random()).await;
    let node3 = prepare_node(SecretKey::random()).await;

    manually_establish_connection(&node1.swarm, &node2.swarm).await;
    manually_establish_connection(&node1.swarm, &node3.swarm).await;
    wait_for_msgs([&node1, &node2, &node3]).await;

    replace_observed_topology(&node1, &[node2.did()], Some(node2.did()), &[
        (0, node3.did()),
        (3, node3.did()),
    ])?;

    node1
        .swarm
        .transport
        .force_peer_connection_state_without_callback(node2.did(), state)?;
    if let Some(open) = data_channel_open {
        node1
            .swarm
            .transport
            .force_peer_data_channel_open_without_callback(node2.did(), Some(open))?;
    }

    node1
        .swarm
        .stabilizer()
        .clean_unavailable_connections()
        .await?;

    assert!(!node1.swarm.transport.is_admitted_connection(node2.did()));
    assert!(node1.swarm.transport.get_connection(node2.did()).is_none());
    assert!(!node1.dht().successors().contains(&node2.did())?);
    assert!(node1.dht().successors().contains(&node3.did())?);
    assert_eq!(*node1.dht().lock_predecessor()?, None);
    assert!(!node1.dht().lock_finger()?.contains(Some(node2.did())));
    assert!(node1.dht().lock_finger()?.contains(Some(node3.did())));
    assert!(node1.swarm.transport.is_admitted_connection(node3.did()));
    assert!(node1.swarm.transport.storage_repair_requested());
    assert_eq!(
        node1
            .swarm
            .transport
            .get_connection(node3.did())
            .map(|conn| conn.webrtc_connection_state()),
        Some(WebrtcConnectionState::Connected)
    );

    Ok(())
}

#[tokio::test]
async fn test_unavailable_successor_states_only_promote_a_live_replacement() -> Result<()> {
    for (state, data_channel_open) in [
        (WebrtcConnectionState::Disconnected, None),
        (WebrtcConnectionState::Failed, None),
        (WebrtcConnectionState::Closed, None),
        (WebrtcConnectionState::Connected, Some(false)),
    ] {
        assert_unavailable_successor_fails_over(state, data_channel_open).await?;
    }
    Ok(())
}