Skip to content

Commit

Permalink
Extract test framework into hbbft_testing crate. (#404)
Browse files Browse the repository at this point in the history
* Extract test framework into hbbft_testing crate.

Also update Rust and some dependencies.

* Rename DHB tests.

They are only called `net_dynamic_hb` because we used to have two test
frameworks and two DHB test modules.
  • Loading branch information
afck authored and vkomenda committed Apr 26, 2019
1 parent a64f625 commit 15f7313
Show file tree
Hide file tree
Showing 21 changed files with 138 additions and 132 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
language: rust
rust:
- 1.33.0
- 1.34.0
cache:
cargo: true
timeout: 1200
Expand Down
9 changes: 4 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,13 @@ tiny-keccak = "1.4"

[dev-dependencies]
colored = "1.7"
crossbeam = "0.6"
crossbeam = "0.7.1"
crossbeam-channel = "0.3"
docopt = "1.0"
hbbft_testing = { path = "hbbft_testing" }
itertools = "0.8.0"
rand_xorshift = "0.1.1"
signifix = "0.9"
proptest = "0.8.7"
integer-sqrt = "0.1.2"
signifix = "0.10.0"
proptest = "0.9.2"

[[example]]
name = "consensus-node"
Expand Down
7 changes: 7 additions & 0 deletions ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,10 @@ cargo test --features=use-insecure-test-only-mock-crypto --release
cargo doc
cargo deadlinks --dir target/doc/hbbft/
cargo audit

cd hbbft_testing
cargo clippy --all-targets -- --deny clippy::all
cargo fmt -- --check
cargo test --release
cargo audit
cd ..
3 changes: 2 additions & 1 deletion examples/simulation.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::collections::{BTreeMap, VecDeque};
use std::convert::TryFrom;
use std::time::{Duration, Instant};
use std::{cmp, u64};

Expand All @@ -8,7 +9,7 @@ use itertools::Itertools;
use rand::{distributions::Standard, rngs::OsRng, seq::SliceRandom, Rng};
use rand_derive::Rand;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use signifix::{metric, TryFrom};
use signifix::metric;

use hbbft::dynamic_honey_badger::DynamicHoneyBadger;
use hbbft::queueing_honey_badger::{Batch, QueueingHoneyBadger};
Expand Down
31 changes: 31 additions & 0 deletions hbbft_testing/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[package]
name = "hbbft_testing"
version = "0.1.0"
authors = [
"Vladimir Komendantskiy <[email protected]>",
"Andreas Fackler <[email protected]>",
"Peter van Nostrand <[email protected]>",
"Andrew Gross <[email protected]>",
"Nick Sanders <[email protected]>",
"Marc Brinkmann <[email protected]>",
"David Forstenlechner <[email protected]>",
]
categories = ["algorithms", "asynchronous", "cryptography", "network-programming"]
keywords = ["consensus", "asynchronous", "threshold"]
license = "MIT/Apache-2.0"
readme = "README.md"
repository = "https://github.com/poanetwork/hbbft"
description = "Utilities for simulating and testing hbbft-based networks."
edition = "2018"

[badges]
travis-ci = { repository = "poanetwork/hbbft" }

[dependencies]
failure = "0.1.5"
hbbft = { path = ".." }
integer-sqrt = "0.1.2"
proptest = "0.9.2"
rand = "0.6.5"
rand_xorshift = "0.1.1"
threshold_crypto = "0.3.1"
4 changes: 2 additions & 2 deletions tests/net/adversary.rs → hbbft_testing/src/adversary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ use rand::Rng;

use hbbft::{ConsensusProtocol, CpStep};

use crate::net::util::randomly;
use crate::net::{CrankError, NetMessage, NetworkMessage, Node, VirtualNet};
use crate::util::randomly;
use crate::{CrankError, NetMessage, NetworkMessage, Node, VirtualNet};

/// Immutable network handle.
///
Expand Down
File renamed without changes.
10 changes: 5 additions & 5 deletions tests/net/mod.rs → hbbft_testing/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ pub mod err;
pub mod proptest;
pub mod util;

#[cfg(test)]
mod util_tests;

use std::collections::{BTreeMap, BTreeSet, VecDeque};
use std::io::Write;
use std::{cmp, env, fmt, fs, io, ops, process, time};
Expand All @@ -29,8 +32,6 @@ use hbbft::dynamic_honey_badger::Batch;
use hbbft::sender_queue::SenderQueueableOutput;
use hbbft::{self, ConsensusProtocol, Contribution, CpStep, Fault, NetworkInfo, NodeIdT, Step};

use crate::try_some;

pub use self::adversary::Adversary;
pub use self::err::CrankError;

Expand Down Expand Up @@ -534,7 +535,7 @@ where

// If the trace setting is not overriden, we use the setting from the environment.
let trace = self.trace.unwrap_or_else(|| {
match env::var("HBBFT_TEST_TRACE").as_ref().map(|s| s.as_str()) {
match env::var("HBBFT_TEST_TRACE").as_ref().map(String::as_str) {
Ok("true") | Ok("1") => true,
_ => false,
}
Expand Down Expand Up @@ -1070,8 +1071,7 @@ where
}
for node in self.correct_nodes().filter(|n| n.id() != full_node.id()) {
let id = node.id();
let actual_epochs: BTreeSet<_> =
node.outputs.iter().map(|batch| batch.epoch()).collect();
let actual_epochs: BTreeSet<_> = node.outputs.iter().map(Batch::epoch).collect();
let expected_epochs: BTreeSet<_> =
expected[id].iter().map(|batch| batch.epoch()).collect();
assert_eq!(
Expand Down
File renamed without changes.
File renamed without changes.
6 changes: 2 additions & 4 deletions tests/net_util.rs → hbbft_testing/src/util_tests.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
pub mod net;

use proptest::arbitrary::any;
use proptest::proptest;
use proptest::strategy::{Strategy, ValueTree};
use proptest::{proptest, proptest_helper};
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;

use crate::net::proptest::{max_sum, NetworkDimension, NetworkDimensionTree};
use crate::proptest::{max_sum, NetworkDimension, NetworkDimensionTree};

proptest! {
/// Ensures all generated network dimensions are actually sane.
Expand Down
4 changes: 3 additions & 1 deletion src/dynamic_honey_badger/dynamic_honey_badger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,9 @@ where
let kgs = match self.key_gen_state {
Some(ref mut kgs) => kgs,
None => {
return Ok(Fault::new(sender_id.clone(), FaultKind::UnexpectedKeyGenMessage).into());
return Ok(
Fault::new(sender_id.clone(), FaultKind::UnexpectedKeyGenMessage).into(),
);
}
};

Expand Down
71 changes: 35 additions & 36 deletions tests/binary_agreement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,18 @@
//! - Validity: If any correct node outputs `b`, then at least one correct node received `b` as
//! input.
pub mod net;

use std::iter::once;
use std::sync::Arc;
use std::time;

use proptest::arbitrary::any;
use proptest::{prelude::ProptestConfig, prop_compose, proptest, proptest_helper};
use rand::{Rng, SeedableRng};

use hbbft::binary_agreement::BinaryAgreement;
use hbbft::ConsensusProtocol;

use crate::net::adversary::{Adversary, ReorderingAdversary};
use crate::net::proptest::{gen_seed, NetworkDimension, TestRng, TestRngSeed};
use crate::net::{NetBuilder, NewNodeInfo, VirtualNet};
use hbbft_testing::adversary::{Adversary, ReorderingAdversary};
use hbbft_testing::proptest::{gen_seed, NetworkDimension, TestRng, TestRngSeed};
use hbbft_testing::{NetBuilder, NewNodeInfo, VirtualNet};
use proptest::arbitrary::any;
use proptest::{prelude::ProptestConfig, prop_compose, proptest};
use rand::{Rng, SeedableRng};

/// Test configuration for Binary Agreement tests.
#[derive(Debug)]
Expand Down Expand Up @@ -72,36 +68,35 @@ proptest! {

type NodeId = u16;

impl<A> VirtualNet<BinaryAgreement<NodeId, u8>, A>
where
fn test_binary_agreement<A, R>(
net: &mut VirtualNet<BinaryAgreement<NodeId, u8>, A>,
input: Option<bool>,
mut rng: R,
) where
R: Rng + 'static,
A: Adversary<BinaryAgreement<NodeId, u8>>,
{
fn test_binary_agreement<R>(&mut self, input: Option<bool>, mut rng: R)
where
R: Rng + 'static,
{
let ids: Vec<NodeId> = self.nodes().map(|n| *n.id()).collect();
for id in ids {
let _ = self.send_input(id, input.unwrap_or_else(|| rng.gen::<bool>()), &mut rng);
}
let ids: Vec<NodeId> = net.nodes().map(|n| *n.id()).collect();
for id in ids {
let _ = net.send_input(id, input.unwrap_or_else(|| rng.gen::<bool>()), &mut rng);
}

// Handle messages in random order until all nodes have output the proposed value.
while !self.nodes().all(|node| node.algorithm().terminated()) {
let _ = self.crank_expect(&mut rng);
}
// Verify that all instances output the same value.
let mut expected = input;
for node in self.nodes() {
if let Some(b) = expected {
assert!(once(&b).eq(node.outputs()));
} else {
assert_eq!(1, node.outputs().len());
expected = Some(node.outputs()[0]);
}
// Handle messages in random order until all nodes have output the proposed value.
while !net.nodes().all(|node| node.algorithm().terminated()) {
let _ = net.crank_expect(&mut rng);
}
// Verify that all instances output the same value.
let mut expected = input;
for node in net.nodes() {
if let Some(b) = expected {
assert!(once(&b).eq(node.outputs()));
} else {
assert_eq!(1, node.outputs().len());
expected = Some(node.outputs()[0]);
}
// TODO: As soon as observers are added to the test framework, compare the expected output
// against the output of observers.
}
// TODO: As soon as observers are added to the test framework, compare the expected output
// against the output of observers.
}

/// Tests Binary Agreement on a given configuration.
Expand All @@ -127,7 +122,11 @@ fn binary_agreement(cfg: TestConfig) {
})
.build(&mut rng)
.expect("Could not construct test network.");
net.test_binary_agreement(cfg.input, TestRng::from_seed(rng.gen::<TestRngSeed>()));
test_binary_agreement(
&mut net,
cfg.input,
TestRng::from_seed(rng.gen::<TestRngSeed>()),
);
println!(
"Test success: {} good nodes and {} faulty nodes, input: {:?}",
num_good_nodes, num_faulty_nodes, cfg.input
Expand Down
13 changes: 5 additions & 8 deletions tests/binary_agreement_mitm.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
#![deny(unused_must_use)]
//! Tests the BinaryAgreement protocol with a MTIM adversary.
pub mod net;

use std::iter;
use std::sync::{Arc, Mutex};

use hbbft::binary_agreement::{BinaryAgreement, MessageContent, SbvMessage};
use hbbft::threshold_sign::ThresholdSign;
use hbbft::{ConsensusProtocol, CpStep, NetworkInfo};
use proptest::{proptest, proptest_helper};
use hbbft_testing::adversary::{NetMutHandle, QueuePosition};
use hbbft_testing::err::CrankError;
use hbbft_testing::proptest::{gen_seed, TestRng, TestRngSeed};
use hbbft_testing::{Adversary, NetBuilder, NetMessage};
use proptest::proptest;
use rand::{Rng, SeedableRng};

use crate::net::adversary::{NetMutHandle, QueuePosition};
use crate::net::err::CrankError;
use crate::net::proptest::{gen_seed, TestRng, TestRngSeed};
use crate::net::{Adversary, NetBuilder, NetMessage};

type NodeId = usize;
type SessionId = u8;
type Algo = BinaryAgreement<NodeId, SessionId>;
Expand Down
16 changes: 6 additions & 10 deletions tests/broadcast.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
pub mod net;

use std::collections::BTreeMap;
use std::iter::once;
use std::sync::{Arc, Mutex};

use log::info;
use proptest::{prelude::ProptestConfig, proptest, proptest_helper};
use rand::{Rng, SeedableRng};

use hbbft::{broadcast::Broadcast, util, ConsensusProtocol, CpStep, NetworkInfo};

use crate::net::adversary::{
use hbbft_testing::adversary::{
sort_ascending, swap_random, Adversary, NetMutHandle, NodeOrderAdversary, RandomAdversary,
ReorderingAdversary,
};
use crate::net::proptest::{gen_seed, TestRng, TestRngSeed};
use crate::net::{CrankError, NetBuilder, NetMessage, NewNodeInfo, VirtualNet};
use hbbft_testing::proptest::{gen_seed, TestRng, TestRngSeed};
use hbbft_testing::{CrankError, NetBuilder, NetMessage, NewNodeInfo, VirtualNet};
use log::info;
use proptest::{prelude::ProptestConfig, proptest};
use rand::{Rng, SeedableRng};

type NodeId = u16;
type NetworkInfoMap = BTreeMap<NodeId, Arc<NetworkInfo<NodeId>>>;
Expand Down
24 changes: 11 additions & 13 deletions tests/net_dynamic_hb.rs → tests/dynamic_honey_badger.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
pub mod net;

use std::collections::{BTreeMap, BTreeSet};
use std::time;

use hbbft::dynamic_honey_badger::{Change, ChangeState, DynamicHoneyBadger, Input, JoinPlan};
use hbbft::dynamic_honey_badger::{
Batch, Change, ChangeState, DynamicHoneyBadger, Input, JoinPlan,
};
use hbbft::sender_queue::{SenderQueue, Step};
use hbbft::Epoched;
use proptest::{prelude::ProptestConfig, prop_compose, proptest, proptest_helper};
use hbbft::{util, Epoched};
use hbbft_testing::adversary::{Adversary, ReorderingAdversary};
use hbbft_testing::proptest::{gen_seed, NetworkDimension, TestRng, TestRngSeed};
use hbbft_testing::{NetBuilder, NewNodeInfo, Node, VirtualNet};
use proptest::{prelude::ProptestConfig, prop_compose, proptest};
use rand::{seq::SliceRandom, SeedableRng};

use crate::net::adversary::{Adversary, ReorderingAdversary};
use crate::net::proptest::{gen_seed, NetworkDimension, TestRng, TestRngSeed};
use crate::net::{NetBuilder, NewNodeInfo, Node, VirtualNet};
use hbbft::util;
use threshold_crypto::PublicKey;

type DHB = SenderQueue<DynamicHoneyBadger<Vec<usize>, usize>>;
Expand Down Expand Up @@ -218,7 +216,7 @@ fn do_drop_and_re_add(cfg: TestConfig) {
);
}
}
for change in step.output.iter().map(|output| output.change()) {
for change in step.output.iter().map(Batch::change) {
match change {
ChangeState::Complete(Change::NodeChange(ref pub_keys))
if *pub_keys == new_pub_keys =>
Expand Down Expand Up @@ -389,7 +387,7 @@ fn do_drop_and_re_add(cfg: TestConfig) {
}

// Check if we are done.
if expected_outputs.values().all(|s| s.is_empty())
if expected_outputs.values().all(BTreeSet::is_empty)
&& awaiting_apply_old_subset.is_empty()
&& awaiting_apply_new_subset.is_empty()
{
Expand Down Expand Up @@ -443,7 +441,7 @@ where
// TODO: When an observer node is added to the network, it should also be added to peer_ids.
let peer_ids: Vec<_> = net
.nodes()
.map(|node| node.id())
.map(Node::id)
.filter(|id| *id != node.id())
.cloned()
.collect();
Expand Down
Loading

0 comments on commit 15f7313

Please sign in to comment.