validate: Make use of rust more complex error types in action types

For sync action failures, instead of requiring users to report the error
through the Reporter interface, let it pass the detail of the failure into
the ActionError::Error directly and report it in the validate reporting
system automatically.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1265>
This commit is contained in:
Thibault Saunier 2023-06-09 07:10:46 -04:00 committed by GStreamer Marge Bot
parent 45d4725de9
commit 0e4b03ada0
2 changed files with 43 additions and 15 deletions

View file

@ -1,7 +1,7 @@
use std::{ffi::c_int, ptr}; use std::{ffi::c_int, ptr};
use crate::ffi; use crate::ffi;
use glib::translate::*; use glib::{object::Cast, translate::*};
#[derive(Debug)] #[derive(Debug)]
#[repr(transparent)] #[repr(transparent)]
@ -325,14 +325,29 @@ impl<'a> ActionTypeBuilder<'a> {
) -> c_int { ) -> c_int {
let action_type = ffi::gst_validate_get_action_type((*action).type_); let action_type = ffi::gst_validate_get_action_type((*action).type_);
let scenario = from_glib_borrow(scenario); let scenario = from_glib_borrow(scenario);
let action = crate::Action::from_glib_borrow(action); let raction = from_glib_borrow(action);
let func: &ActionFunction = &*(gst::ffi::gst_mini_object_get_qdata( let func: &ActionFunction = &*(gst::ffi::gst_mini_object_get_qdata(
action_type as *mut gst::ffi::GstMiniObject, action_type as *mut gst::ffi::GstMiniObject,
QUARK_ACTION_TYPE_FUNC.get().unwrap().into_glib(), QUARK_ACTION_TYPE_FUNC.get().unwrap().into_glib(),
) as *const Box<ActionFunction>); ) as *const Box<ActionFunction>);
(*func)(&scenario, action).into_glib() let res = (*func)(&scenario, raction);
if let Err(crate::ActionError::Error(ref err)) = res {
scenario
.dynamic_cast_ref::<crate::Reporter>()
.unwrap()
.report_action(
&crate::Action::from_glib_none(action),
glib::Quark::from_str("scenario::execution-error"),
err,
);
return ffi::GST_VALIDATE_EXECUTE_ACTION_ERROR_REPORTED;
}
res.into_glib()
} }
unsafe { unsafe {
@ -391,6 +406,7 @@ impl ActionTypeExtManual for crate::ActionType {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::{ use std::{
env,
io::Write, io::Write,
sync::{Arc, Condvar, Mutex}, sync::{Arc, Condvar, Mutex},
}; };
@ -399,6 +415,8 @@ mod tests {
fn test_action_types() { fn test_action_types() {
gst::init().unwrap(); gst::init().unwrap();
use crate::prelude::*; use crate::prelude::*;
// Validate should not exit process on criticals
env::set_var("GST_VALIDATE", "");
crate::init(); crate::init();
let fails_called = Arc::new(Mutex::new(false)); let fails_called = Arc::new(Mutex::new(false));
@ -410,7 +428,9 @@ mod tests {
move |_, _action| { move |_, _action| {
*fails_called.lock().unwrap() = true; *fails_called.lock().unwrap() = true;
Err(crate::ActionError::Error) Err(crate::ActionError::Error(
"the `fails` action seems to fail".into(),
))
} }
), ),
) )
@ -509,7 +529,7 @@ mod tests {
scenario.connect_action_done(glib::clone!( scenario.connect_action_done(glib::clone!(
#[strong] #[strong]
async_called, async_called,
move |_, action| { move |_, _| {
async_called.1.notify_one(); async_called.1.notify_one();
} }
)); ));

View file

@ -35,11 +35,10 @@ impl IntoGlib for ActionSuccess {
} }
} }
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] #[derive(Clone, Debug, Eq, PartialEq, Hash)]
#[repr(i32)] #[repr(i32)]
pub enum ActionError { pub enum ActionError {
Error = ffi::GST_VALIDATE_EXECUTE_ACTION_ERROR, Error(String),
ErrorReported = ffi::GST_VALIDATE_EXECUTE_ACTION_ERROR_REPORTED,
None = ffi::GST_VALIDATE_EXECUTE_ACTION_NONE, None = ffi::GST_VALIDATE_EXECUTE_ACTION_NONE,
} }
@ -47,10 +46,11 @@ impl ActionError {
pub fn from_value(value: impl Into<i32>) -> Self { pub fn from_value(value: impl Into<i32>) -> Self {
skip_assert_initialized!(); skip_assert_initialized!();
match value.into() { match value.into() {
ffi::GST_VALIDATE_EXECUTE_ACTION_ERROR => ActionError::Error, ffi::GST_VALIDATE_EXECUTE_ACTION_ERROR => {
ffi::GST_VALIDATE_EXECUTE_ACTION_ERROR_REPORTED => ActionError::ErrorReported, ActionError::Error("Execution failed".to_string())
}
ffi::GST_VALIDATE_EXECUTE_ACTION_NONE => ActionError::None, ffi::GST_VALIDATE_EXECUTE_ACTION_NONE => ActionError::None,
_ => ActionError::Error, _ => ActionError::Error("Unknown error".to_string()),
} }
} }
} }
@ -60,7 +60,10 @@ impl IntoGlib for ActionError {
#[inline] #[inline]
fn into_glib(self) -> ffi::GstValidateActionReturn { fn into_glib(self) -> ffi::GstValidateActionReturn {
self as ffi::GstValidateActionReturn match self {
ActionError::Error(_) => ffi::GST_VALIDATE_EXECUTE_ACTION_ERROR,
ActionError::None => ffi::GST_VALIDATE_EXECUTE_ACTION_NONE,
}
} }
} }
@ -129,9 +132,10 @@ impl ActionReturn {
#[inline] #[inline]
pub fn into_result(self) -> Result<ActionSuccess, ActionError> { pub fn into_result(self) -> Result<ActionSuccess, ActionError> {
match self { match self {
Self::Error | Self::ErrorReported | Self::None => { Self::Error | Self::ErrorReported => {
Err(unsafe { std::mem::transmute::<ActionReturn, ActionError>(self) }) Err(ActionError::Error("Execution failed".to_string()))
} }
Self::None => Err(ActionError::None),
_ => Ok(unsafe { std::mem::transmute::<ActionReturn, ActionSuccess>(self) }), _ => Ok(unsafe { std::mem::transmute::<ActionReturn, ActionSuccess>(self) }),
} }
} }
@ -139,7 +143,11 @@ impl ActionReturn {
#[inline] #[inline]
pub fn from_error(v: ActionError) -> Self { pub fn from_error(v: ActionError) -> Self {
skip_assert_initialized!(); skip_assert_initialized!();
unsafe { std::mem::transmute::<ActionError, ActionReturn>(v) }
match v {
ActionError::Error(_) => Self::Error,
ActionError::None => Self::None,
}
} }
#[inline] #[inline]