1 /* GLib testing framework examples and tests
2 * Copyright (C) 2008 Red Hat, Inc.
3 * Authors: Tomas Bzatek <tbzatek@redhat.com>
4 *
5 * SPDX-License-Identifier: LicenseRef-old-glib-tests
6 *
7 * This work is provided "as is"; redistribution and modification
8 * in whole or in part, in any medium, physical or electronic is
9 * permitted without restriction.
10 *
11 * This work is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 *
15 * In no event shall the authors or contributors be liable for any
16 * direct, indirect, incidental, special, exemplary, or consequential
17 * damages (including, but not limited to, procurement of substitute
18 * goods or services; loss of use, data, or profits; or business
19 * interruption) however caused and on any theory of liability, whether
20 * in contract, strict liability, or tort (including negligence or
21 * otherwise) arising in any way out of the use of this software, even
22 * if advised of the possibility of such damage.
23 */
24
25 #include <glib/glib.h>
26 #include <gio/gio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #define MAX_LINES 0xFFF
31 #define MAX_LINES_BUFF 0xFFFFFF
32 #define MAX_BYTES_BINARY 0x100
33
34 static void
35 test_basic (void)
36 {
37 GOutputStream *stream;
38 GOutputStream *base_stream;
39 gpointer data;
40 gint val;
41
42 data = g_malloc0 (MAX_LINES_BUFF);
43
44 /* initialize objects */
45 base_stream = g_memory_output_stream_new (data, MAX_LINES_BUFF, NULL, NULL);
46 stream = G_OUTPUT_STREAM (g_data_output_stream_new (base_stream));
47
48 g_object_get (stream, "byte-order", &val, NULL);
49 g_assert_cmpint (val, ==, G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN);
50 g_object_set (stream, "byte-order", G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN, NULL);
51 g_assert_cmpint (g_data_output_stream_get_byte_order (G_DATA_OUTPUT_STREAM (stream)), ==, G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN);
52
53 g_object_unref (stream);
54 g_object_unref (base_stream);
55 g_free (data);
56 }
57
58 static void
59 test_read_lines (GDataStreamNewlineType newline_type)
60 {
61 GOutputStream *stream;
62 GOutputStream *base_stream;
63 GError *error = NULL;
64 gpointer data;
65 char *lines;
66 int size;
67 int i;
68
69 #define TEST_STRING "some_text"
70
71 const char* endl[4] = {"\n", "\r", "\r\n", "\n"};
72
73
74 data = g_malloc0 (MAX_LINES_BUFF);
75 lines = g_malloc0 ((strlen (TEST_STRING) + strlen (endl[newline_type])) * MAX_LINES + 1);
76
77 /* initialize objects */
78 base_stream = g_memory_output_stream_new (data, MAX_LINES_BUFF, NULL, NULL);
79 stream = G_OUTPUT_STREAM (g_data_output_stream_new (base_stream));
80
81
82 /* fill data */
83 for (i = 0; i < MAX_LINES; i++)
84 {
85 gboolean res;
86 char *s = g_strconcat (TEST_STRING, endl[newline_type], NULL);
87 res = g_data_output_stream_put_string (G_DATA_OUTPUT_STREAM (stream), s, NULL, &error);
88 g_stpcpy ((char*)(lines + i*strlen(s)), s);
89 g_assert_no_error (error);
90 g_assert (res == TRUE);
91 g_free (s);
92 }
93
94 /* Byte order testing */
95 g_data_output_stream_set_byte_order (G_DATA_OUTPUT_STREAM (stream), G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN);
96 g_assert_cmpint (g_data_output_stream_get_byte_order (G_DATA_OUTPUT_STREAM (stream)), ==, G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN);
97 g_data_output_stream_set_byte_order (G_DATA_OUTPUT_STREAM (stream), G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN);
98 g_assert_cmpint (g_data_output_stream_get_byte_order (G_DATA_OUTPUT_STREAM (stream)), ==, G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN);
99
100 /* compare data */
101 size = strlen (data);
102 g_assert_cmpint (size, <, MAX_LINES_BUFF);
103 g_assert_cmpstr ((char*)data, ==, lines);
104
105 g_object_unref (base_stream);
106 g_object_unref (stream);
107 g_free (data);
108 g_free (lines);
109 }
110
111 static void
112 test_read_lines_LF (void)
113 {
114 test_read_lines (G_DATA_STREAM_NEWLINE_TYPE_LF);
115 }
116
117 static void
118 test_read_lines_CR (void)
119 {
120 test_read_lines (G_DATA_STREAM_NEWLINE_TYPE_CR);
121 }
122
123 static void
124 test_read_lines_CR_LF (void)
125 {
126 test_read_lines (G_DATA_STREAM_NEWLINE_TYPE_CR_LF);
127 }
128
129 enum TestDataType {
130 TEST_DATA_BYTE = 0,
131 TEST_DATA_INT16,
132 TEST_DATA_UINT16,
133 TEST_DATA_INT32,
134 TEST_DATA_UINT32,
135 TEST_DATA_INT64,
136 TEST_DATA_UINT64
137 };
138
139 static void
140 test_data_array (guchar *buffer, gsize len,
141 enum TestDataType data_type, GDataStreamByteOrder byte_order)
142 {
143 GOutputStream *stream;
144 GOutputStream *base_stream;
145 guchar *stream_data;
146
147 GError *error = NULL;
148 guint pos;
149 GDataStreamByteOrder native;
150 gboolean swap;
151 gboolean res;
152
153 /* create objects */
154 stream_data = g_malloc0 (len);
155 base_stream = g_memory_output_stream_new (stream_data, len, NULL, NULL);
156 stream = G_OUTPUT_STREAM (g_data_output_stream_new (base_stream));
157 g_data_output_stream_set_byte_order (G_DATA_OUTPUT_STREAM (stream), byte_order);
158
159 /* Set flag to swap bytes if needed */
160 native = (G_BYTE_ORDER == G_BIG_ENDIAN) ? G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN : G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
161 swap = (byte_order != G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN) && (byte_order != native);
162
163 /* set len to length of buffer cast to actual type */
164 switch (data_type)
165 {
166 case TEST_DATA_BYTE:
167 break;
168 case TEST_DATA_INT16:
169 case TEST_DATA_UINT16:
170 g_assert_cmpint (len % 2, ==, 0);
171 G_GNUC_FALLTHROUGH;
172 case TEST_DATA_INT32:
173 case TEST_DATA_UINT32:
174 g_assert_cmpint (len % 4, ==, 0);
175 G_GNUC_FALLTHROUGH;
176 case TEST_DATA_INT64:
177 case TEST_DATA_UINT64:
178 g_assert_cmpint (len % 8, ==, 0);
179 len /= 8;
180 break;
181 default:
182 g_assert_not_reached ();
183 break;
184 }
185
186 /* Write data to the file */
187 for (pos = 0; pos < len; pos++)
188 {
189 switch (data_type)
190 {
191 case TEST_DATA_BYTE:
192 res = g_data_output_stream_put_byte (G_DATA_OUTPUT_STREAM (stream), buffer[pos], NULL, &error);
193 break;
194 case TEST_DATA_INT16:
195 res = g_data_output_stream_put_int16 (G_DATA_OUTPUT_STREAM (stream), ((gint16 *) buffer)[pos], NULL, &error);
196 break;
197 case TEST_DATA_UINT16:
198 res = g_data_output_stream_put_uint16 (G_DATA_OUTPUT_STREAM (stream), ((guint16 *) buffer)[pos], NULL, &error);
199 break;
200 case TEST_DATA_INT32:
201 res = g_data_output_stream_put_int32 (G_DATA_OUTPUT_STREAM (stream), ((gint32 *) buffer)[pos], NULL, &error);
202 break;
203 case TEST_DATA_UINT32:
204 res = g_data_output_stream_put_uint32 (G_DATA_OUTPUT_STREAM (stream), ((guint32 *) buffer)[pos], NULL, &error);
205 break;
206 case TEST_DATA_INT64:
207 res = g_data_output_stream_put_int64 (G_DATA_OUTPUT_STREAM (stream), ((gint64 *) buffer)[pos], NULL, &error);
208 break;
209 case TEST_DATA_UINT64:
210 res = g_data_output_stream_put_uint64 (G_DATA_OUTPUT_STREAM (stream), ((guint64 *) buffer)[pos], NULL, &error);
211 break;
212 default:
213 g_assert_not_reached ();
214 break;
215 }
216 g_assert_no_error (error);
217 g_assert_cmpint (res, ==, TRUE);
218 }
219
220 /* Compare data back */
221 for (pos = 0; pos < len; pos++)
222 {
223 switch (data_type)
224 {
225 case TEST_DATA_BYTE:
226 /* swapping unnecessary */
227 g_assert_cmpint (buffer[pos], ==, stream_data[pos]);
228 break;
229 case TEST_DATA_UINT16:
230 if (swap)
231 g_assert_cmpint (GUINT16_SWAP_LE_BE (((guint16 *) buffer)[pos]), ==, ((guint16 *) stream_data)[pos]);
232 else
233 g_assert_cmpint (((guint16 *) buffer)[pos], ==, ((guint16 *) stream_data)[pos]);
234 break;
235 case TEST_DATA_INT16:
236 if (swap)
237 g_assert_cmpint ((gint16) GUINT16_SWAP_LE_BE (((gint16 *) buffer)[pos]), ==, ((gint16 *) stream_data)[pos]);
238 else
239 g_assert_cmpint (((gint16 *) buffer)[pos], ==, ((gint16 *) stream_data)[pos]);
240 break;
241 case TEST_DATA_UINT32:
242 if (swap)
243 g_assert_cmpint (GUINT32_SWAP_LE_BE (((guint32 *) buffer)[pos]), ==, ((guint32 *) stream_data)[pos]);
244 else
245 g_assert_cmpint (((guint32 *) buffer)[pos], ==, ((guint32 *) stream_data)[pos]);
246 break;
247 case TEST_DATA_INT32:
248 if (swap)
249 g_assert_cmpint ((gint32) GUINT32_SWAP_LE_BE (((gint32 *) buffer)[pos]), ==, ((gint32 *) stream_data)[pos]);
250 else
251 g_assert_cmpint (((gint32 *) buffer)[pos], ==, ((gint32 *) stream_data)[pos]);
252 break;
253 case TEST_DATA_UINT64:
254 if (swap)
255 g_assert_cmpint (GUINT64_SWAP_LE_BE (((guint64 *) buffer)[pos]), ==, ((guint64 *) stream_data)[pos]);
256 else
257 g_assert_cmpint (((guint64 *) buffer)[pos], ==, ((guint64 *) stream_data)[pos]);
258 break;
259 case TEST_DATA_INT64:
260 if (swap)
261 g_assert_cmpint ((gint64) GUINT64_SWAP_LE_BE (((gint64 *) buffer)[pos]), ==, ((gint64 *) stream_data)[pos]);
262 else
263 g_assert_cmpint (((gint64 *) buffer)[pos], ==, ((gint64 *) stream_data)[pos]);
264 break;
265 default:
266 g_assert_not_reached ();
267 break;
268 }
269 }
270
271 g_object_unref (base_stream);
272 g_object_unref (stream);
273 g_free (stream_data);
274 }
275
276 static void
277 test_read_int (void)
278 {
279 GRand *randomizer;
280 gpointer buffer;
281 int i;
282
283 randomizer = g_rand_new ();
284 buffer = g_malloc0(MAX_BYTES_BINARY);
285
286 /* Fill in some random data */
287 for (i = 0; i < MAX_BYTES_BINARY; i++)
288 {
289 guchar x = 0;
290 while (! x) x = (guchar)g_rand_int (randomizer);
291 *(guchar*)((guchar*)buffer + sizeof (guchar) * i) = x;
292 }
293
294 for (i = 0; i < 3; i++)
295 {
296 int j;
297 for (j = 0; j <= TEST_DATA_UINT64; j++)
298 test_data_array (buffer, MAX_BYTES_BINARY, j, i);
299 }
300
301 g_rand_free (randomizer);
302 g_free (buffer);
303 }
304
305 static void
306 test_seek (void)
307 {
308 GDataOutputStream *stream;
309 GMemoryOutputStream *base_stream;
310 GSeekable *seekable;
311 GError *error;
312 guchar *stream_data;
313 gsize len;
314 gboolean res;
315
316 len = 8;
317
318 /* create objects */
319 stream_data = g_malloc0 (len);
320 base_stream = G_MEMORY_OUTPUT_STREAM (g_memory_output_stream_new (stream_data, len, NULL, NULL));
321 stream = g_data_output_stream_new (G_OUTPUT_STREAM (base_stream));
322 g_data_output_stream_set_byte_order (stream, G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN);
323 seekable = G_SEEKABLE (stream);
324 g_assert (!g_seekable_can_truncate (seekable));
325 error = NULL;
326
327 /* Write */
328 g_assert_cmpint (g_seekable_tell (seekable), ==, 0);
329 res = g_data_output_stream_put_uint16 (stream, 0x0123, NULL, &error);
330 g_assert_no_error (error);
331 g_assert (res);
332 g_data_output_stream_put_uint16 (stream, 0x4567, NULL, NULL);
333 g_assert_cmpint (g_seekable_tell (seekable), ==, 4);
334 g_assert_cmpint (stream_data[0], ==, 0x01);
335 g_assert_cmpint (stream_data[1], ==, 0x23);
336 g_assert_cmpint (stream_data[2], ==, 0x45);
337 g_assert_cmpint (stream_data[3], ==, 0x67);
338 g_assert_cmpint (g_memory_output_stream_get_data_size (base_stream), ==, 4);
339
340 /* Forward relative seek */
341 res = g_seekable_seek (seekable, 2, G_SEEK_CUR, NULL, &error);
342 g_assert_no_error (error);
343 g_assert (res);
344 g_assert_cmpint (g_seekable_tell (seekable), ==, 6);
345 g_assert_cmpint (g_memory_output_stream_get_data_size (base_stream), ==, 4);
346 res = g_data_output_stream_put_uint16 (stream, 0x89AB, NULL, &error);
347 g_assert (res);
348 g_assert_cmpint (g_seekable_tell (seekable), ==, 8);
349 g_assert_cmpint (g_memory_output_stream_get_data_size (base_stream), ==, 8);
350 g_assert_cmpint (stream_data[0], ==, 0x01);
351 g_assert_cmpint (stream_data[1], ==, 0x23);
352 g_assert_cmpint (stream_data[2], ==, 0x45);
353 g_assert_cmpint (stream_data[3], ==, 0x67);
354 g_assert_cmpint (stream_data[4], ==, 0x00);
355 g_assert_cmpint (stream_data[5], ==, 0x00);
356 g_assert_cmpint (stream_data[6], ==, 0x89);
357 g_assert_cmpint (stream_data[7], ==, 0xAB);
358
359 /* Backward relative seek */
360 res = g_seekable_seek (seekable, -3, G_SEEK_CUR, NULL, &error);
361 g_assert_no_error (error);
362 g_assert (res);
363 g_assert_cmpint (g_seekable_tell (seekable), ==, 5);
364 g_assert_cmpint (g_memory_output_stream_get_data_size (base_stream), ==, 8);
365 res = g_data_output_stream_put_uint16 (stream, 0xCDEF, NULL, &error);
366 g_assert_no_error (error);
367 g_assert (res);
368 g_assert_cmpint (g_seekable_tell (seekable), ==, 7);
369 g_assert_cmpint (g_memory_output_stream_get_data_size (base_stream), ==, 8);
370 g_assert_cmpint (stream_data[0], ==, 0x01);
371 g_assert_cmpint (stream_data[1], ==, 0x23);
372 g_assert_cmpint (stream_data[2], ==, 0x45);
373 g_assert_cmpint (stream_data[3], ==, 0x67);
374 g_assert_cmpint (stream_data[4], ==, 0x00);
375 g_assert_cmpint (stream_data[5], ==, 0xCD);
376 g_assert_cmpint (stream_data[6], ==, 0xEF);
377 g_assert_cmpint (stream_data[7], ==, 0xAB);
378
379 /* From start */
380 res = g_seekable_seek (seekable, 4, G_SEEK_SET, NULL, &error);
381 g_assert_no_error (error);
382 g_assert (res);
383 g_assert_cmpint (g_seekable_tell (seekable), ==, 4);
384 g_assert_cmpint (g_memory_output_stream_get_data_size (base_stream), ==, 8);
385 res = g_data_output_stream_put_uint16 (stream, 0xFEDC, NULL, &error);
386 g_assert_no_error (error);
387 g_assert (res);
388 g_assert_cmpint (g_seekable_tell (seekable), ==, 6);
389 g_assert_cmpint (g_memory_output_stream_get_data_size (base_stream), ==, 8);
390 g_assert_cmpint (stream_data[0], ==, 0x01);
391 g_assert_cmpint (stream_data[1], ==, 0x23);
392 g_assert_cmpint (stream_data[2], ==, 0x45);
393 g_assert_cmpint (stream_data[3], ==, 0x67);
394 g_assert_cmpint (stream_data[4], ==, 0xFE);
395 g_assert_cmpint (stream_data[5], ==, 0xDC);
396 g_assert_cmpint (stream_data[6], ==, 0xEF);
397 g_assert_cmpint (stream_data[7], ==, 0xAB);
398
399 /* From end */
400 res = g_seekable_seek (seekable, -4, G_SEEK_END, NULL, &error);
401 g_assert_no_error (error);
402 g_assert (res);
403 g_assert_cmpint (g_seekable_tell (seekable), ==, 4);
404 g_assert_cmpint (g_memory_output_stream_get_data_size (base_stream), ==, 8);
405 res = g_data_output_stream_put_uint16 (stream, 0xBA87, NULL, &error);
406 g_assert_no_error (error);
407 g_assert (res);
408 g_assert_cmpint (g_seekable_tell (seekable), ==, 6);
409 g_assert_cmpint (g_memory_output_stream_get_data_size (base_stream), ==, 8);
410 g_assert_cmpint (stream_data[0], ==, 0x01);
411 g_assert_cmpint (stream_data[1], ==, 0x23);
412 g_assert_cmpint (stream_data[2], ==, 0x45);
413 g_assert_cmpint (stream_data[3], ==, 0x67);
414 g_assert_cmpint (stream_data[4], ==, 0xBA);
415 g_assert_cmpint (stream_data[5], ==, 0x87);
416 g_assert_cmpint (stream_data[6], ==, 0xEF);
417 g_assert_cmpint (stream_data[7], ==, 0xAB);
418
419 g_object_unref (stream);
420 g_object_unref (base_stream);
421 g_free (stream_data);
422 }
423
424 static void
425 test_truncate (void)
426 {
427 GDataOutputStream *stream;
428 GMemoryOutputStream *base_stream;
429 GSeekable *seekable;
430 GError *error;
431 guchar *stream_data;
432 gsize len;
433 gboolean res;
434
435 len = 8;
436
437 /* Create objects */
438 stream_data = g_malloc0 (len);
439 base_stream = G_MEMORY_OUTPUT_STREAM (g_memory_output_stream_new (stream_data, len, g_realloc, g_free));
440 stream = g_data_output_stream_new (G_OUTPUT_STREAM (base_stream));
441 g_data_output_stream_set_byte_order (stream, G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN);
442 seekable = G_SEEKABLE (stream);
443 error = NULL;
444 g_assert (g_seekable_can_truncate (seekable));
445
446 /* Write */
447 g_assert_cmpint (g_memory_output_stream_get_size (base_stream), ==, len);
448 g_assert_cmpint (g_memory_output_stream_get_data_size (base_stream), ==, 0);
449 res = g_data_output_stream_put_uint16 (stream, 0x0123, NULL, &error);
450 g_assert_no_error (error);
451 g_assert (res);
452 res = g_data_output_stream_put_uint16 (stream, 0x4567, NULL, NULL);
453 g_assert_no_error (error);
454 g_assert (res);
455 g_assert_cmpint (g_memory_output_stream_get_size (base_stream), ==, len);
456 g_assert_cmpint (g_memory_output_stream_get_data_size (base_stream), ==, 4);
457 stream_data = g_memory_output_stream_get_data (base_stream);
458 g_assert_cmpint (stream_data[0], ==, 0x01);
459 g_assert_cmpint (stream_data[1], ==, 0x23);
460 g_assert_cmpint (stream_data[2], ==, 0x45);
461 g_assert_cmpint (stream_data[3], ==, 0x67);
462
463 /* Truncate at position */
464 res = g_seekable_truncate (seekable, 4, NULL, &error);
465 g_assert_no_error (error);
466 g_assert (res);
467 g_assert_cmpint (g_memory_output_stream_get_size (base_stream), ==, 4);
468 g_assert_cmpint (g_memory_output_stream_get_data_size (base_stream), ==, 4);
469 stream_data = g_memory_output_stream_get_data (base_stream);
470 g_assert_cmpint (stream_data[0], ==, 0x01);
471 g_assert_cmpint (stream_data[1], ==, 0x23);
472 g_assert_cmpint (stream_data[2], ==, 0x45);
473 g_assert_cmpint (stream_data[3], ==, 0x67);
474
475 /* Truncate beyond position */
476 res = g_seekable_truncate (seekable, 6, NULL, &error);
477 g_assert_no_error (error);
478 g_assert (res);
479 g_assert_cmpint (g_memory_output_stream_get_size (base_stream), ==, 6);
480 g_assert_cmpint (g_memory_output_stream_get_data_size (base_stream), ==, 6);
481 stream_data = g_memory_output_stream_get_data (base_stream);
482 g_assert_cmpint (stream_data[0], ==, 0x01);
483 g_assert_cmpint (stream_data[1], ==, 0x23);
484 g_assert_cmpint (stream_data[2], ==, 0x45);
485 g_assert_cmpint (stream_data[3], ==, 0x67);
486
487 /* Truncate before position */
488 res = g_seekable_truncate (seekable, 2, NULL, &error);
489 g_assert_no_error (error);
490 g_assert (res);
491 g_assert_cmpint (g_memory_output_stream_get_size (base_stream), ==, 2);
492 g_assert_cmpint (g_memory_output_stream_get_data_size (base_stream), ==, 2);
493 stream_data = g_memory_output_stream_get_data (base_stream);
494 g_assert_cmpint (stream_data[0], ==, 0x01);
495 g_assert_cmpint (stream_data[1], ==, 0x23);
496
497 g_object_unref (stream);
498 g_object_unref (base_stream);
499 }
500
501 int
502 main (int argc,
503 char *argv[])
504 {
505 g_test_init (&argc, &argv, NULL);
506
507 g_test_add_func ("/data-output-stream/basic", test_basic);
508 g_test_add_func ("/data-output-stream/write-lines-LF", test_read_lines_LF);
509 g_test_add_func ("/data-output-stream/write-lines-CR", test_read_lines_CR);
510 g_test_add_func ("/data-output-stream/write-lines-CR-LF", test_read_lines_CR_LF);
511 g_test_add_func ("/data-output-stream/write-int", test_read_int);
512 g_test_add_func ("/data-output-stream/seek", test_seek);
513 g_test_add_func ("/data-output-stream/truncate", test_truncate);
514
515 return g_test_run();
516 }