Skip to content

Commit

Permalink
impl: explicitly randomize map/set iteration order
Browse files Browse the repository at this point in the history
And finally, this commit is the pay-off of previous refactorings. We can
now easily randomize iteration order over hash maps/sets. The idea here
is to provoke bugs that depend on iteration order.
  • Loading branch information
BurntSushi committed Jan 22, 2024
1 parent 2f85c02 commit bb53f67
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 5 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ thiserror = "1.0"
rustc-hash = "1.1.0"
serde = { version = "1.0", features = ["derive"], optional = true }
log = "0.4.14" # for debug logs in tests
rand = "0.8.5"

[dev-dependencies]
proptest = "0.10.1"
Expand Down
16 changes: 11 additions & 5 deletions src/type_aliases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ impl<K, V, S> Map<K, V, S> {
let keys: Vec<&K> = self.map.keys().collect();
MapIter {
map: self,
order: keys.into_iter(),
order: shuffle(keys).into_iter(),
}
}

pub fn keys(&self) -> impl Iterator<Item = &K> {
let keys: Vec<&K> = self.map.keys().collect();
MapKeys {
order: keys.into_iter(),
order: shuffle(keys).into_iter(),
_v: std::marker::PhantomData::<&V>,
}
}
Expand Down Expand Up @@ -142,7 +142,7 @@ impl<K: Clone + Eq + Hash, V, S: BuildHasher> IntoIterator for Map<K, V, S> {
let keys: Vec<K> = self.map.keys().map(|k| k.clone()).collect();
MapIntoIter {
map: self,
order: keys.into_iter(),
order: shuffle(keys).into_iter(),
}
}
}
Expand Down Expand Up @@ -205,7 +205,7 @@ impl<V> Set<V> {
pub fn iter(&self) -> SetIter<V> {
let keys: Vec<&V> = self.set.iter().collect();
SetIter {
order: keys.into_iter(),
order: shuffle(keys).into_iter(),
}
}
}
Expand Down Expand Up @@ -251,7 +251,7 @@ impl<V> IntoIterator for Set<V> {
fn into_iter(self) -> Self::IntoIter {
let keys: Vec<V> = self.set.into_iter().collect();
SetIntoIter {
order: keys.into_iter(),
order: shuffle(keys).into_iter(),
}
}
}
Expand All @@ -277,3 +277,9 @@ impl<'a, V> Iterator for SetIntoIter<V> {
self.order.next()
}
}

fn shuffle<T>(mut v: Vec<T>) -> Vec<T> {
use rand::seq::SliceRandom;
v.shuffle(&mut rand::thread_rng());
v
}

0 comments on commit bb53f67

Please sign in to comment.