use super::*;
#[test]
fn test_gen_bridge_wrapper_struct_contains_struct_name() {
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", vec![]);
let config = make_trait_bridge_config(None, None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let result = gen_bridge_wrapper_struct(&spec, &generator);
assert!(
result.contains("pub struct PyOcrBackendBridge"),
"missing struct declaration in:\n{result}"
);
}
#[test]
fn test_gen_bridge_wrapper_struct_contains_inner_field() {
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", vec![]);
let config = make_trait_bridge_config(None, None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let result = gen_bridge_wrapper_struct(&spec, &generator);
assert!(result.contains("inner: Py<PyAny>"), "missing inner field in:\n{result}");
}
#[test]
fn test_gen_bridge_wrapper_struct_contains_cached_name() {
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", vec![]);
let config = make_trait_bridge_config(None, None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let result = gen_bridge_wrapper_struct(&spec, &generator);
assert!(
result.contains("cached_name: String"),
"missing cached_name field in:\n{result}"
);
}
#[test]
fn test_gen_bridge_plugin_impl_returns_none_when_no_super_trait() {
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", vec![]);
let config = make_trait_bridge_config(None, None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
assert!(gen_bridge_plugin_impl(&spec, &generator).is_none());
}
#[test]
fn test_gen_bridge_plugin_impl_returns_some_when_super_trait_configured() {
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", vec![]);
let config = make_trait_bridge_config(Some("Plugin"), None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
assert!(gen_bridge_plugin_impl(&spec, &generator).is_some());
}
#[test]
fn test_gen_bridge_plugin_impl_uses_qualified_super_trait_path() {
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", vec![]);
let config = make_trait_bridge_config(Some("Plugin"), None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let result = gen_bridge_plugin_impl(&spec, &generator).unwrap();
assert!(
result.contains("impl mylib::Plugin for PyOcrBackendBridge"),
"missing qualified super-trait path in:\n{result}"
);
}
#[test]
fn test_gen_bridge_plugin_impl_uses_already_qualified_super_trait_path() {
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", vec![]);
let config = make_trait_bridge_config(Some("other_crate::Plugin"), None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let result = gen_bridge_plugin_impl(&spec, &generator).unwrap();
assert!(
result.contains("impl other_crate::Plugin for PyOcrBackendBridge"),
"wrong super-trait path in:\n{result}"
);
}
#[test]
fn test_gen_bridge_plugin_impl_contains_name_fn() {
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", vec![]);
let config = make_trait_bridge_config(Some("Plugin"), None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let result = gen_bridge_plugin_impl(&spec, &generator).unwrap();
assert!(
result.contains("fn name(") && result.contains("cached_name"),
"missing name() using cached_name in:\n{result}"
);
}
#[test]
fn test_gen_bridge_plugin_impl_contains_version_fn() {
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", vec![]);
let config = make_trait_bridge_config(Some("Plugin"), None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let result = gen_bridge_plugin_impl(&spec, &generator).unwrap();
assert!(result.contains("fn version("), "missing version() in:\n{result}");
}
#[test]
fn test_gen_bridge_plugin_impl_contains_initialize_fn() {
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", vec![]);
let config = make_trait_bridge_config(Some("Plugin"), None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let result = gen_bridge_plugin_impl(&spec, &generator).unwrap();
assert!(result.contains("fn initialize("), "missing initialize() in:\n{result}");
}
#[test]
fn test_gen_bridge_plugin_impl_contains_shutdown_fn() {
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", vec![]);
let config = make_trait_bridge_config(Some("Plugin"), None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let result = gen_bridge_plugin_impl(&spec, &generator).unwrap();
assert!(result.contains("fn shutdown("), "missing shutdown() in:\n{result}");
}
#[test]
fn test_gen_bridge_trait_impl_includes_impl_header() {
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", vec![]);
let config = make_trait_bridge_config(None, None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let result = gen_bridge_trait_impl(&spec, &generator);
assert!(
result.contains("impl mylib::OcrBackend for PyOcrBackendBridge"),
"missing impl header in:\n{result}"
);
}
#[test]
fn test_gen_bridge_trait_impl_includes_method_signatures() {
let methods = vec![make_method(
"process",
vec![],
TypeRef::String,
false,
false,
None,
None,
)];
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", methods);
let config = make_trait_bridge_config(None, None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let result = gen_bridge_trait_impl(&spec, &generator);
assert!(result.contains("fn process("), "missing method signature in:\n{result}");
}
#[test]
fn test_gen_bridge_trait_impl_includes_method_body_from_generator() {
let methods = vec![make_method(
"process",
vec![],
TypeRef::String,
false,
false,
None,
None,
)];
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", methods);
let config = make_trait_bridge_config(None, None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let result = gen_bridge_trait_impl(&spec, &generator);
assert!(
result.contains("// sync body for process"),
"missing sync method body in:\n{result}"
);
}
#[test]
fn test_gen_bridge_trait_impl_async_method_uses_async_body() {
let methods = vec![make_method(
"process_async",
vec![],
TypeRef::String,
true,
false,
None,
None,
)];
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", methods);
let config = make_trait_bridge_config(None, None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let result = gen_bridge_trait_impl(&spec, &generator);
assert!(
result.contains("// async body for process_async"),
"missing async method body in:\n{result}"
);
assert!(
result.contains("async fn process_async("),
"missing async keyword in method signature in:\n{result}"
);
}
#[test]
fn test_gen_bridge_trait_impl_filters_trait_source_methods() {
let methods = vec![
make_method("own_method", vec![], TypeRef::String, false, false, None, None),
make_method(
"inherited_method",
vec![],
TypeRef::String,
false,
false,
Some("other_crate::OtherTrait"),
None,
),
];
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", methods);
let config = make_trait_bridge_config(None, None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let result = gen_bridge_trait_impl(&spec, &generator);
assert!(
result.contains("fn own_method("),
"own method should be present in:\n{result}"
);
assert!(
!result.contains("fn inherited_method("),
"inherited method should be filtered out in:\n{result}"
);
}
#[test]
fn test_gen_bridge_trait_impl_method_with_params() {
let params = vec![
make_param("input", TypeRef::String, true),
make_param("count", TypeRef::Primitive(PrimitiveType::U32), false),
];
let methods = vec![make_method(
"process",
params,
TypeRef::String,
false,
false,
None,
None,
)];
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", methods);
let config = make_trait_bridge_config(None, None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let result = gen_bridge_trait_impl(&spec, &generator);
assert!(result.contains("input: &str"), "missing &str param in:\n{result}");
assert!(result.contains("count: u32"), "missing u32 param in:\n{result}");
}
#[test]
fn test_gen_bridge_trait_impl_return_type_with_error() {
let methods = vec![make_method(
"process",
vec![],
TypeRef::String,
false,
false,
None,
Some("MyError"),
)];
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", methods);
let config = make_trait_bridge_config(None, None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let result = gen_bridge_trait_impl(&spec, &generator);
assert!(
result.contains("-> std::result::Result<String, mylib::MyError>"),
"missing std::result::Result return type in:\n{result}"
);
}
#[test]
fn test_gen_bridge_registration_fn_returns_none_without_register_fn() {
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", vec![]);
let config = make_trait_bridge_config(None, None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
assert!(gen_bridge_registration_fn(&spec, &generator).is_none());
}
#[test]
fn test_gen_bridge_registration_fn_returns_some_with_register_fn() {
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", vec![]);
let config = make_trait_bridge_config(None, Some("register_ocr_backend"));
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let result = gen_bridge_registration_fn(&spec, &generator);
assert!(result.is_some());
let code = result.unwrap();
assert!(
code.contains("register_ocr_backend"),
"missing register fn name in:\n{code}"
);
}
#[test]
fn test_gen_bridge_all_includes_imports() {
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", vec![]);
let config = make_trait_bridge_config(None, None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let output = gen_bridge_all(&spec, &generator);
assert!(output.imports.contains(&"pyo3::prelude::*".to_string()));
assert!(output.imports.contains(&"pyo3::types::PyString".to_string()));
}
#[test]
fn test_gen_bridge_all_includes_wrapper_struct() {
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", vec![]);
let config = make_trait_bridge_config(None, None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let output = gen_bridge_all(&spec, &generator);
assert!(
output.code.contains("pub struct PyOcrBackendBridge"),
"missing struct in:\n{}",
output.code
);
}
#[test]
fn test_gen_bridge_all_includes_constructor() {
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", vec![]);
let config = make_trait_bridge_config(None, None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let output = gen_bridge_all(&spec, &generator);
assert!(
output.code.contains("pub fn new("),
"missing constructor in:\n{}",
output.code
);
}
#[test]
fn test_gen_bridge_all_includes_trait_impl() {
let methods = vec![make_method(
"process",
vec![],
TypeRef::String,
false,
false,
None,
None,
)];
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", methods);
let config = make_trait_bridge_config(None, None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let output = gen_bridge_all(&spec, &generator);
assert!(
output.code.contains("impl mylib::OcrBackend for PyOcrBackendBridge"),
"missing trait impl in:\n{}",
output.code
);
}
#[test]
fn test_gen_bridge_all_includes_plugin_impl_when_super_trait_set() {
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", vec![]);
let config = make_trait_bridge_config(Some("Plugin"), None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let output = gen_bridge_all(&spec, &generator);
assert!(
output.code.contains("impl mylib::Plugin for PyOcrBackendBridge"),
"missing plugin impl in:\n{}",
output.code
);
}
#[test]
fn test_gen_bridge_all_no_plugin_impl_when_no_super_trait() {
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", vec![]);
let config = make_trait_bridge_config(None, None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let output = gen_bridge_all(&spec, &generator);
assert!(
!output.code.contains("fn name(") || !output.code.contains("cached_name"),
"unexpected plugin impl present without super_trait"
);
}
#[test]
fn test_gen_bridge_all_includes_registration_fn_when_configured() {
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", vec![]);
let config = make_trait_bridge_config(None, Some("register_ocr_backend"));
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let output = gen_bridge_all(&spec, &generator);
assert!(
output.code.contains("register_ocr_backend"),
"missing registration fn in:\n{}",
output.code
);
}
#[test]
fn test_gen_bridge_all_no_registration_fn_when_absent() {
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", vec![]);
let config = make_trait_bridge_config(None, None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let output = gen_bridge_all(&spec, &generator);
assert!(
!output.code.contains("register_ocr_backend"),
"unexpected registration fn present:\n{}",
output.code
);
}
#[test]
fn test_gen_bridge_all_ordering_struct_before_trait_impl() {
let trait_def = make_type_def("OcrBackend", "mylib::OcrBackend", vec![]);
let config = make_trait_bridge_config(None, None);
let spec = make_spec(&trait_def, &config, "Py", HashMap::new());
let generator = MockBridgeGenerator;
let output = gen_bridge_all(&spec, &generator);
let struct_pos = output.code.find("pub struct PyOcrBackendBridge").unwrap();
let impl_pos = output
.code
.find("impl mylib::OcrBackend for PyOcrBackendBridge")
.unwrap();
assert!(struct_pos < impl_pos, "struct should appear before trait impl");
}