base64url_nopad

base64url without padding library.
git clone https://git.philomathiclife.com/repos/base64url_nopad
Log | Files | Refs | README

tests.rs (7532B)


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