memory improvements
[platform/upstream/gstreamer.git] / tests / check / gst / gstmemory.c
1 /* GStreamer
2  *
3  * unit test for GstMemory
4  *
5  * Copyright (C) <2012> Wim Taymans <wim.taymans at gmail.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26
27 #ifdef HAVE_VALGRIND_H
28 # include <valgrind/valgrind.h>
29 #else
30 # define RUNNING_ON_VALGRIND FALSE
31 #endif
32
33 #include <gst/check/gstcheck.h>
34
35 GST_START_TEST (test_submemory)
36 {
37   GstMemory *memory, *sub;
38   gsize size, maxsize, ssize;
39   guint8 *data, *sdata;
40
41   memory = gst_allocator_alloc (NULL, 4, 0);
42
43   /* check sizes, memory starts out empty */
44   data = gst_memory_map (memory, &size, &maxsize, GST_MAP_WRITE);
45   fail_unless (size == 4, "memory has wrong size");
46   fail_unless (maxsize >= 4, "memory has wrong size");
47   memset (data, 0, 4);
48   gst_memory_unmap (memory);
49
50   data = gst_memory_map (memory, &size, NULL, GST_MAP_READ);
51
52   sub = gst_memory_share (memory, 1, 2);
53   fail_if (sub == NULL, "share of memory returned NULL");
54
55   sdata = gst_memory_map (sub, &ssize, NULL, GST_MAP_READ);
56   fail_unless (ssize == 2, "submemory has wrong size");
57   fail_unless (memcmp (data + 1, sdata, 2) == 0,
58       "submemory contains the wrong data");
59   ASSERT_MEMORY_REFCOUNT (sub, "submemory", 1);
60   gst_memory_unmap (sub);
61   gst_memory_unref (sub);
62
63   /* create a submemory of size 0 */
64   sub = gst_memory_share (memory, 1, 0);
65   fail_if (sub == NULL, "share memory returned NULL");
66   sdata = gst_memory_map (sub, &ssize, NULL, GST_MAP_READ);
67   fail_unless (ssize == 0, "submemory has wrong size");
68   fail_unless (memcmp (data + 1, sdata, 0) == 0,
69       "submemory contains the wrong data");
70   ASSERT_MEMORY_REFCOUNT (sub, "submemory", 1);
71   gst_memory_unmap (sub);
72   gst_memory_unref (sub);
73
74   /* test if metadata is coppied, not a complete memory copy so only the
75    * timestamp and offset fields are copied. */
76   sub = gst_memory_share (memory, 0, 1);
77   fail_if (sub == NULL, "share of memory returned NULL");
78   fail_unless (gst_memory_get_sizes (sub, NULL, NULL) == 1,
79       "submemory has wrong size");
80   gst_memory_unref (sub);
81
82   /* test if metadata is coppied, a complete memory is copied so all the timing
83    * fields should be copied. */
84   sub = gst_memory_share (memory, 0, 4);
85   fail_if (sub == NULL, "share of memory returned NULL");
86   fail_unless (gst_memory_get_sizes (sub, NULL, NULL) == 4,
87       "submemory has wrong size");
88
89   /* clean up */
90   gst_memory_unref (sub);
91
92   gst_memory_unmap (memory);
93   gst_memory_unref (memory);
94 }
95
96 GST_END_TEST;
97
98 GST_START_TEST (test_is_span)
99 {
100   GstMemory *memory, *sub1, *sub2;
101
102   memory = gst_allocator_alloc (NULL, 4, 0);
103
104   sub1 = gst_memory_share (memory, 0, 2);
105   fail_if (sub1 == NULL, "share of memory returned NULL");
106
107   sub2 = gst_memory_share (memory, 2, 2);
108   fail_if (sub2 == NULL, "share of memory returned NULL");
109
110   fail_if (gst_memory_is_span (memory, sub2, NULL) == TRUE,
111       "a parent memory can't be span");
112
113   fail_if (gst_memory_is_span (sub1, memory, NULL) == TRUE,
114       "a parent memory can't be span");
115
116   fail_if (gst_memory_is_span (sub1, sub2, NULL) == FALSE,
117       "two submemorys next to each other should be span");
118
119   /* clean up */
120   gst_memory_unref (sub1);
121   gst_memory_unref (sub2);
122   gst_memory_unref (memory);
123 }
124
125 GST_END_TEST;
126
127 static const char ro_memory[] = "abcdefghijklmnopqrstuvwxyz";
128
129 static GstMemory *
130 create_read_only_memory (void)
131 {
132   GstMemory *mem;
133
134   /* assign some read-only data to the new memory */
135   mem = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
136       (gpointer) ro_memory, NULL, sizeof (ro_memory), 0, sizeof (ro_memory));
137   fail_if (gst_memory_is_writable (mem));
138
139   return mem;
140 }
141
142 GST_START_TEST (test_writable)
143 {
144   GstMemory *mem, *mem2;
145   guint8 *data;
146   gsize size;
147
148   /* create read-only memory and try to write */
149   mem = create_read_only_memory ();
150
151   ASSERT_CRITICAL (gst_memory_map (mem, &size, NULL, GST_MAP_WRITE));
152   fail_if (gst_memory_is_writable (mem));
153
154   mem2 = gst_memory_copy (mem, 0, -1);
155   fail_if (gst_memory_is_writable (mem));
156   fail_unless (gst_memory_is_writable (mem2));
157
158   data = gst_memory_map (mem2, &size, NULL, GST_MAP_WRITE);
159   data[4] = 'a';
160   gst_memory_unmap (mem2);
161
162   gst_memory_ref (mem2);
163   ASSERT_CRITICAL (gst_memory_map (mem, &size, NULL, GST_MAP_WRITE));
164   gst_memory_unref (mem2);
165
166   data = gst_memory_map (mem2, &size, NULL, GST_MAP_WRITE);
167   data[4] = 'a';
168   gst_memory_unmap (mem2);
169   gst_memory_unref (mem2);
170
171   gst_memory_unref (mem);
172 }
173
174 GST_END_TEST;
175
176 GST_START_TEST (test_submemory_writable)
177 {
178   GstMemory *mem, *sub_mem;
179   gsize size;
180
181   /* create sub-memory of read-only memory and try to write */
182   mem = create_read_only_memory ();
183
184   sub_mem = gst_memory_share (mem, 0, 8);
185   fail_if (gst_memory_is_writable (sub_mem));
186
187   ASSERT_CRITICAL (gst_memory_map (mem, &size, NULL, GST_MAP_WRITE));
188   ASSERT_CRITICAL (gst_memory_map (sub_mem, &size, NULL, GST_MAP_WRITE));
189
190   gst_memory_unref (sub_mem);
191   gst_memory_unref (mem);
192 }
193
194 GST_END_TEST;
195
196 GST_START_TEST (test_copy)
197 {
198   GstMemory *memory, *copy;
199   gsize size, ssize;
200
201   memory = gst_allocator_alloc (NULL, 4, 0);
202   ASSERT_MEMORY_REFCOUNT (memory, "memory", 1);
203
204   copy = gst_memory_copy (memory, 0, -1);
205   ASSERT_MEMORY_REFCOUNT (memory, "memory", 1);
206   ASSERT_MEMORY_REFCOUNT (copy, "copy", 1);
207   /* memorys are copied and must point to different memory */
208   fail_if (memory == copy);
209
210   gst_memory_map (memory, &size, NULL, GST_MAP_READ);
211   gst_memory_map (copy, &ssize, NULL, GST_MAP_READ);
212
213   /* NOTE that data is refcounted */
214   fail_unless (size == ssize);
215
216   gst_memory_unmap (copy);
217   gst_memory_unmap (memory);
218
219   gst_memory_unref (copy);
220   gst_memory_unref (memory);
221
222   memory = gst_allocator_alloc (NULL, 0, 0);
223   gst_memory_map (memory, &size, NULL, GST_MAP_READ);
224   fail_unless (size == 0);
225   gst_memory_unmap (memory);
226
227   /* copying a 0-sized memory should not crash */
228   copy = gst_memory_copy (memory, 0, -1);
229   gst_memory_map (copy, &size, NULL, GST_MAP_READ);
230   fail_unless (size == 0);
231   gst_memory_unmap (copy);
232
233   gst_memory_unref (copy);
234   gst_memory_unref (memory);
235 }
236
237 GST_END_TEST;
238
239 GST_START_TEST (test_try_new_and_alloc)
240 {
241   GstMemory *mem;
242   gsize size;
243   guint8 *data;
244
245   mem = gst_allocator_alloc (NULL, 0, 0);
246   fail_unless (mem != NULL);
247   data = gst_memory_map (mem, &size, NULL, GST_MAP_READ);
248   fail_unless (size == 0);
249   gst_memory_unmap (mem);
250   gst_memory_unref (mem);
251
252   /* normal alloc should still work */
253   mem = gst_allocator_alloc (NULL, 640 * 480 * 4, 0);
254   fail_unless (mem != NULL);
255   data = gst_memory_map (mem, &size, NULL, GST_MAP_WRITE);
256   fail_unless (data != NULL);
257   fail_unless (size == (640 * 480 * 4));
258   data[640 * 479 * 4 + 479] = 0xff;
259   gst_memory_unmap (mem);
260
261   gst_memory_unref (mem);
262
263 #if 0
264   /* Disabled this part of the test, because it happily succeeds on 64-bit
265    * machines that have enough memory+swap, because the address space is large
266    * enough. There's not really any way to test the failure case except by
267    * allocating chunks of memory until it fails, which would suck. */
268
269   /* now this better fail (don't run in valgrind, it will abort
270    * or warn when passing silly arguments to malloc) */
271   if (!RUNNING_ON_VALGRIND) {
272     mem = gst_allocator_alloc (NULL, (guint) - 1, 0);
273     fail_unless (mem == NULL);
274   }
275 #endif
276 }
277
278 GST_END_TEST;
279
280 GST_START_TEST (test_resize)
281 {
282   GstMemory *mem;
283   gsize maxalloc;
284   gsize size, maxsize, offset;
285
286   /* one memory block */
287   mem = gst_allocator_alloc (NULL, 100, 0);
288
289   size = gst_memory_get_sizes (mem, &offset, &maxalloc);
290   fail_unless (size == 100);
291   fail_unless (offset == 0);
292   fail_unless (maxalloc >= 100);
293
294   ASSERT_CRITICAL (gst_memory_resize (mem, 200, 50));
295   ASSERT_CRITICAL (gst_memory_resize (mem, 0, 150));
296   ASSERT_CRITICAL (gst_memory_resize (mem, 1, maxalloc));
297   ASSERT_CRITICAL (gst_memory_resize (mem, maxalloc, 1));
298
299   /* this does nothing */
300   gst_memory_resize (mem, 0, 100);
301
302   /* nothing should have changed */
303   size = gst_memory_get_sizes (mem, &offset, &maxsize);
304   fail_unless (size == 100);
305   fail_unless (offset == 0);
306   fail_unless (maxsize == maxalloc);
307
308   gst_memory_resize (mem, 0, 50);
309   size = gst_memory_get_sizes (mem, &offset, &maxsize);
310   fail_unless (size == 50);
311   fail_unless (offset == 0);
312   fail_unless (maxsize == maxalloc);
313
314   gst_memory_resize (mem, 0, 100);
315   size = gst_memory_get_sizes (mem, &offset, &maxsize);
316   fail_unless (size == 100);
317   fail_unless (offset == 0);
318   fail_unless (maxsize == maxalloc);
319
320   gst_memory_resize (mem, 1, 99);
321   size = gst_memory_get_sizes (mem, &offset, &maxsize);
322   fail_unless (size == 99);
323   fail_unless (offset == 1);
324   fail_unless (maxsize == maxalloc);
325
326   ASSERT_CRITICAL (gst_memory_resize (mem, 1, maxalloc - 1));
327
328   gst_memory_resize (mem, 0, 99);
329   size = gst_memory_get_sizes (mem, &offset, &maxsize);
330   fail_unless (size == 99);
331   fail_unless (offset == 1);
332   fail_unless (maxsize == maxalloc);
333
334   gst_memory_resize (mem, -1, 100);
335   size = gst_memory_get_sizes (mem, &offset, &maxsize);
336   fail_unless (size == 100);
337   fail_unless (offset == 0);
338   fail_unless (maxsize == maxalloc);
339
340   /* can't set offset below 0 */
341   ASSERT_CRITICAL (gst_memory_resize (mem, -1, 100));
342
343   gst_memory_resize (mem, 50, 40);
344   size = gst_memory_get_sizes (mem, &offset, &maxsize);
345   fail_unless (size == 40);
346   fail_unless (offset == 50);
347   fail_unless (maxsize == maxalloc);
348
349   gst_memory_resize (mem, -50, 100);
350   size = gst_memory_get_sizes (mem, &offset, &maxsize);
351   fail_unless (size == 100);
352   fail_unless (offset == 0);
353   fail_unless (maxsize == maxalloc);
354
355   gst_memory_resize (mem, 0, 0);
356   size = gst_memory_get_sizes (mem, &offset, &maxsize);
357   fail_unless (size == 0);
358   fail_unless (offset == 0);
359   fail_unless (maxsize == maxalloc);
360
361   gst_memory_resize (mem, 0, 100);
362   size = gst_memory_get_sizes (mem, &offset, &maxsize);
363   fail_unless (size == 100);
364   fail_unless (offset == 0);
365   fail_unless (maxsize == maxalloc);
366
367   gst_memory_resize (mem, 0, 100);
368   size = gst_memory_get_sizes (mem, &offset, &maxsize);
369   fail_unless (size == 100);
370   fail_unless (offset == 0);
371   fail_unless (maxsize == maxalloc);
372
373   gst_memory_unref (mem);
374 }
375
376 GST_END_TEST;
377
378 GST_START_TEST (test_map)
379 {
380   GstMemory *mem;
381   gsize maxalloc;
382   gsize size, maxsize, offset;
383   gpointer data;
384
385   /* one memory block */
386   mem = gst_allocator_alloc (NULL, 100, 0);
387
388   size = gst_memory_get_sizes (mem, &offset, &maxalloc);
389   fail_unless (size == 100);
390   fail_unless (offset == 0);
391   fail_unless (maxalloc >= 100);
392
393   /* see if simply mapping works */
394   data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
395   fail_unless (data != NULL);
396   fail_unless (size == 100);
397   fail_unless (maxsize == maxalloc);
398
399   gst_memory_unmap (mem);
400   gst_memory_unref (mem);
401 }
402
403 GST_END_TEST;
404
405 GST_START_TEST (test_map_nested)
406 {
407   GstMemory *mem;
408   gsize size1, maxsize1, size2, maxsize2;
409   gpointer data1, data2;
410
411   mem = gst_allocator_alloc (NULL, 100, 0);
412
413   /* nested mapping */
414   data1 = gst_memory_map (mem, &size1, &maxsize1, GST_MAP_READ);
415   fail_unless (data1 != NULL);
416   fail_unless (size1 == 100);
417
418   data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READ);
419   fail_unless (data2 == data1);
420   fail_unless (size2 == 100);
421
422   /* unmap */
423   gst_memory_unmap (mem);
424   gst_memory_unmap (mem);
425
426   data1 = gst_memory_map (mem, &size1, &maxsize1, GST_MAP_READ);
427   /* not allowed */
428   ASSERT_CRITICAL (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_WRITE));
429   ASSERT_CRITICAL (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READWRITE));
430   data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READ);
431   gst_memory_unmap (mem);
432   gst_memory_unmap (mem);
433   fail_unless (mem->state == 0);
434
435   data1 = gst_memory_map (mem, &size1, &maxsize1, GST_MAP_WRITE);
436   /* not allowed */
437   ASSERT_CRITICAL (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READ));
438   ASSERT_CRITICAL (gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READWRITE));
439   data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_WRITE);
440   gst_memory_unmap (mem);
441   gst_memory_unmap (mem);
442   /* nothing was mapped */
443   ASSERT_CRITICAL (gst_memory_unmap (mem));
444
445   data1 = gst_memory_map (mem, &size1, &maxsize1, GST_MAP_READWRITE);
446   data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_READ);
447   gst_memory_unmap (mem);
448   data2 = gst_memory_map (mem, &size2, &maxsize2, GST_MAP_WRITE);
449   gst_memory_unmap (mem);
450   gst_memory_unmap (mem);
451   /* nothing was mapped */
452   ASSERT_CRITICAL (gst_memory_unmap (mem));
453
454   gst_memory_unref (mem);
455 }
456
457 GST_END_TEST;
458
459 GST_START_TEST (test_map_resize)
460 {
461   GstMemory *mem;
462   gsize size, maxsize, maxalloc, offset;
463   gpointer data;
464
465   mem = gst_allocator_alloc (NULL, 100, 0);
466
467   /* do mapping */
468   data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
469   fail_unless (data != NULL);
470   fail_unless (size == 100);
471
472   /* resize the buffer */
473   gst_memory_resize (mem, 1, size - 1);
474   size = gst_memory_get_sizes (mem, &offset, &maxalloc);
475   fail_unless (size == 99);
476   fail_unless (offset == 1);
477   fail_unless (maxalloc >= 100);
478   gst_memory_unmap (mem);
479
480   size = gst_memory_get_sizes (mem, &offset, &maxalloc);
481   fail_unless (size == 99);
482   fail_unless (offset == 1);
483   fail_unless (maxalloc >= 100);
484
485   data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
486   fail_unless (data != NULL);
487   fail_unless (size == 99);
488   fail_unless (offset == 1);
489   fail_unless (maxsize >= 100);
490   gst_memory_unmap (mem);
491
492   /* and larger */
493   data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
494   gst_memory_resize (mem, -1, 100);
495   gst_memory_unmap (mem);
496
497   size = gst_memory_get_sizes (mem, &offset, &maxalloc);
498   fail_unless (size == 100);
499   fail_unless (offset == 0);
500   fail_unless (maxalloc >= 100);
501
502   data = gst_memory_map (mem, &size, &maxsize, GST_MAP_READ);
503   gst_memory_unmap (mem);
504   gst_memory_unref (mem);
505 }
506
507 GST_END_TEST;
508
509
510 static Suite *
511 gst_memory_suite (void)
512 {
513   Suite *s = suite_create ("GstMemory");
514   TCase *tc_chain = tcase_create ("general");
515
516   suite_add_tcase (s, tc_chain);
517   tcase_add_test (tc_chain, test_submemory);
518   tcase_add_test (tc_chain, test_submemory_writable);
519   tcase_add_test (tc_chain, test_writable);
520   tcase_add_test (tc_chain, test_is_span);
521   tcase_add_test (tc_chain, test_copy);
522   tcase_add_test (tc_chain, test_try_new_and_alloc);
523   tcase_add_test (tc_chain, test_resize);
524   tcase_add_test (tc_chain, test_map);
525   tcase_add_test (tc_chain, test_map_nested);
526   tcase_add_test (tc_chain, test_map_resize);
527
528   return s;
529 }
530
531 GST_CHECK_MAIN (gst_memory);