solana/core/tests/gossip.rs

184 lines
5.6 KiB
Rust
Raw Normal View History

2018-05-30 09:50:28 -07:00
#[macro_use]
extern crate log;
2018-05-30 09:50:28 -07:00
use rayon::iter::*;
2019-08-21 10:23:33 -07:00
use solana_core::cluster_info::{ClusterInfo, Node};
use solana_core::gossip_service::GossipService;
use solana_perf::packet::Packet;
use solana_sdk::signature::{Keypair, Signer};
2018-11-16 08:45:59 -08:00
use solana_sdk::timing::timestamp;
2018-05-30 09:50:28 -07:00
use std::net::UdpSocket;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
2018-05-30 09:50:28 -07:00
use std::thread::sleep;
use std::time::Duration;
fn test_node(exit: &Arc<AtomicBool>) -> (Arc<ClusterInfo>, GossipService, UdpSocket) {
let keypair = Arc::new(Keypair::new());
let mut test_node = Node::new_localhost_with_pubkey(&keypair.pubkey());
let cluster_info = Arc::new(ClusterInfo::new(test_node.info.clone(), keypair));
2020-01-31 14:23:51 -08:00
let gossip_service = GossipService::new(&cluster_info, None, test_node.sockets.gossip, exit);
let _ = cluster_info.my_contact_info();
(
cluster_info,
gossip_service,
test_node.sockets.tvu.pop().unwrap(),
)
2018-05-30 09:50:28 -07:00
}
/// Test that the network converges.
2019-03-08 17:23:07 -08:00
/// Run until every node in the network has a full ContactInfo set.
/// Check that nodes stop sending updates after all the ContactInfo has been shared.
2018-05-30 09:50:28 -07:00
/// tests that actually use this function are below
fn run_gossip_topo<F>(num: usize, topo: F)
2018-05-30 09:50:28 -07:00
where
F: Fn(&Vec<(Arc<ClusterInfo>, GossipService, UdpSocket)>),
2018-05-30 09:50:28 -07:00
{
let exit = Arc::new(AtomicBool::new(false));
let listen: Vec<_> = (0..num).map(|_| test_node(&exit)).collect();
2018-05-30 09:50:28 -07:00
topo(&listen);
let mut done = true;
for i in 0..(num * 32) {
done = true;
let total: usize = listen.iter().map(|v| v.0.gossip_peers().len()).sum();
if (total + num) * 10 > num * num * 9 {
done = true;
2018-05-30 09:50:28 -07:00
break;
} else {
trace!("not converged {} {} {}", i, total + num, num * num);
2018-05-30 09:50:28 -07:00
}
sleep(Duration::new(1, 0));
}
exit.store(true, Ordering::Relaxed);
for (_, dr, _) in listen {
2018-07-03 22:21:53 -07:00
dr.join().unwrap();
2018-05-30 09:50:28 -07:00
}
assert!(done);
}
/// ring a -> b -> c -> d -> e -> a
#[test]
fn gossip_ring() {
solana_logger::setup();
run_gossip_topo(50, |listen| {
2018-05-30 09:50:28 -07:00
let num = listen.len();
for n in 0..num {
let y = n % listen.len();
let x = (n + 1) % listen.len();
let yv = &listen[y].0;
let mut d = yv.lookup_contact_info(&yv.id(), |ci| ci.clone()).unwrap();
d.wallclock = timestamp();
listen[x].0.insert_info(d);
2018-05-30 09:50:28 -07:00
}
});
}
/// ring a -> b -> c -> d -> e -> a
#[test]
#[ignore]
fn gossip_ring_large() {
solana_logger::setup();
run_gossip_topo(600, |listen| {
let num = listen.len();
for n in 0..num {
let y = n % listen.len();
let x = (n + 1) % listen.len();
let yv = &listen[y].0;
let mut d = yv.lookup_contact_info(&yv.id(), |ci| ci.clone()).unwrap();
d.wallclock = timestamp();
listen[x].0.insert_info(d);
}
});
}
2018-05-30 09:50:28 -07:00
/// star a -> (b,c,d,e)
#[test]
fn gossip_star() {
solana_logger::setup();
run_gossip_topo(10, |listen| {
2018-05-30 09:50:28 -07:00
let num = listen.len();
for n in 0..(num - 1) {
let x = 0;
let y = (n + 1) % listen.len();
let yv = &listen[y].0;
let mut yd = yv.lookup_contact_info(&yv.id(), |ci| ci.clone()).unwrap();
yd.wallclock = timestamp();
let xv = &listen[x].0;
xv.insert_info(yd);
trace!("star leader {}", &xv.id());
2018-05-30 09:50:28 -07:00
}
});
}
/// rstar a <- (b,c,d,e)
#[test]
fn gossip_rstar() {
solana_logger::setup();
run_gossip_topo(10, |listen| {
2018-05-30 09:50:28 -07:00
let num = listen.len();
let xd = {
let xv = &listen[0].0;
xv.lookup_contact_info(&xv.id(), |ci| ci.clone()).unwrap()
2018-05-30 09:50:28 -07:00
};
trace!("rstar leader {}", xd.id);
2018-05-30 09:50:28 -07:00
for n in 0..(num - 1) {
let y = (n + 1) % listen.len();
let yv = &listen[y].0;
yv.insert_info(xd.clone());
trace!("rstar insert {} into {}", xd.id, yv.id());
2018-05-30 09:50:28 -07:00
}
});
}
#[test]
pub fn cluster_info_retransmit() {
solana_logger::setup();
2018-05-30 09:50:28 -07:00
let exit = Arc::new(AtomicBool::new(false));
trace!("c1:");
let (c1, dr1, tn1) = test_node(&exit);
2018-05-30 09:50:28 -07:00
trace!("c2:");
let (c2, dr2, tn2) = test_node(&exit);
2018-05-30 09:50:28 -07:00
trace!("c3:");
let (c3, dr3, tn3) = test_node(&exit);
let c1_contact_info = c1.my_contact_info();
2018-05-30 09:50:28 -07:00
c2.insert_info(c1_contact_info.clone());
c3.insert_info(c1_contact_info);
2018-05-30 09:50:28 -07:00
let num = 3;
2018-05-30 09:50:28 -07:00
//wait to converge
trace!("waiting to converge:");
let mut done = false;
for _ in 0..30 {
done = c1.gossip_peers().len() == num - 1
&& c2.gossip_peers().len() == num - 1
&& c3.gossip_peers().len() == num - 1;
2018-05-30 09:50:28 -07:00
if done {
break;
}
sleep(Duration::new(1, 0));
}
assert!(done);
let mut p = Packet::default();
p.meta.size = 10;
let peers = c1.retransmit_peers();
let retransmit_peers: Vec<_> = peers.iter().collect();
ClusterInfo::retransmit_to(&retransmit_peers, &mut p, None, &tn1, false).unwrap();
2018-05-30 09:50:28 -07:00
let res: Vec<_> = [tn1, tn2, tn3]
.into_par_iter()
.map(|s| {
let mut p = Packet::default();
2018-05-30 09:50:28 -07:00
s.set_read_timeout(Some(Duration::new(1, 0))).unwrap();
let res = s.recv_from(&mut p.data);
2018-05-30 09:50:28 -07:00
res.is_err() //true if failed to receive the retransmit packet
})
.collect();
2018-05-30 09:50:28 -07:00
//true if failed receive the retransmit packet, r2, and r3 should succeed
//r1 was the sender, so it should fail to receive the packet
assert_eq!(res, [true, false, false]);
exit.store(true, Ordering::Relaxed);
2018-07-03 22:21:53 -07:00
dr1.join().unwrap();
dr2.join().unwrap();
dr3.join().unwrap();
2018-05-30 09:50:28 -07:00
}