mod common;
use audio_core_bsd::{AudioFrame, ProcessContext};
use audio_plugin_bsd::{is_abi_compatible, PluginLoader, AUDIO_PLUGIN_ABI_VERSION};
fn approx_eq(a: f32, b: f32) -> bool {
(a - b).abs() < 1e-6
}
#[test]
fn load_abi_verify_metadata_instantiate_process_unload() {
let so = common::ensure_test_plugin_built();
let mut loader = PluginLoader::new();
let id = loader
.load(&so)
.expect("plugin should load with a matching ABI magic + major version");
let meta = loader.metadata(id).expect("loaded plugin has metadata");
assert_eq!(meta.name, "test-plugin");
assert_eq!(meta.version, "0.1.0");
assert_eq!(meta.description, "cdylib test plugin");
assert!(
is_abi_compatible(AUDIO_PLUGIN_ABI_VERSION, meta.abi_version),
"metadata abi_version {:#010x} must be major-compatible with host {:#010x}",
meta.abi_version,
AUDIO_PLUGIN_ABI_VERSION,
);
let mut node = loader
.instantiate(id)
.expect("loaded plugin instantiates an AudioNode");
let mut ctx = ProcessContext::new(8, 0, 48_000);
let input =
AudioFrame::from_planar(1, 48_000, vec![0.1, -0.2, 0.3, -0.4, 0.5, -0.6, 0.7, -0.8]);
let mut outputs = [AudioFrame::silence(1, 8, 48_000)];
node.process(&mut ctx, std::slice::from_ref(&input), &mut outputs);
let out = &outputs[0];
assert_eq!(out.samples.len(), input.samples.len());
for (got, want) in out.samples.iter().zip(input.samples.iter()) {
assert!(
approx_eq(*got, *want),
"pass-through output sample mismatch: got {got}, want {want}"
);
}
drop(node);
assert!(loader.is_loaded(id), "still loaded before unload");
loader.unload(id).expect("unload drops the library");
assert!(!loader.is_loaded(id), "no longer loaded after unload");
}
#[test]
fn loading_same_path_twice_yields_distinct_ids() {
let so = common::ensure_test_plugin_built();
let mut loader = PluginLoader::new();
let first = loader.load(&so).expect("first load");
let second = loader.load(&so).expect("second load");
assert_ne!(first, second, "each load receives a fresh id");
assert_eq!(loader.len(), 2);
assert_eq!(loader.metadata(first).unwrap().name, "test-plugin");
assert_eq!(loader.metadata(second).unwrap().name, "test-plugin");
loader.unload(first).expect("unload first");
assert!(!loader.is_loaded(first));
assert!(loader.is_loaded(second), "second survives first's unload");
loader.unload(second).expect("unload second");
assert!(loader.is_empty());
}