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