summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim-Philipp Müller <tim@centricular.net>2007-03-28 18:38:11 +0000
committerTim-Philipp Müller <tim@centricular.net>2007-03-28 18:38:11 +0000
commitdf244cef0484e858ee0bc42dcd88d6af0bd8627b (patch)
tree8a3413c1cb87626f36071ea4ec2751808dc96334
parent799bc90b1f2097108e8d386a7f00051f95b9f494 (diff)
plugins/elements/gstmultiqueue.c: Don't leak GCond.
Original commit message from CVS: * plugins/elements/gstmultiqueue.c: (gst_single_queue_free): Don't leak GCond. * tests/check/Makefile.am: * tests/check/elements/.cvsignore: * tests/check/elements/multiqueue.c: (setup_multiqueue), (GST_START_TEST), (multiqueue_suite): Add some dead simple unit tests for the 'multiqueue' element (some bits don't work yet and are disabled for now).
-rw-r--r--ChangeLog12
-rw-r--r--plugins/elements/gstmultiqueue.c1
-rw-r--r--tests/check/Makefile.am1
-rw-r--r--tests/check/elements/.gitignore1
-rw-r--r--tests/check/elements/multiqueue.c274
5 files changed, 289 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 5cfb94f77..72373af51 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
2007-03-28 Tim-Philipp Müller <tim at centricular dot net>
+ * plugins/elements/gstmultiqueue.c: (gst_single_queue_free):
+ Don't leak GCond.
+
+ * tests/check/Makefile.am:
+ * tests/check/elements/.cvsignore:
+ * tests/check/elements/multiqueue.c: (setup_multiqueue),
+ (GST_START_TEST), (multiqueue_suite):
+ Add some dead simple unit tests for the 'multiqueue' element
+ (some bits don't work yet and are disabled for now).
+
+2007-03-28 Tim-Philipp Müller <tim at centricular dot net>
+
* gst/gstelement.c: (gst_element_get_request_pad),
(gst_element_class_get_request_pad_template):
Make gst_element_get_request_pad() create request pads only for
diff --git a/plugins/elements/gstmultiqueue.c b/plugins/elements/gstmultiqueue.c
index 21d9d8d50..1a52c407f 100644
--- a/plugins/elements/gstmultiqueue.c
+++ b/plugins/elements/gstmultiqueue.c
@@ -998,6 +998,7 @@ gst_single_queue_free (GstSingleQueue * sq)
/* DRAIN QUEUE */
gst_data_queue_flush (sq->queue);
g_object_unref (sq->queue);
+ g_cond_free (sq->turn);
g_free (sq);
}
diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am
index b707399e2..c16da59ae 100644
--- a/tests/check/Makefile.am
+++ b/tests/check/Makefile.am
@@ -59,6 +59,7 @@ REGISTRY_CHECKS = \
elements/fdsrc \
elements/filesrc \
elements/identity \
+ elements/multiqueue \
libs/basesrc \
libs/controller \
libs/typefindhelper \
diff --git a/tests/check/elements/.gitignore b/tests/check/elements/.gitignore
index 1ea71e4b9..42b7fbd9b 100644
--- a/tests/check/elements/.gitignore
+++ b/tests/check/elements/.gitignore
@@ -4,5 +4,6 @@ fakesink
fdsrc
filesrc
identity
+multiqueue
queue
*.check.xml
diff --git a/tests/check/elements/multiqueue.c b/tests/check/elements/multiqueue.c
new file mode 100644
index 000000000..ddf01ae01
--- /dev/null
+++ b/tests/check/elements/multiqueue.c
@@ -0,0 +1,274 @@
+/* GStreamer unit tests for multiqueue
+ *
+ * Copyright (C) 2007 Tim-Philipp Müller <tim centricular net>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <unistd.h>
+
+#include <gst/check/gstcheck.h>
+
+static GstElement *
+setup_multiqueue (GstElement * pipe, GstElement * inputs[],
+ GstElement * outputs[], guint num)
+{
+ GstElement *mq;
+ guint i;
+
+ mq = gst_element_factory_make ("multiqueue", NULL);
+ fail_unless (mq != NULL, "failed to create 'multiqueue' element");
+
+ gst_bin_add (GST_BIN (pipe), mq);
+
+ for (i = 0; i < num; ++i) {
+ GstPad *sinkpad = NULL;
+ GstPad *srcpad = NULL;
+
+ /* create multiqueue sink (and source) pad */
+ sinkpad = gst_element_get_request_pad (mq, "sink%d");
+ fail_unless (sinkpad != NULL,
+ "failed to create multiqueue request pad #%u", i);
+
+ /* link input element N to the N-th multiqueue sink pad we just created */
+ if (inputs != NULL && inputs[i] != NULL) {
+ gst_bin_add (GST_BIN (pipe), inputs[i]);
+
+ srcpad = gst_element_get_pad (inputs[i], "src");
+ if (srcpad == NULL)
+ srcpad = gst_element_get_pad (inputs[i], "src%d");
+ if (srcpad == NULL)
+ srcpad = gst_element_get_pad (inputs[i], "src_%d");
+ fail_unless (srcpad != NULL, "failed to find src pad for input #%u", i);
+
+ fail_unless_equals_int (GST_PAD_LINK_OK, gst_pad_link (srcpad, sinkpad));
+
+ gst_object_unref (srcpad);
+ srcpad = NULL;
+ }
+ gst_object_unref (sinkpad);
+ sinkpad = NULL;
+
+ /* link output element N to the N-th multiqueue src pad */
+ if (outputs != NULL && outputs[i] != NULL) {
+ gchar padname[10];
+
+ /* only the sink pads are by request, the source pads are sometimes pads,
+ * so this should return NULL */
+ srcpad = gst_element_get_request_pad (mq, "src%d");
+ fail_unless (srcpad == NULL);
+
+ g_snprintf (padname, sizeof (padname), "src%d", i);
+ srcpad = gst_element_get_pad (mq, padname);
+ fail_unless (srcpad != NULL, "failed to get multiqueue src pad #%u", i);
+ fail_unless (GST_PAD_IS_SRC (srcpad),
+ "%s:%s is not a source pad?!", GST_DEBUG_PAD_NAME (srcpad));
+
+ gst_bin_add (GST_BIN (pipe), outputs[i]);
+
+ sinkpad = gst_element_get_pad (outputs[i], "sink");
+ if (sinkpad == NULL)
+ sinkpad = gst_element_get_pad (outputs[i], "sink%d");
+ if (sinkpad == NULL)
+ sinkpad = gst_element_get_pad (outputs[i], "sink_%d");
+ fail_unless (sinkpad != NULL, "failed to find sink pad of output #%u", i);
+ fail_unless (GST_PAD_IS_SINK (sinkpad));
+
+ fail_unless_equals_int (GST_PAD_LINK_OK, gst_pad_link (srcpad, sinkpad));
+
+ gst_object_unref (srcpad);
+ gst_object_unref (sinkpad);
+ }
+ }
+
+ return mq;
+}
+
+GST_START_TEST (test_simple_pipeline)
+{
+ GstElement *pipe, *mq;
+ GstElement *inputs[1];
+ GstElement *outputs[1];
+ GstMessage *msg;
+
+ pipe = gst_pipeline_new ("pipeline");
+
+ inputs[0] = gst_element_factory_make ("fakesrc", NULL);
+ fail_unless (inputs[0] != NULL, "failed to create 'fakesrc' element");
+ g_object_set (inputs[0], "num-buffers", 256, NULL);
+
+ outputs[0] = gst_element_factory_make ("fakesink", NULL);
+ fail_unless (outputs[0] != NULL, "failed to create 'fakesink' element");
+
+ mq = setup_multiqueue (pipe, inputs, outputs, 1);
+
+ gst_element_set_state (pipe, GST_STATE_PLAYING);
+
+ msg = gst_bus_poll (GST_ELEMENT_BUS (pipe),
+ GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
+
+ fail_if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR,
+ "Expected EOS message, got ERROR message");
+ gst_message_unref (msg);
+
+ GST_LOG ("Got EOS, cleaning up");
+
+ gst_element_set_state (pipe, GST_STATE_NULL);
+ gst_object_unref (pipe);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_simple_shutdown_while_running)
+{
+ GstElement *pipe, *mq;
+ GstElement *inputs[1];
+ GstElement *outputs[1];
+ GstMessage *msg;
+
+ pipe = gst_pipeline_new ("pipeline");
+
+ inputs[0] = gst_element_factory_make ("fakesrc", NULL);
+ fail_unless (inputs[0] != NULL, "failed to create 'fakesrc' element");
+
+ outputs[0] = gst_element_factory_make ("fakesink", NULL);
+ fail_unless (outputs[0] != NULL, "failed to create 'fakesink' element");
+
+ mq = setup_multiqueue (pipe, inputs, outputs, 1);
+
+ gst_element_set_state (pipe, GST_STATE_PAUSED);
+
+ /* wait until pipeline is up and running */
+ msg = gst_bus_poll (GST_ELEMENT_BUS (pipe),
+ GST_MESSAGE_ERROR | GST_MESSAGE_ASYNC_DONE, -1);
+ fail_if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR, "Got ERROR message");
+ gst_message_unref (msg);
+
+ GST_LOG ("pipeline is running now");
+ gst_element_set_state (pipe, GST_STATE_PAUSED);
+
+ /* wait a bit to accumulate some buffers in the queue (while it's blocking
+ * in the sink) */
+ msg =
+ gst_bus_poll (GST_ELEMENT_BUS (pipe), GST_MESSAGE_ERROR, GST_SECOND / 4);
+ if (msg)
+ g_error ("Got ERROR message");
+
+ /* now shut down only the sink, so the queue gets a wrong-state flow return */
+ gst_element_set_state (outputs[0], GST_STATE_NULL);
+ msg =
+ gst_bus_poll (GST_ELEMENT_BUS (pipe), GST_MESSAGE_ERROR, GST_SECOND / 2);
+ if (msg)
+ g_error ("Got ERROR message");
+
+ GST_LOG ("Cleaning up");
+
+ gst_element_set_state (pipe, GST_STATE_NULL);
+ gst_object_unref (pipe);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_simple_create_destroy)
+{
+ GstElement *mq;
+
+ mq = gst_element_factory_make ("multiqueue", NULL);
+ gst_object_unref (mq);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_request_pads)
+{
+ gboolean change_state_before_cleanup = TRUE;
+ GstElement *mq;
+ GstPad *sink1, *sink2;
+
+again:
+
+ mq = gst_element_factory_make ("multiqueue", NULL);
+
+ sink1 = gst_element_get_request_pad (mq, "foo%d");
+ fail_unless (sink1 == NULL,
+ "Expected NULL pad, as there is no request pad template for 'foo%%d'");
+
+ sink1 = gst_element_get_request_pad (mq, "src%d");
+ fail_unless (sink1 == NULL,
+ "Expected NULL pad, as there is no request pad template for 'src%%d'");
+
+ sink1 = gst_element_get_request_pad (mq, "sink%d");
+ fail_unless (sink1 != NULL);
+ fail_unless (GST_IS_PAD (sink1));
+ fail_unless (GST_PAD_IS_SINK (sink1));
+ GST_LOG ("Got pad %s:%s", GST_DEBUG_PAD_NAME (sink1));
+
+ sink2 = gst_element_get_request_pad (mq, "sink%d");
+ fail_unless (sink2 != NULL);
+ fail_unless (GST_IS_PAD (sink2));
+ fail_unless (GST_PAD_IS_SINK (sink2));
+ GST_LOG ("Got pad %s:%s", GST_DEBUG_PAD_NAME (sink2));
+
+ fail_unless (sink1 != sink2);
+
+ if (change_state_before_cleanup) {
+ /* FIXME: if we don't change state, it will deadlock forever when unref'ing
+ * the queue (waiting for pad tasks to join) */
+ GST_LOG ("Changing state to PLAYING");
+ gst_element_set_state (mq, GST_STATE_PLAYING);
+ g_usleep (G_USEC_PER_SEC);
+ GST_LOG ("Changing state to NULL");
+ gst_element_set_state (mq, GST_STATE_NULL);
+ }
+
+ GST_LOG ("Cleaning up");
+ gst_object_unref (sink1);
+ gst_object_unref (sink2);
+ gst_object_unref (mq);
+
+ /* FIXME: this should work without state change before cleanup as well,
+ * but currently doesn't, see above, so disable this for now */
+ if (change_state_before_cleanup && 0) {
+ change_state_before_cleanup = FALSE;
+ goto again;
+ }
+
+}
+
+GST_END_TEST;
+
+static Suite *
+multiqueue_suite (void)
+{
+ Suite *s = suite_create ("multiqueue");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_simple_create_destroy);
+ tcase_add_test (tc_chain, test_simple_pipeline);
+
+ if (0) {
+ /* FIXME: this leaks buffers, disabled for now */
+ tcase_add_test (tc_chain, test_simple_shutdown_while_running);
+ }
+
+ /* FIXME: test_request_pads() needs some more fixes, see comments there */
+ tcase_add_test (tc_chain, test_request_pads);
+
+ return s;
+}
+
+GST_CHECK_MAIN (multiqueue)