1 /*
2 * Copyright 2011 Collabora Ltd.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the 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
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include "glib.h"
18
19 /* Keep in sync with glib/gbytes.c */
20 struct _GBytes
21 {
22 gconstpointer data;
23 gsize size;
24 gint ref_count;
25 GDestroyNotify free_func;
26 gpointer user_data;
27 };
28
29 static const gchar *NYAN = "nyannyan";
30 static const gsize N_NYAN = 8;
31
32 static void
test_new(void)33 test_new (void)
34 {
35 const gchar *data;
36 GBytes *bytes;
37 gsize size;
38
39 data = "test";
40 bytes = g_bytes_new (data, 4);
41 g_assert (bytes != NULL);
42 g_assert (g_bytes_get_data (bytes, &size) != data);
43 g_assert_cmpuint (size, ==, 4);
44 g_assert_cmpuint (g_bytes_get_size (bytes), ==, 4);
45 g_assert_cmpmem (data, 4, g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes));
46
47 g_bytes_unref (bytes);
48 }
49
50 static void
test_new_take(void)51 test_new_take (void)
52 {
53 gchar *data;
54 GBytes *bytes;
55 gsize size;
56
57 data = g_strdup ("test");
58 bytes = g_bytes_new_take (data, 4);
59 g_assert (bytes != NULL);
60 g_assert (g_bytes_get_data (bytes, &size) == data);
61 g_assert_cmpuint (size, ==, 4);
62 g_assert_cmpuint (g_bytes_get_size (bytes), ==, 4);
63
64 g_bytes_unref (bytes);
65 }
66
67 static void
test_new_static(void)68 test_new_static (void)
69 {
70 const gchar *data;
71 GBytes *bytes;
72 gsize size;
73
74 data = "test";
75 bytes = g_bytes_new_static (data, 4);
76 g_assert (bytes != NULL);
77 g_assert (g_bytes_get_data (bytes, &size) == data);
78 g_assert_cmpuint (size, ==, 4);
79 g_assert_cmpuint (g_bytes_get_size (bytes), ==, 4);
80
81 g_bytes_unref (bytes);
82 }
83
84 static void
test_new_from_bytes(void)85 test_new_from_bytes (void)
86 {
87 const gchar *data = "smile and wave";
88 GBytes *bytes;
89 GBytes *sub;
90
91 bytes = g_bytes_new (data, 14);
92 sub = g_bytes_new_from_bytes (bytes, 10, 4);
93
94 g_assert (sub != NULL);
95 g_assert (g_bytes_get_data (sub, NULL) == ((gchar *)g_bytes_get_data (bytes, NULL)) + 10);
96 g_bytes_unref (bytes);
97
98 g_assert_cmpmem (g_bytes_get_data (sub, NULL), g_bytes_get_size (sub), "wave", 4);
99 g_bytes_unref (sub);
100 }
101
102 /* Verify that creating slices of GBytes reference the top-most bytes
103 * at the correct offset. Ensure that intermediate GBytes are not referenced.
104 */
105 static void
test_new_from_bytes_slice(void)106 test_new_from_bytes_slice (void)
107 {
108 GBytes *bytes = g_bytes_new_static ("Some stupid data", strlen ("Some stupid data") + 1);
109 GBytes *bytes1 = g_bytes_new_from_bytes (bytes, 4, 13);
110 GBytes *bytes2 = g_bytes_new_from_bytes (bytes1, 1, 12);
111 GBytes *bytes3 = g_bytes_new_from_bytes (bytes2, 0, 6);
112
113 g_assert_cmpint (bytes->ref_count, ==, 4);
114 g_assert_cmpint (bytes1->ref_count, ==, 1);
115 g_assert_cmpint (bytes2->ref_count, ==, 1);
116 g_assert_cmpint (bytes3->ref_count, ==, 1);
117
118 g_assert_null (bytes->user_data);
119 g_assert (bytes1->user_data == bytes);
120 g_assert (bytes2->user_data == bytes);
121 g_assert (bytes3->user_data == bytes);
122
123 g_assert_cmpint (17, ==, g_bytes_get_size (bytes));
124 g_assert_cmpint (13, ==, g_bytes_get_size (bytes1));
125 g_assert_cmpint (12, ==, g_bytes_get_size (bytes2));
126 g_assert_cmpint (6, ==, g_bytes_get_size (bytes3));
127
128 g_assert_cmpint (0, ==, strncmp ("Some stupid data", (gchar *)bytes->data, 17));
129 g_assert_cmpint (0, ==, strncmp (" stupid data", (gchar *)bytes1->data, 13));
130 g_assert_cmpint (0, ==, strncmp ("stupid data", (gchar *)bytes2->data, 12));
131 g_assert_cmpint (0, ==, strncmp ("stupid", (gchar *)bytes3->data, 6));
132
133 g_bytes_unref (bytes);
134 g_bytes_unref (bytes1);
135 g_bytes_unref (bytes2);
136 g_bytes_unref (bytes3);
137 }
138
139 /* Ensure that referencing an entire GBytes just returns the same bytes
140 * instance (with incremented reference count) instead of a new instance.
141 */
142 static void
test_new_from_bytes_shared_ref(void)143 test_new_from_bytes_shared_ref (void)
144 {
145 GBytes *bytes = g_bytes_new_static ("Some data", strlen ("Some data") + 1);
146 GBytes *other = g_bytes_new_from_bytes (bytes, 0, g_bytes_get_size (bytes));
147
148 g_assert (bytes == other);
149 g_assert_cmpint (bytes->ref_count, ==, 2);
150
151 g_bytes_unref (bytes);
152 g_bytes_unref (other);
153 }
154
155 static void
on_destroy_increment(gpointer data)156 on_destroy_increment (gpointer data)
157 {
158 gint *count = data;
159 g_assert (count != NULL);
160 (*count)++;
161 }
162
163 static void
test_new_with_free_func(void)164 test_new_with_free_func (void)
165 {
166 GBytes *bytes;
167 gchar *data;
168 gint count = 0;
169 gsize size;
170
171 data = "test";
172 bytes = g_bytes_new_with_free_func (data, 4, on_destroy_increment, &count);
173 g_assert (bytes != NULL);
174 g_assert_cmpint (count, ==, 0);
175 g_assert (g_bytes_get_data (bytes, &size) == data);
176 g_assert_cmpuint (size, ==, 4);
177 g_assert_cmpuint (g_bytes_get_size (bytes), ==, 4);
178
179 g_bytes_unref (bytes);
180 g_assert_cmpuint (count, ==, 1);
181 }
182
183 static void
test_hash(void)184 test_hash (void)
185 {
186 GBytes *bytes1;
187 GBytes *bytes2;
188 guint hash1;
189 guint hash2;
190
191 bytes1 = g_bytes_new ("blah", 4);
192 bytes2 = g_bytes_new ("blah", 4);
193
194 hash1 = g_bytes_hash (bytes1);
195 hash2 = g_bytes_hash (bytes2);
196 g_assert (hash1 == hash2);
197
198 g_bytes_unref (bytes1);
199 g_bytes_unref (bytes2);
200 }
201
202 static void
test_equal(void)203 test_equal (void)
204 {
205 GBytes *bytes;
206 GBytes *bytes2;
207
208 bytes = g_bytes_new ("blah", 4);
209
210 bytes2 = g_bytes_new ("blah", 4);
211 g_assert (g_bytes_equal (bytes, bytes2));
212 g_assert (g_bytes_equal (bytes2, bytes));
213 g_bytes_unref (bytes2);
214
215 bytes2 = g_bytes_new ("bla", 3);
216 g_assert (!g_bytes_equal (bytes, bytes2));
217 g_assert (!g_bytes_equal (bytes2, bytes));
218 g_bytes_unref (bytes2);
219
220 bytes2 = g_bytes_new ("true", 4);
221 g_assert (!g_bytes_equal (bytes, bytes2));
222 g_assert (!g_bytes_equal (bytes2, bytes));
223 g_bytes_unref (bytes2);
224
225 g_bytes_unref (bytes);
226 }
227
228 static void
test_compare(void)229 test_compare (void)
230 {
231 GBytes *bytes;
232 GBytes *bytes2;
233
234 bytes = g_bytes_new ("blah", 4);
235
236 bytes2 = g_bytes_new ("blah", 4);
237 g_assert_cmpint (g_bytes_compare (bytes, bytes2), ==, 0);
238 g_bytes_unref (bytes2);
239
240 bytes2 = g_bytes_new ("bla", 3);
241 g_assert_cmpint (g_bytes_compare (bytes, bytes2), >, 0);
242 g_bytes_unref (bytes2);
243
244 bytes2 = g_bytes_new ("abcd", 4);
245 g_assert_cmpint (g_bytes_compare (bytes, bytes2), >, 0);
246 g_bytes_unref (bytes2);
247
248 bytes2 = g_bytes_new ("blahblah", 8);
249 g_assert_cmpint (g_bytes_compare (bytes, bytes2), <, 0);
250 g_bytes_unref (bytes2);
251
252 bytes2 = g_bytes_new ("zyx", 3);
253 g_assert_cmpint (g_bytes_compare (bytes, bytes2), <, 0);
254 g_bytes_unref (bytes2);
255
256 bytes2 = g_bytes_new ("zyxw", 4);
257 g_assert_cmpint (g_bytes_compare (bytes, bytes2), <, 0);
258 g_bytes_unref (bytes2);
259
260 g_bytes_unref (bytes);
261 }
262
263 static void
test_to_data_transferred(void)264 test_to_data_transferred (void)
265 {
266 gconstpointer memory;
267 gpointer data;
268 gsize size;
269 GBytes *bytes;
270
271 /* Memory transferred: one reference, and allocated with g_malloc */
272 bytes = g_bytes_new (NYAN, N_NYAN);
273 memory = g_bytes_get_data (bytes, NULL);
274 data = g_bytes_unref_to_data (bytes, &size);
275 g_assert (data == memory);
276 g_assert_cmpmem (data, size, NYAN, N_NYAN);
277 g_free (data);
278 }
279
280 static void
test_to_data_two_refs(void)281 test_to_data_two_refs (void)
282 {
283 gconstpointer memory;
284 gpointer data;
285 gsize size;
286 GBytes *bytes;
287
288 /* Memory copied: two references */
289 bytes = g_bytes_new (NYAN, N_NYAN);
290 bytes = g_bytes_ref (bytes);
291 memory = g_bytes_get_data (bytes, NULL);
292 data = g_bytes_unref_to_data (bytes, &size);
293 g_assert (data != memory);
294 g_assert_cmpmem (data, size, NYAN, N_NYAN);
295 g_free (data);
296 g_assert (g_bytes_get_data (bytes, &size) == memory);
297 g_assert_cmpuint (size, ==, N_NYAN);
298 g_assert_cmpuint (g_bytes_get_size (bytes), ==, N_NYAN);
299 g_bytes_unref (bytes);
300 }
301
302 static void
test_to_data_non_malloc(void)303 test_to_data_non_malloc (void)
304 {
305 gpointer data;
306 gsize size;
307 GBytes *bytes;
308
309 /* Memory copied: non malloc memory */
310 bytes = g_bytes_new_static (NYAN, N_NYAN);
311 g_assert (g_bytes_get_data (bytes, NULL) == NYAN);
312 data = g_bytes_unref_to_data (bytes, &size);
313 g_assert (data != (gpointer)NYAN);
314 g_assert_cmpmem (data, size, NYAN, N_NYAN);
315 g_free (data);
316 }
317
318 static void
test_to_array_transferred(void)319 test_to_array_transferred (void)
320 {
321 gconstpointer memory;
322 GByteArray *array;
323 GBytes *bytes;
324
325 /* Memory transferred: one reference, and allocated with g_malloc */
326 bytes = g_bytes_new (NYAN, N_NYAN);
327 memory = g_bytes_get_data (bytes, NULL);
328 array = g_bytes_unref_to_array (bytes);
329 g_assert (array != NULL);
330 g_assert (array->data == memory);
331 g_assert_cmpmem (array->data, array->len, NYAN, N_NYAN);
332 g_byte_array_unref (array);
333 }
334
335 static void
test_to_array_transferred_oversize(void)336 test_to_array_transferred_oversize (void)
337 {
338 g_test_message ("g_bytes_unref_to_array() can only take GBytes up to "
339 "G_MAXUINT in length; test that longer ones are rejected");
340
341 if (sizeof (guint) >= sizeof (gsize))
342 {
343 g_test_skip ("Skipping test as guint is not smaller than gsize");
344 }
345 else if (g_test_undefined ())
346 {
347 GByteArray *array = NULL;
348 GBytes *bytes = NULL;
349 gpointer data = g_memdup2 (NYAN, N_NYAN);
350 gsize len = ((gsize) G_MAXUINT) + 1;
351
352 bytes = g_bytes_new_take (data, len);
353 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
354 "g_byte_array_new_take: assertion 'len <= G_MAXUINT' failed");
355 array = g_bytes_unref_to_array (g_steal_pointer (&bytes));
356 g_test_assert_expected_messages ();
357 g_assert_null (array);
358
359 g_free (data);
360 }
361 else
362 {
363 g_test_skip ("Skipping test as testing undefined behaviour is disabled");
364 }
365 }
366
367 static void
test_to_array_two_refs(void)368 test_to_array_two_refs (void)
369 {
370 gconstpointer memory;
371 GByteArray *array;
372 GBytes *bytes;
373 gsize size;
374
375 /* Memory copied: two references */
376 bytes = g_bytes_new (NYAN, N_NYAN);
377 bytes = g_bytes_ref (bytes);
378 memory = g_bytes_get_data (bytes, NULL);
379 array = g_bytes_unref_to_array (bytes);
380 g_assert (array != NULL);
381 g_assert (array->data != memory);
382 g_assert_cmpmem (array->data, array->len, NYAN, N_NYAN);
383 g_byte_array_unref (array);
384 g_assert (g_bytes_get_data (bytes, &size) == memory);
385 g_assert_cmpuint (size, ==, N_NYAN);
386 g_assert_cmpuint (g_bytes_get_size (bytes), ==, N_NYAN);
387 g_bytes_unref (bytes);
388 }
389
390 static void
test_to_array_non_malloc(void)391 test_to_array_non_malloc (void)
392 {
393 GByteArray *array;
394 GBytes *bytes;
395
396 /* Memory copied: non malloc memory */
397 bytes = g_bytes_new_static (NYAN, N_NYAN);
398 g_assert (g_bytes_get_data (bytes, NULL) == NYAN);
399 array = g_bytes_unref_to_array (bytes);
400 g_assert (array != NULL);
401 g_assert (array->data != (gpointer)NYAN);
402 g_assert_cmpmem (array->data, array->len, NYAN, N_NYAN);
403 g_byte_array_unref (array);
404 }
405
406 static void
test_null(void)407 test_null (void)
408 {
409 GBytes *bytes;
410 gpointer data;
411 gsize size;
412
413 bytes = g_bytes_new (NULL, 0);
414
415 data = g_bytes_unref_to_data (bytes, &size);
416
417 g_assert (data == NULL);
418 g_assert (size == 0);
419 }
420
421 int
main(int argc,char * argv[])422 main (int argc, char *argv[])
423 {
424 g_test_init (&argc, &argv, NULL);
425
426 g_test_bug_base ("https://bugzilla.gnome.org/");
427
428 g_test_add_func ("/bytes/new", test_new);
429 g_test_add_func ("/bytes/new-take", test_new_take);
430 g_test_add_func ("/bytes/new-static", test_new_static);
431 g_test_add_func ("/bytes/new-with-free-func", test_new_with_free_func);
432 g_test_add_func ("/bytes/new-from-bytes", test_new_from_bytes);
433 g_test_add_func ("/bytes/new-from-bytes-slice", test_new_from_bytes_slice);
434 g_test_add_func ("/bytes/new-from-bytes-shared-ref", test_new_from_bytes_shared_ref);
435 g_test_add_func ("/bytes/hash", test_hash);
436 g_test_add_func ("/bytes/equal", test_equal);
437 g_test_add_func ("/bytes/compare", test_compare);
438 g_test_add_func ("/bytes/to-data/transferred", test_to_data_transferred);
439 g_test_add_func ("/bytes/to-data/two-refs", test_to_data_two_refs);
440 g_test_add_func ("/bytes/to-data/non-malloc", test_to_data_non_malloc);
441 g_test_add_func ("/bytes/to-array/transferred", test_to_array_transferred);
442 g_test_add_func ("/bytes/to-array/transferred/oversize", test_to_array_transferred_oversize);
443 g_test_add_func ("/bytes/to-array/two-refs", test_to_array_two_refs);
444 g_test_add_func ("/bytes/to-array/non-malloc", test_to_array_non_malloc);
445 g_test_add_func ("/bytes/null", test_null);
446
447 return g_test_run ();
448 }
449