value: remove our FOURCC GType
[platform/upstream/gstreamer.git] / tests / check / gst / gstvalue.c
index 32992dc..11a5584 100644 (file)
@@ -31,12 +31,69 @@ GST_START_TEST (test_deserialize_buffer)
 
   g_value_init (&value, GST_TYPE_BUFFER);
   fail_unless (gst_value_deserialize (&value, "1234567890abcdef"));
-  buf = GST_BUFFER (gst_value_get_mini_object (&value));
+  /* does not increase the refcount */
+  buf = GST_BUFFER (g_value_get_boxed (&value));
+  ASSERT_MINI_OBJECT_REFCOUNT (buf, "buffer", 1);
+
+  /* does not increase the refcount */
+  buf = gst_value_get_buffer (&value);
+  ASSERT_MINI_OBJECT_REFCOUNT (buf, "buffer", 1);
+
+  /* cleanup */
+  g_value_unset (&value);
+}
+
+GST_END_TEST;
+
+/* create and serialize a buffer */
+GST_START_TEST (test_serialize_buffer)
+{
+  GValue value = { 0 };
+  GstBuffer *buf;
+  gchar *serialized;
+  static const char *buf_data = "1234567890abcdef";
+  gint len;
+  gpointer data;
+
+  len = strlen (buf_data);
+  buf = gst_buffer_new_and_alloc (len);
+
+  data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
+  memcpy (data, buf_data, len);
+  gst_buffer_unmap (buf, data, len);
+
+  ASSERT_MINI_OBJECT_REFCOUNT (buf, "buffer", 1);
 
+  /* and assign buffer to mini object */
+  g_value_init (&value, GST_TYPE_BUFFER);
+  gst_value_take_buffer (&value, buf);
+  ASSERT_MINI_OBJECT_REFCOUNT (buf, "buffer", 1);
+
+  /* now serialize it */
+  serialized = gst_value_serialize (&value);
+  GST_DEBUG ("serialized buffer to %s", serialized);
+  fail_unless (serialized != NULL);
+
+  /* refcount should not change */
   ASSERT_MINI_OBJECT_REFCOUNT (buf, "buffer", 1);
 
   /* cleanup */
-  gst_buffer_unref (buf);
+  g_free (serialized);
+  g_value_unset (&value);
+
+  /* take NULL buffer */
+  g_value_init (&value, GST_TYPE_BUFFER);
+  GST_DEBUG ("setting NULL buffer");
+  gst_value_take_buffer (&value, NULL);
+
+  /* now serialize it */
+  GST_DEBUG ("serializing NULL buffer");
+  serialized = gst_value_serialize (&value);
+  /* should return NULL */
+  fail_unless (serialized == NULL);
+
+  g_free (serialized);
+  g_value_unset (&value);
 }
 
 GST_END_TEST;
@@ -47,10 +104,14 @@ GST_START_TEST (test_deserialize_gint64)
   const char *strings[] = {
     "12345678901",
     "-12345678901",
+    "1152921504606846976",
+    "-1152921504606846976",
   };
   gint64 results[] = {
     12345678901LL,
     -12345678901LL,
+    1152921504606846976LL,
+    -1152921504606846976LL,
   };
   int i;
 
@@ -68,6 +129,86 @@ GST_START_TEST (test_deserialize_gint64)
 
 GST_END_TEST;
 
+GST_START_TEST (test_deserialize_guint64)
+{
+  GValue value = { 0 };
+  const char *strings[] = {
+    "0xffffffffffffffff",
+    "9223372036854775810",
+    "-9223372036854775810",
+    "-1",
+    "1",
+    "-0",
+  };
+  guint64 results[] = {
+    0xffffffffffffffffULL,
+    9223372036854775810ULL,
+    9223372036854775806ULL,
+    (guint64) - 1,
+    1,
+    0,
+  };
+  int i;
+
+  g_value_init (&value, G_TYPE_UINT64);
+
+  for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
+    fail_unless (gst_value_deserialize (&value, strings[i]),
+        "could not deserialize %s (%d)", strings[i], i);
+    fail_unless (g_value_get_uint64 (&value) == results[i],
+        "resulting value is %" G_GUINT64_FORMAT ", not %" G_GUINT64_FORMAT
+        ", for string %s (%d)", g_value_get_uint64 (&value),
+        results[i], strings[i], i);
+  }
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_deserialize_guchar)
+{
+  GValue value = { 0 };
+  const char *strings[] = {
+    "0xff",
+    "255",
+    "-1",
+    "1",
+    "-0",
+  };
+  guchar results[] = {
+    0xff,
+    255,
+    (guchar) - 1,
+    1,
+    0,
+  };
+  int i;
+
+  g_value_init (&value, G_TYPE_UCHAR);
+
+  for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
+    fail_unless (gst_value_deserialize (&value, strings[i]),
+        "could not deserialize %s (%d)", strings[i], i);
+    fail_unless (g_value_get_uchar (&value) == results[i],
+        "resulting value is %u not %u, for string %s (%d)",
+        g_value_get_uchar (&value), results[i], strings[i], i);
+  }
+
+  /* test serialisation as well while we're at it */
+  {
+    gchar *str;
+    GValue value = { 0 };
+    g_value_init (&value, G_TYPE_UCHAR);
+
+    g_value_set_uchar (&value, 255);
+    str = gst_value_serialize (&value);
+
+    fail_unless_equals_string (str, "255");
+    g_free (str);
+  }
+}
+
+GST_END_TEST;
+
 GST_START_TEST (test_deserialize_gstfraction)
 {
   GValue value = { 0 };
@@ -126,21 +267,21 @@ GST_START_TEST (test_deserialize_gint)
     "0xFFFFFFFFFFFFFFFF",
     "0xEFFFFFFF",
   };
+  /* some casts need to be explicit because of unsigned -> signed */
   gint results[] = {
     123456,
     -123456,
     0xFFFF,
     0xFFFF,
     0x7FFFFFFF,
-    0x80000000,
-    0x80000000,
-    0xFF000000,
+    (gint) 0x80000000,
+    (gint) 0x80000000,
+    (gint) 0xFF000000,
     -1,
-    0xFFFFFFFF,
+    (gint) 0xFFFFFFFF,
     -1,
-    /* cast needs to be explicit because of unsigned -> signed */
     (gint) 0xFFFFFFFFFFFFFFFFLL,
-    0xEFFFFFFF,
+    (gint) 0xEFFFFFFF,
   };
   int i;
 
