aboutsummaryrefslogtreecommitdiff
path: root/tests/check/libs/collectpads2.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/check/libs/collectpads2.c')
-rw-r--r--tests/check/libs/collectpads2.c353
1 files changed, 353 insertions, 0 deletions
diff --git a/tests/check/libs/collectpads2.c b/tests/check/libs/collectpads2.c
new file mode 100644
index 0000000..2a04aa2
--- /dev/null
+++ b/tests/check/libs/collectpads2.c
@@ -0,0 +1,353 @@
+/*
+ * collectpads.c - GstCollectPads2 testsuite
+ * Copyright (C) 2006 Alessandro Decina <alessandro@nnva.org>
+ *
+ * Authors:
+ * Alessandro Decina <alessandro@nnva.org>
+ *
+ * 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 <gst/check/gstcheck.h>
+#include <gst/base/gstcollectpads2.h>
+
+#define fail_unless_collected(expected) \
+G_STMT_START { \
+ g_mutex_lock (lock); \
+ while (expected == TRUE && collected == FALSE) \
+ g_cond_wait (cond, lock); \
+ fail_unless_equals_int (collected, expected); \
+ g_mutex_unlock (lock); \
+} G_STMT_END;
+
+typedef struct
+{
+ char foo;
+} BadCollectData2;
+
+typedef struct
+{
+ GstCollectData2 data;
+ GstPad *pad;
+ GstBuffer *buffer;
+ GstEvent *event;
+} TestData;
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS_ANY);
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS_ANY);
+
+static GstCollectPads2 *collect;
+static gboolean collected;
+static GstPad *srcpad1, *srcpad2;
+static GstPad *sinkpad1, *sinkpad2;
+static TestData *data1, *data2;
+
+static GMutex *lock;
+static GCond *cond;
+
+static GstFlowReturn
+collected_cb (GstCollectPads2 * pads, gpointer user_data)
+{
+ g_mutex_lock (lock);
+ collected = TRUE;
+ g_cond_signal (cond);
+ g_mutex_unlock (lock);
+
+ return GST_FLOW_OK;
+}
+
+static gpointer
+push_buffer (gpointer user_data)
+{
+ TestData *test_data = (TestData *) user_data;
+
+ fail_unless (gst_pad_push (test_data->pad, test_data->buffer)
+ == GST_FLOW_OK);
+
+ return NULL;
+}
+
+static gpointer
+push_event (gpointer user_data)
+{
+ TestData *test_data = (TestData *) user_data;
+
+ fail_unless (gst_pad_push_event (test_data->pad, test_data->event) == TRUE);
+
+ return NULL;
+}
+
+static void
+setup (void)
+{
+ collect = gst_collect_pads2_new ();
+ gst_collect_pads2_set_function (collect, collected_cb, NULL);
+
+ srcpad1 = gst_pad_new_from_static_template (&srctemplate, "src1");
+ srcpad2 = gst_pad_new_from_static_template (&srctemplate, "src2");
+ sinkpad1 = gst_pad_new_from_static_template (&sinktemplate, "sink1");
+ sinkpad2 = gst_pad_new_from_static_template (&sinktemplate, "sink2");
+ fail_unless (gst_pad_link (srcpad1, sinkpad1) == GST_PAD_LINK_OK);
+ fail_unless (gst_pad_link (srcpad2, sinkpad2) == GST_PAD_LINK_OK);
+
+ gst_pad_set_active (sinkpad1, TRUE);
+ gst_pad_set_active (sinkpad2, TRUE);
+ gst_pad_set_active (srcpad1, TRUE);
+ gst_pad_set_active (srcpad2, TRUE);
+
+ cond = g_cond_new ();
+ lock = g_mutex_new ();
+ data1 = NULL;
+ data2 = NULL;
+ collected = FALSE;
+}
+
+static void
+teardown (void)
+{
+ gst_object_unref (sinkpad1);
+ gst_object_unref (sinkpad2);
+ gst_object_unref (collect);
+ g_cond_free (cond);
+ g_mutex_free (lock);
+}
+
+GST_START_TEST (test_pad_add_remove)
+{
+ ASSERT_CRITICAL (gst_collect_pads2_add_pad (collect, sinkpad1,
+ sizeof (BadCollectData2)));
+
+ data1 = (TestData *) gst_collect_pads2_add_pad (collect,
+ sinkpad1, sizeof (TestData));
+ fail_unless (data1 != NULL);
+
+ fail_unless (gst_collect_pads2_remove_pad (collect, sinkpad2) == FALSE);
+ fail_unless (gst_collect_pads2_remove_pad (collect, sinkpad1) == TRUE);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_collect)
+{
+ GstBuffer *buf1, *buf2, *tmp;
+ GThread *thread1, *thread2;
+
+ data1 = (TestData *) gst_collect_pads2_add_pad (collect,
+ sinkpad1, sizeof (TestData));
+ fail_unless (data1 != NULL);
+
+ data2 = (TestData *) gst_collect_pads2_add_pad (collect,
+ sinkpad2, sizeof (TestData));
+ fail_unless (data2 != NULL);
+
+ buf1 = gst_buffer_new ();
+ buf2 = gst_buffer_new ();
+
+ /* start collect pads */
+ gst_collect_pads2_start (collect);
+
+ /* push buffers on the pads */
+ data1->pad = srcpad1;
+ data1->buffer = buf1;
+ thread1 = g_thread_create (push_buffer, data1, TRUE, NULL);
+ /* here thread1 is blocked and srcpad1 has a queued buffer */
+ fail_unless_collected (FALSE);
+
+ data2->pad = srcpad2;
+ data2->buffer = buf2;
+ thread2 = g_thread_create (push_buffer, data2, TRUE, NULL);
+
+ /* now both pads have a buffer */
+ fail_unless_collected (TRUE);
+
+ tmp = gst_collect_pads2_pop (collect, (GstCollectData2 *) data1);
+ fail_unless (tmp == buf1);
+ tmp = gst_collect_pads2_pop (collect, (GstCollectData2 *) data2);
+ fail_unless (tmp == buf2);
+
+ /* these will return immediately as at this point the threads have been
+ * unlocked and are finished */
+ g_thread_join (thread1);
+ g_thread_join (thread2);
+
+ gst_collect_pads2_stop (collect);
+
+ gst_buffer_unref (buf1);
+ gst_buffer_unref (buf2);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_collect_eos)
+{
+ GstBuffer *buf1, *tmp;
+ GThread *thread1, *thread2;
+
+ data1 = (TestData *) gst_collect_pads2_add_pad (collect,
+ sinkpad1, sizeof (TestData));
+ fail_unless (data1 != NULL);
+
+ data2 = (TestData *) gst_collect_pads2_add_pad (collect,
+ sinkpad2, sizeof (TestData));
+ fail_unless (data2 != NULL);
+
+ buf1 = gst_buffer_new ();
+
+ /* start collect pads */
+ gst_collect_pads2_start (collect);
+
+ /* push a buffer on srcpad1 and EOS on srcpad2 */
+ data1->pad = srcpad1;
+ data1->buffer = buf1;
+ thread1 = g_thread_create (push_buffer, data1, TRUE, NULL);
+ /* here thread1 is blocked and srcpad1 has a queued buffer */
+ fail_unless_collected (FALSE);
+
+ data2->pad = srcpad2;
+ data2->event = gst_event_new_eos ();
+ thread2 = g_thread_create (push_event, data2, TRUE, NULL);
+ /* now sinkpad1 has a buffer and sinkpad2 has EOS */
+ fail_unless_collected (TRUE);
+
+ tmp = gst_collect_pads2_pop (collect, (GstCollectData2 *) data1);
+ fail_unless (tmp == buf1);
+ /* sinkpad2 has EOS so a NULL buffer is returned */
+ tmp = gst_collect_pads2_pop (collect, (GstCollectData2 *) data2);
+ fail_unless (tmp == NULL);
+
+ /* these will return immediately as when the data is popped the threads are
+ * unlocked and will terminate */
+ g_thread_join (thread1);
+ g_thread_join (thread2);
+
+ gst_collect_pads2_stop (collect);
+
+ gst_buffer_unref (buf1);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_collect_twice)
+{
+ GstBuffer *buf1, *buf2, *tmp;
+ GThread *thread1, *thread2;
+
+ data1 = (TestData *) gst_collect_pads2_add_pad (collect,
+ sinkpad1, sizeof (TestData));
+ fail_unless (data1 != NULL);
+
+ data2 = (TestData *) gst_collect_pads2_add_pad (collect,
+ sinkpad2, sizeof (TestData));
+ fail_unless (data2 != NULL);
+
+ buf1 = gst_buffer_new ();
+
+ /* start collect pads */
+ gst_collect_pads2_start (collect);
+
+ /* queue a buffer */
+ data1->pad = srcpad1;
+ data1->buffer = buf1;
+ thread1 = g_thread_create (push_buffer, data1, TRUE, NULL);
+ /* here thread1 is blocked and srcpad1 has a queued buffer */
+ fail_unless_collected (FALSE);
+
+ /* push EOS on the other pad */
+ data2->pad = srcpad2;
+ data2->event = gst_event_new_eos ();
+ thread2 = g_thread_create (push_event, data2, TRUE, NULL);
+
+ /* one of the pads has a buffer, the other has EOS */
+ fail_unless_collected (TRUE);
+
+ tmp = gst_collect_pads2_pop (collect, (GstCollectData2 *) data1);
+ fail_unless (tmp == buf1);
+ /* there's nothing to pop from the one which received EOS */
+ tmp = gst_collect_pads2_pop (collect, (GstCollectData2 *) data2);
+ fail_unless (tmp == NULL);
+
+ /* these will return immediately as at this point the threads have been
+ * unlocked and are finished */
+ g_thread_join (thread1);
+ g_thread_join (thread2);
+
+ gst_collect_pads2_stop (collect);
+ collected = FALSE;
+
+ buf2 = gst_buffer_new ();
+
+ /* start collect pads */
+ gst_collect_pads2_start (collect);
+
+ /* push buffers on the pads */
+ data1->pad = srcpad1;
+ data1->buffer = buf1;
+ thread1 = g_thread_create (push_buffer, data1, TRUE, NULL);
+ /* here thread1 is blocked and srcpad1 has a queued buffer */
+ fail_unless_collected (FALSE);
+
+ data2->pad = srcpad2;
+ data2->buffer = buf2;
+ thread2 = g_thread_create (push_buffer, data2, TRUE, NULL);
+
+ /* now both pads have a buffer */
+ fail_unless_collected (TRUE);
+
+ tmp = gst_collect_pads2_pop (collect, (GstCollectData2 *) data1);
+ fail_unless (tmp == buf1);
+ tmp = gst_collect_pads2_pop (collect, (GstCollectData2 *) data2);
+ fail_unless (tmp == buf2);
+
+ /* these will return immediately as at this point the threads have been
+ * unlocked and are finished */
+ g_thread_join (thread1);
+ g_thread_join (thread2);
+
+ gst_collect_pads2_stop (collect);
+
+ gst_buffer_unref (buf1);
+ gst_buffer_unref (buf2);
+
+}
+
+GST_END_TEST;
+
+static Suite *
+gst_collect_pads2_suite (void)
+{
+ Suite *suite;
+ TCase *general;
+
+ suite = suite_create ("GstCollectPads2");
+ general = tcase_create ("general");
+ suite_add_tcase (suite, general);
+ tcase_add_checked_fixture (general, setup, teardown);
+ tcase_add_test (general, test_pad_add_remove);
+ tcase_add_test (general, test_collect);
+ tcase_add_test (general, test_collect_eos);
+ tcase_add_test (general, test_collect_twice);
+
+ return suite;
+}
+
+GST_CHECK_MAIN (gst_collect_pads2);