1 // Copyright (c) 2016-2019, The Tor Project, Inc. */
2 // See LICENSE for licensing information */
3 
4 extern crate protover;
5 
6 use protover::errors::ProtoverError;
7 use protover::ProtoEntry;
8 use protover::ProtoverVote;
9 use protover::UnvalidatedProtoEntry;
10 
11 #[test]
parse_protocol_with_single_proto_and_single_version()12 fn parse_protocol_with_single_proto_and_single_version() {
13     let _: ProtoEntry = "Cons=1".parse().unwrap();
14 }
15 
16 #[test]
parse_protocol_with_single_protocol_and_multiple_versions()17 fn parse_protocol_with_single_protocol_and_multiple_versions() {
18     let _: ProtoEntry = "Cons=1-2".parse().unwrap();
19 }
20 
21 #[test]
parse_protocol_with_different_single_protocol_and_single_version()22 fn parse_protocol_with_different_single_protocol_and_single_version() {
23     let _: ProtoEntry = "HSDir=1".parse().unwrap();
24 }
25 
26 #[test]
parse_protocol_with_single_protocol_and_supported_version()27 fn parse_protocol_with_single_protocol_and_supported_version() {
28     let _: ProtoEntry = "Desc=2".parse().unwrap();
29 }
30 
31 #[test]
parse_protocol_with_two_protocols_and_single_version()32 fn parse_protocol_with_two_protocols_and_single_version() {
33     let _: ProtoEntry = "Cons=1 HSDir=1".parse().unwrap();
34 }
35 
36 #[test]
parse_protocol_with_single_protocol_and_two_sequential_versions()37 fn parse_protocol_with_single_protocol_and_two_sequential_versions() {
38     let _: ProtoEntry = "Desc=1-2".parse().unwrap();
39 }
40 
41 #[test]
parse_protocol_with_single_protocol_and_protocol_range()42 fn parse_protocol_with_single_protocol_and_protocol_range() {
43     let _: ProtoEntry = "Link=1-4".parse().unwrap();
44 }
45 
46 #[test]
parse_protocol_with_single_protocol_and_protocol_set()47 fn parse_protocol_with_single_protocol_and_protocol_set() {
48     let _: ProtoEntry = "Link=3-4 Desc=2".parse().unwrap();
49 }
50 
51 #[test]
protocol_all_supported_with_single_protocol_and_protocol_set()52 fn protocol_all_supported_with_single_protocol_and_protocol_set() {
53     let protocols: UnvalidatedProtoEntry = "Link=3-4 Desc=2".parse().unwrap();
54     let unsupported: Option<UnvalidatedProtoEntry> = protocols.all_supported();
55     assert_eq!(true, unsupported.is_none());
56 }
57 
58 #[test]
protocol_all_supported_with_two_values()59 fn protocol_all_supported_with_two_values() {
60     let protocols: UnvalidatedProtoEntry = "Microdesc=1-2 Relay=2".parse().unwrap();
61     let unsupported: Option<UnvalidatedProtoEntry> = protocols.all_supported();
62     assert_eq!(true, unsupported.is_none());
63 }
64 
65 #[test]
protocol_all_supported_with_one_value()66 fn protocol_all_supported_with_one_value() {
67     let protocols: UnvalidatedProtoEntry = "Microdesc=1-2".parse().unwrap();
68     let unsupported: Option<UnvalidatedProtoEntry> = protocols.all_supported();
69     assert_eq!(true, unsupported.is_none());
70 }
71 
72 #[test]
protocol_all_supported_with_three_values()73 fn protocol_all_supported_with_three_values() {
74     let protocols: UnvalidatedProtoEntry = "LinkAuth=1 Microdesc=1-2 Relay=2".parse().unwrap();
75     let unsupported: Option<UnvalidatedProtoEntry> = protocols.all_supported();
76     assert_eq!(true, unsupported.is_none());
77 }
78 
79 #[test]
protocol_all_supported_with_unsupported_protocol()80 fn protocol_all_supported_with_unsupported_protocol() {
81     let protocols: UnvalidatedProtoEntry = "Wombat=9".parse().unwrap();
82     let unsupported: Option<UnvalidatedProtoEntry> = protocols.all_supported();
83     assert_eq!(true, unsupported.is_some());
84     assert_eq!("Wombat=9", &unsupported.unwrap().to_string());
85 }
86 
87 #[test]
protocol_all_supported_with_unsupported_versions()88 fn protocol_all_supported_with_unsupported_versions() {
89     let protocols: UnvalidatedProtoEntry = "Link=3-63".parse().unwrap();
90     let unsupported: Option<UnvalidatedProtoEntry> = protocols.all_supported();
91     assert_eq!(true, unsupported.is_some());
92     assert_eq!("Link=6-63", &unsupported.unwrap().to_string());
93 }
94 
95 #[test]
protocol_all_supported_with_unsupported_low_version()96 fn protocol_all_supported_with_unsupported_low_version() {
97     let protocols: UnvalidatedProtoEntry = "HSIntro=2-3".parse().unwrap();
98     let unsupported: Option<UnvalidatedProtoEntry> = protocols.all_supported();
99     assert_eq!(true, unsupported.is_some());
100     assert_eq!("HSIntro=2", &unsupported.unwrap().to_string());
101 }
102 
103 #[test]
protocol_all_supported_with_unsupported_high_version()104 fn protocol_all_supported_with_unsupported_high_version() {
105     let protocols: UnvalidatedProtoEntry = "Cons=1-2,60".parse().unwrap();
106     let unsupported: Option<UnvalidatedProtoEntry> = protocols.all_supported();
107     assert_eq!(true, unsupported.is_some());
108     assert_eq!("Cons=60", &unsupported.unwrap().to_string());
109 }
110 
111 #[test]
protocol_all_supported_with_mix_of_supported_and_unsupproted()112 fn protocol_all_supported_with_mix_of_supported_and_unsupproted() {
113     let protocols: UnvalidatedProtoEntry = "Link=3-4 Wombat=9".parse().unwrap();
114     let unsupported: Option<UnvalidatedProtoEntry> = protocols.all_supported();
115     assert_eq!(true, unsupported.is_some());
116     assert_eq!("Wombat=9", &unsupported.unwrap().to_string());
117 }
118 
119 #[test]
protover_string_supports_protocol_returns_true_for_single_supported()120 fn protover_string_supports_protocol_returns_true_for_single_supported() {
121     let protocols: UnvalidatedProtoEntry = "Link=3-4 Cons=1".parse().unwrap();
122     let is_supported = protocols.supports_protocol(&protover::Protocol::Cons.into(), &1);
123     assert_eq!(true, is_supported);
124 }
125 
126 #[test]
protover_string_supports_protocol_returns_false_for_single_unsupported()127 fn protover_string_supports_protocol_returns_false_for_single_unsupported() {
128     let protocols: UnvalidatedProtoEntry = "Link=3-4 Cons=1".parse().unwrap();
129     let is_supported = protocols.supports_protocol(&protover::Protocol::Cons.into(), &2);
130     assert_eq!(false, is_supported);
131 }
132 
133 #[test]
protover_string_supports_protocol_returns_false_for_unsupported()134 fn protover_string_supports_protocol_returns_false_for_unsupported() {
135     let protocols: UnvalidatedProtoEntry = "Link=3-4".parse().unwrap();
136     let is_supported = protocols.supports_protocol(&protover::Protocol::Cons.into(), &2);
137     assert_eq!(false, is_supported);
138 }
139 
140 #[test]
141 #[should_panic]
parse_protocol_with_unexpected_characters()142 fn parse_protocol_with_unexpected_characters() {
143     let _: UnvalidatedProtoEntry = "Cons=*-%".parse().unwrap();
144 }
145 
146 #[test]
protover_compute_vote_returns_empty_for_empty_string()147 fn protover_compute_vote_returns_empty_for_empty_string() {
148     let protocols: &[UnvalidatedProtoEntry] = &["".parse().unwrap()];
149     let listed = ProtoverVote::compute(protocols, &1);
150     assert_eq!("", listed.to_string());
151 }
152 
153 #[test]
protover_compute_vote_returns_single_protocol_for_matching()154 fn protover_compute_vote_returns_single_protocol_for_matching() {
155     let protocols: &[UnvalidatedProtoEntry] = &["Cons=1".parse().unwrap()];
156     let listed = ProtoverVote::compute(protocols, &1);
157     assert_eq!("Cons=1", listed.to_string());
158 }
159 
160 #[test]
protover_compute_vote_returns_two_protocols_for_two_matching()161 fn protover_compute_vote_returns_two_protocols_for_two_matching() {
162     let protocols: &[UnvalidatedProtoEntry] = &["Link=1 Cons=1".parse().unwrap()];
163     let listed = ProtoverVote::compute(protocols, &1);
164     assert_eq!("Cons=1 Link=1", listed.to_string());
165 }
166 
167 #[test]
protover_compute_vote_returns_one_protocol_when_one_out_of_two_matches()168 fn protover_compute_vote_returns_one_protocol_when_one_out_of_two_matches() {
169     let protocols: &[UnvalidatedProtoEntry] =
170         &["Cons=1 Link=2".parse().unwrap(), "Cons=1".parse().unwrap()];
171     let listed = ProtoverVote::compute(protocols, &2);
172     assert_eq!("Cons=1", listed.to_string());
173 }
174 
175 #[test]
protover_compute_vote_returns_protocols_that_it_doesnt_currently_support()176 fn protover_compute_vote_returns_protocols_that_it_doesnt_currently_support() {
177     let protocols: &[UnvalidatedProtoEntry] =
178         &["Foo=1 Cons=2".parse().unwrap(), "Bar=1".parse().unwrap()];
179     let listed = ProtoverVote::compute(protocols, &1);
180     assert_eq!("Bar=1 Cons=2 Foo=1", listed.to_string());
181 }
182 
183 #[test]
protover_compute_vote_returns_matching_for_mix()184 fn protover_compute_vote_returns_matching_for_mix() {
185     let protocols: &[UnvalidatedProtoEntry] = &["Link=1-10,50 Cons=1,3-7,8".parse().unwrap()];
186     let listed = ProtoverVote::compute(protocols, &1);
187     assert_eq!("Cons=1,3-8 Link=1-10,50", listed.to_string());
188 }
189 
190 #[test]
protover_compute_vote_returns_matching_for_longer_mix()191 fn protover_compute_vote_returns_matching_for_longer_mix() {
192     let protocols: &[UnvalidatedProtoEntry] = &[
193         "Desc=1-10,50 Cons=1,3-7,8".parse().unwrap(),
194         "Link=12-45,8 Cons=2-6,8 Desc=9".parse().unwrap(),
195     ];
196 
197     let listed = ProtoverVote::compute(protocols, &1);
198     assert_eq!("Cons=1-8 Desc=1-10,50 Link=8,12-45", listed.to_string());
199 }
200 
201 #[test]
protover_compute_vote_returns_matching_for_longer_mix_with_threshold_two()202 fn protover_compute_vote_returns_matching_for_longer_mix_with_threshold_two() {
203     let protocols: &[UnvalidatedProtoEntry] = &[
204         "Desc=1-10,50 Cons=1,3-7,8".parse().unwrap(),
205         "Link=8,12-45 Cons=2-6,8 Desc=9".parse().unwrap(),
206     ];
207 
208     let listed = ProtoverVote::compute(protocols, &2);
209     assert_eq!("Cons=3-6,8 Desc=9", listed.to_string());
210 }
211 
212 #[test]
protover_compute_vote_handles_duplicated_versions()213 fn protover_compute_vote_handles_duplicated_versions() {
214     let protocols: &[UnvalidatedProtoEntry] =
215         &["Cons=1".parse().unwrap(), "Cons=1".parse().unwrap()];
216     assert_eq!("Cons=1", ProtoverVote::compute(protocols, &2).to_string());
217 
218     let protocols: &[UnvalidatedProtoEntry] =
219         &["Cons=1-2".parse().unwrap(), "Cons=1-2".parse().unwrap()];
220     assert_eq!("Cons=1-2", ProtoverVote::compute(protocols, &2).to_string());
221 }
222 
223 #[test]
protover_compute_vote_handles_invalid_proto_entries()224 fn protover_compute_vote_handles_invalid_proto_entries() {
225     let protocols: &[UnvalidatedProtoEntry] = &[
226         "Cons=1".parse().unwrap(),
227         "Cons=1".parse().unwrap(),
228         "Dinosaur=1".parse().unwrap(),
229     ];
230     assert_eq!("Cons=1", ProtoverVote::compute(protocols, &2).to_string());
231 }
232 
233 #[test]
parse_protocol_with_single_protocol_and_two_nonsequential_versions()234 fn parse_protocol_with_single_protocol_and_two_nonsequential_versions() {
235     let _: ProtoEntry = "Desc=1,2".parse().unwrap();
236 }
237 
238 #[test]
protover_is_supported_here_returns_true_for_supported_protocol()239 fn protover_is_supported_here_returns_true_for_supported_protocol() {
240     assert_eq!(
241         true,
242         protover::is_supported_here(&protover::Protocol::Cons, &1)
243     );
244 }
245 
246 #[test]
protover_is_supported_here_returns_false_for_unsupported_protocol()247 fn protover_is_supported_here_returns_false_for_unsupported_protocol() {
248     assert_eq!(
249         false,
250         protover::is_supported_here(&protover::Protocol::Cons, &5)
251     );
252 }
253 
254 #[test]
protocol_all_supported_with_single_proto_and_single_version()255 fn protocol_all_supported_with_single_proto_and_single_version() {
256     let protocol: UnvalidatedProtoEntry = "Cons=1".parse().unwrap();
257     let unsupported: Option<UnvalidatedProtoEntry> = protocol.all_supported();
258     assert_eq!(true, unsupported.is_none());
259 }
260 
261 #[test]
protocol_all_supported_with_single_protocol_and_multiple_versions()262 fn protocol_all_supported_with_single_protocol_and_multiple_versions() {
263     let protocol: UnvalidatedProtoEntry = "Cons=1-2".parse().unwrap();
264     let unsupported: Option<UnvalidatedProtoEntry> = protocol.all_supported();
265     assert_eq!(true, unsupported.is_none());
266 }
267 
268 #[test]
protocol_all_supported_with_different_single_protocol_and_single_version()269 fn protocol_all_supported_with_different_single_protocol_and_single_version() {
270     let protocol: UnvalidatedProtoEntry = "HSDir=1".parse().unwrap();
271     let unsupported: Option<UnvalidatedProtoEntry> = protocol.all_supported();
272     assert_eq!(true, unsupported.is_none());
273 }
274 
275 #[test]
protocol_all_supported_with_single_protocol_and_supported_version()276 fn protocol_all_supported_with_single_protocol_and_supported_version() {
277     let protocol: UnvalidatedProtoEntry = "Desc=2".parse().unwrap();
278     let unsupported: Option<UnvalidatedProtoEntry> = protocol.all_supported();
279     assert_eq!(true, unsupported.is_none());
280 }
281 
282 #[test]
protocol_all_supported_with_two_protocols_and_single_version()283 fn protocol_all_supported_with_two_protocols_and_single_version() {
284     let protocols: UnvalidatedProtoEntry = "Cons=1 HSDir=1".parse().unwrap();
285     let unsupported: Option<UnvalidatedProtoEntry> = protocols.all_supported();
286     assert_eq!(true, unsupported.is_none());
287 }
288 
289 #[test]
protocol_all_supported_with_single_protocol_and_two_nonsequential_versions()290 fn protocol_all_supported_with_single_protocol_and_two_nonsequential_versions() {
291     let protocol: UnvalidatedProtoEntry = "Desc=1,2".parse().unwrap();
292     let unsupported: Option<UnvalidatedProtoEntry> = protocol.all_supported();
293     assert_eq!(true, unsupported.is_none());
294 }
295 
296 #[test]
protocol_all_supported_with_single_protocol_and_two_sequential_versions()297 fn protocol_all_supported_with_single_protocol_and_two_sequential_versions() {
298     let protocol: UnvalidatedProtoEntry = "Desc=1-2".parse().unwrap();
299     let unsupported: Option<UnvalidatedProtoEntry> = protocol.all_supported();
300     assert_eq!(true, unsupported.is_none());
301 }
302 
303 #[test]
protocol_all_supported_with_single_protocol_and_protocol_range()304 fn protocol_all_supported_with_single_protocol_and_protocol_range() {
305     let protocol: UnvalidatedProtoEntry = "Link=1-4".parse().unwrap();
306     let unsupported: Option<UnvalidatedProtoEntry> = protocol.all_supported();
307     assert_eq!(true, unsupported.is_none());
308 }
309 
310 #[test]
protover_all_supported_should_exclude_versions_we_actually_do_support()311 fn protover_all_supported_should_exclude_versions_we_actually_do_support() {
312     let proto: UnvalidatedProtoEntry = "Link=3-63".parse().unwrap();
313     let result: String = proto.all_supported().unwrap().to_string();
314 
315     assert_eq!(result, "Link=6-63".to_string());
316 }
317 
318 #[test]
protover_all_supported_should_exclude_versions_we_actually_do_support_complex1()319 fn protover_all_supported_should_exclude_versions_we_actually_do_support_complex1() {
320     let proto: UnvalidatedProtoEntry = "Link=1-3,30-63".parse().unwrap();
321     let result: String = proto.all_supported().unwrap().to_string();
322 
323     assert_eq!(result, "Link=30-63".to_string());
324 }
325 
326 #[test]
protover_all_supported_should_exclude_versions_we_actually_do_support_complex2()327 fn protover_all_supported_should_exclude_versions_we_actually_do_support_complex2() {
328     let proto: UnvalidatedProtoEntry = "Link=1-3,5-12".parse().unwrap();
329     let result: String = proto.all_supported().unwrap().to_string();
330 
331     assert_eq!(result, "Link=6-12".to_string());
332 }
333 
334 #[test]
protover_all_supported_should_exclude_some_versions_and_entire_protocols()335 fn protover_all_supported_should_exclude_some_versions_and_entire_protocols() {
336     let proto: UnvalidatedProtoEntry = "Link=1-3,5-12 Quokka=50-51".parse().unwrap();
337     let result: String = proto.all_supported().unwrap().to_string();
338 
339     assert_eq!(result, "Link=6-12 Quokka=50-51".to_string());
340 }
341 
342 #[test]
343 // C_RUST_DIFFERS: The C will return true (e.g. saying "yes, that's supported")
344 // but set the msg to NULL (??? seems maybe potentially bad).  The Rust will
345 // simply return a None.
protover_all_supported_should_return_empty_string_for_weird_thing()346 fn protover_all_supported_should_return_empty_string_for_weird_thing() {
347     let proto: UnvalidatedProtoEntry = "Fribble=".parse().unwrap();
348     let result: Option<UnvalidatedProtoEntry> = proto.all_supported();
349 
350     assert!(result.is_none());
351 }
352 
353 #[test]
protover_unvalidatedprotoentry_should_err_entirely_unparseable_things()354 fn protover_unvalidatedprotoentry_should_err_entirely_unparseable_things() {
355     let proto: Result<UnvalidatedProtoEntry, ProtoverError> = "Fribble".parse();
356 
357     assert_eq!(Err(ProtoverError::Unparseable), proto);
358 }
359 
360 #[test]
protover_all_supported_over_maximum_limit()361 fn protover_all_supported_over_maximum_limit() {
362     let proto: Result<UnvalidatedProtoEntry, ProtoverError> = "Sleen=1-4294967295".parse();
363 
364     assert_eq!(Err(ProtoverError::ExceedsMax), proto);
365 }
366