tests/check/: Add some test basetransform element and the beginnings of various unit...
authorWim Taymans <wim.taymans@gmail.com>
Fri, 20 Jun 2008 12:06:54 +0000 (12:06 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Fri, 20 Jun 2008 12:06:54 +0000 (12:06 +0000)
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.

ChangeLog
tests/check/Makefile.am
tests/check/libs/test_transform.c [new file with mode: 0644]
tests/check/libs/transform1.c [new file with mode: 0644]

index 82a13b8..cf54a6f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 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):
        Increase code readability.
        Don't try to compare buffer offsets when ther are invalid.
index 20ddeda..5904a9f 100644 (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
diff --git a/tests/check/libs/test_transform.c b/tests/check/libs/test_transform.c
new file mode 100644 (file)
index 0000000..ccb8d01
--- /dev/null
@@ -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;
+}
diff --git a/tests/check/libs/transform1.c b/tests/check/libs/transform1.c
new file mode 100644 (file)
index 0000000..592aa8c
--- /dev/null
@@ -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);