@@ -209,7 +350,7 @@ GST_START_TEST (test_deserialize_guint)
   };
   guint results[] = {
     123456,
-    -123456,
+    (guint) - 123456,
     0xFFFF,
     0xFFFF,
     0x7FFFFFFF,
@@ -267,13 +408,78 @@ GST_START_TEST (test_deserialize_guint_failures)
 
 GST_END_TEST;
 
+GST_START_TEST (test_serialize_flags)
+{
+  GValue value = { 0 };
+  gchar *string;
+  GstSeekFlags flags[] = {
+    0,
+    GST_SEEK_FLAG_NONE,
+    GST_SEEK_FLAG_FLUSH,
+    GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE,
+  };
+  const char *results[] = {
+    "GST_SEEK_FLAG_NONE",
+    "GST_SEEK_FLAG_NONE",
+    "GST_SEEK_FLAG_FLUSH",
+    "GST_SEEK_FLAG_FLUSH+GST_SEEK_FLAG_ACCURATE",
+  };
+  int i;
+
+  g_value_init (&value, GST_TYPE_SEEK_FLAGS);
+
+  for (i = 0; i < G_N_ELEMENTS (flags); ++i) {
+    g_value_set_flags (&value, flags[i]);
+    string = gst_value_serialize (&value);
+    fail_if (string == NULL, "could not serialize flags %d", i);
+    fail_unless (strcmp (string, results[i]) == 0,
+        "resulting value is %s, not %s, for flags #%d", string, results[i], i);
+    g_free (string);
+  }
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_deserialize_flags)
+{
+  GValue value = { 0 };
+  const char *strings[] = {
+    "",
+    "0",
+    "GST_SEEK_FLAG_NONE",
+    "GST_SEEK_FLAG_FLUSH",
+    "GST_SEEK_FLAG_FLUSH+GST_SEEK_FLAG_ACCURATE",
+  };
+  GstSeekFlags results[] = {
+    GST_SEEK_FLAG_NONE,
+    GST_SEEK_FLAG_NONE,
+    GST_SEEK_FLAG_NONE,
+    GST_SEEK_FLAG_FLUSH,
+    GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE,
+  };
+  int i;
+
+  g_value_init (&value, GST_TYPE_SEEK_FLAGS);
+
+  for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
+    fail_unless (gst_value_deserialize (&value, strings[i]),
+        "could not deserialize %s (%d)", strings[i], i);
+    fail_unless (g_value_get_flags (&value) == results[i],
+        "resulting value is %d, not %d, for string %s (%d)",
+        g_value_get_flags (&value), results[i], strings[i], i);
+  }
+}
+
+GST_END_TEST;
 
 GST_START_TEST (test_string)
 {
-  gchar *try[] = {
+  const gchar *try[] = {
     "Dude",
     "Hi, I'm a string",
-    "tüüüt!"
+    "tüüüt!",
+    "\"\""                      /* Empty string */
   };
   gchar *tmp;
   GValue v = { 0, };
@@ -304,13 +510,14 @@ GST_START_TEST (test_deserialize_string)
 {
   struct
   {
-    gchar *from;
-    gchar *to;
+    const gchar *from;
+    const gchar *to;
   } tests[] = {
     {
     "", ""},                    /* empty strings */
     {
-    "\"\"", ""},                /* FAILURES */
+    "\"\"", ""},                /* quoted empty string -> empty string */
+        /* Expected FAILURES: */
     {
     "\"", NULL},                /* missing second quote */
     {
@@ -331,7 +538,6 @@ GST_START_TEST (test_deserialize_string)
   };
   guint i;
   GValue v = { 0, };
-  gboolean ret = TRUE;
 
   g_value_init (&v, G_TYPE_STRING);
   for (i = 0; i < G_N_ELEMENTS (tests); i++) {
@@ -342,7 +548,6 @@ GST_START_TEST (test_deserialize_string)
           "\nwanted: %s\ngot    : %s", tests[i].to, g_value_get_string (&v));
     } else {
       fail_if (tests[i].to != NULL, "failed, but wanted: %s", tests[i].to);
-      ret = FALSE;
     }
   }
   g_value_unset (&v);
@@ -354,6 +559,7 @@ GST_START_TEST (test_value_compare)
 {
   GValue value1 = { 0 };
   GValue value2 = { 0 };
+  GValue tmp = { 0 };
 
   g_value_init (&value1, G_TYPE_INT);
   g_value_set_int (&value1, 10);
@@ -382,15 +588,12 @@ GST_START_TEST (test_value_compare)
   fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_LESS_THAN);
   fail_unless (gst_value_compare (&value2, &value1) == GST_VALUE_GREATER_THAN);
   fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL);
-  g_value_unset (&value1);
-  g_value_unset (&value2);
-
-  g_value_init (&value1, GST_TYPE_FOURCC);
-  gst_value_set_fourcc (&value1, GST_MAKE_FOURCC ('a', 'b', 'c', 'd'));
-  g_value_init (&value2, GST_TYPE_FOURCC);
-  gst_value_set_fourcc (&value2, GST_MAKE_FOURCC ('1', '2', '3', '4'));
+  /* Test some NULL string comparisons */
+  g_value_set_string (&value2, NULL);
   fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_UNORDERED);
-  fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL);
+  fail_unless (gst_value_compare (&value2, &value1) == GST_VALUE_UNORDERED);
+  fail_unless (gst_value_compare (&value2, &value2) == GST_VALUE_EQUAL);
+
   g_value_unset (&value1);
   g_value_unset (&value2);
 
@@ -436,6 +639,104 @@ GST_START_TEST (test_value_compare)
   g_value_unset (&value1);
   g_value_unset (&value2);
 
+  /* Check that lists are equal regardless of order */
+  g_value_init (&value1, GST_TYPE_LIST);
+  g_value_init (&tmp, G_TYPE_INT);
+  g_value_set_int (&tmp, 1);
+  gst_value_list_append_value (&value1, &tmp);
+  g_value_set_int (&tmp, 2);
+  gst_value_list_append_value (&value1, &tmp);
+  g_value_set_int (&tmp, 3);
+  gst_value_list_append_value (&value1, &tmp);
+  g_value_set_int (&tmp, 4);
+  gst_value_list_append_value (&value1, &tmp);
+
+  g_value_init (&value2, GST_TYPE_LIST);
+  g_value_set_int (&tmp, 4);
+  gst_value_list_append_value (&value2, &tmp);
+  g_value_set_int (&tmp, 3);
+  gst_value_list_append_value (&value2, &tmp);
+  g_value_set_int (&tmp, 2);
+  gst_value_list_append_value (&value2, &tmp);
+  g_value_set_int (&tmp, 1);
+  gst_value_list_append_value (&value2, &tmp);
+
+  fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL,
+      "value lists with different order were not equal when they should be");
+  fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL,
+      "value lists with same order were not equal when they should be");
+  fail_unless (gst_value_compare (&value2, &value2) == GST_VALUE_EQUAL,
+      "value lists with same order were not equal when they should be");
+
+  /* Carry over the lists to this next check: */
+  /* Lists with different sizes are unequal */
+  g_value_set_int (&tmp, 1);
+  gst_value_list_append_value (&value2, &tmp);
+
+  fail_if (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL,
+      "Value lists with different size were equal when they shouldn't be");
+
+  /* Carry over the lists to this next check: */
+  /* Lists with same size but list1 contains one more element not in list2 */
+  g_value_set_int (&tmp, 5);
+  gst_value_list_append_value (&value1, &tmp);
+
+  fail_if (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL,
+      "Value lists with different elements were equal when they shouldn't be");
+  fail_if (gst_value_compare (&value2, &value1) == GST_VALUE_EQUAL,
+      "Value lists with different elements were equal when they shouldn't be");
+
+  g_value_unset (&value1);
+  g_value_unset (&value2);
+  g_value_unset (&tmp);
+
+  /* Arrays are only equal when in the same order */
+  g_value_init (&value1, GST_TYPE_ARRAY);
+  g_value_init (&tmp, G_TYPE_INT);
+  g_value_set_int (&tmp, 1);
+  gst_value_array_append_value (&value1, &tmp);
+  g_value_set_int (&tmp, 2);
+  gst_value_array_append_value (&value1, &tmp);
+  g_value_set_int (&tmp, 3);
+  gst_value_array_append_value (&value1, &tmp);
+  g_value_set_int (&tmp, 4);
+  gst_value_array_append_value (&value1, &tmp);
+
+  g_value_init (&value2, GST_TYPE_ARRAY);
+  g_value_set_int (&tmp, 4);
+  gst_value_array_append_value (&value2, &tmp);
+  g_value_set_int (&tmp, 3);
+  gst_value_array_append_value (&value2, &tmp);
+  g_value_set_int (&tmp, 2);
+  gst_value_array_append_value (&value2, &tmp);
+  g_value_set_int (&tmp, 1);
+  gst_value_array_append_value (&value2, &tmp);
+
+  fail_if (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL,
+      "Value arrays with different order were equal when they shouldn't be");
+  fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL,
+      "Identical value arrays were not equal when they should be");
+  fail_unless (gst_value_compare (&value2, &value2) == GST_VALUE_EQUAL,
+      "Identical value arrays were not equal when they should be");
+
+  /* Carry over the arrays to this next check: */
+  /* Arrays with different sizes are unequal */
+  g_value_unset (&value2);
+  g_value_init (&value2, GST_TYPE_ARRAY);
+  g_value_copy (&value1, &value2);
+
+  g_value_set_int (&tmp, 1);
+  gst_value_array_append_value (&value2, &tmp);
+
+  fail_if (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL,
+      "Value arrays with different size were equal when they shouldn't be");
+  /* order should not matter */
+  fail_if (gst_value_compare (&value2, &value1) == GST_VALUE_EQUAL,
+      "Value arrays with different size were equal when they shouldn't be");
+
+  g_value_unset (&value1);
+  g_value_unset (&value2);
+  g_value_unset (&tmp);
 }
 
 GST_END_TEST;
