1 extern crate rand;
2 
3 use encode::encoded_size;
4 use *;
5 
6 use std::str;
7 
8 use self::rand::distributions::{Distribution, Uniform};
9 use self::rand::{FromEntropy, Rng};
10 use self::rand::seq::SliceRandom;
11 
12 #[test]
roundtrip_random_config_short()13 fn roundtrip_random_config_short() {
14     // exercise the slower encode/decode routines that operate on shorter buffers more vigorously
15     roundtrip_random_config(Uniform::new(0, 50), 10_000);
16 }
17 
18 #[test]
roundtrip_random_config_long()19 fn roundtrip_random_config_long() {
20     roundtrip_random_config(Uniform::new(0, 1000), 10_000);
21 }
22 
assert_encode_sanity(encoded: &str, config: Config, input_len: usize)23 pub fn assert_encode_sanity(encoded: &str, config: Config, input_len: usize) {
24     let input_rem = input_len % 3;
25     let expected_padding_len = if input_rem > 0 {
26         if config.pad {
27             3 - input_rem
28         } else {
29             0
30         }
31     } else {
32         0
33     };
34 
35     let expected_encoded_len = encoded_size(input_len, config).unwrap();
36 
37     assert_eq!(expected_encoded_len, encoded.len());
38 
39     let padding_len = encoded.chars().filter(|&c| c == '=').count();
40 
41     assert_eq!(expected_padding_len, padding_len);
42 
43     let _ = str::from_utf8(encoded.as_bytes()).expect("Base64 should be valid utf8");
44 }
45 
roundtrip_random_config(input_len_range: Uniform<usize>, iterations: u32)46 fn roundtrip_random_config(input_len_range: Uniform<usize>, iterations: u32) {
47     let mut input_buf: Vec<u8> = Vec::new();
48     let mut encoded_buf = String::new();
49     let mut rng = rand::rngs::SmallRng::from_entropy();
50 
51     for _ in 0..iterations {
52         input_buf.clear();
53         encoded_buf.clear();
54 
55         let input_len = input_len_range.sample(&mut rng);
56 
57         let config = random_config(&mut rng);
58 
59         for _ in 0..input_len {
60             input_buf.push(rng.gen());
61         }
62 
63         encode_config_buf(&input_buf, config, &mut encoded_buf);
64 
65         assert_encode_sanity(&encoded_buf, config, input_len);
66 
67         assert_eq!(input_buf, decode_config(&encoded_buf, config).unwrap());
68     }
69 }
70 
random_config<R: Rng>(rng: &mut R) -> Config71 pub fn random_config<R: Rng>(rng: &mut R) -> Config {
72     const CHARSETS: &[CharacterSet] = &[
73         CharacterSet::UrlSafe,
74         CharacterSet::Standard,
75         CharacterSet::Crypt,
76     ];
77     let charset = *CHARSETS.choose(rng).unwrap();
78 
79     Config::new(charset, rng.gen())
80 }
81