caps: Add gst_caps_foreach() and gst_caps_map_in_place()
[platform/upstream/gstreamer.git] / tests / check / gst / gstcaps.c
index e5af97e..cb6128b 100644 (file)
@@ -16,8 +16,8 @@
  *
  * 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.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
  */
 
 
@@ -103,6 +103,8 @@ GST_START_TEST (test_static_caps)
   static GstStaticCaps scaps = GST_STATIC_CAPS ("audio/x-raw,rate=44100");
   GstCaps *caps1;
   GstCaps *caps2;
+  static GstStaticCaps sany = GST_STATIC_CAPS_ANY;
+  static GstStaticCaps snone = GST_STATIC_CAPS_NONE;
 
   /* caps creation */
   caps1 = gst_static_caps_get (&scaps);
@@ -120,6 +122,14 @@ GST_START_TEST (test_static_caps)
 
   gst_caps_unref (caps1);
   gst_caps_unref (caps2);
+
+  caps1 = gst_static_caps_get (&sany);
+  fail_unless (gst_caps_is_equal (caps1, GST_CAPS_ANY));
+  caps2 = gst_static_caps_get (&snone);
+  fail_unless (gst_caps_is_equal (caps2, GST_CAPS_NONE));
+  fail_if (gst_caps_is_equal (caps1, caps2));
+  gst_caps_unref (caps1);
+  gst_caps_unref (caps2);
 }
 
 GST_END_TEST;
@@ -190,16 +200,14 @@ check_string_list (const GValue * format_value)
 GST_START_TEST (test_simplify)
 {
   GstStructure *s1;
-  gboolean did_simplify;
   GstCaps *caps;
 
   caps = gst_caps_from_string (non_simple_caps_string);
   fail_unless (caps != NULL,
       "gst_caps_from_string (non_simple_caps_string) failed");
 
-  did_simplify = gst_caps_do_simplify (caps);
-  fail_unless (did_simplify == TRUE,
-      "gst_caps_do_simplify() should have worked");
+  caps = gst_caps_simplify (caps);
+  fail_unless (caps != NULL, "gst_caps_simplify() should have worked");
 
   /* check simplified caps, should be:
    *
@@ -272,7 +280,7 @@ GST_START_TEST (test_truncate)
   fail_unless (caps != NULL,
       "gst_caps_from_string (non_simple_caps_string) failed");
   fail_unless_equals_int (gst_caps_get_size (caps), 4);
-  gst_caps_truncate (caps);
+  caps = gst_caps_truncate (caps);
   fail_unless_equals_int (gst_caps_get_size (caps), 1);
   gst_caps_unref (caps);
 }
@@ -314,6 +322,50 @@ GST_START_TEST (test_subset)
   fail_if (gst_caps_is_subset (c2, c1));
   gst_caps_unref (c1);
   gst_caps_unref (c2);
+
+  c1 = gst_caps_from_string ("video/x-h264, parsed=(boolean)true");
+  c2 = gst_caps_from_string
+      ("video/x-h264, stream-format=(string)byte-stream, alignment=(string)nal");
+  fail_if (gst_caps_is_subset (c2, c1));
+  fail_if (gst_caps_is_subset (c1, c2));
+  fail_if (gst_caps_is_equal (c1, c2));
+  gst_caps_unref (c1);
+  gst_caps_unref (c2);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_subset_duplication)
+{
+  GstCaps *c1, *c2;
+
+  c1 = gst_caps_from_string ("audio/x-raw, format=(string)F32LE");
+  c2 = gst_caps_from_string ("audio/x-raw, format=(string)F32LE");
+
+  fail_unless (gst_caps_is_subset (c1, c2));
+  fail_unless (gst_caps_is_subset (c2, c1));
+
+  gst_caps_unref (c2);
+  c2 = gst_caps_from_string ("audio/x-raw, format=(string){ F32LE }");
+
+  fail_unless (gst_caps_is_subset (c1, c2));
+  fail_unless (gst_caps_is_subset (c2, c1));
+
+  gst_caps_unref (c2);
+  c2 = gst_caps_from_string ("audio/x-raw, format=(string){ F32LE, F32LE }");
+
+  fail_unless (gst_caps_is_subset (c1, c2));
+  fail_unless (gst_caps_is_subset (c2, c1));
+
+  gst_caps_unref (c2);
+  c2 = gst_caps_from_string
+      ("audio/x-raw, format=(string){ F32LE, F32LE, F32LE }");
+
+  fail_unless (gst_caps_is_subset (c1, c2));
+  fail_unless (gst_caps_is_subset (c2, c1));
+
+  gst_caps_unref (c1);
+  gst_caps_unref (c2);
 }
 
 GST_END_TEST;
@@ -325,7 +377,7 @@ GST_START_TEST (test_merge_fundamental)
   /* ANY + specific = ANY */
   c1 = gst_caps_from_string ("audio/x-raw,rate=44100");
   c2 = gst_caps_new_any ();
-  gst_caps_merge (c2, c1);
+  c2 = gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 0, NULL);
   fail_unless (gst_caps_is_any (c2), NULL);
