use super::*;
#[test]
fn slice_u8_input_two_params() {
let loc = SourceLocation::default();
let func: syn::ItemFn = syn::parse_quote!(
pub fn z_zbytes_from_bytes(bytes: &[u8]) -> ZZBytes {
unimplemented!()
}
);
let registry =
crate::test_util::reg_from_items(declare_referenced([(syn::Item::Fn(func), loc.clone())]))
.expect("index items");
let cbindgen = CbindgenBuilder::new()
.source_module(syn::parse_quote!(zenoh_flat))
.opaque_ptr(syn::parse_quote!(ZZBytes))
.base_name("z_zbytes")
.function(syn::parse_quote!(z_zbytes_from_bytes));
let src = write(cbindgen, registry, "slice_u8");
let compact: String = src.split_whitespace().collect();
assert!(compact.contains("bytes:*constu8"), "{src}");
assert!(compact.contains("bytes_len:usize"), "{src}");
assert!(
compact.contains("::core::slice::from_raw_parts(bytes,bytes_len)"),
"{src}"
);
assert!(compact.contains("->*mutz_zbytes"), "{src}");
}
#[test]
fn option_opaque_input_reuses_pointer() {
let loc = SourceLocation::default();
let func: syn::ItemFn = syn::parse_quote!(
pub fn z_op(attachment: Option<ZZBytes>) -> Result<(), Error> {
unimplemented!()
}
);
let registry = crate::test_util::reg_from_items(declare_referenced([
(syn::Item::Fn(func), loc.clone()),
(syn::Item::Struct(error_struct()), loc.clone()),
]))
.expect("index items");
let cbindgen = CbindgenBuilder::new()
.source_module(syn::parse_quote!(zenoh_flat))
.free_memory_function("z_free")
.opaque_ptr(syn::parse_quote!(ZZBytes))
.base_name("z_zbytes")
.data_struct(syn::parse_quote!(Error))
.base_name("z_error")
.error()
.function(syn::parse_quote!(z_op));
let src = write(cbindgen, registry, "option_in_opaque");
let compact: String = src.split_whitespace().collect();
assert!(compact.contains("attachment:*mutz_zbytes"), "{src}");
assert!(
compact.contains(
"ifv.is_null(){return::core::result::Result::Ok(::core::option::Option::None);}"
),
"{src}"
);
assert!(compact.contains("match__cbg_in_ZZBytes(v)"), "{src}");
assert!(compact.contains("e:*mutz_error"), "{src}");
assert!(compact.contains("__cbg_out_Error"), "{src}");
}
#[test]
fn option_scalar_input_boxed_pointer() {
let loc = SourceLocation::default();
let func: syn::ItemFn = syn::parse_quote!(
pub fn z_op(timestamp_ntp64: Option<i64>) {
unimplemented!()
}
);
let registry =
crate::test_util::reg_from_items(declare_referenced([(syn::Item::Fn(func), loc.clone())]))
.expect("index items");
let cbindgen = CbindgenBuilder::new()
.source_module(syn::parse_quote!(zenoh_flat))
.function(syn::parse_quote!(z_op));
let src = write(cbindgen, registry, "option_in_scalar");
let compact: String = src.split_whitespace().collect();
assert!(compact.contains("timestamp_ntp64:*consti64"), "{src}");
assert!(
compact.contains("ifv.is_null(){::core::option::Option::None}"),
"{src}"
);
assert!(compact.contains("::core::option::Option::Some"), "{src}");
assert!(!compact.contains("e:*mut"), "{src}");
}
#[test]
fn str_borrow_input_lowering() {
let loc = SourceLocation::default();
let func: syn::ItemFn = syn::parse_quote!(
pub fn z_init_logs(filter: &str) {
unimplemented!()
}
);
let registry =
crate::test_util::reg_from_items(declare_referenced([(syn::Item::Fn(func), loc.clone())]))
.expect("index items");
let cbindgen = CbindgenBuilder::new()
.source_module(syn::parse_quote!(zenoh_flat))
.function(syn::parse_quote!(z_init_logs))
.panic();
let src = write(cbindgen, registry, "str_borrow");
let compact: String = src.split_whitespace().collect();
assert!(compact.contains("extern\"C\"fnz_init_logs"), "{src}");
assert!(
compact.contains("filter:*const::core::ffi::c_char"),
"{src}"
);
assert!(compact.contains("CStr::from_ptr(v).to_str()"), "{src}");
assert!(compact.contains("panic!("), "{src}");
}
#[test]
fn relation_to_lowering() {
let loc = SourceLocation::default();
let func: syn::ItemFn = syn::parse_quote!(
pub fn z_keyexpr_relation_to(a: &ZKeyExpr, b: &ZKeyExpr) -> SetIntersectionLevel {
unimplemented!()
}
);
let enum_item: syn::ItemEnum = syn::parse_quote!(
pub enum SetIntersectionLevel {
Disjoint = 0,
Intersects = 1,
Includes = 2,
Equals = 3,
}
);
let registry = crate::test_util::reg_from_items(declare_referenced([
(syn::Item::Fn(func), loc.clone()),
(syn::Item::Enum(enum_item), loc.clone()),
]))
.expect("index items");
let cbindgen = CbindgenBuilder::new()
.source_module(syn::parse_quote!(zenoh_flat))
.opaque_ptr(syn::parse_quote!(ZKeyExpr))
.base_name("z_keyexpr")
.enum_type(syn::parse_quote!(SetIntersectionLevel))
.base_name("z_intersection")
.function(syn::parse_quote!(z_keyexpr_relation_to))
.panic();
let src = write(cbindgen, registry, "relation_to");
let compact: String = src.split_whitespace().collect();
assert!(compact.contains("#[repr(C)]"), "{src}");
assert!(compact.contains("pubenumz_intersection"), "{src}");
assert!(compact.contains("Disjoint=0"), "{src}");
assert!(
compact.contains("extern\"C\"fnz_keyexpr_relation_to"),
"{src}"
);
assert!(compact.contains("a:*constz_keyexpr"), "{src}");
assert!(compact.contains("b:*constz_keyexpr"), "{src}");
assert!(compact.contains("->z_intersection"), "{src}");
assert!(compact.contains("panic!("), "{src}");
assert!(
compact.contains("zenoh_flat::SetIntersectionLevel::Disjoint=>z_intersection::Disjoint"),
"{src}"
);
}
#[test]
fn enum_input_validates_the_discriminant() {
let loc = SourceLocation::default();
let func: syn::ItemFn = syn::parse_quote!(
pub fn z_keyexpr_require(level: SetIntersectionLevel) -> Result<(), Error> {
unimplemented!()
}
);
let enum_item: syn::ItemEnum = syn::parse_quote!(
pub enum SetIntersectionLevel {
Disjoint = 0,
Equals = LEVELS - 1,
}
);
let registry = crate::test_util::reg_from_items(declare_referenced([
(syn::Item::Fn(func), loc.clone()),
(syn::Item::Enum(enum_item), loc.clone()),
(syn::Item::Struct(error_struct()), loc.clone()),
]))
.expect("index items");
let cbindgen = CbindgenBuilder::new()
.source_module(syn::parse_quote!(zenoh_flat))
.free_memory_function("z_free")
.data_struct(syn::parse_quote!(Error))
.base_name("z_error")
.error()
.enum_type(syn::parse_quote!(SetIntersectionLevel))
.base_name("z_intersection")
.function(syn::parse_quote!(z_keyexpr_require));
let src = write(cbindgen, registry, "enum_input_validated");
let compact: String = src.split_whitespace().collect();
assert!(
compact.contains("level:::core::mem::MaybeUninit<z_intersection>"),
"{src}"
);
assert!(
!compact.contains("fn__cbg_in_SetIntersectionLevel(v:z_intersection)"),
"{src}"
);
assert!(
compact.contains(
"let__raw:::core::ffi::c_int=::core::ptr::read(v.as_ptr()as*const::core::ffi::c_int"
),
"{src}"
);
assert!(
compact.contains("if__raw==z_intersection::Equalsas::core::ffi::c_int"),
"{src}"
);
assert!(compact.contains("Equals=LEVELS-1"), "{src}");
assert!(
compact.contains("invaliddiscriminant{}for`z_intersection`"),
"{src}"
);
assert!(compact.contains("if!e.is_null()"), "{src}");
}
#[test]
fn enum_input_without_error_channel_requires_panic() {
let enum_item: syn::ItemEnum = syn::parse_quote!(
pub enum SetIntersectionLevel {
Disjoint = 0,
Equals = 1,
}
);
let func: syn::ItemFn = syn::parse_quote!(
pub fn z_intersection_value(level: SetIntersectionLevel) -> i32 {
unimplemented!()
}
);
let build = |allow_panic: bool| {
let loc = SourceLocation::default();
let registry = crate::test_util::reg_from_items(declare_referenced([
(syn::Item::Fn(func.clone()), loc.clone()),
(syn::Item::Enum(enum_item.clone()), loc.clone()),
]))
.expect("index items");
let cbindgen = CbindgenBuilder::new()
.source_module(syn::parse_quote!(zenoh_flat))
.enum_type(syn::parse_quote!(SetIntersectionLevel))
.base_name("z_intersection")
.function(syn::parse_quote!(z_intersection_value));
let cbindgen = if allow_panic {
cbindgen.panic()
} else {
cbindgen
};
write(cbindgen, registry, "enum_input_panic")
};
assert!(catch(|| {
build(false);
}));
let src = build(true);
let compact: String = src.split_whitespace().collect();
assert!(compact.contains("panic!("), "{src}");
}
#[test]
fn mutable_opaque_borrow_input_lowering() {
let loc = SourceLocation::default();
let func: syn::ItemFn = syn::parse_quote!(
pub fn z_config_insert_json5(
c: &mut ZConfig,
key: String,
value: String,
) -> Result<(), Error> {
unimplemented!()
}
);
let registry = crate::test_util::reg_from_items(declare_referenced([
(syn::Item::Fn(func), loc.clone()),
(syn::Item::Struct(error_struct()), loc.clone()),
]))
.expect("index items");
let cbindgen = CbindgenBuilder::new()
.source_module(syn::parse_quote!(zenoh_flat))
.free_memory_function("z_free")
.opaque_ptr(syn::parse_quote!(ZConfig))
.base_name("z_config")
.data_struct(syn::parse_quote!(Error))
.base_name("z_error")
.error()
.function(syn::parse_quote!(z_config_insert_json5));
let src = write(cbindgen, registry, "mut_opaque_borrow");
let compact: String = src.split_whitespace().collect();
assert!(
compact.contains("extern\"C\"fnz_config_insert_json5"),
"{src}"
);
assert!(compact.contains("c:*mutz_config"), "{src}");
assert!(!compact.contains("__h._0"), "{src}");
assert!(
compact.contains("Result::Ok(&mut*(vas*mutzenoh_flat::ZConfig))"),
"{src}"
);
}