validate: Start a testsuite

Currently implemented tests are:
  * Settup and cleanup on monitor is done properly
  * Some tests in the PadMonitor are done properly, namely:
        - Buffer before segment
        - Buffer outside segment
        - First buffer running time is always 0
        - The Demuxer flow aggregation is properly checked

https://bugzilla.gnome.org/show_bug.cgi?id=736379
This commit is contained in:
Thibault Saunier 2014-09-10 09:47:22 +02:00 committed by Thibault Saunier
parent 80de4392ce
commit 7e85c9b0b5
9 changed files with 863 additions and 0 deletions

View file

@ -7,6 +7,7 @@ SUBDIRS = \
tools \
pkgconfig \
docs \
tests \
po
DIST_SUBDIRS = $(SUBDIRS)

View file

@ -179,6 +179,7 @@ AC_SUBST(GIO_LIBS)
dnl checks for gstreamer
AG_GST_CHECK_GST_CHECK($GST_API_VERSION, [$GST_REQ], no)
AM_CONDITIONAL(HAVE_GST_CHECK, test "x$HAVE_GST_CHECK" = "xyes")
dnl *** set variables based on configure arguments ***
@ -278,6 +279,8 @@ gst/Makefile
gst/validate/Makefile
gst/preload/Makefile
gst/overrides/Makefile
tests/Makefile
tests/check/Makefile
pkgconfig/Makefile
pkgconfig/gst-validate-uninstalled.pc
pkgconfig/gst-validate.pc

View file

@ -2,6 +2,9 @@
* Copyright (C) 2013 Thiago Santos <thiago.sousa.santos@collabora.com>
*/
#ifndef _GST_VALIDATE_H
#define _GST_VALIDATE_H
#include <gst/validate/gst-validate-runner.h>
#include <gst/validate/gst-validate-monitor-factory.h>
#include <gst/validate/gst-validate-override-registry.h>
@ -10,3 +13,5 @@
#include <gst/validate/gst-validate-media-info.h>
void gst_validate_init (void);
#endif /* _GST_VALIDATE_H */

View file

@ -0,0 +1,10 @@
if HAVE_GST_CHECK
CHECK_SUBDIRS= check
else
CHECK_SUBDIRS=
endif
SUBDIRS= $(CHECK_SUBDIRS)
DIST_SUBDIRS = check

View file