@@ -334,7 +386,7 @@ GST_START_TEST (test_merge_fundamental)
   /* specific + ANY = ANY */
   c2 = gst_caps_from_string ("audio/x-raw,rate=44100");
   c1 = gst_caps_new_any ();
-  gst_caps_merge (c2, c1);
+  c2 = gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 0, NULL);
   fail_unless (gst_caps_is_any (c2), NULL);
@@ -343,7 +395,7 @@ GST_START_TEST (test_merge_fundamental)
   /* EMPTY + specific = specific */
   c1 = gst_caps_from_string ("audio/x-raw,rate=44100");
   c2 = gst_caps_new_empty ();
-  gst_caps_merge (c2, c1);
+  c2 = gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 1, NULL);
   fail_if (gst_caps_is_empty (c2), NULL);
@@ -352,7 +404,7 @@ GST_START_TEST (test_merge_fundamental)
   /* specific + EMPTY = specific */
   c2 = gst_caps_from_string ("audio/x-raw,rate=44100");
   c1 = gst_caps_new_empty ();
-  gst_caps_merge (c2, c1);
+  c2 = gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 1, NULL);
   fail_if (gst_caps_is_empty (c2), NULL);
@@ -368,7 +420,7 @@ GST_START_TEST (test_merge_same)
   /* this is the same */
   c1 = gst_caps_from_string ("audio/x-raw,rate=44100,channels=1");
   c2 = gst_caps_from_string ("audio/x-raw,rate=44100,channels=1");
-  gst_caps_merge (c2, c1);
+  c2 = gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 1, NULL);
   test = gst_caps_from_string ("audio/x-raw,rate=44100,channels=1");
@@ -379,35 +431,35 @@ GST_START_TEST (test_merge_same)
   /* and so is this */
   c1 = gst_caps_from_string ("audio/x-raw,rate=44100,channels=1");
   c2 = gst_caps_from_string ("audio/x-raw,channels=1,rate=44100");
-  gst_caps_merge (c2, c1);
+  c2 = gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 1, NULL);
   gst_caps_unref (c2);
 
   c1 = gst_caps_from_string ("video/x-foo, data=(buffer)AA");
   c2 = gst_caps_from_string ("video/x-foo, data=(buffer)AABB");
-  gst_caps_merge (c2, c1);
+  c2 = gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 2, NULL);
   gst_caps_unref (c2);
 
   c1 = gst_caps_from_string ("video/x-foo, data=(buffer)AABB");
   c2 = gst_caps_from_string ("video/x-foo, data=(buffer)AA");
-  gst_caps_merge (c2, c1);
+  c2 = gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 2, NULL);
   gst_caps_unref (c2);
 
   c1 = gst_caps_from_string ("video/x-foo, data=(buffer)AA");
   c2 = gst_caps_from_string ("video/x-foo, data=(buffer)AA");
-  gst_caps_merge (c2, c1);
+  c2 = gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 1, NULL);
   gst_caps_unref (c2);
 
   c1 = gst_caps_from_string ("video/x-foo, data=(buffer)AA");
   c2 = gst_caps_from_string ("video/x-bar, data=(buffer)AA");
-  gst_caps_merge (c2, c1);
+  c2 = gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 2, NULL);
   gst_caps_unref (c2);
@@ -422,7 +474,7 @@ GST_START_TEST (test_merge_subset)
   /* the 2nd is already covered */
   c2 = gst_caps_from_string ("audio/x-raw,channels=[1,2]");
   c1 = gst_caps_from_string ("audio/x-raw,channels=1");
-  gst_caps_merge (c2, c1);
+  c2 = gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 1, NULL);
   test = gst_caps_from_string ("audio/x-raw,channels=[1,2]");
