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