Skip to main content

tor_netdoc/
testdata_live.rs

1//! Test data, downloaded from the live network, and filtered to reduce its size
2//!
3//! The parsed forms obtained by [`netstatus_plain()`] etc.
4//! have retained unknown values iff the `retain-unknown` cargo feature is enabled.
5
6use paste::paste;
7
8use crate::doc::microdesc::Microdesc;
9use crate::doc::netstatus;
10use crate::doc::routerdesc::{RouterDesc, RouterDescUnverified};
11use crate::parse2::{NetdocParseable, NetdocParseableUnverified};
12use crate::test_support::parse_test_document;
13
14#[macro_use]
15#[path = "../testdata-live/generated_consts.rs"]
16#[rustfmt::skip] // shell script output is nice, but not 100% identical to rustfmt
17mod generated_consts;
18
19pub use generated_consts::*;
20
21/// Three test data file contents', one per variety
22#[derive(Clone, Debug)]
23#[non_exhaustive]
24pub struct PerVariety {
25    /// Plain consensus
26    pub plain: &'static str,
27
28    /// Microdescriptor consensus
29    pub md: &'static str,
30
31    /// Vote
32    pub vote: &'static str,
33}
34
35/// Test data for one (selected) relay
36#[derive(Clone, Debug)]
37#[non_exhaustive]
38pub struct PerRelay {
39    /// Nickname
40    pub nick: &'static str,
41
42    /// Data for this relay
43    pub data: PerVariety,
44}
45
46// ---------- parsed documents ----------
47
48/// Relay-specific parsed test document or fragment
49///
50/// Used for routerstatus entries in network statuses, and also
51/// relay descriptors and microdescriptors.
52#[derive(Debug, Clone, Copy)]
53#[non_exhaustive]
54pub struct RelayDocument<D: 'static> {
55    /// Nickname
56    pub nick: &'static str,
57
58    /// Actual document
59    pub doc: &'static D,
60}
61
62/// Parse and yield a `Vec<RelayDocument<_>>`
63fn relay_documents<D, S>(inputs: &[PerRelay], selector: S) -> Vec<RelayDocument<D>>
64where
65    D: NetdocParseable + Sync,
66    S: Fn(&PerVariety) -> &'static str,
67{
68    inputs
69        .iter()
70        .map(|relay| RelayDocument {
71            nick: relay.nick,
72            doc: parse_test_document::<D>(selector(&relay.data)),
73        })
74        // We don't memoise the Vec; it has only about 5 elements of 3 words each
75        .collect()
76}
77
78/// Turn a `Vec<RelayDocument<FooUnverified>>` into a `Vec<RelayDocument<Foo>>`
79fn unwrap_bodies<U>(u: Vec<RelayDocument<U>>) -> Vec<RelayDocument<U::Body>>
80where
81    U: NetdocParseableUnverified,
82{
83    u.into_iter()
84        .map(|rd| RelayDocument {
85            nick: rd.nick,
86            doc: rd.doc.inspect_unverified().0,
87        })
88        .collect()
89}
90
91/// Define `netstatus_V`, `netstatus_V_unverified` and `relay_routerstatuses_V`
92//
93// We could use the per variety macros but that seems even more confusing
94macro_rules! netstatus_variety { { $v:ident } => { paste!{
95    /// Parsed network status, in unverified form
96    pub fn [<netstatus_ $v _unverified>]() -> &'static netstatus::$v::NetworkStatusUnverified {
97        parse_test_document(NETSTATUS.$v)
98    }
99    /// Parsed network status
100    pub fn [<netstatus_ $v>]() -> &'static netstatus::$v::NetworkStatus {
101        [<netstatus_ $v _unverified>]().inspect_unverified().0
102    }
103    /// Parsed routerstatus entries
104    pub fn [<relay_routerstatuses_ $v>]() -> Vec<RelayDocument<netstatus::$v::RouterStatus>> {
105        relay_documents(RELAY_ROUTERSTATUSES, |relay| relay.$v)
106    }
107} } }
108
109netstatus_variety! { plain }
110netstatus_variety! { md }
111netstatus_variety! { vote }
112
113/// Router descriptors (as listed in the consensus)
114pub fn relay_routerdescs() -> Vec<RelayDocument<RouterDesc>> {
115    unwrap_bodies(relay_routerdescs_unverified())
116}
117/// Router descriptors (as listed in the consensus), in unverified form
118pub fn relay_routerdescs_unverified() -> Vec<RelayDocument<RouterDescUnverified>> {
119    relay_documents(RELAY_DESCRIPTORS, |relay| relay.plain)
120}
121/// Router descriptors (as listed in the vote)
122pub fn relay_routerdescs_vote() -> Vec<RelayDocument<RouterDesc>> {
123    unwrap_bodies(relay_routerdescs_vote_unverified())
124}
125/// Router descriptors (as listed in the consensus), in unverified form
126pub fn relay_routerdescs_vote_unverified() -> Vec<RelayDocument<RouterDescUnverified>> {
127    relay_documents(RELAY_DESCRIPTORS, |relay| relay.vote)
128}
129/// Microdescriptors as listed in the consensus
130// Microdescs aren't signed so there is no relay_microdescs_unverified
131pub fn relay_microdescs() -> Vec<RelayDocument<Microdesc>> {
132    relay_documents(RELAY_DESCRIPTORS, |relay| relay.md)
133}
134
135/// Find a particular relay's document, given the relay's nickname
136///
137/// This is sound for `testdata_live` data, because we only have a small curated
138/// subset of of relays, all of which have distinct nicks.
139///
140/// # Panics
141///
142/// Panics if no relay with the given name is found.
143///
144/// # Example
145///
146/// ```
147/// use tor_netdoc::doc::microdesc::Microdesc;
148/// use tor_netdoc::testdata_live::{relay_document_by_nick, relay_microdescs};
149///
150/// let _: &'static Microdesc = relay_document_by_nick("lisdex", &relay_microdescs());
151/// ```
152pub fn relay_document_by_nick<D>(nick: &str, docs: &[RelayDocument<D>]) -> &'static D {
153    docs.iter().find(|d| d.nick == nick).expect(nick).doc
154}
155
156#[test]
157fn test_all() {
158    netstatus_plain();
159    netstatus_md();
160    netstatus_vote();
161
162    netstatus_plain_unverified();
163    netstatus_md_unverified();
164    netstatus_vote_unverified();
165
166    relay_routerstatuses_plain();
167    relay_routerstatuses_md();
168    relay_routerstatuses_vote();
169
170    relay_routerdescs();
171    relay_routerdescs_unverified();
172
173    relay_routerdescs_vote();
174    relay_routerdescs_vote_unverified();
175
176    relay_microdescs();
177}