blob: 88748de79cc97fabef23a775d50a164720d789c7 [file] [log] [blame]
Jeff Vander Stoep0029ba42021-06-25 09:40:28 +02001use crate::{decode_config, encode::encoded_size, encode_config_buf, CharacterSet, Config};
2
3use std::str;
4
5use rand::{
6 distributions::{Distribution, Uniform},
7 seq::SliceRandom,
8 FromEntropy, Rng,
9};
10
11#[test]
12fn 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]
18fn roundtrip_random_config_long() {
19 roundtrip_random_config(Uniform::new(0, 1000), 10_000);
20}
21
22pub 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
45fn 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
70pub 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}