mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-22 14:06:23 +00:00
testsuite/threads/: Added a bunch of testcases that show threadsafety bugs in glib.
Original commit message from CVS: * testsuite/threads/Makefile.am: * testsuite/threads/signals.c: (gst_test_get_type), (gst_test_class_init), (gst_test_init), (gst_test_dispose), (gst_test_set_property), (gst_test_get_property), (gst_test_do_signal1), (signal2_handler), (gst_test_do_signal2), (gst_test_do_prop), (run_thread), (main): Added a bunch of testcases that show threadsafety bugs in glib.
This commit is contained in:
parent
ab472f9a48
commit
4c20dfd33d
5 changed files with 486 additions and 4 deletions
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
|||
2004-11-29 Wim Taymans <wim@fluendo.com>
|
||||
|
||||
* testsuite/threads/Makefile.am:
|
||||
* testsuite/threads/signals.c: (gst_test_get_type),
|
||||
(gst_test_class_init), (gst_test_init), (gst_test_dispose),
|
||||
(gst_test_set_property), (gst_test_get_property),
|
||||
(gst_test_do_signal1), (signal2_handler), (gst_test_do_signal2),
|
||||
(gst_test_do_prop), (run_thread), (main):
|
||||
Added a bunch of testcases that show threadsafety bugs in glib.
|
||||
|
||||
2004-11-29 Stefan Kost <ensonic@users.sf.net>
|
||||
|
||||
* docs/manual/programs.xml:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
include ../Rules
|
||||
|
||||
tests_pass = thread1 thread2 thread3 thread4 thread5 threade threadf
|
||||
tests_fail = 159566
|
||||
tests_pass = thread1 thread2 thread3 thread4 thread5 threade threadf signal1
|
||||
tests_fail = 159566 signal2 signal3
|
||||
|
||||
# threadh
|
||||
|
||||
|
@ -17,3 +17,10 @@ thread4_SOURCES = thread.c
|
|||
thread4_CFLAGS = -DTESTNUM=4 $(AM_CFLAGS)
|
||||
thread5_SOURCES = thread.c
|
||||
thread5_CFLAGS = -DTESTNUM=5 $(AM_CFLAGS)
|
||||
|
||||
signal1_SOURCES = signals.c
|
||||
signal1_CFLAGS = -DTESTNUM=1 $(AM_CFLAGS)
|
||||
signal2_SOURCES = signals.c
|
||||
signal2_CFLAGS = -DTESTNUM=2 $(AM_CFLAGS)
|
||||
signal3_SOURCES = signals.c
|
||||
signal3_CFLAGS = -DTESTNUM=3 $(AM_CFLAGS)
|
||||
|
|
229
tests/old/testsuite/threads/signals.c
Normal file
229
tests/old/testsuite/threads/signals.c
Normal file
|
@ -0,0 +1,229 @@
|
|||
#include <unistd.h>
|
||||
#include <gst/gst.h>
|
||||
|
||||
#define GST_TYPE_TEST (gst_test_get_type ())
|
||||
#define GST_TEST(test) (G_TYPE_CHECK_INSTANCE_CAST ((test), GST_TYPE_TEST, GstTest))
|
||||
#define GST_IS_TEST(test) (G_TYPE_CHECK_INSTANCE_TYPE ((test), GST_TYPE_TEST))
|
||||
#define GST_TEST_CLASS(tclass) (G_TYPE_CHECK_CLASS_CAST ((tclass), GST_TYPE_TEST, GstTestClass))
|
||||
#define GST_IS_TEST_CLASS(tclass) (G_TYPE_CHECK_CLASS_TYPE ((tclass), GST_TYPE_TEST))
|
||||
#define GST_TEST_GET_CLASS(test) (G_TYPE_INSTANCE_GET_CLASS ((test), GST_TYPE_TEST, GstTestClass))
|
||||
|
||||
typedef struct _GstTest GstTest;
|
||||
typedef struct _GstTestClass GstTestClass;
|
||||
|
||||
struct _GstTest
|
||||
{
|
||||
GstObject object;
|
||||
};
|
||||
|
||||
struct _GstTestClass
|
||||
{
|
||||
GstObjectClass parent_class;
|
||||
|
||||
void (*test_signal1) (GstTest * test, gint an_int);
|
||||
void (*test_signal2) (GstTest * test, gint an_int);
|
||||
};
|
||||
|
||||
static GType gst_test_get_type (void);
|
||||
|
||||
/* Element signals and args */
|
||||
enum
|
||||
{
|
||||
TEST_SIGNAL1,
|
||||
TEST_SIGNAL2,
|
||||
/* add more above */
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_TEST_PROP
|
||||
};
|
||||
|
||||
static void gst_test_class_init (GstTestClass * klass);
|
||||
static void gst_test_init (GstTest * test);
|
||||
static void gst_test_dispose (GObject * object);
|
||||
|
||||
static void signal2_handler (GstTest * test, gint anint);
|
||||
|
||||
static void gst_test_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_test_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static GstObjectClass *parent_class = NULL;
|
||||
|
||||
static guint gst_test_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
static GType
|
||||
gst_test_get_type (void)
|
||||
{
|
||||
static GType test_type = 0;
|
||||
|
||||
if (!test_type) {
|
||||
static const GTypeInfo test_info = {
|
||||
sizeof (GstTestClass),
|
||||
NULL,
|
||||
NULL,
|
||||
(GClassInitFunc) gst_test_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof (GstTest),
|
||||
0,
|
||||
(GInstanceInitFunc) gst_test_init,
|
||||
NULL
|
||||
};
|
||||
|
||||
test_type = g_type_register_static (GST_TYPE_OBJECT, "GstTest",
|
||||
&test_info, 0);
|
||||
}
|
||||
return test_type;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_test_class_init (GstTestClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstObjectClass *gstobject_class;
|
||||
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
gstobject_class = (GstObjectClass *) klass;
|
||||
|
||||
parent_class = g_type_class_ref (GST_TYPE_OBJECT);
|
||||
|
||||
if (!g_thread_supported ())
|
||||
g_thread_init (NULL);
|
||||
|
||||
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_test_dispose);
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_test_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_test_get_property);
|
||||
|
||||
gst_test_signals[TEST_SIGNAL1] =
|
||||
g_signal_new ("test-signal1", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstTestClass, test_signal1), NULL,
|
||||
NULL, gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
|
||||
gst_test_signals[TEST_SIGNAL2] =
|
||||
g_signal_new ("test-signal2", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstTestClass, test_signal2), NULL,
|
||||
NULL, gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TEST_PROP,
|
||||
g_param_spec_int ("test-prop", "Test Prop", "Test property",
|
||||
0, 1, 0, G_PARAM_READWRITE));
|
||||
|
||||
klass->test_signal2 = signal2_handler;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_test_init (GstTest * test)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gst_test_dispose (GObject * object)
|
||||
{
|
||||
GstTest *test;
|
||||
|
||||
test = GST_TEST (object);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_test_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstTest *test;
|
||||
|
||||
test = GST_TEST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_TEST_PROP:
|
||||
g_value_get_int (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_test_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstTest *test;
|
||||
|
||||
test = GST_TEST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_TEST_PROP:
|
||||
g_value_set_int (value, 0);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_test_do_signal1 (GstTest * test)
|
||||
{
|
||||
g_signal_emit (G_OBJECT (test), gst_test_signals[TEST_SIGNAL1], 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
signal2_handler (GstTest * test, gint anint)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gst_test_do_signal2 (GstTest * test)
|
||||
{
|
||||
g_signal_emit (G_OBJECT (test), gst_test_signals[TEST_SIGNAL2], 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_test_do_prop (GstTest * test)
|
||||
{
|
||||
g_object_notify (G_OBJECT (test), "test-prop");
|
||||
}
|
||||
|
||||
static gpointer
|
||||
run_thread (GstTest * test)
|
||||
{
|
||||
gint i = 0;
|
||||
|
||||
while (TRUE) {
|
||||
if (TESTNUM == 1)
|
||||
gst_test_do_signal1 (test);
|
||||
if (TESTNUM == 2)
|
||||
gst_test_do_signal2 (test);
|
||||
if (TESTNUM == 3)
|
||||
gst_test_do_prop (test);
|
||||
if ((i++ % 10000) == 0)
|
||||
g_print (".");
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
gint i;
|
||||
GstTest *test1, *test2;
|
||||
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
test1 = g_object_new (GST_TYPE_TEST, NULL);
|
||||
test2 = g_object_new (GST_TYPE_TEST, NULL);
|
||||
|
||||
for (i = 0; i < 100; i++) {
|
||||
g_thread_create ((GThreadFunc) run_thread, test1, TRUE, NULL);
|
||||
g_thread_create ((GThreadFunc) run_thread, test2, TRUE, NULL);
|
||||
}
|
||||
sleep (5);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
include ../Rules
|
||||
|
||||
tests_pass = thread1 thread2 thread3 thread4 thread5 threade threadf
|
||||
tests_fail = 159566
|
||||
tests_pass = thread1 thread2 thread3 thread4 thread5 threade threadf signal1
|
||||
tests_fail = 159566 signal2 signal3
|
||||
|
||||
# threadh
|
||||
|
||||
|
@ -17,3 +17,10 @@ thread4_SOURCES = thread.c
|
|||
thread4_CFLAGS = -DTESTNUM=4 $(AM_CFLAGS)
|
||||
thread5_SOURCES = thread.c
|
||||
thread5_CFLAGS = -DTESTNUM=5 $(AM_CFLAGS)
|
||||
|
||||
signal1_SOURCES = signals.c
|
||||
signal1_CFLAGS = -DTESTNUM=1 $(AM_CFLAGS)
|
||||
signal2_SOURCES = signals.c
|
||||
signal2_CFLAGS = -DTESTNUM=2 $(AM_CFLAGS)
|
||||
signal3_SOURCES = signals.c
|
||||
signal3_CFLAGS = -DTESTNUM=3 $(AM_CFLAGS)
|
||||
|
|
229
testsuite/threads/signals.c
Normal file
229
testsuite/threads/signals.c
Normal file
|
@ -0,0 +1,229 @@
|
|||
#include <unistd.h>
|
||||
#include <gst/gst.h>
|
||||
|
||||
#define GST_TYPE_TEST (gst_test_get_type ())
|
||||
#define GST_TEST(test) (G_TYPE_CHECK_INSTANCE_CAST ((test), GST_TYPE_TEST, GstTest))
|
||||
#define GST_IS_TEST(test) (G_TYPE_CHECK_INSTANCE_TYPE ((test), GST_TYPE_TEST))
|
||||
#define GST_TEST_CLASS(tclass) (G_TYPE_CHECK_CLASS_CAST ((tclass), GST_TYPE_TEST, GstTestClass))
|
||||
#define GST_IS_TEST_CLASS(tclass) (G_TYPE_CHECK_CLASS_TYPE ((tclass), GST_TYPE_TEST))
|
||||
#define GST_TEST_GET_CLASS(test) (G_TYPE_INSTANCE_GET_CLASS ((test), GST_TYPE_TEST, GstTestClass))
|
||||
|
||||
typedef struct _GstTest GstTest;
|
||||
typedef struct _GstTestClass GstTestClass;
|
||||
|
||||
struct _GstTest
|
||||
{
|
||||
GstObject object;
|
||||
};
|
||||
|
||||
struct _GstTestClass
|
||||
{
|
||||
GstObjectClass parent_class;
|
||||
|
||||
void (*test_signal1) (GstTest * test, gint an_int);
|
||||
void (*test_signal2) (GstTest * test, gint an_int);
|
||||
};
|
||||
|
||||
static GType gst_test_get_type (void);
|
||||
|
||||
/* Element signals and args */
|
||||
enum
|
||||
{
|
||||
TEST_SIGNAL1,
|
||||
TEST_SIGNAL2,
|
||||
/* add more above */
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_TEST_PROP
|
||||
};
|
||||
|
||||
static void gst_test_class_init (GstTestClass * klass);
|
||||
static void gst_test_init (GstTest * test);
|
||||
static void gst_test_dispose (GObject * object);
|
||||
|
||||
static void signal2_handler (GstTest * test, gint anint);
|
||||
|
||||
static void gst_test_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_test_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static GstObjectClass *parent_class = NULL;
|
||||
|
||||
static guint gst_test_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
static GType
|
||||
gst_test_get_type (void)
|
||||
{
|
||||
static GType test_type = 0;
|
||||
|
||||
if (!test_type) {
|
||||
static const GTypeInfo test_info = {
|
||||
sizeof (GstTestClass),
|
||||
NULL,
|
||||
NULL,
|
||||
(GClassInitFunc) gst_test_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof (GstTest),
|
||||
0,
|
||||
(GInstanceInitFunc) gst_test_init,
|
||||
NULL
|
||||
};
|
||||
|
||||
test_type = g_type_register_static (GST_TYPE_OBJECT, "GstTest",
|
||||
&test_info, 0);
|
||||
}
|
||||
return test_type;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_test_class_init (GstTestClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstObjectClass *gstobject_class;
|
||||
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
gstobject_class = (GstObjectClass *) klass;
|
||||
|
||||
parent_class = g_type_class_ref (GST_TYPE_OBJECT);
|
||||
|
||||
if (!g_thread_supported ())
|
||||
g_thread_init (NULL);
|
||||
|
||||
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_test_dispose);
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_test_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_test_get_property);
|
||||
|
||||
gst_test_signals[TEST_SIGNAL1] =
|
||||
g_signal_new ("test-signal1", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstTestClass, test_signal1), NULL,
|
||||
NULL, gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
|
||||
gst_test_signals[TEST_SIGNAL2] =
|
||||
g_signal_new ("test-signal2", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstTestClass, test_signal2), NULL,
|
||||
NULL, gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TEST_PROP,
|
||||
g_param_spec_int ("test-prop", "Test Prop", "Test property",
|
||||
0, 1, 0, G_PARAM_READWRITE));
|
||||
|
||||
klass->test_signal2 = signal2_handler;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_test_init (GstTest * test)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gst_test_dispose (GObject * object)
|
||||
{
|
||||
GstTest *test;
|
||||
|
||||
test = GST_TEST (object);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_test_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstTest *test;
|
||||
|
||||
test = GST_TEST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_TEST_PROP:
|
||||
g_value_get_int (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_test_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstTest *test;
|
||||
|
||||
test = GST_TEST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_TEST_PROP:
|
||||
g_value_set_int (value, 0);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_test_do_signal1 (GstTest * test)
|
||||
{
|
||||
g_signal_emit (G_OBJECT (test), gst_test_signals[TEST_SIGNAL1], 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
signal2_handler (GstTest * test, gint anint)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gst_test_do_signal2 (GstTest * test)
|
||||
{
|
||||
g_signal_emit (G_OBJECT (test), gst_test_signals[TEST_SIGNAL2], 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_test_do_prop (GstTest * test)
|
||||
{
|
||||
g_object_notify (G_OBJECT (test), "test-prop");
|
||||
}
|
||||
|
||||
static gpointer
|
||||
run_thread (GstTest * test)
|
||||
{
|
||||
gint i = 0;
|
||||
|
||||
while (TRUE) {
|
||||
if (TESTNUM == 1)
|
||||
gst_test_do_signal1 (test);
|
||||
if (TESTNUM == 2)
|
||||
gst_test_do_signal2 (test);
|
||||
if (TESTNUM == 3)
|
||||
gst_test_do_prop (test);
|
||||
if ((i++ % 10000) == 0)
|
||||
g_print (".");
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
gint i;
|
||||
GstTest *test1, *test2;
|
||||
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
test1 = g_object_new (GST_TYPE_TEST, NULL);
|
||||
test2 = g_object_new (GST_TYPE_TEST, NULL);
|
||||
|
||||
for (i = 0; i < 100; i++) {
|
||||
g_thread_create ((GThreadFunc) run_thread, test1, TRUE, NULL);
|
||||
g_thread_create ((GThreadFunc) run_thread, test2, TRUE, NULL);
|
||||
}
|
||||
sleep (5);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue