blob: 4d5e1890a466423ddef3ed96e56c2ea962e8acdc [file] [log] [blame] [edit]
//! Equivalence tests between `base64` crate and `base64ct`.
#![cfg(feature = "std")]
// TODO(tarcieri): fix `base64` crate deprecations
// warning: use of deprecated function `base64::encode`: Use Engine::encode
#![allow(deprecated)]
use base64ct::{Base64 as Base64ct, Encoding};
use proptest::{prelude::*, string::*};
use std::iter;
/// Incremental Base64 decoder.
type Decoder<'a> = base64ct::Decoder<'a, Base64ct>;
/// Incremental Base64 encoder.
type Encoder<'a> = base64ct::Encoder<'a, Base64ct>;
proptest! {
/// Ensure `base64ct` decodes data encoded by `base64` ref crate
#[test]
fn decode_equiv(bytes in bytes_regex(".{0,256}").unwrap()) {
let encoded = base64::encode(&bytes);
let decoded = Base64ct::decode_vec(&encoded);
prop_assert_eq!(Ok(bytes), decoded);
}
/// Ensure that `base64ct`'s incremental decoder is able to decode randomly
/// generated inputs encoded by the `base64` ref crate
#[test]
fn decode_incremental(bytes in bytes_regex(".{1,256}").unwrap(), chunk_size in 1..256usize) {
let encoded = base64::encode(&bytes);
let chunk_size = match chunk_size % bytes.len() {
0 => 1,
n => n
};
let mut buffer = [0u8; 384];
let mut decoder = Decoder::new(encoded.as_bytes()).unwrap();
let mut remaining_len = decoder.remaining_len();
for chunk in bytes.chunks(chunk_size) {
prop_assert!(!decoder.is_finished());
let decoded = decoder.decode(&mut buffer[..chunk.len()]);
prop_assert_eq!(Ok(chunk), decoded);
remaining_len -= decoded.unwrap().len();
prop_assert_eq!(remaining_len, decoder.remaining_len());
}
prop_assert!(decoder.is_finished());
prop_assert_eq!(decoder.remaining_len(), 0);
}
#[test]
fn decode_incremental_wrapped(
bytes in bytes_regex(".{1,256}").unwrap(),
line_width in 4..128usize,
chunk_size in 1..256usize
) {
for line_ending in ["\r", "\n", "\r\n"] {
let encoded = base64::encode(&bytes);
let mut encoded_wrapped = Vec::new();
let mut lines = encoded.as_bytes().chunks_exact(line_width);
for line in &mut lines {
encoded_wrapped.extend_from_slice(line);
encoded_wrapped.extend_from_slice(line_ending.as_bytes());
}
let last = lines.remainder();
if last.is_empty() {
encoded_wrapped.truncate(encoded_wrapped.len() - line_ending.len());
} else {
encoded_wrapped.extend_from_slice(last);
}
let chunk_size = match chunk_size % bytes.len() {
0 => 1,
n => n
};
let mut buffer = [0u8; 384];
let mut decoder = Decoder::new_wrapped(&encoded_wrapped, line_width).unwrap();
let mut remaining_len = decoder.remaining_len();
for chunk in bytes.chunks(chunk_size) {
prop_assert!(!decoder.is_finished());
let decoded = decoder.decode(&mut buffer[..chunk.len()]);
prop_assert_eq!(Ok(chunk), decoded);
remaining_len -= decoded.unwrap().len();
prop_assert_eq!(remaining_len, decoder.remaining_len());
}
prop_assert!(decoder.is_finished());
prop_assert_eq!(decoder.remaining_len(), 0);
}
}
/// Ensure `base64ct` and `base64` ref crate decode randomly generated
/// inputs equivalently.
///
/// Inputs are selected to be valid characters in the standard Base64
/// padded alphabet, but are not necessarily valid Base64.
#[test]
fn decode_random(base64ish in string_regex("[A-Za-z0-9+/]{0,256}").unwrap()) {
let base64ish_padded = match base64ish.len() % 4 {
0 => base64ish,
n => {
let padding_len = 4 - n;
base64ish + &iter::repeat("=").take(padding_len).collect::<String>()
}
};
let decoded_ct = Base64ct::decode_vec(&base64ish_padded).ok();
let decoded_ref = base64::decode(&base64ish_padded).ok();
prop_assert_eq!(decoded_ct, decoded_ref);
}
/// Ensure `base64ct` and the `base64` ref crate encode randomly generated
/// inputs equivalently.
#[test]
fn encode_equiv(bytes in bytes_regex(".{0,256}").unwrap()) {
let encoded_ct = Base64ct::encode_string(&bytes);
let encoded_ref = base64::encode(&bytes);
prop_assert_eq!(encoded_ct, encoded_ref);
}
/// Ensure that `base64ct`'s incremental encoder is able to encode randomly
/// generated inputs which match what's encoded by the `base64` ref crate
#[test]
fn encode_incremental(bytes in bytes_regex(".{1,256}").unwrap(), chunk_size in 1..256usize) {
let expected = base64::encode(&bytes);
let chunk_size = match chunk_size % bytes.len() {
0 => 1,
n => n
};
let mut buffer = [0u8; 1024];
let mut encoder = Encoder::new(&mut buffer).unwrap();
for chunk in bytes.chunks(chunk_size) {
encoder.encode(chunk).unwrap();
}
prop_assert_eq!(expected, encoder.finish().unwrap());
}
}