Skip to content

Commit

Permalink
use rstest for testdata files and fixtures
Browse files Browse the repository at this point in the history
  • Loading branch information
rnbguy committed Nov 16, 2023
1 parent 7c1aaec commit 3b25f5c
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 91 deletions.
1 change: 1 addition & 0 deletions Code/itf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"] }
24 changes: 8 additions & 16 deletions Code/itf/tests/consensus.rs
Original file line number Diff line number Diff line change
@@ -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::<Vec<_>>();
let json = std::fs::read_to_string(&json_fixture).unwrap();
let state = itf::trace_from_str::<State>(&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::<State>(&json).unwrap();

dbg!(state);
}
dbg!(state);
}
150 changes: 75 additions & 75 deletions Code/itf/tests/votekeeper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, Address> {
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::<Vec<_>>();

for fixture in fixtures {
println!("Parsing '{}'", fixture.display());

let json = std::fs::read_to_string(&fixture).unwrap();
let trace = itf::trace_from_str::<State>(&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<TestContext> = 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<String, Address>,
) {
println!("Parsing '{}'", fixture.display());

let json = std::fs::read_to_string(&fixture).unwrap();
let trace = itf::trace_from_str::<State>(&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<TestContext> = 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)),
}
}
}
Expand Down

0 comments on commit 3b25f5c

Please sign in to comment.