#![expect(clippy::tests_outside_test_module, reason = "integration test module")]
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
use pixelflow_core::{Core, CoreConfig, LogRecord, LogSink, Logger};
#[derive(Default)]
struct RecordingSink {
records: Mutex<Vec<LogRecord>>,
}
impl LogSink for RecordingSink {
fn log(&self, record: &LogRecord) {
self.records
.lock()
.expect("record lock poisoned")
.push(record.clone());
}
}
#[test]
#[ignore = "requires PIXELFLOW_SAMPLE_PLUGIN_PATH from a built sample plugin"]
fn sample_rust_plugin_loads_and_registers_filter() {
let path = std::env::var_os("PIXELFLOW_SAMPLE_PLUGIN_PATH")
.map(PathBuf::from)
.expect("PIXELFLOW_SAMPLE_PLUGIN_PATH must point to sample plugin dynamic library")
.canonicalize()
.expect("sample plugin path should be absolute or canonicalizable");
let directory = path
.parent()
.expect("sample plugin path should have parent")
.to_path_buf();
let sink = Arc::new(RecordingSink::default());
let logger = Logger::new(sink.clone());
let mut config = CoreConfig::default()
.with_auto_load_plugins(false)
.with_logger(logger);
config.plugin_directories_mut().push(directory);
let core = Core::with_config(config).expect("core should load sample plugin");
let loaded_plugin_names = core
.loaded_plugins()
.iter()
.map(|plugin| plugin.name().to_owned())
.collect::<Vec<_>>();
let log_messages = sink
.records
.lock()
.expect("record lock poisoned")
.iter()
.map(|record| record.message().to_owned())
.collect::<Vec<_>>();
assert!(
core.registry().contains_filter("sample.identity"),
"loaded_plugins={loaded_plugin_names:?}; logs={log_messages:?}"
);
assert!(
core.registry()
.metadata_schema()
.contains_key("pixelflow/sample:enabled")
);
assert!(
core.loaded_plugins()
.iter()
.any(|plugin| plugin.name() == "pixelflow-sample-plugin")
);
}