use libssz::{ContainerDecoder, ContainerEncoder, DecodeError, SszDecode, SszEncode};
#[test]
fn bool_true_round_trip() {
let encoded = true.to_ssz();
assert_eq!(encoded, vec![1]);
assert!(bool::from_ssz_bytes(&encoded).unwrap());
}
#[test]
fn bool_false_round_trip() {
let encoded = false.to_ssz();
assert_eq!(encoded, vec![0]);
assert!(!bool::from_ssz_bytes(&encoded).unwrap());
}
#[test]
fn bool_invalid_byte() {
assert_eq!(
bool::from_ssz_bytes(&[2]),
Err(DecodeError::InvalidBooleanByte(2))
);
}
#[test]
fn bool_wrong_length() {
assert_eq!(
bool::from_ssz_bytes(&[0, 1]),
Err(DecodeError::InvalidFixedLength {
expected: 1,
got: 2
})
);
}
#[test]
fn u8_round_trip() {
for val in [0u8, 1, 127, 255] {
let encoded = val.to_ssz();
assert_eq!(encoded, vec![val]);
assert_eq!(u8::from_ssz_bytes(&encoded).unwrap(), val);
}
}
#[test]
fn u16_round_trip() {
let val: u16 = 0x0102;
let encoded = val.to_ssz();
assert_eq!(encoded, vec![0x02, 0x01]); assert_eq!(u16::from_ssz_bytes(&encoded).unwrap(), val);
}
#[test]
fn u32_round_trip() {
let val: u32 = 0x01020304;
let encoded = val.to_ssz();
assert_eq!(encoded, vec![0x04, 0x03, 0x02, 0x01]);
assert_eq!(u32::from_ssz_bytes(&encoded).unwrap(), val);
}
#[test]
fn u64_round_trip() {
let val: u64 = 0x0102030405060708;
let encoded = val.to_ssz();
assert_eq!(
encoded,
vec![0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01]
);
assert_eq!(u64::from_ssz_bytes(&encoded).unwrap(), val);
}
#[test]
fn u128_round_trip() {
let val: u128 = 1;
let encoded = val.to_ssz();
assert_eq!(encoded.len(), 16);
assert_eq!(u128::from_ssz_bytes(&encoded).unwrap(), val);
}
#[test]
fn u256_round_trip() {
let mut val = [0u8; 32];
val[0] = 1;
val[31] = 0xFF;
let encoded = val.to_ssz();
assert_eq!(encoded.len(), 32);
assert_eq!(<[u8; 32]>::from_ssz_bytes(&encoded).unwrap(), val);
}
#[test]
fn vec_u16_round_trip() {
let val: Vec<u16> = vec![1, 2, 3];
let encoded = val.to_ssz();
assert_eq!(encoded, vec![0x01, 0x00, 0x02, 0x00, 0x03, 0x00]);
assert_eq!(Vec::<u16>::from_ssz_bytes(&encoded).unwrap(), val);
}
#[test]
fn vec_empty() {
let val: Vec<u16> = vec![];
let encoded = val.to_ssz();
assert_eq!(encoded, vec![]);
assert_eq!(Vec::<u16>::from_ssz_bytes(&encoded).unwrap(), val);
}
#[test]
fn vec_of_vecs_round_trip() {
let val: Vec<Vec<u8>> = vec![vec![1, 2], vec![3], vec![4, 5, 6]];
let encoded = val.to_ssz();
let expected = vec![
12, 0, 0, 0, 14, 0, 0, 0, 15, 0, 0, 0, 1, 2, 3, 4, 5, 6, ];
assert_eq!(encoded, expected);
assert_eq!(Vec::<Vec<u8>>::from_ssz_bytes(&encoded).unwrap(), val);
}
#[test]
fn vec_of_vecs_empty() {
let val: Vec<Vec<u8>> = vec![];
let encoded = val.to_ssz();
assert!(encoded.is_empty());
assert_eq!(Vec::<Vec<u8>>::from_ssz_bytes(&encoded).unwrap(), val);
}
#[test]
fn container_mixed_round_trip() {
let a: u32 = 42;
let b: Vec<u8> = vec![0xAA, 0xBB, 0xCC];
let c: u16 = 1000;
let mut buf = Vec::new();
let fixed_part_len_enc = 4 + 4 + 2; let mut encoder = ContainerEncoder::new(&mut buf, fixed_part_len_enc);
encoder.append_fixed(&a);
encoder.append_variable(&b);
encoder.append_fixed(&c);
encoder.finalize();
let expected = vec![42, 0, 0, 0, 10, 0, 0, 0, 0xE8, 0x03, 0xAA, 0xBB, 0xCC];
assert_eq!(buf, expected);
let fixed_part_len = 4 + 4 + 2; let mut decoder = ContainerDecoder::new(&buf, fixed_part_len).unwrap();
let dec_a: u32 = decoder.decode_fixed().unwrap();
decoder.read_variable_offset().unwrap();
let dec_c: u16 = decoder.decode_fixed().unwrap();
let dec_b: Vec<u8> = decoder.decode_variable().unwrap();
assert_eq!(dec_a, a);
assert_eq!(dec_b, b);
assert_eq!(dec_c, c);
}
#[test]
fn container_all_fixed_round_trip() {
let x: u32 = 7;
let y: u64 = 999;
let mut buf = Vec::new();
let mut encoder = ContainerEncoder::new(&mut buf, 4 + 8);
encoder.append_fixed(&x);
encoder.append_fixed(&y);
encoder.finalize();
assert_eq!(buf.len(), 4 + 8);
let mut decoder = ContainerDecoder::new(&buf, 12).unwrap();
let dec_x: u32 = decoder.decode_fixed().unwrap();
let dec_y: u64 = decoder.decode_fixed().unwrap();
decoder.finish_fixed().unwrap();
assert_eq!(dec_x, x);
assert_eq!(dec_y, y);
}
#[test]
fn container_extra_bytes() {
let mut buf = vec![0u8; 16]; buf[0] = 7;
let mut decoder = ContainerDecoder::new(&buf, 12).unwrap();
let _x: u32 = decoder.decode_fixed().unwrap();
let _y: u64 = decoder.decode_fixed().unwrap();
assert!(decoder.finish_fixed().is_err());
}
#[test]
fn encoded_len_matches_actual() {
let val: Vec<Vec<u8>> = vec![vec![1, 2, 3], vec![], vec![4]];
assert_eq!(val.encoded_len(), val.to_ssz().len());
let fixed: Vec<u32> = vec![1, 2, 3, 4, 5];
assert_eq!(fixed.encoded_len(), fixed.to_ssz().len());
assert_eq!(true.encoded_len(), 1);
assert_eq!(42u64.encoded_len(), 8);
}
#[test]
fn u32_wrong_length() {
assert_eq!(
u32::from_ssz_bytes(&[1, 2, 3]),
Err(DecodeError::InvalidFixedLength {
expected: 4,
got: 3
})
);
}
#[test]
fn vec_u32_not_divisible() {
assert!(Vec::<u32>::from_ssz_bytes(&[1, 2, 3, 4, 5]).is_err());
}
#[test]
fn byte_array_4_round_trip() {
let val = [0x01, 0x02, 0x03, 0x04];
let encoded = val.to_ssz();
assert_eq!(<[u8; 4]>::from_ssz_bytes(&encoded).unwrap(), val);
}
#[test]
fn byte_array_20_round_trip() {
let mut val = [0u8; 20];
val[0] = 0xDE;
val[19] = 0xAD;
let encoded = val.to_ssz();
assert_eq!(encoded.len(), 20);
assert_eq!(<[u8; 20]>::from_ssz_bytes(&encoded).unwrap(), val);
}
#[test]
fn byte_array_48_round_trip() {
let mut val = [0u8; 48];
val[0] = 0xAB;
val[47] = 0xCD;
let encoded = val.to_ssz();
assert_eq!(encoded.len(), 48);
assert_eq!(<[u8; 48]>::from_ssz_bytes(&encoded).unwrap(), val);
}
#[test]
fn byte_array_96_round_trip() {
let mut val = [0u8; 96];
val[0] = 0x01;
val[95] = 0xFF;
let encoded = val.to_ssz();
assert_eq!(encoded.len(), 96);
assert_eq!(<[u8; 96]>::from_ssz_bytes(&encoded).unwrap(), val);
}
#[test]
fn byte_array_wrong_length() {
let err = <[u8; 48]>::from_ssz_bytes(&[0u8; 32]).unwrap_err();
assert_eq!(
err,
DecodeError::InvalidFixedLength {
expected: 48,
got: 32
}
);
}
#[test]
fn variable_list_truncated_offset_region() {
let err = Vec::<Vec<u8>>::from_ssz_bytes(&[0x01, 0x02]).unwrap_err();
assert_eq!(
err,
DecodeError::InvalidByteLength {
expected: 4,
got: 2
}
);
}
#[test]
fn variable_list_first_offset_not_aligned() {
let bytes = 5u32.to_le_bytes();
let err = Vec::<Vec<u8>>::from_ssz_bytes(&bytes).unwrap_err();
assert_eq!(
err,
DecodeError::InvalidFirstOffset {
expected: 0,
got: 5
}
);
}
#[test]
fn variable_list_offset_out_of_bounds() {
let mut bytes = Vec::new();
bytes.extend_from_slice(&8u32.to_le_bytes()); bytes.extend_from_slice(&255u32.to_le_bytes()); bytes.extend_from_slice(&[0xAA]); let err = Vec::<Vec<u8>>::from_ssz_bytes(&bytes).unwrap_err();
assert_eq!(
err,
DecodeError::OffsetOutOfBounds {
offset: 255,
length: 9
}
);
}
#[test]
fn variable_list_offsets_not_monotonic() {
let mut bytes = Vec::new();
bytes.extend_from_slice(&8u32.to_le_bytes()); bytes.extend_from_slice(&7u32.to_le_bytes()); bytes.extend_from_slice(&[0xAA, 0xBB]); let err = Vec::<Vec<u8>>::from_ssz_bytes(&bytes).unwrap_err();
assert_eq!(err, DecodeError::OffsetsAreNotMonotonicallyIncreasing);
}
#[test]
fn variable_list_single_empty_item() {
let bytes = 4u32.to_le_bytes();
let decoded = Vec::<Vec<u8>>::from_ssz_bytes(&bytes).unwrap();
assert_eq!(decoded, vec![Vec::<u8>::new()]);
}
#[test]
fn container_decoder_bytes_too_short() {
let bytes = [0u8; 8];
match ContainerDecoder::new(&bytes, 12) {
Err(DecodeError::InvalidByteLength {
expected: 12,
got: 8,
}) => {}
Err(e) => panic!("unexpected error: {e:?}"),
Ok(_) => panic!("expected error"),
}
}
#[test]
fn container_decoder_fixed_field_overflow() {
let bytes = [0u8; 4];
let mut decoder = ContainerDecoder::new(&bytes, 4).unwrap();
let err = decoder.decode_fixed::<u64>().unwrap_err();
assert_eq!(
err,
DecodeError::InvalidByteLength {
expected: 8, got: 4
}
);
}
#[test]
fn container_decoder_variable_offset_out_of_bounds() {
let mut bytes = Vec::new();
bytes.extend_from_slice(&255u32.to_le_bytes()); let mut decoder = ContainerDecoder::new(&bytes, 4).unwrap();
let err = decoder.read_variable_offset().unwrap_err();
assert_eq!(
err,
DecodeError::InvalidFirstOffset {
expected: 4,
got: 255
}
);
}
#[test]
fn container_decoder_variable_offsets_not_monotonic() {
let mut bytes = Vec::new();
bytes.extend_from_slice(&8u32.to_le_bytes()); bytes.extend_from_slice(&4u32.to_le_bytes()); let mut decoder = ContainerDecoder::new(&bytes, 8).unwrap();
decoder.read_variable_offset().unwrap(); let err = decoder.read_variable_offset().unwrap_err();
assert_eq!(err, DecodeError::OffsetsAreNotMonotonicallyIncreasing);
}
#[test]
fn container_decoder_decode_variable_without_offsets() {
let bytes = [0u8; 8];
let mut decoder = ContainerDecoder::new(&bytes, 8).unwrap();
let err = decoder.decode_variable::<Vec<u8>>().unwrap_err();
assert_eq!(
err,
DecodeError::InvalidByteLength {
expected: 1,
got: 0
}
);
}
#[test]
fn decode_error_display_formats_correctly() {
use std::fmt::Write;
let err = DecodeError::InvalidFixedLength {
expected: 4,
got: 2,
};
let mut s = String::new();
write!(s, "{err}").unwrap();
assert!(s.contains("InvalidFixedLength"));
assert!(s.contains("4"));
assert!(s.contains("2"));
let err_ref: &dyn std::error::Error = &err;
assert!(err_ref.to_string().contains("InvalidFixedLength"));
}
#[test]
fn encode_byte_array_7() {
let arr = [0xab_u8; 7];
assert_eq!(arr.to_ssz(), arr.to_vec());
assert_eq!(<[u8; 7] as SszEncode>::fixed_size(), 7);
assert!(<[u8; 7] as SszEncode>::is_fixed_size());
}
#[test]
fn encode_byte_array_52() {
let arr = [0xcd_u8; 52];
assert_eq!(arr.to_ssz(), arr.to_vec());
assert_eq!(<[u8; 52] as SszEncode>::fixed_size(), 52);
}
#[test]
fn encode_byte_array_100() {
let arr = [0xff_u8; 100];
assert_eq!(arr.to_ssz(), arr.to_vec());
assert_eq!(<[u8; 100] as SszEncode>::fixed_size(), 100);
}
#[test]
fn decode_byte_array_7() {
let bytes = [0xab_u8; 7];
let decoded = <[u8; 7]>::from_ssz_bytes(&bytes).unwrap();
assert_eq!(decoded, bytes);
}
#[test]
fn decode_byte_array_52() {
let bytes = [0xcd_u8; 52];
let decoded = <[u8; 52]>::from_ssz_bytes(&bytes).unwrap();
assert_eq!(decoded, bytes);
}
#[test]
fn decode_byte_array_wrong_length() {
let bytes = [0u8; 31];
let err = <[u8; 52]>::from_ssz_bytes(&bytes).unwrap_err();
assert_eq!(
err,
DecodeError::InvalidFixedLength {
expected: 52,
got: 31
}
);
}
#[test]
fn roundtrip_byte_array_33() {
let arr = [0x42_u8; 33];
let encoded = arr.to_ssz();
let decoded = <[u8; 33]>::from_ssz_bytes(&encoded).unwrap();
assert_eq!(arr, decoded);
}
#[test]
fn container_encoder_new() {
let mut buf1 = Vec::new();
let mut buf2 = Vec::new();
let mut enc1 = ContainerEncoder::new(&mut buf1, 4);
enc1.append_fixed(&42u32);
enc1.finalize();
let mut enc2 = ContainerEncoder::new(&mut buf2, 4);
enc2.append_fixed(&42u32);
enc2.finalize();
assert_eq!(buf1, buf2);
}