mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2024-11-26 11:31:06 +00:00
Add tests for pad and element subclassing
This commit is contained in:
parent
c282f34c74
commit
698120c620
2 changed files with 263 additions and 0 deletions
|
@ -431,3 +431,196 @@ unsafe extern "C" fn element_set_context<T: ObjectSubclass>(
|
|||
imp.set_context(&wrap, &from_glib_borrow(context))
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use glib;
|
||||
use glib::subclass;
|
||||
use std::sync::Mutex;
|
||||
|
||||
struct TestElement {
|
||||
srcpad: ::Pad,
|
||||
sinkpad: ::Pad,
|
||||
n_buffers: Mutex<u32>,
|
||||
reached_playing: Mutex<bool>,
|
||||
}
|
||||
|
||||
impl TestElement {
|
||||
fn set_pad_functions(sinkpad: &::Pad, srcpad: &::Pad) {
|
||||
sinkpad.set_chain_function(|pad, parent, buffer| {
|
||||
TestElement::catch_panic_pad_function(
|
||||
parent,
|
||||
|| Err(::FlowError::Error),
|
||||
|identity, element| identity.sink_chain(pad, element, buffer),
|
||||
)
|
||||
});
|
||||
sinkpad.set_event_function(|pad, parent, event| {
|
||||
TestElement::catch_panic_pad_function(
|
||||
parent,
|
||||
|| false,
|
||||
|identity, element| identity.sink_event(pad, element, event),
|
||||
)
|
||||
});
|
||||
sinkpad.set_query_function(|pad, parent, query| {
|
||||
TestElement::catch_panic_pad_function(
|
||||
parent,
|
||||
|| false,
|
||||
|identity, element| identity.sink_query(pad, element, query),
|
||||
)
|
||||
});
|
||||
|
||||
srcpad.set_event_function(|pad, parent, event| {
|
||||
TestElement::catch_panic_pad_function(
|
||||
parent,
|
||||
|| false,
|
||||
|identity, element| identity.src_event(pad, element, event),
|
||||
)
|
||||
});
|
||||
srcpad.set_query_function(|pad, parent, query| {
|
||||
TestElement::catch_panic_pad_function(
|
||||
parent,
|
||||
|| false,
|
||||
|identity, element| identity.src_query(pad, element, query),
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
fn sink_chain(
|
||||
&self,
|
||||
_pad: &::Pad,
|
||||
_element: &::Element,
|
||||
buffer: ::Buffer,
|
||||
) -> Result<::FlowSuccess, ::FlowError> {
|
||||
*self.n_buffers.lock().unwrap() += 1;
|
||||
self.srcpad.push(buffer)
|
||||
}
|
||||
|
||||
fn sink_event(&self, _pad: &::Pad, _element: &::Element, event: ::Event) -> bool {
|
||||
self.srcpad.push_event(event)
|
||||
}
|
||||
|
||||
fn sink_query(&self, _pad: &::Pad, _element: &::Element, query: &mut ::QueryRef) -> bool {
|
||||
self.srcpad.peer_query(query)
|
||||
}
|
||||
|
||||
fn src_event(&self, _pad: &::Pad, _element: &::Element, event: ::Event) -> bool {
|
||||
self.sinkpad.push_event(event)
|
||||
}
|
||||
|
||||
fn src_query(&self, _pad: &::Pad, _element: &::Element, query: &mut ::QueryRef) -> bool {
|
||||
self.sinkpad.peer_query(query)
|
||||
}
|
||||
}
|
||||
|
||||
impl ObjectSubclass for TestElement {
|
||||
const NAME: &'static str = "TestElement";
|
||||
type ParentType = ::Element;
|
||||
type Instance = ::subclass::ElementInstanceStruct<Self>;
|
||||
type Class = subclass::simple::ClassStruct<Self>;
|
||||
|
||||
glib_object_subclass!();
|
||||
|
||||
fn new_with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
|
||||
let templ = klass.get_pad_template("sink").unwrap();
|
||||
let sinkpad = ::Pad::new_from_template(&templ, Some("sink"));
|
||||
let templ = klass.get_pad_template("src").unwrap();
|
||||
let srcpad = ::Pad::new_from_template(&templ, Some("src"));
|
||||
|
||||
TestElement::set_pad_functions(&sinkpad, &srcpad);
|
||||
|
||||
Self {
|
||||
n_buffers: Mutex::new(0),
|
||||
reached_playing: Mutex::new(false),
|
||||
srcpad,
|
||||
sinkpad,
|
||||
}
|
||||
}
|
||||
|
||||
fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
|
||||
klass.set_metadata(
|
||||
"Test Element",
|
||||
"Generic",
|
||||
"Does nothing",
|
||||
"Sebastian Dröge <sebastian@centricular.com>",
|
||||
);
|
||||
|
||||
let caps = ::Caps::new_any();
|
||||
let src_pad_template =
|
||||
::PadTemplate::new("src", ::PadDirection::Src, ::PadPresence::Always, &caps)
|
||||
.unwrap();
|
||||
klass.add_pad_template(src_pad_template);
|
||||
|
||||
let sink_pad_template =
|
||||
::PadTemplate::new("sink", ::PadDirection::Sink, ::PadPresence::Always, &caps)
|
||||
.unwrap();
|
||||
klass.add_pad_template(sink_pad_template);
|
||||
}
|
||||
}
|
||||
|
||||
impl ObjectImpl for TestElement {
|
||||
glib_object_impl!();
|
||||
|
||||
fn constructed(&self, obj: &glib::Object) {
|
||||
self.parent_constructed(obj);
|
||||
|
||||
let element = obj.downcast_ref::<::Element>().unwrap();
|
||||
element.add_pad(&self.sinkpad).unwrap();
|
||||
element.add_pad(&self.srcpad).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl ElementImpl for TestElement {
|
||||
fn change_state(
|
||||
&self,
|
||||
element: &::Element,
|
||||
transition: ::StateChange,
|
||||
) -> Result<::StateChangeSuccess, ::StateChangeError> {
|
||||
let res = self.parent_change_state(element, transition)?;
|
||||
|
||||
if transition == ::StateChange::PausedToPlaying {
|
||||
*self.reached_playing.lock().unwrap() = true;
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_element_subclass() {
|
||||
::init().unwrap();
|
||||
|
||||
let element = glib::Object::new(TestElement::get_type(), &[("name", &"test")])
|
||||
.unwrap()
|
||||
.downcast::<::Element>()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(element.get_name(), "test");
|
||||
|
||||
assert_eq!(
|
||||
element.get_metadata(&::ELEMENT_METADATA_LONGNAME),
|
||||
Some("Test Element")
|
||||
);
|
||||
|
||||
let pipeline = ::Pipeline::new(None);
|
||||
let src = ::ElementFactory::make("fakesrc", None).unwrap();
|
||||
let sink = ::ElementFactory::make("fakesink", None).unwrap();
|
||||
|
||||
src.set_property("num-buffers", &100i32).unwrap();
|
||||
|
||||
pipeline.add_many(&[&src, &element, &sink]).unwrap();
|
||||
::Element::link_many(&[&src, &element, &sink]).unwrap();
|
||||
|
||||
pipeline.set_state(::State::Playing).unwrap();
|
||||
let bus = pipeline.get_bus().unwrap();
|
||||
|
||||
let eos = bus.timed_pop_filtered(::CLOCK_TIME_NONE, &[::MessageType::Eos]);
|
||||
assert!(eos.is_some());
|
||||
|
||||
pipeline.set_state(::State::Null).unwrap();
|
||||
|
||||
let imp = TestElement::from_instance(&element);
|
||||
assert_eq!(*imp.n_buffers.lock().unwrap(), 100);
|
||||
assert_eq!(*imp.reached_playing.lock().unwrap(), true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,3 +97,73 @@ unsafe extern "C" fn pad_unlinked<T: ObjectSubclass>(
|
|||
|
||||
imp.unlinked(&wrap, &from_glib_borrow(peer))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::prelude::*;
|
||||
use glib;
|
||||
use glib::subclass;
|
||||
use std::sync::Mutex;
|
||||
|
||||
struct TestPad {
|
||||
linked: Mutex<bool>,
|
||||
unlinked: Mutex<bool>,
|
||||
}
|
||||
|
||||
impl ObjectSubclass for TestPad {
|
||||
const NAME: &'static str = "TestPad";
|
||||
type ParentType = ::Pad;
|
||||
type Instance = subclass::simple::InstanceStruct<Self>;
|
||||
type Class = subclass::simple::ClassStruct<Self>;
|
||||
|
||||
glib_object_subclass!();
|
||||
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
linked: Mutex::new(false),
|
||||
unlinked: Mutex::new(false),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ObjectImpl for TestPad {
|
||||
glib_object_impl!();
|
||||
}
|
||||
|
||||
impl PadImpl for TestPad {
|
||||
fn linked(&self, pad: &Pad, peer: &Pad) {
|
||||
*self.linked.lock().unwrap() = true;
|
||||
self.parent_linked(pad, peer)
|
||||
}
|
||||
|
||||
fn unlinked(&self, pad: &Pad, peer: &Pad) {
|
||||
*self.unlinked.lock().unwrap() = true;
|
||||
self.parent_unlinked(pad, peer)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pad_subclass() {
|
||||
::init().unwrap();
|
||||
|
||||
let pad = glib::Object::new(
|
||||
TestPad::get_type(),
|
||||
&[("name", &"test"), ("direction", &::PadDirection::Src)],
|
||||
)
|
||||
.unwrap()
|
||||
.downcast::<::Pad>()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(pad.get_name(), "test");
|
||||
|
||||
let otherpad = ::Pad::new(Some("other-test"), ::PadDirection::Sink);
|
||||
pad.link(&otherpad).unwrap();
|
||||
pad.unlink(&otherpad).unwrap();
|
||||
|
||||
let imp = TestPad::from_instance(&pad);
|
||||
assert!(*imp.linked.lock().unwrap());
|
||||
assert!(*imp.unlinked.lock().unwrap());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue