Files
improvise/crates/zset-ffi/tests/dylib.rs
T
2026-10-10 11:53:08 -07:00

64 lines
2.4 KiB
Rust

//! The built shared library, loaded the way a CFFI caller loads it.
//! Evidence: `context/test-evidence/zset-ffi.md`.
use libloading::{Library, Symbol};
use std::path::PathBuf;
use std::ptr::null_mut;
type Opaque = std::ffi::c_void;
/// Cargo puts the cdylib in `target/<profile>/deps` beside this test binary's own directory.
fn library() -> PathBuf {
let exe = std::env::current_exe().unwrap();
let deps = exe.parent().unwrap();
let ext = if cfg!(target_os = "macos") {
"dylib"
} else {
"so"
};
let name = format!("{}zset_ffi.{ext}", if cfg!(windows) { "" } else { "lib" });
[deps.join(&name), deps.parent().unwrap().join(&name)]
.into_iter()
.find(|p| p.exists())
.unwrap_or_else(|| panic!("{name} was not built next to {}", deps.display()))
}
#[test]
fn a_loaded_library_adds_queries_frees_and_reports_overflow() {
// SAFETY: loads this workspace's own library; the symbols below have the header's types.
unsafe {
let lib = Library::new(library()).unwrap();
let version: Symbol<extern "C" fn() -> u32> = lib.get(b"zs_abi_version").unwrap();
let new: Symbol<extern "C" fn(*mut *mut Opaque) -> i32> = lib.get(b"zs_zset_new").unwrap();
let free: Symbol<extern "C" fn(*mut Opaque)> = lib.get(b"zs_zset_free").unwrap();
let insert: Symbol<extern "C" fn(*mut Opaque, *const u8, usize, i64) -> i32> =
lib.get(b"zs_zset_insert").unwrap();
let weight: Symbol<extern "C" fn(*const Opaque, *const u8, usize, *mut i64) -> i32> =
lib.get(b"zs_zset_weight").unwrap();
let last: Symbol<extern "C" fn() -> *const std::ffi::c_char> =
lib.get(b"zs_last_error").unwrap();
assert_eq!(version(), 1);
let mut z = null_mut();
assert_eq!(new(&mut z), 0);
assert_eq!(insert(z, b"k".as_ptr(), 1, 40), 0);
assert_eq!(insert(z, b"k".as_ptr(), 1, 2), 0);
let mut w = 0;
assert_eq!(weight(z, b"k".as_ptr(), 1, &mut w), 0);
assert_eq!(w, 42);
assert_eq!(
insert(z, b"k".as_ptr(), 1, i64::MAX),
2,
"overflow is ZS_ERR_OVERFLOW"
);
assert!(
std::ffi::CStr::from_ptr(last())
.to_str()
.unwrap()
.contains("overflow")
);
assert_eq!(weight(z, b"k".as_ptr(), 1, &mut w), 0);
assert_eq!(w, 42, "the failed insert changed nothing");
free(z);
}
}