tests: add GBytes memfd testcase
[platform/upstream/glib.git] / glib / tests / bytes.c
1 /*
2  * Copyright 2011 Collabora Ltd.
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * See the included COPYING file for more information.
10  */
11
12 #undef G_DISABLE_ASSERT
13 #undef G_LOG_DOMAIN
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <errno.h>
19 #include <unistd.h>
20 #include "glib.h"
21 #include "glib-unix.h"
22
23 #include "glib-linux.h"
24
25 static const gchar *NYAN = "nyannyan";
26 static const gsize N_NYAN = 8;
27
28 static void
29 test_new (void)
30 {
31   const gchar *data;
32   GBytes *bytes;
33   gsize size;
34
35   data = "test";
36   bytes = g_bytes_new (data, 4);
37   g_assert (bytes != NULL);
38   g_assert (g_bytes_get_data (bytes, &size) != data);
39   g_assert_cmpuint (size, ==, 4);
40   g_assert_cmpuint (g_bytes_get_size (bytes), ==, 4);
41   g_assert (memcmp (data, g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes)) == 0);
42
43   g_bytes_unref (bytes);
44 }
45
46 static void
47 test_new_take (void)
48 {
49   gchar *data;
50   GBytes *bytes;
51   gsize size;
52
53   data = g_strdup ("test");
54   bytes = g_bytes_new_take (data, 4);
55   g_assert (bytes != NULL);
56   g_assert (g_bytes_get_data (bytes, &size) == data);
57   g_assert_cmpuint (size, ==, 4);
58   g_assert_cmpuint (g_bytes_get_size (bytes), ==, 4);
59
60   g_bytes_unref (bytes);
61 }
62
63 static void
64 test_new_static (void)
65 {
66   const gchar *data;
67   GBytes *bytes;
68   gsize size;
69
70   data = "test";
71   bytes = g_bytes_new_static (data, 4);
72   g_assert (bytes != NULL);
73   g_assert (g_bytes_get_data (bytes, &size) == data);
74   g_assert_cmpuint (size, ==, 4);
75   g_assert_cmpuint (g_bytes_get_size (bytes), ==, 4);
76
77   g_bytes_unref (bytes);
78 }
79
80 static void
81 test_new_from_bytes (void)
82 {
83   const gchar *data = "smile and wave";
84   GBytes *bytes;
85   GBytes *sub;
86
87   bytes = g_bytes_new (data, 14);
88   sub = g_bytes_new_from_bytes (bytes, 10, 4);
89
90   g_assert (sub != NULL);
91   g_assert (g_bytes_get_data (sub, NULL) == ((gchar *)g_bytes_get_data (bytes, NULL)) + 10);
92   g_assert (g_bytes_get_size (sub) == 4);
93   g_bytes_unref (bytes);
94
95   g_assert (memcmp (g_bytes_get_data (sub, NULL), "wave", 4) == 0);
96   g_bytes_unref (sub);
97 }
98
99 static void
100 on_destroy_increment (gpointer data)
101 {
102   gint *count = data;
103   g_assert (count != NULL);
104   (*count)++;
105 }
106
107 static void
108 test_new_with_free_func (void)
109 {
110   GBytes *bytes;
111   gchar *data;
112   gint count = 0;
113   gsize size;
114
115   data = "test";
116   bytes = g_bytes_new_with_free_func (data, 4, on_destroy_increment, &count);
117   g_assert (bytes != NULL);
118   g_assert_cmpint (count, ==, 0);
119   g_assert (g_bytes_get_data (bytes, &size) == data);
120   g_assert_cmpuint (size, ==, 4);
121   g_assert_cmpuint (g_bytes_get_size (bytes), ==, 4);
122
123   g_bytes_unref (bytes);
124   g_assert_cmpuint (count, ==, 1);
125 }
126
127 static void
128 test_hash (void)
129 {
130   GBytes *bytes1;
131   GBytes *bytes2;
132   guint hash1;
133   guint hash2;
134
135   bytes1 = g_bytes_new ("blah", 4);
136   bytes2 = g_bytes_new ("blah", 4);
137
138   hash1 = g_bytes_hash (bytes1);
139   hash2 = g_bytes_hash (bytes2);
140   g_assert (hash1 == hash2);
141
142   g_bytes_unref (bytes1);
143   g_bytes_unref (bytes2);
144 }
145
146 static void
147 test_equal (void)
148 {
149   GBytes *bytes;
150   GBytes *bytes2;
151
152   bytes = g_bytes_new ("blah", 4);
153
154   bytes2 = g_bytes_new ("blah", 4);
155   g_assert (g_bytes_equal (bytes, bytes2));
156   g_assert (g_bytes_equal (bytes2, bytes));
157   g_bytes_unref (bytes2);
158
159   bytes2 = g_bytes_new ("bla", 3);
160   g_assert (!g_bytes_equal (bytes, bytes2));
161   g_assert (!g_bytes_equal (bytes2, bytes));
162   g_bytes_unref (bytes2);
163
164   bytes2 = g_bytes_new ("true", 4);
165   g_assert (!g_bytes_equal (bytes, bytes2));
166   g_assert (!g_bytes_equal (bytes2, bytes));
167   g_bytes_unref (bytes2);
168
169   g_bytes_unref (bytes);
170 }
171
172 static void
173 test_compare (void)
174 {
175   GBytes *bytes;
176   GBytes *bytes2;
177
178   bytes = g_bytes_new ("blah", 4);
179
180   bytes2 = g_bytes_new ("blah", 4);
181   g_assert_cmpint (g_bytes_compare (bytes, bytes2), ==, 0);
182   g_bytes_unref (bytes2);
183
184   bytes2 = g_bytes_new ("bla", 3);
185   g_assert_cmpint (g_bytes_compare (bytes, bytes2), >, 0);
186   g_bytes_unref (bytes2);
187
188   bytes2 = g_bytes_new ("abcd", 4);
189   g_assert_cmpint (g_bytes_compare (bytes, bytes2), >, 0);
190   g_bytes_unref (bytes2);
191
192   bytes2 = g_bytes_new ("blahblah", 8);
193   g_assert_cmpint (g_bytes_compare (bytes, bytes2), <, 0);
194   g_bytes_unref (bytes2);
195
196   bytes2 = g_bytes_new ("zyx", 3);
197   g_assert_cmpint (g_bytes_compare (bytes, bytes2), <, 0);
198   g_bytes_unref (bytes2);
199
200   bytes2 = g_bytes_new ("zyxw", 4);
201   g_assert_cmpint (g_bytes_compare (bytes, bytes2), <, 0);
202   g_bytes_unref (bytes2);
203
204   g_bytes_unref (bytes);
205 }
206
207 static void
208 test_to_data_transferred (void)
209 {
210   gconstpointer memory;
211   gpointer data;
212   gsize size;
213   GBytes *bytes;
214
215   /* Memory transferred: one reference, and allocated with g_malloc */
216   bytes = g_bytes_new_take (g_memdup (NYAN, N_NYAN), N_NYAN);
217   memory = g_bytes_get_data (bytes, NULL);
218   data = g_bytes_unref_to_data (bytes, &size);
219   g_assert (data == memory);
220   g_assert_cmpuint (size, ==, N_NYAN);
221   g_assert (memcmp (data, NYAN, N_NYAN) == 0);
222   g_free (data);
223 }
224
225 static void
226 test_to_data_two_refs (void)
227 {
228   gconstpointer memory;
229   gpointer data;
230   gsize size;
231   GBytes *bytes;
232
233   /* Memory copied: two references */
234   bytes = g_bytes_new (NYAN, N_NYAN);
235   bytes = g_bytes_ref (bytes);
236   memory = g_bytes_get_data (bytes, NULL);
237   data = g_bytes_unref_to_data (bytes, &size);
238   g_assert (data != memory);
239   g_assert_cmpuint (size, ==, N_NYAN);
240   g_assert (memcmp (data, NYAN, N_NYAN) == 0);
241   g_free (data);
242   g_assert (g_bytes_get_data (bytes, &size) == memory);
243   g_assert_cmpuint (size, ==, N_NYAN);
244   g_assert_cmpuint (g_bytes_get_size (bytes), ==, N_NYAN);
245   g_bytes_unref (bytes);
246 }
247
248 static void
249 test_to_data_non_malloc (void)
250 {
251   gpointer data;
252   gsize size;
253   GBytes *bytes;
254
255   /* Memory copied: non malloc memory */
256   bytes = g_bytes_new_static (NYAN, N_NYAN);
257   g_assert (g_bytes_get_data (bytes, NULL) == NYAN);
258   data = g_bytes_unref_to_data (bytes, &size);
259   g_assert (data != (gpointer)NYAN);
260   g_assert_cmpuint (size, ==, N_NYAN);
261   g_assert (memcmp (data, NYAN, N_NYAN) == 0);
262   g_free (data);
263 }
264
265 static void
266 test_to_array_transferred (void)
267 {
268   gconstpointer memory;
269   GByteArray *array;
270   GBytes *bytes;
271
272   /* Memory transferred: one reference, and allocated with g_malloc */
273   bytes = g_bytes_new_take (g_memdup (NYAN, N_NYAN), N_NYAN);
274   memory = g_bytes_get_data (bytes, NULL);
275   array = g_bytes_unref_to_array (bytes);
276   g_assert (array != NULL);
277   g_assert (array->data == memory);
278   g_assert_cmpuint (array->len, ==, N_NYAN);
279   g_assert (memcmp (array->data, NYAN, N_NYAN) == 0);
280   g_byte_array_unref (array);
281 }
282
283 static void
284 test_to_array_two_refs (void)
285 {
286   gconstpointer memory;
287   GByteArray *array;
288   GBytes *bytes;
289   gsize size;
290
291   /* Memory copied: two references */
292   bytes = g_bytes_new (NYAN, N_NYAN);
293   bytes = g_bytes_ref (bytes);
294   memory = g_bytes_get_data (bytes, NULL);
295   array = g_bytes_unref_to_array (bytes);
296   g_assert (array != NULL);
297   g_assert (array->data != memory);
298   g_assert_cmpuint (array->len, ==, N_NYAN);
299   g_assert (memcmp (array->data, NYAN, N_NYAN) == 0);
300   g_byte_array_unref (array);
301   g_assert (g_bytes_get_data (bytes, &size) == memory);
302   g_assert_cmpuint (size, ==, N_NYAN);
303   g_assert_cmpuint (g_bytes_get_size (bytes), ==, N_NYAN);
304   g_bytes_unref (bytes);
305 }
306
307 static void
308 test_to_array_non_malloc (void)
309 {
310   GByteArray *array;
311   GBytes *bytes;
312
313   /* Memory copied: non malloc memory */
314   bytes = g_bytes_new_static (NYAN, N_NYAN);
315   g_assert (g_bytes_get_data (bytes, NULL) == NYAN);
316   array = g_bytes_unref_to_array (bytes);
317   g_assert (array != NULL);
318   g_assert (array->data != (gpointer)NYAN);
319   g_assert_cmpuint (array->len, ==, N_NYAN);
320   g_assert (memcmp (array->data, NYAN, N_NYAN) == 0);
321   g_byte_array_unref (array);
322 }
323
324 static void
325 test_null (void)
326 {
327   GBytes *bytes;
328   gpointer data;
329   gsize size;
330
331   bytes = g_bytes_new (NULL, 0);
332
333   data = g_bytes_unref_to_data (bytes, &size);
334
335   g_assert (data == NULL);
336   g_assert (size == 0);
337 }
338
339 #ifdef GLIB_LINUX
340 static void
341 test_memfd (void)
342 {
343   GBytes *bytes;
344   gint fd;
345
346   fd = glib_linux_memfd_create ("", MFD_CLOEXEC);
347   if (fd == -1 && errno == EINVAL)
348     {
349       g_test_skip ("missing kernel memfd support");
350       return;
351     }
352
353   /* We should not be able to seal this one */
354   g_assert (!g_unix_fd_ensure_zero_copy_safe (fd));
355   close (fd);
356
357   /* but this one will work */
358   fd = glib_linux_memfd_create ("", MFD_CLOEXEC | MFD_ALLOW_SEALING);
359   bytes = g_bytes_new_take_zero_copy_fd (fd);
360   g_assert_cmpint (g_bytes_get_size (bytes), ==, 0);
361   g_bytes_unref (bytes);
362
363   /* try with real data */
364   fd = glib_linux_memfd_create ("", MFD_CLOEXEC | MFD_ALLOW_SEALING);
365   g_assert_se (write (fd, NYAN, N_NYAN) == N_NYAN);
366   bytes = g_bytes_new_take_zero_copy_fd (fd);
367   g_assert_cmpint (g_bytes_get_size (bytes), ==, N_NYAN);
368   g_assert (memcmp (g_bytes_get_data (bytes, NULL), NYAN, N_NYAN) == 0);
369   g_assert (g_bytes_get_zero_copy_fd (bytes) == fd);
370
371   /* ensure that we cannot modify the fd further */
372   g_assert_se (write (fd, NYAN, N_NYAN) == -1);
373
374   /* that's enough for now */
375   g_bytes_unref (bytes);
376 }
377 #endif
378
379 int
380 main (int argc, char *argv[])
381 {
382   g_test_init (&argc, &argv, NULL);
383
384   g_test_bug_base ("http://bugs.gnome.org/");
385
386   g_test_add_func ("/bytes/new", test_new);
387   g_test_add_func ("/bytes/new-take", test_new_take);
388   g_test_add_func ("/bytes/new-static", test_new_static);
389   g_test_add_func ("/bytes/new-with-free-func", test_new_with_free_func);
390   g_test_add_func ("/bytes/new-from-bytes", test_new_from_bytes);
391   g_test_add_func ("/bytes/hash", test_hash);
392   g_test_add_func ("/bytes/equal", test_equal);
393   g_test_add_func ("/bytes/compare", test_compare);
394   g_test_add_func ("/bytes/to-data/transfered", test_to_data_transferred);
395   g_test_add_func ("/bytes/to-data/two-refs", test_to_data_two_refs);
396   g_test_add_func ("/bytes/to-data/non-malloc", test_to_data_non_malloc);
397   g_test_add_func ("/bytes/to-array/transfered", test_to_array_transferred);
398   g_test_add_func ("/bytes/to-array/two-refs", test_to_array_two_refs);
399   g_test_add_func ("/bytes/to-array/non-malloc", test_to_array_non_malloc);
400   g_test_add_func ("/bytes/null", test_null);
401 #ifdef GLIB_LINUX
402   g_test_add_func ("/bytes/memfd", test_memfd);
403 #endif
404
405   return g_test_run ();
406 }