#![cfg(feature = "std")]
#![allow(clippy::useless_vec)]
use oxicode::{config, decode_from_slice_with_config, encode_to_vec_with_config};
use std::collections::{HashMap, HashSet};
#[test]
fn test_hashmap_decode_huge_len_rejected_under_limit() {
let huge_len: u64 = u64::MAX / 2;
let payload =
encode_to_vec_with_config(&huge_len, config::standard()).expect("encode huge len");
let cfg = config::standard().with_limit::<64>();
let result: Result<(HashMap<u32, u32>, usize), _> =
decode_from_slice_with_config(&payload, cfg);
assert!(
result.is_err(),
"decoding a HashMap with an enormous declared length must fail fast under a small limit, \
not attempt to allocate memory for it"
);
}
#[test]
fn test_hashset_decode_huge_len_rejected_under_limit() {
let huge_len: u64 = u64::MAX / 2;
let payload =
encode_to_vec_with_config(&huge_len, config::standard()).expect("encode huge len");
let cfg = config::standard().with_limit::<64>();
let result: Result<(HashSet<u32>, usize), _> = decode_from_slice_with_config(&payload, cfg);
assert!(
result.is_err(),
"decoding a HashSet with an enormous declared length must fail fast under a small limit, \
not attempt to allocate memory for it"
);
}
#[test]
fn test_hashmap_roundtrip_unaffected_by_claim() {
let mut map: HashMap<u32, String> = HashMap::new();
map.insert(1, "one".to_string());
map.insert(2, "two".to_string());
map.insert(3, "three".to_string());
let enc = encode_to_vec_with_config(&map, config::standard()).expect("encode hashmap");
let (decoded, consumed): (HashMap<u32, String>, usize) =
decode_from_slice_with_config(&enc, config::standard()).expect("decode hashmap");
assert_eq!(decoded, map);
assert_eq!(consumed, enc.len());
}
#[test]
fn test_hashset_roundtrip_unaffected_by_claim() {
let mut set: HashSet<i64> = HashSet::new();
set.insert(-5);
set.insert(0);
set.insert(42);
let enc = encode_to_vec_with_config(&set, config::standard()).expect("encode hashset");
let (decoded, consumed): (HashSet<i64>, usize) =
decode_from_slice_with_config(&enc, config::standard()).expect("decode hashset");
assert_eq!(decoded, set);
assert_eq!(consumed, enc.len());
}
#[test]
fn test_cstring_decode_huge_len_rejected_under_limit() {
use std::ffi::CString;
let huge_len: u64 = u64::MAX / 2;
let payload =
encode_to_vec_with_config(&huge_len, config::standard()).expect("encode huge len");
let cfg = config::standard().with_limit::<64>();
let result: Result<(CString, usize), _> = decode_from_slice_with_config(&payload, cfg);
assert!(
result.is_err(),
"decoding a CString with an enormous declared length must fail fast under a small limit"
);
}
#[test]
fn test_cstring_roundtrip() {
use std::ffi::CString;
let value = CString::new("hello, oxicode").unwrap();
let enc = encode_to_vec_with_config(&value, config::standard()).expect("encode cstring");
let (decoded, consumed): (CString, usize) =
decode_from_slice_with_config(&enc, config::standard()).expect("decode cstring");
assert_eq!(decoded, value);
assert_eq!(consumed, enc.len());
}
#[cfg(unix)]
#[test]
fn test_pathbuf_decode_huge_len_rejected_under_limit() {
use std::path::PathBuf;
let huge_len: u64 = u64::MAX / 2;
let payload =
encode_to_vec_with_config(&huge_len, config::standard()).expect("encode huge len");
let cfg = config::standard().with_limit::<64>();
let result: Result<(PathBuf, usize), _> = decode_from_slice_with_config(&payload, cfg);
assert!(
result.is_err(),
"decoding a PathBuf with an enormous declared length must fail fast under a small limit"
);
}
#[cfg(unix)]
#[test]
fn test_pathbuf_roundtrip_unix() {
use std::path::PathBuf;
let value = PathBuf::from("/tmp/some/oxicode/test/path.bin");
let enc = encode_to_vec_with_config(&value, config::standard()).expect("encode pathbuf");
let (decoded, consumed): (PathBuf, usize) =
decode_from_slice_with_config(&enc, config::standard()).expect("decode pathbuf");
assert_eq!(decoded, value);
assert_eq!(consumed, enc.len());
}
#[cfg(not(target_family = "wasm"))]
#[test]
fn test_osstring_roundtrip_valid_utf8() {
use std::ffi::OsString;
let value = OsString::from("hello world, oxicode");
let enc = encode_to_vec_with_config(&value, config::standard()).expect("encode osstring");
let (decoded, consumed): (OsString, usize) =
decode_from_slice_with_config(&enc, config::standard()).expect("decode osstring");
assert_eq!(decoded, value);
assert_eq!(consumed, enc.len());
let as_string = value.to_str().unwrap().to_string();
let string_enc =
encode_to_vec_with_config(&as_string, config::standard()).expect("encode string");
assert_eq!(
enc, string_enc,
"OsString encode must be byte-identical to the equivalent String encode for valid UTF-8"
);
}
#[cfg(unix)]
#[test]
fn test_osstr_encode_errors_on_non_utf8_instead_of_lossy_converting() {
use oxicode::enc::{EncoderImpl, VecWriter};
use oxicode::Encode;
use std::ffi::OsStr;
use std::os::unix::ffi::OsStrExt;
let invalid_bytes: &[u8] = &[0x66, 0x6f, 0x6f, 0xff, 0x9f, 0x62, 0x61, 0x72];
let os_str = OsStr::from_bytes(invalid_bytes);
assert!(
os_str.to_str().is_none(),
"test fixture must actually be invalid UTF-8"
);
let writer = VecWriter::new();
let mut encoder = EncoderImpl::new(writer, config::standard());
let result = os_str.encode(&mut encoder);
assert!(
result.is_err(),
"encoding a non-UTF-8 OsStr must return an error, not silently lossy-convert the data"
);
}