#![cfg(feature = "reflect")]
use buffa::{DecodeError, DecodeOptions, Message};
use buffa_descriptor::generated::descriptor::field_descriptor_proto::{Label, Type};
use buffa_descriptor::generated::descriptor::{
DescriptorProto, FieldDescriptorProto, FileDescriptorProto, FileDescriptorSet,
};
use buffa_descriptor::{DescriptorPool, PoolError};
fn wide_descriptor_set(files: usize, messages_per_file: usize) -> Vec<u8> {
let mut set = FileDescriptorSet::default();
for f in 0..files {
let mut file = FileDescriptorProto {
name: Some(format!("wide/f{f}.proto")),
package: Some(format!("wide.p{f}")),
syntax: Some("proto3".to_string()),
..Default::default()
};
for m in 0..messages_per_file {
file.message_type.push(DescriptorProto {
name: Some(format!("M{m}")),
field: (0..8)
.map(|k| FieldDescriptorProto {
name: Some(format!("f{k}")),
number: Some(k + 1),
label: Some(Label::Optional),
r#type: Some(Type::String),
json_name: Some(format!("f{k}")),
..Default::default()
})
.collect(),
..Default::default()
});
}
set.file.push(file);
}
set.encode_to_vec()
}
#[test]
fn decode_applies_the_default_element_memory_bound() {
let bytes = wide_descriptor_set(400, 40);
assert!(bytes.len() < 32 * 1024 * 1024, "{} bytes", bytes.len());
match DescriptorPool::decode(&bytes) {
Err(PoolError::Decode(DecodeError::ElementMemoryLimitExceeded)) => {}
other => panic!("expected the element-memory bound to reject this, got {other:?}"),
}
}
#[test]
fn decode_with_options_can_lift_the_bound() {
let bytes = wide_descriptor_set(400, 40);
let opts = DecodeOptions::new().with_element_memory_limit(usize::MAX);
let pool = DescriptorPool::decode_with_options(&bytes, &opts)
.expect("an unbounded decode accepts the same bytes");
assert!(pool.message_index("wide.p0.M0").is_some());
assert!(pool.message_index("wide.p399.M39").is_some());
}
#[test]
fn decode_with_options_still_rejects_beyond_the_given_bound() {
let bytes = wide_descriptor_set(400, 40);
let opts = DecodeOptions::new().with_element_memory_limit(64 * 1024);
match DescriptorPool::decode_with_options(&bytes, &opts) {
Err(PoolError::Decode(DecodeError::ElementMemoryLimitExceeded)) => {}
other => panic!("expected a caller-supplied bound to be enforced, got {other:?}"),
}
}
#[test]
fn decode_and_decode_with_options_agree_on_defaults() {
let bytes = wide_descriptor_set(2, 2);
let a = DescriptorPool::decode(&bytes).expect("small set decodes");
let b = DescriptorPool::decode_with_options(&bytes, &DecodeOptions::new())
.expect("small set decodes with explicit defaults");
assert!(a.message_index("wide.p1.M1").is_some());
assert_eq!(a.message_index("wide.p1.M1"), b.message_index("wide.p1.M1"));
}