use std::sync::{Arc, Weak};
use alpha2_ffmpeg_bridge::{BridgeError, GpuFault, NativeGpuBackend};
pub(crate) trait Backend {
type Context;
type Surface;
const BACKEND: NativeGpuBackend;
const STATUSES: &'static [(i32, Option<GpuFault>)];
fn context() -> Option<Self::Context>;
fn surface(context: &Self::Context) -> Arc<Self::Surface>;
fn fail_next_import(status: i32);
fn import(context: &Self::Context, surface: Arc<Self::Surface>) -> Result<(), BridgeError>;
fn leaked() -> u64;
}
fn import<B: Backend>(context: &B::Context) -> (Result<(), BridgeError>, Weak<B::Surface>) {
let surface = B::surface(context);
let probe = Arc::downgrade(&surface);
(B::import(context, surface), probe)
}
pub(crate) fn check<B: Backend>() {
let Some(context) = B::context() else {
return;
};
let backend = B::BACKEND.as_str();
let leaked = B::leaked();
let (imported, probe) = import::<B>(&context);
imported.unwrap_or_else(|error| panic!("{backend}: a healthy import fails: {error}"));
assert!(
probe.upgrade().is_none(),
"{backend}: a finished import keeps its surface"
);
for &(status, fault) in B::STATUSES {
B::fail_next_import(status);
let (imported, probe) = import::<B>(&context);
let error = imported.expect_err("the injected failure fails the import");
let BridgeError::NativeGpu(failure) = &error else {
panic!("{backend} status {status}: not a native GPU failure: {error:?}");
};
assert_eq!(failure.backend, B::BACKEND, "{error}");
assert_eq!(failure.status, status, "{error}");
assert_eq!(
failure.fault, fault,
"{backend} status {status} names the wrong fault: {error}"
);
assert!(
probe.upgrade().is_none(),
"{backend} status {status}: an import that submitted nothing keeps its surface"
);
assert_eq!(
B::leaked(),
leaked,
"{backend} status {status}: an import that submitted nothing leaks"
);
let (imported, probe) = import::<B>(&context);
imported.unwrap_or_else(|error| {
panic!("{backend} status {status}: the next import fails: {error}")
});
assert!(
probe.upgrade().is_none(),
"{backend} status {status}: the next import keeps its surface"
);
}
assert_eq!(B::leaked(), leaked, "{backend}: the suite leaks");
}