Skip to content

Commit

Permalink
Merge pull request #11 from Davidson-Souza/rework-tests
Browse files Browse the repository at this point in the history
Rework tests from the json file
  • Loading branch information
kcalvinalvin authored Oct 24, 2022
2 parents 989be56 + 18a62a5 commit efa63f6
Show file tree
Hide file tree
Showing 5 changed files with 354 additions and 270 deletions.
50 changes: 50 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ bitcoin_hashes = "0.7.6"
sha2 = "0.10.2"

[dev-dependencies]
serde_json="1.0.81"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.81"
89 changes: 37 additions & 52 deletions src/accumulator/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ impl Proof {
pub fn targets(&self) -> usize {
self.targets.len()
}

/// This function computes a set of roots from a proof.
/// If some target's hashes are null, then it computes the roots after
/// those targets are deleted. In this context null means [sha256::Hash::default].
Expand Down Expand Up @@ -240,6 +241,7 @@ impl Proof {

Ok((nodes, calculated_root_hashes))
}

fn sorted_push(
nodes: &mut Vec<(u64, bitcoin_hashes::sha256::Hash)>,
to_add: (u64, bitcoin_hashes::sha256::Hash),
Expand All @@ -251,14 +253,22 @@ impl Proof {

#[cfg(test)]
mod tests {
use core::panic;
use std::{str::FromStr, vec};
use std::str::FromStr;

use bitcoin_hashes::{sha256, Hash, HashEngine};
use serde::Deserialize;

use super::Proof;
use crate::accumulator::stump::Stump;

#[derive(Deserialize)]
struct TestCase {
numleaves: usize,
roots: Vec<String>,
targets: Vec<u64>,
target_preimages: Vec<u8>,
proofhashes: Vec<String>,
expected: bool,
}
fn hash_from_u8(value: u8) -> bitcoin_hashes::sha256::Hash {
let mut engine = bitcoin_hashes::sha256::Hash::engine();

Expand Down Expand Up @@ -348,61 +358,36 @@ mod tests {
}
}
fn run_single_case(case: &serde_json::Value) {
let mut s = Stump::new();

let mut hashes = Vec::new();

if let Some(roots) = case["roots"].as_array() {
for root in roots {
s.roots
.push(bitcoin_hashes::sha256::Hash::from_str(root.as_str().unwrap()).unwrap());
}
s.leafs = case["leafs"].as_u64().expect("Missing leafs count");
} else if let Some(leafs) = case["leaf_values"].as_array() {
for i in leafs {
hashes.push(hash_from_u8(i.as_u64().unwrap() as u8));
}

s = s
.modify(&hashes, &vec![], &Proof::default())
.expect("Test stump is valid");
} else {
panic!("Missing test data");
}

let json_targets = case["targets"].as_array().expect("Test case misformed");
let json_proof_hashes = case["proof"].as_array().expect("Test case misformed");
let json_del_values = case["values"].as_array();

let mut targets = vec![];
let mut del_hashes = vec![];
let mut proof_hashes = vec![];
let case = serde_json::from_value::<TestCase>(case.clone()).expect("Invalid test case");
let roots = case
.roots
.into_iter()
.map(|root| sha256::Hash::from_str(root.as_str()).expect("Test case hash is valid"))
.collect();

for i in json_targets {
targets.push(i.as_u64().unwrap());
}
let s = Stump {
leafs: case.numleaves as u64,
roots,
};

if let Some(values) = json_del_values {
for i in values.iter() {
let value = i.as_u64().unwrap();
del_hashes.push(hash_from_u8(value as u8));
}
} else {
for i in targets.iter() {
del_hashes.push(hash_from_u8(*i as u8));
}
}
let targets = case.targets;
let del_hashes = case
.target_preimages
.into_iter()
.map(|target| hash_from_u8(target))
.collect();

for i in json_proof_hashes {
proof_hashes.push(bitcoin_hashes::sha256::Hash::from_str(i.as_str().unwrap()).unwrap());
}
let proof_hashes = case
.proofhashes
.into_iter()
.map(|hash| sha256::Hash::from_str(hash.as_str()).expect("Test case hash is valid"))
.collect();

let p = Proof::new(targets, proof_hashes);
let expected = case["expected"].as_bool().unwrap();
let expected = case.expected;

if let Ok(res) = p.verify(&del_hashes, &s) {
assert!(expected == res);
}
let res = p.verify(&del_hashes, &s);
assert!(Ok(expected) == res);
}

#[test]
Expand Down
95 changes: 53 additions & 42 deletions src/accumulator/stump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,21 @@ impl Stump {

#[cfg(test)]
mod test {
use crate::{
accumulator::proof::Proof, get_hash_array_from_obj, get_json_field, get_u64_array_from_obj,
};
use crate::accumulator::proof::Proof;

use super::Stump;
use bitcoin_hashes::{hex::ToHex, sha256, Hash, HashEngine};
use serde::Deserialize;
use std::{str::FromStr, vec};

#[derive(Debug, Deserialize)]
struct TestCase {
leaf_preimages: Vec<u8>,
target_values: Option<Vec<u64>>,
expected_roots: Vec<String>,
proofhashes: Option<Vec<String>>,
}

#[test]
// Make a few simple tests about stump creation
fn test_stump() {
Expand All @@ -176,53 +183,53 @@ mod test {
sha256::Hash::from_engine(engine)
}

fn run_case_with_deletion(case: &serde_json::Value) {
let leafs = get_json_field!("leaf_values", case);
let target_values = get_json_field!("target_values", case);
let roots = get_json_field!("roots", case);
let proof_hashes = get_json_field!("proof_hashes", case);
fn run_case_with_deletion(case: TestCase) {
let leaf_hashes = case
.leaf_preimages
.into_iter()
.map(|leaf| hash_from_u8(leaf))
.collect();

let leafs = get_u64_array_from_obj!(leafs);
let target_values = get_u64_array_from_obj!(target_values);
let roots = get_hash_array_from_obj!(roots);
let proof_hashes = get_hash_array_from_obj!(proof_hashes);
let target_hashes = case
.target_values
.clone()
.unwrap()
.into_iter()
.map(|target| hash_from_u8(target as u8))
.collect();

let mut leaf_hashes = vec![];
for i in leafs.iter() {
leaf_hashes.push(hash_from_u8(*i as u8));
}
let proof_hashes = case
.proofhashes
.unwrap_or_default()
.into_iter()
.map(|hash| sha256::Hash::from_str(hash.as_str()).expect("Test case hashes are valid"))
.collect();

let mut target_hashes = vec![];
for i in target_values.iter() {
target_hashes.push(hash_from_u8(*i as u8));
}
let proof = Proof::new(case.target_values.unwrap(), proof_hashes);

let proof = Proof::new(target_values, proof_hashes);
let roots = case
.expected_roots
.into_iter()
.map(|hash| sha256::Hash::from_str(hash.as_str()).expect("Test case hashes are valid"))
.collect::<Vec<sha256::Hash>>();

let stump = Stump::new()
.modify(&leaf_hashes, &vec![], &Proof::default())
.expect("This stump is valid");

let stump = stump.modify(&vec![], &target_hashes, &proof).unwrap();

assert_eq!(stump.roots, roots);
}

fn run_single_addition_case(case: &serde_json::Value) {
fn run_single_addition_case(case: TestCase) {
let s = Stump::new();
let test_values = case["leaf_values"]
.as_array()
.expect("Test data is missing");

let roots = case["roots"]
.as_array()
.expect("Fail reading roots for this case");
let test_values = case.leaf_preimages;
let roots = case.expected_roots;

let mut hashes = vec![];

for i in test_values {
hashes.push(hash_from_u8(i.as_u64().unwrap() as u8));
}
let hashes = test_values
.iter()
.map(|value| hash_from_u8(*value))
.collect();

let s = s
.modify(&hashes, &vec![], &Proof::default())
Expand All @@ -231,7 +238,7 @@ mod test {
assert_eq!(s.leafs, hashes.len() as u64);

for i in 0..roots.len() {
assert_eq!(roots[i].as_str().unwrap(), s.roots[i].to_hex());
assert_eq!(roots[i].as_str(), s.roots[i].to_hex());
}
}

Expand Down Expand Up @@ -268,18 +275,22 @@ mod test {

#[test]
fn run_test_cases() {
#[derive(Deserialize)]
struct TestsJSON {
insertion_tests: Vec<TestCase>,
deletion_tests: Vec<TestCase>,
}

let contents = std::fs::read_to_string("test_values/test_cases.json")
.expect("Something went wrong reading the file");

let values: serde_json::Value =
serde_json::from_str(contents.as_str()).expect("JSON deserialization error");
let insertion_tests = values["insertion_tests"].as_array().unwrap();
let deletion_tests = values["deletion_tests"].as_array().unwrap();
let tests = serde_json::from_str::<TestsJSON>(contents.as_str())
.expect("JSON deserialization error");

for i in insertion_tests {
for i in tests.insertion_tests {
run_single_addition_case(i);
}
for i in deletion_tests {
for i in tests.deletion_tests {
run_case_with_deletion(i);
}
}
Expand Down
Loading

0 comments on commit efa63f6

Please sign in to comment.