extern crate capnp;
use capnp::message;
#[test]
fn canonicalize_succeeds_on_null_message() {
let segment: &[capnp::Word] = &[
capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
];
let segments = &[capnp::Word::words_to_bytes(segment)];
let segment_array = message::SegmentArray::new(segments);
let message = message::Reader::new(segment_array, Default::default());
assert!(message.is_canonical().unwrap());
let canonical_bytes = message.canonicalize().unwrap();
assert_eq!(&canonical_bytes[..], segment);
}
#[test]
fn dont_truncate_struct_too_far() {
let segment: &[capnp::Word] = &[
capnp::word(0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00),
capnp::word(0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11),
capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80),
capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
];
let segments = &[capnp::Word::words_to_bytes(segment)];
let segment_array = message::SegmentArray::new(segments);
let message = message::Reader::new(segment_array, Default::default());
assert!(!message.is_canonical().unwrap());
let canonicalized = message.canonicalize().unwrap();
let canonical_segment: &[capnp::Word] = &[
capnp::word(0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00),
capnp::word(0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11),
capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80),
];
assert_eq!(&canonicalized[..], canonical_segment);
}
#[test]
fn dont_truncate_struct_list_too_far() {
let segment: &[capnp::Word] = &[
capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00),
capnp::word(0x01, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00),
capnp::word(0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00),
capnp::word(0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22),
capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80),
capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
];
let segments = &[capnp::Word::words_to_bytes(segment)];
let segment_array = message::SegmentArray::new(segments);
let message = message::Reader::new(segment_array, Default::default());
assert!(!message.is_canonical().unwrap());
let canonicalized = message.canonicalize().unwrap();
let canonical_segment: &[capnp::Word] = &[
capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00),
capnp::word(0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00),
capnp::word(0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00),
capnp::word(0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22),
capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80),
];
assert_eq!(&canonicalized[..], canonical_segment);
}
#[test]
fn canonical_non_null_empty_struct_field() {
let segment: &[capnp::Word] = &[
capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00),
capnp::word(0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00),
capnp::word(0xfc, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00),
capnp::word(0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee),
];
let segments = &[capnp::Word::words_to_bytes(segment)];
let segment_array = message::SegmentArray::new(segments);
let message = message::Reader::new(segment_array, Default::default());
assert!(message.is_canonical().unwrap());
}
#[test]
fn pointer_to_empty_struct_preorder_not_canonical() {
let segment: &[capnp::Word] = &[
capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00),
capnp::word(0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00),
capnp::word(0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
capnp::word(0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee),
];
let segments = &[capnp::Word::words_to_bytes(segment)];
let segment_array = message::SegmentArray::new(segments);
let message = message::Reader::new(segment_array, Default::default());
assert!(!message.is_canonical().unwrap());
}
#[test]
fn is_canonical_requires_pointer_preorder() {
let segment: &[capnp::Word] = &[
capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00),
capnp::word(0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00),
capnp::word(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00),
capnp::word(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07),
capnp::word(0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00),
];
let segments = &[capnp::Word::words_to_bytes(segment)];
let segment_array = message::SegmentArray::new(segments);
let message = message::Reader::new(segment_array, Default::default());
assert!(!message.is_canonical().unwrap());
}
#[test]
fn is_canonical_requires_dense_packing() {
let segment: &[capnp::Word] = &[
capnp::word(0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00),
capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
capnp::word(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07),
];
let segments = &[capnp::Word::words_to_bytes(segment)];
let segment_array = message::SegmentArray::new(segments);
let message = message::Reader::new(segment_array, Default::default());
assert!(!message.is_canonical().unwrap());
}
#[test]
fn simple_multisegment_message() {
let segment0: &[capnp::Word] = &[
capnp::word(0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00),
];
let segment1: &[capnp::Word] = &[
capnp::word(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00),
capnp::word(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07),
];
let segments = &[capnp::Word::words_to_bytes(segment0),
capnp::Word::words_to_bytes(segment1)];
let segment_array = message::SegmentArray::new(segments);
let message = message::Reader::new(segment_array, Default::default());
assert!(!message.is_canonical().unwrap());
let canonicalized = message.canonicalize().unwrap();
let canonical_segment: &[capnp::Word] = &[
capnp::word(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00),
capnp::word(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07),
];
assert_eq!(&canonicalized[..], canonical_segment);
}
#[test]
fn multisegment_only_first_segment_used() {
let segment0: &[capnp::Word] = &[
capnp::word(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00),
capnp::word(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07),
];
let segment1: &[capnp::Word] = &[
capnp::word(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00),
];
let segments = &[capnp::Word::words_to_bytes(segment0),
capnp::Word::words_to_bytes(segment1)];
let segment_array = message::SegmentArray::new(segments);
let message = message::Reader::new(segment_array, Default::default());
assert!(!message.is_canonical().unwrap());
let canonicalized = message.canonicalize().unwrap();
let canonical_segment: &[capnp::Word] = &[
capnp::word(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00),
capnp::word(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07),
];
assert_eq!(&canonicalized[..], canonical_segment);
}
#[test]
fn is_canonical_requires_truncation_of_0_valued_struct_fields() {
let segment: &[capnp::Word] = &[
capnp::word(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00),
capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
];
let segments = &[capnp::Word::words_to_bytes(segment)];
let segment_array = message::SegmentArray::new(segments);
let message = message::Reader::new(segment_array, Default::default());
assert!(!message.is_canonical().unwrap());
}
#[test]
fn is_canonical_rejects_unused_trailing_words() {
let segment: &[capnp::Word] = &[
capnp::word(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00),
capnp::word(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07),
capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
];
let segments = &[capnp::Word::words_to_bytes(segment)];
let segment_array = message::SegmentArray::new(segments);
let message = message::Reader::new(segment_array, Default::default());
assert!(!message.is_canonical().unwrap());
}
#[test]
fn empty_inline_composite_list_of_0_sized_structs() {
let segment: &[capnp::Word] = &[
capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00),
capnp::word(0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00),
capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
];
let segments = &[capnp::Word::words_to_bytes(segment)];
let segment_array = message::SegmentArray::new(segments);
let message = message::Reader::new(segment_array, Default::default());
assert!(message.is_canonical().unwrap());
let canonical_words = message.canonicalize().unwrap();
assert_eq!(segment, &canonical_words[..]);
}
#[test]
fn inline_composite_list_with_void_list() {
let segment: &[capnp::Word] = &[
capnp::word(0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00),
capnp::word(0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00),
capnp::word(0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00),
];
let segments = &[capnp::Word::words_to_bytes(segment)];
let segment_array = message::SegmentArray::new(segments);
let message = message::Reader::new(segment_array, Default::default());
assert!(message.is_canonical().unwrap());
let canonical_words = message.canonicalize().unwrap();
assert_eq!(segment, &canonical_words[..]);
}
#[test]
fn is_canonical_rejects_inline_composite_list_with_inaccurate_word_length() {
let segment: &[capnp::Word] = &[
capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00),
capnp::word(0x05, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00),
capnp::word(0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00),
capnp::word(0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00),
capnp::word(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07),
capnp::word(0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00),
];
let segments = &[capnp::Word::words_to_bytes(segment)];
let segment_array = message::SegmentArray::new(segments);
let message = message::Reader::new(segment_array, Default::default());
assert!(!message.is_canonical().unwrap());
}
#[test]
fn truncate_data_section_inline_composite() {
let segment: &[capnp::Word] = &[
capnp::word(0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00),
capnp::word(0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00),
capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
capnp::word(0x01, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00),
capnp::word(0x35, 0x35, 0x35, 0x2d, 0x31, 0x32, 0x31, 0x32),
capnp::word(0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
];
let segments = &[capnp::Word::words_to_bytes(segment)];
let segment_array = message::SegmentArray::new(segments);
let message = message::Reader::new(segment_array, Default::default());
assert!(!message.is_canonical().unwrap());
let canonical_words = message.canonicalize().unwrap();
let canonical_segments = &[capnp::Word::words_to_bytes(&canonical_words[..])];
let canonical_segment_array = message::SegmentArray::new(canonical_segments);
let canonical_message = message::Reader::new(canonical_segment_array, Default::default());
assert!(canonical_message.is_canonical().unwrap());
}
#[test]
fn truncate_pointer_section_inline_composite() {
let segment: &[capnp::Word] = &[
capnp::word(0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00),
capnp::word(0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00),
capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
capnp::word(0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa),
capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
];
let segments = &[capnp::Word::words_to_bytes(segment)];
let segment_array = message::SegmentArray::new(segments);
let message = message::Reader::new(segment_array, Default::default());
assert!(!message.is_canonical().unwrap());
let canonical_words = message.canonicalize().unwrap();
let canonical_segments = &[capnp::Word::words_to_bytes(&canonical_words[..])];
let canonical_segment_array = message::SegmentArray::new(canonical_segments);
let canonical_message = message::Reader::new(canonical_segment_array, Default::default());
assert!(canonical_message.is_canonical().unwrap());
let expected_canonical_words: &[capnp::Word] = &[
capnp::word(0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00),
capnp::word(0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00),
capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
capnp::word(0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa),
];
assert_eq!(expected_canonical_words, &canonical_words[..]);
}
#[test]
fn list_padding_must_be_zero() {
let segment: &[capnp::Word] = &[
capnp::word(0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00),
capnp::word(0x01, 0x02, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00),
];
let segments = &[capnp::Word::words_to_bytes(segment)];
let segment_array = message::SegmentArray::new(segments);
let message = message::Reader::new(segment_array, Default::default());
assert!(!message.is_canonical().unwrap());
let canonical_words = message.canonicalize().unwrap();
let canonical_segments = &[capnp::Word::words_to_bytes(&canonical_words[..])];
let canonical_segment_array = message::SegmentArray::new(canonical_segments);
let canonical_message = message::Reader::new(canonical_segment_array, Default::default());
assert!(canonical_message.is_canonical().unwrap());
let expected_canonical_words: &[capnp::Word] = &[
capnp::word(0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00),
capnp::word(0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00),
];
assert_eq!(expected_canonical_words, &canonical_words[..]);
}
#[test]
fn bit_list_padding_must_be_zero() {
let segment: &[capnp::Word] = &[
capnp::word(0x01, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00),
capnp::word(0xee, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
];
let segments = &[capnp::Word::words_to_bytes(segment)];
let segment_array = message::SegmentArray::new(segments);
let message = message::Reader::new(segment_array, Default::default());
assert!(!message.is_canonical().unwrap());
let canonical_words = message.canonicalize().unwrap();
let canonical_segments = &[capnp::Word::words_to_bytes(&canonical_words[..])];
let canonical_segment_array = message::SegmentArray::new(canonical_segments);
let canonical_message = message::Reader::new(canonical_segment_array, Default::default());
assert!(canonical_message.is_canonical().unwrap());
let expected_canonical_words: &[capnp::Word] = &[
capnp::word(0x01, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00),
capnp::word(0xee, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
];
assert_eq!(expected_canonical_words, &canonical_words[..]);
}
#[test]
fn out_of_bounds_zero_sized_list_returns_error() {
let segment: &[capnp::Word] = &[
capnp::word(0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00),
];
let segments = &[capnp::Word::words_to_bytes(segment)];
let segment_array = message::SegmentArray::new(segments);
let message = message::Reader::new(segment_array, Default::default());
assert!(message.is_canonical().is_err());
}
#[test]
fn out_of_bounds_zero_sized_void_list_returns_error() {
let segment: &[capnp::Word] = &[
capnp::word(0x01, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00),
];
let segments = &[capnp::Word::words_to_bytes(segment)];
let segment_array = message::SegmentArray::new(segments);
let message = message::Reader::new(segment_array, Default::default());
assert!(message.is_canonical().is_err());
}
#[test]
fn far_pointer_to_same_segment() {
let segment: &[capnp::Word] = &[
capnp::word(0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
capnp::word(0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
capnp::word(0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00),
];
let segments = &[capnp::Word::words_to_bytes(segment)];
let segment_array = message::SegmentArray::new(segments);
let message = message::Reader::new(segment_array, Default::default());
assert!(!message.is_canonical().unwrap());
}