@ -0,0 +1,96 @@
include $(top_srcdir)/common/check.mak
TESTS_ENVIRONMENT =
plugindir = $(libdir)/gstreamer-@GST_API_VERSION@
# override to _not_ install the test plugins
install-pluginLTLIBRARIES:
# the core dumps of some machines have PIDs appended
CLEANFILES = core.* test-registry.* *.gcno *.gcda
common_cflags=-I$(top_srcdir) $(GST_PLUGINS_BASE_CFLAGS) $(GST_OBJ_CFLAGS) \
$(GST_CHECK_CFLAGS) $(GST_OPTION_CFLAGS) $(GST_CFLAGS)
common_ldadd=$(top_builddir)/gst/validate/libgstvalidate-@GST_API_VERSION@.la \
$(GST_PLUGINS_BASE_LIBS) -lgstpbutils-$(GST_API_VERSION) \
$(GST_OBJ_LIBS) $(GST_CHECK_LIBS)
testutils_noisnt_libraries=libtestutils.la
testutils_noinst_headers=validate/test-utils.h
libtestutils_la_LIBADD=$(common_ldadd)
libtestutils_la_CFLAGS=$(common_cflags)
libtestutils_la_SOURCES=validate/test-utils.c
SUPPRESSIONS = $(top_srcdir)/common/gst.supp # $(srcdir)/gst-plugins-bad.supp
clean-local: clean-local-check
check_PROGRAMS = \
validate/padmonitor \
validate/monitoring
noinst_LTLIBRARIES=$(testutils_noisnt_libraries)
noinst_HEADERS=$(testutils_noinst_headers)
TESTS = $(check_PROGRAMS)
AM_CFLAGS = $(common_cflags) -UG_DISABLE_ASSERT -UG_DISABLE_CAST_CHECKS
LDADD = $(common_ldadd) libtestutils.la
debug:
echo $(COVERAGE_FILES)
echo $(COVERAGE_FILES_REL)
.PHONY: coverage
if GST_GCOV_ENABLED
# we rebuild a registry and do gst-inspect so that all the get/set codepaths
# are also covered
coverage:
make check
make coverage-report
else
coverage:
echo "You need to configure with --enable-gcov to get coverage data"
exit 1
endif
coverage-report:
if test ! -e coverage; then
rm -r coverage
fi
for dir in $(COVERAGE_DIRS); do \
mkdir -p coverage/$$dir; \
make -C $(top_builddir)/$$dir gcov; \
done
for dir in $(COVERAGE_DIRS); do \
files="`ls $(top_builddir)/$$dir/*.gcov.out 2> /dev/null`"; \
if test ! -z "$$files"; then \
perl $(top_srcdir)/common/coverage/coverage-report.pl \
$(top_builddir)/$$dir/*.gcov.out > \
coverage/$$dir/index.xml; \
xsltproc $(top_srcdir)/common/coverage/coverage-report.xsl \
coverage/$$dir/index.xml > coverage/$$dir/index.html; \
fi; \
done
for file in $(COVERAGE_FILES_REL); do \
echo Generating coverage/$$file.html; \
perl $(top_srcdir)/common/coverage/coverage-report-entry.pl \
$(top_builddir)/$$file > coverage/$$file.html; \
done
check-integration: integration
CK_DEFAULT_TIMEOUT=20 ./integration
check-integration-forever:
@while true; do \
make check-integration \
CK_DEFAULT_TIMEOUT=20 \
$* || break; done
check-integration-gdb:
@$(TESTS_ENVIRONMENT) \
CK_FORK=no \
$(LIBTOOL) --mode=execute \
gdb ./integration

View file

@ -0,0 +1,110 @@
/* GstValidate
* Copyright (C) 2014 Thibault Saunier <thibault.saunier@collabora.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <gst/validate/validate.h>
#include <gst/validate/gst-validate-pad-monitor.h>
#include <gst/validate/gst-validate-bin-monitor.h>
#include <gst/check/gstcheck.h>
#include "test-utils.h"
GST_START_TEST (monitors_added)
{
GList *tmp;
GstValidateRunner *runner;
GstValidateMonitor *monitor;
GstElement *pipeline = gst_pipeline_new ("validate-pipeline");
GstElement *src, *sink;
src = gst_element_factory_make ("fakesrc", "source");
sink = gst_element_factory_make ("fakesink", "sink");
runner = gst_validate_runner_new ();
fail_unless (GST_IS_VALIDATE_RUNNER (runner));
monitor = gst_validate_monitor_factory_create (GST_OBJECT_CAST (pipeline),
runner, NULL);
fail_unless (GST_IS_VALIDATE_BIN_MONITOR (monitor));
gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
gst_element_link (src, sink);
/* Check that the elements are properly monitored */
fail_unless_equals_int (g_list_length (src->srcpads), 1);
for (tmp = src->srcpads; tmp; tmp = tmp->next)
fail_unless (GST_IS_VALIDATE_PAD_MONITOR (g_object_get_data ((GObject *)
tmp->data, "validate-monitor")));
fail_unless_equals_int (g_list_length (sink->sinkpads), 1);
for (tmp = sink->sinkpads; tmp; tmp = tmp->next)
fail_unless (GST_IS_VALIDATE_PAD_MONITOR (g_object_get_data ((GObject *)
tmp->data, "validate-monitor")));
/* clean up */
gst_object_unref (pipeline);
gst_object_unref (monitor);
gst_object_unref (runner);
}
GST_END_TEST;
GST_START_TEST (monitors_cleanup)
{
GstElement *src, *sink;
GstValidateRunner *runner;
GstValidateMonitor *monitor, *pmonitor1, *pmonitor2;
GstElement *pipeline = gst_pipeline_new ("validate-pipeline");
src = gst_element_factory_make ("fakesrc", "source");
sink = gst_element_factory_make ("fakesink", "sink");
runner = gst_validate_runner_new ();
monitor = gst_validate_monitor_factory_create (GST_OBJECT_CAST (pipeline),
runner, NULL);
gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
gst_element_link (src, sink);
/* Check cleanup */
pmonitor1 =
g_object_get_data ((GObject *) src->srcpads->data, "validate-monitor");
pmonitor2 =
g_object_get_data ((GObject *) sink->sinkpads->data, "validate-monitor");
check_destroyed (monitor, pmonitor1, pmonitor2, NULL);
check_destroyed (pipeline, src, sink, NULL);
}
GST_END_TEST;
static Suite *
gst_validate_suite (void)
{
Suite *s = suite_create ("monitoring");
TCase *tc_chain = tcase_create ("monitoring");
suite_add_tcase (s, tc_chain);
gst_validate_init ();
tcase_add_test (tc_chain, monitors_added);
tcase_add_test (tc_chain, monitors_cleanup);
return s;
}
GST_CHECK_MAIN (gst_validate);