@@ -433,7 +485,7 @@ GST_START_TEST (test_merge_subset)
   /* here it is not */
   c2 = gst_caps_from_string ("audio/x-raw,channels=1,rate=44100");
   c1 = gst_caps_from_string ("audio/x-raw,channels=[1,2],rate=44100");
-  gst_caps_merge (c2, c1);
+  c2 = gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 2, NULL);
   test = gst_caps_from_string ("audio/x-raw,channels=[1,2],rate=44100");
@@ -444,7 +496,7 @@ GST_START_TEST (test_merge_subset)
   /* second one was already contained in the first one */
   c2 = gst_caps_from_string ("audio/x-raw,channels=[1,3]");
   c1 = gst_caps_from_string ("audio/x-raw,channels=[1,2]");
-  gst_caps_merge (c2, c1);
+  c2 = gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 1, NULL);
   test = gst_caps_from_string ("audio/x-raw,channels=[1,3]");
@@ -455,7 +507,7 @@ GST_START_TEST (test_merge_subset)
   /* second one was already contained in the first one */
   c2 = gst_caps_from_string ("audio/x-raw,channels=[1,4]");
   c1 = gst_caps_from_string ("audio/x-raw,channels=[1,2]");
-  gst_caps_merge (c2, c1);
+  c2 = gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 1, NULL);
   test = gst_caps_from_string ("audio/x-raw,channels=[1,4]");
@@ -466,7 +518,7 @@ GST_START_TEST (test_merge_subset)
   /* second one was already contained in the first one */
   c2 = gst_caps_from_string ("audio/x-raw,channels=[1,4]");
   c1 = gst_caps_from_string ("audio/x-raw,channels=[2,4]");
-  gst_caps_merge (c2, c1);
+  c2 = gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 1, NULL);
   test = gst_caps_from_string ("audio/x-raw,channels=[1,4]");
@@ -477,7 +529,7 @@ GST_START_TEST (test_merge_subset)
   /* second one was already contained in the first one */
   c2 = gst_caps_from_string ("audio/x-raw,channels=[1,4]");
   c1 = gst_caps_from_string ("audio/x-raw,channels=[2,3]");
-  gst_caps_merge (c2, c1);
+  c2 = gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 1, NULL);
   test = gst_caps_from_string ("audio/x-raw,channels=[1,4]");
@@ -488,7 +540,7 @@ GST_START_TEST (test_merge_subset)
   /* these caps cannot be merged */
   c2 = gst_caps_from_string ("audio/x-raw,channels=[2,3]");
   c1 = gst_caps_from_string ("audio/x-raw,channels=[1,4]");
-  gst_caps_merge (c2, c1);
+  c2 = gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 2, NULL);
   test =
@@ -501,7 +553,7 @@ GST_START_TEST (test_merge_subset)
   /* these caps cannot be merged */
   c2 = gst_caps_from_string ("audio/x-raw,channels=[1,2]");
   c1 = gst_caps_from_string ("audio/x-raw,channels=[1,3]");
-  gst_caps_merge (c2, c1);
+  c2 = gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 2, NULL);
   test =
@@ -513,7 +565,7 @@ GST_START_TEST (test_merge_subset)
 
   c2 = gst_caps_from_string ("audio/x-raw,channels={1,2}");
   c1 = gst_caps_from_string ("audio/x-raw,channels={1,2,3,4}");
-  gst_caps_merge (c2, c1);
+  c2 = gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 2, NULL);
   test = gst_caps_from_string ("audio/x-raw,channels={1,2};"
@@ -524,7 +576,7 @@ GST_START_TEST (test_merge_subset)
 
   c2 = gst_caps_from_string ("audio/x-raw,channels={1,2}");
   c1 = gst_caps_from_string ("audio/x-raw,channels={1,3}");
-  gst_caps_merge (c2, c1);
+  c2 = gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 2, NULL);
   test = gst_caps_from_string ("audio/x-raw,channels={1,2};"
@@ -536,7 +588,7 @@ GST_START_TEST (test_merge_subset)
   c2 = gst_caps_from_string ("video/x-raw, framerate=(fraction){ 15/2, 5/1 }");
   c1 = gst_caps_from_string ("video/x-raw, framerate=(fraction){ 15/1, 5/1 }");
   test = gst_caps_copy (c1);
-  gst_caps_merge (c2, c1);
+  c2 = gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_is_subset (test, c2));
   gst_caps_unref (test);
