mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-31 11:32:38 +00:00
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:
parent
80de4392ce
commit
7e85c9b0b5
9 changed files with 863 additions and 0 deletions
|
@ -7,6 +7,7 @@ SUBDIRS = \
|
|||
tools \
|
||||
pkgconfig \
|
||||
docs \
|
||||
tests \
|
||||
po
|
||||
|
||||
DIST_SUBDIRS = $(SUBDIRS)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
10
validate/tests/Makefile.am
Normal file
10
validate/tests/Makefile.am
Normal file
|
@ -0,0 +1,10 @@
|
|||
if HAVE_GST_CHECK
|
||||
CHECK_SUBDIRS= check
|
||||
else
|
||||
CHECK_SUBDIRS=
|
||||
endif
|
||||
|
||||
SUBDIRS= $(CHECK_SUBDIRS)
|
||||
|
||||
DIST_SUBDIRS = check
|
||||
|
96
validate/tests/check/Makefile.am
Normal file
96
validate/tests/check/Makefile.am
Normal 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
|
||||
|
110
validate/tests/check/validate/monitoring.c
Normal file
110
validate/tests/check/validate/monitoring.c
Normal 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);
|
382
validate/tests/check/validate/padmonitor.c
Normal file
382
validate/tests/check/validate/padmonitor.c
Normal 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);
|
198
validate/tests/check/validate/test-utils.c
Normal file
198
validate/tests/check/validate/test-utils.c
Normal 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));
|
||||
}
|
58
validate/tests/check/validate/test-utils.h
Normal file
58
validate/tests/check/validate/test-utils.h
Normal 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 */
|
Loading…
Reference in a new issue