Make "random" trie tests fully determinate.

This commit is contained in:
Gav Wood 2016-02-27 15:49:44 +01:00
parent d01c1c0d32
commit ec8c1cb5f9
2 changed files with 37 additions and 46 deletions

View File

@ -20,6 +20,7 @@ extern crate rand;
use bytes::*; use bytes::*;
use sha3::*; use sha3::*;
use hash::*; use hash::*;
use rlp::encode;
/// Alphabet to use when creating words for insertion into tries. /// Alphabet to use when creating words for insertion into tries.
pub enum Alphabet { pub enum Alphabet {
@ -39,6 +40,8 @@ pub enum ValueMode {
Mirror, Mirror,
/// Randomly (50:50) 1 or 32 byte randomly string. /// Randomly (50:50) 1 or 32 byte randomly string.
Random, Random,
/// RLP-encoded index.
Index,
} }
/// Standard test map for profiling tries. /// Standard test map for profiling tries.
@ -89,19 +92,27 @@ impl StandardMap {
/// Create the standard map (set of keys and values) for the object's fields. /// Create the standard map (set of keys and values) for the object's fields.
pub fn make(&self) -> Vec<(Bytes, Bytes)> { pub fn make(&self) -> Vec<(Bytes, Bytes)> {
self.make_with(&mut H256::new())
}
/// Create the standard map (set of keys and values) for the object's fields, using the given seed.
pub fn make_with(&self, seed: &mut H256) -> Vec<(Bytes, Bytes)> {
let low = b"abcdef"; let low = b"abcdef";
let mid = b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_"; let mid = b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_";
let mut d: Vec<(Bytes, Bytes)> = Vec::new(); let mut d: Vec<(Bytes, Bytes)> = Vec::new();
let mut seed = H256::new(); for index in 0..self.count {
for _ in 0..self.count {
let k = match self.alphabet { let k = match self.alphabet {
Alphabet::All => Self::random_bytes(self.min_key, self.journal_key, &mut seed), Alphabet::All => Self::random_bytes(self.min_key, self.journal_key, seed),
Alphabet::Low => Self::random_word(low, self.min_key, self.journal_key, &mut seed), Alphabet::Low => Self::random_word(low, self.min_key, self.journal_key, seed),
Alphabet::Mid => Self::random_word(mid, self.min_key, self.journal_key, &mut seed), Alphabet::Mid => Self::random_word(mid, self.min_key, self.journal_key, seed),
Alphabet::Custom(ref a) => Self::random_word(&a, self.min_key, self.journal_key, &mut seed), Alphabet::Custom(ref a) => Self::random_word(&a, self.min_key, self.journal_key, seed),
};
let v = match self.value_mode {
ValueMode::Mirror => k.clone(),
ValueMode::Random => Self::random_value(seed),
ValueMode::Index => encode(&index).to_vec(),
}; };
let v = match self.value_mode { ValueMode::Mirror => k.clone(), ValueMode::Random => Self::random_value(&mut seed) };
d.push((k, v)) d.push((k, v))
} }
d d

View File

@ -687,31 +687,10 @@ mod tests {
use super::*; use super::*;
use nibbleslice::*; use nibbleslice::*;
use rlp::*; use rlp::*;
use rand::random; use bytes::ToPretty;
use std::collections::HashSet;
use bytes::{ToPretty,Bytes,Populatable};
use super::super::node::*; use super::super::node::*;
use super::super::trietraits::*; use super::super::trietraits::*;
use super::super::standardmap::*;
fn random_key(alphabet: &[u8], min_count: usize, journal_count: usize) -> Vec<u8> {
let mut ret: Vec<u8> = Vec::new();
let r = min_count + if journal_count > 0 {random::<usize>() % journal_count} else {0};
for _ in 0..r {
ret.push(alphabet[random::<usize>() % alphabet.len()]);
}
ret
}
fn random_value_indexed(j: usize) -> Bytes {
match random::<usize>() % 2 {
0 => encode(&j).to_vec(),
_ => {
let mut h = H256::new();
h.as_slice_mut()[31] = j as u8;
encode(&h).to_vec()
},
}
}
fn populate_trie<'db>(db: &'db mut HashDB, root: &'db mut H256, v: &[(Vec<u8>, Vec<u8>)]) -> TrieDBMut<'db> { fn populate_trie<'db>(db: &'db mut HashDB, root: &'db mut H256, v: &[(Vec<u8>, Vec<u8>)]) -> TrieDBMut<'db> {
let mut t = TrieDBMut::new(db, root); let mut t = TrieDBMut::new(db, root);
@ -756,20 +735,18 @@ mod tests {
};*/ };*/
// panic!(); // panic!();
let mut seed = H256::new();
for test_i in 0..1 { for test_i in 0..1 {
if test_i % 50 == 0 { if test_i % 50 == 0 {
debug!("{:?} of 10000 stress tests done", test_i); debug!("{:?} of 10000 stress tests done", test_i);
} }
let mut x: Vec<(Vec<u8>, Vec<u8>)> = Vec::new(); let x = StandardMap {
let mut got: HashSet<Vec<u8>> = HashSet::new(); alphabet: Alphabet::Custom(b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_".to_vec()),
let alphabet = b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_"; min_key: 5,
for j in 0..100usize { journal_key: 0,
let key = random_key(alphabet, 5, 0); value_mode: ValueMode::Index,
if !got.contains(&key) { count: 100,
x.push((key.clone(), random_value_indexed(j))); }.make_with(&mut seed);
got.insert(key);
}
}
let real = trie_root(x.clone()); let real = trie_root(x.clone());
let mut memdb = MemoryDB::new(); let mut memdb = MemoryDB::new();
@ -1049,13 +1026,16 @@ mod tests {
#[test] #[test]
fn stress() { fn stress() {
let mut seed = H256::new();
for _ in 0..50 { for _ in 0..50 {
let mut x: Vec<(Vec<u8>, Vec<u8>)> = Vec::new(); let x = StandardMap {
let alphabet = b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_"; alphabet: Alphabet::Custom(b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_".to_vec()),
for j in 0..4u32 { min_key: 5,
let key = random_key(alphabet, 5, 1); journal_key: 0,
x.push((key, encode(&j).to_vec())); value_mode: ValueMode::Index,
} count: 4,
}.make_with(&mut seed);
let real = trie_root(x.clone()); let real = trie_root(x.clone());
let mut memdb = MemoryDB::new(); let mut memdb = MemoryDB::new();
let mut root = H256::new(); let mut root = H256::new();