#![allow(
unsafe_code,
unused_qualifications,
reason = "the derive macro emits audited zero-copy code and these upstream tests preserve explicit trait paths"
)]
use pinapod::{pod::PodBool, PinaPod, PinaPodCompact};
#[allow(dead_code)]
#[derive(PinaPod)]
struct Validatable {
pub score: u64,
pub active: bool,
pub maybe: Option<u64>,
pub name: pinapod::String<8>,
pub items: pinapod::Vec<u8, 4>,
}
#[test]
fn validate_correct_size() {
assert_eq!(Validatable::SIZE, 33);
}
#[test]
fn validate_zeroed_buffer_ok() {
let buf = [0u8; 33];
assert!(Validatable::read_exact(&buf).is_ok());
}
#[test]
fn validate_bad_bool() {
let mut buf = [0u8; 33];
buf[8] = 2; assert!(Validatable::read_exact(&buf).is_err());
}
#[test]
fn validate_truncated_buffer() {
let buf = [0u8; 20]; assert!(Validatable::read_exact(&buf).is_err());
}
#[test]
fn validate_bad_option_tag() {
let mut buf = [0u8; 33];
buf[9] = 3; assert!(Validatable::read_exact(&buf).is_err());
}
#[test]
fn validate_overlength_string() {
let mut buf = [0u8; 33];
buf[18] = 9; assert!(Validatable::read_exact(&buf).is_err());
}
#[test]
fn validate_overlength_vec() {
let mut buf = [0u8; 33];
buf[27] = 5; buf[28] = 0; assert!(Validatable::read_exact(&buf).is_err());
}
#[test]
fn validate_rejects_invalid_utf8_in_string() {
let mut buf = [0u8; 33];
buf[18] = 2;
buf[19] = 0xFF;
buf[20] = 0xFE;
assert!(Validatable::read_exact(&buf).is_err());
}
#[allow(dead_code)]
#[derive(PinaPod)]
struct WithOptionBool {
pub flag: Option<bool>,
}
#[test]
fn validate_option_bool_none_ok() {
let buf = [0u8; 2]; assert!(WithOptionBool::read_exact(&buf).is_ok());
}
#[test]
fn validate_option_bool_some_valid() {
let buf = [1u8, 1]; assert!(WithOptionBool::read_exact(&buf).is_ok());
}
#[test]
fn validate_option_bool_some_invalid_inner() {
let buf = [1u8, 5]; assert!(WithOptionBool::read_exact(&buf).is_err());
}
#[derive(PinaPod, Debug, PartialEq)]
#[repr(u8)]
enum Color {
Red = 0,
Green = 1,
Blue = 2,
}
#[allow(dead_code)]
#[derive(PinaPod)]
struct WithOptionEnum {
pub color: Option<Color>,
}
#[test]
fn validate_option_enum_none_ok() {
let buf = [0u8; 2]; assert!(WithOptionEnum::read_exact(&buf).is_ok());
}
#[test]
fn validate_option_enum_some_valid() {
let buf = [1u8, 2]; assert!(WithOptionEnum::read_exact(&buf).is_ok());
}
#[test]
fn validate_option_enum_some_invalid_inner() {
let buf = [1u8, 99]; assert!(WithOptionEnum::read_exact(&buf).is_err());
}
#[allow(dead_code)]
#[derive(PinaPod)]
#[pinapod(compact)]
struct CompactVal {
pub authority: [u8; 32],
pub bio: pinapod::String<16>,
}
#[test]
fn compact_validate_overlength_tail_string() {
let mut buf = vec![0u8; 100];
buf[32] = 17; assert!(CompactVal::validate(&buf).is_err());
}
#[test]
fn compact_validate_tail_exceeds_buffer() {
let mut buf = vec![0u8; 40]; buf[32] = 10; assert!(CompactVal::validate(&buf).is_err());
}
#[test]
fn compact_validate_rejects_invalid_utf8_in_tail_string() {
let mut buf = vec![0u8; 100];
buf[32] = 3; buf[33] = 0xFF; buf[34] = 0xFE;
buf[35] = 0xFD;
assert!(CompactVal::validate(&buf).is_err());
}
#[allow(dead_code)]
#[derive(PinaPod)]
#[pinapod(compact)]
struct CompactWithBool {
pub active: bool,
pub bio: pinapod::String<8>,
}
#[test]
fn compact_validate_inline_bad_bool() {
let mut buf = vec![0u8; 20];
buf[0] = 5; assert!(CompactWithBool::validate(&buf).is_err());
}
#[test]
fn validate_vec_bool_all_valid() {
let mut buf = [0u8; 7];
buf[0] = 3;
buf[1] = 0;
buf[2] = 0;
buf[3] = 1;
buf[4] = 0;
let v = unsafe { &*(buf.as_ptr() as *const pinapod::pod::PodVec<PodBool, 5>) };
assert!(pinapod::ZcValidate::validate_ref(v).is_ok());
}
#[test]
fn validate_vec_bool_rejects_invalid_element() {
let mut buf = [0u8; 7];
buf[0] = 3;
buf[1] = 0;
buf[2] = 0;
buf[3] = 1;
buf[4] = 5;
let v = unsafe { &*(buf.as_ptr() as *const pinapod::pod::PodVec<PodBool, 5>) };
assert!(pinapod::ZcValidate::validate_ref(v).is_err());
}
#[cfg(target_pointer_width = "32")]
#[test]
fn validate_rejects_eight_byte_lengths_that_do_not_fit_usize() {
use pinapod::{pod::PodVec, PodString, ZcValidate};
let bytes: [u8; 8] = [0, 0, 0, 0, 1, 0, 0, 0];
let string = unsafe { &*(bytes.as_ptr() as *const PodString<0, 8>) };
let vector = unsafe { &*(bytes.as_ptr() as *const PodVec<u8, 0, 8>) };
assert!(ZcValidate::validate_ref(string).is_err());
assert!(ZcValidate::validate_ref(vector).is_err());
}
#[test]
fn podstring_truncate_snaps_to_char_boundary() {
use pinapod::pod::PodString;
let mut s = PodString::<32>::default();
s.try_set("h\u{00e9}llo").unwrap(); assert_eq!(s.len(), 6);
s.truncate(2);
assert_eq!(s.len(), 1);
assert_eq!(s.as_str(), "h");
assert!(core::str::from_utf8(s.as_bytes()).is_ok());
}
#[test]
fn podstring_truncate_at_boundary_is_exact() {
use pinapod::pod::PodString;
let mut s = PodString::<32>::default();
s.try_set("h\u{00e9}llo").unwrap();
s.truncate(3);
assert_eq!(s.len(), 3);
assert_eq!(s.as_str(), "h\u{00e9}");
}
#[test]
fn error_invalid_bool_variant() {
let buf = [2u8]; let val = unsafe { &*(buf.as_ptr() as *const pinapod::pod::PodBool) };
let err = <pinapod::pod::PodBool as pinapod::ZcValidate>::validate_ref(val);
assert_eq!(err, Err(pinapod::PinaPodError::InvalidBool));
}
#[test]
fn error_invalid_tag_variant() {
let buf = [5u8, 0u8]; let val = unsafe { &*(buf.as_ptr() as *const pinapod::pod::PodOption<u8>) };
let err = <pinapod::pod::PodOption<u8> as pinapod::ZcValidate>::validate_ref(val);
assert_eq!(err, Err(pinapod::PinaPodError::InvalidTag));
}
#[test]
fn pod_option_invalid_tag_is_not_some() {
let buf = [0xFFu8, 42u8]; let opt = unsafe { &*(buf.as_ptr() as *const pinapod::pod::PodOption<u8>) };
assert!(
!opt.is_some(),
"invalid tag 0xFF must not be treated as Some"
);
assert!(opt.is_none(), "invalid tag 0xFF must be treated as None");
assert_eq!(opt.get(), None);
}
#[cfg(feature = "wincode")]
mod wincode_option_validation {
use pinapod::pod::{PodBool, PodOption};
#[test]
fn wincode_read_rejects_option_with_invalid_inner() {
let bytes: [u8; 2] = [1, 5];
let result = wincode::deserialize::<PodOption<PodBool>>(&bytes);
assert!(
result.is_err(),
"wincode SchemaRead must reject PodOption<PodBool> with invalid inner byte"
);
}
#[test]
fn wincode_read_accepts_valid_option_some() {
let bytes: [u8; 2] = [1, 1]; let result = wincode::deserialize::<PodOption<PodBool>>(&bytes);
assert!(result.is_ok());
}
#[test]
fn wincode_read_accepts_valid_option_none() {
let bytes: [u8; 2] = [0, 0]; let result = wincode::deserialize::<PodOption<PodBool>>(&bytes);
assert!(result.is_ok());
}
}
#[allow(dead_code)]
#[derive(PinaPod)]
#[pinapod(compact)]
struct CompactWithVecBool {
pub score: u64,
pub flags: pinapod::Vec<PodBool, 4>,
}
#[test]
fn compact_validate_rejects_invalid_vec_bool_element() {
let mut buf = vec![0u8; 13]; buf[8] = 3; buf[9] = 0;
buf[10] = 0; buf[11] = 1; buf[12] = 5;
assert!(
CompactWithVecBool::validate(&buf).is_err(),
"compact validate must reject Vec tail with invalid PodBool element"
);
}
#[test]
fn compact_validate_accepts_valid_vec_bool_elements() {
let mut buf = vec![0u8; 12]; buf[8] = 2; buf[9] = 0;
buf[10] = 0; buf[11] = 1;
assert!(CompactWithVecBool::validate(&buf).is_ok());
}