diff -r 000000000000 -r 0e761a78d257 gstreamer_core/tsrc/check/gst/gstbus/src/gstbus.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gstreamer_core/tsrc/check/gst/gstbus/src/gstbus.c Thu Dec 17 08:53:32 2009 +0200 @@ -0,0 +1,581 @@ +/* GStreamer message bus unit tests + * Copyright (C) 2005 Andy Wingo + * Copyright (C) 2007 Tim-Philipp Müller + * + * 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 +#include "libgstreamer_wsd_solution.h" + +#include +#include +//gboolean _gst_check_expecting_log = FALSE; +#if EMULATOR +static GET_GLOBAL_VAR_FROM_TLS(threads_running,gstcheck,gboolean) +#define _gst_check_threads_running (*GET_GSTREAMER_WSD_VAR_NAME(threads_running,gstcheck,g)()) +#else +extern gboolean _gst_check_threads_running = FALSE; +#endif +#if EMULATOR +static GET_GLOBAL_VAR_FROM_TLS(raised_critical,gstcheck,gboolean) +#define _gst_check_raised_critical (*GET_GSTREAMER_WSD_VAR_NAME(raised_critical,gstcheck,g)()) +#else +extern gboolean _gst_check_raised_critical = FALSE; +#endif +//gboolean _gst_check_raised_warning = FALSE; +#if EMULATOR +static GET_GLOBAL_VAR_FROM_TLS(raised_warning,gstcheck,gboolean) +#define _gst_check_raised_warning (*GET_GSTREAMER_WSD_VAR_NAME(raised_warning,gstcheck,g)()) +#else +extern gboolean _gst_check_raised_warning = FALSE; +#endif +//gboolean _gst_check_expecting_log = FALSE; +#if EMULATOR +static GET_GLOBAL_VAR_FROM_TLS(expecting_log,gstcheck,gboolean) +#define _gst_check_expecting_log (*GET_GSTREAMER_WSD_VAR_NAME(expecting_log,gstcheck,g)()) +#else +extern gboolean _gst_check_expecting_log = FALSE; +#endif +#if EMULATOR +GET_GLOBAL_VAR_FROM_TLS(buffers,gstcheck,GList*) +#define buffers (*GET_GSTREAMER_WSD_VAR_NAME(buffers,gstcheck,g)()) +#else +extern GList *buffers = NULL; +#endif + +#if EMULATOR +GET_GLOBAL_VAR_FROM_TLS(thread_list,gstcheck,GList*) +#define thread_list (*GET_GSTREAMER_WSD_VAR_NAME(thread_list,gstcheck,g)()) +#else +extern GList *thread_list; +#endif + +//GMutex *mutex; +#if EMULATOR +GET_GLOBAL_VAR_FROM_TLS(mutex,gstcheck,GMutex*) +#define mutex (*GET_GSTREAMER_WSD_VAR_NAME(mutex,gstcheck,g)()) +#else +extern GMutex *mutex; +#endif + +//GCond *start_cond; /* used to notify main thread of thread startups */ +#if EMULATOR +static GET_GLOBAL_VAR_FROM_TLS(start_cond,gstcheck,GCond*) +#define start_cond (*GET_GSTREAMER_WSD_VAR_NAME(start_cond,gstcheck,g)()) +#else +extern GCond *start_cond; +#endif + +//GCond *sync_cond; /* used to synchronize all threads and main thread */ +#if EMULATOR +static GET_GLOBAL_VAR_FROM_TLS(sync_cond,gstcheck,GCond*) +#define sync_cond (*GET_GSTREAMER_WSD_VAR_NAME(sync_cond,gstcheck,g)()) +#else +extern GCond *sync_cond; +#endif + +#define LOG_FILE "c:\\logs\\gstbus_logs.txt" +#include "std_log_result.h" +#define LOG_FILENAME_LINE __FILE__, __LINE__ +void create_xml(int result) +{ + if(result) + assert_failed = 1; + + testResultXml(xmlfile); + close_log_file(); +} + + + + +static GstBus *test_bus = NULL; +static GMainLoop *main_loop; + +#define NUM_MESSAGES 100 +#define NUM_THREADS 10 + +static gpointer +pound_bus_with_messages (gpointer data) +{ + gint thread_id = GPOINTER_TO_INT (data); + gint i; + + for (i = 0; i < NUM_MESSAGES; i++) { + GstMessage *m; + GstStructure *s; + + s = gst_structure_new ("test_message", + "thread_id", G_TYPE_INT, thread_id, "msg_id", G_TYPE_INT, i, NULL); + m = gst_message_new_application (NULL, s); + gst_bus_post (test_bus, m); + } + return NULL; +} + +static void +pull_messages (void) +{ + GstMessage *m; + const GstStructure *s; + guint message_ids[NUM_THREADS]; + gint i; + + for (i = 0; i < NUM_THREADS; i++) + message_ids[i] = 0; + + while (1) { + gint _t, _i; + + m = gst_bus_pop (test_bus); + if (!m) + break; + g_return_if_fail (GST_MESSAGE_TYPE (m) == GST_MESSAGE_APPLICATION); + + s = gst_message_get_structure (m); + if (!gst_structure_get_int (s, "thread_id", &_t)) + g_critical ("Invalid message"); + if (!gst_structure_get_int (s, "msg_id", &_i)) + g_critical ("Invalid message"); + + g_return_if_fail (_t < NUM_THREADS); + g_return_if_fail (_i == message_ids[_t]++); + + gst_message_unref (m); + } + + for (i = 0; i < NUM_THREADS; i++) + g_return_if_fail (message_ids[i] == NUM_MESSAGES); +} + +void test_hammer_bus() +{ + GThread *threads[NUM_THREADS]; + gint i; + + std_log(LOG_FILENAME_LINE, "Test Started test_hammer_bus"); + test_bus = gst_bus_new (); + + for (i = 0; i < NUM_THREADS; i++) + threads[i] = g_thread_create (pound_bus_with_messages, GINT_TO_POINTER (i), + TRUE, NULL); + + for (i = 0; i < NUM_THREADS; i++) + g_thread_join (threads[i]); + + pull_messages (); + + gst_object_unref ((GstObject *) test_bus); + std_log(LOG_FILENAME_LINE, "Test Successful"); + create_xml(0); +} + + + +static gboolean +message_func_eos (GstBus * bus, GstMessage * message, gpointer data) +{ + const GstStructure *s; + gint i; + + g_return_val_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_EOS, FALSE); + + GST_DEBUG ("got EOS message"); + + s = gst_message_get_structure (message); + if (!gst_structure_get_int (s, "msg_id", &i)) + g_critical ("Invalid message"); + + return i != 9; +} + +static gboolean +message_func_app (GstBus * bus, GstMessage * message, gpointer data) +{ + const GstStructure *s; + gint i; + + g_return_val_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_APPLICATION, + FALSE); + + GST_DEBUG ("got APP message"); + + s = gst_message_get_structure (message); + if (!gst_structure_get_int (s, "msg_id", &i)) + g_critical ("Invalid message"); + + return i != 9; +} + +static gboolean +send_messages (gpointer data) +{ + GstMessage *m; + GstStructure *s; + gint i; + + for (i = 0; i < 10; i++) { + s = gst_structure_new ("test_message", "msg_id", G_TYPE_INT, i, NULL); + m = gst_message_new_application (NULL, s); + gst_bus_post (test_bus, m); + s = gst_structure_new ("test_message", "msg_id", G_TYPE_INT, i, NULL); + m = gst_message_new_custom (GST_MESSAGE_EOS, NULL, s); + gst_bus_post (test_bus, m); + } + + return FALSE; +} + +/* test if adding a signal watch for different message types calls the + * respective callbacks. */ +void test_watch() +{ + guint id; + + std_log(LOG_FILENAME_LINE, "Test Started test_watch"); + + test_bus = gst_bus_new (); + + main_loop = g_main_loop_new (NULL, FALSE); + + id = gst_bus_add_watch (test_bus, gst_bus_async_signal_func, NULL); + g_signal_connect (test_bus, "message::eos", (GCallback) message_func_eos, + NULL); + g_signal_connect (test_bus, "message::application", + (GCallback) message_func_app, NULL); + + g_idle_add ((GSourceFunc) send_messages, NULL); + while (g_main_context_pending (NULL)) + g_main_context_iteration (NULL, FALSE); + + g_source_remove (id); + g_main_loop_unref (main_loop); + + gst_object_unref ((GstObject *) test_bus); + std_log(LOG_FILENAME_LINE, "Test Successful"); + create_xml(0); +} + + + +static gint messages_seen; + +static void +message_func (GstBus * bus, GstMessage * message, gpointer data) +{ + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_APPLICATION); + + messages_seen++; +} + +static void +send_5app_1el_1err_2app_messages (guint interval_usecs) +{ + GstMessage *m; + GstStructure *s; + gint i; + + for (i = 0; i < 5; i++) { + s = gst_structure_new ("test_message", "msg_id", G_TYPE_INT, i, NULL); + m = gst_message_new_application (NULL, s); + GST_LOG ("posting application message"); + gst_bus_post (test_bus, m); + g_usleep (interval_usecs); + } + for (i = 0; i < 1; i++) { + s = gst_structure_new ("test_message", "msg_id", G_TYPE_INT, i, NULL); + m = gst_message_new_element (NULL, s); + GST_LOG ("posting element message"); + gst_bus_post (test_bus, m); + g_usleep (interval_usecs); + } + for (i = 0; i < 1; i++) { + m = gst_message_new_error (NULL, NULL, "debug string"); + GST_LOG ("posting error message"); + gst_bus_post (test_bus, m); + g_usleep (interval_usecs); + } + for (i = 0; i < 2; i++) { + s = gst_structure_new ("test_message", "msg_id", G_TYPE_INT, i, NULL); + m = gst_message_new_application (NULL, s); + GST_LOG ("posting application message"); + gst_bus_post (test_bus, m); + g_usleep (interval_usecs); + } +} + +static void +send_10_app_messages (void) +{ + GstMessage *m; + GstStructure *s; + gint i; + + for (i = 0; i < 10; i++) { + s = gst_structure_new ("test_message", "msg_id", G_TYPE_INT, i, NULL); + m = gst_message_new_application (NULL, s); + gst_bus_post (test_bus, m); + } +} + +/* test that you get the same messages from a poll as from signal watches. */ +void test_watch_with_poll() +{ + guint i; + + std_log(LOG_FILENAME_LINE, "Test Started test_watch_with_poll"); + + test_bus = gst_bus_new (); + messages_seen = 0; + + gst_bus_add_signal_watch (test_bus); + g_signal_connect (test_bus, "message", (GCallback) message_func, NULL); + + send_10_app_messages (); + + for (i = 0; i < 10; i++) + gst_message_unref (gst_bus_poll (test_bus, GST_MESSAGE_APPLICATION, + GST_CLOCK_TIME_NONE)); + + fail_if (gst_bus_have_pending (test_bus), "unexpected messages on bus"); + fail_unless (messages_seen == 10, "signal handler didn't get 10 messages"); + + gst_bus_remove_signal_watch (test_bus); + + gst_object_unref (test_bus); + std_log(LOG_FILENAME_LINE, "Test Successful"); + create_xml(0); +} + + + +/* test that you get the messages with pop. */ +void test_timed_pop() +{ + guint i; + + std_log(LOG_FILENAME_LINE, "Test Started test_timed_pop"); + + test_bus = gst_bus_new (); + + send_10_app_messages (); + + for (i = 0; i < 10; i++) + gst_message_unref (gst_bus_timed_pop (test_bus, GST_CLOCK_TIME_NONE)); + + fail_if (gst_bus_have_pending (test_bus), "unexpected messages on bus"); + + gst_object_unref (test_bus); + std_log(LOG_FILENAME_LINE, "Test Successful"); + create_xml(0); +} + + + +/* test that you get the messages with pop_filtered */ +void test_timed_pop_filtered() +{ + GstMessage *msg; + guint i; + + std_log(LOG_FILENAME_LINE, "Test Started test_timed_pop_filtered"); + + test_bus = gst_bus_new (); + + send_10_app_messages (); + for (i = 0; i < 10; i++) { + msg = gst_bus_timed_pop_filtered (test_bus, GST_CLOCK_TIME_NONE, + GST_MESSAGE_ANY); + fail_unless (msg != NULL); + gst_message_unref (msg); + + } + + /* should flush all messages on the bus with types not matching */ + send_10_app_messages (); + msg = gst_bus_timed_pop_filtered (test_bus, 0, + GST_MESSAGE_ANY ^ GST_MESSAGE_APPLICATION); + fail_unless (msg == NULL); + msg = gst_bus_timed_pop_filtered (test_bus, GST_SECOND / 2, + GST_MESSAGE_ANY ^ GST_MESSAGE_APPLICATION); + fail_unless (msg == NULL); + /* there should be nothing on the bus now */ + fail_if (gst_bus_have_pending (test_bus), "unexpected messages on bus"); + msg = gst_bus_timed_pop_filtered (test_bus, 0, GST_MESSAGE_ANY); + fail_unless (msg == NULL); + + send_5app_1el_1err_2app_messages (0); + msg = gst_bus_timed_pop_filtered (test_bus, 0, + GST_MESSAGE_ANY ^ GST_MESSAGE_APPLICATION); + fail_unless (msg != NULL); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT); + gst_message_unref (msg); + fail_unless (gst_bus_have_pending (test_bus), "expected messages on bus"); + msg = gst_bus_timed_pop_filtered (test_bus, 0, GST_MESSAGE_APPLICATION); + fail_unless (msg != NULL); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_APPLICATION); + gst_message_unref (msg); + msg = gst_bus_timed_pop_filtered (test_bus, 0, GST_MESSAGE_ERROR); + fail_unless (msg == NULL); + + gst_object_unref (test_bus); + std_log(LOG_FILENAME_LINE, "Test Successful"); + create_xml(0); +} + + + +static gpointer +post_delayed_thread (gpointer data) +{ + THREAD_START (); + send_5app_1el_1err_2app_messages (1 * G_USEC_PER_SEC); + return NULL; +} + +/* test that you get the messages with pop_filtered if there's a timeout*/ +void test_timed_pop_filtered_with_timeout() +{ + GstMessage *msg; + + std_log(LOG_FILENAME_LINE, "test_timed_pop_filtered_with_timeout"); + MAIN_INIT (); + + test_bus = gst_bus_new (); + + MAIN_START_THREAD_FUNCTIONS (1, post_delayed_thread, NULL); + + + MAIN_SYNCHRONIZE (); + + msg = gst_bus_timed_pop_filtered (test_bus, 2 * GST_SECOND, + GST_MESSAGE_ERROR); + fail_unless (msg == NULL, "Got unexpected %s message", + (msg) ? GST_MESSAGE_TYPE_NAME (msg) : ""); + msg = gst_bus_timed_pop_filtered (test_bus, (3 + 1 + 1 + 1) * GST_SECOND, + GST_MESSAGE_ERROR | GST_MESSAGE_ELEMENT); + fail_unless (msg != NULL, "expected element message, but got nothing"); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT); + gst_message_unref (msg); + msg = gst_bus_timed_pop_filtered (test_bus, GST_CLOCK_TIME_NONE, + GST_MESSAGE_APPLICATION); + fail_unless (msg != NULL, "expected application message, but got nothing"); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_APPLICATION); + gst_message_unref (msg); + msg = gst_bus_timed_pop_filtered (test_bus, GST_CLOCK_TIME_NONE, + GST_MESSAGE_APPLICATION); + fail_unless (msg != NULL, "expected application message, but got nothing"); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_APPLICATION); + gst_message_unref (msg); + msg = gst_bus_timed_pop_filtered (test_bus, GST_SECOND / 4, + GST_MESSAGE_TAG | GST_MESSAGE_ERROR); + fail_unless (msg == NULL, "Got unexpected %s message", + (msg) ? GST_MESSAGE_TYPE_NAME (msg) : ""); + + MAIN_STOP_THREADS (); + + gst_object_unref (test_bus); + std_log(LOG_FILENAME_LINE, "Test Successful"); + create_xml(0); +} + + + +/* test that you get the messages with pop from another thread. */ +static gpointer +pop_thread (gpointer data) +{ + GstBus *bus = GST_BUS_CAST (data); + guint i; + + for (i = 0; i < 10; i++) + gst_message_unref (gst_bus_timed_pop (bus, GST_CLOCK_TIME_NONE)); + + return NULL; +} + +void test_timed_pop_thread() +{ + GThread *thread; + GError *error = NULL; + + std_log(LOG_FILENAME_LINE, "Test Started test_timed_pop_thread"); + + test_bus = gst_bus_new (); + + thread = g_thread_create (pop_thread, test_bus, TRUE, &error); + fail_if (error != NULL); + + send_10_app_messages (); + + g_thread_join (thread); + + fail_if (gst_bus_have_pending (test_bus), "unexpected messages on bus"); + + /* try to pop a message without timeout. */ + fail_if (gst_bus_timed_pop (test_bus, 0) != NULL); + + /* with a small timeout */ + fail_if (gst_bus_timed_pop (test_bus, 1000) != NULL); + + gst_object_unref (test_bus); + std_log(LOG_FILENAME_LINE, "Test Successful"); + create_xml(0); +} + + +/* +void +gst_bus_suite (void) +{ +test_hammer_bus(); +test_watch(); +test_watch_with_poll(); +test_timed_pop(); +test_timed_pop_thread(); +test_timed_pop_filtered(); +test_timed_pop_filtered_with_timeout(); +} +*/ +void (*fn[]) (void) = { +test_hammer_bus, +test_watch, +test_watch_with_poll, +test_timed_pop, +test_timed_pop_thread, +test_timed_pop_filtered, +test_timed_pop_filtered_with_timeout +}; + +char *args[] = { +"test_hammer_bus", +"test_watch", +"test_watch_with_poll", +"test_timed_pop", +"test_timed_pop_thread", +"test_timed_pop_filtered", +"test_timed_pop_filtered_with_timeout" +}; + + +GST_CHECK_MAIN (gst_bus); + + +