use super::*;
use alloc::vec;
#[test]
fn growing_output_checks_limits_before_reserving_and_handles_capacity_overflow() {
let failed = Cell::new(false);
let mut output = GrowingOutput {
output: Output {
bytes: Vec::new(),
limit: 257,
},
allocation_failed: &failed,
};
output.try_extend(&[1; 64]).unwrap();
output.try_push(2).unwrap();
output.try_extend(&[3; 192]).unwrap();
let capacity = output.output.bytes.capacity();
assert_eq!(
output.try_push(4),
Err(postcard::Error::SerializeBufferFull)
);
assert_eq!(
output.try_extend(&[4]),
Err(postcard::Error::SerializeBufferFull)
);
assert_eq!(output.output.bytes.capacity(), capacity);
assert!(!failed.get());
let bytes = output.finalize().unwrap();
assert_eq!(bytes.len(), 257);
assert_eq!(&bytes[..64], &[1; 64]);
assert_eq!(bytes[64], 2);
assert_eq!(&bytes[65..], &[3; 192]);
let mut overflow = GrowingOutput {
output: Output {
bytes: Vec::new(),
limit: usize::MAX,
},
allocation_failed: &failed,
};
assert_eq!(
overflow.reserve(usize::MAX),
Err(postcard::Error::SerializeBufferFull)
);
assert!(failed.get());
assert!(overflow.output.bytes.is_empty());
failed.set(false);
let mut spare = GrowingOutput {
output: Output {
bytes: Vec::with_capacity(512),
limit: 1,
},
allocation_failed: &failed,
};
spare.try_push(1).unwrap();
assert_eq!(spare.try_push(2), Err(postcard::Error::SerializeBufferFull));
assert_eq!(
spare.try_extend(&[2]),
Err(postcard::Error::SerializeBufferFull)
);
spare.try_extend(&[]).unwrap();
assert_eq!(spare.finalize().unwrap(), vec![1]);
assert!(!failed.get());
}
#[test]
fn finite_encoding_allocates_for_emitted_bytes_without_a_second_visit() {
struct Once(Cell<bool>);
impl serde::Serialize for Once {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
assert!(!self.0.replace(true), "encoder visited the value twice");
s.serialize_bytes(&[])
}
}
impl Wire for Once {
const SHAPE: crate::Shape = crate::Bytes::<196608>::SHAPE;
}
let limits = Limits {
bytes: 200000,
allocation: 400000,
nodes: 8,
depth: 8,
};
let bytes = encode(1, 0, limits, &Once(Cell::new(false))).unwrap();
assert_eq!(bytes.len(), HEADER + 1);
assert!(
bytes.capacity() < 1024,
"tiny message reserved the schema maximum"
);
assert_eq!(bytes, [header(1, 0).as_slice(), &[0]].concat());
}
#[test]
fn exact_bulk_equality_covers_word_boundaries_tails_and_every_mismatch() {
for len in 0..=97 {
let original: Vec<_> = (0..len).map(|i| i as u8).collect();
let compare = || Compare {
remaining: &original,
allowance: len,
equal: true,
};
let mut equal = compare();
equal.try_extend(&original).unwrap();
assert!(equal.finalize().unwrap());
let copy = original.clone();
let mut separate = compare();
separate.try_extend(©).unwrap();
assert!(separate.finalize().unwrap());
for position in 0..len {
let mut different = original.clone();
different[position] ^= 1;
let mut refused = compare();
refused.try_extend(&different).unwrap();
assert!(
!refused.finalize().unwrap(),
"length {len}, position {position}"
);
}
for emitted in [len.saturating_sub(1), len + 1] {
if emitted == len {
continue;
}
let mut unequal = Compare {
remaining: &original,
allowance: len + 1,
equal: true,
};
unequal.try_extend(&vec![0; emitted]).unwrap();
assert!(!unequal.finalize().unwrap());
}
}
}
#[test]
fn identical_slice_still_checks_budget_length_and_previous_mismatch() {
let bytes = [42; 64];
let mut limited = Compare {
remaining: &bytes,
allowance: 63,
equal: true,
};
assert_eq!(
limited.try_extend(&bytes),
Err(postcard::Error::SerializeBufferFull)
);
let mut mismatch = Compare {
remaining: &bytes,
allowance: 64,
equal: false,
};
mismatch.try_extend(&bytes).unwrap();
assert!(!mismatch.finalize().unwrap());
let mut short = Compare {
remaining: &bytes[..32],
allowance: 64,
equal: true,
};
short.try_extend(&bytes).unwrap();
assert!(!short.finalize().unwrap());
let mut trailing = Compare {
remaining: &bytes,
allowance: 64,
equal: true,
};
trailing.try_extend(&bytes[..32]).unwrap();
assert!(!trailing.finalize().unwrap());
}
#[test]
fn a_mismatch_still_checks_later_bytes_and_the_output_allowance() {
let mut compare = Compare {
remaining: &[0; 9],
allowance: 9,
equal: true,
};
compare.try_extend(&[1; 8]).unwrap();
compare.try_push(0).unwrap();
assert_eq!(
compare.try_push(0),
Err(postcard::Error::SerializeBufferFull)
);
assert!(!compare.finalize().unwrap());
let mut exhausted = Compare {
remaining: &[],
allowance: 1,
equal: true,
};
exhausted.try_push(0).unwrap();
assert!(!exhausted.finalize().unwrap());
}