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

MAID-1957 test/tunnel: tunnel client reconnect #1355

Merged
merged 1 commit into from Feb 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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); });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'd best sort the indices from highest to lowest if you want to remove them from the Vec like this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it was taken in a reversed order, https://github.com/maidsafe/routing/pull/1355/files#diff-b83639c52df93eae4d3e66ec59a8e66fR69
so I think we are ok here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess so. I don't much like this style of coding because it's easy to accidentally break it, but I guess it'll do.

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