tests/check/: Add some test basetransform element and the beginnings of various unit tests for it.

Original commit message from CVS:
* tests/check/Makefile.am:
* tests/check/libs/test_transform.c: (gst_test_trans_base_init),
(gst_test_trans_class_init), (gst_test_trans_init),
(gst_test_trans_set_data), (result_sink_chain),
(gst_test_trans_new), (gst_test_trans_free), (gst_test_trans_push),
(gst_test_trans_pop):
* tests/check/libs/transform1.c: (GST_START_TEST),
(transform_ip_1), (set_caps_1), (gst_basetransform_suite):
Add some test basetransform element and the beginnings of various
unit tests for it.
This commit is contained in:
Wim Taymans 2008-06-20 12:06:54 +00:00
parent bfb7bace38
commit 90629e72a2
4 changed files with 527 additions and 1 deletions

View file

@ -1,3 +1,16 @@
2008-06-20 Wim Taymans <wim.taymans@collabora.co.uk>
* tests/check/Makefile.am:
* tests/check/libs/test_transform.c: (gst_test_trans_base_init),
(gst_test_trans_class_init), (gst_test_trans_init),
(gst_test_trans_set_data), (result_sink_chain),
(gst_test_trans_new), (gst_test_trans_free), (gst_test_trans_push),
(gst_test_trans_pop):
* tests/check/libs/transform1.c: (GST_START_TEST),
(transform_ip_1), (set_caps_1), (gst_basetransform_suite):
Add some test basetransform element and the beginnings of various
unit tests for it.
2008-06-20 Wim Taymans <wim.taymans@collabora.co.uk>
* libs/gst/base/gsttypefindhelper.c: (helper_find_peek):

View file

@ -100,7 +100,8 @@ check_PROGRAMS = \
libs/gdp \
libs/adapter \
libs/gstnetclientclock \
libs/gstnettimeprovider
libs/gstnettimeprovider \
libs/transform1
# failing tests
# queue : tests is unstable (race conditions)
@ -163,6 +164,9 @@ libs_gstnettimeprovider_LDADD = \
libs_typefindhelper_LDADD = \
$(top_builddir)/libs/gst/base/libgstbase-@GST_MAJORMINOR@.la \
$(LDADD)
libs_transform1_LDADD = \
$(top_builddir)/libs/gst/base/libgstbase-@GST_MAJORMINOR@.la \
$(LDADD)
# valgrind testing
# these just need valgrind fixing, period

View file

