Skip to content

Commit

Permalink
Added tests for tunnel timeout, keep_alive and for lib unstable peers…
Browse files Browse the repository at this point in the history
…, data errors
  • Loading branch information
0liCom committed Aug 27, 2020
1 parent afded6e commit 402a339
Show file tree
Hide file tree
Showing 2 changed files with 190 additions and 2 deletions.
54 changes: 54 additions & 0 deletions src/onion/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use tokio::stream;

const TEST_IP: IpAddr = IpAddr::V4(Ipv4Addr::LOCALHOST);
static PORT_COUNTER: AtomicU16 = AtomicU16::new(42000);
const TIME_ERROR_TIMEOUT: u64 = 4;
const ERROR_TIMEOUT: Duration = Duration::from_secs(TIME_ERROR_TIMEOUT);

async fn listen(mut listener: TcpListener, host_key: &RsaPrivateKey) -> Result<()> {
println!(
Expand Down Expand Up @@ -208,3 +210,55 @@ async fn test_data_bidirectional() -> Result<()> {
);
Ok(())
}

#[tokio::test]
async fn test_keep_alive() -> Result<()> {
let rng = rand::SystemRandom::new();
let peers = spawn_n_peers(3).await;
let mut tunnel = Tunnel::init(0, &peers[0], &rng).await?;
for i in 1..3 {
tunnel.extend(&peers[i], &rng).await?;
}
assert_eq!(tunnel.len(), 3);
tunnel.keep_alive(&rng).await?;
assert_eq!(tunnel.len(), 3);
Ok(())
}

#[tokio::test]
async fn test_timeout() -> Result<()> {
let rng = rand::SystemRandom::new();
let peers = spawn_n_peers(3).await;
let mut tunnel = Tunnel::init(0, &peers[0], &rng).await?;
for i in 1..2 {
tunnel.extend(&peers[i], &rng).await?;
}
assert_eq!(tunnel.len(), 2);
let (tx, rx) = mpsc::unbounded_channel();
let (events_tx, mut events_rx) = mpsc::channel(1);
let tunnel_id = tunnel.id;
let peer_provider = PeerProvider::from_stream(stream::iter(vec![peers[2].clone()]));
let builder = TunnelBuilder::new(tunnel.id, TunnelDestination::Fixed(peers[1].clone()), 1, peer_provider, rng);
let mut handler = TunnelHandler::new(tunnel, builder, rx, events_tx);

let handler_task = tokio::spawn({
async move {
handler.handle().await;
}
});

tx.send(tunnel::Request::Switchover)?;
match time::timeout(ERROR_TIMEOUT, events_rx.next()).await {
Ok(Some(Event::Ready { tunnel_id: ev_tunnel_id })) => assert_eq!(ev_tunnel_id, tunnel_id),
Ok(e) => panic!("Expected ready event, got {:?}", e),
Err(_) => panic!("Expected ready event, got timeout"),
}

let mut delay = time::delay_for(Duration::from_secs(circuit::TIMEOUT_IDLE + TIME_ERROR_TIMEOUT));
tokio::select! {
_ = handler_task => Ok(()),
_ = &mut delay => {
panic!("No circuit destroyed the tunnel before timeout")
},
}
}
138 changes: 136 additions & 2 deletions tests/onion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ use tokio::stream::StreamExt;
use tokio::time;

static PORT_COUNTER: AtomicU16 = AtomicU16::new(42000);
const ERROR_TIMEOUT: Duration = Duration::from_secs(2);
const ERROR_TIMEOUT: Duration = Duration::from_secs(4);
const ROUND_TIMEOUT: Duration = Duration::from_secs(45);
const DELAY_TIMEOUT: Duration = Duration::from_secs(2);
const TUNNEL_ID: TunnelId = 3; // chosen by fair dice roll
const TEST_DATA: &[u8] = b"test";
const LONG_DATA: [u8; 4098] = [13; 4098];
Expand All @@ -28,6 +29,15 @@ fn new_unique_peer() -> (Peer, RsaPrivateKey) {
(Peer::new(addr, hostkey.public_key()), hostkey)
}

fn new_unique_peers(n: usize) -> Vec<Peer> {
let mut peers = vec![];
for _ in 0..n {
let (peer, _) = new_unique_peer();
peers.push(peer);
}
peers
}

async fn spawn_peer(
peers: Vec<Peer>,
cover: bool,
Expand Down Expand Up @@ -61,7 +71,7 @@ async fn test_cover() {
pretty_env_logger::init();
let peer1 = spawn_simple_peer().await;
let mut peer2 = spawn_peer(vec![peer1.peer], true, 0).await;
time::delay_for(ERROR_TIMEOUT).await;
time::delay_for(DELAY_TIMEOUT).await;
peer2.onion.send_cover(1);
match time::timeout(ERROR_TIMEOUT, peer2.events.next()).await {
Ok(e) => panic!("Got error event: {:?}", e),
Expand Down Expand Up @@ -116,6 +126,46 @@ async fn test_build_error() {
}
}

#[tokio::test]
async fn test_build_unstable_success() {
// For some reason 8 (MAX_PEER_FAILURES - 2) or higher fails
let mut peers = new_unique_peers(7);
let peer2 = spawn_peer(vec![]).await;
peers.push(peer2.peer);
let mut peer1 = spawn_peer(peers).await;
let mut peer3 = spawn_peer(vec![]).await;
peer1.onion.build_tunnel(TUNNEL_ID, peer3.peer, 1);
match time::timeout(ROUND_TIMEOUT, peer1.events.next()).await {
Ok(Some(Event::Ready { tunnel_id })) => assert_eq!(tunnel_id, TUNNEL_ID),
Ok(e) => panic!("Expected ready event, got {:?}", e),
Err(_) => panic!("Expected ready event, got timeout"),
}

match time::timeout(ERROR_TIMEOUT, peer3.events.next()).await {
Ok(Some(Event::Incoming { tunnel_id })) => assert_eq!(tunnel_id, TUNNEL_ID),
Ok(e) => panic!("Expected incoming event, got {:?}", e),
Err(_) => panic!("Expected incoming event, got timeout"),
}
}

#[tokio::test]
async fn test_build_unstable_error() {
let mut peers = new_unique_peers(12);
let peer2 = spawn_peer(vec![]).await;
peers.push(peer2.peer);
let mut peer1 = spawn_peer(peers).await;
let peer3 = spawn_peer(vec![]).await;
peer1.onion.build_tunnel(TUNNEL_ID, peer3.peer, 1);
match time::timeout(ERROR_TIMEOUT, peer1.events.next()).await {
Ok(Some(Event::Error {
reason: ErrorReason::Build,
tunnel_id,
})) => assert_eq!(tunnel_id, TUNNEL_ID),
Ok(e) => panic!("Expected error event, got {:?}", e),
Err(_) => panic!("Expected error event, got timeout"),
}
}

#[tokio::test]
async fn test_data() {
let mut peer1 = spawn_simple_peer().await;
Expand Down Expand Up @@ -220,3 +270,87 @@ async fn test_long_data_two_hops() {
}
}
}

#[tokio::test]
async fn test_data_error_tunnel_id() {
let mut peer1 = spawn_peer(vec![]).await;
let mut peer2 = spawn_peer(vec![]).await;

peer1.onion.build_tunnel(TUNNEL_ID, peer2.peer, 0);
match time::timeout(ROUND_TIMEOUT, peer1.events.next()).await {
Ok(Some(Event::Ready { tunnel_id })) => assert_eq!(tunnel_id, TUNNEL_ID),
Ok(e) => panic!("Expected ready event, got {:?}", e),
Err(_) => panic!("Expected ready event, got timeout"),
}

match time::timeout(ERROR_TIMEOUT, peer2.events.next()).await {
Ok(Some(Event::Incoming { tunnel_id })) => assert_eq!(tunnel_id, TUNNEL_ID),
Ok(e) => panic!("Expected incoming event, got {:?}", e),
Err(_) => panic!("Expected incoming event, got timeout"),
}

let wrong_tunnel_id = TUNNEL_ID + 1;
peer1.onion.send_data(wrong_tunnel_id, TEST_DATA);
match time::timeout(ERROR_TIMEOUT, peer2.events.next()).await {
Ok(Some(Event::Error {
reason: ErrorReason::Data,
tunnel_id,
})) => assert_eq!(tunnel_id, wrong_tunnel_id),
Ok(e) => panic!("Expected error event, got {:?}", e),
Err(_) => panic!("Expected error event, got timeout"),
}
}

#[tokio::test]
async fn test_data_error_disconnected_destination() {
let mut peer1 = spawn_peer(vec![]).await;
let mut peer2 = spawn_peer(vec![]).await;

peer1.onion.build_tunnel(TUNNEL_ID, peer2.peer, 0);
match time::timeout(ROUND_TIMEOUT, peer1.events.next()).await {
Ok(Some(Event::Ready { tunnel_id })) => assert_eq!(tunnel_id, TUNNEL_ID),
Ok(e) => panic!("Expected ready event, got {:?}", e),
Err(_) => panic!("Expected ready event, got timeout"),
}

match time::timeout(ERROR_TIMEOUT, peer2.events.next()).await {
Ok(Some(Event::Incoming { tunnel_id })) => assert_eq!(tunnel_id, TUNNEL_ID),
Ok(e) => panic!("Expected incoming event, got {:?}", e),
Err(_) => panic!("Expected incoming event, got timeout"),
}

peer2.onion.destroy_tunnel(TUNNEL_ID);
time::delay_for(DELAY_TIMEOUT).await;
peer1.onion.send_data(TUNNEL_ID, TEST_DATA);
match time::timeout(ERROR_TIMEOUT, peer2.events.next()).await {
Ok(e) => panic!("Got unexpected event: {:?}", e),
Err(_) => {}
}
}

#[tokio::test]
async fn test_data_error_disconnected_source() {
let mut peer1 = spawn_peer(vec![]).await;
let mut peer2 = spawn_peer(vec![]).await;

peer1.onion.build_tunnel(TUNNEL_ID, peer2.peer, 0);
match time::timeout(ROUND_TIMEOUT, peer1.events.next()).await {
Ok(Some(Event::Ready { tunnel_id })) => assert_eq!(tunnel_id, TUNNEL_ID),
Ok(e) => panic!("Expected ready event, got {:?}", e),
Err(_) => panic!("Expected ready event, got timeout"),
}

match time::timeout(ERROR_TIMEOUT, peer2.events.next()).await {
Ok(Some(Event::Incoming { tunnel_id })) => assert_eq!(tunnel_id, TUNNEL_ID),
Ok(e) => panic!("Expected incoming event, got {:?}", e),
Err(_) => panic!("Expected incoming event, got timeout"),
}

peer1.onion.destroy_tunnel(TUNNEL_ID);
time::delay_for(DELAY_TIMEOUT).await;
peer1.onion.send_data(TUNNEL_ID, TEST_DATA);
match time::timeout(ERROR_TIMEOUT, peer2.events.next()).await {
Ok(e) => panic!("Got unexpected event: {:?}", e),
Err(_) => {}
}
}

0 comments on commit 402a339

Please sign in to comment.