bufferlist: add gst_buffer_list_calculate_size()
[platform/upstream/gstreamer.git] / tests / check / gst / gstbufferlist.c
1 /* GStreamer
2  *
3  * unit test for GstBufferList
4  *
5  * Copyright (C) 2009 Axis Communications <dev-gstreamer at axis dot com>
6  * @author Jonas Holmberg <jonas dot holmberg at axis dot com>
7  *
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.
12  *
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.
17  *
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.
22  */
23
24 #include <gst/check/gstcheck.h>
25 #include <gst/gstbufferlist.h>
26 #include <string.h>
27
28 static GstBufferList *list;
29
30 static void
31 setup (void)
32 {
33   list = gst_buffer_list_new ();
34 }
35
36 static void
37 cleanup (void)
38 {
39   gst_buffer_list_unref (list);
40   list = NULL;
41 }
42
43 GST_START_TEST (test_add_and_iterate)
44 {
45   GstBuffer *buf1;
46   GstBuffer *buf2;
47
48   /* buffer list is initially empty */
49   fail_unless (gst_buffer_list_length (list) == 0);
50
51   ASSERT_CRITICAL (gst_buffer_list_insert (list, 0, NULL));
52   ASSERT_CRITICAL (gst_buffer_list_insert (NULL, 0, NULL));
53
54   buf1 = gst_buffer_new ();
55
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);
67 }
68
69 GST_END_TEST;
70
71 GST_START_TEST (test_remove)
72 {
73   GstBuffer *buf;
74
75   /* buffer list is initially empty */
76   fail_unless (gst_buffer_list_length (list) == 0);
77
78   buf = gst_buffer_new ();
79
80   /* add our own ref so it stays alive after removal from the list */
81   buf = gst_buffer_ref (buf);
82
83   /* add a buffer */
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);
94 }
95
96 GST_END_TEST;
97
98 GST_START_TEST (test_make_writable)
99 {
100   GstBufferList *wlist;
101   GstBuffer *buf1;
102   GstBuffer *buf2;
103   GstBuffer *buf3;
104   GstBuffer *buf;
105
106   /* add buffers to list */
107   buf1 = gst_buffer_new_allocate (NULL, 1, NULL);
108   gst_buffer_list_add (list, buf1);
109
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));
113
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);
126
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);
135   /* check 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);
145   /* check wlist */
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 */
157 }
158
159 GST_END_TEST;
160
161 GST_START_TEST (test_copy)
162 {
163   GstBufferList *list_copy;
164   GstBuffer *buf1;
165   GstBuffer *buf2;
166   GstBuffer *buf3;
167   GstBuffer *buf;
168
169   /* add buffers to the list */
170   buf1 = gst_buffer_new_allocate (NULL, 1, NULL);
171   gst_buffer_list_add (list, buf1);
172
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));
176
177   /* make a copy */
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);
192
193   gst_buffer_list_unref (list_copy);
194 }
195
196 GST_END_TEST;
197
198 GST_START_TEST (test_copy_deep)
199 {
200   GstBufferList *list_copy;
201   GstMapInfo info, sinfo;
202   GstBuffer *buf1;
203   GstBuffer *buf2;
204   GstBuffer *buf_copy;
205
206   /* add buffers to the list */
207   buf1 = gst_buffer_new_allocate (NULL, 1, NULL);
208   gst_buffer_list_add (list, buf1);
209
210   buf2 = gst_buffer_new_allocate (NULL, 2, NULL);
211   gst_buffer_list_add (list, buf2);
212
213   /* make a copy */
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);
219
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);
225
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);
230
231   fail_unless (gst_buffer_map (buf2, &info, GST_MAP_READ));
232   fail_unless (gst_buffer_map (buf_copy, &sinfo, GST_MAP_READ));
233
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);
238
239   gst_buffer_unmap (buf_copy, &sinfo);
240   gst_buffer_unmap (buf2, &info);
241
242   gst_buffer_list_unref (list_copy);
243 }
244
245 GST_END_TEST;
246
247 typedef struct
248 {
249   GstBuffer *buf[2];
250   guint iter;
251 } ForeachData;
252
253 static gboolean
254 foreach_func1 (GstBuffer ** buffer, guint idx, ForeachData * data)
255 {
256   fail_unless (buffer != NULL);
257   fail_unless (GST_IS_BUFFER (*buffer));
258   fail_unless (*buffer == data->buf[idx]);
259
260   data->iter++;
261
262   return TRUE;
263 }
264
265 static gboolean
266 foreach_func3 (GstBuffer ** buffer, guint idx, ForeachData * data)
267 {
268   fail_unless (idx == 0);
269   fail_unless (buffer != NULL);
270   fail_unless (GST_IS_BUFFER (*buffer));
271   fail_unless (*buffer == data->buf[idx]);
272
273   data->iter++;
274
275   return FALSE;
276 }
277
278 static gboolean
279 foreach_func4 (GstBuffer ** buffer, guint idx, ForeachData * data)
280 {
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]);
285
286   /* remove first */
287   if (*buffer == data->buf[0]) {
288     gst_buffer_unref (*buffer);
289     *buffer = NULL;
290   }
291
292   data->iter++;
293
294   return TRUE;
295 }
296
297 static gboolean
298 foreach_func5 (GstBuffer ** buffer, guint idx, ForeachData * data)
299 {
300   fail_unless (buffer != NULL);
301   fail_unless (GST_IS_BUFFER (*buffer));
302
303   data->iter++;
304
305   return TRUE;
306 }
307
308 GST_START_TEST (test_foreach)
309 {
310   GstBuffer *buf2, *buf3;
311   ForeachData data;
312
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]);
316
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]);
321
322   fail_unless (gst_buffer_list_get (list, 0) == data.buf[0]);
323   fail_unless (gst_buffer_list_get (list, 1) == data.buf[1]);
324
325   /* iterate everything */
326   data.iter = 0;
327   gst_buffer_list_foreach (list, (GstBufferListFunc) foreach_func1, &data);
328   fail_unless (data.iter == 2);
329
330   /* iterate only the first buffer */
331   data.iter = 0;
332   gst_buffer_list_foreach (list, (GstBufferListFunc) foreach_func3, &data);
333   fail_unless (data.iter == 1);
334
335   /* remove the first buffer */
336   data.iter = 0;
337   gst_buffer_list_foreach (list, (GstBufferListFunc) foreach_func4, &data);
338   fail_unless (data.iter == 2);
339
340   fail_unless (gst_buffer_list_get (list, 0) == data.buf[1]);
341   fail_unless_equals_int (gst_buffer_list_length (list), 1);
342
343   /* iterate everything, just one more buffer now */
344   data.iter = 0;
345   gst_buffer_list_foreach (list, (GstBufferListFunc) foreach_func5, &data);
346   fail_unless (data.iter == 1);
347 }
348
349 GST_END_TEST;
350
351 /* make sure everything is fine if we exceed the pre-allocated size */
352 GST_START_TEST (test_expand_and_remove)
353 {
354   GArray *arr;
355   GstBuffer *buf;
356   guint i, idx, num, counter = 0;
357
358   gst_buffer_list_unref (list);
359
360   arr = g_array_new (FALSE, FALSE, sizeof (guint));
361
362   list = gst_buffer_list_new_sized (1);
363
364   for (i = 0; i < 250; ++i) {
365     num = ++counter;
366     buf = gst_buffer_new_allocate (NULL, num, NULL);
367     gst_buffer_list_add (list, buf);
368     g_array_append_val (arr, num);
369   }
370
371   for (i = 0; i < 250; ++i) {
372     num = ++counter;
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);
377   }
378
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));
385   }
386
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);
392   }
393
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));
400   }
401
402   for (i = 0; i < 500; ++i) {
403     num = ++counter;
404     buf = gst_buffer_new_allocate (NULL, num, NULL);
405     gst_buffer_list_add (list, buf);
406     g_array_append_val (arr, num);
407   }
408
409   for (i = 0; i < 500; ++i) {
410     num = ++counter;
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);
415   }
416
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));
423   }
424
425   g_array_unref (arr);
426 }
427
428 GST_END_TEST;
429
430 GST_START_TEST (test_get_writable)
431 {
432   GstBuffer *buf, *writable_buf;
433
434   /* buffer list is initially empty */
435   fail_unless (gst_buffer_list_length (list) == 0);
436
437   /* Add 2 buffers */
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));
445
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);
451
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);
457
458   gst_buffer_unref (buf);
459 }
460
461 GST_END_TEST;
462
463 GST_START_TEST (test_calc_size)
464 {
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));
468
469   fail_unless_equals_int (5 + 2 + 6, gst_buffer_list_calculate_size (list));
470 }
471
472 GST_END_TEST;
473
474 static Suite *
475 gst_buffer_list_suite (void)
476 {
477   Suite *s = suite_create ("GstBufferList");
478   TCase *tc_chain = tcase_create ("general");
479
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);
491
492   return s;
493 }
494
495 GST_CHECK_MAIN (gst_buffer_list);