tests.rs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. extern crate base64;
  2. extern crate rand;
  3. use rand::{FromEntropy, Rng};
  4. use base64::*;
  5. mod helpers;
  6. use self::helpers::*;
  7. // generate random contents of the specified length and test encode/decode roundtrip
  8. fn roundtrip_random(
  9. byte_buf: &mut Vec<u8>,
  10. str_buf: &mut String,
  11. config: Config,
  12. byte_len: usize,
  13. approx_values_per_byte: u8,
  14. max_rounds: u64,
  15. ) {
  16. // let the short ones be short but don't let it get too crazy large
  17. let num_rounds = calculate_number_of_rounds(byte_len, approx_values_per_byte, max_rounds);
  18. let mut r = rand::rngs::SmallRng::from_entropy();
  19. let mut decode_buf = Vec::new();
  20. for _ in 0..num_rounds {
  21. byte_buf.clear();
  22. str_buf.clear();
  23. decode_buf.clear();
  24. while byte_buf.len() < byte_len {
  25. byte_buf.push(r.gen::<u8>());
  26. }
  27. encode_config_buf(&byte_buf, config, str_buf);
  28. decode_config_buf(&str_buf, config, &mut decode_buf).unwrap();
  29. assert_eq!(byte_buf, &decode_buf);
  30. }
  31. }
  32. fn calculate_number_of_rounds(byte_len: usize, approx_values_per_byte: u8, max: u64) -> u64 {
  33. // don't overflow
  34. let mut prod = approx_values_per_byte as u64;
  35. for _ in 0..byte_len {
  36. if prod > max {
  37. return max;
  38. }
  39. prod = prod.saturating_mul(prod);
  40. }
  41. prod
  42. }
  43. fn no_pad_config() -> Config {
  44. Config::new(CharacterSet::Standard, false)
  45. }
  46. #[test]
  47. fn roundtrip_random_short_standard() {
  48. let mut byte_buf: Vec<u8> = Vec::new();
  49. let mut str_buf = String::new();
  50. for input_len in 0..40 {
  51. roundtrip_random(&mut byte_buf, &mut str_buf, STANDARD, input_len, 4, 10000);
  52. }
  53. }
  54. #[test]
  55. fn roundtrip_random_with_fast_loop_standard() {
  56. let mut byte_buf: Vec<u8> = Vec::new();
  57. let mut str_buf = String::new();
  58. for input_len in 40..100 {
  59. roundtrip_random(&mut byte_buf, &mut str_buf, STANDARD, input_len, 4, 1000);
  60. }
  61. }
  62. #[test]
  63. fn roundtrip_random_short_no_padding() {
  64. let mut byte_buf: Vec<u8> = Vec::new();
  65. let mut str_buf = String::new();
  66. for input_len in 0..40 {
  67. roundtrip_random(
  68. &mut byte_buf,
  69. &mut str_buf,
  70. no_pad_config(),
  71. input_len,
  72. 4,
  73. 10000,
  74. );
  75. }
  76. }
  77. #[test]
  78. fn roundtrip_random_no_padding() {
  79. let mut byte_buf: Vec<u8> = Vec::new();
  80. let mut str_buf = String::new();
  81. for input_len in 40..100 {
  82. roundtrip_random(
  83. &mut byte_buf,
  84. &mut str_buf,
  85. no_pad_config(),
  86. input_len,
  87. 4,
  88. 1000,
  89. );
  90. }
  91. }
  92. #[test]
  93. fn roundtrip_decode_trailing_10_bytes() {
  94. // This is a special case because we decode 8 byte blocks of input at a time as much as we can,
  95. // ideally unrolled to 32 bytes at a time, in stages 1 and 2. Since we also write a u64's worth
  96. // of bytes (8) to the output, we always write 2 garbage bytes that then will be overwritten by
  97. // the NEXT block. However, if the next block only contains 2 bytes, it will decode to 1 byte,
  98. // and therefore be too short to cover up the trailing 2 garbage bytes. Thus, we have stage 3
  99. // to handle that case.
  100. for num_quads in 0..25 {
  101. let mut s: String = std::iter::repeat("ABCD").take(num_quads).collect();
  102. s.push_str("EFGHIJKLZg");
  103. let decoded = decode(&s).unwrap();
  104. assert_eq!(num_quads * 3 + 7, decoded.len());
  105. assert_eq!(s, encode_config(&decoded, STANDARD_NO_PAD));
  106. }
  107. }
  108. #[test]
  109. fn display_wrapper_matches_normal_encode() {
  110. let mut bytes = Vec::<u8>::with_capacity(256);
  111. for i in 0..255 {
  112. bytes.push(i);
  113. }
  114. bytes.push(255);
  115. assert_eq!(
  116. encode(&bytes),
  117. format!(
  118. "{}",
  119. base64::display::Base64Display::with_config(&bytes, STANDARD)
  120. )
  121. );
  122. }
  123. #[test]
  124. fn because_we_can() {
  125. compare_decode("alice", "YWxpY2U=");
  126. compare_decode("alice", &encode(b"alice"));
  127. compare_decode("alice", &encode(&decode(&encode(b"alice")).unwrap()));
  128. }
  129. #[test]
  130. fn encode_config_slice_can_use_inline_buffer() {
  131. let mut buf: [u8; 22] = [0; 22];
  132. let mut larger_buf: [u8; 24] = [0; 24];
  133. let mut input: [u8; 16] = [0; 16];
  134. let mut rng = rand::rngs::SmallRng::from_entropy();
  135. for elt in &mut input {
  136. *elt = rng.gen();
  137. }
  138. assert_eq!(22, encode_config_slice(&input, STANDARD_NO_PAD, &mut buf));
  139. let decoded = decode_config(&buf, STANDARD_NO_PAD).unwrap();
  140. assert_eq!(decoded, input);
  141. // let's try it again with padding
  142. assert_eq!(24, encode_config_slice(&input, STANDARD, &mut larger_buf));
  143. let decoded = decode_config(&buf, STANDARD).unwrap();
  144. assert_eq!(decoded, input);
  145. }
  146. #[test]
  147. #[should_panic(expected = "index 24 out of range for slice of length 22")]
  148. fn encode_config_slice_panics_when_buffer_too_small() {
  149. let mut buf: [u8; 22] = [0; 22];
  150. let mut input: [u8; 16] = [0; 16];
  151. let mut rng = rand::rngs::SmallRng::from_entropy();
  152. for elt in &mut input {
  153. *elt = rng.gen();
  154. }
  155. encode_config_slice(&input, STANDARD, &mut buf);
  156. }