#![cfg(feature = "reflect")]
use std::sync::Arc;
use buffa::editions::{EnumType, FieldPresence};
use buffa_descriptor::{DescriptorPool, FieldKind, ScalarType, SingularKind};
const FDS_BYTES: &[u8] = include_bytes!("protos/reflect_test.fds");
fn pool() -> Arc<DescriptorPool> {
Arc::new(DescriptorPool::decode(FDS_BYTES).expect("pool builds from protoc FDS"))
}
#[test]
fn pool_registers_all_types() {
let p = pool();
assert!(p.message_by_name("reflect.test.Scalars").is_some());
assert!(p.message_by_name("reflect.test.Containers").is_some());
assert!(p.message_by_name("reflect.test.Inner").is_some());
assert!(p.message_by_name("reflect.test.OneOf").is_some());
assert!(p.enum_by_name("reflect.test.Color").is_some());
assert!(p.message_by_name("reflect.editions.Editions").is_some());
assert!(p.enum_by_name("reflect.editions.Status").is_some());
assert!(p.enum_by_name("reflect.test.Scalars").is_none());
assert!(p.message_by_name("reflect.test.Color").is_none());
assert!(p.message_by_name("reflect.test.NoSuchType").is_none());
}
#[test]
fn scalar_fields_link_with_proto3_presence() {
let p = pool();
let scalars = p.message_by_name("reflect.test.Scalars").unwrap();
assert_eq!(scalars.fields().len(), 16);
let f_int32 = scalars.field(3).unwrap();
assert_eq!(f_int32.name(), "f_int32");
assert_eq!(f_int32.json_name(), "fInt32");
assert_eq!(
f_int32.kind(),
FieldKind::Singular(SingularKind::Scalar(ScalarType::Int32))
);
assert_eq!(f_int32.presence(), FieldPresence::Implicit);
let f_opt = scalars.field(16).unwrap();
assert_eq!(f_opt.presence(), FieldPresence::Explicit);
assert!(f_opt.oneof_index().is_some());
let oneof_idx = f_opt.oneof_index().unwrap() as usize;
assert!(scalars.oneofs()[oneof_idx].is_synthetic());
}
#[test]
fn container_fields_link_correctly() {
let p = pool();
let containers = p.message_by_name("reflect.test.Containers").unwrap();
let packed = containers.field(1).unwrap();
assert_eq!(
packed.kind(),
FieldKind::List(SingularKind::Scalar(ScalarType::Int32))
);
assert!(packed.is_packed());
let strings = containers.field(2).unwrap();
assert_eq!(
strings.kind(),
FieldKind::List(SingularKind::Scalar(ScalarType::String))
);
assert!(!strings.is_packed());
let tags = containers.field(3).unwrap();
assert_eq!(
tags.kind(),
FieldKind::Map {
key: ScalarType::String,
value: SingularKind::Scalar(ScalarType::Int32),
}
);
let children = containers.field(4).unwrap();
let inner_idx = p.message_index("reflect.test.Inner").unwrap();
assert_eq!(
children.kind(),
FieldKind::Map {
key: ScalarType::Int32,
value: SingularKind::Message(inner_idx),
}
);
let nested = containers.field(5).unwrap();
assert_eq!(
nested.kind(),
FieldKind::Singular(SingularKind::Message(inner_idx))
);
assert_eq!(nested.presence(), FieldPresence::Explicit);
let color = containers.field(6).unwrap();
let color_idx = p.enum_index("reflect.test.Color").unwrap();
assert_eq!(
color.kind(),
FieldKind::Singular(SingularKind::Enum(color_idx))
);
let colors = containers.field(7).unwrap();
assert_eq!(
colors.kind(),
FieldKind::List(SingularKind::Enum(color_idx))
);
assert!(colors.is_packed());
}
#[test]
fn enum_links_with_proto3_open() {
let p = pool();
let color = p.enum_by_name("reflect.test.Color").unwrap();
assert_eq!(color.enum_type(), EnumType::Open);
assert_eq!(color.values().len(), 4);
assert_eq!(color.value(1).unwrap().name(), "RED");
assert_eq!(color.value_by_name("BLUE").unwrap().number(), 3);
}
#[test]
fn oneof_links() {
let p = pool();
let oneof = p.message_by_name("reflect.test.OneOf").unwrap();
assert_eq!(oneof.oneofs().len(), 1);
let o = &oneof.oneofs()[0];
assert_eq!(o.name(), "variant");
assert!(!o.is_synthetic());
assert_eq!(o.field_indices(), vec![0, 1, 2]);
}
#[test]
fn editions_feature_resolution() {
let p = pool();
let editions = p.message_by_name("reflect.editions.Editions").unwrap();
let explicit = editions.field(2).unwrap();
assert_eq!(
explicit.presence(),
FieldPresence::Explicit,
"editions 2023 default"
);
let implicit = editions.field(1).unwrap();
assert_eq!(
implicit.presence(),
FieldPresence::Implicit,
"explicit field-level override"
);
let packed_default = editions.field(3).unwrap();
assert!(
packed_default.is_packed(),
"editions 2023 packs by default — this is the case buffa-reflect gets wrong"
);
let unpacked = editions.field(4).unwrap();
assert!(!unpacked.is_packed(), "explicit EXPANDED override");
let status = p.enum_by_name("reflect.editions.Status").unwrap();
assert_eq!(status.enum_type(), EnumType::Closed);
}
#[test]
fn idempotent_re_add() {
let mut p = DescriptorPool::decode(FDS_BYTES).unwrap();
let count = p.messages().len();
use buffa::Message;
let set =
buffa_descriptor::generated::descriptor::FileDescriptorSet::decode_from_slice(FDS_BYTES)
.unwrap();
p.add_file_descriptor_set(set).unwrap();
assert_eq!(
p.messages().len(),
count,
"re-adding the same files is a no-op"
);
}
#[test]
fn service_descriptor_links() {
let p = pool();
let svc = p
.service_by_name("reflect.test.Demo")
.expect("Demo service registered");
assert_eq!(svc.full_name(), "reflect.test.Demo");
assert_eq!(svc.methods().len(), 4);
let inner_idx = p.message_index("reflect.test.Inner").unwrap();
let containers_idx = p.message_index("reflect.test.Containers").unwrap();
let get = svc.method("Get").expect("Get method");
assert_eq!(get.name(), "Get");
assert_eq!(get.input(), inner_idx);
assert_eq!(get.output(), containers_idx);
assert!(!get.is_client_streaming());
assert!(!get.is_server_streaming());
let push = svc.method("Push").expect("Push method");
assert!(push.is_client_streaming());
assert!(!push.is_server_streaming());
let pull = svc.method("Pull").expect("Pull method");
assert!(!pull.is_client_streaming());
assert!(pull.is_server_streaming());
let sync = svc.method("Sync").expect("Sync method");
assert!(sync.is_client_streaming());
assert!(sync.is_server_streaming());
assert!(svc.method("Nonexistent").is_none());
assert!(p.service_by_name("reflect.test.Other").is_none());
let idx = p.service_index("reflect.test.Demo").expect("indexed");
assert_eq!(p.service(idx).full_name(), "reflect.test.Demo");
}
#[test]
fn extensions_link() {
let p = pool();
let extendable = p.message_index("reflect.ext.Extendable").unwrap();
let ext = p
.extension_by_name("reflect.ext.ext_int32")
.expect("file-level extension registered");
assert_eq!(ext.full_name(), "reflect.ext.ext_int32");
assert_eq!(ext.extendee(), extendable);
assert_eq!(ext.field().name(), "ext_int32");
assert_eq!(ext.field().number(), 100);
assert_eq!(
ext.field().kind(),
FieldKind::Singular(SingularKind::Scalar(ScalarType::Int32))
);
assert_eq!(ext.field().presence(), FieldPresence::Explicit);
let rep = p.extension_by_name("reflect.ext.ext_repeated").unwrap();
assert_eq!(
rep.field().kind(),
FieldKind::List(SingularKind::Scalar(ScalarType::Int32))
);
let payload = p.message_index("reflect.ext.Payload").unwrap();
let msg_ext = p.extension_by_name("reflect.ext.ext_message").unwrap();
assert_eq!(
msg_ext.field().kind(),
FieldKind::Singular(SingularKind::Message(payload))
);
let nested = p
.extension_by_name("reflect.ext.Scope.ext_nested")
.expect("message-scoped extension registered under its scope");
assert_eq!(nested.extendee(), extendable);
assert_eq!(nested.field().number(), 110);
assert!(p.extension_by_name("reflect.ext.ext_nested").is_none());
assert!(p.extension_for(extendable, 100).is_some());
assert!(p.extension_for(extendable, 99).is_none());
let all: Vec<u32> = p
.extensions_of(extendable)
.map(|e| e.field().number())
.collect();
assert_eq!(all, vec![100, 101, 102, 103, 110, 120]);
let inner = p.message_index("reflect.test.Inner").unwrap();
assert_eq!(p.extensions_of(inner).count(), 0);
}