@@ -457,21 +758,23 @@ GST_START_TEST (test_value_intersect)
   g_value_unset (&src1);
   g_value_unset (&src2);
 
-  g_value_init (&src1, GST_TYPE_FOURCC);
-  gst_value_set_fourcc (&src1, GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'));
+  g_value_init (&src1, G_TYPE_STRING);
+  g_value_set_string (&src1, "YUY2");
   g_value_init (&src2, GST_TYPE_LIST);
-  g_value_init (&item, GST_TYPE_FOURCC);
-  gst_value_set_fourcc (&item, GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'));
+  g_value_init (&item, G_TYPE_STRING);
+  g_value_set_string (&item, "YUY2");
   gst_value_list_append_value (&src2, &item);
-  gst_value_set_fourcc (&item, GST_MAKE_FOURCC ('I', '4', '2', '0'));
+  g_value_set_string (&item, "I420");
   gst_value_list_append_value (&src2, &item);
-  gst_value_set_fourcc (&item, GST_MAKE_FOURCC ('A', 'B', 'C', 'D'));
+  g_value_set_string (&item, "ABCD");
   gst_value_list_append_value (&src2, &item);
 
   fail_unless (gst_value_intersect (&dest, &src1, &src2));
-  fail_unless (GST_VALUE_HOLDS_FOURCC (&dest));
-  fail_unless (gst_value_get_fourcc (&dest) ==
-      GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'));
+  fail_unless (G_VALUE_HOLDS_STRING (&dest));
+  fail_unless (g_str_equal (g_value_get_string (&dest), "YUY2"));
+
+  g_value_unset (&src1);
+  g_value_unset (&src2);
 }
 
 GST_END_TEST;
@@ -752,6 +1055,281 @@ GST_START_TEST (test_value_subtract_int)
 
 GST_END_TEST;
 
+GST_START_TEST (test_value_subtract_int64)
+{
+  GValue dest = { 0 };
+  GValue src1 = { 0 };
+  GValue src2 = { 0 };
+  const GValue *tmp;
+  gboolean ret;
+
+  /*  int64 <-> int64
+   */
+  g_value_init (&src1, G_TYPE_INT64);
+  g_value_set_int64 (&src1, 10);
+  g_value_init (&src2, G_TYPE_INT64);
+  g_value_set_int64 (&src2, 20);
+  /* subtract as in sets, result is 10 */
+  ret = gst_value_subtract (&dest, &src1, &src2);
+  fail_unless (ret == TRUE);
+  fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL);
+  g_value_unset (&dest);
+
+  /* same values, yields empty set */
+  ret = gst_value_subtract (&dest, &src1, &src1);
+  fail_unless (ret == FALSE);
+  g_value_unset (&src1);
+  g_value_unset (&src2);
+
+  /*  int64 <-> int64_range
+   */
+
+  /* would yield an empty set */
+  g_value_init (&src1, G_TYPE_INT64);
+  g_value_set_int64 (&src1, 10);
+  g_value_init (&src2, GST_TYPE_INT64_RANGE);
+  gst_value_set_int64_range (&src2, 0, 20);
+  ret = gst_value_subtract (&dest, &src1, &src2);
+  fail_unless (ret == FALSE);
+
+  /* and the other way around, should create a list of two ranges. */
+  ret = gst_value_subtract (&dest, &src2, &src1);
+  fail_unless (ret == TRUE);
+  fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE);
+  tmp = gst_value_list_get_value (&dest, 0);
+  fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE);
+  fail_unless (gst_value_get_int64_range_min (tmp) == 0);
+  fail_unless (gst_value_get_int64_range_max (tmp) == 9);
+  tmp = gst_value_list_get_value (&dest, 1);
+  fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE);
+  fail_unless (gst_value_get_int64_range_min (tmp) == 11);
+  fail_unless (gst_value_get_int64_range_max (tmp) == 20);
+  g_value_unset (&dest);
+  g_value_unset (&src1);
+  g_value_unset (&src2);
+
+  /* border case 1, empty set */
+  g_value_init (&src1, G_TYPE_INT64);
+  g_value_set_int64 (&src1, 10);
+  g_value_init (&src2, GST_TYPE_INT64_RANGE);
+  gst_value_set_int64_range (&src2, 10, 20);
+  ret = gst_value_subtract (&dest, &src1, &src2);
+  fail_unless (ret == FALSE);
+
+  /* and the other way around, should create a new range. */
+  ret = gst_value_subtract (&dest, &src2, &src1);
+  fail_unless (ret == TRUE);
+  fail_unless (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE);
+  fail_unless (gst_value_get_int64_range_min (&dest) == 11);
+  fail_unless (gst_value_get_int64_range_max (&dest) == 20);
+  g_value_unset (&dest);
+  g_value_unset (&src1);
+  g_value_unset (&src2);
+
+  /* border case 2, empty set */
+  g_value_init (&src1, G_TYPE_INT64);
+  g_value_set_int64 (&src1, 20);
+  g_value_init (&src2, GST_TYPE_INT64_RANGE);
+  gst_value_set_int64_range (&src2, 10, 20);
+  ret = gst_value_subtract (&dest, &src1, &src2);
+  fail_unless (ret == FALSE);
+
+  /* and the other way around, should create a new range. */
+  ret = gst_value_subtract (&dest, &src2, &src1);
+  fail_unless (ret == TRUE);
+  fail_unless (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE);
+  fail_unless (gst_value_get_int64_range_min (&dest) == 10);
+  fail_unless (gst_value_get_int64_range_max (&dest) == 19);
+  g_value_unset (&dest);
+  g_value_unset (&src1);
+  g_value_unset (&src2);
+
+  /* case 3, valid set */
+  g_value_init (&src1, G_TYPE_INT64);
+  g_value_set_int64 (&src1, 0);
+  g_value_init (&src2, GST_TYPE_INT64_RANGE);
+  gst_value_set_int64_range (&src2, 10, 20);
+  ret = gst_value_subtract (&dest, &src1, &src2);
+  fail_unless (ret == TRUE);
+  fail_unless (G_VALUE_HOLDS_INT64 (&dest) == TRUE);
+  fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL);
+  g_value_unset (&dest);
+
+  /* and the other way around, should keep the range. */
+  ret = gst_value_subtract (&dest, &src2, &src1);
+  fail_unless (ret == TRUE);
+  fail_unless (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE);
+  fail_unless (gst_value_get_int64_range_min (&dest) == 10);
+  fail_unless (gst_value_get_int64_range_max (&dest) == 20);
+  g_value_unset (&dest);
+  g_value_unset (&src1);
+  g_value_unset (&src2);
+
+  /*  int64_range <-> int64_range
+   */
+
+  /* same range, empty set */
+  g_value_init (&src1, GST_TYPE_INT64_RANGE);
+  gst_value_set_int64_range (&src1, 10, 20);
+  g_value_init (&src2, GST_TYPE_INT64_RANGE);
+  gst_value_set_int64_range (&src2, 10, 20);
+  ret = gst_value_subtract (&dest, &src1, &src2);
+  fail_unless (ret == FALSE);
+  ret = gst_value_subtract (&dest, &src2, &src1);
+  fail_unless (ret == FALSE);
+  g_value_unset (&src1);
+  g_value_unset (&src2);
+
+  /* non overlapping ranges */
+  g_value_init (&src1, GST_TYPE_INT64_RANGE);
+  gst_value_set_int64_range (&src1, 10, 20);
+  g_value_init (&src2, GST_TYPE_INT64_RANGE);
+  gst_value_set_int64_range (&src2, 30, 40);
+  ret = gst_value_subtract (&dest, &src1, &src2);
+  fail_unless (ret == TRUE);
+  fail_unless (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE);
+  fail_unless (gst_value_get_int64_range_min (&dest) == 10);
+  fail_unless (gst_value_get_int64_range_max (&dest) == 20);
+  g_value_unset (&dest);
+  /* the other way */
+  ret = gst_value_subtract (&dest, &src2, &src1);
+  fail_unless (ret == TRUE);
+  fail_unless (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE);
+  fail_unless (gst_value_get_int64_range_min (&dest) == 30);
+  fail_unless (gst_value_get_int64_range_max (&dest) == 40);
+  g_value_unset (&dest);
+  g_value_unset (&src1);
+  g_value_unset (&src2);
+
+  /* completely overlapping ranges */
+  g_value_init (&src1, GST_TYPE_INT64_RANGE);
+  gst_value_set_int64_range (&src1, 10, 20);
+  g_value_init (&src2, GST_TYPE_INT64_RANGE);
+  gst_value_set_int64_range (&src2, 10, 30);
+  ret = gst_value_subtract (&dest, &src1, &src2);
+  fail_unless (ret == FALSE);
+  /* the other way */
+  ret = gst_value_subtract (&dest, &src2, &src1);
+  fail_unless (ret == TRUE);
+  fail_unless (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE);
+  fail_unless (gst_value_get_int64_range_min (&dest) == 21);
+  fail_unless (gst_value_get_int64_range_max (&dest) == 30);
+  g_value_unset (&dest);
+  g_value_unset (&src1);
+  g_value_unset (&src2);
+
+  /* partially overlapping ranges */
+  g_value_init (&src1, GST_TYPE_INT64_RANGE);
+  gst_value_set_int64_range (&src1, 10, 20);
+  g_value_init (&src2, GST_TYPE_INT64_RANGE);
+  gst_value_set_int64_range (&src2, 15, 30);
+  ret = gst_value_subtract (&dest, &src1, &src2);
+  fail_unless (ret == TRUE);
+  fail_unless (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE);
+  fail_unless (gst_value_get_int64_range_min (&dest) == 10);
+  fail_unless (gst_value_get_int64_range_max (&dest) == 14);
+  g_value_unset (&dest);
+  /* the other way */
+  ret = gst_value_subtract (&dest, &src2, &src1);
+  fail_unless (ret == TRUE);
+  fail_unless (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE);
+  fail_unless (gst_value_get_int64_range_min (&dest) == 21);
+  fail_unless (gst_value_get_int64_range_max (&dest) == 30);
+  g_value_unset (&dest);
+  g_value_unset (&src1);
+  g_value_unset (&src2);
+
+  /* create a hole { int64_range, int64_range } */
+  g_value_init (&src1, GST_TYPE_INT64_RANGE);
+  gst_value_set_int64_range (&src1, 10, 30);
+  g_value_init (&src2, GST_TYPE_INT64_RANGE);
+  gst_value_set_int64_range (&src2, 15, 20);
+  ret = gst_value_subtract (&dest, &src1, &src2);
+  fail_unless (ret == TRUE);
+  fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE);
+  tmp = gst_value_list_get_value (&dest, 0);
+  fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE);
+  fail_unless (gst_value_get_int64_range_min (tmp) == 10);
+  fail_unless (gst_value_get_int64_range_max (tmp) == 14);
+  tmp = gst_value_list_get_value (&dest, 1);
+  fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE);
+  fail_unless (gst_value_get_int64_range_min (tmp) == 21);
+  fail_unless (gst_value_get_int64_range_max (tmp) == 30);
+  g_value_unset (&dest);
+  /* the other way */
+  ret = gst_value_subtract (&dest, &src2, &src1);
+  fail_unless (ret == FALSE);
+  g_value_unset (&src1);
+  g_value_unset (&src2);
+
+  /* create a hole, { int64, int64 } */
+  g_value_init (&src1, GST_TYPE_INT64_RANGE);
+  gst_value_set_int64_range (&src1, 10, 30);
+  g_value_init (&src2, GST_TYPE_INT64_RANGE);
+  gst_value_set_int64_range (&src2, 11, 29);
+  ret = gst_value_subtract (&dest, &src1, &src2);
+  fail_unless (ret == TRUE);
+  fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE);
+  tmp = gst_value_list_get_value (&dest, 0);
+  fail_unless (G_VALUE_HOLDS_INT64 (tmp) == TRUE);
+  fail_unless (g_value_get_int64 (tmp) == 10);
+  tmp = gst_value_list_get_value (&dest, 1);
+  fail_unless (G_VALUE_HOLDS_INT64 (tmp) == TRUE);
+  fail_unless (g_value_get_int64 (tmp) == 30);
+  g_value_unset (&dest);
+  /* the other way */
+  ret = gst_value_subtract (&dest, &src2, &src1);
+  fail_unless (ret == FALSE);
+  g_value_unset (&src1);
+  g_value_unset (&src2);
+
+  /* create a hole, { int64, int64_range } */
+  g_value_init (&src1, GST_TYPE_INT64_RANGE);
+  gst_value_set_int64_range (&src1, 10, 30);
+  g_value_init (&src2, GST_TYPE_INT64_RANGE);
+  gst_value_set_int64_range (&src2, 11, 28);
+  ret = gst_value_subtract (&dest, &src1, &src2);
+  fail_unless (ret == TRUE);
+  fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE);
+  tmp = gst_value_list_get_value (&dest, 0);
+  fail_unless (G_VALUE_HOLDS_INT64 (tmp) == TRUE);
+  fail_unless (g_value_get_int64 (tmp) == 10);
+  tmp = gst_value_list_get_value (&dest, 1);
+  fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE);
+  fail_unless (gst_value_get_int64_range_min (tmp) == 29);
+  fail_unless (gst_value_get_int64_range_max (tmp) == 30);
+  g_value_unset (&dest);
+  /* the other way */
+  ret = gst_value_subtract (&dest, &src2, &src1);
+  fail_unless (ret == FALSE);
+  g_value_unset (&src1);
+  g_value_unset (&src2);
+
+  /* create a hole, { int64_range, int64 } */
+  g_value_init (&src1, GST_TYPE_INT64_RANGE);
+  gst_value_set_int64_range (&src1, 10, 30);
+  g_value_init (&src2, GST_TYPE_INT64_RANGE);
+  gst_value_set_int64_range (&src2, 12, 29);
+  ret = gst_value_subtract (&dest, &src1, &src2);
+  fail_unless (ret == TRUE);
+  fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE);
+  tmp = gst_value_list_get_value (&dest, 0);
+  fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE);
+  fail_unless (gst_value_get_int64_range_min (tmp) == 10);
+  fail_unless (gst_value_get_int64_range_max (tmp) == 11);
+  tmp = gst_value_list_get_value (&dest, 1);
+  fail_unless (G_VALUE_HOLDS_INT64 (tmp) == TRUE);
+  fail_unless (g_value_get_int64 (tmp) == 30);
+  g_value_unset (&dest);
+  /* the other way */
+  ret = gst_value_subtract (&dest, &src2, &src1);
+  fail_unless (ret == FALSE);
+  g_value_unset (&src1);
+  g_value_unset (&src2);
+}
+
+GST_END_TEST;
+
 GST_START_TEST (test_value_subtract_double)
 {
   GValue dest = { 0 };
@@ -1249,6 +1827,54 @@ GST_START_TEST (test_value_subtract_fraction_range)
 
 GST_END_TEST;
 
+/* Test set subtraction operations on fraction lists */
+GST_START_TEST (test_value_subtract_fraction_list)
+{
+  GValue list1 = { 0 };
+  GValue list2 = { 0 };
+  GValue val1 = { 0 };
+  GValue val2 = { 0 };
+  GValue tmp = { 0 };
+  gboolean ret;
+
+  g_value_init (&list1, GST_TYPE_LIST);
+  g_value_init (&val1, GST_TYPE_FRACTION);
+  gst_value_set_fraction (&val1, 15, 2);
+  gst_value_list_append_value (&list1, &val1);
+  g_value_init (&tmp, GST_TYPE_FRACTION);
+  gst_value_set_fraction (&tmp, 5, 1);
+  gst_value_list_append_value (&list1, &tmp);
+  g_value_unset (&tmp);
+
+  g_value_init (&list2, GST_TYPE_LIST);
+  g_value_init (&val2, GST_TYPE_FRACTION);
+  gst_value_set_fraction (&val2, 15, 1);
+  gst_value_list_append_value (&list2, &val2);
+  g_value_init (&tmp, GST_TYPE_FRACTION);
+  gst_value_set_fraction (&tmp, 5, 1);
+  gst_value_list_append_value (&list2, &tmp);
+  g_value_unset (&tmp);
+
+  /* should subtract all common elements */
+  ret = gst_value_subtract (&tmp, &list1, &list2);
+  fail_unless (ret == TRUE);
+  fail_unless (gst_value_compare (&tmp, &val1) == GST_VALUE_EQUAL);
+  g_value_unset (&val1);
+  g_value_unset (&tmp);
+
+  ret = gst_value_subtract (&tmp, &list2, &list1);
+  fail_unless (ret == TRUE);
+  fail_unless (gst_value_compare (&tmp, &val2) == GST_VALUE_EQUAL);
+  g_value_unset (&val2);
+  g_value_unset (&tmp);
+
+  g_value_unset (&list1);
+  g_value_unset (&list2);
+}
+
+GST_END_TEST;
+
+
 GST_START_TEST (test_date)
 {
   GstStructure *s;
@@ -1277,7 +1903,7 @@ GST_START_TEST (test_date)
   s = NULL;
 
   fail_unless (g_str_equal (str,
-          "media/x-type, SOME_DATE_TAG=(GstDate)2005-09-22"));
+          "media/x-type, SOME_DATE_TAG=(date)2005-09-22;"));
 
   s = gst_structure_from_string (str, NULL);
   g_free (str);
