protover.rs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. // Copyright (c) 2016-2018, The Tor Project, Inc. */
  2. // See LICENSE for licensing information */
  3. extern crate protover;
  4. use protover::ProtoEntry;
  5. use protover::ProtoverVote;
  6. use protover::UnvalidatedProtoEntry;
  7. use protover::errors::ProtoverError;
  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] = &["Cons=1 Link=2".parse().unwrap(), "Cons=1".parse().unwrap()];
  154. let listed = ProtoverVote::compute(protocols, &2);
  155. assert_eq!("Cons=1", listed.to_string());
  156. }
  157. #[test]
  158. fn protover_compute_vote_returns_protocols_that_it_doesnt_currently_support() {
  159. let protocols: &[UnvalidatedProtoEntry] = &["Foo=1 Cons=2".parse().unwrap(), "Bar=1".parse().unwrap()];
  160. let listed = ProtoverVote::compute(protocols, &1);
  161. assert_eq!("Bar=1 Cons=2 Foo=1", listed.to_string());
  162. }
  163. #[test]
  164. fn protover_compute_vote_returns_matching_for_mix() {
  165. let protocols: &[UnvalidatedProtoEntry] = &["Link=1-10,500 Cons=1,3-7,8".parse().unwrap()];
  166. let listed = ProtoverVote::compute(protocols, &1);
  167. assert_eq!("Cons=1,3-8 Link=1-10,500", listed.to_string());
  168. }
  169. #[test]
  170. fn protover_compute_vote_returns_matching_for_longer_mix() {
  171. let protocols: &[UnvalidatedProtoEntry] = &[
  172. "Desc=1-10,500 Cons=1,3-7,8".parse().unwrap(),
  173. "Link=123-456,78 Cons=2-6,8 Desc=9".parse().unwrap(),
  174. ];
  175. let listed = ProtoverVote::compute(protocols, &1);
  176. assert_eq!("Cons=1-8 Desc=1-10,500 Link=78,123-456", listed.to_string());
  177. }
  178. #[test]
  179. fn protover_compute_vote_returns_matching_for_longer_mix_with_threshold_two() {
  180. let protocols: &[UnvalidatedProtoEntry] = &[
  181. "Desc=1-10,500 Cons=1,3-7,8".parse().unwrap(),
  182. "Link=123-456,78 Cons=2-6,8 Desc=9".parse().unwrap(),
  183. ];
  184. let listed = ProtoverVote::compute(protocols, &2);
  185. assert_eq!("Cons=3-6,8 Desc=9", listed.to_string());
  186. }
  187. #[test]
  188. fn protover_compute_vote_handles_duplicated_versions() {
  189. let protocols: &[UnvalidatedProtoEntry] = &["Cons=1".parse().unwrap(), "Cons=1".parse().unwrap()];
  190. assert_eq!("Cons=1", ProtoverVote::compute(protocols, &2).to_string());
  191. let protocols: &[UnvalidatedProtoEntry] = &["Cons=1-2".parse().unwrap(), "Cons=1-2".parse().unwrap()];
  192. assert_eq!("Cons=1-2", ProtoverVote::compute(protocols, &2).to_string());
  193. }
  194. #[test]
  195. fn protover_compute_vote_handles_invalid_proto_entries() {
  196. let protocols: &[UnvalidatedProtoEntry] = &[
  197. "Cons=1".parse().unwrap(),
  198. "Cons=1".parse().unwrap(),
  199. "Dinosaur=1".parse().unwrap(),
  200. ];
  201. assert_eq!("Cons=1", ProtoverVote::compute(protocols, &2).to_string());
  202. }
  203. #[test]
  204. fn parse_protocol_with_single_protocol_and_two_nonsequential_versions() {
  205. let _: ProtoEntry = "Desc=1,2".parse().unwrap();
  206. }
  207. #[test]
  208. fn protover_is_supported_here_returns_true_for_supported_protocol() {
  209. assert_eq!(true, protover::is_supported_here(&protover::Protocol::Cons, &1));
  210. }
  211. #[test]
  212. fn protover_is_supported_here_returns_false_for_unsupported_protocol() {
  213. assert_eq!(false, protover::is_supported_here(&protover::Protocol::Cons, &5));
  214. }
  215. #[test]
  216. fn protocol_all_supported_with_single_proto_and_single_version() {
  217. let protocol: UnvalidatedProtoEntry = "Cons=1".parse().unwrap();
  218. let unsupported: Option<UnvalidatedProtoEntry> = protocol.all_supported();
  219. assert_eq!(true, unsupported.is_none());
  220. }
  221. #[test]
  222. fn protocol_all_supported_with_single_protocol_and_multiple_versions() {
  223. let protocol: UnvalidatedProtoEntry = "Cons=1-2".parse().unwrap();
  224. let unsupported: Option<UnvalidatedProtoEntry> = protocol.all_supported();
  225. assert_eq!(true, unsupported.is_none());
  226. }
  227. #[test]
  228. fn protocol_all_supported_with_different_single_protocol_and_single_version() {
  229. let protocol: UnvalidatedProtoEntry = "HSDir=1".parse().unwrap();
  230. let unsupported: Option<UnvalidatedProtoEntry> = protocol.all_supported();
  231. assert_eq!(true, unsupported.is_none());
  232. }
  233. #[test]
  234. fn protocol_all_supported_with_single_protocol_and_supported_version() {
  235. let protocol: UnvalidatedProtoEntry = "Desc=2".parse().unwrap();
  236. let unsupported: Option<UnvalidatedProtoEntry> = protocol.all_supported();
  237. assert_eq!(true, unsupported.is_none());
  238. }
  239. #[test]
  240. fn protocol_all_supported_with_two_protocols_and_single_version() {
  241. let protocols: UnvalidatedProtoEntry = "Cons=1 HSDir=1".parse().unwrap();
  242. let unsupported: Option<UnvalidatedProtoEntry> = protocols.all_supported();
  243. assert_eq!(true, unsupported.is_none());
  244. }
  245. #[test]
  246. fn protocol_all_supported_with_single_protocol_and_two_nonsequential_versions() {
  247. let protocol: UnvalidatedProtoEntry = "Desc=1,2".parse().unwrap();
  248. let unsupported: Option<UnvalidatedProtoEntry> = protocol.all_supported();
  249. assert_eq!(true, unsupported.is_none());
  250. }
  251. #[test]
  252. fn protocol_all_supported_with_single_protocol_and_two_sequential_versions() {
  253. let protocol: UnvalidatedProtoEntry = "Desc=1-2".parse().unwrap();
  254. let unsupported: Option<UnvalidatedProtoEntry> = protocol.all_supported();
  255. assert_eq!(true, unsupported.is_none());
  256. }
  257. #[test]
  258. fn protocol_all_supported_with_single_protocol_and_protocol_range() {
  259. let protocol: UnvalidatedProtoEntry = "Link=1-4".parse().unwrap();
  260. let unsupported: Option<UnvalidatedProtoEntry> = protocol.all_supported();
  261. assert_eq!(true, unsupported.is_none());
  262. }
  263. // By allowing us to add to votes, the C implementation allows us to
  264. // exceed the limit.
  265. #[test]
  266. fn protover_compute_vote_may_exceed_limit() {
  267. let proto1: UnvalidatedProtoEntry = "Sleen=1-65535".parse().unwrap();
  268. let proto2: UnvalidatedProtoEntry = "Sleen=100000".parse().unwrap();
  269. let _result: UnvalidatedProtoEntry = ProtoverVote::compute(&[proto1, proto2], &1);
  270. }
  271. #[test]
  272. fn protover_all_supported_should_exclude_versions_we_actually_do_support() {
  273. let proto: UnvalidatedProtoEntry = "Link=3-999".parse().unwrap();
  274. let result: String = proto.all_supported().unwrap().to_string();
  275. assert_eq!(result, "Link=6-999".to_string());
  276. }
  277. #[test]
  278. fn protover_all_supported_should_exclude_versions_we_actually_do_support_complex1() {
  279. let proto: UnvalidatedProtoEntry = "Link=1-3,345-666".parse().unwrap();
  280. let result: String = proto.all_supported().unwrap().to_string();
  281. assert_eq!(result, "Link=345-666".to_string());
  282. }
  283. #[test]
  284. fn protover_all_supported_should_exclude_versions_we_actually_do_support_complex2() {
  285. let proto: UnvalidatedProtoEntry = "Link=1-3,5-12".parse().unwrap();
  286. let result: String = proto.all_supported().unwrap().to_string();
  287. assert_eq!(result, "Link=6-12".to_string());
  288. }
  289. #[test]
  290. fn protover_all_supported_should_exclude_some_versions_and_entire_protocols() {
  291. let proto: UnvalidatedProtoEntry = "Link=1-3,5-12 Quokka=9000-9001".parse().unwrap();
  292. let result: String = proto.all_supported().unwrap().to_string();
  293. assert_eq!(result, "Link=6-12 Quokka=9000-9001".to_string());
  294. }
  295. #[test]
  296. fn protover_all_supported_should_not_dos_anyones_computer() {
  297. let proto: UnvalidatedProtoEntry = "Sleen=0-2147483648".parse().unwrap();
  298. let result: String = proto.all_supported().unwrap().to_string();
  299. assert_eq!(result, "Sleen=0-2147483648".to_string());
  300. }
  301. #[test]
  302. fn protover_all_supported_should_not_dos_anyones_computer_max_versions() {
  303. let proto: UnvalidatedProtoEntry = "Sleen=0-4294967294".parse().unwrap();
  304. let result: String = proto.all_supported().unwrap().to_string();
  305. assert_eq!(result, "Sleen=0-4294967294".to_string());
  306. }
  307. #[test]
  308. // C_RUST_DIFFERS: The C will return true (e.g. saying "yes, that's supported")
  309. // but set the msg to NULL (??? seems maybe potentially bad). The Rust will
  310. // simply return a None.
  311. fn protover_all_supported_should_return_empty_string_for_weird_thing() {
  312. let proto: UnvalidatedProtoEntry = "Fribble=".parse().unwrap();
  313. let result: Option<UnvalidatedProtoEntry> = proto.all_supported();
  314. assert!(result.is_none());
  315. }
  316. #[test]
  317. fn protover_unvalidatedprotoentry_should_err_entirely_unparseable_things() {
  318. let proto: Result<UnvalidatedProtoEntry, ProtoverError> = "Fribble".parse();
  319. assert_eq!(Err(ProtoverError::Unparseable), proto);
  320. }
  321. #[test]
  322. fn protover_all_supported_over_maximum_limit() {
  323. let proto: Result<UnvalidatedProtoEntry, ProtoverError> = "Sleen=0-4294967295".parse();
  324. assert_eq!(Err(ProtoverError::ExceedsMax), proto);
  325. }