View file

@ -0,0 +1,382 @@
/* GstValidate
* Copyright (C) 2014 Thibault Saunier <thibault.saunier@collabora.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <gst/validate/validate.h>
#include <gst/validate/gst-validate-pad-monitor.h>
#include <gst/check/gstcheck.h>
#include "test-utils.h"
GST_START_TEST (buffer_before_segment)
{
GstPad *srcpad;
GstElement *src, *sink;
GstValidateRunner *runner;
GstValidateReport *report;
GstValidateMonitor *monitor;
/* getting an existing element class is cheating, but easier */
src = gst_element_factory_make ("fakesrc", "fakesrc");
sink = gst_element_factory_make ("fakesink", "fakesink");
fail_unless (gst_element_link (src, sink));
runner = gst_validate_runner_new ();
monitor =
gst_validate_monitor_factory_create (GST_OBJECT (src), runner, NULL);
gst_validate_reporter_set_handle_g_logs (GST_VALIDATE_REPORTER (monitor));
fail_unless (GST_IS_VALIDATE_ELEMENT_MONITOR (monitor));
srcpad = gst_element_get_static_pad (src, "src");
/* We want to handle the src behaviour ourself */
fail_unless (gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, TRUE));
fail_unless_equals_int (gst_element_set_state (sink, GST_STATE_PLAYING),
GST_STATE_CHANGE_ASYNC);
/* Send a buffer before pushing any segment (FAILS) */
{
_gst_check_expecting_log = TRUE;
fail_unless_equals_int (gst_pad_push (srcpad, gst_buffer_new ()),
GST_FLOW_OK);
assert_equals_int (g_slist_length (runner->reports), 1);
report = runner->reports->data;
fail_unless_equals_int (report->level, GST_VALIDATE_REPORT_LEVEL_WARNING);
fail_unless_equals_int (report->issue->issue_id,
GST_VALIDATE_ISSUE_ID_BUFFER_BEFORE_SEGMENT);
}
/* Setup all needed event and push a new buffer (WORKS) */
{
_gst_check_expecting_log = FALSE;
gst_check_setup_events (srcpad, src, NULL, GST_FORMAT_TIME);
fail_unless_equals_int (gst_pad_push (srcpad, gst_buffer_new ()),
GST_FLOW_OK);
assert_equals_int (g_slist_length (runner->reports), 1);
}
/* clean up */
fail_unless (gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, FALSE));
fail_unless_equals_int (gst_element_set_state (sink, GST_STATE_NULL),
GST_STATE_CHANGE_SUCCESS);
gst_object_unref (srcpad);
check_destroyed (src, srcpad, NULL);
check_destroyed (sink, NULL, NULL);
check_destroyed (runner, NULL, NULL);
}
GST_END_TEST;
GST_START_TEST (buffer_outside_segment)
{
GstPad *srcpad;
GstBuffer *buffer;
GstSegment segment;
GstElement *src, *sink;
const gchar *fakesrc_klass;
GstValidateReport *report;
GstValidateRunner *runner;
GstValidateMonitor *monitor;
/* getting an existing element class is cheating, but easier */
src = gst_element_factory_make ("fakesrc", "fakesrc");
sink = gst_element_factory_make ("fakesink", "fakesink");
fakesrc_klass =
gst_element_class_get_metadata (GST_ELEMENT_GET_CLASS (src), "klass");
/* Testing if a buffer is outside a segment is only done for buffer outputed
* from decoders for the moment, fake a Decoder so that the test is properly
* executed */
gst_element_class_add_metadata (GST_ELEMENT_GET_CLASS (src), "klass",
"Decoder");
runner = gst_validate_runner_new ();
monitor =
gst_validate_monitor_factory_create (GST_OBJECT (src), runner, NULL);
gst_validate_reporter_set_handle_g_logs (GST_VALIDATE_REPORTER (monitor));
srcpad = gst_element_get_static_pad (src, "src");
fail_unless (GST_IS_VALIDATE_PAD_MONITOR (g_object_get_data ((GObject *)
srcpad, "validate-monitor")));
fail_unless (gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, TRUE));
fail_unless_equals_int (gst_element_set_state (sink, GST_STATE_PLAYING),
GST_STATE_CHANGE_ASYNC);
gst_segment_init (&segment, GST_FORMAT_TIME);
segment.start = 0;
segment.stop = GST_SECOND;
fail_unless (gst_pad_push_event (srcpad,
gst_event_new_stream_start ("the-stream")));
fail_unless (gst_pad_push_event (srcpad, gst_event_new_segment (&segment)));
/* Pushing a buffer that is outside the segment */
{
buffer = gst_buffer_new ();
GST_BUFFER_PTS (buffer) = 10 * GST_SECOND;
GST_BUFFER_DURATION (buffer) = GST_SECOND;
fail_unless (gst_pad_push (srcpad, buffer));
assert_equals_int (g_slist_length (runner->reports), 1);
report = runner->reports->data;
fail_unless_equals_int (report->level, GST_VALIDATE_REPORT_LEVEL_ISSUE);
fail_unless_equals_int (report->issue->issue_id,
GST_VALIDATE_ISSUE_ID_BUFFER_IS_OUT_OF_SEGMENT);
}
/* Pushing a buffer inside the segment */
{
fail_unless (gst_pad_push (srcpad, gst_buffer_new ()));
assert_equals_int (g_slist_length (runner->reports), 1);
}
/* clean up */
fail_unless (gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, FALSE));
gst_object_unref (srcpad);
gst_element_class_add_metadata (GST_ELEMENT_GET_CLASS (src), "klass",
fakesrc_klass);
gst_object_unref (src);
gst_object_unref (runner);
fail_unless_equals_int (gst_element_set_state (sink, GST_STATE_NULL),
GST_STATE_CHANGE_SUCCESS);
gst_object_unref (sink);
}
GST_END_TEST;
static void
_first_buffer_running_time (gboolean failing)
{
GstPad *srcpad;
GstBuffer *buffer;
GstElement *src, *sink;
GstValidateReport *report;
GstValidateRunner *runner;
GstValidateMonitor *monitor;
/* getting an existing element class is cheating, but easier */
src = gst_element_factory_make ("fakesrc", "fakesrc");
sink = gst_element_factory_make ("fakesink", "fakesink");
runner = gst_validate_runner_new ();
monitor =
gst_validate_monitor_factory_create (GST_OBJECT (src), runner, NULL);
gst_validate_reporter_set_handle_g_logs (GST_VALIDATE_REPORTER (monitor));
srcpad = gst_element_get_static_pad (src, "src");
fail_unless (GST_IS_VALIDATE_PAD_MONITOR (g_object_get_data ((GObject *)
srcpad, "validate-monitor")));
fail_unless (gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, TRUE));
fail_unless_equals_int (gst_element_set_state (sink, GST_STATE_PLAYING),
GST_STATE_CHANGE_ASYNC);
gst_check_setup_events (srcpad, src, NULL, GST_FORMAT_TIME);
/* Pushing a first buffer that as a wrong running time */
{
buffer = gst_buffer_new ();
if (failing)
GST_BUFFER_PTS (buffer) = 23;
GST_BUFFER_DURATION (buffer) = GST_SECOND;
fail_unless (gst_pad_push (srcpad, buffer));
if (failing) {
assert_equals_int (g_slist_length (runner->reports), 1);
report = runner->reports->data;
fail_unless_equals_int (report->level, GST_VALIDATE_REPORT_LEVEL_WARNING);
fail_unless_equals_int (report->issue->issue_id,
GST_VALIDATE_ISSUE_ID_FIRST_BUFFER_RUNNING_TIME_IS_NOT_ZERO);
} else {
assert_equals_int (g_slist_length (runner->reports), 0);
}
}
/* clean up */
fail_unless (gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, FALSE));
fail_unless_equals_int (gst_element_set_state (sink, GST_STATE_NULL),
GST_STATE_CHANGE_SUCCESS);
gst_object_unref (srcpad);
check_destroyed (src, srcpad, NULL);
check_destroyed (sink, NULL, NULL);
check_destroyed (runner, NULL, NULL);
check_destroyed (monitor, NULL, NULL);
}
GST_START_TEST (first_buffer_running_time)
{
/* First run the test with a first buffer timestamp != 0 */
_first_buffer_running_time (TRUE);
/* First run the test with a first buffer timestamp == 0 */
_first_buffer_running_time (FALSE);
}
GST_END_TEST;
static void
fake_demuxer_prepare_pads (GstBin * pipeline, GstElement * demux,
GstValidateRunner * runner)
{
gint i = 0;
GList *tmp;
fail_unless (g_list_length (demux->srcpads), 3);
for (tmp = demux->srcpads; tmp; tmp = tmp->next) {
GstPad *new_peer;
gchar *name = g_strdup_printf ("sink-%d", i++);
GstElement *sink = gst_element_factory_make ("fakesink", name);
gst_bin_add (pipeline, sink);
new_peer = sink->sinkpads->data;
gst_pad_link (tmp->data, new_peer);
gst_element_set_state (sink, GST_STATE_PLAYING);
gst_pad_activate_mode (tmp->data, GST_PAD_MODE_PUSH, TRUE);
g_free (name);
}
fail_unless (gst_pad_activate_mode (demux->sinkpads->data, GST_PAD_MODE_PUSH,
TRUE));
}
static GstValidatePadMonitor *
_get_pad_monitor (GstPad * pad)
{
GstValidatePadMonitor *m = get_pad_monitor (pad);
gst_object_unref (pad);
return m;
}
static void
_test_flow_aggregation (GstFlowReturn flow, GstFlowReturn flow1,
GstFlowReturn flow2, GstFlowReturn demux_flow, gboolean should_fail)
{
GstPad *srcpad;
GstValidateReport *report;
GstValidatePadMonitor *pmonitor, *pmonitor1, *pmonitor2;
GstElement *demuxer = fake_demuxer_new ();
GstBin *pipeline = GST_BIN (gst_pipeline_new ("validate-pipeline"));
GstValidateRunner *runner = gst_validate_runner_new ();
GstValidateMonitor *monitor =
gst_validate_monitor_factory_create (GST_OBJECT (pipeline),
runner, NULL);
gst_validate_reporter_set_handle_g_logs (GST_VALIDATE_REPORTER (monitor));
gst_bin_add (pipeline, demuxer);
fake_demuxer_prepare_pads (pipeline, demuxer, runner);
srcpad = gst_pad_new ("srcpad1", GST_PAD_SRC);
gst_pad_link (srcpad, demuxer->sinkpads->data);
fail_unless (gst_pad_activate_mode (srcpad, GST_PAD_MODE_PUSH, TRUE));
gst_check_setup_events_with_stream_id (srcpad, demuxer, NULL,
GST_FORMAT_TIME, "the-stream");
pmonitor = _get_pad_monitor (gst_pad_get_peer (demuxer->srcpads->data));
pmonitor1 =
_get_pad_monitor (gst_pad_get_peer (demuxer->srcpads->next->data));
pmonitor2 =
_get_pad_monitor (gst_pad_get_peer (demuxer->srcpads->next->next->data));
pmonitor->last_flow_return = flow;
pmonitor1->last_flow_return = flow1;
pmonitor2->last_flow_return = flow2;
FAKE_DEMUXER (demuxer)->return_value = demux_flow;
fail_unless_equals_int (gst_pad_push (srcpad, gst_buffer_new ()), demux_flow);
if (should_fail) {
assert_equals_int (g_slist_length (runner->reports), 1);
report = runner->reports->data;
fail_unless_equals_int (report->level, GST_VALIDATE_REPORT_LEVEL_CRITICAL);
fail_unless_equals_int (report->issue->issue_id,
GST_VALIDATE_ISSUE_ID_WRONG_FLOW_RETURN);
} else {
assert_equals_int (g_slist_length (runner->reports), 0);
}
clean_bus (GST_ELEMENT (pipeline));
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
ASSERT_OBJECT_REFCOUNT (pipeline, "ours", 1);
check_destroyed (pipeline, demuxer, NULL);
check_destroyed (monitor, pmonitor, NULL);
}
GST_START_TEST (flow_aggregation)
{
/* Check the GstFlowCombiner to find the rules */
/* Failling cases: */
_test_flow_aggregation (GST_FLOW_OK, GST_FLOW_OK,
GST_FLOW_ERROR, GST_FLOW_OK, TRUE);
_test_flow_aggregation (GST_FLOW_EOS, GST_FLOW_EOS,
GST_FLOW_EOS, GST_FLOW_OK, TRUE);
_test_flow_aggregation (GST_FLOW_FLUSHING, GST_FLOW_OK,
GST_FLOW_OK, GST_FLOW_OK, TRUE);
_test_flow_aggregation (GST_FLOW_NOT_NEGOTIATED, GST_FLOW_OK,
GST_FLOW_OK, GST_FLOW_OK, TRUE);
/* Passing cases: */
_test_flow_aggregation (GST_FLOW_EOS, GST_FLOW_EOS,
GST_FLOW_EOS, GST_FLOW_EOS, FALSE);
_test_flow_aggregation (GST_FLOW_EOS, GST_FLOW_EOS,
GST_FLOW_OK, GST_FLOW_OK, FALSE);
_test_flow_aggregation (GST_FLOW_OK, GST_FLOW_OK,
GST_FLOW_OK, GST_FLOW_EOS, FALSE);
_test_flow_aggregation (GST_FLOW_NOT_NEGOTIATED, GST_FLOW_OK,
GST_FLOW_OK, GST_FLOW_NOT_NEGOTIATED, FALSE);
}
GST_END_TEST;
static Suite *
gst_validate_suite (void)
{
Suite *s = suite_create ("padmonitor");
TCase *tc_chain = tcase_create ("padmonitor");
suite_add_tcase (s, tc_chain);
gst_validate_init ();
tcase_add_test (tc_chain, buffer_before_segment);
tcase_add_test (tc_chain, buffer_outside_segment);
tcase_add_test (tc_chain, first_buffer_running_time);
tcase_add_test (tc_chain, flow_aggregation);
return s;
}
GST_CHECK_MAIN (gst_validate);

