Skip to content
This repository has been archived by the owner on Jun 25, 2021. It is now read-only.

Commit

Permalink
test/tunnel: tunnel client reconnects
Browse files Browse the repository at this point in the history
  • Loading branch information
maqi committed Feb 28, 2017
1 parent bf703e7 commit 5932152
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 57 deletions.
6 changes: 6 additions & 0 deletions src/mock_crust/support.rs
Expand Up @@ -109,6 +109,12 @@ impl Network {
imp.blocked_connections.insert((sender, receiver));
}

/// Make all packets from `sender` to `receiver` succeed.
pub fn unblock_connection(&self, sender: Endpoint, receiver: Endpoint) {
let mut imp = self.0.borrow_mut();
let _ = imp.blocked_connections.remove(&(sender, receiver));
}

/// Construct a new [`XorShiftRng`](https://doc.rust-lang.org/rand/rand/struct.XorShiftRng.html)
/// using a seed generated from random data provided by `self`.
pub fn new_rng(&self) -> XorShiftRng {
Expand Down
47 changes: 5 additions & 42 deletions tests/mock_crust/mod.rs
Expand Up @@ -21,14 +21,16 @@ mod churn;
mod drop;
mod merge;
mod requests;
mod tunnel;
mod utils;

use routing::{Event, EventStream, Prefix, XOR_NAME_LEN, XorName};
use routing::mock_crust::{Config, Endpoint, Network};
use routing::mock_crust::crust::PeerId;
pub use self::utils::{Nodes, TestClient, TestNode, create_connected_clients,
create_connected_nodes, create_connected_nodes_until_split, gen_bytes,
gen_immutable_data, gen_range_except, poll_all, poll_and_resend,
pub use self::utils::{Nodes, TestClient, TestNode, add_connected_nodes_until_split,
create_connected_clients, create_connected_nodes,
create_connected_nodes_until_split, gen_bytes, gen_immutable_data,
gen_range_except, poll_all, poll_and_resend,
remove_nodes_which_failed_to_connect, sort_nodes_by_distance_to,
verify_invariant_for_all_nodes};

Expand Down Expand Up @@ -71,45 +73,6 @@ fn more_than_section_size_nodes() {
test_nodes(600);
}

#[test]
fn failing_connections_ring() {
let min_section_size = 8;
let network = Network::new(min_section_size, None);
let len = min_section_size * 2;
for i in 0..(len - 1) {
let ep0 = Endpoint(1 + i);
let ep1 = Endpoint(1 + (i % len));

network.block_connection(ep0, ep1);
network.block_connection(ep1, ep0);
}
let nodes = create_connected_nodes(&network, len);
verify_invariant_for_all_nodes(&nodes);
}

#[test]
fn failing_connections_bidirectional() {
let min_section_size = 4;
let network = Network::new(min_section_size, None);
network.block_connection(Endpoint(2), Endpoint(3));
network.block_connection(Endpoint(3), Endpoint(2));

let nodes = create_connected_nodes(&network, min_section_size);
verify_invariant_for_all_nodes(&nodes);
}

#[test]
fn failing_connections_unidirectional() {
let min_section_size = 8;
let network = Network::new(min_section_size, None);
network.block_connection(Endpoint(1), Endpoint(6));
network.block_connection(Endpoint(1), Endpoint(7));
network.block_connection(Endpoint(6), Endpoint(7));

let nodes = create_connected_nodes(&network, min_section_size);
verify_invariant_for_all_nodes(&nodes);
}

#[test]
fn client_connects_to_nodes() {
let min_section_size = 8;
Expand Down
149 changes: 149 additions & 0 deletions tests/mock_crust/tunnel.rs
@@ -0,0 +1,149 @@
// Copyright 2017 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which
// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement, version 1.1. This, along with the
// Licenses can be found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.
//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

use itertools::Itertools;
use routing::{XOR_NAME_LEN, XorName};
use routing::mock_crust::{Config, Endpoint, Network};
use super::{TestNode, add_connected_nodes_until_split, create_connected_nodes, poll_all,
poll_and_resend, verify_invariant_for_all_nodes};

#[test]
fn failing_connections_ring() {
let min_section_size = 8;
let network = Network::new(min_section_size, None);
let len = min_section_size * 2;
for i in 0..(len - 1) {
let ep0 = Endpoint(1 + i);
let ep1 = Endpoint(1 + (i % len));

network.block_connection(ep0, ep1);
network.block_connection(ep1, ep0);
}
let nodes = create_connected_nodes(&network, len);
verify_invariant_for_all_nodes(&nodes);
}

#[test]
fn failing_connections_bidirectional() {
let min_section_size = 4;
let network = Network::new(min_section_size, None);
network.block_connection(Endpoint(2), Endpoint(3));
network.block_connection(Endpoint(3), Endpoint(2));

let nodes = create_connected_nodes(&network, min_section_size);
verify_invariant_for_all_nodes(&nodes);
}

#[test]
fn failing_connections_unidirectional() {
let min_section_size = 8;
let network = Network::new(min_section_size, None);
network.block_connection(Endpoint(1), Endpoint(6));
network.block_connection(Endpoint(1), Endpoint(7));
network.block_connection(Endpoint(6), Endpoint(7));

let nodes = create_connected_nodes(&network, min_section_size);
verify_invariant_for_all_nodes(&nodes);
}

// Removes nodes from the specified section so that this section will merge with another section.
fn remove_nodes_from_section_till_merge(prefix_name: &XorName,
nodes: &mut Vec<TestNode>,
min_section_size: usize) {
let section_indexes: Vec<usize> = nodes.iter()
.enumerate()
.rev()
.filter_map(|(index, node)| if node.routing_table().our_prefix().matches(prefix_name) {
Some(index)
} else {
None
})
.collect();
section_indexes.iter()
.take(section_indexes.len() - min_section_size + 1)
.foreach(|index| { let _ = nodes.remove(*index); });
poll_and_resend(nodes, &mut []);
}

// Adds a pair of nodes with specified names into the network. Also blocks direct connection between
// these them if `is_tunnel` is true. Returns the endpoints of the nodes.
fn add_a_pair(network: &Network,
nodes: &mut Vec<TestNode>,
name0: XorName,
name1: XorName,
is_tunnel: bool)
-> (Endpoint, Endpoint) {
let config = Config::with_contacts(&[nodes[0].handle.endpoint()]);

for node in &mut *nodes {
node.inner.set_next_node_name(name0);
}
nodes.push(TestNode::builder(network).config(config.clone()).create());
poll_and_resend(nodes, &mut []);

for node in &mut *nodes {
node.inner.set_next_node_name(name1);
}
nodes.push(TestNode::builder(network).config(config.clone()).create());

let endpoints = (Endpoint(nodes.len() - 2), Endpoint(nodes.len() - 1));
if is_tunnel {
network.block_connection(endpoints.0, endpoints.1);
network.block_connection(endpoints.1, endpoints.0);
}

poll_and_resend(nodes, &mut []);
endpoints
}

#[test]
fn tunnel_clients() {
let min_section_size = 3;
let network = Network::new(min_section_size, None);
let mut nodes = create_connected_nodes(&network, min_section_size);

let direct_pair = add_a_pair(&network,
&mut nodes,
XorName([0u8; XOR_NAME_LEN]),
XorName([253u8; XOR_NAME_LEN]),
false);
let _ = poll_all(&mut nodes, &mut []);
let _ = add_a_pair(&network,
&mut nodes,
XorName([1u8; XOR_NAME_LEN]),
XorName([255u8; XOR_NAME_LEN]),
true);
let tunnel_pair = add_a_pair(&network,
&mut nodes,
XorName([2u8; XOR_NAME_LEN]),
XorName([254u8; XOR_NAME_LEN]),
true);
verify_invariant_for_all_nodes(&nodes);

add_connected_nodes_until_split(&network, &mut nodes, vec![2, 2, 2, 2], false);
verify_invariant_for_all_nodes(&nodes);

network.unblock_connection(tunnel_pair.0, tunnel_pair.1);
network.unblock_connection(tunnel_pair.1, tunnel_pair.0);
network.block_connection(direct_pair.0, direct_pair.1);
network.block_connection(direct_pair.1, direct_pair.0);

remove_nodes_from_section_till_merge(&XorName([64u8; XOR_NAME_LEN]),
&mut nodes,
min_section_size);
verify_invariant_for_all_nodes(&nodes);
}
41 changes: 26 additions & 15 deletions tests/mock_crust/utils.rs
Expand Up @@ -368,7 +368,19 @@ pub fn create_connected_nodes_with_cache(network: &Network, size: usize, use_cac
Nodes(nodes)
}

// This creates new nodes (all with `use_cache` set to `true`) until the specified disjoint sections
pub fn create_connected_nodes_until_split(network: &Network,
prefix_lengths: Vec<usize>,
use_cache: bool)
-> Nodes {
// Start first node.
let mut nodes =
vec![TestNode::builder(network).first().endpoint(Endpoint(0)).cache(use_cache).create()];
nodes[0].poll();
add_connected_nodes_until_split(network, &mut nodes, prefix_lengths, use_cache);
Nodes(nodes)
}

// This adds new nodes (all with `use_cache` set to `true`) until the specified disjoint sections
// have formed.
//
// `prefix_lengths` is an array representing the required `bit_count`s of the section prefixes. For
Expand All @@ -378,26 +390,26 @@ pub fn create_connected_nodes_with_cache(network: &Network, size: usize, use_cac
//
// The array is sanity checked (e.g. it would be an error to pass [1, 1, 1]), must comprise at
// least two elements, and every element must be no more than `8`.
pub fn create_connected_nodes_until_split(network: &Network,
mut prefix_lengths: Vec<usize>,
use_cache: bool)
-> Nodes {
pub fn add_connected_nodes_until_split(network: &Network,
nodes: &mut Vec<TestNode>,
mut prefix_lengths: Vec<usize>,
use_cache: bool) {
// Get sorted list of prefixes to suit requested lengths.
sanity_check(&prefix_lengths);
prefix_lengths.sort();
let mut rng = network.new_rng();
let prefixes = prefixes(&prefix_lengths, &mut rng);

// Start first node.
let mut nodes =
vec![TestNode::builder(network).first().endpoint(Endpoint(0)).cache(use_cache).create()];
nodes[0].poll();
// Cleanup the previous event queue
for node in nodes.iter_mut() {
while let Ok(_) = node.try_next_ev() {}
}

// Start enough new nodes under each target prefix to trigger a split eventually.
let min_split_size = nodes[0].routing_table().min_split_size();
for prefix in &prefixes {
for _ in 0..min_split_size {
add_node_to_section(network, &mut nodes, prefix, &mut rng, use_cache);
add_node_to_section(network, nodes, prefix, &mut rng, use_cache);
if nodes.len() == 2 {
expect_next_event!(nodes[0], Event::Connected);
}
Expand All @@ -409,7 +421,7 @@ pub fn create_connected_nodes_until_split(network: &Network,
// Find and add nodes to sections which still need to split to trigger this.
loop {
let mut found_prefix = None;
for node in &nodes {
for node in nodes.iter() {
if let Some(prefix_to_split) =
unwrap!(node.inner.routing_table())
.prefixes()
Expand All @@ -429,15 +441,15 @@ pub fn create_connected_nodes_until_split(network: &Network,
}
}
if let Some(prefix_to_split) = found_prefix {
add_node_to_section(network, &mut nodes, &prefix_to_split, &mut rng, use_cache);
add_node_to_section(network, nodes, &prefix_to_split, &mut rng, use_cache);
} else {
break;
}
}

// Gather all the actual prefixes and check they are as expected.
let mut actual_prefixes = BTreeSet::<Prefix<XorName>>::new();
for node in &nodes {
for node in nodes.iter() {
actual_prefixes.append(&mut unwrap!(node.inner.routing_table()).prefixes());
}
assert_eq!(prefixes.iter().cloned().collect::<BTreeSet<_>>(),
Expand All @@ -446,7 +458,7 @@ pub fn create_connected_nodes_until_split(network: &Network,
prefixes.iter().map(|prefix| prefix.bit_count()).collect_vec());

// Clear all event queues and clear the `next_node_name` values.
for node in &mut nodes {
for node in nodes.iter_mut() {
while let Ok(event) = node.try_next_ev() {
match event {
Event::NodeAdded(..) |
Expand All @@ -460,7 +472,6 @@ pub fn create_connected_nodes_until_split(network: &Network,
}

trace!("Created testnet comprising {:?}", prefixes);
Nodes(nodes)
}

// Create `size` clients, all of whom are connected to `nodes[0]`.
Expand Down

0 comments on commit 5932152

Please sign in to comment.