When you want to write unit tests for your Rust plugin that relies on functions / globals only available through a dynamically linked library, I thought the only way to test would be to abstract the functionality away. Abstracting is good, but may not always be the answer. I found out today that you can conditionally supply your own implementation of these functions for tests, benchmarks, etc.
I’ll use a crate of mine to give a concrete example. collectd-rust-plugin allows writing plugins in Rust that are instantiated by and communicate with the C daemon. This setup makes testing difficult.
Below is one such function that the daemon provides
extern "C" {
pub fn plugin_dispatch_values(vl: *const value_list_t) -> ::std::os::raw::c_int;
}
Running any code that called this function in a unit test would result in a linker error, as the function would be missing. You can supply your own implementation for tests by using the export_name directive
#[cfg(test)]
pub mod overrides {
#[no_mangle]
pub extern "C" fn plugin_dispatch_values(vl: *const value_list_t) -> ::std::os::raw::c_int {
0
}
}
When I came across this solution and verified it works, I just had to share