buffer: Add more exhaustive test for gst_buffer_foreach_meta() meta removal
authorDardo D Kleiner <dardokleiner@gmail.com>
Sat, 1 Dec 2018 15:32:07 +0000 (10:32 -0500)
committerSebastian Dröge <slomo@coaxion.net>
Wed, 5 Dec 2018 20:50:45 +0000 (20:50 +0000)
Existing test for iterating/removing buffer meta data was insufficient
to detect linked list corruption when removing multiple items, and could
also suffer from such corruption in attempting to count remaining items.
Modified the one test and added several others to exercise multiple
scenarios.

Validates fix for issue #332.

tests/check/gst/gstmeta.c

index 557c1c2..e5ad47d 100644 (file)
@@ -337,10 +337,98 @@ count_buffer_meta (GstBuffer * buffer)
   return ret;
 }
 
-GST_START_TEST (test_meta_foreach_remove_one)
+GST_START_TEST (test_meta_foreach_remove_one_of_one)
+{
+  GstBuffer *buffer;
+  GstMetaTest *meta1;
+  gpointer state = NULL;
+
+  buffer = gst_buffer_new_and_alloc (4);
+  fail_if (buffer == NULL);
+
+  /* add some metadata */
+  meta1 = GST_META_TEST_ADD (buffer);
+  fail_if (meta1 == NULL);
+
+  fail_unless_equals_int (count_buffer_meta (buffer), 1);
+
+  gst_buffer_foreach_meta (buffer, foreach_meta_remove_one, meta1);
+
+  fail_unless (gst_buffer_iterate_meta (buffer, &state) == NULL);
+
+  /* clean up */
+  gst_buffer_unref (buffer);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_meta_foreach_remove_head_of_three)
+{
+  GstBuffer *buffer;
+  GstMetaTest *meta1, *meta2, *meta3;
+  gpointer state = NULL;
+
+  buffer = gst_buffer_new_and_alloc (4);
+  fail_if (buffer == NULL);
+
+  /* add some metadata */
+  meta1 = GST_META_TEST_ADD (buffer);
+  fail_if (meta1 == NULL);
+  meta2 = GST_META_TEST_ADD (buffer);
+  fail_if (meta2 == NULL);
+  meta3 = GST_META_TEST_ADD (buffer);
+  fail_if (meta3 == NULL);
+
+  fail_unless_equals_int (count_buffer_meta (buffer), 3);
+
+  gst_buffer_foreach_meta (buffer, foreach_meta_remove_one, meta3);
+
+  fail_unless (gst_buffer_iterate_meta (buffer, &state) == (GstMeta *) meta2);
+  fail_unless (gst_buffer_iterate_meta (buffer, &state) == (GstMeta *) meta1);
+  fail_unless (gst_buffer_iterate_meta (buffer, &state) == NULL);
+
+  /* clean up */
+  gst_buffer_unref (buffer);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_meta_foreach_remove_middle_of_three)
 {
   GstBuffer *buffer;
   GstMetaTest *meta1, *meta2, *meta3;
+  gpointer state = NULL;
+
+  buffer = gst_buffer_new_and_alloc (4);
+  fail_if (buffer == NULL);
+
+  /* add some metadata */
+  meta1 = GST_META_TEST_ADD (buffer);
+  fail_if (meta1 == NULL);
+  meta2 = GST_META_TEST_ADD (buffer);
+  fail_if (meta2 == NULL);
+  meta3 = GST_META_TEST_ADD (buffer);
+  fail_if (meta3 == NULL);
+
+  fail_unless_equals_int (count_buffer_meta (buffer), 3);
+
+  gst_buffer_foreach_meta (buffer, foreach_meta_remove_one, meta2);
+
+  fail_unless (gst_buffer_iterate_meta (buffer, &state) == (GstMeta *) meta3);
+  fail_unless (gst_buffer_iterate_meta (buffer, &state) == (GstMeta *) meta1);
+  fail_unless (gst_buffer_iterate_meta (buffer, &state) == NULL);
+
+  /* clean up */
+  gst_buffer_unref (buffer);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_meta_foreach_remove_tail_of_three)
+{
+  GstBuffer *buffer;
+  GstMetaTest *meta1, *meta2, *meta3;
+  gpointer state = NULL;
 
   buffer = gst_buffer_new_and_alloc (4);
   fail_if (buffer == NULL);
@@ -357,7 +445,89 @@ GST_START_TEST (test_meta_foreach_remove_one)
 
   gst_buffer_foreach_meta (buffer, foreach_meta_remove_one, meta1);
 
-  fail_unless_equals_int (count_buffer_meta (buffer), 2);
+  fail_unless (gst_buffer_iterate_meta (buffer, &state) == (GstMeta *) meta3);
+  fail_unless (gst_buffer_iterate_meta (buffer, &state) == (GstMeta *) meta2);
+  fail_unless (gst_buffer_iterate_meta (buffer, &state) == NULL);
+
+  /* clean up */
+  gst_buffer_unref (buffer);
+}
+
+GST_END_TEST;
+
+static gboolean
+foreach_meta_remove_unpooled (GstBuffer * buffer, GstMeta ** meta,
+    gpointer unused)
+{
+  if (!GST_META_FLAG_IS_SET (*meta, GST_META_FLAG_POOLED)) {
+    *meta = NULL;
+  }
+
+  return TRUE;
+}
+
+GST_START_TEST (test_meta_foreach_remove_head_and_tail_of_three)
+{
+  GstBuffer *buffer;
+  GstMetaTest *meta1, *meta2, *meta3;
+  gpointer state = NULL;
+
+  buffer = gst_buffer_new_and_alloc (4);
+  fail_if (buffer == NULL);
+
+  /* add some metadata */
+  meta1 = GST_META_TEST_ADD (buffer);
+  fail_if (meta1 == NULL);
+  meta2 = GST_META_TEST_ADD (buffer);
+  fail_if (meta2 == NULL);
+  GST_META_FLAG_SET (meta2, GST_META_FLAG_POOLED);
+  meta3 = GST_META_TEST_ADD (buffer);
+  fail_if (meta3 == NULL);
+
+  fail_unless_equals_int (count_buffer_meta (buffer), 3);
+
+  gst_buffer_foreach_meta (buffer, foreach_meta_remove_unpooled, NULL);
+
+  fail_unless (gst_buffer_iterate_meta (buffer, &state) == (GstMeta *) meta2);
+  fail_unless (gst_buffer_iterate_meta (buffer, &state) == NULL);
+
+  /* clean up */
+  gst_buffer_unref (buffer);
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_meta_foreach_remove_several)
+{
+  GstBuffer *buffer;
+  GstMetaTest *meta1, *meta2, *meta3, *meta4, *meta5;
+  gpointer state = NULL;
+
+  buffer = gst_buffer_new_and_alloc (4);
+  fail_if (buffer == NULL);
+
+  /* add some metadata */
+  meta1 = GST_META_TEST_ADD (buffer);
+  fail_if (meta1 == NULL);
+  meta2 = GST_META_TEST_ADD (buffer);
+  fail_if (meta2 == NULL);
+  GST_META_FLAG_SET (meta2, GST_META_FLAG_POOLED);
+  meta3 = GST_META_TEST_ADD (buffer);
+  fail_if (meta3 == NULL);
+  meta4 = GST_META_TEST_ADD (buffer);
+  fail_if (meta4 == NULL);
+  meta5 = GST_META_TEST_ADD (buffer);
+  fail_if (meta5 == NULL);
+  GST_META_FLAG_SET (meta5, GST_META_FLAG_POOLED);
+
+  fail_unless_equals_int (count_buffer_meta (buffer), 5);
+
+  gst_buffer_foreach_meta (buffer, foreach_meta_remove_unpooled, NULL);
+
+  fail_unless (gst_buffer_iterate_meta (buffer, &state) == (GstMeta *) meta5);
+  fail_unless (gst_buffer_iterate_meta (buffer, &state) == (GstMeta *) meta2);
+  fail_unless (gst_buffer_iterate_meta (buffer, &state) == NULL);
 
   /* clean up */
   gst_buffer_unref (buffer);
@@ -472,7 +642,12 @@ gst_buffermeta_suite (void)
   suite_add_tcase (s, tc_chain);
   tcase_add_test (tc_chain, test_meta_test);
   tcase_add_test (tc_chain, test_meta_locked);
-  tcase_add_test (tc_chain, test_meta_foreach_remove_one);
+  tcase_add_test (tc_chain, test_meta_foreach_remove_one_of_one);
+  tcase_add_test (tc_chain, test_meta_foreach_remove_head_of_three);
+  tcase_add_test (tc_chain, test_meta_foreach_remove_middle_of_three);
+  tcase_add_test (tc_chain, test_meta_foreach_remove_tail_of_three);
+  tcase_add_test (tc_chain, test_meta_foreach_remove_head_and_tail_of_three);
+  tcase_add_test (tc_chain, test_meta_foreach_remove_several);
   tcase_add_test (tc_chain, test_meta_iterate);
 
   return s;