protover.rs 14 KB

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