tor_circmgr/path/
dirpath.rs1use super::TorPath;
3use crate::Result;
4use tor_guardmgr::{GuardMgr, GuardMonitor, GuardUsable};
5use tor_rtcompat::Runtime;
6use tracing::instrument;
7
8#[non_exhaustive]
10pub(crate) struct DirPathBuilder {}
11
12impl Default for DirPathBuilder {
13 fn default() -> Self {
14 Self::new()
15 }
16}
17
18impl DirPathBuilder {
19 pub(crate) fn new() -> Self {
21 DirPathBuilder {}
22 }
23
24 #[instrument(skip_all, level = "trace")]
27 pub(crate) fn pick_path<'a, RT: Runtime>(
28 &self,
29 guards: &GuardMgr<RT>,
30 ) -> Result<(TorPath<'a>, GuardMonitor, GuardUsable)> {
31 let guard_usage = tor_guardmgr::GuardUsageBuilder::default()
32 .kind(tor_guardmgr::GuardUsageKind::OneHopDirectory)
33 .build()
34 .expect("Unable to build directory guard usage");
35 let (guard, mon, usable) = guards.select_guard(guard_usage)?;
36 Ok((TorPath::new_one_hop_owned(&guard), mon, usable))
37 }
38}
39
40#[cfg(test)]
41mod test {
42 #![allow(clippy::bool_assert_comparison)]
44 #![allow(clippy::clone_on_copy)]
45 #![allow(clippy::dbg_macro)]
46 #![allow(clippy::mixed_attributes_style)]
47 #![allow(clippy::print_stderr)]
48 #![allow(clippy::print_stdout)]
49 #![allow(clippy::single_char_pattern)]
50 #![allow(clippy::unwrap_used)]
51 #![allow(clippy::unchecked_time_subtraction)]
52 #![allow(clippy::useless_vec)]
53 #![allow(clippy::needless_pass_by_value)]
54 #![allow(clippy::string_slice)] use super::*;
58 use std::collections::HashSet;
59 use tor_guardmgr::TestConfig;
60 use tor_linkspec::RelayIds;
61 use tor_netdir::testnet;
62 use tor_persist::TestingStateMgr;
63
64 #[test]
65 fn dirpath() {
66 tor_rtcompat::test_with_all_runtimes!(|rt| async move {
67 let netdir = testnet::construct_netdir().unwrap_if_sufficient().unwrap();
68 let statemgr = TestingStateMgr::new();
69 let guards =
70 tor_guardmgr::GuardMgr::new(rt.clone(), statemgr, &TestConfig::default()).unwrap();
71 guards.install_test_netdir(&netdir);
72
73 let mut distinct_guards = HashSet::new();
74
75 for _ in 0..40 {
78 let (path, mon, usable) = DirPathBuilder::new().pick_path(&guards).unwrap();
79 if let crate::path::TorPathInner::OwnedOneHop(relay) = path.inner {
80 distinct_guards.insert(RelayIds::from_relay_ids(&relay));
81 mon.succeeded();
82 assert!(usable.await.unwrap());
83 } else {
84 panic!("Generated the wrong kind of path.");
85 }
86 }
87 assert_eq!(
88 distinct_guards.len(),
89 netdir.params().guard_dir_use_parallelism.get() as usize
90 );
91 });
92 }
93}