@ -0,0 +1,199 @@
#include <gst/base/gstbasetransform.h>
typedef struct
{
GstPad *srcpad;
GstPad *sinkpad;
GList *events;
GList *buffers;
GstElement *trans;
GstBaseTransformClass *klass;
} TestTransData;
static GstStaticPadTemplate gst_test_trans_src_template =
GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("foo/x-bar")
);
static GstStaticPadTemplate gst_test_trans_sink_template =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("foo/x-bar")
);
typedef struct _GstTestTrans GstTestTrans;
typedef struct _GstTestTransClass GstTestTransClass;
#define GST_TYPE_TEST_TRANS \
(gst_test_trans_get_type())
#define GST_TEST_TRANS(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TEST_TRANS,GstTestTrans))
#define GST_TEST_TRANS_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TEST_TRANS,GstTestTransClass))
#define GST_TEST_TRANS_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj), GST_TYPE_TEST_TRANS, GstTestTransClass))
#define GST_IS_TEST_TRANS(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TEST_TRANS))
#define GST_IS_TEST_TRANS_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TEST_TRANS))
struct _GstTestTrans
{
GstBaseTransform element;
TestTransData *data;
};
struct _GstTestTransClass
{
GstBaseTransformClass parent_class;
};
GST_BOILERPLATE (GstTestTrans, gst_test_trans, GstBaseTransform,
GST_TYPE_BASE_TRANSFORM);
static void
gst_test_trans_base_init (gpointer g_class)
{
GstElementClass *element_class;
element_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_set_details_simple (element_class, "TestTrans",
"Filter/Test", "Test transform", "Wim Taymans <wim.taymans@gmail.com>");
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&gst_test_trans_sink_template));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&gst_test_trans_src_template));
}
static GstFlowReturn (*klass_transform) (GstBaseTransform * trans,
GstBuffer * inbuf, GstBuffer * outbuf) = NULL;
static GstFlowReturn (*klass_transform_ip) (GstBaseTransform * trans,
GstBuffer * buf) = NULL;
static gboolean (*klass_set_caps) (GstBaseTransform * trans, GstCaps * incaps,
GstCaps * outcaps) = NULL;
static void
gst_test_trans_class_init (GstTestTransClass * klass)
{
GObjectClass *gobject_class;
GstBaseTransformClass *trans_class;
gobject_class = (GObjectClass *) klass;
trans_class = (GstBaseTransformClass *) klass;
trans_class->transform_ip = klass_transform_ip;
trans_class->transform = klass_transform;
trans_class->set_caps = klass_set_caps;
}
static void
gst_test_trans_init (GstTestTrans * this, GstTestTransClass * g_class)
{
}
static void
gst_test_trans_set_data (GstTestTrans * this, TestTransData * data)
{
this->data = data;
}
static GstFlowReturn
result_sink_chain (GstPad * pad, GstBuffer * buffer)
{
TestTransData *data;
data = gst_pad_get_element_private (pad);
data->buffers = g_list_append (data->buffers, buffer);
return GST_FLOW_OK;
}
static TestTransData *
gst_test_trans_new (void)
{
TestTransData *res;
GstPad *tmp;
res = g_new0 (TestTransData, 1);
res->trans = g_object_new (GST_TYPE_TEST_TRANS, NULL);
res->srcpad =
gst_pad_new_from_static_template (&gst_test_trans_src_template, "src");
res->sinkpad =
gst_pad_new_from_static_template (&gst_test_trans_sink_template, "sink");
res->klass = GST_BASE_TRANSFORM_GET_CLASS (res->trans);
gst_test_trans_set_data (GST_TEST_TRANS (res->trans), res);
gst_pad_set_element_private (res->sinkpad, res);
gst_pad_set_chain_function (res->sinkpad, result_sink_chain);
tmp = gst_element_get_static_pad (res->trans, "sink");
gst_pad_link (res->srcpad, tmp);
gst_object_unref (tmp);
tmp = gst_element_get_static_pad (res->trans, "src");
gst_pad_link (tmp, res->sinkpad);
gst_object_unref (tmp);
gst_pad_set_active (res->sinkpad, TRUE);
gst_element_set_state (res->trans, GST_STATE_PAUSED);
gst_pad_set_active (res->srcpad, TRUE);
return res;
}
static void
gst_test_trans_free (TestTransData * data)
{
GstPad *tmp;
gst_pad_set_active (data->sinkpad, FALSE);
gst_element_set_state (data->trans, GST_STATE_NULL);
gst_pad_set_active (data->srcpad, FALSE);
tmp = gst_element_get_static_pad (data->trans, "src");
gst_pad_unlink (tmp, data->sinkpad);
gst_object_unref (tmp);
tmp = gst_element_get_static_pad (data->trans, "sink");
gst_pad_link (data->srcpad, tmp);
gst_object_unref (tmp);
gst_object_unref (data->srcpad);
gst_object_unref (data->sinkpad);
gst_object_unref (data->trans);
g_free (data);
}
static GstFlowReturn
gst_test_trans_push (TestTransData * data, GstBuffer * buffer)
{
GstFlowReturn ret;
ret = gst_pad_push (data->srcpad, buffer);
return ret;
}
static GstBuffer *
gst_test_trans_pop (TestTransData * data)
{
GstBuffer *ret;
if (data->buffers) {
ret = data->buffers->data;
data->buffers = g_list_delete_link (data->buffers, data->buffers);
} else {
ret = NULL;
}
return ret;
}

View file

