Rename our custom `HashMap` to `RandomMap`

This makes it easier to distinguish with the stdlib.

Also, we add an env var that can control the RNG seed, for testing
purposes.
This commit is contained in:
cloudhead 2023-08-09 10:50:49 +02:00
parent d13f47b2a4
commit efb8de2728
No known key found for this signature in database
9 changed files with 43 additions and 29 deletions

View File

@ -56,6 +56,7 @@ fn formula(root: &Path, test: impl AsRef<Path>) -> Result<TestFormula, Box<dyn s
.env("GIT_COMMITTER_NAME", "radicle")
.env("RAD_PASSPHRASE", "radicle")
.env("RAD_SEED", RAD_SEED)
.env("RAD_RNG_SEED", "0")
.env("EDITOR", "true")
.env("TZ", "UTC")
.env("LANG", "C")

View File

@ -12,7 +12,7 @@ use radicle::node::routing::Store as _;
use radicle::node::ConnectOptions;
use radicle::storage::ReadRepository;
use crate::collections::{HashMap, HashSet};
use crate::collections::{RandomMap, RandomSet};
use crate::crypto::test::signer::MockSigner;
use crate::identity::Id;
use crate::node;
@ -1375,7 +1375,7 @@ fn prop_inventory_exchange_dense() {
eve_inv.clone(),
peer::Config::default(),
);
let mut routing = HashMap::with_hasher(rng.clone().into());
let mut routing = RandomMap::with_hasher(rng.clone().into());
for (inv, peer) in &[
(alice_inv.inventory, alice.node_id()),
@ -1385,7 +1385,7 @@ fn prop_inventory_exchange_dense() {
for id in inv.keys() {
routing
.entry(*id)
.or_insert_with(|| HashSet::with_hasher(rng.clone().into()))
.or_insert_with(|| RandomSet::with_hasher(rng.clone().into()))
.insert(*peer);
}
}
@ -1407,7 +1407,7 @@ fn prop_inventory_exchange_dense() {
ConnectOptions::default(),
));
let mut peers: HashMap<_, _> = [
let mut peers: RandomMap<_, _> = [
(alice.node_id(), alice),
(bob.node_id(), bob),
(eve.node_id(), eve),
@ -1439,7 +1439,7 @@ fn prop_inventory_exchange_dense() {
"There are remote locations for the project"
);
assert_eq!(
&lookup.remote.into_iter().collect::<HashSet<_>>(),
&lookup.remote.into_iter().collect::<RandomSet<_>>(),
remotes,
"The remotes match the global routing table"
);

View File

@ -21,7 +21,7 @@ use netservices::session::{ProtocolArtifact, Socks5Session};
use netservices::{NetConnection, NetProtocol, NetReader, NetWriter};
use reactor::Timestamp;
use radicle::collections::HashMap;
use radicle::collections::RandomMap;
use radicle::node::{address, routing, NodeId};
use radicle::storage::WriteStorage;
@ -74,7 +74,7 @@ struct Streams {
/// Active streams and their associated worker channels.
/// Note that the gossip and control streams are not included here as they are always
/// implied to exist.
streams: HashMap<StreamId, worker::Channels>,
streams: RandomMap<StreamId, worker::Channels>,
/// Connection direction.
link: Link,
/// Sequence number used to compute the next stream id.
@ -85,7 +85,7 @@ impl Streams {
/// Create a new [`Streams`] object, passing the connection link.
fn new(link: Link) -> Self {
Self {
streams: HashMap::default(),
streams: RandomMap::default(),
link,
seq: 0,
}
@ -257,7 +257,7 @@ impl Peer {
}
}
struct Peers(HashMap<RawFd, Peer>);
struct Peers(RandomMap<RawFd, Peer>);
impl Peers {
fn get_mut(&mut self, fd: &RawFd) -> Option<&mut Peer> {
@ -352,7 +352,7 @@ where
signer,
proxy,
actions: VecDeque::new(),
peers: Peers(HashMap::default()),
peers: Peers(RandomMap::default()),
}
}

View File

@ -2,10 +2,10 @@
use siphasher::sip::SipHasher13;
/// A `HashMap` which uses [`fastrand::Rng`] for its random state.
pub type HashMap<K, V> = std::collections::HashMap<K, V, RandomState>;
pub type RandomMap<K, V> = std::collections::HashMap<K, V, RandomState>;
/// A `HashSet` which uses [`fastrand::Rng`] for its random state.
pub type HashSet<K> = std::collections::HashSet<K, RandomState>;
pub type RandomSet<K> = std::collections::HashSet<K, RandomState>;
/// Random hasher state.
#[derive(Clone)]
@ -16,7 +16,7 @@ pub struct RandomState {
impl Default for RandomState {
fn default() -> Self {
Self::new(fastrand::Rng::new())
Self::new(crate::profile::env::rng())
}
}

View File

@ -6,7 +6,7 @@ use std::str::FromStr;
use git_ext::ref_format as format;
use once_cell::sync::Lazy;
use crate::collections::HashMap;
use crate::collections::RandomMap;
use crate::crypto::PublicKey;
use crate::storage;
use crate::storage::refs::Refs;
@ -367,9 +367,9 @@ pub mod refs {
}
/// List remote refs of a project, given the remote URL.
pub fn remote_refs(url: &Url) -> Result<HashMap<RemoteId, Refs>, ListRefsError> {
pub fn remote_refs(url: &Url) -> Result<RandomMap<RemoteId, Refs>, ListRefsError> {
let url = url.to_string();
let mut remotes = HashMap::default();
let mut remotes = RandomMap::default();
let mut remote = git2::Remote::create_detached(url)?;
remote.connect(git2::Direction::Fetch)?;

View File

@ -3,7 +3,7 @@ use std::ops::{Deref, DerefMut};
use localtime::LocalTime;
use nonempty::NonEmpty;
use crate::collections::HashMap;
use crate::collections::RandomMap;
use crate::node;
use crate::node::{Address, Alias};
use crate::prelude::Timestamp;
@ -11,7 +11,7 @@ use crate::prelude::Timestamp;
/// A map with the ability to randomly select values.
#[derive(Debug, Clone)]
pub struct AddressBook<K, V> {
inner: HashMap<K, V>,
inner: RandomMap<K, V>,
rng: fastrand::Rng,
}
@ -19,7 +19,7 @@ impl<K, V> AddressBook<K, V> {
/// Create a new address book.
pub fn new(rng: fastrand::Rng) -> Self {
Self {
inner: HashMap::with_hasher(rng.clone().into()),
inner: RandomMap::with_hasher(rng.clone().into()),
rng,
}
}
@ -61,7 +61,7 @@ impl<K, V> AddressBook<K, V> {
}
impl<K, V> Deref for AddressBook<K, V> {
type Target = HashMap<K, V>;
type Target = RandomMap<K, V>;
fn deref(&self) -> &Self::Target {
&self.inner

View File

@ -37,6 +37,8 @@ pub mod env {
pub const RAD_SOCKET: &str = "RAD_SOCKET";
/// Passphrase for the encrypted radicle secret key.
pub const RAD_PASSPHRASE: &str = "RAD_PASSPHRASE";
/// RNG seed. Must be convertible to a `u64`.
pub const RAD_RNG_SEED: &str = "RAD_RNG_SEED";
/// Get the radicle passphrase from the environment.
pub fn passphrase() -> Option<super::Passphrase> {
@ -45,6 +47,17 @@ pub mod env {
};
Some(super::Passphrase::from(passphrase))
}
/// Get a random number generator from the environment.
pub fn rng() -> fastrand::Rng {
let Ok(seed) = std::env::var(RAD_RNG_SEED) else {
return fastrand::Rng::new();
};
fastrand::Rng::with_seed(
seed.parse()
.expect("env::rng: invalid seed specified in `RAD_RNG_SEED`"),
)
}
}
#[derive(Debug, Error)]

View File

@ -14,7 +14,7 @@ use crypto::{PublicKey, Signer, Unverified, Verified};
pub use git::VerifyError;
pub use radicle_git_ext::Oid;
use crate::collections::HashMap;
use crate::collections::RandomMap;
use crate::git::ext as git_ext;
use crate::git::{refspec::Refspec, PatternString, Qualified, RefError, RefString};
use crate::identity;
@ -168,7 +168,7 @@ impl fmt::Display for RefUpdate {
/// Project remotes. Tracks the git state of a project.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Remotes<V>(HashMap<RemoteId, Remote<V>>);
pub struct Remotes<V>(RandomMap<RemoteId, Remote<V>>);
impl<V> FromIterator<(RemoteId, Remote<V>)> for Remotes<V> {
fn from_iter<T: IntoIterator<Item = (RemoteId, Remote<V>)>>(iter: T) -> Self {
@ -177,7 +177,7 @@ impl<V> FromIterator<(RemoteId, Remote<V>)> for Remotes<V> {
}
impl<V> Deref for Remotes<V> {
type Target = HashMap<RemoteId, Remote<V>>;
type Target = RandomMap<RemoteId, Remote<V>>;
fn deref(&self) -> &Self::Target {
&self.0
@ -185,7 +185,7 @@ impl<V> Deref for Remotes<V> {
}
impl<V> Remotes<V> {
pub fn new(remotes: HashMap<RemoteId, Remote<V>>) -> Self {
pub fn new(remotes: RandomMap<RemoteId, Remote<V>>) -> Self {
Self(remotes)
}
}
@ -202,7 +202,7 @@ impl Remotes<Verified> {
impl<V> Default for Remotes<V> {
fn default() -> Self {
Self(HashMap::default())
Self(RandomMap::default())
}
}
@ -215,9 +215,9 @@ impl<V> IntoIterator for Remotes<V> {
}
}
impl<V> From<Remotes<V>> for HashMap<RemoteId, Refs> {
impl<V> From<Remotes<V>> for RandomMap<RemoteId, Refs> {
fn from(other: Remotes<V>) -> Self {
let mut remotes = HashMap::with_hasher(fastrand::Rng::new().into());
let mut remotes = RandomMap::with_hasher(fastrand::Rng::new().into());
for (k, v) in other.into_iter() {
remotes.insert(k, v.refs.into());

View File

@ -9,7 +9,7 @@ use crypto::{PublicKey, Unverified, Verified};
use nonempty::NonEmpty;
use qcheck::Arbitrary;
use crate::collections::HashMap;
use crate::collections::RandomMap;
use crate::identity::{
doc::{Doc, Id},
project::Project,
@ -82,7 +82,7 @@ pub fn gen<T: Arbitrary>(size: usize) -> T {
impl Arbitrary for storage::Remotes<crypto::Verified> {
fn arbitrary(g: &mut qcheck::Gen) -> Self {
let remotes: HashMap<storage::RemoteId, storage::Remote<crypto::Verified>> =
let remotes: RandomMap<storage::RemoteId, storage::Remote<crypto::Verified>> =
Arbitrary::arbitrary(g);
storage::Remotes::new(remotes)