From 3b25f5c2accfb603ec420469843ca2703ddaf993 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Thu, 16 Nov 2023 12:50:33 +0100 Subject: [PATCH] use rstest for testdata files and fixtures --- Code/itf/Cargo.toml | 1 + Code/itf/tests/consensus.rs | 24 ++---- Code/itf/tests/votekeeper.rs | 150 +++++++++++++++++------------------ 3 files changed, 84 insertions(+), 91 deletions(-) diff --git a/Code/itf/Cargo.toml b/Code/itf/Cargo.toml index bdfd64e11..ad19c12f6 100644 --- a/Code/itf/Cargo.toml +++ b/Code/itf/Cargo.toml @@ -15,4 +15,5 @@ malachite-common = { version = "0.1.0", path = "../common" } malachite-vote = { version = "0.1.0", path = "../vote" } malachite-test = { version = "0.1.0", path = "../test" } num-bigint = { version = "0.4", features = ["serde"] } +rstest = { version = "0.18.2", default-features = false } serde = { workspace = true, features = ["derive"] } diff --git a/Code/itf/tests/consensus.rs b/Code/itf/tests/consensus.rs index 435ec6481..6777ef01e 100644 --- a/Code/itf/tests/consensus.rs +++ b/Code/itf/tests/consensus.rs @@ -1,21 +1,13 @@ use malachite_itf::consensus::State; +use rstest::rstest; +use std::path::PathBuf; -#[test] -fn parse_fixtures() { - let folder = format!("{}/tests/fixtures/consensus", env!("CARGO_MANIFEST_DIR")); +#[rstest] +fn test_itf(#[files("tests/fixtures/consensus/*.json")] json_fixture: PathBuf) { + println!("Parsing {json_fixture:?}"); - let fixtures = std::fs::read_dir(folder) - .unwrap() - .map(|entry| entry.unwrap().path()) - .filter(|path| path.extension().map_or(false, |ext| ext == "json")) - .collect::>(); + let json = std::fs::read_to_string(&json_fixture).unwrap(); + let state = itf::trace_from_str::(&json).unwrap(); - for fixture in fixtures { - println!("Parsing '{}'", fixture.display()); - - let json = std::fs::read_to_string(&fixture).unwrap(); - let state = itf::trace_from_str::(&json).unwrap(); - - dbg!(state); - } + dbg!(state); } diff --git a/Code/itf/tests/votekeeper.rs b/Code/itf/tests/votekeeper.rs index caf2ee713..1812337a3 100644 --- a/Code/itf/tests/votekeeper.rs +++ b/Code/itf/tests/votekeeper.rs @@ -8,92 +8,92 @@ use malachite_vote::keeper::Message; use malachite_vote::{keeper::VoteKeeper, Weight}; use num_bigint::Sign; +use std::path::PathBuf; + use rand::rngs::StdRng; use rand::SeedableRng; -#[test] -fn parse_fixtures() { +use rstest::{fixture, rstest}; + +#[fixture] +#[once] +fn model_address_map() -> HashMap { let mut rng = StdRng::seed_from_u64(0x42); // build mapping from model addresses to real addresses - let valid_model_addresses = vec!["alice", "bob", "john"]; - let model_address_map: HashMap<&str, Address> = valid_model_addresses + let valid_model_addresses = ["alice", "bob", "john"]; + valid_model_addresses .iter() .map(|&name| { let pk = PrivateKey::generate(&mut rng).public_key(); - (name, Address::from_public_key(&pk)) + (name.into(), Address::from_public_key(&pk)) }) - .collect(); - - // read fixtures files in test/fixtures/votekeeper/ - let folder = format!("{}/tests/fixtures/votekeeper", env!("CARGO_MANIFEST_DIR")); - - let fixtures = std::fs::read_dir(folder) - .unwrap() - .map(|entry| entry.unwrap().path()) - .filter(|path| path.extension().map_or(false, |ext| ext == "json")) - .collect::>(); - - for fixture in fixtures { - println!("Parsing '{}'", fixture.display()); - - let json = std::fs::read_to_string(&fixture).unwrap(); - let trace = itf::trace_from_str::(&json).unwrap(); - - // Obtain the initial total_weight from the first state in the model. - let bookkeper = trace.states[0].value.bookkeeper.clone(); - let total_weight: Weight = uint_from_model(bookkeper.total_weight).unwrap(); - - let mut keeper: VoteKeeper = VoteKeeper::new(total_weight); - - for state in &trace.states[1..] { - let state = state.clone().value; - - // Build step to execute. - let (input_vote, weight) = state.weighted_vote.value(); - let round = round_from_model(input_vote.round); - let value = value_from_model(input_vote.value); - let address = model_address_map.get(input_vote.address.as_str()).unwrap(); - let vote = match input_vote.typ.as_str() { - "Prevote" => Vote::new_prevote(round, value, *address), - "Precommit" => Vote::new_precommit(round, value, *address), - _ => unreachable!(), - }; - let weight: Weight = uint_from_model(weight).unwrap(); - println!( - "🟢 step: vote={:?}, round={:?}, value={:?}, address={:?}, weight={:?}", - input_vote.typ, round, value, input_vote.address, weight - ); - - // Execute step. - let result = keeper.apply_vote(vote.clone(), weight); - - // Get expected result. - let model_result = state.last_emitted; - println!( - "🟣 result: model={:?}({:?}), code={:?}", - model_result.name, model_result.value, result - ); - - // Check result against expected result. - if result.is_none() { - assert_eq!(model_result.name, "None"); - } else { - match result.unwrap() { - Message::PolkaValue(value) => { - assert_eq!(model_result.name, "PolkaValue"); - assert_eq!(value_from_model(model_result.value), Some(value)); - } - Message::PrecommitValue(value) => { - assert_eq!(model_result.name, "PrecommitValue"); - assert_eq!(value_from_model(model_result.value), Some(value)); - } - Message::SkipRound(round) => { - assert_eq!(model_result.name, "SkipRound"); - assert_eq!(round_from_model(model_result.round), round); - } - msg => assert_eq!(model_result.name, format!("{:?}", msg)), + .collect() +} + +#[rstest] +fn test_itf( + #[files("tests/fixtures/votekeeper/*.json")] fixture: PathBuf, + model_address_map: &HashMap, +) { + println!("Parsing '{}'", fixture.display()); + + let json = std::fs::read_to_string(&fixture).unwrap(); + let trace = itf::trace_from_str::(&json).unwrap(); + + // Obtain the initial total_weight from the first state in the model. + let bookkeper = trace.states[0].value.bookkeeper.clone(); + let total_weight: Weight = uint_from_model(bookkeper.total_weight).unwrap(); + + let mut keeper: VoteKeeper = VoteKeeper::new(total_weight); + + for state in &trace.states[1..] { + let state = state.clone().value; + + // Build step to execute. + let (input_vote, weight) = state.weighted_vote.value(); + let round = round_from_model(input_vote.round); + let value = value_from_model(input_vote.value); + let address = model_address_map.get(input_vote.address.as_str()).unwrap(); + let vote = match input_vote.typ.as_str() { + "Prevote" => Vote::new_prevote(round, value, *address), + "Precommit" => Vote::new_precommit(round, value, *address), + _ => unreachable!(), + }; + let weight: Weight = uint_from_model(weight).unwrap(); + println!( + "🟢 step: vote={:?}, round={:?}, value={:?}, address={:?}, weight={:?}", + input_vote.typ, round, value, input_vote.address, weight + ); + + // Execute step. + let result = keeper.apply_vote(vote.clone(), weight); + + // Get expected result. + let model_result = state.last_emitted; + println!( + "🟣 result: model={:?}({:?}), code={:?}", + model_result.name, model_result.value, result + ); + + // Check result against expected result. + if result.is_none() { + assert_eq!(model_result.name, "None"); + } else { + match result.unwrap() { + Message::PolkaValue(value) => { + assert_eq!(model_result.name, "PolkaValue"); + assert_eq!(value_from_model(model_result.value), Some(value)); + } + Message::PrecommitValue(value) => { + assert_eq!(model_result.name, "PrecommitValue"); + assert_eq!(value_from_model(model_result.value), Some(value)); + } + Message::SkipRound(round) => { + assert_eq!(model_result.name, "SkipRound"); + assert_eq!(round_from_model(model_result.round), round); } + msg => assert_eq!(model_result.name, format!("{:?}", msg)), } } }