@@ -1301,9 +1927,208 @@ GST_START_TEST (test_date)
   s = NULL;
 
   fail_unless (g_str_equal (str,
-          "media/x-type, SOME_DATE_TAG=(GstDate)2005-09-22"));
+          "media/x-type, SOME_DATE_TAG=(date)2005-09-22;"));
+  g_free (str);
+  str = NULL;
+}
+
+GST_END_TEST;
+
+static gboolean
+date_time_equal (GstDateTime * a, GstDateTime * b)
+{
+  if (gst_date_time_get_year (a) != gst_date_time_get_year (b) ||
+      gst_date_time_get_month (a) != gst_date_time_get_month (b) ||
+      gst_date_time_get_day (a) != gst_date_time_get_day (b))
+    return FALSE;
+
+  if (gst_date_time_get_hour (a) != gst_date_time_get_hour (b) ||
+      gst_date_time_get_minute (a) != gst_date_time_get_minute (b) ||
+      gst_date_time_get_second (a) != gst_date_time_get_second (b) ||
+      gst_date_time_get_microsecond (a) != gst_date_time_get_microsecond (b))
+    return FALSE;
+
+  if (gst_date_time_get_time_zone_offset (a) !=
+      gst_date_time_get_time_zone_offset (b))
+    return FALSE;
+
+  return TRUE;
+}
+
+GST_START_TEST (test_date_time)
+{
+  GstStructure *s;
+  GstDateTime *datetime, *datetime2;
+  gchar *str;
+
+  /* utc timezone */
+  datetime = gst_date_time_new (0, 2010, 6, 23, 7, 40, 10);
+
+  s = gst_structure_new ("media/x-type", "SOME_DATE_TIME_TAG",
+      GST_TYPE_DATE_TIME, datetime, NULL);
+
+  fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TIME_TAG",
+          GST_TYPE_DATE_TIME));
+  fail_unless (gst_structure_get_date_time (s, "SOME_DATE_TIME_TAG",
+          &datetime2));
+  fail_unless (datetime2 != NULL);
+  fail_unless (date_time_equal (datetime, datetime2));
+
+  gst_date_time_unref (datetime);
+  gst_date_time_unref (datetime2);
+  datetime = NULL;
+  datetime2 = NULL;
+
+  str = gst_structure_to_string (s);
+  gst_structure_free (s);
+  s = NULL;
+
+  fail_unless (g_str_equal (str,
+          "media/x-type, SOME_DATE_TIME_TAG=(datetime)\"2010-06-23T07:40:10.000000+0000\";"));
+
+  s = gst_structure_from_string (str, NULL);
+  g_free (str);
+  str = NULL;
+
+  fail_unless (s != NULL);
+  fail_unless (gst_structure_has_name (s, "media/x-type"));
+  fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TIME_TAG",
+          GST_TYPE_DATE_TIME));
+  fail_unless (gst_structure_get_date_time (s, "SOME_DATE_TIME_TAG",
+          &datetime));
+  fail_unless (datetime != NULL);
+  fail_unless (gst_date_time_get_year (datetime) == 2010);
+  fail_unless (gst_date_time_get_month (datetime) == 6);
+  fail_unless (gst_date_time_get_day (datetime) == 23);
+  fail_unless (gst_date_time_get_hour (datetime) == 7);
+  fail_unless (gst_date_time_get_minute (datetime) == 40);
+  fail_unless (gst_date_time_get_second (datetime) == 10);
+  fail_unless (gst_date_time_get_microsecond (datetime) == 0);
+  fail_unless (gst_date_time_get_time_zone_offset (datetime) == 0);
+  gst_date_time_unref (datetime);
+  datetime = NULL;
+
+  str = gst_structure_to_string (s);
+  gst_structure_free (s);
+  s = NULL;
+
+  fail_unless (g_str_equal (str,
+          "media/x-type, SOME_DATE_TIME_TAG=(datetime)\"2010-06-23T07:40:10.000000+0000\";"));
+  g_free (str);
+  str = NULL;
+
+  /* with timezone */
+  datetime = gst_date_time_new (-3.0, 2010, 6, 23, 7, 40, 10.000001);
+
+  s = gst_structure_new ("media/x-type", "SOME_DATE_TIME_TAG",
+      GST_TYPE_DATE_TIME, datetime, NULL);
+
+  fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TIME_TAG",
+          GST_TYPE_DATE_TIME));
+  fail_unless (gst_structure_get_date_time (s, "SOME_DATE_TIME_TAG",
+          &datetime2));
+  fail_unless (datetime2 != NULL);
+  fail_unless (date_time_equal (datetime, datetime2));
+
+  gst_date_time_unref (datetime);
+  gst_date_time_unref (datetime2);
+  datetime = NULL;
+  datetime2 = NULL;
+
+  str = gst_structure_to_string (s);
+  gst_structure_free (s);
+  s = NULL;
+
+  fail_unless (g_str_equal (str,
+          "media/x-type, SOME_DATE_TIME_TAG=(datetime)\"2010-06-23T07:40:10.000001-0300\";"));
+
+  s = gst_structure_from_string (str, NULL);
   g_free (str);
   str = NULL;
