diff options
author | Tim-Philipp Müller <tim@centricular.net> | 2007-03-28 18:38:11 +0000 |
---|---|---|
committer | Tim-Philipp Müller <tim@centricular.net> | 2007-03-28 18:38:11 +0000 |
commit | df244cef0484e858ee0bc42dcd88d6af0bd8627b (patch) | |
tree | 8a3413c1cb87626f36071ea4ec2751808dc96334 | |
parent | 799bc90b1f2097108e8d386a7f00051f95b9f494 (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-- | ChangeLog | 12 | ||||
-rw-r--r-- | plugins/elements/gstmultiqueue.c | 1 | ||||
-rw-r--r-- | tests/check/Makefile.am | 1 | ||||
-rw-r--r-- | tests/check/elements/.gitignore | 1 | ||||
-rw-r--r-- | tests/check/elements/multiqueue.c | 274 |
5 files changed, 289 insertions, 0 deletions
@@ -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) |