mod utils;
use anyhow::{Error, Result};
use ed25519_dalek::Keypair;
use futures::future;
use sn_routing::{Config, Event, NodeElderChange, ELDER_SIZE};
use std::collections::HashSet;
use tokio::time;
use utils::*;
use xor_name::XOR_NAME_LEN;
#[tokio::test]
async fn test_genesis_node() -> Result<()> {
let keypair = Keypair::generate(&mut rand::thread_rng());
let (node, mut event_stream) = create_node(Config {
first: true,
keypair: Some(keypair),
..Default::default()
})
.await?;
assert_next_event!(event_stream, Event::EldersChanged { .. });
assert!(node.is_elder().await);
assert_eq!(node.name().await[XOR_NAME_LEN - 1], 255);
Ok(())
}
#[tokio::test]
async fn test_node_bootstrapping() -> Result<()> {
let (genesis_node, mut event_stream) = create_node(Config {
first: true,
..Default::default()
})
.await?;
let genesis_handler = tokio::spawn(async move {
assert_next_event!(event_stream, Event::EldersChanged { .. });
assert_next_event!(event_stream, Event::MemberJoined { .. });
});
let genesis_contact = genesis_node.our_connection_info();
let (node1, _event_stream) = create_node(config_with_contact(genesis_contact)).await?;
genesis_handler.await?;
let elder_size = 2;
verify_invariants_for_node(&genesis_node, elder_size).await?;
verify_invariants_for_node(&node1, elder_size).await?;
Ok(())
}
#[tokio::test]
async fn test_startup_section_bootstrapping() -> Result<()> {
let (genesis_node, mut event_stream) = create_node(Config {
first: true,
..Default::default()
})
.await?;
let other_node_count = ELDER_SIZE - 1;
let genesis_contact = genesis_node.our_connection_info();
let nodes_joining_tasks = (0..other_node_count).map(|_| async {
let (node, mut event_stream) = create_node(config_with_contact(genesis_contact)).await?;
assert_event!(
event_stream,
Event::EldersChanged {
self_status_change: NodeElderChange::Promoted,
..
}
);
Ok::<_, Error>(node)
});
let other_nodes = future::try_join_all(nodes_joining_tasks).await?;
let mut joined_names = HashSet::new();
while let Some(event) = time::timeout(TIMEOUT, event_stream.next()).await? {
let _ = match event {
Event::MemberJoined { name, .. } => joined_names.insert(name),
Event::MemberLeft { name, .. } => joined_names.remove(&name),
_ => false,
};
let actual_names: HashSet<_> = future::join_all(other_nodes.iter().map(|node| node.name()))
.await
.into_iter()
.collect();
if joined_names == actual_names {
return Ok(());
}
}
panic!("event stream unexpectedly closed")
}
#[tokio::test]
async fn test_startup_elders() -> Result<()> {
let mut nodes = create_connected_nodes(ELDER_SIZE).await?;
future::join_all(nodes.iter_mut().map(|(node, stream)| async move {
if node.is_elder().await {
return;
}
assert_event!(
stream,
Event::EldersChanged {
self_status_change: NodeElderChange::Promoted,
..
}
)
}))
.await;
Ok(())
}