+
+  fail_unless (s != NULL);
+  fail_unless (gst_structure_has_name (s, "media/x-type"));
+  fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TIME_TAG",
+          GST_TYPE_DATE_TIME));
+  fail_unless (gst_structure_get_date_time (s, "SOME_DATE_TIME_TAG",
+          &datetime));
+  fail_unless (datetime != NULL);
+  fail_unless (gst_date_time_get_year (datetime) == 2010);
+  fail_unless (gst_date_time_get_month (datetime) == 6);
+  fail_unless (gst_date_time_get_day (datetime) == 23);
+  fail_unless (gst_date_time_get_hour (datetime) == 7);
+  fail_unless (gst_date_time_get_minute (datetime) == 40);
+  fail_unless (gst_date_time_get_second (datetime) == 10);
+  fail_unless (gst_date_time_get_microsecond (datetime) == 1);
+  fail_unless (gst_date_time_get_time_zone_offset (datetime) == -3);
+  gst_date_time_unref (datetime);
+  datetime = NULL;
+
+  str = gst_structure_to_string (s);
+  gst_structure_free (s);
+  s = NULL;
+  fail_unless (g_str_equal (str,
+          "media/x-type, SOME_DATE_TIME_TAG=(datetime)\"2010-06-23T07:40:10.000001-0300\";"));
+
+  g_free (str);
+  str = NULL;
+
+  /* with positive timezone */
+  datetime = gst_date_time_new (2.0, 2010, 6, 23, 7, 40, 10.000001);
+
+  s = gst_structure_new ("media/x-type", "SOME_DATE_TIME_TAG",
+      GST_TYPE_DATE_TIME, datetime, NULL);
+
+  fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TIME_TAG",
+          GST_TYPE_DATE_TIME));
+  fail_unless (gst_structure_get_date_time (s, "SOME_DATE_TIME_TAG",
+          &datetime2));
+  fail_unless (datetime2 != NULL);
+  fail_unless (date_time_equal (datetime, datetime2));
+
+  gst_date_time_unref (datetime);
+  gst_date_time_unref (datetime2);
+  datetime = NULL;
+  datetime2 = NULL;
+
+  str = gst_structure_to_string (s);
+  gst_structure_free (s);
+  s = NULL;
+
+  fail_unless (g_str_equal (str,
+          "media/x-type, SOME_DATE_TIME_TAG=(datetime)\"2010-06-23T07:40:10.000001+0200\";"));
+
+  s = gst_structure_from_string (str, NULL);
+  g_free (str);
+  str = NULL;
+
+  fail_unless (s != NULL);
+  fail_unless (gst_structure_has_name (s, "media/x-type"));
+  fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TIME_TAG",
+          GST_TYPE_DATE_TIME));
+  fail_unless (gst_structure_get_date_time (s, "SOME_DATE_TIME_TAG",
+          &datetime));
+  fail_unless (datetime != NULL);
+  fail_unless (gst_date_time_get_year (datetime) == 2010);
+  fail_unless (gst_date_time_get_month (datetime) == 6);
+  fail_unless (gst_date_time_get_day (datetime) == 23);
+  fail_unless (gst_date_time_get_hour (datetime) == 7);
+  fail_unless (gst_date_time_get_minute (datetime) == 40);
+  fail_unless (gst_date_time_get_second (datetime) == 10);
+  fail_unless (gst_date_time_get_microsecond (datetime) == 1);
+  fail_unless (gst_date_time_get_time_zone_offset (datetime) == 2);
+  gst_date_time_unref (datetime);
+  datetime = NULL;
+
+  str = gst_structure_to_string (s);
+  gst_structure_free (s);
+  s = NULL;
+  fail_unless (g_str_equal (str,
+          "media/x-type, SOME_DATE_TIME_TAG=(datetime)\"2010-06-23T07:40:10.000001+0200\";"));
+
+  g_free (str);
+  str = NULL;
+
 }
 
 GST_END_TEST;
