diff --git a/crates/socket-patch-core/src/crawlers/cargo_crawler.rs b/crates/socket-patch-core/src/crawlers/cargo_crawler.rs index b03b797ed..b262e4a5b 100644 --- a/crates/socket-patch-core/src/crawlers/cargo_crawler.rs +++ b/crates/socket-patch-core/src/crawlers/cargo_crawler.rs @@ -1394,7 +1394,8 @@ version = "fake" mod equivalence { use super::super::oracle::LegacyCargoCrawler; use super::*; - use crate::crawlers::oracle_support::{mkdir, rows, symlink, write, PermGuard, Rng}; + use crate::crawlers::oracle_support::{mkdir, rows, symlink, write, PermGuard}; + use crate::test_rng::Rng; const NAMES: &[&str] = &["serde", "serde-json", "sha-1", "tokio", "dup", "a_b"]; const VERSIONS: &[&str] = &["1.0.0", "1.0.0-rc.1", "0.2.3", "5", "1.0.0+build"]; diff --git a/crates/socket-patch-core/src/crawlers/composer_crawler.rs b/crates/socket-patch-core/src/crawlers/composer_crawler.rs index 0e7143238..c11fbae07 100644 --- a/crates/socket-patch-core/src/crawlers/composer_crawler.rs +++ b/crates/socket-patch-core/src/crawlers/composer_crawler.rs @@ -2376,7 +2376,8 @@ mod tests { mod equivalence { use super::super::oracle::LegacyComposerCrawler; use super::*; - use crate::crawlers::oracle_support::{map_rows, mkdir, rows, symlink, write, Rng}; + use crate::crawlers::oracle_support::{map_rows, mkdir, rows, symlink, write}; + use crate::test_rng::Rng; const NAMES: &[&str] = &[ "monolog/monolog", diff --git a/crates/socket-patch-core/src/crawlers/go_crawler.rs b/crates/socket-patch-core/src/crawlers/go_crawler.rs index 79784f1dc..5c5d243f3 100644 --- a/crates/socket-patch-core/src/crawlers/go_crawler.rs +++ b/crates/socket-patch-core/src/crawlers/go_crawler.rs @@ -1696,9 +1696,8 @@ mod tests { mod equivalence { use super::super::oracle::LegacyGoCrawler; use super::*; - use crate::crawlers::oracle_support::{ - map_rows, mkdir, rows, symlink, write, PermGuard, Rng, - }; + use crate::crawlers::oracle_support::{map_rows, mkdir, rows, symlink, write, PermGuard}; + use crate::test_rng::Rng; const NAMES: &[&str] = &[ "github.com", diff --git a/crates/socket-patch-core/src/crawlers/maven_crawler.rs b/crates/socket-patch-core/src/crawlers/maven_crawler.rs index 0b454704f..0822a50ab 100644 --- a/crates/socket-patch-core/src/crawlers/maven_crawler.rs +++ b/crates/socket-patch-core/src/crawlers/maven_crawler.rs @@ -2909,8 +2909,9 @@ mod tests { use super::super::oracle::LegacyMavenCrawler; use super::*; use crate::crawlers::oracle_support::{ - mkdir, rows, symlink, write, write_bytes, PermGuard, Rng, + mkdir, rows, symlink, write, write_bytes, PermGuard, }; + use crate::test_rng::Rng; const GROUPS: &[&str] = &["org/apache/commons", "com/google/guava", "io/netty"]; const ARTIFACTS: &[&str] = &["commons-lang3", "guava", "netty-all", "dup"]; diff --git a/crates/socket-patch-core/src/crawlers/npm_crawler/oracle.rs b/crates/socket-patch-core/src/crawlers/npm_crawler/oracle.rs index 5663ba351..5f7dd6bec 100644 --- a/crates/socket-patch-core/src/crawlers/npm_crawler/oracle.rs +++ b/crates/socket-patch-core/src/crawlers/npm_crawler/oracle.rs @@ -973,6 +973,7 @@ impl LegacyNpmCrawler { #[cfg(test)] mod tests { use super::*; + use crate::test_rng::Rng; use std::collections::BTreeMap; type Row = (String, String, String, Option, PathBuf); @@ -1029,7 +1030,7 @@ mod tests { // Symlinks, FIFOs and permission stripping are generated on Unix only. #[cfg_attr(not(unix), allow(dead_code))] struct Gen { - state: u64, + rng: Rng, /// Out-of-tree dir for symlink targets that get traversed. scratch: PathBuf, /// Real package dirs created so far (symlink targets). @@ -1045,7 +1046,7 @@ mod tests { impl Gen { fn new(seed: u64, scratch: PathBuf) -> Self { Self { - state: seed.wrapping_mul(0x9E37_79B9_7F4A_7C15) | 1, + rng: Rng::new(seed), scratch, pkg_dirs: Vec::new(), nm_dirs: Vec::new(), @@ -1054,28 +1055,6 @@ mod tests { } } - fn next(&mut self) -> u64 { - // xorshift64* - let mut x = self.state; - x ^= x >> 12; - x ^= x << 25; - x ^= x >> 27; - self.state = x; - x.wrapping_mul(0x2545_F491_4F6C_DD1D) - } - - fn below(&mut self, n: usize) -> usize { - (self.next() % n as u64) as usize - } - - fn chance(&mut self, pct: usize) -> bool { - self.below(100) < pct - } - - fn pick<'a>(&mut self, items: &'a [&'a str]) -> &'a str { - items[self.below(items.len())] - } - fn uniq(&mut self) -> usize { self.uniq += 1; self.uniq @@ -1127,7 +1106,7 @@ mod tests { return; } let valid = format!(r#"{{"name": "{name}", "version": "{version}"}}"#); - match self.below(100) { + match self.rng.below(100) { 0..=69 => { let _ = std::fs::write(&pj, valid); } @@ -1163,25 +1142,25 @@ mod tests { /// A package dir `nm/` (maybe with nested node_modules). fn package(&mut self, nm: &Path, depth: usize) { - let dir_name = self.pick(NAMES).to_string(); + let dir_name = self.rng.pick(NAMES).to_string(); // Mostly the dir's own name; sometimes an alias install. - let pkg_name = if self.chance(88) { + let pkg_name = if self.rng.chance(88) { dir_name.clone() } else { - self.pick(NAMES).to_string() + self.rng.pick(NAMES).to_string() }; - let version = self.pick(VERSIONS).to_string(); + let version = self.rng.pick(VERSIONS).to_string(); let dir = nm.join(&dir_name); if dir.exists() { return; } self.package_json(&dir, &pkg_name, &version); self.pkg_dirs.push(dir.clone()); - if depth < 3 && self.chance(30) { - let store_ok = self.chance(10); + if depth < 3 && self.rng.chance(30) { + let store_ok = self.rng.chance(10); self.node_modules(&dir.join("node_modules"), depth + 1, store_ok); } - if self.chance(4) { + if self.rng.chance(4) { self.plan_lock(&dir, 0o000); } } @@ -1190,37 +1169,37 @@ mod tests { let _ = std::fs::create_dir_all(nm); self.nm_dirs.push(nm.to_path_buf()); let mut store_pkgs: Vec<(String, PathBuf)> = Vec::new(); - if store_ok && self.chance(60) { + if store_ok && self.rng.chance(60) { store_pkgs = self.pnpm_store(&nm.join(".pnpm"), depth); - } else if self.chance(5) { + } else if self.rng.chance(5) { let _ = std::fs::write(nm.join(".pnpm"), "not a store"); } - if store_ok && self.chance(15) { + if store_ok && self.rng.chance(15) { self.legacy_store(&nm.join(".registry.npmjs.org"), depth); } - if store_ok && self.chance(20) { + if store_ok && self.rng.chance(20) { let vlt_pkgs = self.vlt_store(&nm.join(".vlt"), depth); store_pkgs.extend(vlt_pkgs); } - let n = self.below(6); + let n = self.rng.below(6); for _ in 0..n { - match self.below(100) { + match self.rng.below(100) { 0..=54 => self.package(nm, depth), 55..=62 => { // Symlinked entry: live, into the store, or dangling. - let name = self.pick(NAMES); + let name = self.rng.pick(NAMES); let link = nm.join(name); if link.symlink_metadata().is_ok() { continue; } - let target = if !store_pkgs.is_empty() && self.chance(50) { + let target = if !store_pkgs.is_empty() && self.rng.chance(50) { { - let i = self.below(store_pkgs.len()); + let i = self.rng.below(store_pkgs.len()); store_pkgs[i].1.clone() } - } else if !self.pkg_dirs.is_empty() && self.chance(80) { + } else if !self.pkg_dirs.is_empty() && self.rng.chance(80) { { - let i = self.below(self.pkg_dirs.len()); + let i = self.rng.below(self.pkg_dirs.len()); self.pkg_dirs[i].clone() } } else { @@ -1240,7 +1219,7 @@ mod tests { // the tree, so the followed walk cannot cycle). let id = self.uniq(); let target = self.scratch.join(format!("scope{id}")); - let version = self.pick(VERSIONS).to_string(); + let version = self.rng.pick(VERSIONS).to_string(); self.package_json(&target.join("x"), "@link/x", &version); let link = nm.join(format!("@link{}", self.uniq())); Self::symlink(&target, &link); @@ -1258,13 +1237,13 @@ mod tests { self.package_json(&nm.join("node_modules").join("foo"), "foo", "1.0.0"); } _ => { - let scoped = self.pick(&["@s/a", "@s/b", "@t/c"]).to_string(); + let scoped = self.rng.pick(&["@s/a", "@s/b", "@t/c"]).to_string(); let dir = nm.join(&scoped); if !dir.exists() { - let version = self.pick(VERSIONS).to_string(); + let version = self.rng.pick(VERSIONS).to_string(); self.package_json(&dir, &scoped, &version); self.pkg_dirs.push(dir.clone()); - if depth < 3 && self.chance(25) { + if depth < 3 && self.rng.chance(25) { self.node_modules(&dir.join("node_modules"), depth + 1, false); } } @@ -1274,11 +1253,11 @@ mod tests { // Root-linked direct deps: importer symlinks into the store. for (name, target) in store_pkgs { let link = nm.join(&name); - if self.chance(50) && link.symlink_metadata().is_err() { + if self.rng.chance(50) && link.symlink_metadata().is_err() { Self::symlink(&target, &link); } } - if self.chance(3) { + if self.rng.chance(3) { self.plan_lock(nm, 0o000); } } @@ -1291,11 +1270,11 @@ mod tests { let _ = std::fs::create_dir_all(store); let _ = std::fs::write(store.join("vlt.json"), "{}"); let mut own = Vec::new(); - for _ in 0..1 + self.below(6) { - let name = self.pick(NAMES).to_string(); - let version = self.pick(VERSIONS).to_string(); + for _ in 0..1 + self.rng.below(6) { + let name = self.rng.pick(NAMES).to_string(); + let version = self.rng.pick(VERSIONS).to_string(); let escaped = name.replace('/', "+"); - let id = match self.below(10) { + let id = match self.rng.below(10) { 0 => format!("~npm~{escaped}@{version}~peer.{}", self.uniq()), 1 => format!("··{}@{version}", name.replace('/', "§")), 2 => format!("·npm·{}@{version}", name.replace('/', "§")), @@ -1309,7 +1288,7 @@ mod tests { continue; } let entry_nm = entry.join("node_modules"); - if self.chance(5) { + if self.rng.chance(5) { let _ = std::fs::create_dir_all(&entry); let id = self.uniq(); let elsewhere = self.scratch.join(format!("vlt-nm{id}")); @@ -1317,24 +1296,24 @@ mod tests { Self::symlink(&elsewhere, &entry_nm); continue; } - let pkg_name = if self.chance(90) { + let pkg_name = if self.rng.chance(90) { name.clone() } else { - self.pick(NAMES).to_string() + self.rng.pick(NAMES).to_string() }; let pkg = entry_nm.join(&name); self.package_json(&pkg, &pkg_name, &version); self.pkg_dirs.push(pkg.clone()); own.push((name.clone(), pkg.clone())); - for _ in 0..self.below(3) { + for _ in 0..self.rng.below(3) { if let Some((dep, target)) = own.first().cloned() { Self::symlink(&target, &entry_nm.join(&dep)); } } - if depth < 2 && self.chance(25) { + if depth < 2 && self.rng.chance(25) { self.node_modules(&pkg.join("node_modules"), depth + 1, false); } - if self.chance(4) { + if self.rng.chance(4) { self.plan_lock(&entry_nm, 0o000); } } @@ -1343,7 +1322,7 @@ mod tests { fn store_entry_name(&mut self, name: &str, version: &str) -> String { let escaped = name.replace('/', "+"); - match self.below(10) { + match self.rng.below(10) { 0 => format!("{escaped}@{version}(peer@1.0.0)"), 1 => format!("{escaped}@{version}_peer@1.0.0"), 2 => format!("{escaped}@github.com+u+r@abc{}", self.uniq()), @@ -1358,38 +1337,38 @@ mod tests { let _ = std::fs::create_dir_all(store); let _ = std::fs::write(store.join("lock.yaml"), "x"); let mut own = Vec::new(); - let n = 1 + self.below(6); + let n = 1 + self.rng.below(6); for _ in 0..n { - let name = self.pick(NAMES).to_string(); - let version = self.pick(VERSIONS).to_string(); - match self.below(100) { + let name = self.rng.pick(NAMES).to_string(); + let version = self.rng.pick(VERSIONS).to_string(); + match self.rng.below(100) { 0..=59 => { let entry = store.join(self.store_entry_name(&name, &version)); let entry_nm = entry.join("node_modules"); - let pkg_name = if self.chance(90) { + let pkg_name = if self.rng.chance(90) { name.clone() } else { - self.pick(NAMES).to_string() + self.rng.pick(NAMES).to_string() }; let pkg = entry_nm.join(&name); self.package_json(&pkg, &pkg_name, &version); self.pkg_dirs.push(pkg.clone()); own.push((name.clone(), pkg.clone())); // Dependencies: symlinks to sibling entries. - for _ in 0..self.below(3) { + for _ in 0..self.rng.below(3) { if let Some((dep, target)) = own.first().cloned() { Self::symlink(&target, &entry_nm.join(format!("{dep}-dep"))); } } // Another real package in the entry (injected dep). - if self.chance(20) { + if self.rng.chance(20) { self.package(&entry_nm, depth + 1); } // Bundled deps below the package itself. - if depth < 2 && self.chance(25) { + if depth < 2 && self.rng.chance(25) { self.node_modules(&pkg.join("node_modules"), depth + 1, false); } - match self.below(100) { + match self.rng.below(100) { 0..=3 => self.plan_lock(&entry_nm, 0o000), 4..=6 => self.plan_lock(&entry, 0o000), 7..=9 => self.plan_lock(&entry_nm, 0o300), @@ -1465,12 +1444,12 @@ mod tests { /// A pnpm <=3 `.registry.npmjs.org` store. fn legacy_store(&mut self, store: &Path, depth: usize) { - for _ in 0..1 + self.below(4) { - let name = self.pick(NAMES).to_string(); - let version = self.pick(VERSIONS).to_string(); + for _ in 0..1 + self.rng.below(4) { + let name = self.rng.pick(NAMES).to_string(); + let version = self.rng.pick(VERSIONS).to_string(); let home = store.join(&name).join(&version).join("node_modules"); self.package_json(&home.join(&name), &name, &version); - if depth < 2 && self.chance(20) { + if depth < 2 && self.rng.chance(20) { self.package(&home, depth + 1); } } @@ -1478,19 +1457,19 @@ mod tests { fn workspace(&mut self, dir: &Path, depth: usize) { let _ = std::fs::create_dir_all(dir); - if self.chance(70) { + if self.rng.chance(70) { self.node_modules(&dir.join("node_modules"), 0, true); } if depth >= 3 { return; } - for _ in 0..self.below(5) { - let child = dir.join(format!("{}{}", self.pick(WS_NAMES), self.uniq())); - match self.below(100) { + for _ in 0..self.rng.below(5) { + let child = dir.join(format!("{}{}", self.rng.pick(WS_NAMES), self.uniq())); + match self.rng.below(100) { 0..=49 => self.workspace(&child, depth + 1), 50..=57 => { // Skipped by name (dist/vendor/.git/tmp as-is). - let skipped = dir.join(self.pick(&["dist", "vendor", ".git", "tmp"])); + let skipped = dir.join(self.rng.pick(&["dist", "vendor", ".git", "tmp"])); self.workspace(&skipped, depth + 1); } 58..=63 => { @@ -1514,7 +1493,7 @@ mod tests { 74..=79 => { // Case variant (aliases node_modules on APFS/NTFS). let _ = std::fs::create_dir_all(&child); - let variant = self.pick(&["Node_Modules", "NODE_MODULES"]); + let variant = self.rng.pick(&["Node_Modules", "NODE_MODULES"]); self.node_modules(&child.join(variant), 1, false); } 80..=85 => { diff --git a/crates/socket-patch-core/src/crawlers/nuget_crawler.rs b/crates/socket-patch-core/src/crawlers/nuget_crawler.rs index 79e354a32..f7faecf3c 100644 --- a/crates/socket-patch-core/src/crawlers/nuget_crawler.rs +++ b/crates/socket-patch-core/src/crawlers/nuget_crawler.rs @@ -2096,9 +2096,8 @@ mod tests { mod equivalence { use super::super::oracle::LegacyNuGetCrawler; use super::*; - use crate::crawlers::oracle_support::{ - map_rows, mkdir, rows, symlink, write, PermGuard, Rng, - }; + use crate::crawlers::oracle_support::{map_rows, mkdir, rows, symlink, write, PermGuard}; + use crate::test_rng::Rng; const IDS: &[&str] = &["Newtonsoft.Json", "xunit", "System.Text.Json", "Dup", "dup"]; const VERSIONS: &[&str] = &["13.0.3", "2.0.0-RC1", "8.0.0", "1.0.0"]; diff --git a/crates/socket-patch-core/src/crawlers/oracle_support.rs b/crates/socket-patch-core/src/crawlers/oracle_support.rs index bc62a0256..e7c6aff8e 100644 --- a/crates/socket-patch-core/src/crawlers/oracle_support.rs +++ b/crates/socket-patch-core/src/crawlers/oracle_support.rs @@ -7,36 +7,6 @@ use std::path::{Path, PathBuf}; use super::types::CrawledPackage; -/// Deterministic xorshift64* generator (no `rand` dependency). -pub(crate) struct Rng(u64); - -impl Rng { - pub(crate) fn new(seed: u64) -> Self { - Self(seed.wrapping_mul(0x9E37_79B9_7F4A_7C15) | 1) - } - - pub(crate) fn next(&mut self) -> u64 { - let mut x = self.0; - x ^= x >> 12; - x ^= x << 25; - x ^= x >> 27; - self.0 = x; - x.wrapping_mul(0x2545_F491_4F6C_DD1D) - } - - pub(crate) fn below(&mut self, n: usize) -> usize { - (self.next() % n as u64) as usize - } - - pub(crate) fn chance(&mut self, pct: usize) -> bool { - self.below(100) < pct - } - - pub(crate) fn pick<'a>(&mut self, items: &[&'a str]) -> &'a str { - items[self.below(items.len())] - } -} - /// Restores permissions a generator stripped before the tempdir is removed /// (declare it AFTER the tempdir so it drops first). Only Unix strips /// permissions; everywhere else the plan is recorded and ignored. diff --git a/crates/socket-patch-core/src/crawlers/python_crawler.rs b/crates/socket-patch-core/src/crawlers/python_crawler.rs index fa6083566..559738b25 100644 --- a/crates/socket-patch-core/src/crawlers/python_crawler.rs +++ b/crates/socket-patch-core/src/crawlers/python_crawler.rs @@ -7946,8 +7946,9 @@ G= use super::super::oracle::{self, LegacyPythonCrawler}; use super::*; use crate::crawlers::oracle_support::{ - fifo, map_rows, mkdir, rows, symlink, write, write_bytes, PermGuard, Rng, + fifo, map_rows, mkdir, rows, symlink, write, write_bytes, PermGuard, }; + use crate::test_rng::Rng; const NAMES: &[&str] = &["requests", "Flask_Cors", "zope.interface", "dup", "Dup"]; const VERSIONS: &[&str] = &["1.0", "2.31.0", "1.0+local", "3.0a1"]; diff --git a/crates/socket-patch-core/src/crawlers/ruby_crawler.rs b/crates/socket-patch-core/src/crawlers/ruby_crawler.rs index f2643b0b5..851ba6485 100644 --- a/crates/socket-patch-core/src/crawlers/ruby_crawler.rs +++ b/crates/socket-patch-core/src/crawlers/ruby_crawler.rs @@ -6241,7 +6241,8 @@ mod tests { #[tokio::test] async fn find_each_by_purl_matches_per_purl_find_by_purls() { - use crate::crawlers::oracle_support::{mkdir, symlink, write, PermGuard, Rng}; + use crate::crawlers::oracle_support::{mkdir, symlink, write, PermGuard}; + use crate::test_rng::Rng; const GEMS: &[&str] = &["rails", "nokogiri", "rack", "rails-html"]; const VERSIONS: &[&str] = &["7.1.0", "1.16.5", "3.0.0"]; diff --git a/crates/socket-patch-core/src/patch/copy_tree.rs b/crates/socket-patch-core/src/patch/copy_tree.rs index 0fefe3244..cc871ffcd 100644 --- a/crates/socket-patch-core/src/patch/copy_tree.rs +++ b/crates/socket-patch-core/src/patch/copy_tree.rs @@ -198,6 +198,7 @@ pub async fn remove_tree(dir: &Path) -> std::io::Result<()> { #[cfg(test)] mod tests { use super::*; + use crate::test_rng::Rng; use std::fs; #[cfg(unix)] @@ -234,23 +235,6 @@ mod tests { .collect() } - /// Deterministic xorshift64* — no `rand` dev-dependency. - struct Rng(u64); - - impl Rng { - fn next(&mut self) -> u64 { - let mut x = self.0; - x ^= x >> 12; - x ^= x << 25; - x ^= x >> 27; - self.0 = x; - x.wrapping_mul(0x2545_F491_4F6C_DD1D) - } - fn below(&mut self, n: usize) -> usize { - (self.next() % n as u64) as usize - } - } - const SKIP: &str = ".cargo-checksum.json"; /// A random tree under `dir`: nested and empty dirs, files (some diff --git a/crates/socket-patch-core/src/patch/redirect/pnpm_equivalence_tests.rs b/crates/socket-patch-core/src/patch/redirect/pnpm_equivalence_tests.rs index d79bc06ba..2d026a253 100644 --- a/crates/socket-patch-core/src/patch/redirect/pnpm_equivalence_tests.rs +++ b/crates/socket-patch-core/src/patch/redirect/pnpm_equivalence_tests.rs @@ -426,7 +426,7 @@ fn indexed_pnpm_rewrite_matches_golden_on_random_lock_sets() { // instead of quietly testing only the plain rewrite path. let mut outcomes: std::collections::BTreeSet = std::collections::BTreeSet::new(); for seed in 1..=300u64 { - let mut rng = Rng(seed.wrapping_mul(0x9E37_79B9_7F4A_7C15) | 1); + let mut rng = Rng::new(seed); let lock_count = 1 + rng.below(3); let mut files = BTreeMap::new(); let mut all: Vec = Vec::new(); diff --git a/crates/socket-patch-core/src/vendor/go_mod_edit.rs b/crates/socket-patch-core/src/vendor/go_mod_edit.rs index b29ab5c10..2e940848f 100644 --- a/crates/socket-patch-core/src/vendor/go_mod_edit.rs +++ b/crates/socket-patch-core/src/vendor/go_mod_edit.rs @@ -2543,13 +2543,8 @@ replace ( /// Random go.mod-grammar text: directive keywords (and near misses), /// block opens/closes (balanced or not), comments, blank lines, CRLF. fn random_go_mod(seed: u64) -> String { - let mut x = seed.wrapping_mul(0x9E37_79B9_7F4A_7C15) | 1; - let mut next = move |n: usize| { - x ^= x >> 12; - x ^= x << 25; - x ^= x >> 27; - (x.wrapping_mul(0x2545_F491_4F6C_DD1D) % n as u64) as usize - }; + let mut rng = crate::test_rng::Rng::new(seed); + let mut next = move |n: usize| rng.below(n); const PIECES: &[&str] = &[ "replace", "require", diff --git a/crates/socket-patch-core/src/vendor/go_sum_edit.rs b/crates/socket-patch-core/src/vendor/go_sum_edit.rs index f70c0b89d..3ac1420f2 100644 --- a/crates/socket-patch-core/src/vendor/go_sum_edit.rs +++ b/crates/socket-patch-core/src/vendor/go_sum_edit.rs @@ -777,13 +777,8 @@ mod tests { #[test] fn lines_form_matches_the_text_form_step_by_step() { for seed in 1..=3000u64 { - let mut x = seed.wrapping_mul(0x9E37_79B9_7F4A_7C15) | 1; - let mut rng = move |n: usize| { - x ^= x >> 12; - x ^= x << 25; - x ^= x >> 27; - (x.wrapping_mul(0x2545_F491_4F6C_DD1D) % n as u64) as usize - }; + let mut r = crate::test_rng::Rng::new(seed); + let mut rng = move |n: usize| r.below(n); let start = random_go_sum(&mut rng); let mut text = start.clone(); let mut editor = GoSumEditor::new(start.clone()); diff --git a/crates/socket-patch-core/src/vex/verify.rs b/crates/socket-patch-core/src/vex/verify.rs index 6893c7175..d5e4a42d7 100644 --- a/crates/socket-patch-core/src/vex/verify.rs +++ b/crates/socket-patch-core/src/vex/verify.rs @@ -2597,7 +2597,8 @@ mod tests { #[tokio::test] async fn judge_installed_record_matches_verify_and_evidence_scan() { - use crate::crawlers::oracle_support::{fifo, mkdir, write, Rng}; + use crate::crawlers::oracle_support::{fifo, mkdir, write}; + use crate::test_rng::Rng; let patched = compute_git_sha256_from_bytes(b"patched"); let upstream = compute_git_sha256_from_bytes(b"upstream");