Loading crates/tor-guardmgr/src/guard.rs +6 −0 Original line number Diff line number Diff line Loading @@ -660,6 +660,12 @@ impl Guard { orports: self.orports.clone(), } } /// Testing only: Return true if this guard was ever contacted successfully. #[cfg(test)] pub(crate) fn confirmed(&self) -> bool { self.confirmed_at.is_some() } } impl tor_linkspec::ChanTarget for Guard { Loading crates/tor-guardmgr/src/sample.rs +59 −0 Original line number Diff line number Diff line Loading @@ -1263,4 +1263,63 @@ mod test { assert_eq!(guards.missing_primary_microdescriptors(&netdir2), 1); } #[test] fn copy_status() { let netdir = netdir(); let params = GuardParams { min_filtered_sample_size: 5, n_primary: 2, max_sample_bw_fraction: 1.0, ..GuardParams::default() }; let mut guards1 = GuardSet::default(); guards1.extend_sample_as_needed(SystemTime::now(), ¶ms, &netdir); guards1.select_primary_guards(¶ms); let mut guards2 = guards1.clone(); // Make a persistent change in guards1, and a different persistent change in guards2. let id1 = guards1.primary[0].clone(); let id2 = guards1.primary[1].clone(); guards1.record_success(&id1, ¶ms, None, SystemTime::now()); guards2.record_success(&id2, ¶ms, None, SystemTime::now()); // Make a non-persistent change in guards2. guards2.record_failure(&id2, None, Instant::now()); // Copy status: make sure non-persistent status changed, and persistent didn't. guards1.copy_status_from(guards2); { let g1 = guards1.get(&id1).unwrap(); let g2 = guards1.get(&id2).unwrap(); assert!(g1.confirmed()); assert!(!g2.confirmed()); assert_eq!(g1.reachable(), Reachable::Unknown); assert_eq!(g2.reachable(), Reachable::Unreachable); } // Now make a new set of unrelated guards, and make sure that copying // from it doesn't change the membership of guards1. let mut guards3 = GuardSet::default(); let g1_set: HashSet<_> = guards1.guards.keys().map(Clone::clone).collect(); let mut g3_set: HashSet<_> = HashSet::new(); for _ in 0..4 { // There is roughly a 1-in-5000 chance of getting the same set // twice, so we loop until that doesn't happen. guards3.extend_sample_as_needed(SystemTime::now(), ¶ms, &netdir); guards3.select_primary_guards(¶ms); g3_set = guards3.guards.keys().map(Clone::clone).collect(); // There is roughly a 1-in-5000 chance of getting the same set twice, so if g1_set == g3_set { guards3 = GuardSet::default(); continue; } break; } assert_ne!(g1_set, g3_set); // Do the copy; make sure that the membership is unchanged. guards1.copy_status_from(guards3); let g1_set_new: HashSet<_> = guards1.guards.keys().map(Clone::clone).collect(); assert_eq!(g1_set, g1_set_new); } } Loading
crates/tor-guardmgr/src/guard.rs +6 −0 Original line number Diff line number Diff line Loading @@ -660,6 +660,12 @@ impl Guard { orports: self.orports.clone(), } } /// Testing only: Return true if this guard was ever contacted successfully. #[cfg(test)] pub(crate) fn confirmed(&self) -> bool { self.confirmed_at.is_some() } } impl tor_linkspec::ChanTarget for Guard { Loading
crates/tor-guardmgr/src/sample.rs +59 −0 Original line number Diff line number Diff line Loading @@ -1263,4 +1263,63 @@ mod test { assert_eq!(guards.missing_primary_microdescriptors(&netdir2), 1); } #[test] fn copy_status() { let netdir = netdir(); let params = GuardParams { min_filtered_sample_size: 5, n_primary: 2, max_sample_bw_fraction: 1.0, ..GuardParams::default() }; let mut guards1 = GuardSet::default(); guards1.extend_sample_as_needed(SystemTime::now(), ¶ms, &netdir); guards1.select_primary_guards(¶ms); let mut guards2 = guards1.clone(); // Make a persistent change in guards1, and a different persistent change in guards2. let id1 = guards1.primary[0].clone(); let id2 = guards1.primary[1].clone(); guards1.record_success(&id1, ¶ms, None, SystemTime::now()); guards2.record_success(&id2, ¶ms, None, SystemTime::now()); // Make a non-persistent change in guards2. guards2.record_failure(&id2, None, Instant::now()); // Copy status: make sure non-persistent status changed, and persistent didn't. guards1.copy_status_from(guards2); { let g1 = guards1.get(&id1).unwrap(); let g2 = guards1.get(&id2).unwrap(); assert!(g1.confirmed()); assert!(!g2.confirmed()); assert_eq!(g1.reachable(), Reachable::Unknown); assert_eq!(g2.reachable(), Reachable::Unreachable); } // Now make a new set of unrelated guards, and make sure that copying // from it doesn't change the membership of guards1. let mut guards3 = GuardSet::default(); let g1_set: HashSet<_> = guards1.guards.keys().map(Clone::clone).collect(); let mut g3_set: HashSet<_> = HashSet::new(); for _ in 0..4 { // There is roughly a 1-in-5000 chance of getting the same set // twice, so we loop until that doesn't happen. guards3.extend_sample_as_needed(SystemTime::now(), ¶ms, &netdir); guards3.select_primary_guards(¶ms); g3_set = guards3.guards.keys().map(Clone::clone).collect(); // There is roughly a 1-in-5000 chance of getting the same set twice, so if g1_set == g3_set { guards3 = GuardSet::default(); continue; } break; } assert_ne!(g1_set, g3_set); // Do the copy; make sure that the membership is unchanged. guards1.copy_status_from(guards3); let g1_set_new: HashSet<_> = guards1.guards.keys().map(Clone::clone).collect(); assert_eq!(g1_set, g1_set_new); } }