@@ -1311,10 +2136,10 @@ GST_END_TEST;
 GST_START_TEST (test_fraction_range)
 {
   GValue range = { 0, };
-  GValue start = { 0, }, end = {
-  0,};
-  GValue src = { 0, }, dest = {
-  0,};
+  GValue start = { 0, };
+  GValue end = { 0, };
+  GValue src = { 0, };
+  GValue dest = { 0, };
   GValue range2 = { 0, };
 
   g_value_init (&range, GST_TYPE_FRACTION_RANGE);
@@ -1361,7 +2186,321 @@ GST_START_TEST (test_fraction_range)
 
 GST_END_TEST;
 
-Suite *
+GST_START_TEST (test_serialize_deserialize_format_enum)
+{
+  GstStructure *s, *s2;
+  GstFormat foobar_fmt;
+  gchar *str, *str2, *end = NULL;
+
+  /* make sure custom formats are serialised properly as well */
+  foobar_fmt = gst_format_register ("foobar", "GST_FORMAT_FOOBAR");
+  fail_unless (foobar_fmt != GST_FORMAT_UNDEFINED);
+
+  s = gst_structure_new ("foo/bar", "format1", GST_TYPE_FORMAT,
+      GST_FORMAT_BYTES, "format2", GST_TYPE_FORMAT, GST_FORMAT_TIME,
+      "format3", GST_TYPE_FORMAT, GST_FORMAT_DEFAULT, "format4",
+      GST_TYPE_FORMAT, foobar_fmt, NULL);
+
+  str = gst_structure_to_string (s);
+  GST_LOG ("Got structure string '%s'", GST_STR_NULL (str));
+  fail_unless (str != NULL);
+  fail_unless (strstr (str, "TIME") != NULL);
+  fail_unless (strstr (str, "BYTE") != NULL);
+  fail_unless (strstr (str, "DEFAULT") != NULL);
+  fail_unless (strstr (str, "FOOBAR") != NULL);
+
+  s2 = gst_structure_from_string (str, &end);
+  fail_unless (s2 != NULL);
+
+  str2 = gst_structure_to_string (s2);
+  fail_unless (str2 != NULL);
+
+  fail_unless (g_str_equal (str, str2));
+
+  g_free (str);
+  g_free (str2);
+  gst_structure_free (s);
+  gst_structure_free (s2);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_serialize_deserialize_caps)
+{
+  GValue value = { 0 }
+  , value2 = {
+  0};
+  GstCaps *caps, *caps2;
+  gchar *serialized;
+
+  caps = gst_caps_new_simple ("test/caps",
+      "foo", G_TYPE_INT, 10, "bar", G_TYPE_STRING, "test", NULL);
+  fail_if (GST_CAPS_REFCOUNT_VALUE (caps) != 1);
+
+  /* and assign caps to gvalue */
+  g_value_init (&value, GST_TYPE_CAPS);
+  g_value_take_boxed (&value, caps);
+  fail_if (GST_CAPS_REFCOUNT_VALUE (caps) != 1);
+
+  /* now serialize it */
+  serialized = gst_value_serialize (&value);
+  GST_DEBUG ("serialized caps to %s", serialized);
+  fail_unless (serialized != NULL);
+
+  /* refcount should not change */
+  fail_if (GST_CAPS_REFCOUNT_VALUE (caps) != 1);
+
+  /* now deserialize again */
+  g_value_init (&value2, GST_TYPE_CAPS);
+  gst_value_deserialize (&value2, serialized);
+
+  caps2 = g_value_get_boxed (&value2);
+  fail_if (GST_CAPS_REFCOUNT_VALUE (caps2) != 1);
+
+  /* they should be equal */
+  fail_unless (gst_caps_is_equal (caps, caps2));
+
+  /* cleanup */
+  g_value_unset (&value);
+  g_value_unset (&value2);
+  g_free (serialized);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_int_range)
+{
+  GValue range = { 0, };
+  GValue start = { 0, };
+  GValue end = { 0, };
+  GValue src = { 0, };
+  GValue dest = { 0, };
+  GValue range2 = { 0, };
+
+  g_value_init (&range, GST_TYPE_INT_RANGE);
+  g_value_init (&range2, GST_TYPE_INT_RANGE);
+  g_value_init (&start, G_TYPE_INT);
+  g_value_init (&end, G_TYPE_INT);
+  g_value_init (&src, G_TYPE_INT);
+
+  g_value_set_int (&src, 2);
+
+  /* Check that a intersection of int & range = int */
+  gst_value_set_int_range (&range, 1, 5);
+
+  fail_unless (gst_value_intersect (&dest, &src, &range) == TRUE);
+  fail_unless (G_VALUE_TYPE (&dest) == G_TYPE_INT);
+  fail_unless (gst_value_compare (&dest, &src) == GST_VALUE_EQUAL);
+
+  /* Check that a intersection selects the overlapping range */
+  gst_value_set_int_range (&range2, 2, 3);
+  g_value_unset (&dest);
+  fail_unless (gst_value_intersect (&dest, &range, &range2) == TRUE);
+  fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT_RANGE);
+
+  fail_unless (gst_value_compare (&dest, &range2) == GST_VALUE_EQUAL);
+
+  /* Check that non intersection ranges don't intersect */
+  gst_value_set_int_range (&range2, 6, 7);
+  g_value_unset (&dest);
+  fail_unless (gst_value_intersect (&dest, &range, &range2) == FALSE);
+
+  g_value_unset (&start);
+  g_value_unset (&end);
+  g_value_unset (&range);
+  g_value_unset (&range2);
+  g_value_unset (&src);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_int64_range)
+{
+  GValue range = { 0, };
+  GValue start = { 0, };
+  GValue end = { 0, };
+  GValue src = { 0, };
+  GValue dest = { 0, };
+  GValue range2 = { 0, };
+
+  g_value_init (&range, GST_TYPE_INT64_RANGE);
+  g_value_init (&range2, GST_TYPE_INT64_RANGE);
+  g_value_init (&start, G_TYPE_INT64);
+  g_value_init (&end, G_TYPE_INT64);
+  g_value_init (&src, G_TYPE_INT64);
+
+  g_value_set_int64 (&src, 2);
+
+  /* Check that a intersection of int64 & range = int64 */
+  gst_value_set_int64_range (&range, 1, 5);
+
+  fail_unless (gst_value_intersect (&dest, &src, &range) == TRUE);
+  fail_unless (G_VALUE_TYPE (&dest) == G_TYPE_INT64);
+  fail_unless (gst_value_compare (&dest, &src) == GST_VALUE_EQUAL);
+
+  /* Check that a intersection selects the overlapping range */
+  gst_value_set_int64_range (&range2, 2, 3);
+  g_value_unset (&dest);
+  fail_unless (gst_value_intersect (&dest, &range, &range2) == TRUE);
+  fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT64_RANGE);
+
+  fail_unless (gst_value_compare (&dest, &range2) == GST_VALUE_EQUAL);
+
+  /* Check that non intersection ranges don't intersect */
+  gst_value_set_int64_range (&range2, 6, 7);
+  g_value_unset (&dest);
+  fail_unless (gst_value_intersect (&dest, &range, &range2) == FALSE);
+
+  g_value_unset (&start);
+  g_value_unset (&end);
+  g_value_unset (&range);
+  g_value_unset (&range2);
+  g_value_unset (&src);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_serialize_int64_range)
+{
+  int i = 0;
+
+  gint64 int64_ranges[] = {
+    0, 5,
+    0, G_MAXINT,
+    5, G_MAXINT32,
+    5, G_MAXINT64,
+  };
+  gint int64_ranges_size = sizeof (int64_ranges) / sizeof (int64_ranges[0]) / 2;
+
+  gchar *int64_range_strings[] = {
+    g_strdup ("[ 0, 5 ]"),
+    g_strdup_printf ("[ 0, %" G_GINT64_FORMAT " ]", (gint64) G_MAXINT),
+    g_strdup_printf ("[ 5, %" G_GINT64_FORMAT " ]", (gint64) G_MAXINT32),
+    g_strdup_printf ("[ 5, %" G_GINT64_FORMAT " ]", G_MAXINT64),
+  };
+  gint int64_range_strings_size =
+      sizeof (int64_range_strings) / sizeof (int64_range_strings[0]);
+
+  fail_unless (int64_ranges_size == int64_range_strings_size);
+
+  while (i + 1 < (int64_ranges_size * 2)) {
+    if ((i + 1) % 2) {
+      gchar *str;
+      gchar *str2;
+      GValue value = { 0 };
+      const GValue *deserialized_value;
+      int idx = i / 2;
+      GstStructure *s;
+
+      g_value_init (&value, GST_TYPE_INT64_RANGE);
+
+      /* check serialization */
+      gst_value_set_int64_range (&value, int64_ranges[i], int64_ranges[i + 1]);
+      str = gst_value_serialize (&value);
+      fail_unless (strcmp (str, int64_range_strings[idx]) == 0);
+      g_free (int64_range_strings[idx]);
+
+      /* now deserialize again to an int64 range */
+      s = gst_structure_new ("foo/bar", "range", GST_TYPE_INT64_RANGE,
+          int64_ranges[i], int64_ranges[i + 1], NULL);
+      deserialized_value = gst_structure_get_value (s, "range");
+      fail_unless (GST_VALUE_HOLDS_INT64_RANGE (deserialized_value) == TRUE);
+      str2 = gst_value_serialize (deserialized_value);
+
+      fail_unless (gst_value_get_int64_range_min (deserialized_value) ==
+          int64_ranges[i]);
+      fail_unless (gst_value_get_int64_range_max (deserialized_value) ==
+          int64_ranges[i + 1]);
+
+      gst_structure_free (s);
+      g_free (str);
+      g_free (str2);
+    }
+    i++;
+  }
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_deserialize_int_range)
+{
+  GstStructure *s;
+  gchar *str, *str2;
+  gchar *end = NULL;
+  const GValue *deserialized_value;
+
+  /* check a valid int_range deserialization */
+  str = g_strdup_printf ("foo/bar, range=[ 1, %d ];", G_MAXINT);
+  s = gst_structure_from_string (str, &end);
+  fail_unless (*end == '\0');
+  deserialized_value = gst_structure_get_value (s, "range");
+  fail_unless (GST_VALUE_HOLDS_INT_RANGE (deserialized_value) == TRUE);
+  fail_unless (gst_value_get_int_range_min (deserialized_value) == 1);
+  fail_unless (gst_value_get_int_range_max (deserialized_value) == G_MAXINT);
+  gst_structure_free (s);
+  end = NULL;
+  g_free (str);
+
+  /* check invalid int_range deserialization */
+  str =
+      g_strdup_printf ("foo/bar, range=[ 1, %" G_GINT64_FORMAT " ];",
+      (gint64) G_MAXINT + 1);
+  ASSERT_CRITICAL (s = gst_structure_from_string (str, &end));
+  g_free (str);
+  gst_structure_free (s);
+  str =
+      g_strdup_printf ("foo/bar, range=[ %" G_GINT64_FORMAT ", %"
+      G_GINT64_FORMAT " ];", (gint64) G_MAXINT, (gint64) G_MAXINT + 1);
+  ASSERT_CRITICAL (s = gst_structure_from_string (str, NULL));
+  end = NULL;
+  g_free (str);
+  gst_structure_free (s);
+
+  /* check a valid int64_range deserialization. Those ranges need to
+   * be explicit about their storage type. */
+  str = g_strdup_printf ("foo/bar, range=(gint64)[ 1, %d ];", G_MAXINT);
+  s = gst_structure_from_string (str, &end);
+  fail_unless (*end == '\0');
+  deserialized_value = gst_structure_get_value (s, "range");
+  fail_unless (GST_VALUE_HOLDS_INT64_RANGE (deserialized_value) == TRUE);
+  fail_unless (gst_value_get_int64_range_min (deserialized_value) == 1);
+  fail_unless (gst_value_get_int64_range_max (deserialized_value) == G_MAXINT);
+  str2 = gst_structure_to_string (s);
+  fail_unless (strcmp (str, str2) == 0);
+  gst_structure_free (s);
+  end = NULL;
+  g_free (str);
+  g_free (str2);
+
+  /* check invalid int64_range (starting with a gint) deserialization */
+  str =
+      g_strdup_printf ("foo/bar, range=(gint64)[ 1, %" G_GUINT64_FORMAT " ];",
+      (guint64) G_MAXINT64 + 1);
+  ASSERT_CRITICAL (s = gst_structure_from_string (str, &end));
+  fail_unless (*end == '\0');
+  gst_structure_free (s);
+  end = NULL;
+  g_free (str);
+
+  /* check invalid int64_range deserialization into a int64_range */
+  str =
+      g_strdup_printf ("foo/bar, range=(gint64)[ %" G_GINT64_FORMAT ", %"
+      G_GUINT64_FORMAT " ];", (gint64) G_MAXINT, (guint64) G_MAXINT64 + 1);
+  ASSERT_CRITICAL (s = gst_structure_from_string (str, NULL));
+  g_free (str);
+  gst_structure_free (s);
+
+  /* check invalid int64_range deserialization into a int_range */
+  str =
+      g_strdup_printf ("foo/bar, range=[ %" G_GINT64_FORMAT ", %"
+      G_GUINT64_FORMAT " ];", (gint64) G_MAXINT, (guint64) G_MAXINT64 + 1);
+  s = gst_structure_from_string (str, &end);
+  fail_unless (s == NULL);
+  fail_unless (end == NULL);
+  g_free (str);
+}
+
+GST_END_TEST static Suite *
 gst_value_suite (void)
 {
   Suite *s = suite_create ("GstValue");
@@ -1369,39 +2508,38 @@ gst_value_suite (void)
 
   suite_add_tcase (s, tc_chain);
   tcase_add_test (tc_chain, test_deserialize_buffer);
+  tcase_add_test (tc_chain, test_serialize_buffer);
   tcase_add_test (tc_chain, test_deserialize_gint);
   tcase_add_test (tc_chain, test_deserialize_gint_failures);
   tcase_add_test (tc_chain, test_deserialize_guint);
   tcase_add_test (tc_chain, test_deserialize_guint_failures);
   tcase_add_test (tc_chain, test_deserialize_gint64);
+  tcase_add_test (tc_chain, test_deserialize_guint64);
+  tcase_add_test (tc_chain, test_deserialize_guchar);
   tcase_add_test (tc_chain, test_deserialize_gstfraction);
+  tcase_add_test (tc_chain, test_serialize_flags);
+  tcase_add_test (tc_chain, test_deserialize_flags);
+  tcase_add_test (tc_chain, test_serialize_deserialize_format_enum);
   tcase_add_test (tc_chain, test_string);
   tcase_add_test (tc_chain, test_deserialize_string);
   tcase_add_test (tc_chain, test_value_compare);
   tcase_add_test (tc_chain, test_value_intersect);
   tcase_add_test (tc_chain, test_value_subtract_int);
+  tcase_add_test (tc_chain, test_value_subtract_int64);
   tcase_add_test (tc_chain, test_value_subtract_double);
   tcase_add_test (tc_chain, test_value_subtract_fraction);
   tcase_add_test (tc_chain, test_value_subtract_fraction_range);
+  tcase_add_test (tc_chain, test_value_subtract_fraction_list);
   tcase_add_test (tc_chain, test_date);
+  tcase_add_test (tc_chain, test_date_time);
   tcase_add_test (tc_chain, test_fraction_range);
+  tcase_add_test (tc_chain, test_serialize_deserialize_caps);
+  tcase_add_test (tc_chain, test_int_range);
+  tcase_add_test (tc_chain, test_int64_range);
+  tcase_add_test (tc_chain, test_serialize_int64_range);
+  tcase_add_test (tc_chain, test_deserialize_int_range);
 
   return s;
 }
 
-int
-main (int argc, char **argv)
-{
-  int nf;
-
-  Suite *s = gst_value_suite ();
-  SRunner *sr = srunner_create (s);
-
-  gst_check_init (&argc, &argv);
-
-  srunner_run_all (sr, CK_NORMAL);
-  nf = srunner_ntests_failed (sr);
-  srunner_free (sr);
-
-  return nf;
-}
+GST_CHECK_MAIN (gst_value);