@ -0,0 +1,310 @@
/* GStreamer
*
* some unit tests for GstBaseTransform
*
* Copyright (C) 2008 Wim Taymans <wim.taymans@gmail.com>
*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gst/gst.h>
#include <gst/check/gstcheck.h>
#include <gst/base/gstbasetransform.h>
#undef FAILING_TESTS
#include "test_transform.c"
/* basic passthrough, we don't have any transform functions so we can only
* perform passthrough. We also don't have caps, which is fine */
GST_START_TEST (basetransform_chain_pt1)
{
TestTransData *trans;
GstBuffer *buffer;
GstFlowReturn res;
trans = gst_test_trans_new ();
buffer = gst_buffer_new_and_alloc (20);
res = gst_test_trans_push (trans, buffer);
fail_unless (res == GST_FLOW_OK);
buffer = gst_test_trans_pop (trans);
fail_unless (buffer != NULL);
fail_unless (GST_BUFFER_SIZE (buffer) == 20);
/* caps should not have been set */
fail_unless (GST_BUFFER_CAPS (buffer) == NULL);
gst_buffer_unref (buffer);
buffer = gst_buffer_new_and_alloc (10);
res = gst_test_trans_push (trans, buffer);
fail_unless (res == GST_FLOW_OK);
buffer = gst_test_trans_pop (trans);
fail_unless (buffer != NULL);
fail_unless (GST_BUFFER_SIZE (buffer) == 10);
/* caps should not have been set */
fail_unless (GST_BUFFER_CAPS (buffer) == NULL);
gst_buffer_unref (buffer);
gst_test_trans_free (trans);
}
GST_END_TEST;
/* basic passthrough, we don't have any transform functions so we can only
* perform passthrough with same caps */
GST_START_TEST (basetransform_chain_pt2)
{
TestTransData *trans;
GstBuffer *buffer;
GstCaps *caps;
GstFlowReturn res;
trans = gst_test_trans_new ();
/* first buffer */
caps = gst_caps_new_simple ("foo/x-bar", NULL);
buffer = gst_buffer_new_and_alloc (20);
gst_buffer_set_caps (buffer, caps);
res = gst_test_trans_push (trans, buffer);
fail_unless (res == GST_FLOW_OK);
buffer = gst_test_trans_pop (trans);
fail_unless (buffer != NULL);
fail_unless (GST_BUFFER_SIZE (buffer) == 20);
fail_unless (GST_BUFFER_CAPS (buffer) == caps);
gst_buffer_unref (buffer);
gst_caps_unref (caps);
/* second buffer, renegotiates, keeps extra type arg in caps */
caps = gst_caps_new_simple ("foo/x-bar", "type", G_TYPE_INT, 1, NULL);
buffer = gst_buffer_new_and_alloc (10);
gst_buffer_set_caps (buffer, caps);
res = gst_test_trans_push (trans, buffer);
fail_unless (res == GST_FLOW_OK);
buffer = gst_test_trans_pop (trans);
fail_unless (buffer != NULL);
fail_unless (GST_BUFFER_SIZE (buffer) == 10);
fail_unless (GST_BUFFER_CAPS (buffer) == caps);
gst_buffer_unref (buffer);
gst_caps_unref (caps);
gst_test_trans_free (trans);
}
GST_END_TEST;
static gboolean transform_ip_1_called;
static gboolean transform_ip_1_writable;
static GstFlowReturn
transform_ip_1 (GstBaseTransform * trans, GstBuffer * buf)
{
GST_DEBUG_OBJECT (trans, "transform called");
transform_ip_1_called = TRUE;
transform_ip_1_writable = gst_buffer_is_writable (buf);
GST_DEBUG_OBJECT (trans, "writable: %d", transform_ip_1_writable);
return GST_FLOW_OK;
}
/* basic in-place, check if the _ip function is called, buffer should
* be writable. no setcaps is set */
GST_START_TEST (basetransform_chain_ip1)
{
TestTransData *trans;
GstBuffer *buffer;
GstFlowReturn res;
klass_transform_ip = transform_ip_1;
trans = gst_test_trans_new ();
buffer = gst_buffer_new_and_alloc (20);
transform_ip_1_called = FALSE;;
transform_ip_1_writable = TRUE;;
res = gst_test_trans_push (trans, buffer);
fail_unless (res == GST_FLOW_OK);
fail_unless (transform_ip_1_called == TRUE);
fail_unless (transform_ip_1_writable == TRUE);
buffer = gst_test_trans_pop (trans);
fail_unless (buffer != NULL);
fail_unless (GST_BUFFER_SIZE (buffer) == 20);
gst_buffer_unref (buffer);
buffer = gst_buffer_new_and_alloc (20);
/* take additional ref to make it non-writable */
gst_buffer_ref (buffer);
fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 2);
transform_ip_1_called = FALSE;;
transform_ip_1_writable = FALSE;;
res = gst_test_trans_push (trans, buffer);
fail_unless (res == GST_FLOW_OK);
fail_unless (transform_ip_1_called == TRUE);
/* copy should have been taken */
fail_unless (transform_ip_1_writable == TRUE);
/* after push, get rid of the final ref we had */
gst_buffer_unref (buffer);
buffer = gst_test_trans_pop (trans);
fail_unless (buffer != NULL);
fail_unless (GST_BUFFER_SIZE (buffer) == 20);
/* output buffer has refcount 1 */
fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1);
gst_buffer_unref (buffer);
gst_test_trans_free (trans);
}
GST_END_TEST;
static gboolean set_caps_1_called;
static gboolean
set_caps_1 (GstBaseTransform * trans, GstCaps * incaps, GstCaps * outcaps)
{
GstCaps *caps;
GST_DEBUG_OBJECT (trans, "set_caps called");
set_caps_1_called = TRUE;
caps = gst_caps_new_simple ("foo/x-bar", NULL);
fail_unless (gst_caps_is_equal (incaps, caps));
fail_unless (gst_caps_is_equal (outcaps, caps));
gst_caps_unref (caps);
return TRUE;
}
/* basic in-place, check if the _ip function is called, buffer should be
* writable. we also set a setcaps function and see if it's called. */
GST_START_TEST (basetransform_chain_ip2)
{
TestTransData *trans;
GstBuffer *buffer;
GstFlowReturn res;
GstCaps *caps;
klass_transform_ip = transform_ip_1;
klass_set_caps = set_caps_1;
trans = gst_test_trans_new ();
caps = gst_caps_new_simple ("foo/x-bar", NULL);
/* first try to push a buffer without caps, this should fail */
buffer = gst_buffer_new_and_alloc (20);
transform_ip_1_called = FALSE;;
transform_ip_1_writable = FALSE;;
set_caps_1_called = FALSE;;
res = gst_test_trans_push (trans, buffer);
fail_unless (res == GST_FLOW_NOT_NEGOTIATED);
fail_unless (transform_ip_1_called == FALSE);
fail_unless (transform_ip_1_writable == FALSE);
fail_unless (set_caps_1_called == FALSE);
/* try to push a buffer with caps */
buffer = gst_buffer_new_and_alloc (20);
gst_buffer_set_caps (buffer, caps);
transform_ip_1_called = FALSE;
transform_ip_1_writable = FALSE;
set_caps_1_called = FALSE;;
res = gst_test_trans_push (trans, buffer);
fail_unless (res == GST_FLOW_OK);
fail_unless (transform_ip_1_called == TRUE);
fail_unless (transform_ip_1_writable == TRUE);
fail_unless (set_caps_1_called == TRUE);
buffer = gst_test_trans_pop (trans);
fail_unless (buffer != NULL);
fail_unless (GST_BUFFER_SIZE (buffer) == 20);
fail_unless (GST_BUFFER_CAPS (buffer) == caps);
gst_buffer_unref (buffer);
buffer = gst_buffer_new_and_alloc (20);
gst_buffer_set_caps (buffer, caps);
/* take additional ref to make it non-writable */
gst_buffer_ref (buffer);
fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 2);
transform_ip_1_called = FALSE;;
transform_ip_1_writable = FALSE;;
res = gst_test_trans_push (trans, buffer);
fail_unless (res == GST_FLOW_OK);
fail_unless (transform_ip_1_called == TRUE);
fail_unless (transform_ip_1_writable == TRUE);
/* after push, get rid of the final ref we had */
gst_buffer_unref (buffer);
buffer = gst_test_trans_pop (trans);
fail_unless (buffer != NULL);
fail_unless (GST_BUFFER_SIZE (buffer) == 20);
fail_unless (GST_BUFFER_CAPS (buffer) == caps);
/* output buffer has refcount 1 */
fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1);
gst_buffer_unref (buffer);
gst_caps_unref (caps);
trans->klass->transform_ip = NULL;
gst_test_trans_free (trans);
}
GST_END_TEST;
static Suite *
gst_basetransform_suite (void)
{
Suite *s = suite_create ("GstBaseTransform");
TCase *tc = tcase_create ("general");
suite_add_tcase (s, tc);
tcase_add_test (tc, basetransform_chain_pt1);
tcase_add_test (tc, basetransform_chain_pt2);
tcase_add_test (tc, basetransform_chain_ip1);
tcase_add_test (tc, basetransform_chain_ip2);
return s;
}
GST_CHECK_MAIN (gst_basetransform);