hbbft/tests/subset.rs

123 lines
3.6 KiB
Rust
Raw Normal View History

#![deny(unused_must_use)]
//! Integration tests of the Subset protocol.
2018-05-15 04:49:39 -07:00
extern crate env_logger;
2018-05-15 04:49:39 -07:00
extern crate hbbft;
#[macro_use]
extern crate log;
extern crate pairing;
extern crate rand;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate rand_derive;
extern crate threshold_crypto as crypto;
2018-05-15 04:49:39 -07:00
mod network;
2018-05-15 04:49:39 -07:00
use std::collections::{BTreeMap, BTreeSet};
use std::iter::once;
use std::sync::Arc;
2018-05-15 04:49:39 -07:00
use hbbft::messaging::NetworkInfo;
2018-08-14 06:06:51 -07:00
use hbbft::subset::Subset;
2018-05-15 04:49:39 -07:00
2018-08-29 09:08:35 -07:00
use network::{Adversary, MessageScheduler, NodeId, SilentAdversary, TestNetwork, TestNode};
2018-05-15 04:49:39 -07:00
type ProposedValue = Vec<u8>;
2018-05-15 04:49:39 -07:00
2018-08-29 09:08:35 -07:00
fn test_subset<A: Adversary<Subset<NodeId>>>(
mut network: TestNetwork<A, Subset<NodeId>>,
inputs: &BTreeMap<NodeId, ProposedValue>,
) {
2018-08-29 09:08:35 -07:00
let ids: Vec<NodeId> = network.nodes.keys().cloned().collect();
2018-05-15 04:49:39 -07:00
for id in ids {
if let Some(value) = inputs.get(&id) {
network.input(id, value.to_owned());
2018-05-15 04:49:39 -07:00
}
}
// Terminate when all good nodes do.
while !network.nodes.values().all(TestNode::terminated) {
network.step();
}
// Verify that all instances output the same set.
let mut expected = None;
for node in network.nodes.values() {
if let Some(output) = expected.as_ref() {
assert!(once(output).eq(node.outputs()));
continue;
2018-05-15 04:49:39 -07:00
}
assert_eq!(1, node.outputs().len());
expected = Some(node.outputs()[0].clone());
}
let output = expected.unwrap();
assert!(once(&output).eq(network.observer.outputs()));
2018-08-14 06:06:51 -07:00
// The Subset algorithm guarantees that more than two thirds of the proposed elements
2018-05-19 08:10:30 -07:00
// are in the set.
assert!(output.len() * 3 > inputs.len() * 2);
2018-05-19 08:10:30 -07:00
// Verify that the set's elements match the proposed values.
for (id, value) in output {
assert_eq!(inputs[&id], value);
2018-05-15 04:49:39 -07:00
}
}
fn new_network<A, F>(
good_num: usize,
bad_num: usize,
adversary: F,
2018-08-29 09:08:35 -07:00
) -> TestNetwork<A, Subset<NodeId>>
where
2018-08-29 09:08:35 -07:00
A: Adversary<Subset<NodeId>>,
F: Fn(BTreeMap<NodeId, Arc<NetworkInfo<NodeId>>>) -> A,
{
// This returns an error in all but the first test.
2018-05-15 04:49:39 -07:00
let _ = env_logger::try_init();
2018-08-14 06:06:51 -07:00
let new_subset =
2018-08-29 09:08:35 -07:00
|netinfo: Arc<NetworkInfo<NodeId>>| Subset::new(netinfo, 0).expect("new Subset instance");
2018-08-14 06:06:51 -07:00
TestNetwork::new(good_num, bad_num, adversary, new_subset)
2018-05-15 04:49:39 -07:00
}
#[test]
2018-08-14 06:06:51 -07:00
fn test_subset_3_out_of_4_nodes_propose() {
2018-05-15 04:49:39 -07:00
let proposed_value = Vec::from("Fake news");
2018-08-29 09:08:35 -07:00
let proposing_ids: BTreeSet<NodeId> = (0..3).map(NodeId).collect();
let proposals: BTreeMap<NodeId, ProposedValue> = proposing_ids
.iter()
2018-05-15 14:25:41 -07:00
.map(|id| (*id, proposed_value.clone()))
.collect();
let adversary = |_| SilentAdversary::new(MessageScheduler::First);
let network = new_network(3, 1, adversary);
2018-08-14 06:06:51 -07:00
test_subset(network, &proposals);
2018-05-15 04:49:39 -07:00
}
#[test]
2018-08-14 06:06:51 -07:00
fn test_subset_5_nodes_different_proposed_values() {
let proposed_values = vec![
Vec::from("Alpha"),
Vec::from("Bravo"),
Vec::from("Charlie"),
Vec::from("Delta"),
Vec::from("Echo"),
];
2018-08-29 09:08:35 -07:00
let proposals: BTreeMap<NodeId, ProposedValue> = (0..5)
.into_iter()
2018-08-29 09:08:35 -07:00
.map(NodeId)
.zip(proposed_values)
.collect();
let adversary = |_| SilentAdversary::new(MessageScheduler::Random);
let network = new_network(5, 0, adversary);
2018-08-14 06:06:51 -07:00
test_subset(network, &proposals);
}
2018-07-09 02:36:30 -07:00
#[test]
2018-08-14 06:06:51 -07:00
fn test_subset_1_node() {
2018-08-29 09:08:35 -07:00
let proposals: BTreeMap<NodeId, ProposedValue> =
once((NodeId(0), Vec::from("Node 0 is the greatest!"))).collect();
2018-07-09 02:36:30 -07:00
let adversary = |_| SilentAdversary::new(MessageScheduler::Random);
let network = new_network(1, 0, adversary);
2018-08-14 06:06:51 -07:00
test_subset(network, &proposals);
2018-07-09 02:36:30 -07:00
}