use gc_json_bridge::GCJsonBridge;
use gc_plugin_abi::*;
use serde_json::Value;
use std::sync::atomic::AtomicBool;
static INIT_CALLED: AtomicBool = AtomicBool::new(false);
unsafe extern "C" fn publish_datapoint_value(ctx: raw::GCCoreCtx, _dp_value: raw::GCDatapointValue) -> bool {
assert_eq!(
ctx,
std::ptr::null_mut(),
"The ctx should be null, as it was set in the function get_interface"
);
true
}
unsafe extern "C" fn system_log(ctx: raw::GCCoreCtx, _log_level: raw::GCLogLevel, _log: *const ::std::os::raw::c_char) {
assert_eq!(
ctx,
std::ptr::null_mut(),
"The ctx should be null, as it was set in the function get_interface"
);
}
unsafe extern "C" fn audit_log(ctx: raw::GCCoreCtx, _log: *const ::std::os::raw::c_char) {
assert_eq!(
ctx,
std::ptr::null_mut(),
"The ctx should be null, as it was set in the function get_interface"
);
}
unsafe extern "C" fn release_datapoint_value(_: raw::GCDatapointValue) -> bool {
true
}
unsafe extern "C" fn get_last_datapoint_value(ctx: raw::GCCoreCtx, _datapoint_id: raw::GCDatapointIdentifier) -> raw::GCDatapointValue {
assert_eq!(
ctx,
std::ptr::null_mut(),
"The ctx should be null, as it was set in the function get_interface"
);
std::ptr::null_mut()
}
pub fn get_config() -> Value {
let data = r#"
{
"name": "John Doe",
"age": 43,
"phones": [
"+44 1234567",
"+44 2345678"
]
}"#;
serde_json::from_str(data).unwrap()
}
pub fn get_interface(bridge: &GCJsonBridge) -> raw::sGCPluginInterface {
raw::sGCPluginInterface {
logLevel: raw::eGCLogLevel_INFO,
publishDatapointValueCallback: Some(publish_datapoint_value),
logSystemCallback: Some(system_log),
logAuditCallback: Some(audit_log),
releaseDatapointValueCallback: Some(release_datapoint_value),
getLastDatapointValueCallback: Some(get_last_datapoint_value),
getEthernetInterfaceCallback: None,
getSerialInterfaceCallback: None,
storeDatapointValueCallback: None,
config: raw::GCPluginConfig {
pluginJsonConfig: bridge.gc_json_bridge_callbacks() as *const raw::sGCJsonCallbacks,
ownDatapoints: std::ptr::null(),
ownDatapointsCount: 0,
subscribedDatapoints: std::ptr::null(),
subscribedDatapointsCount: 0,
},
ctx: std::ptr::null_mut(),
}
}
#[gc_plugin]
pub struct RestSomethingPlugin<'a> {
_plugin_interface: &'a GCPluginInterface,
}
impl<'a> RestSomethingPlugin<'a> {
pub fn new(plugin_interface: &'a GCPluginInterface) -> Self {
let config: Value = plugin_interface.get_own_configuration().expect("Failed to get configuration");
INIT_CALLED.store(true, std::sync::atomic::Ordering::SeqCst);
assert_eq!(get_config(), config);
Self {
_plugin_interface: plugin_interface,
}
}
}
impl<'a> GCPluginInstance<'a> for RestSomethingPlugin<'a> {
fn get_plugin_info() -> GCPluginInfo {
GCPluginInfo::new("RestSomethingPlugin", "0.1.0", "0", 0)
}
fn receive_datapoint(&self, _data_value: GCBorrowedDatapointValue) -> bool {
true
}
fn init(plugin_interface: &'a GCPluginInterface) -> Box<Self> {
Box::new(RestSomethingPlugin::new(plugin_interface))
}
}
#[cfg(test)]
mod tests {
use super::*;
use gc_utils::testing::gc_integration_test;
#[gc_integration_test]
fn test_config_loading() {
let info = allocation_counter::measure(|| {
let json_config = get_config();
let json_bridge = GCJsonBridge::new(&json_config);
let core_ifc = get_interface(&json_bridge);
unsafe {
let handle = gc_plugin_init(&core_ifc as raw::GCPluginInterface);
gc_plugin_shutdown(handle);
}
});
println!("{}", INIT_CALLED.load(std::sync::atomic::Ordering::SeqCst));
assert!(INIT_CALLED.load(std::sync::atomic::Ordering::SeqCst), "The init function was not called");
assert_eq!(info.bytes_current, 0, "Memory leak detected, ensure the shutdown function was called");
assert_eq!(info.count_current, 0, "Memory leak detected, ensure the shutdown function was called");
}
}