handling of input via proptest and doc correction

This commit is contained in:
Vladimir Komendantskiy 2018-11-13 11:50:37 +00:00
parent cb997737c9
commit 9c207e734a
1 changed files with 36 additions and 33 deletions

View File

@ -1,10 +1,8 @@
#![deny(unused_must_use)] #![deny(unused_must_use)]
//! Tests of the Binary Agreement protocol //! Tests of the Binary Agreement protocol
//! //!
//! Each of the nodes in the simulated network runs only one instance of Binary Agreement for node //! Each of the nodes in the simulated network runs one instance of Binary Agreement. This suffices
//! `0`, the proposer. In real applications there would be multiple proposers in the //! to test correctness of the protocol.
//! network. However, having only one proposer allows to test correctness of the protocol rather
//! than message dispatch between multiple proposers.
//! //!
//! There are three properties that are tested: //! There are three properties that are tested:
//! //!
@ -28,6 +26,7 @@ use std::iter::once;
use std::sync::Arc; use std::sync::Arc;
use std::time; use std::time;
use proptest::arbitrary::any;
use proptest::{prelude::ProptestConfig, prop_compose, proptest, proptest_helper}; use proptest::{prelude::ProptestConfig, prop_compose, proptest, proptest_helper};
use rand::{Rng, SeedableRng}; use rand::{Rng, SeedableRng};
@ -45,6 +44,12 @@ struct TestConfig {
dimension: NetworkDimension, dimension: NetworkDimension,
/// Random number generator to be passed to subsystems. /// Random number generator to be passed to subsystems.
seed: TestRngSeed, seed: TestRngSeed,
/// Input to Binary Agreement instances that has the following meaning:
///
/// - `Some(b)`: all instances receive `b` as input.
///
/// - `None`: each instance receives a random `bool` as input.
input: Option<bool>,
} }
prop_compose! { prop_compose! {
@ -52,21 +57,22 @@ prop_compose! {
fn arb_config() fn arb_config()
( (
dimension in NetworkDimension::range(1, 50), dimension in NetworkDimension::range(1, 50),
seed in gen_seed() seed in gen_seed(),
input in any::<Option<bool>>(),
) -> TestConfig ) -> TestConfig
{ {
TestConfig { dimension, seed } TestConfig { dimension, seed, input }
} }
} }
/// Proptest wrapper for `binary_agreement`. /// Proptest wrapper for `binary_agreement` that runs the test function on generated configurations.
proptest!{ proptest!{
#![proptest_config(ProptestConfig { #![proptest_config(ProptestConfig {
cases: 1, .. ProptestConfig::default() cases: 1, .. ProptestConfig::default()
})] })]
#[test] #[test]
#[cfg_attr(feature = "cargo-clippy", allow(unnecessary_operation))] #[cfg_attr(feature = "cargo-clippy", allow(unnecessary_operation))]
fn binary_agreement_wrapper(cfg in arb_config()) { fn run_binary_agreement(cfg in arb_config()) {
binary_agreement(cfg) binary_agreement(cfg)
} }
} }
@ -103,35 +109,32 @@ impl VirtualNet<Algo> {
} }
} }
/// Tests Binary Agreement on a given configuration with random inputs, with all `false` inputs and /// Tests Binary Agreement on a given configuration.
/// with all `true` inputs.
#[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))] #[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]
fn binary_agreement(cfg: TestConfig) { fn binary_agreement(cfg: TestConfig) {
let mut rng: TestRng = TestRng::from_seed(cfg.seed); let mut rng: TestRng = TestRng::from_seed(cfg.seed);
let size = cfg.dimension.size(); let size = cfg.dimension.size();
let num_faulty_nodes = cfg.dimension.faulty(); let num_faulty_nodes = cfg.dimension.faulty();
let num_good_nodes = size - num_faulty_nodes; let num_good_nodes = size - num_faulty_nodes;
for &input in &[None, Some(false), Some(true)] { println!(
println!( "Test start: {} good nodes and {} faulty nodes, input: {:?}",
"Test start: {} good nodes and {} faulty nodes, input: {:?}", num_good_nodes, num_faulty_nodes, cfg.input
num_good_nodes, num_faulty_nodes, input );
); // Create a network with `size` validators and one observer.
// Create a network with `size` validators and one observer. let mut net: VirtualNet<Algo> = NetBuilder::new(0..size as u16)
let mut net: VirtualNet<Algo> = NetBuilder::new(0..size as u16) .num_faulty(num_faulty_nodes as usize)
.num_faulty(num_faulty_nodes as usize) .message_limit(10_000 * size as usize)
.message_limit(10_000 * size as usize) .time_limit(time::Duration::from_secs(30 * size as u64))
.time_limit(time::Duration::from_secs(30 * size as u64)) .rng(rng.gen::<TestRng>())
.rng(rng.gen::<TestRng>()) .adversary(ReorderingAdversary::new(rng.gen::<TestRng>()))
.adversary(ReorderingAdversary::new(rng.gen::<TestRng>())) .using(move |node_info: NewNodeInfo<_>| {
.using(move |node_info: NewNodeInfo<_>| { BinaryAgreement::new(Arc::new(node_info.netinfo), 0)
BinaryAgreement::new(Arc::new(node_info.netinfo), 0) .expect("Failed to create a BinaryAgreement instance.")
.expect("Failed to create a BinaryAgreement instance.") }).build()
}).build() .expect("Could not construct test network.");
.expect("Could not construct test network."); net.test_binary_agreement(cfg.input, rng.gen::<TestRng>());
net.test_binary_agreement(input, rng.gen::<TestRng>()); println!(
println!( "Test success: {} good nodes and {} faulty nodes, input: {:?}",
"Test success: {} good nodes and {} faulty nodes, input: {:?}", num_good_nodes, num_faulty_nodes, cfg.input
num_good_nodes, num_faulty_nodes, input );
);
}
} }