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 */
20struct _GBytes
21{
22 gconstpointer data;
23 gsize size;
24 gint ref_count;
25 GDestroyNotify free_func;
26 gpointer user_data;
27};
28
29static const gchar *NYAN = "nyannyan";
30static const gsize N_NYAN = 8;
31
32static void
33test_new (void)
34{
35 const gchar *data;
36 GBytes *bytes;
37 gsize size;
38
39 data = "test";
40 bytes = g_bytes_new (data, size: 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
50static void
51test_new_take (void)
52{
53 gchar *data;
54 GBytes *bytes;
55 gsize size;
56
57 data = g_strdup (str: "test");
58 bytes = g_bytes_new_take (data, size: 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
67static void
68test_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, size: 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
84static void
85test_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, size: 14);
92 sub = g_bytes_new_from_bytes (bytes, offset: 10, length: 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 (bytes: 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 */
105static void
106test_new_from_bytes_slice (void)
107{
108 GBytes *bytes = g_bytes_new_static (data: "Some stupid data", size: strlen (s: "Some stupid data") + 1);
109 GBytes *bytes1 = g_bytes_new_from_bytes (bytes, offset: 4, length: 13);
110 GBytes *bytes2 = g_bytes_new_from_bytes (bytes: bytes1, offset: 1, length: 12);
111 GBytes *bytes3 = g_bytes_new_from_bytes (bytes: bytes2, offset: 0, length: 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 (bytes: bytes1);
135 g_bytes_unref (bytes: bytes2);
136 g_bytes_unref (bytes: 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 */
142static void
143test_new_from_bytes_shared_ref (void)
144{
145 GBytes *bytes = g_bytes_new_static (data: "Some data", size: strlen (s: "Some data") + 1);
146 GBytes *other = g_bytes_new_from_bytes (bytes, offset: 0, length: 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 (bytes: other);
153}
154
155static void
156on_destroy_increment (gpointer data)
157{
158 gint *count = data;
159 g_assert (count != NULL);
160 (*count)++;
161}
162
163static void
164test_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, size: 4, free_func: on_destroy_increment, user_data: &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
183static void
184test_hash (void)
185{
186 GBytes *bytes1;
187 GBytes *bytes2;
188 guint hash1;
189 guint hash2;
190
191 bytes1 = g_bytes_new (data: "blah", size: 4);
192 bytes2 = g_bytes_new (data: "blah", size: 4);
193
194 hash1 = g_bytes_hash (bytes: bytes1);
195 hash2 = g_bytes_hash (bytes: bytes2);
196 g_assert (hash1 == hash2);
197
198 g_bytes_unref (bytes: bytes1);
199 g_bytes_unref (bytes: bytes2);
200}
201
202static void
203test_equal (void)
204{
205 GBytes *bytes;
206 GBytes *bytes2;
207
208 bytes = g_bytes_new (data: "blah", size: 4);
209
210 bytes2 = g_bytes_new (data: "blah", size: 4);
211 g_assert (g_bytes_equal (bytes, bytes2));
212 g_assert (g_bytes_equal (bytes2, bytes));
213 g_bytes_unref (bytes: bytes2);
214
215 bytes2 = g_bytes_new (data: "bla", size: 3);
216 g_assert (!g_bytes_equal (bytes, bytes2));
217 g_assert (!g_bytes_equal (bytes2, bytes));
218 g_bytes_unref (bytes: bytes2);
219
220 bytes2 = g_bytes_new (data: "true", size: 4);
221 g_assert (!g_bytes_equal (bytes, bytes2));
222 g_assert (!g_bytes_equal (bytes2, bytes));
223 g_bytes_unref (bytes: bytes2);
224
225 g_bytes_unref (bytes);
226}
227
228static void
229test_compare (void)
230{
231 GBytes *bytes;
232 GBytes *bytes2;
233
234 bytes = g_bytes_new (data: "blah", size: 4);
235
236 bytes2 = g_bytes_new (data: "blah", size: 4);
237 g_assert_cmpint (g_bytes_compare (bytes, bytes2), ==, 0);
238 g_bytes_unref (bytes: bytes2);
239
240 bytes2 = g_bytes_new (data: "bla", size: 3);
241 g_assert_cmpint (g_bytes_compare (bytes, bytes2), >, 0);
242 g_bytes_unref (bytes: bytes2);
243
244 bytes2 = g_bytes_new (data: "abcd", size: 4);
245 g_assert_cmpint (g_bytes_compare (bytes, bytes2), >, 0);
246 g_bytes_unref (bytes: bytes2);
247
248 bytes2 = g_bytes_new (data: "blahblah", size: 8);
249 g_assert_cmpint (g_bytes_compare (bytes, bytes2), <, 0);
250 g_bytes_unref (bytes: bytes2);
251
252 bytes2 = g_bytes_new (data: "zyx", size: 3);
253 g_assert_cmpint (g_bytes_compare (bytes, bytes2), <, 0);
254 g_bytes_unref (bytes: bytes2);
255
256 bytes2 = g_bytes_new (data: "zyxw", size: 4);
257 g_assert_cmpint (g_bytes_compare (bytes, bytes2), <, 0);
258 g_bytes_unref (bytes: bytes2);
259
260 g_bytes_unref (bytes);
261}
262
263static void
264test_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 (data: NYAN, size: N_NYAN);
273 memory = g_bytes_get_data (bytes, NULL);
274 data = g_bytes_unref_to_data (bytes, size: &size);
275 g_assert (data == memory);
276 g_assert_cmpmem (data, size, NYAN, N_NYAN);
277 g_free (mem: data);
278}
279
280static void
281test_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 (data: NYAN, size: 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: &size);
293 g_assert (data != memory);
294 g_assert_cmpmem (data, size, NYAN, N_NYAN);
295 g_free (mem: 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
302static void
303test_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 (data: NYAN, size: N_NYAN);
311 g_assert (g_bytes_get_data (bytes, NULL) == NYAN);
312 data = g_bytes_unref_to_data (bytes, size: &size);
313 g_assert (data != (gpointer)NYAN);
314 g_assert_cmpmem (data, size, NYAN, N_NYAN);
315 g_free (mem: data);
316}
317
318static void
319test_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 (data: NYAN, size: 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
335static void
336test_to_array_transferred_oversize (void)
337{
338 g_test_message (format: "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 (msg: "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 (mem: NYAN, byte_size: N_NYAN);
350 gsize len = ((gsize) G_MAXUINT) + 1;
351
352 bytes = g_bytes_new_take (data, size: len);
353 g_test_expect_message (G_LOG_DOMAIN, log_level: G_LOG_LEVEL_CRITICAL,
354 pattern: "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 (mem: data);
360 }
361 else
362 {
363 g_test_skip (msg: "Skipping test as testing undefined behaviour is disabled");
364 }
365}
366
367static void
368test_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 (data: NYAN, size: 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
390static void
391test_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 (data: NYAN, size: 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
406static void
407test_null (void)
408{
409 GBytes *bytes;
410 gpointer data;
411 gsize size;
412
413 bytes = g_bytes_new (NULL, size: 0);
414
415 data = g_bytes_unref_to_data (bytes, size: &size);
416
417 g_assert (data == NULL);
418 g_assert (size == 0);
419}
420
421int
422main (int argc, char *argv[])
423{
424 g_test_init (argc: &argc, argv: &argv, NULL);
425
426 g_test_bug_base (uri_pattern: "https://bugzilla.gnome.org/");
427
428 g_test_add_func (testpath: "/bytes/new", test_func: test_new);
429 g_test_add_func (testpath: "/bytes/new-take", test_func: test_new_take);
430 g_test_add_func (testpath: "/bytes/new-static", test_func: test_new_static);
431 g_test_add_func (testpath: "/bytes/new-with-free-func", test_func: test_new_with_free_func);
432 g_test_add_func (testpath: "/bytes/new-from-bytes", test_func: test_new_from_bytes);
433 g_test_add_func (testpath: "/bytes/new-from-bytes-slice", test_func: test_new_from_bytes_slice);
434 g_test_add_func (testpath: "/bytes/new-from-bytes-shared-ref", test_func: test_new_from_bytes_shared_ref);
435 g_test_add_func (testpath: "/bytes/hash", test_func: test_hash);
436 g_test_add_func (testpath: "/bytes/equal", test_func: test_equal);
437 g_test_add_func (testpath: "/bytes/compare", test_func: test_compare);
438 g_test_add_func (testpath: "/bytes/to-data/transferred", test_func: test_to_data_transferred);
439 g_test_add_func (testpath: "/bytes/to-data/two-refs", test_func: test_to_data_two_refs);
440 g_test_add_func (testpath: "/bytes/to-data/non-malloc", test_func: test_to_data_non_malloc);
441 g_test_add_func (testpath: "/bytes/to-array/transferred", test_func: test_to_array_transferred);
442 g_test_add_func (testpath: "/bytes/to-array/transferred/oversize", test_func: test_to_array_transferred_oversize);
443 g_test_add_func (testpath: "/bytes/to-array/two-refs", test_func: test_to_array_two_refs);
444 g_test_add_func (testpath: "/bytes/to-array/non-malloc", test_func: test_to_array_non_malloc);
445 g_test_add_func (testpath: "/bytes/null", test_func: test_null);
446
447 return g_test_run ();
448}
449

source code of gtk/subprojects/glib/glib/tests/bytes.c