View file

@ -0,0 +1,198 @@
/* GstValidate
* Copyright (C) 2014 Thibault Saunier <thibault.saunier@collabora.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "test-utils.h"
typedef struct _DestroyedObjectStruct
{
GObject *object;
gboolean destroyed;
} DestroyedObjectStruct;
static void
weak_notify (DestroyedObjectStruct * destroyed, GObject ** object)
{
destroyed->destroyed = TRUE;
}
void
check_destroyed (gpointer object_to_unref, gpointer first_object, ...)
{
gint i = 0;
GObject *object;
GList *objs = NULL, *tmp;
DestroyedObjectStruct *destroyed = g_slice_new0 (DestroyedObjectStruct);
destroyed->object = G_OBJECT (object_to_unref);
g_object_weak_ref (G_OBJECT (object_to_unref), (GWeakNotify) weak_notify,
destroyed);
objs = g_list_prepend (objs, destroyed);
if (first_object) {
va_list varargs;
object = G_OBJECT (first_object);
va_start (varargs, first_object);
while (object) {
destroyed = g_slice_new0 (DestroyedObjectStruct);
destroyed->object = object;
g_object_weak_ref (object, (GWeakNotify) weak_notify, destroyed);
objs = g_list_append (objs, destroyed);
object = va_arg (varargs, GObject *);
}
va_end (varargs);
}
gst_object_unref (object_to_unref);
for (tmp = objs; tmp; tmp = tmp->next) {
fail_unless (((DestroyedObjectStruct *) tmp->data)->destroyed == TRUE,
"%p is not destroyed (object nb %i)",
((DestroyedObjectStruct *) tmp->data)->object, i);
g_slice_free (DestroyedObjectStruct, tmp->data);
i++;
}
g_list_free (objs);
}
void
clean_bus (GstElement * element)
{
GstBus *bus;
bus = gst_element_get_bus (element);
gst_bus_set_flushing (bus, TRUE);
gst_object_unref (bus);
}
GstValidatePadMonitor *
get_pad_monitor (GstPad * pad)
{
return g_object_get_data ((GObject *) pad, "validate-monitor");
}
static GstStaticPadTemplate fake_demuxer_src_template =
GST_STATIC_PAD_TEMPLATE ("src%u",
GST_PAD_SRC,
GST_PAD_SOMETIMES,
GST_STATIC_CAPS ("something")
);
static GstStaticPadTemplate fake_demuxer_sink_template =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("something")
);
static void
fake_demuxer_dispose (FakeDemuxer * self)
{
}
static void
fake_demuxer_finalize (FakeDemuxer * self)
{
}
static GstFlowReturn
_chain (GstPad * pad, GstObject * self, GstBuffer * buffer)
{
gst_buffer_unref (buffer);
return FAKE_DEMUXER (self)->return_value;
}
static void
fake_demuxer_init (FakeDemuxer * self, gpointer * g_class)
{
GstPad *pad;
GstElement *element = GST_ELEMENT (self);
GstPadTemplate *pad_template;
pad_template =
gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src%u");
pad = gst_pad_new_from_template (pad_template, "src0");
gst_element_add_pad (element, pad);
pad = gst_pad_new_from_template (pad_template, "src1");
gst_element_add_pad (element, pad);
pad = gst_pad_new_from_template (pad_template, "src2");
gst_element_add_pad (element, pad);
pad_template =
gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "sink");
pad = gst_pad_new_from_template (pad_template, "sink");
gst_element_add_pad (element, pad);
self->return_value = GST_FLOW_OK;
gst_pad_set_chain_function (pad, _chain);
}
static void
fake_demuxer_class_init (FakeDemuxerClass * self_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (self_class);
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (self_class);
object_class->dispose = (void (*)(GObject * object)) fake_demuxer_dispose;
object_class->finalize = (void (*)(GObject * object)) fake_demuxer_finalize;
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&fake_demuxer_src_template));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&fake_demuxer_sink_template));
gst_element_class_set_static_metadata (gstelement_class,
"Fake Demuxer", "Demuxer", "Some demuxer", "Thibault Saunier");
}
GType
fake_demuxer_get_type (void)
{
static volatile gsize type = 0;
if (g_once_init_enter (&type)) {
GType _type;
static const GTypeInfo info = {
sizeof (FakeDemuxerClass),
NULL,
NULL,
(GClassInitFunc) fake_demuxer_class_init,
NULL,
NULL,
sizeof (FakeDemuxer),
0,
(GInstanceInitFunc) fake_demuxer_init,
};
_type = g_type_register_static (GST_TYPE_ELEMENT, "FakeDemuxer", &info, 0);
g_once_init_leave (&type, _type);
}
return type;
}
GstElement *
fake_demuxer_new (void)
{
return GST_ELEMENT (g_object_new (FAKE_DEMUXER_TYPE, NULL));
}

View file

@ -0,0 +1,58 @@
/* GstValidate
* Copyright (C) 2014 Thibault Saunier <thibault.saunier@collabora.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef _GST_VALIDATE_TEST_UTILS
#define _GST_VALIDATE_TEST_UTILS
#include "test-utils.h"
#include <gst/check/gstcheck.h>
#include <gst/validate/validate.h>
#include <gst/validate/gst-validate-pad-monitor.h>
G_BEGIN_DECLS
void check_destroyed (gpointer object_to_unref, gpointer first_object, ...) G_GNUC_NULL_TERMINATED;
GstValidateRunner * setup_runner (GstObject * object);
void clean_bus (GstElement *element);
GstValidatePadMonitor * get_pad_monitor (GstPad *pad);
typedef struct {
GstElement parent;
GstFlowReturn return_value;
} FakeDemuxer;
typedef struct {
GstElementClass parent;
} FakeDemuxerClass;
#define FAKE_DEMUXER_TYPE (fake_demuxer_get_type ())
#define FAKE_DEMUXER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FAKE_DEMUXER_TYPE, FakeDemuxer))
#define FAKE_DEMUXER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), FAKE_DEMUXER_TYPE, FakeDemuxerClass))
#define IS_FAKE_DEMUXER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FAKE_DEMUXER_TYPE))
#define IS_FAKE_DEMUXER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FAKE_DEMUXER_TYPE))
#define FAKE_DEMUXER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), FAKE_DEMUXER_TYPE, FakeDemuxerClass))
GType fake_demuxer_get_type (void);
GstElement * fake_demuxer_new (void);
G_END_DECLS
#endif /* _GST_VALIDATE_TEST_UTILS */