@@ -544,7 +596,7 @@ GST_START_TEST (test_merge_subset)
 
   c2 = gst_caps_from_string ("audio/x-raw");
   c1 = gst_caps_from_string ("audio/x-raw,channels=1");
-  gst_caps_merge (c2, c1);
+  c2 = gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 1, NULL);
   test = gst_caps_from_string ("audio/x-raw");
@@ -554,7 +606,7 @@ GST_START_TEST (test_merge_subset)
 
   c2 = gst_caps_from_string ("audio/x-raw,channels=1");
   c1 = gst_caps_from_string ("audio/x-raw");
-  gst_caps_merge (c2, c1);
+  c2 = gst_caps_merge (c2, c1);
   GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
   fail_unless (gst_caps_get_size (c2) == 2, NULL);
   test = gst_caps_from_string ("audio/x-raw,channels=1; audio/x-raw");
@@ -716,6 +768,70 @@ GST_START_TEST (test_intersect2)
 
 GST_END_TEST;
 
+GST_START_TEST (test_intersect_list_duplicate)
+{
+  GstCaps *caps1, *caps2, *icaps;
+
+  /* make sure we don't take too long to intersect these.. */
+  caps1 = gst_caps_from_string ("video/x-raw, format=(string)YV12; "
+      "video/x-raw, format=(string)I420; video/x-raw, format=(string)YUY2; "
+      "video/x-raw, format=(string)UYVY; "
+      "video/x-raw, format=(string){ I420, YV12, YUY2, UYVY, AYUV, RGBx, BGRx,"
+      " xRGB, xBGR, { RGBA, RGBA, { RGBA, RGBA }, "
+      "{ RGBA, RGBA, { RGBA, RGBA } }, { RGBA, RGBA, { RGBA, RGBA }, "
+      "{ RGBA, RGBA, { RGBA, RGBA } } }, { RGBA, RGBA, { RGBA, RGBA }, "
+      "{ RGBA, RGBA, { RGBA, RGBA } }, { RGBA, RGBA, { RGBA, RGBA }, "
+      "{ RGBA, RGBA, { RGBA, RGBA } } } }, { RGBA, RGBA, { RGBA, RGBA }, "
+      "{ RGBA, RGBA, { RGBA, RGBA } }, { RGBA, RGBA, { RGBA, RGBA }, "
+      "{ RGBA, RGBA, { RGBA, RGBA } } }, { RGBA, RGBA, { RGBA, RGBA }, "
+      "{ RGBA, RGBA, { RGBA, RGBA } }, { RGBA, RGBA, { RGBA, RGBA }, "
+      "{ RGBA, RGBA, { RGBA, RGBA } } } } } }, BGRA, ARGB, { ABGR, ABGR, "
+      "{ ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } }, "
+      "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } } }, "
+      "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } }, "
+      "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } } } }, "
+      "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } }, "
+      "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } } }, "
+      "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } }, "
+      "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } } } } } }, "
+      "RGB, BGR, Y41B, Y42B, YVYU, Y444 }; "
+      "video/x-raw, format=(string){ I420, YV12, YUY2, UYVY, AYUV, RGBx, BGRx, "
+      "xRGB, xBGR, { RGBA, RGBA, { RGBA, RGBA }, "
+      "{ RGBA, RGBA, { RGBA, RGBA } }, { RGBA, RGBA, { RGBA, RGBA }, "
+      "{ RGBA, RGBA, { RGBA, RGBA } } }, { RGBA, RGBA, { RGBA, RGBA }, "
+      "{ RGBA, RGBA, { RGBA, RGBA } }, { RGBA, RGBA, { RGBA, RGBA }, "
+      "{ RGBA, RGBA, { RGBA, RGBA } } } }, { RGBA, RGBA, { RGBA, RGBA }, "
+      "{ RGBA, RGBA, { RGBA, RGBA } }, { RGBA, RGBA, { RGBA, RGBA }, "
+      "{ RGBA, RGBA, { RGBA, RGBA } } }, { RGBA, RGBA, { RGBA, RGBA }, "
+      "{ RGBA, RGBA, { RGBA, RGBA } }, { RGBA, RGBA, { RGBA, RGBA }, "
+      "{ RGBA, RGBA, { RGBA, RGBA } } } } } }, BGRA, ARGB, "
+      "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } }, "
+      "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } } }, "
+      "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } }, "
+      "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } } } }, "
+      "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } }, "
+      "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } } }, "
+      "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } }, "
+      "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } } } } } }, "
+      "RGB, BGR, Y41B, Y42B, YVYU, Y444, NV12, NV21 }; "
+      "video/x-raw, format=(string){ I420, YV12, YUY2, UYVY, AYUV, RGBx, "
+      "BGRx, xRGB, xBGR, { RGBA, RGBA, { RGBA, RGBA }, "
+      "{ RGBA, RGBA, { RGBA, RGBA } }, { RGBA, RGBA, { RGBA, RGBA }, "
+      "{ RGBA, RGBA, { RGBA, RGBA } } } }, BGRA, ARGB, "
+      "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } }, "
+      "{ ABGR, ABGR, { ABGR, ABGR }, { ABGR, ABGR, { ABGR, ABGR } } } }, "
+      "RGB, BGR, Y41B, Y42B, YVYU, Y444, NV12, NV21 }");
+
+  caps2 = gst_caps_copy (caps1);
+
+  icaps = gst_caps_intersect (caps1, caps2);
+
+  gst_caps_unref (caps1);
+  gst_caps_unref (caps2);
+  gst_caps_unref (icaps);
+}
+
+GST_END_TEST;
 
 GST_START_TEST (test_intersect_zigzag)
 {
@@ -841,7 +957,6 @@ GST_START_TEST (test_normalize)
     fail_unless (gst_structure_foreach (st, _caps_is_fixed_foreach, NULL));
   }
 
