base64_pad

base64 with padding library.
git clone https://git.philomathiclife.com/repos/base64_pad
Log | Files | Refs | README

tests.rs (8566B)


      1 use super::DecodeErr;
      2 #[cfg(any(
      3     target_pointer_width = "16",
      4     target_pointer_width = "32",
      5     target_pointer_width = "64",
      6 ))]
      7 use super::MAX_ENCODE_INPUT_LEN;
      8 #[cfg(feature = "alloc")]
      9 use alloc::{borrow::ToOwned as _, string::String, vec};
     10 use core::fmt::{self, Write};
     11 #[cfg(any(
     12     target_pointer_width = "16",
     13     target_pointer_width = "32",
     14     target_pointer_width = "64",
     15 ))]
     16 use rand::{RngExt as _, rngs::SmallRng};
     17 #[expect(clippy::panic, reason = "want to crash when there is a bug")]
     18 #[expect(clippy::too_many_lines, reason = "a lot to test")]
     19 #[expect(
     20     clippy::as_conversions,
     21     clippy::cast_possible_truncation,
     22     clippy::integer_division_remainder_used,
     23     reason = "comment justifies correctness"
     24 )]
     25 #[cfg(any(
     26     target_pointer_width = "16",
     27     target_pointer_width = "32",
     28     target_pointer_width = "64",
     29 ))]
     30 #[ignore = "slow"]
     31 #[test]
     32 fn encode_decode_len() {
     33     assert_eq!(MAX_ENCODE_INPUT_LEN, 3 * (usize::MAX >> 2u8));
     34     let mut rng = rand::make_rng::<SmallRng>();
     35     for _ in 0u32..10_000_000 {
     36         // `uN as usize` is fine since we `cfg` by pointer width.
     37         #[cfg(target_pointer_width = "16")]
     38         let len = rng.random::<u16>() as usize;
     39         #[cfg(target_pointer_width = "32")]
     40         let len = rng.random::<u32>() as usize;
     41         #[cfg(target_pointer_width = "64")]
     42         let len = rng.random::<u64>() as usize;
     43         if len <= MAX_ENCODE_INPUT_LEN {
     44             assert_eq!(
     45                 super::encode_len_checked(len).map(|l| {
     46                     super::decode_len(l).map(|decode_len| {
     47                         decode_len
     48                             - match len % 3 {
     49                                 0 => 0,
     50                                 1 => 2,
     51                                 2 => 1,
     52                                 _ => panic!("usize % 3 is greater than 3"),
     53                             }
     54                     })
     55                 }),
     56                 Some(Some(len))
     57             );
     58         } else {
     59             assert!(super::encode_len_checked(len).is_none());
     60         }
     61     }
     62     for i in 0..1025 {
     63         assert_eq!(
     64             super::encode_len_checked(i).map(|l| {
     65                 super::decode_len(l).map(|decode_len| {
     66                     decode_len
     67                         - match i % 3 {
     68                             0 => 0,
     69                             1 => 2,
     70                             2 => 1,
     71                             _ => panic!("usize % 3 is greater than 3"),
     72                         }
     73                 })
     74             }),
     75             Some(Some(i))
     76         );
     77     }
     78     #[cfg(target_pointer_width = "16")]
     79     for i in MAX_ENCODE_INPUT_LEN + 1.. {
     80         assert!(super::encode_len_checked(i).is_none());
     81     }
     82     #[cfg(not(target_pointer_width = "16"))]
     83     for i in MAX_ENCODE_INPUT_LEN + 1..MAX_ENCODE_INPUT_LEN + 1_000_000 {
     84         assert!(super::encode_len_checked(i).is_none());
     85     }
     86     assert!(super::encode_len_checked(usize::MAX).is_none());
     87     assert_eq!(
     88         super::encode_len_checked(MAX_ENCODE_INPUT_LEN),
     89         Some(usize::MAX - 3)
     90     );
     91     for _ in 0u32..10_000_000 {
     92         #[cfg(target_pointer_width = "16")]
     93         let len = rng.random::<u16>() as usize;
     94         #[cfg(target_pointer_width = "32")]
     95         let len = rng.random::<u32>() as usize;
     96         #[cfg(target_pointer_width = "64")]
     97         let len = rng.random::<u64>() as usize;
     98         if len.trailing_zeros() > 1 {
     99             assert_eq!(
    100                 super::decode_len(len).map(super::encode_len_checked),
    101                 Some(Some(len))
    102             );
    103         } else {
    104             assert!(super::decode_len(len).is_none());
    105         }
    106     }
    107     for i in 0usize..1025 {
    108         if i.trailing_zeros() > 1 {
    109             assert_eq!(
    110                 super::decode_len(i).map(super::encode_len_checked),
    111                 Some(Some(i))
    112             );
    113         } else {
    114             assert!(super::decode_len(i).is_none());
    115         }
    116     }
    117     #[cfg(target_pointer_width = "16")]
    118     for i in 0..=usize::MAX {
    119         if i & 3 == 1 {
    120             assert!(super::decode_len(i).is_none());
    121         } else {
    122             assert_eq!(
    123                 super::decode_len(i).map(super::encode_len_checked),
    124                 Some(Some(i))
    125             );
    126         }
    127     }
    128     #[cfg(not(target_pointer_width = "16"))]
    129     for i in usize::MAX - 1_000_000..=usize::MAX {
    130         if i.trailing_zeros() > 1 {
    131             assert_eq!(
    132                 super::decode_len(i).map(super::encode_len_checked),
    133                 Some(Some(i))
    134             );
    135         } else {
    136             assert!(super::decode_len(i).is_none());
    137         }
    138     }
    139     assert_eq!(
    140         super::decode_len(usize::MAX - 3),
    141         Some(MAX_ENCODE_INPUT_LEN)
    142     );
    143 }
    144 #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
    145 #[cfg(feature = "alloc")]
    146 #[test]
    147 fn encode_write() {
    148     let input = [9; 8192];
    149     let mut buffer = String::with_capacity(super::encode_len(input.len()));
    150     let cap = buffer.capacity();
    151     let mut write_len;
    152     for len in 0..input.len() {
    153         write_len = super::encode_len(len);
    154         match write_len.checked_add(buffer.len()) {
    155             None => {
    156                 buffer.clear();
    157                 // Indexing is fine since `len <= input.len()`.
    158                 assert_eq!(super::encode_write(&input[..len], &mut buffer), Ok(()));
    159                 assert_eq!(buffer.len(), write_len);
    160             }
    161             Some(l) => {
    162                 if l > cap {
    163                     buffer.clear();
    164                     // Indexing is fine since `len <= input.len()`.
    165                     assert_eq!(super::encode_write(&input[..len], &mut buffer), Ok(()));
    166                     assert_eq!(buffer.len(), write_len);
    167                 } else {
    168                     // Indexing is fine since `len <= input.len()`.
    169                     assert_eq!(super::encode_write(&input[..len], &mut buffer), Ok(()));
    170                     assert_eq!(buffer.len(), l);
    171                 }
    172             }
    173         }
    174         assert!(
    175             buffer
    176                 .as_bytes()
    177                 .iter()
    178                 .all(|b| { matches!(*b, b'C' | b'J' | b'Q' | b'k' | b'=') })
    179         );
    180     }
    181 }
    182 #[cfg(feature = "alloc")]
    183 #[test]
    184 fn try_encode() {
    185     assert_eq!(super::try_encode(&[0]), Ok("AA==".to_owned()));
    186 }
    187 #[cfg(feature = "alloc")]
    188 #[test]
    189 fn encode() {
    190     assert_eq!(super::encode(&[0]), "AA==".to_owned());
    191 }
    192 #[cfg(feature = "alloc")]
    193 #[test]
    194 fn try_encode_append() {
    195     let mut val = "Hi".to_owned();
    196     assert_eq!(
    197         super::try_encode_append(&[0], &mut val),
    198         Ok("AA==".to_owned().as_mut_str())
    199     );
    200     assert_eq!(val, "HiAA==");
    201 }
    202 #[cfg(feature = "alloc")]
    203 #[test]
    204 fn encode_append() {
    205     let mut val = "Hi".to_owned();
    206     assert_eq!(
    207         super::encode_append(&[0], &mut val),
    208         "AA==".to_owned().as_mut_str()
    209     );
    210     assert_eq!(val, "HiAA==");
    211 }
    212 #[cfg(feature = "alloc")]
    213 #[test]
    214 fn try_encode_append_only() {
    215     let mut val = "Hi".to_owned();
    216     assert_eq!(super::try_encode_append_only(&[0], &mut val), Ok(()));
    217     assert_eq!(val, "HiAA==");
    218 }
    219 #[cfg(feature = "alloc")]
    220 #[test]
    221 fn encode_append_only() {
    222     let mut val = "Hi".to_owned();
    223     super::encode_append_only(&[0], &mut val);
    224     assert_eq!(val, "HiAA==");
    225 }
    226 #[test]
    227 fn decode_buffer() {
    228     assert_eq!(
    229         super::decode_buffer(b"AA==", &mut [0]),
    230         Ok([0].as_mut_slice())
    231     );
    232     assert_eq!(
    233         super::decode_buffer(b"AA==", &mut []),
    234         Err(DecodeErr::BufferLen)
    235     );
    236 }
    237 #[cfg(feature = "alloc")]
    238 #[test]
    239 fn decode() {
    240     assert_eq!(super::decode(b"AA=="), Ok(vec![0]));
    241 }
    242 #[test]
    243 fn validate_encoded_data() {
    244     assert_eq!(super::validate_encoded_data(b"AA=="), Ok(()));
    245 }
    246 #[test]
    247 fn encode_buffer_exact() {
    248     let mut output = [0; 4];
    249     super::encode_buffer_exact(&[0], &mut output);
    250     assert_eq!(output, *b"AA==");
    251 }
    252 #[test]
    253 fn decode_buffer_exact() {
    254     let mut output = [1];
    255     assert_eq!(super::decode_buffer_exact(b"AA==", &mut output), Ok(()));
    256     assert_eq!(output, [0]);
    257 }
    258 #[test]
    259 fn encode_write_core() {
    260     struct Writer<'a>(&'a mut [u8]);
    261     impl Write for Writer<'_> {
    262         fn write_str(&mut self, s: &str) -> fmt::Result {
    263             self.0.get_mut(..s.len()).ok_or(fmt::Error).map(|bytes| {
    264                 bytes.copy_from_slice(s.as_bytes());
    265             })
    266         }
    267     }
    268     let mut writer = Writer(&mut [0, 0, 0, 0, 1]);
    269     assert_eq!(super::encode_write(&[0], &mut writer), Ok(()));
    270     assert_eq!(writer.0, b"AA==\x01");
    271     assert_eq!(
    272         super::encode_write(&[0, 0, 0, 0], &mut writer),
    273         Err(fmt::Error)
    274     );
    275 }