Skip to content

Commit a152ff1

Browse files
authored
base64ct, base32ct: proptests for decoder equivalence with base32/64 (#2085)
For the base64 case, this MR adds proptests to ensure that base64 and base64ct accept the same inputs when decoding, and produce the same outputs when decoding them. For the base32 case, that property isn't actually true. Instead, the proptest makes sure that whenever base32 and base32ct both accept an input when decoding, they produce the same output.
1 parent f4c5e14 commit a152ff1

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

base32ct/tests/proptests.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,35 @@ proptest! {
3434
let expected = base32::encode(RFC4648_PADDED, &bytes).to_lowercase();
3535
prop_assert_eq!(actual, expected);
3636
}
37+
38+
/// Make sure that, if base32ct and base32 _both_ decode a value
39+
/// when expecting padded inputs, they give the same output.
40+
///
41+
/// TODO: It might be desirable to ensure that they both decode the
42+
/// _same_ values: that is, that they are equivalently strict about
43+
/// which inputs they accept. But first, we should verify that
44+
/// `base32`'s behavior is actually what we want.
45+
#[test]
46+
fn decode_arbitrary_padded(string in string_regex("[a-z0-9]{0,32}={0,8}").unwrap()) {
47+
let actual = Base32Ct::decode_vec(&string);
48+
let expected = base32::decode(RFC4648_PADDED, &string);
49+
// assert_eq!(actual.ok(), expected);
50+
if let (Ok(a), Some(b)) = (actual, expected) {
51+
assert_eq!(a, b);
52+
}
53+
}
54+
55+
/// Make sure that, if base32ct and base32 _both_ decode a value
56+
/// when expecting unpadded inputs, they give the same output.
57+
///
58+
/// TODO: See note above.
59+
#[test]
60+
fn decode_arbitrary_unpadded(string in string_regex("[a-z0-9]{0,32}={0,8}").unwrap()) {
61+
let actual = Base32UnpaddedCt::decode_vec(&string);
62+
let expected = base32::decode(RFC4648_UNPADDED, &string);
63+
// assert_eq!(actual.ok(), expected);
64+
if let (Ok(a), Some(b)) = (actual, expected) {
65+
assert_eq!(a, b);
66+
}
67+
}
3768
}

base64ct/tests/proptests.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// warning: use of deprecated function `base64::encode`: Use Engine::encode
66
#![allow(deprecated)]
77

8-
use base64ct::{Base64 as Base64ct, Encoding};
8+
use base64ct::{Base64 as Base64ct, Base64Unpadded as Base64UnpaddedCt, Encoding};
99
use proptest::{prelude::*, string::*};
1010

1111
/// Incremental Base64 decoder.
@@ -148,4 +148,23 @@ proptest! {
148148

149149
prop_assert_eq!(expected, encoder.finish().unwrap());
150150
}
151+
152+
/// Make sure that base64ct and base64 both decode the same values
153+
/// when expecting padded inputs, and produce the same outputs for those values.
154+
#[test]
155+
fn decode_arbitrary_padded(string in string_regex("[a-zA-Z0-9/+=?]{0,256}").unwrap()) {
156+
let actual = Base64ct::decode_vec(&string);
157+
let expected = base64::decode( &string);
158+
assert_eq!(actual.ok(), expected.ok());
159+
}
160+
161+
/// Make sure that base64ct and base64 both decode the same values
162+
/// when expecting unpadded inputs, and produce the same outputs for those values.
163+
#[test]
164+
fn decode_arbitrary_unpadded(string in string_regex("[a-zA-Z0-9/+=?]{0,256}").unwrap()) {
165+
use base64::{engine::general_purpose::STANDARD_NO_PAD, Engine as _};
166+
let actual = Base64UnpaddedCt::decode_vec(&string);
167+
let expected = STANDARD_NO_PAD.decode(&string);
168+
assert_eq!(actual.ok(), expected.ok());
169+
}
151170
}

0 commit comments

Comments
 (0)