-  gst_caps_unref (in);
   gst_caps_unref (out);
   gst_caps_unref (norm);
 
@@ -860,7 +975,6 @@ GST_START_TEST (test_normalize)
     fail_unless (gst_structure_foreach (st, _caps_is_fixed_foreach, NULL));
   }
 
-  gst_caps_unref (in);
   gst_caps_unref (out);
   gst_caps_unref (norm);
 
@@ -878,7 +992,6 @@ GST_START_TEST (test_normalize)
     fail_unless (gst_structure_foreach (st, _caps_is_fixed_foreach, NULL));
   }
 
-  gst_caps_unref (in);
   gst_caps_unref (out);
   gst_caps_unref (norm);
 }
@@ -904,6 +1017,228 @@ GST_START_TEST (test_broken)
 
 GST_END_TEST;
 
+GST_START_TEST (test_features)
+{
+  GstCaps *c1, *c2, *c3;
+  GstStructure *s1, *s2;
+  GstCapsFeatures *f1, *f2;
+  gchar *str1;
+  static GstStaticCaps scaps =
+      GST_STATIC_CAPS
+      ("video/x-raw(memory:EGLImage), width=320, height=[ 240, 260 ]");
+
+  c1 = gst_caps_new_empty ();
+  fail_unless (c1 != NULL);
+  s1 = gst_structure_new ("video/x-raw", "width", G_TYPE_INT, 320, "height",
+      GST_TYPE_INT_RANGE, 240, 260, NULL);
+  fail_unless (s1 != NULL);
+  f1 = gst_caps_features_new ("memory:EGLImage", NULL);
+  fail_unless (f1 != NULL);
+
+  gst_caps_append_structure_full (c1, s1, f1);
+  s2 = gst_caps_get_structure (c1, 0);
+  fail_unless (s1 == s2);
+  f2 = gst_caps_get_features (c1, 0);
+  fail_unless (f1 == f2);
+
+  str1 = gst_caps_to_string (c1);
+  fail_unless (str1 != NULL);
+  c2 = gst_caps_from_string (str1);
+  fail_unless (c2 != NULL);
+  g_free (str1);
+
+  fail_unless (gst_caps_is_equal (c1, c2));
+  fail_unless (gst_caps_is_subset (c1, c2));
+  fail_unless (gst_caps_is_subset (c2, c1));
+  fail_unless (gst_caps_can_intersect (c1, c2));
+
+  gst_caps_unref (c2);
+
+  c2 = gst_caps_new_empty ();
+  fail_unless (c2 != NULL);
+  s2 = gst_structure_new ("video/x-raw", "width", G_TYPE_INT, 320, "height",
+      GST_TYPE_INT_RANGE, 240, 260, NULL);
+  fail_unless (s2 != NULL);
+  f2 = gst_caps_features_new ("memory:VASurface", "meta:VAMeta", NULL);
+  fail_unless (f2 != NULL);
+  gst_caps_append_structure_full (c2, s2, f2);
+
+  fail_if (gst_caps_is_equal (c1, c2));
+  fail_if (gst_caps_is_subset (c1, c2));
+  fail_if (gst_caps_is_subset (c2, c1));
+  fail_if (gst_caps_can_intersect (c1, c2));
+
+  str1 = gst_caps_to_string (c2);
+  fail_unless (str1 != NULL);
+  c3 = gst_caps_from_string (str1);
+  fail_unless (c3 != NULL);
+  g_free (str1);
+
+  fail_unless (gst_caps_is_equal (c2, c3));
+  fail_unless (gst_caps_is_subset (c2, c3));
+  fail_unless (gst_caps_is_subset (c3, c2));
+  fail_unless (gst_caps_can_intersect (c2, c3));
+
+  f1 = gst_caps_get_features (c3, 0);
+  fail_unless (f1 != NULL);
+  fail_if (f1 == f2);
+  gst_caps_features_contains (f1, "memory:VASurface");
+  gst_caps_features_remove (f1, "memory:VASurface");
+  fail_if (gst_caps_is_equal (c2, c3));
+  fail_if (gst_caps_is_subset (c2, c3));
+  fail_if (gst_caps_is_subset (c3, c2));
+  fail_if (gst_caps_can_intersect (c2, c3));
+
+  gst_caps_unref (c3);
+  gst_caps_unref (c2);
+
+  c2 = gst_static_caps_get (&scaps);
+  fail_unless (c2 != NULL);
+  fail_unless (gst_caps_is_equal (c1, c2));
+  fail_unless (gst_caps_is_subset (c1, c2));
+  fail_unless (gst_caps_is_subset (c2, c1));
+  fail_unless (gst_caps_can_intersect (c1, c2));
+  gst_caps_unref (c2);
+
+  c2 = gst_caps_from_string
+      ("video/x-raw(ANY), width=320, height=[ 240, 260 ]");
+  fail_unless (c2 != NULL);
+  fail_if (gst_caps_is_equal (c1, c2));
+  fail_unless (gst_caps_is_subset (c1, c2));
+  fail_if (gst_caps_is_subset (c2, c1));
+  fail_unless (gst_caps_can_intersect (c1, c2));
+
+  c3 = gst_caps_intersect (c1, c2);
+  fail_unless (gst_caps_is_equal (c3, c1));
+
+  gst_caps_unref (c3);
+  gst_caps_unref (c2);
+  gst_caps_unref (c1);
+
+  c1 = gst_caps_from_string ("video/x-raw");
+  c2 = gst_caps_from_string ("video/x-raw");
+
+  f1 = gst_caps_get_features (c1, 0);
+  gst_caps_features_add (f1, "memory:VASurface");
+
+  fail_unless (gst_caps_features_is_equal (f1, gst_caps_get_features (c1, 0)));
+  fail_if (gst_caps_can_intersect (c1, c2));
+
+  f2 = gst_caps_get_features (c2, 0);
+  fail_unless (gst_caps_features_is_equal
+      (GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY, f2));
+
+  gst_caps_unref (c2);
+  gst_caps_unref (c1);
+
+  c1 = gst_caps_from_string ("video/x-raw");
+  f1 = gst_caps_get_features (c1, 0);
+  f2 = gst_caps_features_new ("memory:dmabuf", NULL);
+  gst_caps_set_features (c1, 0, f2);
+
+  gst_caps_unref (c1);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_special_caps)
+{
+  GstCaps *caps;
+
+  caps = gst_caps_new_any ();
+  fail_unless (gst_caps_is_any (caps));
+  fail_unless (gst_caps_is_any (caps) == TRUE);
+  fail_if (gst_caps_is_empty (caps));
+  fail_unless (gst_caps_is_empty (caps) == FALSE);
+  gst_caps_unref (caps);
+
+  caps = gst_caps_new_empty ();
+  fail_if (gst_caps_is_any (caps));
+  fail_unless (gst_caps_is_any (caps) == FALSE);
+  fail_unless (gst_caps_is_empty (caps));
+  fail_unless (gst_caps_is_empty (caps) == TRUE);
+  gst_caps_unref (caps);
+}
+
+GST_END_TEST;
+
+static gboolean
+foreach_append_function (GstCapsFeatures * features, GstStructure * structure,
+    gpointer user_data)
+{
+  GstCaps *caps = user_data;
+
+  gst_caps_append_structure_full (caps, gst_structure_copy (structure),
+      features ? gst_caps_features_copy (features) : NULL);
+
+  return TRUE;
+}
+
+GST_START_TEST (test_foreach)
+{
+  GstCaps *caps, *caps2;
+
+  caps =
+      gst_caps_from_string
+      ("video/x-raw, format=I420; video/x-raw(foo:bar); video/x-h264");
+  caps2 = gst_caps_new_empty ();
+  fail_unless (gst_caps_foreach (caps, foreach_append_function, caps2));
+  fail_unless (gst_caps_is_strictly_equal (caps, caps2));
+  gst_caps_unref (caps);
+  gst_caps_unref (caps2);
+
+  caps = gst_caps_new_empty ();
+  caps2 = gst_caps_new_empty ();
+  fail_unless (gst_caps_foreach (caps, foreach_append_function, caps2));
+  fail_unless (gst_caps_is_strictly_equal (caps, caps2));
+  gst_caps_unref (caps);
+  gst_caps_unref (caps2);
+}
+
+GST_END_TEST;
+
+static gboolean
+map_function (GstCapsFeatures * features, GstStructure * structure,
+    gpointer user_data)
+{
+  /* Remove caps features if there are any, otherwise add some dummy */
+  if (gst_caps_features_contains (features, "foo:bar")) {
+    gst_caps_features_remove (features, "foo:bar");
+  } else {
+    gst_caps_features_add (features, "foo:bar");
+    gst_caps_features_remove (features, GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY);
+  }
+
+  /* Set some dummy integer in the structure */
+  gst_structure_set (structure, "foo", G_TYPE_INT, 123, NULL);
+
+  return TRUE;
+}
+
+GST_START_TEST (test_map_in_place)
+{
+  GstCaps *caps, *caps2;
+
+  caps =
+      gst_caps_from_string
+      ("video/x-raw, format=I420; video/x-raw(foo:bar); video/x-h264");
+  caps2 =
+      gst_caps_from_string
+      ("video/x-raw(foo:bar), foo=(int)123, format=I420; video/x-raw, foo=(int)123; video/x-h264(foo:bar), foo=(int)123");
+  fail_unless (gst_caps_map_in_place (caps, map_function, NULL));
+  fail_unless (gst_caps_is_strictly_equal (caps, caps2));
+  gst_caps_unref (caps);
+  gst_caps_unref (caps2);
+
+  caps = gst_caps_new_empty ();
+  caps2 = gst_caps_new_empty ();
+  fail_unless (gst_caps_map_in_place (caps, map_function, NULL));
+  fail_unless (gst_caps_is_strictly_equal (caps, caps2));
+  gst_caps_unref (caps);
+  gst_caps_unref (caps2);
+}
+
+GST_END_TEST;
 
 static Suite *
 gst_caps_suite (void)
