3 * unit test for GstBufferList
5 * Copyright (C) 2009 Axis Communications <dev-gstreamer at axis dot com>
6 * @author Jonas Holmberg <jonas dot holmberg at axis dot com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
24 #include <gst/check/gstcheck.h>
25 #include <gst/gstbufferlist.h>
28 static GstBufferList *list;
33 list = gst_buffer_list_new ();
39 gst_buffer_list_unref (list);
43 GST_START_TEST (test_add_and_iterate)
48 /* buffer list is initially empty */
49 fail_unless (gst_buffer_list_length (list) == 0);
51 ASSERT_CRITICAL (gst_buffer_list_insert (list, 0, NULL));
52 ASSERT_CRITICAL (gst_buffer_list_insert (NULL, 0, NULL));
54 buf1 = gst_buffer_new ();
56 /* add a group of 2 buffers */
57 fail_unless (gst_buffer_list_length (list) == 0);
58 ASSERT_CRITICAL (gst_buffer_list_insert (list, -1, NULL));
59 ASSERT_BUFFER_REFCOUNT (buf1, "buf1", 1);
60 gst_buffer_list_add (list, buf1);
61 ASSERT_BUFFER_REFCOUNT (buf1, "buf1", 1); /* list takes ownership */
62 fail_unless (gst_buffer_list_length (list) == 1);
63 buf2 = gst_buffer_new ();
64 gst_buffer_list_add (list, buf2);
65 ASSERT_BUFFER_REFCOUNT (buf2, "buf2", 1);
66 fail_unless (gst_buffer_list_length (list) == 2);
71 GST_START_TEST (test_remove)
75 /* buffer list is initially empty */
76 fail_unless (gst_buffer_list_length (list) == 0);
78 buf = gst_buffer_new ();
80 /* add our own ref so it stays alive after removal from the list */
81 buf = gst_buffer_ref (buf);
84 fail_unless (gst_buffer_list_length (list) == 0);
85 ASSERT_CRITICAL (gst_buffer_list_insert (list, -1, NULL));
86 ASSERT_BUFFER_REFCOUNT (buf, "buf", 2);
87 gst_buffer_list_add (list, buf);
88 ASSERT_BUFFER_REFCOUNT (buf, "buf", 2); /* list takes ownership */
89 fail_unless (gst_buffer_list_length (list) == 1);
90 gst_buffer_list_remove (list, 0, 1);
91 ASSERT_BUFFER_REFCOUNT (buf, "buf", 1);
92 gst_buffer_unref (buf);
93 fail_unless (gst_buffer_list_length (list) == 0);
98 GST_START_TEST (test_make_writable)
100 GstBufferList *wlist;
106 /* add buffers to list */
107 buf1 = gst_buffer_new_allocate (NULL, 1, NULL);
108 gst_buffer_list_add (list, buf1);
110 buf2 = gst_buffer_new_allocate (NULL, 2, NULL);
111 buf3 = gst_buffer_new_allocate (NULL, 3, NULL);
112 gst_buffer_list_add (list, gst_buffer_append (buf2, buf3));
114 /* making it writable with refcount 1 returns the same list */
115 wlist = gst_buffer_list_make_writable (list);
116 fail_unless (wlist == list);
117 fail_unless_equals_int (gst_buffer_list_length (list), 2);
118 buf = gst_buffer_list_get (list, 0);
119 fail_unless (buf == buf1);
120 ASSERT_BUFFER_REFCOUNT (buf1, "buf1", 1);
121 fail_unless_equals_int (gst_buffer_get_size (buf), 1);
122 buf = gst_buffer_list_get (list, 1);
123 fail_unless (buf == buf2);
124 ASSERT_BUFFER_REFCOUNT (buf2, "buf2", 1);
125 fail_unless_equals_int (gst_buffer_n_memory (buf), 2);
127 /* making it writable with refcount 2 returns a copy of the list with
128 * increased refcount on the buffers in the list */
129 gst_buffer_list_ref (list);
130 fail_unless_equals_int (GST_MINI_OBJECT_REFCOUNT_VALUE (list), 2);
131 wlist = gst_buffer_list_make_writable (list);
132 fail_unless_equals_int (GST_MINI_OBJECT_REFCOUNT_VALUE (list), 1);
133 fail_unless_equals_int (GST_MINI_OBJECT_REFCOUNT_VALUE (wlist), 1);
134 fail_unless (wlist != list);
136 fail_unless_equals_int (gst_buffer_list_length (list), 2);
137 buf = gst_buffer_list_get (list, 0);
138 fail_unless (buf == buf1);
139 ASSERT_BUFFER_REFCOUNT (buf1, "buf1", 2);
140 fail_unless_equals_int (gst_buffer_get_size (buf), 1);
141 buf = gst_buffer_list_get (list, 1);
142 fail_unless (buf == buf2);
143 ASSERT_BUFFER_REFCOUNT (buf2, "buf2", 2);
144 fail_unless_equals_int (gst_buffer_n_memory (buf), 2);
146 fail_unless_equals_int (gst_buffer_list_length (wlist), 2);
147 buf = gst_buffer_list_get (wlist, 0);
148 fail_unless (buf == buf1);
149 ASSERT_BUFFER_REFCOUNT (buf1, "buf1", 2);
150 fail_unless_equals_int (gst_buffer_get_size (buf), 1);
151 buf = gst_buffer_list_get (wlist, 1);
152 fail_unless (buf == buf2);
153 ASSERT_BUFFER_REFCOUNT (buf2, "buf2", 2);
154 fail_unless_equals_int (gst_buffer_n_memory (buf), 2);
155 gst_buffer_list_unref (wlist);
156 /* list will be unrefed in cleanup hook */
161 GST_START_TEST (test_copy)
163 GstBufferList *list_copy;
169 /* add buffers to the list */
170 buf1 = gst_buffer_new_allocate (NULL, 1, NULL);
171 gst_buffer_list_add (list, buf1);
173 buf2 = gst_buffer_new_allocate (NULL, 2, NULL);
174 buf3 = gst_buffer_new_allocate (NULL, 3, NULL);
175 gst_buffer_list_add (list, gst_buffer_append (buf2, buf3));
178 list_copy = gst_buffer_list_copy (list);
179 fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (list) == 1);
180 fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (list_copy) == 1);
181 fail_unless (list_copy != list);
182 fail_unless_equals_int (gst_buffer_list_length (list_copy), 2);
183 buf = gst_buffer_list_get (list_copy, 0);
184 fail_unless (buf == buf1);
185 ASSERT_BUFFER_REFCOUNT (buf1, "buf1", 2);
186 fail_unless_equals_int (gst_buffer_get_size (buf1), 1);
187 buf = gst_buffer_list_get (list_copy, 1);
188 fail_unless (buf == buf2);
189 ASSERT_BUFFER_REFCOUNT (buf2, "buf2", 2);
190 fail_unless_equals_int (gst_buffer_get_size (buf2), 5);
191 fail_unless_equals_int (gst_buffer_n_memory (buf2), 2);
193 gst_buffer_list_unref (list_copy);
198 GST_START_TEST (test_copy_deep)
200 GstBufferList *list_copy;
201 GstMapInfo info, sinfo;
206 /* add buffers to the list */
207 buf1 = gst_buffer_new_allocate (NULL, 1, NULL);
208 gst_buffer_list_add (list, buf1);
210 buf2 = gst_buffer_new_allocate (NULL, 2, NULL);
211 gst_buffer_list_add (list, buf2);
214 list_copy = gst_buffer_list_copy_deep (list);
215 fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (list) == 1);
216 fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (list_copy) == 1);
217 fail_unless (list_copy != list);
218 fail_unless_equals_int (gst_buffer_list_length (list_copy), 2);
220 buf_copy = gst_buffer_list_get (list_copy, 0);
221 /* each buffer in the list is copied and must point to different memory */
222 fail_unless (buf_copy != buf1);
223 ASSERT_BUFFER_REFCOUNT (buf1, "buf1", 1);
224 fail_unless_equals_int (gst_buffer_get_size (buf1), 1);
226 buf_copy = gst_buffer_list_get (list_copy, 1);
227 fail_unless (buf_copy != buf2);
228 ASSERT_BUFFER_REFCOUNT (buf2, "buf2", 1);
229 fail_unless_equals_int (gst_buffer_get_size (buf2), 2);
231 fail_unless (gst_buffer_map (buf2, &info, GST_MAP_READ));
232 fail_unless (gst_buffer_map (buf_copy, &sinfo, GST_MAP_READ));
234 /* NOTE that data is refcounted */
235 fail_unless (info.size == sinfo.size);
236 /* copy_deep() forces new GstMemory to be used */
237 fail_unless (info.data != sinfo.data);
239 gst_buffer_unmap (buf_copy, &sinfo);
240 gst_buffer_unmap (buf2, &info);
242 gst_buffer_list_unref (list_copy);
254 foreach_func1 (GstBuffer ** buffer, guint idx, ForeachData * data)
256 fail_unless (buffer != NULL);
257 fail_unless (GST_IS_BUFFER (*buffer));
258 fail_unless (*buffer == data->buf[idx]);
266 foreach_func3 (GstBuffer ** buffer, guint idx, ForeachData * data)
268 fail_unless (idx == 0);
269 fail_unless (buffer != NULL);
270 fail_unless (GST_IS_BUFFER (*buffer));
271 fail_unless (*buffer == data->buf[idx]);
279 foreach_func4 (GstBuffer ** buffer, guint idx, ForeachData * data)
281 fail_unless (idx == 0);
282 fail_unless (buffer != NULL);
283 fail_unless (GST_IS_BUFFER (*buffer));
284 fail_unless (*buffer == data->buf[data->iter]);
287 if (*buffer == data->buf[0]) {
288 gst_buffer_unref (*buffer);
298 foreach_func5 (GstBuffer ** buffer, guint idx, ForeachData * data)
300 fail_unless (buffer != NULL);
301 fail_unless (GST_IS_BUFFER (*buffer));
308 GST_START_TEST (test_foreach)
310 GstBuffer *buf2, *buf3;
313 /* add buffers to the list */
314 data.buf[0] = gst_buffer_new_allocate (NULL, 1, NULL);
315 gst_buffer_list_add (list, data.buf[0]);
317 buf2 = gst_buffer_new_allocate (NULL, 2, NULL);
318 buf3 = gst_buffer_new_allocate (NULL, 3, NULL);
319 data.buf[1] = gst_buffer_append (buf2, buf3);
320 gst_buffer_list_add (list, data.buf[1]);
322 fail_unless (gst_buffer_list_get (list, 0) == data.buf[0]);
323 fail_unless (gst_buffer_list_get (list, 1) == data.buf[1]);
325 /* iterate everything */
327 gst_buffer_list_foreach (list, (GstBufferListFunc) foreach_func1, &data);
328 fail_unless (data.iter == 2);
330 /* iterate only the first buffer */
332 gst_buffer_list_foreach (list, (GstBufferListFunc) foreach_func3, &data);
333 fail_unless (data.iter == 1);
335 /* remove the first buffer */
337 gst_buffer_list_foreach (list, (GstBufferListFunc) foreach_func4, &data);
338 fail_unless (data.iter == 2);
340 fail_unless (gst_buffer_list_get (list, 0) == data.buf[1]);
341 fail_unless_equals_int (gst_buffer_list_length (list), 1);
343 /* iterate everything, just one more buffer now */
345 gst_buffer_list_foreach (list, (GstBufferListFunc) foreach_func5, &data);
346 fail_unless (data.iter == 1);
351 /* make sure everything is fine if we exceed the pre-allocated size */
352 GST_START_TEST (test_expand_and_remove)
356 guint i, idx, num, counter = 0;
358 gst_buffer_list_unref (list);
360 arr = g_array_new (FALSE, FALSE, sizeof (guint));
362 list = gst_buffer_list_new_sized (1);
364 for (i = 0; i < 250; ++i) {
366 buf = gst_buffer_new_allocate (NULL, num, NULL);
367 gst_buffer_list_add (list, buf);
368 g_array_append_val (arr, num);
371 for (i = 0; i < 250; ++i) {
373 buf = gst_buffer_new_allocate (NULL, num, NULL);
374 idx = g_random_int_range (0, gst_buffer_list_length (list));
375 gst_buffer_list_insert (list, idx, buf);
376 g_array_insert_val (arr, idx, num);
379 /* make sure the list looks like it should */
380 fail_unless_equals_int (arr->len, gst_buffer_list_length (list));
381 for (i = 0; i < arr->len; ++i) {
382 buf = gst_buffer_list_get (list, i);
383 num = gst_buffer_get_size (buf);
384 fail_unless_equals_int (num, g_array_index (arr, guint, i));
387 for (i = 0; i < 44; ++i) {
388 num = g_random_int_range (1, 5);
389 idx = g_random_int_range (0, gst_buffer_list_length (list) - num);
390 gst_buffer_list_remove (list, idx, num);
391 g_array_remove_range (arr, idx, num);
394 /* make sure the list still looks like it should */
395 fail_unless_equals_int (arr->len, gst_buffer_list_length (list));
396 for (i = 0; i < arr->len; ++i) {
397 buf = gst_buffer_list_get (list, i);
398 num = gst_buffer_get_size (buf);
399 fail_unless_equals_int (num, g_array_index (arr, guint, i));
402 for (i = 0; i < 500; ++i) {
404 buf = gst_buffer_new_allocate (NULL, num, NULL);
405 gst_buffer_list_add (list, buf);
406 g_array_append_val (arr, num);
409 for (i = 0; i < 500; ++i) {
411 buf = gst_buffer_new_allocate (NULL, num, NULL);
412 idx = g_random_int_range (0, gst_buffer_list_length (list));
413 gst_buffer_list_insert (list, idx, buf);
414 g_array_insert_val (arr, idx, num);
417 /* make sure the list still looks like it should */
418 fail_unless_equals_int (arr->len, gst_buffer_list_length (list));
419 for (i = 0; i < arr->len; ++i) {
420 buf = gst_buffer_list_get (list, i);
421 num = gst_buffer_get_size (buf);
422 fail_unless_equals_int (num, g_array_index (arr, guint, i));
430 GST_START_TEST (test_get_writable)
432 GstBuffer *buf, *writable_buf;
434 /* buffer list is initially empty */
435 fail_unless (gst_buffer_list_length (list) == 0);
438 buf = gst_buffer_new ();
439 ASSERT_BUFFER_REFCOUNT (buf, "buf", 1);
440 gst_buffer_list_add (list, buf);
441 ASSERT_BUFFER_REFCOUNT (buf, "buf", 1); /* list takes ownership */
442 fail_unless (gst_buffer_list_length (list) == 1);
443 fail_unless (buf == gst_buffer_list_get_writable (list, 0));
444 fail_unless (buf == gst_buffer_list_get (list, 0));
446 /* extra ref to make buffer no longer writable */
447 gst_buffer_ref (buf);
448 ASSERT_BUFFER_REFCOUNT (buf, "buf", 2);
449 fail_unless (buf == gst_buffer_list_get (list, 0));
450 ASSERT_BUFFER_REFCOUNT (buf, "buf", 2);
452 /* should make a copy to make it writable */
453 writable_buf = gst_buffer_list_get_writable (list, 0);
454 fail_if (buf == writable_buf);
455 ASSERT_BUFFER_REFCOUNT (buf, "buf", 1);
456 ASSERT_BUFFER_REFCOUNT (writable_buf, "writable_buf", 1);
458 gst_buffer_unref (buf);
463 GST_START_TEST (test_calc_size)
465 gst_buffer_list_add (list, gst_buffer_new_wrapped (g_strdup ("Hello"), 5));
466 gst_buffer_list_add (list, gst_buffer_new_wrapped (g_strdup (", "), 2));
467 gst_buffer_list_add (list, gst_buffer_new_wrapped (g_strdup ("world!"), 6));
469 fail_unless_equals_int (5 + 2 + 6, gst_buffer_list_calculate_size (list));
475 gst_buffer_list_suite (void)
477 Suite *s = suite_create ("GstBufferList");
478 TCase *tc_chain = tcase_create ("general");
480 suite_add_tcase (s, tc_chain);
481 tcase_add_checked_fixture (tc_chain, setup, cleanup);
482 tcase_add_test (tc_chain, test_add_and_iterate);
483 tcase_add_test (tc_chain, test_remove);
484 tcase_add_test (tc_chain, test_make_writable);
485 tcase_add_test (tc_chain, test_copy);
486 tcase_add_test (tc_chain, test_copy_deep);
487 tcase_add_test (tc_chain, test_foreach);
488 tcase_add_test (tc_chain, test_expand_and_remove);
489 tcase_add_test (tc_chain, test_get_writable);
490 tcase_add_test (tc_chain, test_calc_size);
495 GST_CHECK_MAIN (gst_buffer_list);