datafusion_ffi/tests/
utils.rs1use std::path::{Path, PathBuf};
19
20use datafusion_common::{DataFusionError, Result};
21
22use crate::tests::ForeignLibraryModule;
23
24fn compute_library_dir(target_path: &Path) -> PathBuf {
26 let debug_dir = target_path.join("debug");
27 let release_dir = target_path.join("release");
28 let ci_dir = target_path.join("ci");
29
30 let all_dirs = vec![debug_dir.clone(), release_dir, ci_dir];
31
32 all_dirs
33 .into_iter()
34 .filter(|dir| dir.join("deps").exists())
35 .filter_map(|dir| {
36 dir.join("deps")
37 .metadata()
38 .and_then(|m| m.modified())
39 .ok()
40 .map(|date| (dir, date))
41 })
42 .max_by_key(|(_, date)| *date)
43 .map(|(dir, _)| dir)
44 .unwrap_or(debug_dir)
45}
46
47fn find_cdylib(deps_dir: &Path) -> Result<PathBuf> {
49 let lib_prefix = if cfg!(target_os = "windows") {
50 ""
51 } else {
52 "lib"
53 };
54 let lib_ext = if cfg!(target_os = "macos") {
55 "dylib"
56 } else if cfg!(target_os = "windows") {
57 "dll"
58 } else {
59 "so"
60 };
61
62 let pattern = format!("{lib_prefix}datafusion_ffi.{lib_ext}");
63 let lib_path = deps_dir.join(&pattern);
64
65 if lib_path.exists() {
66 return Ok(lib_path);
67 }
68
69 Err(DataFusionError::External(
70 format!("Could not find library at {}", lib_path.display()).into(),
71 ))
72}
73
74pub fn get_module() -> Result<ForeignLibraryModule> {
75 let expected_version = crate::version();
76
77 let crate_root = Path::new(env!("CARGO_MANIFEST_DIR"));
78 let target_dir = crate_root
79 .parent()
80 .expect("Failed to find crate parent")
81 .parent()
82 .expect("Failed to find workspace root")
83 .join("target");
84
85 let library_dir = compute_library_dir(target_dir.as_path());
86 let lib_path = find_cdylib(&library_dir.join("deps"))?;
87
88 let lib = unsafe {
90 libloading::Library::new(&lib_path)
91 .map_err(|e| DataFusionError::External(Box::new(e)))?
92 };
93
94 let get_module: libloading::Symbol<extern "C" fn() -> ForeignLibraryModule> = unsafe {
95 lib.get(b"datafusion_ffi_get_module")
96 .map_err(|e| DataFusionError::External(Box::new(e)))?
97 };
98
99 let module = get_module();
100
101 assert_eq!((module.version)(), expected_version);
102
103 std::mem::forget(lib);
105
106 Ok(module)
107}