@@ -919,17 +1254,23 @@ gst_caps_suite (void)
   tcase_add_test (tc_chain, test_simplify);
   tcase_add_test (tc_chain, test_truncate);
   tcase_add_test (tc_chain, test_subset);
+  tcase_add_test (tc_chain, test_subset_duplication);
   tcase_add_test (tc_chain, test_merge_fundamental);
   tcase_add_test (tc_chain, test_merge_same);
   tcase_add_test (tc_chain, test_merge_subset);
   tcase_add_test (tc_chain, test_intersect);
   tcase_add_test (tc_chain, test_intersect2);
+  tcase_add_test (tc_chain, test_intersect_list_duplicate);
   tcase_add_test (tc_chain, test_intersect_zigzag);
   tcase_add_test (tc_chain, test_intersect_first);
   tcase_add_test (tc_chain, test_intersect_first2);
   tcase_add_test (tc_chain, test_intersect_duplication);
   tcase_add_test (tc_chain, test_normalize);
   tcase_add_test (tc_chain, test_broken);
+  tcase_add_test (tc_chain, test_features);
+  tcase_add_test (tc_chain, test_special_caps);
+  tcase_add_test (tc_chain, test_foreach);
+  tcase_add_test (tc_chain, test_map_in_place);
 
   return s;
 }