1 | /* GLIB - Library of useful routines for C programming |
2 | * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald |
3 | * |
4 | * This library 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 | * This library is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * Lesser General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU Lesser General Public |
15 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. |
16 | */ |
17 | |
18 | /* |
19 | * Modified by the GLib Team and others 1997-2000. See the AUTHORS |
20 | * file for a list of people on the GLib Team. See the ChangeLog |
21 | * files for a list of changes. These files are distributed with |
22 | * GLib at ftp://ftp.gtk.org/pub/gtk/. |
23 | */ |
24 | |
25 | #undef GLIB_COMPILATION |
26 | |
27 | #include <stdio.h> |
28 | #include <string.h> |
29 | #include <errno.h> |
30 | |
31 | #include "glib.h" |
32 | #include <glib/gstdio.h> |
33 | |
34 | #include <stdlib.h> |
35 | |
36 | #ifdef G_OS_UNIX |
37 | #include <unistd.h> |
38 | #endif |
39 | |
40 | #ifdef G_OS_WIN32 |
41 | #include <io.h> /* For read(), write() etc */ |
42 | #endif |
43 | |
44 | |
45 | #define GLIB_TEST_STRING "el dorado " |
46 | #define GLIB_TEST_STRING_5 "el do" |
47 | |
48 | |
49 | /* --- variables --- */ |
50 | static gint test_nums[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; |
51 | static gint more_nums[10] = { 8, 9, 7, 0, 3, 2, 5, 1, 4, 6}; |
52 | |
53 | /* --- functions --- */ |
54 | static gint |
55 | my_list_compare_one (gconstpointer a, gconstpointer b) |
56 | { |
57 | gint one = *((const gint*)a); |
58 | gint two = *((const gint*)b); |
59 | return one-two; |
60 | } |
61 | |
62 | static gint |
63 | my_list_compare_two (gconstpointer a, gconstpointer b) |
64 | { |
65 | gint one = *((const gint*)a); |
66 | gint two = *((const gint*)b); |
67 | return two-one; |
68 | } |
69 | |
70 | /* static void |
71 | my_list_print (gpointer a, gpointer b) |
72 | { |
73 | gint three = *((gint*)a); |
74 | g_printerr ("%d", three); |
75 | }; */ |
76 | |
77 | static void |
78 | glist_test (void) |
79 | { |
80 | GList *list = NULL; |
81 | guint i; |
82 | |
83 | for (i = 0; i < 10; i++) |
84 | list = g_list_append (list, data: &test_nums[i]); |
85 | list = g_list_reverse (list); |
86 | |
87 | for (i = 0; i < 10; i++) |
88 | { |
89 | GList *t = g_list_nth (list, n: i); |
90 | if (*((gint*) t->data) != (9 - i)) |
91 | g_error ("Regular insert failed" ); |
92 | } |
93 | |
94 | for (i = 0; i < 10; i++) |
95 | if (g_list_position (list, llink: g_list_nth (list, n: i)) != i) |
96 | g_error ("g_list_position does not seem to be the inverse of g_list_nth" ); |
97 | |
98 | g_list_free (list); |
99 | list = NULL; |
100 | |
101 | for (i = 0; i < 10; i++) |
102 | list = g_list_insert_sorted (list, data: &more_nums[i], func: my_list_compare_one); |
103 | |
104 | /* |
105 | g_printerr ("\n"); |
106 | g_list_foreach (list, my_list_print, NULL); |
107 | */ |
108 | |
109 | for (i = 0; i < 10; i++) |
110 | { |
111 | GList *t = g_list_nth (list, n: i); |
112 | if (*((gint*) t->data) != i) |
113 | g_error ("Sorted insert failed" ); |
114 | } |
115 | |
116 | g_list_free (list); |
117 | list = NULL; |
118 | |
119 | for (i = 0; i < 10; i++) |
120 | list = g_list_insert_sorted (list, data: &more_nums[i], func: my_list_compare_two); |
121 | |
122 | /* |
123 | g_printerr ("\n"); |
124 | g_list_foreach (list, my_list_print, NULL); |
125 | */ |
126 | |
127 | for (i = 0; i < 10; i++) |
128 | { |
129 | GList *t = g_list_nth (list, n: i); |
130 | if (*((gint*) t->data) != (9 - i)) |
131 | g_error ("Sorted insert failed" ); |
132 | } |
133 | |
134 | g_list_free (list); |
135 | list = NULL; |
136 | |
137 | for (i = 0; i < 10; i++) |
138 | list = g_list_prepend (list, data: &more_nums[i]); |
139 | |
140 | list = g_list_sort (list, compare_func: my_list_compare_two); |
141 | |
142 | /* |
143 | g_printerr ("\n"); |
144 | g_list_foreach (list, my_list_print, NULL); |
145 | */ |
146 | |
147 | for (i = 0; i < 10; i++) |
148 | { |
149 | GList *t = g_list_nth (list, n: i); |
150 | if (*((gint*) t->data) != (9 - i)) |
151 | g_error ("Merge sort failed" ); |
152 | } |
153 | |
154 | g_list_free (list); |
155 | } |
156 | |
157 | static void |
158 | gslist_test (void) |
159 | { |
160 | GSList *slist = NULL; |
161 | guint i; |
162 | |
163 | for (i = 0; i < 10; i++) |
164 | slist = g_slist_append (list: slist, data: &test_nums[i]); |
165 | slist = g_slist_reverse (list: slist); |
166 | |
167 | for (i = 0; i < 10; i++) |
168 | { |
169 | GSList *st = g_slist_nth (list: slist, n: i); |
170 | if (*((gint*) st->data) != (9 - i)) |
171 | g_error ("failed" ); |
172 | } |
173 | |
174 | g_slist_free (list: slist); |
175 | slist = NULL; |
176 | |
177 | for (i = 0; i < 10; i++) |
178 | slist = g_slist_insert_sorted (list: slist, data: &more_nums[i], func: my_list_compare_one); |
179 | |
180 | /* |
181 | g_printerr ("\n"); |
182 | g_slist_foreach (slist, my_list_print, NULL); |
183 | */ |
184 | |
185 | for (i = 0; i < 10; i++) |
186 | { |
187 | GSList *st = g_slist_nth (list: slist, n: i); |
188 | if (*((gint*) st->data) != i) |
189 | g_error ("Sorted insert failed" ); |
190 | } |
191 | |
192 | g_slist_free (list: slist); |
193 | slist = NULL; |
194 | |
195 | for (i = 0; i < 10; i++) |
196 | slist = g_slist_insert_sorted (list: slist, data: &more_nums[i], func: my_list_compare_two); |
197 | |
198 | /* |
199 | g_printerr ("\n"); |
200 | g_slist_foreach (slist, my_list_print, NULL); |
201 | */ |
202 | |
203 | for (i = 0; i < 10; i++) |
204 | { |
205 | GSList *st = g_slist_nth (list: slist, n: i); |
206 | if (*((gint*) st->data) != (9 - i)) |
207 | g_error("Sorted insert failed" ); |
208 | } |
209 | |
210 | g_slist_free(list: slist); |
211 | slist = NULL; |
212 | |
213 | for (i = 0; i < 10; i++) |
214 | slist = g_slist_prepend (list: slist, data: &more_nums[i]); |
215 | |
216 | slist = g_slist_sort (list: slist, compare_func: my_list_compare_two); |
217 | |
218 | /* |
219 | g_printerr ("\n"); |
220 | g_slist_foreach (slist, my_list_print, NULL); |
221 | */ |
222 | |
223 | for (i = 0; i < 10; i++) |
224 | { |
225 | GSList *st = g_slist_nth (list: slist, n: i); |
226 | if (*((gint*) st->data) != (9 - i)) |
227 | g_error("Sorted insert failed" ); |
228 | } |
229 | |
230 | g_slist_free(list: slist); |
231 | } |
232 | |
233 | static gboolean |
234 | node_build_string (GNode *node, |
235 | gpointer data) |
236 | { |
237 | gchar **p = data; |
238 | gchar *string; |
239 | gchar c[2] = "_" ; |
240 | |
241 | c[0] = ((gchar) ((gintptr) (node->data))); |
242 | |
243 | string = g_strconcat (string1: *p ? *p : "" , c, NULL); |
244 | g_free (mem: *p); |
245 | *p = string; |
246 | |
247 | return FALSE; |
248 | } |
249 | |
250 | static void |
251 | gnode_test (void) |
252 | { |
253 | #define C2P(c) ((gpointer) ((long) (c))) |
254 | #define P2C(p) ((gchar) ((gintptr) (p))) |
255 | GNode *root; |
256 | GNode *node; |
257 | GNode *node_B; |
258 | GNode *node_F; |
259 | GNode *node_G; |
260 | GNode *node_J; |
261 | guint i; |
262 | gchar *tstring, *cstring; |
263 | |
264 | root = g_node_new (C2P ('A')); |
265 | g_assert (g_node_depth (root) == 1 && g_node_max_height (root) == 1); |
266 | |
267 | node_B = g_node_new (C2P ('B')); |
268 | g_node_append (root, node_B); |
269 | g_assert (root->children == node_B); |
270 | |
271 | g_node_append_data (node_B, C2P ('E')); |
272 | g_node_prepend_data (node_B, C2P ('C')); |
273 | g_node_insert (parent: node_B, position: 1, node: g_node_new (C2P ('D'))); |
274 | |
275 | node_F = g_node_new (C2P ('F')); |
276 | g_node_append (root, node_F); |
277 | g_assert (root->children->next == node_F); |
278 | |
279 | node_G = g_node_new (C2P ('G')); |
280 | g_node_append (node_F, node_G); |
281 | node_J = g_node_new (C2P ('J')); |
282 | g_node_prepend (parent: node_G, node: node_J); |
283 | g_node_insert (parent: node_G, position: 42, node: g_node_new (C2P ('K'))); |
284 | g_node_insert_data (node_G, 0, C2P ('H')); |
285 | g_node_insert (parent: node_G, position: 1, node: g_node_new (C2P ('I'))); |
286 | |
287 | g_assert (g_node_depth (root) == 1); |
288 | g_assert (g_node_max_height (root) == 4); |
289 | g_assert (g_node_depth (node_G->children->next) == 4); |
290 | g_assert (g_node_n_nodes (root, G_TRAVERSE_LEAFS) == 7); |
291 | g_assert (g_node_n_nodes (root, G_TRAVERSE_NON_LEAFS) == 4); |
292 | g_assert (g_node_n_nodes (root, G_TRAVERSE_ALL) == 11); |
293 | g_assert (g_node_max_height (node_F) == 3); |
294 | g_assert (g_node_n_children (node_G) == 4); |
295 | g_assert (g_node_find_child (root, G_TRAVERSE_ALL, C2P ('F')) == node_F); |
296 | g_assert (g_node_find (root, G_LEVEL_ORDER, G_TRAVERSE_NON_LEAFS, C2P ('I')) == NULL); |
297 | g_assert (g_node_find (root, G_IN_ORDER, G_TRAVERSE_LEAFS, C2P ('J')) == node_J); |
298 | |
299 | for (i = 0; i < g_node_n_children (node: node_B); i++) |
300 | { |
301 | node = g_node_nth_child (node: node_B, n: i); |
302 | g_assert (P2C (node->data) == ('C' + i)); |
303 | } |
304 | |
305 | for (i = 0; i < g_node_n_children (node: node_G); i++) |
306 | g_assert (g_node_child_position (node_G, g_node_nth_child (node_G, i)) == i); |
307 | |
308 | /* we have built: A |
309 | * / \ |
310 | * B F |
311 | * / | \ \ |
312 | * C D E G |
313 | * / /\ \ |
314 | * H I J K |
315 | * |
316 | * for in-order traversal, 'G' is considered to be the "left" |
317 | * child of 'F', which will cause 'F' to be the last node visited. |
318 | */ |
319 | |
320 | tstring = NULL; |
321 | g_node_traverse (root, order: G_PRE_ORDER, flags: G_TRAVERSE_ALL, max_depth: -1, func: node_build_string, data: &tstring); |
322 | g_assert_cmpstr (tstring, ==, "ABCDEFGHIJK" ); |
323 | g_free (mem: tstring); tstring = NULL; |
324 | g_node_traverse (root, order: G_POST_ORDER, flags: G_TRAVERSE_ALL, max_depth: -1, func: node_build_string, data: &tstring); |
325 | g_assert_cmpstr (tstring, ==, "CDEBHIJKGFA" ); |
326 | g_free (mem: tstring); tstring = NULL; |
327 | g_node_traverse (root, order: G_IN_ORDER, flags: G_TRAVERSE_ALL, max_depth: -1, func: node_build_string, data: &tstring); |
328 | g_assert_cmpstr (tstring, ==, "CBDEAHGIJKF" ); |
329 | g_free (mem: tstring); tstring = NULL; |
330 | g_node_traverse (root, order: G_LEVEL_ORDER, flags: G_TRAVERSE_ALL, max_depth: -1, func: node_build_string, data: &tstring); |
331 | g_assert_cmpstr (tstring, ==, "ABFCDEGHIJK" ); |
332 | g_free (mem: tstring); tstring = NULL; |
333 | |
334 | g_node_traverse (root, order: G_LEVEL_ORDER, flags: G_TRAVERSE_LEAFS, max_depth: -1, func: node_build_string, data: &tstring); |
335 | g_assert_cmpstr (tstring, ==, "CDEHIJK" ); |
336 | g_free (mem: tstring); tstring = NULL; |
337 | g_node_traverse (root, order: G_PRE_ORDER, flags: G_TRAVERSE_NON_LEAFS, max_depth: -1, func: node_build_string, data: &tstring); |
338 | g_assert_cmpstr (tstring, ==, "ABFG" ); |
339 | g_free (mem: tstring); tstring = NULL; |
340 | |
341 | g_node_reverse_children (node: node_B); |
342 | g_node_reverse_children (node: node_G); |
343 | |
344 | g_node_traverse (root, order: G_LEVEL_ORDER, flags: G_TRAVERSE_ALL, max_depth: -1, func: node_build_string, data: &tstring); |
345 | g_assert_cmpstr (tstring, ==, "ABFEDCGKJIH" ); |
346 | g_free (mem: tstring); tstring = NULL; |
347 | |
348 | cstring = NULL; |
349 | node = g_node_copy (node: root); |
350 | g_assert (g_node_n_nodes (root, G_TRAVERSE_ALL) == g_node_n_nodes (node, G_TRAVERSE_ALL)); |
351 | g_assert (g_node_max_height (root) == g_node_max_height (node)); |
352 | g_node_traverse (root, order: G_IN_ORDER, flags: G_TRAVERSE_ALL, max_depth: -1, func: node_build_string, data: &tstring); |
353 | g_node_traverse (root: node, order: G_IN_ORDER, flags: G_TRAVERSE_ALL, max_depth: -1, func: node_build_string, data: &cstring); |
354 | g_assert_cmpstr (tstring, ==, cstring); |
355 | g_free (mem: tstring); tstring = NULL; |
356 | g_free (mem: cstring); cstring = NULL; |
357 | g_node_destroy (root: node); |
358 | |
359 | g_node_destroy (root); |
360 | |
361 | /* allocation tests */ |
362 | |
363 | root = g_node_new (NULL); |
364 | node = root; |
365 | |
366 | for (i = 0; i < 2048; i++) |
367 | { |
368 | g_node_append (node, g_node_new (NULL)); |
369 | if ((i%5) == 4) |
370 | node = node->children->next; |
371 | } |
372 | g_assert (g_node_max_height (root) > 100); |
373 | g_assert (g_node_n_nodes (root, G_TRAVERSE_ALL) == 1 + 2048); |
374 | |
375 | g_node_destroy (root); |
376 | #undef C2P |
377 | #undef P2C |
378 | } |
379 | |
380 | static gint |
381 | my_compare (gconstpointer a, |
382 | gconstpointer b) |
383 | { |
384 | const char *cha = a; |
385 | const char *chb = b; |
386 | |
387 | return *cha - *chb; |
388 | } |
389 | |
390 | static gint |
391 | my_traverse (gpointer key, |
392 | gpointer value, |
393 | gpointer data) |
394 | { |
395 | char *ch = key; |
396 | g_printerr (format: "%c " , *ch); |
397 | return FALSE; |
398 | } |
399 | |
400 | static void |
401 | binary_tree_bound (GTree *tree, |
402 | char c, |
403 | char expected, |
404 | int lower) |
405 | { |
406 | GTreeNode *node; |
407 | |
408 | if (lower) |
409 | node = g_tree_lower_bound (tree, key: &c); |
410 | else |
411 | node = g_tree_upper_bound (tree, key: &c); |
412 | |
413 | if (g_test_verbose ()) |
414 | g_printerr (format: "%c %s: " , c, lower ? "lower" : "upper" ); |
415 | |
416 | if (!node) |
417 | { |
418 | if (!g_tree_nnodes (tree)) |
419 | { |
420 | if (g_test_verbose ()) |
421 | g_printerr (format: "empty tree" ); |
422 | } |
423 | else |
424 | { |
425 | GTreeNode *last = g_tree_node_last (tree); |
426 | |
427 | g_assert (last); |
428 | if (g_test_verbose ()) |
429 | g_printerr (format: "past end last %c" , |
430 | *(char *) g_tree_node_key (node: last)); |
431 | } |
432 | g_assert (expected == '\x00'); |
433 | } |
434 | else |
435 | { |
436 | GTreeNode *begin = g_tree_node_first (tree); |
437 | GTreeNode *last = g_tree_node_last (tree); |
438 | GTreeNode *prev = g_tree_node_previous (node); |
439 | GTreeNode *next = g_tree_node_next (node); |
440 | |
441 | g_assert (expected != '\x00'); |
442 | g_assert (expected == *(char *) g_tree_node_key (node)); |
443 | |
444 | if (g_test_verbose ()) |
445 | g_printerr (format: "%c" , *(char *) g_tree_node_key (node)); |
446 | |
447 | if (node != begin) |
448 | { |
449 | g_assert (prev); |
450 | if (g_test_verbose ()) |
451 | g_printerr (format: " prev %c" , *(char *) g_tree_node_key (node: prev)); |
452 | } |
453 | else |
454 | { |
455 | g_assert (!prev); |
456 | if (g_test_verbose ()) |
457 | g_printerr (format: " no prev, it's the first one" ); |
458 | } |
459 | |
460 | if (node != last) |
461 | { |
462 | g_assert (next); |
463 | if (g_test_verbose ()) |
464 | g_printerr (format: " next %c" , *(char *) g_tree_node_key (node: next)); |
465 | } |
466 | else |
467 | { |
468 | g_assert (!next); |
469 | if (g_test_verbose ()) |
470 | g_printerr (format: " no next, it's the last one" ); |
471 | } |
472 | } |
473 | |
474 | if (g_test_verbose ()) |
475 | g_printerr (format: "\n" ); |
476 | } |
477 | |
478 | static void |
479 | binary_tree_bounds (GTree *tree, |
480 | char c, |
481 | int mode) |
482 | { |
483 | char expectedl, expectedu; |
484 | char first = mode == 0 ? '0' : mode == 1 ? 'A' : 'z'; |
485 | |
486 | g_assert (mode >= 0 && mode <= 3); |
487 | |
488 | if (c < first) |
489 | expectedl = first; |
490 | else if (c > 'z') |
491 | expectedl = '\x00'; |
492 | else |
493 | expectedl = c; |
494 | |
495 | if (c < first) |
496 | expectedu = first; |
497 | else if (c >= 'z') |
498 | expectedu = '\x00'; |
499 | else |
500 | expectedu = c == '9' ? 'A' : c == 'Z' ? 'a' : c + 1; |
501 | |
502 | if (mode == 3) |
503 | { |
504 | expectedl = '\x00'; |
505 | expectedu = '\x00'; |
506 | } |
507 | |
508 | binary_tree_bound (tree, c, expected: expectedl, lower: 1); |
509 | binary_tree_bound (tree, c, expected: expectedu, lower: 0); |
510 | } |
511 | |
512 | static void |
513 | binary_tree_bounds_test (GTree *tree, |
514 | int mode) |
515 | { |
516 | binary_tree_bounds (tree, c: 'a', mode); |
517 | binary_tree_bounds (tree, c: 'A', mode); |
518 | binary_tree_bounds (tree, c: 'z', mode); |
519 | binary_tree_bounds (tree, c: 'Z', mode); |
520 | binary_tree_bounds (tree, c: 'Y', mode); |
521 | binary_tree_bounds (tree, c: '0', mode); |
522 | binary_tree_bounds (tree, c: '9', mode); |
523 | binary_tree_bounds (tree, c: '0' - 1, mode); |
524 | binary_tree_bounds (tree, c: 'z' + 1, mode); |
525 | binary_tree_bounds (tree, c: '0' - 2, mode); |
526 | binary_tree_bounds (tree, c: 'z' + 2, mode); |
527 | } |
528 | |
529 | static void |
530 | binary_tree_test (void) |
531 | { |
532 | GQueue queue = G_QUEUE_INIT; |
533 | GTree *tree; |
534 | char chars[62]; |
535 | guint i, j; |
536 | |
537 | tree = g_tree_new (key_compare_func: my_compare); |
538 | i = 0; |
539 | for (j = 0; j < 10; j++, i++) |
540 | { |
541 | chars[i] = '0' + j; |
542 | g_queue_push_tail (queue: &queue, data: &chars[i]); |
543 | } |
544 | for (j = 0; j < 26; j++, i++) |
545 | { |
546 | chars[i] = 'A' + j; |
547 | g_queue_push_tail (queue: &queue, data: &chars[i]); |
548 | } |
549 | for (j = 0; j < 26; j++, i++) |
550 | { |
551 | chars[i] = 'a' + j; |
552 | g_queue_push_tail (queue: &queue, data: &chars[i]); |
553 | } |
554 | |
555 | if (g_test_verbose ()) |
556 | g_printerr (format: "tree insert: " ); |
557 | while (!g_queue_is_empty (queue: &queue)) |
558 | { |
559 | gint32 which = g_random_int_range (begin: 0, end: g_queue_get_length (queue: &queue)); |
560 | gpointer elem = g_queue_pop_nth (queue: &queue, n: which); |
561 | GTreeNode *node; |
562 | |
563 | if (g_test_verbose ()) |
564 | g_printerr (format: "%c " , *(char *) elem); |
565 | |
566 | node = g_tree_insert_node (tree, key: elem, value: elem); |
567 | g_assert (g_tree_node_key (node) == elem); |
568 | g_assert (g_tree_node_value (node) == elem); |
569 | } |
570 | if (g_test_verbose ()) |
571 | g_printerr (format: "\n" ); |
572 | |
573 | g_assert_cmpint (g_tree_nnodes (tree), ==, 10 + 26 + 26); |
574 | g_assert_cmpint (g_tree_height (tree), >=, 6); |
575 | g_assert_cmpint (g_tree_height (tree), <=, 8); |
576 | |
577 | if (g_test_verbose ()) |
578 | { |
579 | g_printerr (format: "tree: " ); |
580 | g_tree_foreach (tree, func: my_traverse, NULL); |
581 | g_printerr (format: "\n" ); |
582 | } |
583 | |
584 | binary_tree_bounds_test (tree, mode: 0); |
585 | |
586 | for (i = 0; i < 10; i++) |
587 | g_tree_remove (tree, key: &chars[i]); |
588 | |
589 | g_assert_cmpint (g_tree_nnodes (tree), ==, 26 + 26); |
590 | g_assert_cmpint (g_tree_height (tree), >=, 6); |
591 | g_assert_cmpint (g_tree_height (tree), <=, 8); |
592 | |
593 | if (g_test_verbose ()) |
594 | { |
595 | g_printerr (format: "tree: " ); |
596 | g_tree_foreach (tree, func: my_traverse, NULL); |
597 | g_printerr (format: "\n" ); |
598 | } |
599 | |
600 | binary_tree_bounds_test (tree, mode: 1); |
601 | |
602 | for (i = 10; i < 10 + 26 + 26 - 1; i++) |
603 | g_tree_remove (tree, key: &chars[i]); |
604 | |
605 | if (g_test_verbose ()) |
606 | { |
607 | g_printerr (format: "tree: " ); |
608 | g_tree_foreach (tree, func: my_traverse, NULL); |
609 | g_printerr (format: "\n" ); |
610 | } |
611 | |
612 | binary_tree_bounds_test (tree, mode: 2); |
613 | |
614 | g_tree_remove (tree, key: &chars[10 + 26 + 26 - 1]); |
615 | |
616 | if (g_test_verbose ()) |
617 | g_printerr (format: "empty tree\n" ); |
618 | |
619 | binary_tree_bounds_test (tree, mode: 3); |
620 | |
621 | g_tree_unref (tree); |
622 | } |
623 | |
624 | static gboolean |
625 | my_hash_callback_remove (gpointer key, |
626 | gpointer value, |
627 | gpointer user_data) |
628 | { |
629 | int *d = value; |
630 | |
631 | if ((*d) % 2) |
632 | return TRUE; |
633 | |
634 | return FALSE; |
635 | } |
636 | |
637 | static void |
638 | my_hash_callback_remove_test (gpointer key, |
639 | gpointer value, |
640 | gpointer user_data) |
641 | { |
642 | int *d = value; |
643 | |
644 | if ((*d) % 2) |
645 | g_error ("hash table entry %d should have been removed already" , *d); |
646 | } |
647 | |
648 | static void |
649 | my_hash_callback (gpointer key, |
650 | gpointer value, |
651 | gpointer user_data) |
652 | { |
653 | int *d = value; |
654 | *d = 1; |
655 | } |
656 | |
657 | static guint |
658 | my_hash (gconstpointer key) |
659 | { |
660 | return (guint) *((const gint*) key); |
661 | } |
662 | |
663 | static gboolean |
664 | my_hash_equal (gconstpointer a, |
665 | gconstpointer b) |
666 | { |
667 | return *((const gint*) a) == *((const gint*) b); |
668 | } |
669 | |
670 | static gboolean |
671 | find_first_that(gpointer key, |
672 | gpointer value, |
673 | gpointer user_data) |
674 | { |
675 | gint *v = value; |
676 | gint *test = user_data; |
677 | return (*v == *test); |
678 | } |
679 | |
680 | static void |
681 | test_g_parse_debug_string (void) |
682 | { |
683 | GDebugKey keys[] = { |
684 | { "foo" , 1 }, |
685 | { "bar" , 2 }, |
686 | { "baz" , 4 }, |
687 | { "weird" , 8 }, |
688 | }; |
689 | guint n_keys = G_N_ELEMENTS (keys); |
690 | guint result; |
691 | |
692 | result = g_parse_debug_string (string: "bar:foo:blubb" , keys, nkeys: n_keys); |
693 | g_assert (result == 3); |
694 | |
695 | result = g_parse_debug_string (string: ":baz::_E@~!_::" , keys, nkeys: n_keys); |
696 | g_assert (result == 4); |
697 | |
698 | result = g_parse_debug_string (string: "" , keys, nkeys: n_keys); |
699 | g_assert (result == 0); |
700 | |
701 | result = g_parse_debug_string (string: " : " , keys, nkeys: n_keys); |
702 | g_assert (result == 0); |
703 | |
704 | result = g_parse_debug_string (string: "all" , keys, nkeys: n_keys); |
705 | g_assert_cmpuint (result, ==, (1 << n_keys) - 1); |
706 | |
707 | /* Test subtracting debug flags from "all" */ |
708 | result = g_parse_debug_string (string: "all:foo" , keys, nkeys: n_keys); |
709 | g_assert_cmpuint (result, ==, 2 | 4 | 8); |
710 | |
711 | result = g_parse_debug_string (string: "foo baz,all" , keys, nkeys: n_keys); |
712 | g_assert_cmpuint (result, ==, 2 | 8); |
713 | |
714 | result = g_parse_debug_string (string: "all,fooo,baz" , keys, nkeys: n_keys); |
715 | g_assert_cmpuint (result, ==, 1 | 2 | 8); |
716 | |
717 | result = g_parse_debug_string (string: "all:weird" , keys, nkeys: n_keys); |
718 | g_assert_cmpuint (result, ==, 1 | 2 | 4); |
719 | } |
720 | |
721 | static void |
722 | log_warning_error_tests (void) |
723 | { |
724 | g_test_expect_message (G_LOG_DOMAIN, log_level: G_LOG_LEVEL_MESSAGE, |
725 | pattern: "*is a g_message test*" ); |
726 | g_message ("this is a g_message test." ); |
727 | g_test_assert_expected_messages (); |
728 | |
729 | g_test_expect_message (G_LOG_DOMAIN, log_level: G_LOG_LEVEL_MESSAGE, |
730 | pattern: "*non-printable UTF-8*" ); |
731 | g_message ("non-printable UTF-8: \"\xc3\xa4\xda\x85\"" ); |
732 | g_test_assert_expected_messages (); |
733 | |
734 | g_test_expect_message (G_LOG_DOMAIN, log_level: G_LOG_LEVEL_MESSAGE, |
735 | pattern: "*unsafe chars*" ); |
736 | g_message ("unsafe chars: \"\x10\x11\x12\n\t\x7f\x81\x82\x83\"" ); |
737 | g_test_assert_expected_messages (); |
738 | |
739 | g_test_expect_message (G_LOG_DOMAIN, log_level: G_LOG_LEVEL_WARNING, |
740 | pattern: "*harmless warning*" ); |
741 | g_warning ("harmless warning with parameters: %d %s %#x" , 42, "Boo" , 12345); |
742 | g_test_assert_expected_messages (); |
743 | |
744 | g_test_expect_message (G_LOG_DOMAIN, log_level: G_LOG_LEVEL_CRITICAL, |
745 | pattern: "*g_print*assertion*failed*" ); |
746 | g_print (NULL); |
747 | g_test_assert_expected_messages (); |
748 | } |
749 | |
750 | static void |
751 | log_warning_rate_limited_tests (void) |
752 | { |
753 | #if defined(G_HAVE_ISO_VARARGS) || defined(G_HAVE_GNUC_VARARGS) |
754 | int i; |
755 | |
756 | g_test_expect_message (G_LOG_DOMAIN, log_level: G_LOG_LEVEL_WARNING, |
757 | pattern: "*harmless single warning 1*" ); |
758 | g_test_expect_message (G_LOG_DOMAIN, log_level: G_LOG_LEVEL_WARNING, |
759 | pattern: "*harmless single warning 2*" ); |
760 | for (i = 0; i < 10; i++) |
761 | g_warning_once ("harmless single warning 1" ); |
762 | for (i = 0; i < 10; i++) |
763 | g_warning_once ("harmless single warning 2" ); |
764 | g_test_assert_expected_messages (); |
765 | #else |
766 | g_test_skip ("Variadic macro support not available" ); |
767 | #endif |
768 | } |
769 | |
770 | static void |
771 | timer_tests (void) |
772 | { |
773 | GTimer *timer, *timer2; |
774 | gdouble elapsed; |
775 | |
776 | /* basic testing */ |
777 | timer = g_timer_new (); |
778 | g_timer_start (timer); |
779 | elapsed = g_timer_elapsed (timer, NULL); |
780 | g_timer_stop (timer); |
781 | g_assert_cmpfloat (elapsed, <=, g_timer_elapsed (timer, NULL)); |
782 | g_timer_destroy (timer); |
783 | |
784 | if (g_test_slow()) |
785 | { |
786 | if (g_test_verbose()) |
787 | g_printerr (format: "checking timers...\n" ); |
788 | timer = g_timer_new (); |
789 | if (g_test_verbose()) |
790 | g_printerr (format: " spinning for 3 seconds...\n" ); |
791 | g_timer_start (timer); |
792 | while (g_timer_elapsed (timer, NULL) < 3) |
793 | ; |
794 | g_timer_stop (timer); |
795 | g_timer_destroy (timer); |
796 | if (g_test_verbose()) |
797 | g_printerr (format: "ok\n" ); |
798 | } |
799 | |
800 | if (g_test_slow()) |
801 | { |
802 | gulong elapsed_usecs; |
803 | if (g_test_verbose()) |
804 | g_printerr (format: "checking g_timer_continue...\n" ); |
805 | timer2 = g_timer_new (); |
806 | if (g_test_verbose()) |
807 | g_printerr (format: "\trun for 1 second...\n" ); |
808 | timer = g_timer_new(); |
809 | g_usleep (G_USEC_PER_SEC); /* run timer for 1 second */ |
810 | g_timer_stop (timer); |
811 | if (g_test_verbose()) |
812 | g_printerr (format: "\tstop for 1 second...\n" ); |
813 | g_usleep (G_USEC_PER_SEC); /* wait for 1 second */ |
814 | if (g_test_verbose()) |
815 | g_printerr (format: "\trun for 2 seconds...\n" ); |
816 | g_timer_continue (timer); |
817 | g_usleep (microseconds: 2 * G_USEC_PER_SEC); /* run timer for 2 seconds */ |
818 | g_timer_stop(timer); |
819 | if (g_test_verbose()) |
820 | g_printerr (format: "\tstop for 1.5 seconds...\n" ); |
821 | g_usleep (microseconds: (3 * G_USEC_PER_SEC) / 2); /* wait for 1.5 seconds */ |
822 | if (g_test_verbose()) |
823 | g_printerr (format: "\trun for 0.2 seconds...\n" ); |
824 | g_timer_continue (timer); |
825 | g_usleep (G_USEC_PER_SEC / 5); /* run timer for 0.2 seconds */ |
826 | g_timer_stop (timer); |
827 | if (g_test_verbose()) |
828 | g_printerr (format: "\tstop for 4 seconds...\n" ); |
829 | g_usleep (microseconds: 4 * G_USEC_PER_SEC); /* wait for 4 seconds */ |
830 | if (g_test_verbose()) |
831 | g_printerr (format: "\trun for 5.8 seconds...\n" ); |
832 | g_timer_continue (timer); |
833 | g_usleep (microseconds: (29 * G_USEC_PER_SEC) / 5); /* run timer for 5.8 seconds */ |
834 | g_timer_stop(timer); |
835 | elapsed = g_timer_elapsed (timer, microseconds: &elapsed_usecs); |
836 | if (g_test_verbose()) |
837 | g_printerr (format: "\t=> timer = %.6f = %d.%06ld (should be: 9.000000) (%.6f off)\n" , elapsed, (int) elapsed, elapsed_usecs, ABS (elapsed - 9.)); |
838 | g_assert_cmpfloat (elapsed, >, 8.8); |
839 | g_assert_cmpfloat (elapsed, <, 9.2); |
840 | if (g_test_verbose()) |
841 | g_printerr (format: "g_timer_continue ... ok\n\n" ); |
842 | g_timer_stop (timer: timer2); |
843 | elapsed = g_timer_elapsed (timer: timer2, microseconds: &elapsed_usecs); |
844 | if (g_test_verbose()) |
845 | g_printerr (format: "\t=> timer2 = %.6f = %d.%06ld (should be: %.6f) (%.6f off)\n\n" , elapsed, (int) elapsed, elapsed_usecs, 9.+6.5, ABS (elapsed - (9.+6.5))); |
846 | g_assert_cmpfloat (elapsed, >, 8.8 + 6.5); |
847 | g_assert_cmpfloat (elapsed, <, 9.2 + 6.5); |
848 | if (g_test_verbose()) |
849 | g_printerr (format: "timer2 ... ok\n\n" ); |
850 | g_timer_destroy (timer); |
851 | g_timer_destroy (timer: timer2); |
852 | } |
853 | } |
854 | |
855 | static void |
856 | type_sizes (void) |
857 | { |
858 | guint16 gu16t1 = 0x44afU, gu16t2 = 0xaf44U; |
859 | guint32 gu32t1 = 0x02a7f109U, gu32t2 = 0x09f1a702U; |
860 | guint64 gu64t1 = G_GINT64_CONSTANT(0x1d636b02300a7aa7U), |
861 | gu64t2 = G_GINT64_CONSTANT(0xa77a0a30026b631dU); |
862 | /* type sizes */ |
863 | g_assert_cmpint (sizeof (gint8), ==, 1); |
864 | g_assert_cmpint (sizeof (gint16), ==, 2); |
865 | g_assert_cmpint (sizeof (gint32), ==, 4); |
866 | g_assert_cmpint (sizeof (gint64), ==, 8); |
867 | /* endian macros */ |
868 | if (g_test_verbose()) |
869 | g_printerr (format: "checking endian macros (host is %s)...\n" , |
870 | G_BYTE_ORDER == G_BIG_ENDIAN ? "big endian" : "little endian" ); |
871 | g_assert (GUINT16_SWAP_LE_BE (gu16t1) == gu16t2); |
872 | g_assert (GUINT32_SWAP_LE_BE (gu32t1) == gu32t2); |
873 | g_assert (GUINT64_SWAP_LE_BE (gu64t1) == gu64t2); |
874 | } |
875 | |
876 | static void |
877 | test_info (void) |
878 | { |
879 | const gchar *un, *rn, *hn; |
880 | const gchar *tmpdir, *homedir, *userdatadir, *uconfdir, *ucachedir; |
881 | const gchar *uddesktop, *udddocs, *uddpubshare, *uruntimedir; |
882 | gchar **sv, *cwd, *sdatadirs, *sconfdirs, *langnames; |
883 | const gchar *charset; |
884 | gboolean charset_is_utf8; |
885 | if (g_test_verbose()) |
886 | g_printerr (format: "TestGLib v%u.%u.%u (i:%u b:%u)\n" , |
887 | glib_major_version, |
888 | glib_minor_version, |
889 | glib_micro_version, |
890 | glib_interface_age, |
891 | glib_binary_age); |
892 | |
893 | cwd = g_get_current_dir (); |
894 | un = g_get_user_name(); |
895 | rn = g_get_real_name(); |
896 | hn = g_get_host_name(); |
897 | if (g_test_verbose()) |
898 | { |
899 | g_printerr (format: "cwd: %s\n" , cwd); |
900 | g_printerr (format: "user: %s\n" , un); |
901 | g_printerr (format: "real: %s\n" , rn); |
902 | g_printerr (format: "host: %s\n" , hn); |
903 | } |
904 | g_free (mem: cwd); |
905 | |
906 | /* reload, just for fun */ |
907 | g_reload_user_special_dirs_cache (); |
908 | g_reload_user_special_dirs_cache (); |
909 | |
910 | tmpdir = g_get_tmp_dir(); |
911 | g_assert (tmpdir != NULL); |
912 | homedir = g_get_home_dir (); |
913 | g_assert (homedir != NULL); |
914 | userdatadir = g_get_user_data_dir (); |
915 | g_assert (userdatadir != NULL); |
916 | uconfdir = g_get_user_config_dir (); |
917 | g_assert (uconfdir != NULL); |
918 | ucachedir = g_get_user_cache_dir (); |
919 | g_assert (ucachedir != NULL); |
920 | |
921 | uddesktop = g_get_user_special_dir (directory: G_USER_DIRECTORY_DESKTOP); |
922 | g_assert (uddesktop != NULL); |
923 | udddocs = g_get_user_special_dir (directory: G_USER_DIRECTORY_DOCUMENTS); |
924 | uddpubshare = g_get_user_special_dir (directory: G_USER_DIRECTORY_PUBLIC_SHARE); |
925 | uruntimedir = g_get_user_runtime_dir (); |
926 | g_assert (uruntimedir != NULL); |
927 | |
928 | sv = (gchar **) g_get_system_data_dirs (); |
929 | sdatadirs = g_strjoinv (G_SEARCHPATH_SEPARATOR_S, str_array: sv); |
930 | sv = (gchar **) g_get_system_config_dirs (); |
931 | sconfdirs = g_strjoinv (G_SEARCHPATH_SEPARATOR_S, str_array: sv); |
932 | sv = (gchar **) g_get_language_names (); |
933 | langnames = g_strjoinv (separator: ":" , str_array: sv); |
934 | |
935 | if (g_test_verbose()) |
936 | { |
937 | g_printerr (format: "tmp-dir: %s\n" , tmpdir); |
938 | g_printerr (format: "home: %s\n" , homedir); |
939 | g_printerr (format: "user_data: %s\n" , userdatadir); |
940 | g_printerr (format: "user_config: %s\n" , uconfdir); |
941 | g_printerr (format: "user_cache: %s\n" , ucachedir); |
942 | g_printerr (format: "user_runtime: %s\n" , uruntimedir); |
943 | g_printerr (format: "system_data: %s\n" , sdatadirs); |
944 | g_printerr (format: "system_config: %s\n" , sconfdirs); |
945 | g_printerr (format: "languages: %s\n" , langnames); |
946 | g_printerr (format: "user_special[DESKTOP]: %s\n" , uddesktop); |
947 | g_printerr (format: "user_special[DOCUMENTS]: %s\n" , udddocs); |
948 | g_printerr (format: "user_special[PUBLIC_SHARE]: %s\n" , uddpubshare); |
949 | } |
950 | g_free (mem: sdatadirs); |
951 | g_free (mem: sconfdirs); |
952 | g_free (mem: langnames); |
953 | |
954 | charset_is_utf8 = g_get_charset (charset: (const char**)&charset); |
955 | |
956 | if (g_test_verbose()) |
957 | { |
958 | if (charset_is_utf8) |
959 | g_printerr (format: "current charset is UTF-8: %s\n" , charset); |
960 | else |
961 | g_printerr (format: "current charset is not UTF-8: %s\n" , charset); |
962 | } |
963 | |
964 | if (g_test_verbose()) |
965 | { |
966 | #ifdef G_PLATFORM_WIN32 |
967 | g_printerr ("current locale: %s\n" , g_win32_getlocale ()); |
968 | |
969 | g_printerr ("found more.com as %s\n" , g_find_program_in_path ("more.com" )); |
970 | g_printerr ("found regedit as %s\n" , g_find_program_in_path ("regedit" )); |
971 | |
972 | g_printerr ("a Win32 error message: %s\n" , g_win32_error_message (2)); |
973 | #endif |
974 | } |
975 | } |
976 | |
977 | static void |
978 | test_paths (void) |
979 | { |
980 | struct { |
981 | gchar *filename; |
982 | gchar *dirname; |
983 | } dirname_checks[] = { |
984 | { "/" , "/" }, |
985 | { "////" , "/" }, |
986 | { ".////" , "." }, |
987 | { "../" , ".." }, |
988 | { "..////" , ".." }, |
989 | { "a/b" , "a" }, |
990 | { "a/b/" , "a/b" }, |
991 | { "c///" , "c" }, |
992 | #ifdef G_OS_WIN32 |
993 | { "\\" , "\\" }, |
994 | { ".\\\\\\\\" , "." }, |
995 | { "..\\" , ".." }, |
996 | { "..\\\\\\\\" , ".." }, |
997 | { "a\\b" , "a" }, |
998 | { "a\\b/" , "a\\b" }, |
999 | { "a/b\\" , "a/b" }, |
1000 | { "c\\\\/" , "c" }, |
1001 | { "//\\" , "/" }, |
1002 | #endif |
1003 | #ifdef G_WITH_CYGWIN |
1004 | { "//server/share///x" , "//server/share" }, |
1005 | #endif |
1006 | { "." , "." }, |
1007 | { ".." , "." }, |
1008 | { "" , "." }, |
1009 | }; |
1010 | const guint n_dirname_checks = G_N_ELEMENTS (dirname_checks); |
1011 | struct { |
1012 | gchar *filename; |
1013 | gchar *without_root; |
1014 | } skip_root_checks[] = { |
1015 | { "/" , "" }, |
1016 | { "//" , "" }, |
1017 | { "/foo" , "foo" }, |
1018 | { "//foo" , "foo" }, |
1019 | { "a/b" , NULL }, |
1020 | #ifdef G_OS_WIN32 |
1021 | { "\\" , "" }, |
1022 | { "\\foo" , "foo" }, |
1023 | { "\\\\server\\foo" , "" }, |
1024 | { "\\\\server\\foo\\bar" , "bar" }, |
1025 | { "a\\b" , NULL }, |
1026 | #endif |
1027 | #ifdef G_WITH_CYGWIN |
1028 | { "//server/share///x" , "//x" }, |
1029 | #endif |
1030 | { "." , NULL }, |
1031 | { "" , NULL }, |
1032 | }; |
1033 | const guint n_skip_root_checks = G_N_ELEMENTS (skip_root_checks); |
1034 | struct { |
1035 | gchar *cwd; |
1036 | gchar *relative_path; |
1037 | gchar *canonical_path; |
1038 | } canonicalize_filename_checks[] = { |
1039 | #ifndef G_OS_WIN32 |
1040 | { "/etc" , "../usr/share" , "/usr/share" }, |
1041 | { "/" , "/foo/bar" , "/foo/bar" }, |
1042 | { "/usr/bin" , "../../foo/bar" , "/foo/bar" }, |
1043 | { "/" , "../../foo/bar" , "/foo/bar" }, |
1044 | { "/double//dash" , "../../foo/bar" , "/foo/bar" }, |
1045 | { "/usr/share/foo" , ".././././bar" , "/usr/share/bar" }, |
1046 | { "/foo/bar" , "../bar/./.././bar" , "/foo/bar" }, |
1047 | { "/test///dir" , "../../././foo/bar" , "/foo/bar" }, |
1048 | { "/test///dir" , "../../././/foo///bar" , "/foo/bar" }, |
1049 | { "/etc" , "///triple/slash" , "/triple/slash" }, |
1050 | { "/etc" , "//double/slash" , "//double/slash" }, |
1051 | { "///triple/slash" , "." , "/triple/slash" }, |
1052 | { "//double/slash" , "." , "//double/slash" }, |
1053 | { "/cwd/../with/./complexities/" , "./hello" , "/with/complexities/hello" }, |
1054 | #else |
1055 | { "/etc" , "../usr/share" , "\\usr\\share" }, |
1056 | { "/" , "/foo/bar" , "\\foo\\bar" }, |
1057 | { "/usr/bin" , "../../foo/bar" , "\\foo\\bar" }, |
1058 | { "/" , "../../foo/bar" , "\\foo\\bar" }, |
1059 | { "/double//dash" , "../../foo/bar" , "\\foo\\bar" }, |
1060 | { "/usr/share/foo" , ".././././bar" , "\\usr\\share\\bar" }, |
1061 | { "/foo/bar" , "../bar/./.././bar" , "\\foo\\bar" }, |
1062 | { "/test///dir" , "../../././foo/bar" , "\\foo\\bar" }, |
1063 | { "/test///dir" , "../../././/foo///bar" , "\\foo\\bar" }, |
1064 | { "/etc" , "///triple/slash" , "\\triple\\slash" }, |
1065 | { "/etc" , "//double/slash" , "//double/slash" }, |
1066 | { "///triple/slash" , "." , "\\triple\\slash" }, |
1067 | { "//double/slash" , "." , "//double/slash\\" }, |
1068 | { "/cwd/../with/./complexities/" , "./hello" , "\\with\\complexities\\hello" }, |
1069 | |
1070 | { "\\etc" , "..\\usr\\share" , "\\usr\\share" }, |
1071 | { "\\" , "\\foo\\bar" , "\\foo\\bar" }, |
1072 | { "\\usr\\bin" , "..\\..\\foo\\bar" , "\\foo\\bar" }, |
1073 | { "\\" , "..\\..\\foo\\bar" , "\\foo\\bar" }, |
1074 | { "\\double\\\\dash" , "..\\..\\foo\\bar" , "\\foo\\bar" }, |
1075 | { "\\usr\\share\\foo" , "..\\.\\.\\.\\bar" , "\\usr\\share\\bar" }, |
1076 | { "\\foo\\bar" , "..\\bar\\.\\..\\.\\bar" , "\\foo\\bar" }, |
1077 | { "\\test\\\\\\dir" , "..\\..\\.\\.\\foo\\bar" , "\\foo\\bar" }, |
1078 | { "\\test\\\\\\dir" , "..\\..\\.\\.\\\\foo\\\\\\bar" , "\\foo\\bar" }, |
1079 | { "\\etc" , "\\\\\\triple\\slash" , "\\triple\\slash" }, |
1080 | { "\\etc" , "\\\\double\\slash" , "\\\\double\\slash" }, |
1081 | { "\\\\\\triple\\slash" , "." , "\\triple\\slash" }, |
1082 | { "\\\\double\\slash" , "." , "\\\\double\\slash\\" }, |
1083 | { "\\cwd\\..\\with\\.\\complexities\\" , ".\\hello" , "\\with\\complexities\\hello" }, |
1084 | #endif |
1085 | }; |
1086 | const guint n_canonicalize_filename_checks = G_N_ELEMENTS (canonicalize_filename_checks); |
1087 | gchar *string; |
1088 | guint i; |
1089 | if (g_test_verbose()) |
1090 | g_printerr (format: "checking g_path_get_basename()..." ); |
1091 | string = g_path_get_basename (G_DIR_SEPARATOR_S "foo" G_DIR_SEPARATOR_S "dir" G_DIR_SEPARATOR_S); |
1092 | g_assert (strcmp (string, "dir" ) == 0); |
1093 | g_free (mem: string); |
1094 | string = g_path_get_basename (G_DIR_SEPARATOR_S "foo" G_DIR_SEPARATOR_S "file" ); |
1095 | g_assert (strcmp (string, "file" ) == 0); |
1096 | g_free (mem: string); |
1097 | if (g_test_verbose()) |
1098 | g_printerr (format: "ok\n" ); |
1099 | |
1100 | #ifdef G_OS_WIN32 |
1101 | string = g_path_get_basename ("/foo/dir/" ); |
1102 | g_assert (strcmp (string, "dir" ) == 0); |
1103 | g_free (string); |
1104 | string = g_path_get_basename ("/foo/file" ); |
1105 | g_assert (strcmp (string, "file" ) == 0); |
1106 | g_free (string); |
1107 | #endif |
1108 | |
1109 | if (g_test_verbose()) |
1110 | g_printerr (format: "checking g_path_get_dirname()..." ); |
1111 | for (i = 0; i < n_dirname_checks; i++) |
1112 | { |
1113 | gchar *dirname = g_path_get_dirname (file_name: dirname_checks[i].filename); |
1114 | if (strcmp (s1: dirname, s2: dirname_checks[i].dirname) != 0) |
1115 | { |
1116 | g_error ("failed for \"%s\"==\"%s\" (returned: \"%s\")" , |
1117 | dirname_checks[i].filename, |
1118 | dirname_checks[i].dirname, |
1119 | dirname); |
1120 | } |
1121 | g_free (mem: dirname); |
1122 | } |
1123 | if (g_test_verbose()) |
1124 | g_printerr (format: "ok\n" ); |
1125 | |
1126 | if (g_test_verbose()) |
1127 | g_printerr (format: "checking g_path_skip_root()..." ); |
1128 | for (i = 0; i < n_skip_root_checks; i++) |
1129 | { |
1130 | const gchar *skipped = g_path_skip_root (file_name: skip_root_checks[i].filename); |
1131 | if ((skipped && !skip_root_checks[i].without_root) || |
1132 | (!skipped && skip_root_checks[i].without_root) || |
1133 | ((skipped && skip_root_checks[i].without_root) && |
1134 | strcmp (s1: skipped, s2: skip_root_checks[i].without_root))) |
1135 | { |
1136 | g_error ("failed for \"%s\"==\"%s\" (returned: \"%s\")" , |
1137 | skip_root_checks[i].filename, |
1138 | (skip_root_checks[i].without_root ? |
1139 | skip_root_checks[i].without_root : "<NULL>" ), |
1140 | (skipped ? skipped : "<NULL>" )); |
1141 | } |
1142 | } |
1143 | if (g_test_verbose()) |
1144 | g_printerr (format: "ok\n" ); |
1145 | |
1146 | if (g_test_verbose ()) |
1147 | g_printerr (format: "checking g_canonicalize_filename()..." ); |
1148 | for (i = 0; i < n_canonicalize_filename_checks; i++) |
1149 | { |
1150 | gchar *canonical_path = g_canonicalize_filename (filename: canonicalize_filename_checks[i].relative_path, |
1151 | relative_to: canonicalize_filename_checks[i].cwd); |
1152 | if (g_strcmp0 (str1: canonical_path, str2: canonicalize_filename_checks[i].canonical_path) != 0) |
1153 | { |
1154 | g_error ("\nfailed for \"%s\"==\"%s\" (returned: \"%s\")\n" , |
1155 | canonicalize_filename_checks[i].relative_path, |
1156 | canonicalize_filename_checks[i].canonical_path, |
1157 | canonical_path); |
1158 | } |
1159 | g_free (mem: canonical_path); |
1160 | } |
1161 | if (g_test_verbose ()) |
1162 | g_printerr (format: "ok\n" ); |
1163 | |
1164 | if (g_test_verbose ()) |
1165 | g_printerr (format: "checking g_canonicalize_filename() supports NULL..." ); |
1166 | |
1167 | { |
1168 | const gchar *relative_path = "./" ; |
1169 | gchar *canonical_path = g_canonicalize_filename (filename: relative_path, NULL); |
1170 | gchar *cwd = g_get_current_dir (); |
1171 | if (g_strcmp0 (str1: canonical_path, str2: cwd) != 0) |
1172 | { |
1173 | g_error ("\nfailed for \"%s\"==\"%s\" (returned: \"%s\")\n" , |
1174 | relative_path, cwd, canonical_path); |
1175 | } |
1176 | g_free (mem: cwd); |
1177 | g_free (mem: canonical_path); |
1178 | } |
1179 | |
1180 | if (g_test_verbose ()) |
1181 | g_printerr (format: "ok\n" ); |
1182 | } |
1183 | |
1184 | static void |
1185 | test_file_functions (void) |
1186 | { |
1187 | const char hello[] = "Hello, World" ; |
1188 | const int hellolen = sizeof (hello) - 1; |
1189 | GError *error; |
1190 | char template[32]; |
1191 | char *name_used, chars[62]; |
1192 | gint fd, n; |
1193 | int errsv; |
1194 | |
1195 | strcpy (dest: template, src: "foobar" ); |
1196 | fd = g_mkstemp (tmpl: template); |
1197 | if (g_test_verbose() && fd != -1) |
1198 | g_printerr (format: "g_mkstemp works even if template doesn't end in XXXXXX\n" ); |
1199 | if (fd != -1) |
1200 | close (fd: fd); |
1201 | strcpy (dest: template, src: "fooXXXXXX" ); |
1202 | fd = g_mkstemp (tmpl: template); |
1203 | if (fd == -1) |
1204 | g_error ("g_mkstemp didn't work for template %s" , template); |
1205 | n = write (fd: fd, buf: hello, n: hellolen); |
1206 | errsv = errno; |
1207 | if (n == -1) |
1208 | g_error ("write() failed: %s" , g_strerror (errsv)); |
1209 | else if (n != hellolen) |
1210 | g_error ("write() should have written %d bytes, wrote %d" , hellolen, n); |
1211 | |
1212 | lseek (fd: fd, offset: 0, whence: 0); |
1213 | n = read (fd: fd, buf: chars, nbytes: sizeof (chars)); |
1214 | errsv = errno; |
1215 | if (n == -1) |
1216 | g_error ("read() failed: %s" , g_strerror (errsv)); |
1217 | else if (n != hellolen) |
1218 | g_error ("read() should have read %d bytes, got %d" , hellolen, n); |
1219 | |
1220 | chars[n] = 0; |
1221 | if (strcmp (s1: chars, s2: hello) != 0) |
1222 | g_error ("wrote '%s', but got '%s'" , hello, chars); |
1223 | if (fd != -1) |
1224 | close (fd: fd); |
1225 | remove (filename: template); |
1226 | |
1227 | error = NULL; |
1228 | name_used = NULL; |
1229 | strcpy (dest: template, src: "zap" G_DIR_SEPARATOR_S "barXXXXXX" ); |
1230 | fd = g_file_open_tmp (tmpl: template, name_used: &name_used, error: &error); |
1231 | if (g_test_verbose()) |
1232 | { |
1233 | if (fd != -1) |
1234 | g_printerr (format: "g_file_open_tmp works even if template contains '%s'\n" , G_DIR_SEPARATOR_S); |
1235 | else |
1236 | g_printerr (format: "g_file_open_tmp correctly returns error: %s\n" , error->message); |
1237 | } |
1238 | if (fd != -1) |
1239 | close (fd: fd); |
1240 | g_clear_error (err: &error); |
1241 | g_free (mem: name_used); |
1242 | |
1243 | #ifdef G_OS_WIN32 |
1244 | name_used = NULL; |
1245 | strcpy (template, "zap/barXXXXXX" ); |
1246 | fd = g_file_open_tmp (template, &name_used, &error); |
1247 | if (g_test_verbose()) |
1248 | { |
1249 | if (fd != -1) |
1250 | g_printerr ("g_file_open_tmp works even if template contains '/'\n" ); |
1251 | else |
1252 | g_printerr ("g_file_open_tmp correctly returns error: %s\n" , error->message); |
1253 | } |
1254 | if (fd != -1) |
1255 | close (fd); |
1256 | g_clear_error (&error); |
1257 | g_free (name_used); |
1258 | #endif |
1259 | |
1260 | strcpy (dest: template, src: "zapXXXXXX" ); |
1261 | name_used = NULL; |
1262 | fd = g_file_open_tmp (tmpl: template, name_used: &name_used, error: &error); |
1263 | if (fd == -1) |
1264 | g_error ("g_file_open_tmp didn't work for template '%s': %s" , template, error->message); |
1265 | else if (g_test_verbose()) |
1266 | g_printerr (format: "g_file_open_tmp for template '%s' used name '%s'\n" , template, name_used); |
1267 | if (fd != -1) |
1268 | close (fd: fd); |
1269 | g_clear_error (err: &error); |
1270 | remove (filename: name_used); |
1271 | g_free (mem: name_used); |
1272 | |
1273 | name_used = NULL; |
1274 | fd = g_file_open_tmp (NULL, name_used: &name_used, error: &error); |
1275 | if (fd == -1) |
1276 | g_error ("g_file_open_tmp didn't work for a NULL template: %s" , error->message); |
1277 | else |
1278 | close (fd: fd); |
1279 | g_clear_error (err: &error); |
1280 | remove (filename: name_used); |
1281 | g_free (mem: name_used); |
1282 | } |
1283 | |
1284 | static void |
1285 | test_arrays (void) |
1286 | { |
1287 | GByteArray *gbarray; |
1288 | GPtrArray *gparray; |
1289 | GArray *garray; |
1290 | guint i; |
1291 | |
1292 | gparray = g_ptr_array_new (); |
1293 | for (i = 0; i < 10000; i++) |
1294 | g_ptr_array_add (array: gparray, GINT_TO_POINTER (i)); |
1295 | for (i = 0; i < 10000; i++) |
1296 | if (g_ptr_array_index (gparray, i) != GINT_TO_POINTER (i)) |
1297 | g_error ("array fails: %p ( %p )" , g_ptr_array_index (gparray, i), GINT_TO_POINTER (i)); |
1298 | g_ptr_array_free (array: gparray, TRUE); |
1299 | |
1300 | gbarray = g_byte_array_new (); |
1301 | for (i = 0; i < 10000; i++) |
1302 | g_byte_array_append (array: gbarray, data: (guint8*) "abcd" , len: 4); |
1303 | for (i = 0; i < 10000; i++) |
1304 | { |
1305 | g_assert (gbarray->data[4*i] == 'a'); |
1306 | g_assert (gbarray->data[4*i+1] == 'b'); |
1307 | g_assert (gbarray->data[4*i+2] == 'c'); |
1308 | g_assert (gbarray->data[4*i+3] == 'd'); |
1309 | } |
1310 | g_byte_array_free (array: gbarray, TRUE); |
1311 | |
1312 | garray = g_array_new (FALSE, FALSE, element_size: sizeof (gint)); |
1313 | for (i = 0; i < 10000; i++) |
1314 | g_array_append_val (garray, i); |
1315 | for (i = 0; i < 10000; i++) |
1316 | if (g_array_index (garray, gint, i) != i) |
1317 | g_error ("failure: %d ( %d )" , g_array_index (garray, gint, i), i); |
1318 | g_array_free (array: garray, TRUE); |
1319 | |
1320 | garray = g_array_new (FALSE, FALSE, element_size: sizeof (gint)); |
1321 | for (i = 0; i < 100; i++) |
1322 | g_array_prepend_val (garray, i); |
1323 | for (i = 0; i < 100; i++) |
1324 | if (g_array_index (garray, gint, i) != (100 - i - 1)) |
1325 | g_error ("failure: %d ( %d )" , g_array_index (garray, gint, i), 100 - i - 1); |
1326 | g_array_free (array: garray, TRUE); |
1327 | } |
1328 | |
1329 | static void |
1330 | hash_table_tests (void) |
1331 | { |
1332 | GHashTable *hash_table; |
1333 | int array[10000]; |
1334 | gint *pvalue = NULL; |
1335 | gint value = 120; |
1336 | guint i; |
1337 | |
1338 | hash_table = g_hash_table_new (hash_func: my_hash, key_equal_func: my_hash_equal); |
1339 | for (i = 0; i < 10000; i++) |
1340 | { |
1341 | array[i] = i; |
1342 | g_hash_table_insert (hash_table, key: &array[i], value: &array[i]); |
1343 | } |
1344 | pvalue = g_hash_table_find (hash_table, predicate: find_first_that, user_data: &value); |
1345 | if (*pvalue != value) |
1346 | g_error ("g_hash_table_find failed" ); |
1347 | g_hash_table_foreach (hash_table, func: my_hash_callback, NULL); |
1348 | for (i = 0; i < 10000; i++) |
1349 | if (array[i] == 0) |
1350 | g_error ("hashtable-test: wrong value: %d" , i); |
1351 | for (i = 0; i < 10000; i++) |
1352 | g_hash_table_remove (hash_table, key: &array[i]); |
1353 | for (i = 0; i < 10000; i++) |
1354 | { |
1355 | array[i] = i; |
1356 | g_hash_table_insert (hash_table, key: &array[i], value: &array[i]); |
1357 | } |
1358 | if (g_hash_table_foreach_remove (hash_table, func: my_hash_callback_remove, NULL) != 5000 || |
1359 | g_hash_table_size (hash_table) != 5000) |
1360 | g_error ("hashtable removal failed" ); |
1361 | g_hash_table_foreach (hash_table, func: my_hash_callback_remove_test, NULL); |
1362 | g_hash_table_destroy (hash_table); |
1363 | } |
1364 | |
1365 | static void |
1366 | relation_test (void) |
1367 | { |
1368 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS |
1369 | |
1370 | GRelation *relation = g_relation_new (fields: 2); |
1371 | GTuples *tuples; |
1372 | gint data [1024]; |
1373 | guint i; |
1374 | |
1375 | g_relation_index (relation, field: 0, hash_func: g_int_hash, key_equal_func: g_int_equal); |
1376 | g_relation_index (relation, field: 1, hash_func: g_int_hash, key_equal_func: g_int_equal); |
1377 | |
1378 | for (i = 0; i < 1024; i += 1) |
1379 | data[i] = i; |
1380 | |
1381 | for (i = 1; i < 1023; i += 1) |
1382 | { |
1383 | g_relation_insert (relation, data + i, data + i + 1); |
1384 | g_relation_insert (relation, data + i, data + i - 1); |
1385 | } |
1386 | |
1387 | for (i = 2; i < 1022; i += 1) |
1388 | { |
1389 | g_assert (! g_relation_exists (relation, data + i, data + i)); |
1390 | g_assert (! g_relation_exists (relation, data + i, data + i + 2)); |
1391 | g_assert (! g_relation_exists (relation, data + i, data + i - 2)); |
1392 | } |
1393 | |
1394 | for (i = 1; i < 1023; i += 1) |
1395 | { |
1396 | g_assert (g_relation_exists (relation, data + i, data + i + 1)); |
1397 | g_assert (g_relation_exists (relation, data + i, data + i - 1)); |
1398 | } |
1399 | |
1400 | for (i = 2; i < 1022; i += 1) |
1401 | { |
1402 | g_assert (g_relation_count (relation, data + i, 0) == 2); |
1403 | g_assert (g_relation_count (relation, data + i, 1) == 2); |
1404 | } |
1405 | |
1406 | g_assert (g_relation_count (relation, data, 0) == 0); |
1407 | |
1408 | g_assert (g_relation_count (relation, data + 42, 0) == 2); |
1409 | g_assert (g_relation_count (relation, data + 43, 1) == 2); |
1410 | g_assert (g_relation_count (relation, data + 41, 1) == 2); |
1411 | g_relation_delete (relation, key: data + 42, field: 0); |
1412 | g_assert (g_relation_count (relation, data + 42, 0) == 0); |
1413 | g_assert (g_relation_count (relation, data + 43, 1) == 1); |
1414 | g_assert (g_relation_count (relation, data + 41, 1) == 1); |
1415 | |
1416 | tuples = g_relation_select (relation, key: data + 200, field: 0); |
1417 | |
1418 | g_assert (tuples->len == 2); |
1419 | |
1420 | #if 0 |
1421 | for (i = 0; i < tuples->len; i += 1) |
1422 | { |
1423 | printf ("%d %d\n" , |
1424 | *(gint*) g_tuples_index (tuples, i, 0), |
1425 | *(gint*) g_tuples_index (tuples, i, 1)); |
1426 | } |
1427 | #endif |
1428 | |
1429 | g_assert (g_relation_exists (relation, data + 300, data + 301)); |
1430 | g_relation_delete (relation, key: data + 300, field: 0); |
1431 | g_assert (!g_relation_exists (relation, data + 300, data + 301)); |
1432 | |
1433 | g_tuples_destroy (tuples); |
1434 | |
1435 | g_relation_destroy (relation); |
1436 | |
1437 | relation = NULL; |
1438 | |
1439 | G_GNUC_END_IGNORE_DEPRECATIONS |
1440 | } |
1441 | |
1442 | static void |
1443 | gstring_tests (void) |
1444 | { |
1445 | GString *string1, *string2; |
1446 | guint i; |
1447 | |
1448 | if (g_test_verbose()) |
1449 | g_printerr (format: "test GString basics\n" ); |
1450 | |
1451 | string1 = g_string_new (init: "hi pete!" ); |
1452 | string2 = g_string_new (init: "" ); |
1453 | |
1454 | g_assert (strcmp ("hi pete!" , string1->str) == 0); |
1455 | |
1456 | for (i = 0; i < 10000; i++) |
1457 | g_string_append_c (string1, 'a'+(i%26)); |
1458 | |
1459 | #ifndef G_OS_WIN32 |
1460 | /* MSVC, mingw32 and LCC use the same run-time C library, which doesn't like |
1461 | the %10000.10000f format... */ |
1462 | g_string_printf (string: string2, format: "%s|%0100d|%s|%s|%0*d|%*.*f|%10000.10000f" , |
1463 | "this pete guy sure is a wuss, like he's the number " , |
1464 | 1, |
1465 | " wuss. everyone agrees.\n" , |
1466 | string1->str, |
1467 | 10, 666, 15, 15, 666.666666666, 666.666666666); |
1468 | #else |
1469 | g_string_printf (string2, "%s|%0100d|%s|%s|%0*d|%*.*f|%100.100f" , |
1470 | "this pete guy sure is a wuss, like he's the number " , |
1471 | 1, |
1472 | " wuss. everyone agrees.\n" , |
1473 | string1->str, |
1474 | 10, 666, 15, 15, 666.666666666, 666.666666666); |
1475 | #endif |
1476 | |
1477 | if (g_test_verbose()) |
1478 | g_printerr (format: "string2 length = %lu...\n" , (gulong)string2->len); |
1479 | string2->str[70] = '\0'; |
1480 | if (g_test_verbose()) |
1481 | g_printerr (format: "first 70 chars:\n%s\n" , string2->str); |
1482 | string2->str[141] = '\0'; |
1483 | if (g_test_verbose()) |
1484 | g_printerr (format: "next 70 chars:\n%s\n" , string2->str+71); |
1485 | string2->str[212] = '\0'; |
1486 | if (g_test_verbose()) |
1487 | g_printerr (format: "and next 70:\n%s\n" , string2->str+142); |
1488 | if (g_test_verbose()) |
1489 | g_printerr (format: "last 70 chars:\n%s\n" , string2->str+string2->len - 70); |
1490 | |
1491 | g_string_free (string: string1, TRUE); |
1492 | g_string_free (string: string2, TRUE); |
1493 | |
1494 | /* append */ |
1495 | string1 = g_string_new (init: "firsthalf" ); |
1496 | g_string_append (string: string1, val: "lasthalf" ); |
1497 | g_assert (strcmp (string1->str, "firsthalflasthalf" ) == 0); |
1498 | g_string_free (string: string1, TRUE); |
1499 | |
1500 | /* append_len */ |
1501 | string1 = g_string_new (init: "firsthalf" ); |
1502 | g_string_append_len (string: string1, val: "lasthalfjunkjunk" , len: strlen (s: "lasthalf" )); |
1503 | g_assert (strcmp (string1->str, "firsthalflasthalf" ) == 0); |
1504 | g_string_free (string: string1, TRUE); |
1505 | |
1506 | /* prepend */ |
1507 | string1 = g_string_new (init: "lasthalf" ); |
1508 | g_string_prepend (string: string1, val: "firsthalf" ); |
1509 | g_assert (strcmp (string1->str, "firsthalflasthalf" ) == 0); |
1510 | g_string_free (string: string1, TRUE); |
1511 | |
1512 | /* prepend_len */ |
1513 | string1 = g_string_new (init: "lasthalf" ); |
1514 | g_string_prepend_len (string: string1, val: "firsthalfjunkjunk" , len: strlen (s: "firsthalf" )); |
1515 | g_assert (strcmp (string1->str, "firsthalflasthalf" ) == 0); |
1516 | g_string_free (string: string1, TRUE); |
1517 | |
1518 | /* insert */ |
1519 | string1 = g_string_new (init: "firstlast" ); |
1520 | g_string_insert (string: string1, pos: 5, val: "middle" ); |
1521 | g_assert (strcmp (string1->str, "firstmiddlelast" ) == 0); |
1522 | g_string_free (string: string1, TRUE); |
1523 | |
1524 | /* insert with pos == end of the string */ |
1525 | string1 = g_string_new (init: "firstmiddle" ); |
1526 | g_string_insert (string: string1, pos: strlen (s: "firstmiddle" ), val: "last" ); |
1527 | g_assert (strcmp (string1->str, "firstmiddlelast" ) == 0); |
1528 | g_string_free (string: string1, TRUE); |
1529 | |
1530 | /* insert_len */ |
1531 | string1 = g_string_new (init: "firstlast" ); |
1532 | g_string_insert_len (string: string1, pos: 5, val: "middlejunkjunk" , len: strlen (s: "middle" )); |
1533 | g_assert (strcmp (string1->str, "firstmiddlelast" ) == 0); |
1534 | g_string_free (string: string1, TRUE); |
1535 | |
1536 | /* insert_len with magic -1 pos for append */ |
1537 | string1 = g_string_new (init: "first" ); |
1538 | g_string_insert_len (string: string1, pos: -1, val: "lastjunkjunk" , len: strlen (s: "last" )); |
1539 | g_assert (strcmp (string1->str, "firstlast" ) == 0); |
1540 | g_string_free (string: string1, TRUE); |
1541 | |
1542 | /* insert_len with magic -1 len for strlen-the-string */ |
1543 | string1 = g_string_new (init: "first" ); |
1544 | g_string_insert_len (string: string1, pos: 5, val: "last" , len: -1); |
1545 | g_assert (strcmp (string1->str, "firstlast" ) == 0); |
1546 | g_string_free (string: string1, TRUE); |
1547 | |
1548 | /* g_string_equal */ |
1549 | string1 = g_string_new (init: "test" ); |
1550 | string2 = g_string_new (init: "te" ); |
1551 | g_assert (! g_string_equal(string1, string2)); |
1552 | g_string_append (string: string2, val: "st" ); |
1553 | g_assert (g_string_equal(string1, string2)); |
1554 | g_string_free (string: string1, TRUE); |
1555 | g_string_free (string: string2, TRUE); |
1556 | |
1557 | /* Check handling of embedded ASCII 0 (NUL) characters in GString. */ |
1558 | if (g_test_verbose()) |
1559 | g_printerr (format: "test embedded ASCII 0 (NUL) characters in GString\n" ); |
1560 | string1 = g_string_new (init: "fiddle" ); |
1561 | string2 = g_string_new (init: "fiddle" ); |
1562 | g_assert (g_string_equal(string1, string2)); |
1563 | g_string_append_c(string1, '\0'); |
1564 | g_assert (! g_string_equal(string1, string2)); |
1565 | g_string_append_c(string2, '\0'); |
1566 | g_assert (g_string_equal(string1, string2)); |
1567 | g_string_append_c(string1, 'x'); |
1568 | g_string_append_c(string2, 'y'); |
1569 | g_assert (! g_string_equal(string1, string2)); |
1570 | g_assert (string1->len == 8); |
1571 | g_string_append(string: string1, val: "yzzy" ); |
1572 | g_assert (string1->len == 12); |
1573 | g_assert ( memcmp(string1->str, "fiddle\0xyzzy" , 13) == 0); |
1574 | g_string_insert(string: string1, pos: 1, val: "QED" ); |
1575 | g_assert ( memcmp(string1->str, "fQEDiddle\0xyzzy" , 16) == 0); |
1576 | g_string_free (string: string1, TRUE); |
1577 | g_string_free (string: string2, TRUE); |
1578 | } |
1579 | |
1580 | static void |
1581 | various_string_tests (void) |
1582 | { |
1583 | GStringChunk *string_chunk; |
1584 | GTimeVal ref_date, date; |
1585 | gchar *tmp_string = NULL, *tmp_string_2, *string, *date_str; |
1586 | guint i; |
1587 | const gchar *tz; |
1588 | |
1589 | if (g_test_verbose()) |
1590 | g_printerr (format: "checking string chunks..." ); |
1591 | string_chunk = g_string_chunk_new (size: 1024); |
1592 | for (i = 0; i < 100000; i ++) |
1593 | { |
1594 | tmp_string = g_string_chunk_insert (chunk: string_chunk, string: "hi pete" ); |
1595 | if (strcmp (s1: "hi pete" , s2: tmp_string) != 0) |
1596 | g_error ("string chunks are broken." ); |
1597 | } |
1598 | tmp_string_2 = g_string_chunk_insert_const (chunk: string_chunk, string: tmp_string); |
1599 | g_assert (tmp_string_2 != tmp_string && strcmp (tmp_string_2, tmp_string) == 0); |
1600 | tmp_string = g_string_chunk_insert_const (chunk: string_chunk, string: tmp_string); |
1601 | g_assert (tmp_string_2 == tmp_string); |
1602 | g_string_chunk_free (chunk: string_chunk); |
1603 | |
1604 | if (g_test_verbose()) |
1605 | g_printerr (format: "test positional printf formats (not supported):" ); |
1606 | string = g_strdup_printf (format: "%.*s%s" , 5, "a" , "b" ); |
1607 | tmp_string = g_strdup_printf (format: "%2$*1$s" , 5, "c" ); |
1608 | if (g_test_verbose()) |
1609 | g_printerr (format: "%s%s\n" , string, tmp_string); |
1610 | g_free (mem: tmp_string); |
1611 | g_free (mem: string); |
1612 | |
1613 | #define REF_INVALID1 "Wed Dec 19 17:20:20 GMT 2007" |
1614 | #define REF_INVALID2 "1980-02-22T10:36:00Zulu" |
1615 | #define REF_INVALID3 "1980-02-22T" |
1616 | #define REF_SEC_UTC 320063760 |
1617 | #define REF_STR_UTC "1980-02-22T10:36:00Z" |
1618 | #define REF_STR_LOCAL "1980-02-22T13:36:00" |
1619 | #define REF_STR_CEST "1980-02-22T12:36:00+02:00" |
1620 | #define REF_STR_EST "19800222T053600-0500" |
1621 | #define REF_STR_NST "1980-02-22T07:06:00-03:30" |
1622 | #define REF_USEC_UTC 50000 |
1623 | #define REF_STR_USEC_UTC "1980-02-22T10:36:00.050000Z" |
1624 | #define REF_STR_USEC_CEST "19800222T123600.050000000+0200" |
1625 | #define REF_STR_USEC_EST "1980-02-22T05:36:00,05-05:00" |
1626 | #define REF_STR_USEC_NST "19800222T070600,0500-0330" |
1627 | #define REF_STR_DATE_ONLY "1980-02-22" |
1628 | |
1629 | if (g_test_verbose()) |
1630 | g_printerr (format: "checking g_time_val_from_iso8601...\n" ); |
1631 | ref_date.tv_sec = REF_SEC_UTC; |
1632 | ref_date.tv_usec = 0; |
1633 | g_assert (g_time_val_from_iso8601 (REF_INVALID1, &date) == FALSE); |
1634 | g_assert (g_time_val_from_iso8601 (REF_INVALID2, &date) == FALSE); |
1635 | g_assert (g_time_val_from_iso8601 (REF_INVALID3, &date) == FALSE); |
1636 | g_assert (g_time_val_from_iso8601 (REF_STR_DATE_ONLY, &date) == FALSE); |
1637 | g_assert (g_time_val_from_iso8601 (REF_STR_UTC, &date) != FALSE); |
1638 | if (g_test_verbose()) |
1639 | g_printerr (format: "\t=> UTC stamp = %ld.%06ld (should be: %ld.%06ld) (%ld.%06ld off)\n" , |
1640 | date.tv_sec, date.tv_usec, ref_date.tv_sec, ref_date.tv_usec, |
1641 | date.tv_sec - ref_date.tv_sec, date.tv_usec - ref_date.tv_usec); |
1642 | g_assert (date.tv_sec == ref_date.tv_sec && date.tv_usec == ref_date.tv_usec); |
1643 | |
1644 | /* predefine time zone */ |
1645 | tz = g_getenv(variable: "TZ" ); |
1646 | g_setenv(variable: "TZ" , value: "UTC-03:00" , overwrite: 1); |
1647 | tzset(); |
1648 | |
1649 | g_assert (g_time_val_from_iso8601 (REF_STR_LOCAL, &date) != FALSE); |
1650 | if (g_test_verbose()) |
1651 | g_printerr (format: "\t=> LOCAL stamp = %ld.%06ld (should be: %ld.%06ld) (%ld.%06ld off)\n" , |
1652 | date.tv_sec, date.tv_usec, ref_date.tv_sec, ref_date.tv_usec, |
1653 | date.tv_sec - ref_date.tv_sec, date.tv_usec - ref_date.tv_usec); |
1654 | g_assert (date.tv_sec == ref_date.tv_sec && date.tv_usec == ref_date.tv_usec); |
1655 | |
1656 | /* revert back user defined time zone */ |
1657 | if (tz) |
1658 | g_setenv(variable: "TZ" , value: tz, TRUE); |
1659 | else |
1660 | g_unsetenv(variable: "TZ" ); |
1661 | tzset(); |
1662 | |
1663 | g_assert (g_time_val_from_iso8601 (REF_STR_CEST, &date) != FALSE); |
1664 | if (g_test_verbose()) |
1665 | g_printerr (format: "\t=> CEST stamp = %ld.%06ld (should be: %ld.%06ld) (%ld.%06ld off)\n" , |
1666 | date.tv_sec, date.tv_usec, ref_date.tv_sec, ref_date.tv_usec, |
1667 | date.tv_sec - ref_date.tv_sec, date.tv_usec - ref_date.tv_usec); |
1668 | g_assert (date.tv_sec == ref_date.tv_sec && date.tv_usec == ref_date.tv_usec); |
1669 | |
1670 | g_assert (g_time_val_from_iso8601 (REF_STR_EST, &date) != FALSE); |
1671 | if (g_test_verbose()) |
1672 | g_printerr (format: "\t=> EST stamp = %ld.%06ld (should be: %ld.%06ld) (%ld.%06ld off)\n" , |
1673 | date.tv_sec, date.tv_usec, ref_date.tv_sec, ref_date.tv_usec, |
1674 | date.tv_sec - ref_date.tv_sec, date.tv_usec - ref_date.tv_usec); |
1675 | g_assert (date.tv_sec == ref_date.tv_sec && date.tv_usec == ref_date.tv_usec); |
1676 | |
1677 | g_assert (g_time_val_from_iso8601 (REF_STR_NST, &date) != FALSE); |
1678 | if (g_test_verbose()) |
1679 | g_printerr (format: "\t=> NST stamp = %ld.%06ld (should be: %ld.%06ld) (%ld.%06ld off)\n" , |
1680 | date.tv_sec, date.tv_usec, ref_date.tv_sec, ref_date.tv_usec, |
1681 | date.tv_sec - ref_date.tv_sec, date.tv_usec - ref_date.tv_usec); |
1682 | g_assert (date.tv_sec == ref_date.tv_sec && date.tv_usec == ref_date.tv_usec); |
1683 | |
1684 | ref_date.tv_usec = REF_USEC_UTC; |
1685 | g_assert (g_time_val_from_iso8601 (REF_STR_USEC_UTC, &date) != FALSE); |
1686 | if (g_test_verbose()) |
1687 | g_printerr (format: "\t=> UTC stamp = %ld.%06ld (should be: %ld.%06ld) (%ld.%06ld off)\n" , |
1688 | date.tv_sec, date.tv_usec, ref_date.tv_sec, ref_date.tv_usec, |
1689 | date.tv_sec - ref_date.tv_sec, date.tv_usec - ref_date.tv_usec); |
1690 | g_assert (date.tv_sec == ref_date.tv_sec && date.tv_usec == ref_date.tv_usec); |
1691 | |
1692 | g_assert (g_time_val_from_iso8601 (REF_STR_USEC_CEST, &date) != FALSE); |
1693 | if (g_test_verbose()) |
1694 | g_printerr (format: "\t=> CEST stamp = %ld.%06ld (should be: %ld.%06ld) (%ld.%06ld off)\n" , |
1695 | date.tv_sec, date.tv_usec, ref_date.tv_sec, ref_date.tv_usec, |
1696 | date.tv_sec - ref_date.tv_sec, date.tv_usec - ref_date.tv_usec); |
1697 | g_assert (date.tv_sec == ref_date.tv_sec && date.tv_usec == ref_date.tv_usec); |
1698 | |
1699 | g_assert (g_time_val_from_iso8601 (REF_STR_USEC_EST, &date) != FALSE); |
1700 | if (g_test_verbose()) |
1701 | g_printerr (format: "\t=> EST stamp = %ld.%06ld (should be: %ld.%06ld) (%ld.%06ld off)\n" , |
1702 | date.tv_sec, date.tv_usec, ref_date.tv_sec, ref_date.tv_usec, |
1703 | date.tv_sec - ref_date.tv_sec, date.tv_usec - ref_date.tv_usec); |
1704 | g_assert (date.tv_sec == ref_date.tv_sec && date.tv_usec == ref_date.tv_usec); |
1705 | |
1706 | g_assert (g_time_val_from_iso8601 (REF_STR_USEC_NST, &date) != FALSE); |
1707 | if (g_test_verbose()) |
1708 | g_printerr (format: "\t=> NST stamp = %ld.%06ld (should be: %ld.%06ld) (%ld.%06ld off)\n" , |
1709 | date.tv_sec, date.tv_usec, ref_date.tv_sec, ref_date.tv_usec, |
1710 | date.tv_sec - ref_date.tv_sec, date.tv_usec - ref_date.tv_usec); |
1711 | g_assert (date.tv_sec == ref_date.tv_sec && date.tv_usec == ref_date.tv_usec); |
1712 | |
1713 | if (g_test_verbose()) |
1714 | g_printerr (format: "checking g_time_val_to_iso8601...\n" ); |
1715 | ref_date.tv_sec = REF_SEC_UTC; |
1716 | ref_date.tv_usec = 0; |
1717 | date_str = g_time_val_to_iso8601 (time_: &ref_date); |
1718 | g_assert (date_str != NULL); |
1719 | if (g_test_verbose()) |
1720 | g_printerr (format: "\t=> date string = %s (should be: %s)\n" , date_str, REF_STR_UTC); |
1721 | g_assert (strcmp (date_str, REF_STR_UTC) == 0); |
1722 | g_free (mem: date_str); |
1723 | |
1724 | ref_date.tv_usec = REF_USEC_UTC; |
1725 | date_str = g_time_val_to_iso8601 (time_: &ref_date); |
1726 | g_assert (date_str != NULL); |
1727 | if (g_test_verbose()) |
1728 | g_printerr (format: "\t=> date string = %s (should be: %s)\n" , date_str, REF_STR_USEC_UTC); |
1729 | g_assert (strcmp (date_str, REF_STR_USEC_UTC) == 0); |
1730 | g_free (mem: date_str); |
1731 | |
1732 | if (g_test_verbose()) |
1733 | g_printerr (format: "checking g_ascii_strcasecmp..." ); |
1734 | g_assert (g_ascii_strcasecmp ("FroboZZ" , "frobozz" ) == 0); |
1735 | g_assert (g_ascii_strcasecmp ("frobozz" , "frobozz" ) == 0); |
1736 | g_assert (g_ascii_strcasecmp ("frobozz" , "FROBOZZ" ) == 0); |
1737 | g_assert (g_ascii_strcasecmp ("FROBOZZ" , "froboz" ) > 0); |
1738 | g_assert (g_ascii_strcasecmp ("" , "" ) == 0); |
1739 | g_assert (g_ascii_strcasecmp ("!#%&/()" , "!#%&/()" ) == 0); |
1740 | g_assert (g_ascii_strcasecmp ("a" , "b" ) < 0); |
1741 | g_assert (g_ascii_strcasecmp ("a" , "B" ) < 0); |
1742 | g_assert (g_ascii_strcasecmp ("A" , "b" ) < 0); |
1743 | g_assert (g_ascii_strcasecmp ("A" , "B" ) < 0); |
1744 | g_assert (g_ascii_strcasecmp ("b" , "a" ) > 0); |
1745 | g_assert (g_ascii_strcasecmp ("b" , "A" ) > 0); |
1746 | g_assert (g_ascii_strcasecmp ("B" , "a" ) > 0); |
1747 | g_assert (g_ascii_strcasecmp ("B" , "A" ) > 0); |
1748 | |
1749 | if (g_test_verbose()) |
1750 | g_printerr (format: "checking g_strdup...\n" ); |
1751 | g_assert (g_strdup (NULL) == NULL); |
1752 | string = g_strdup (GLIB_TEST_STRING); |
1753 | g_assert (string != NULL); |
1754 | g_assert (strcmp(string, GLIB_TEST_STRING) == 0); |
1755 | g_free (mem: string); |
1756 | |
1757 | if (g_test_verbose()) |
1758 | g_printerr (format: "checking g_strconcat...\n" ); |
1759 | string = g_strconcat (GLIB_TEST_STRING, NULL); |
1760 | g_assert (string != NULL); |
1761 | g_assert (strcmp (string, GLIB_TEST_STRING) == 0); |
1762 | g_free (mem: string); |
1763 | string = g_strconcat (GLIB_TEST_STRING, GLIB_TEST_STRING, |
1764 | GLIB_TEST_STRING, NULL); |
1765 | g_assert (string != NULL); |
1766 | g_assert (strcmp (string, GLIB_TEST_STRING GLIB_TEST_STRING |
1767 | GLIB_TEST_STRING) == 0); |
1768 | g_free (mem: string); |
1769 | |
1770 | if (g_test_verbose()) |
1771 | g_printerr (format: "checking g_strlcpy/g_strlcat..." ); |
1772 | /* The following is a torture test for strlcpy/strlcat, with lots of |
1773 | * checking; normal users wouldn't use them this way! |
1774 | */ |
1775 | string = g_malloc (n_bytes: 6); |
1776 | *(string + 5) = 'Z'; /* guard value, shouldn't change during test */ |
1777 | *string = 'q'; |
1778 | g_assert (g_strlcpy(string, "" , 5) == 0); |
1779 | g_assert ( *string == '\0' ); |
1780 | *string = 'q'; |
1781 | g_assert (g_strlcpy(string, "abc" , 5) == 3); |
1782 | g_assert ( *(string + 3) == '\0' ); |
1783 | g_assert (g_str_equal(string, "abc" )); |
1784 | g_assert (g_strlcpy(string, "abcd" , 5) == 4); |
1785 | g_assert ( *(string + 4) == '\0' ); |
1786 | g_assert ( *(string + 5) == 'Z' ); |
1787 | g_assert (g_str_equal(string, "abcd" )); |
1788 | g_assert (g_strlcpy(string, "abcde" , 5) == 5); |
1789 | g_assert ( *(string + 4) == '\0' ); |
1790 | g_assert ( *(string + 5) == 'Z' ); |
1791 | g_assert (g_str_equal(string, "abcd" )); |
1792 | g_assert (g_strlcpy(string, "abcdef" , 5) == 6); |
1793 | g_assert ( *(string + 4) == '\0' ); |
1794 | g_assert ( *(string + 5) == 'Z' ); |
1795 | g_assert (g_str_equal(string, "abcd" )); |
1796 | *string = 'Y'; |
1797 | *(string + 1)= '\0'; |
1798 | g_assert (g_strlcpy(string, "Hello" , 0) == 5); |
1799 | g_assert (*string == 'Y'); |
1800 | *string = '\0'; |
1801 | g_assert (g_strlcat(string, "123" , 5) == 3); |
1802 | g_assert ( *(string + 3) == '\0' ); |
1803 | g_assert (g_str_equal(string, "123" )); |
1804 | g_assert (g_strlcat(string, "" , 5) == 3); |
1805 | g_assert ( *(string + 3) == '\0' ); |
1806 | g_assert (g_str_equal(string, "123" )); |
1807 | g_assert (g_strlcat(string, "4" , 5) == 4); |
1808 | g_assert (g_str_equal(string, "1234" )); |
1809 | g_assert (g_strlcat(string, "5" , 5) == 5); |
1810 | g_assert ( *(string + 4) == '\0' ); |
1811 | g_assert (g_str_equal(string, "1234" )); |
1812 | g_assert ( *(string + 5) == 'Z' ); |
1813 | *string = 'Y'; |
1814 | *(string + 1)= '\0'; |
1815 | g_assert (g_strlcat(string, "123" , 0) == 3); |
1816 | g_assert (*string == 'Y'); |
1817 | |
1818 | /* A few more tests, demonstrating more "normal" use */ |
1819 | g_assert (g_strlcpy(string, "hi" , 5) == 2); |
1820 | g_assert (g_str_equal(string, "hi" )); |
1821 | g_assert (g_strlcat(string, "t" , 5) == 3); |
1822 | g_assert (g_str_equal(string, "hit" )); |
1823 | g_free(mem: string); |
1824 | |
1825 | if (g_test_verbose()) |
1826 | g_printerr (format: "checking g_strdup_printf...\n" ); |
1827 | string = g_strdup_printf (format: "%05d %-5s" , 21, "test" ); |
1828 | g_assert (string != NULL); |
1829 | g_assert (strcmp(string, "00021 test " ) == 0); |
1830 | g_free (mem: string); |
1831 | |
1832 | /* g_debug (argv[0]); */ |
1833 | } |
1834 | |
1835 | static void |
1836 | test_mem_chunks (void) |
1837 | { |
1838 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS |
1839 | |
1840 | GMemChunk *mem_chunk = g_mem_chunk_new (name: "test mem chunk" , atom_size: 50, area_size: 100, G_ALLOC_AND_FREE); |
1841 | gchar *mem[10000]; |
1842 | guint i; |
1843 | for (i = 0; i < 10000; i++) |
1844 | { |
1845 | guint j; |
1846 | mem[i] = g_chunk_new (gchar, mem_chunk); |
1847 | for (j = 0; j < 50; j++) |
1848 | mem[i][j] = i * j; |
1849 | } |
1850 | for (i = 0; i < 10000; i++) |
1851 | g_mem_chunk_free (mem_chunk, mem: mem[i]); |
1852 | |
1853 | g_mem_chunk_destroy (mem_chunk); |
1854 | |
1855 | G_GNUC_END_IGNORE_DEPRECATIONS |
1856 | } |
1857 | |
1858 | int |
1859 | main (int argc, |
1860 | char *argv[]) |
1861 | { |
1862 | g_test_init (argc: &argc, argv: &argv, NULL); |
1863 | |
1864 | g_test_add_func (testpath: "/testglib/Infos" , test_func: test_info); |
1865 | g_test_add_func (testpath: "/testglib/Types Sizes" , test_func: type_sizes); |
1866 | g_test_add_func (testpath: "/testglib/GStrings" , test_func: gstring_tests); |
1867 | g_test_add_func (testpath: "/testglib/Various Strings" , test_func: various_string_tests); |
1868 | g_test_add_func (testpath: "/testglib/GList" , test_func: glist_test); |
1869 | g_test_add_func (testpath: "/testglib/GSList" , test_func: gslist_test); |
1870 | g_test_add_func (testpath: "/testglib/GNode" , test_func: gnode_test); |
1871 | g_test_add_func (testpath: "/testglib/GTree" , test_func: binary_tree_test); |
1872 | g_test_add_func (testpath: "/testglib/Arrays" , test_func: test_arrays); |
1873 | g_test_add_func (testpath: "/testglib/GHashTable" , test_func: hash_table_tests); |
1874 | g_test_add_func (testpath: "/testglib/Relation (deprecated)" , test_func: relation_test); |
1875 | g_test_add_func (testpath: "/testglib/File Paths" , test_func: test_paths); |
1876 | g_test_add_func (testpath: "/testglib/File Functions" , test_func: test_file_functions); |
1877 | g_test_add_func (testpath: "/testglib/Parse Debug Strings" , test_func: test_g_parse_debug_string); |
1878 | g_test_add_func (testpath: "/testglib/GMemChunk (deprecated)" , test_func: test_mem_chunks); |
1879 | g_test_add_func (testpath: "/testglib/Warnings & Errors" , test_func: log_warning_error_tests); |
1880 | g_test_add_func (testpath: "/testglib/Warnings (rate limited)" , test_func: log_warning_rate_limited_tests); |
1881 | g_test_add_func (testpath: "/testglib/Timers (slow)" , test_func: timer_tests); |
1882 | |
1883 | return g_test_run(); |
1884 | } |
1885 | |