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 use super::*;
57 use std::collections::HashSet;
58 use tor_guardmgr::TestConfig;
59 use tor_linkspec::RelayIds;
60 use tor_netdir::testnet;
61 use tor_persist::TestingStateMgr;
62
63 #[test]
64 fn dirpath() {
65 tor_rtcompat::test_with_all_runtimes!(|rt| async move {
66 let netdir = testnet::construct_netdir().unwrap_if_sufficient().unwrap();
67 let statemgr = TestingStateMgr::new();
68 let guards =
69 tor_guardmgr::GuardMgr::new(rt.clone(), statemgr, &TestConfig::default()).unwrap();
70 guards.install_test_netdir(&netdir);
71
72 let mut distinct_guards = HashSet::new();
73
74 for _ in 0..40 {
77 let (path, mon, usable) = DirPathBuilder::new().pick_path(&guards).unwrap();
78 if let crate::path::TorPathInner::OwnedOneHop(relay) = path.inner {
79 distinct_guards.insert(RelayIds::from_relay_ids(&relay));
80 mon.succeeded();
81 assert!(usable.await.unwrap());
82 } else {
83 panic!("Generated the wrong kind of path.");
84 }
85 }
86 assert_eq!(
87 distinct_guards.len(),
88 netdir.params().guard_dir_use_parallelism.get() as usize
89 );
90 });
91 }
92}