Fix #117925 (Dov Grobgeld):
[platform/upstream/glib.git] / tests / testglib.c
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 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, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GLib Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include "config.h"
28
29 #undef G_DISABLE_ASSERT
30 #undef G_LOG_DOMAIN
31
32 #ifdef GLIB_COMPILATION
33 #undef GLIB_COMPILATION
34 #endif
35
36 #include <stdio.h>
37 #include <string.h>
38 #include <errno.h>
39
40 #include "glib.h"
41
42 #ifdef HAVE_UNISTD_H
43 #include <unistd.h>
44 #endif
45
46 #ifdef G_OS_WIN32
47 #include <io.h>                 /* For read(), write() etc */
48 #endif
49
50 static int array[10000];
51 static gboolean failed = FALSE;
52
53 /* We write (m ? m : "") even in the m != NULL case to suppress a warning with GCC-3.1
54  */
55 #define TEST(m,cond)    G_STMT_START { failed = !(cond); \
56 if (failed) \
57   { if (!m) \
58       g_print ("\n(%s:%d) failed for: %s\n", __FILE__, __LINE__, ( # cond )); \
59     else \
60       g_print ("\n(%s:%d) failed for: %s: (%s)\n", __FILE__, __LINE__, ( # cond ), (gchar*)(m ? m : "")); \
61   } \
62 else \
63   g_print ("."); fflush (stdout); \
64 } G_STMT_END
65
66 #define C2P(c)          ((gpointer) ((long) (c)))
67 #define P2C(p)          ((gchar) ((long) (p)))
68
69 #define GLIB_TEST_STRING "el dorado "
70 #define GLIB_TEST_STRING_5 "el do"
71
72 static gboolean
73 node_build_string (GNode    *node,
74                    gpointer  data)
75 {
76   gchar **p = data;
77   gchar *string;
78   gchar c[2] = "_";
79
80   c[0] = P2C (node->data);
81
82   string = g_strconcat (*p ? *p : "", c, NULL);
83   g_free (*p);
84   *p = string;
85
86   return FALSE;
87 }
88
89 static void
90 g_node_test (void)
91 {
92   GNode *root;
93   GNode *node;
94   GNode *node_B;
95   GNode *node_F;
96   GNode *node_G;
97   GNode *node_J;
98   guint i;
99   gchar *tstring, *cstring;
100
101   g_print ("checking n-way trees: ");
102   failed = FALSE;
103
104   root = g_node_new (C2P ('A'));
105   TEST (NULL, g_node_depth (root) == 1 && g_node_max_height (root) == 1);
106
107   node_B = g_node_new (C2P ('B'));
108   g_node_append (root, node_B);
109   TEST (NULL, root->children == node_B);
110
111   g_node_append_data (node_B, C2P ('E'));
112   g_node_prepend_data (node_B, C2P ('C'));
113   g_node_insert (node_B, 1, g_node_new (C2P ('D')));
114
115   node_F = g_node_new (C2P ('F'));
116   g_node_append (root, node_F);
117   TEST (NULL, root->children->next == node_F);
118
119   node_G = g_node_new (C2P ('G'));
120   g_node_append (node_F, node_G);
121   node_J = g_node_new (C2P ('J'));
122   g_node_prepend (node_G, node_J);
123   g_node_insert (node_G, 42, g_node_new (C2P ('K')));
124   g_node_insert_data (node_G, 0, C2P ('H'));
125   g_node_insert (node_G, 1, g_node_new (C2P ('I')));
126
127   TEST (NULL, g_node_depth (root) == 1);
128   TEST (NULL, g_node_max_height (root) == 4);
129   TEST (NULL, g_node_depth (node_G->children->next) == 4);
130   TEST (NULL, g_node_n_nodes (root, G_TRAVERSE_LEAFS) == 7);
131   TEST (NULL, g_node_n_nodes (root, G_TRAVERSE_NON_LEAFS) == 4);
132   TEST (NULL, g_node_n_nodes (root, G_TRAVERSE_ALL) == 11);
133   TEST (NULL, g_node_max_height (node_F) == 3);
134   TEST (NULL, g_node_n_children (node_G) == 4);
135   TEST (NULL, g_node_find_child (root, G_TRAVERSE_ALL, C2P ('F')) == node_F);
136   TEST (NULL, g_node_find (root, G_LEVEL_ORDER, G_TRAVERSE_NON_LEAFS, C2P ('I')) == NULL);
137   TEST (NULL, g_node_find (root, G_IN_ORDER, G_TRAVERSE_LEAFS, C2P ('J')) == node_J);
138
139   for (i = 0; i < g_node_n_children (node_B); i++)
140     {
141       node = g_node_nth_child (node_B, i);
142       TEST (NULL, P2C (node->data) == ('C' + i));
143     }
144   
145   for (i = 0; i < g_node_n_children (node_G); i++)
146     TEST (NULL, g_node_child_position (node_G, g_node_nth_child (node_G, i)) == i);
147
148   /* we have built:                    A
149    *                                 /   \
150    *                               B       F
151    *                             / | \       \
152    *                           C   D   E       G
153    *                                         / /\ \
154    *                                       H  I  J  K
155    *
156    * for in-order traversal, 'G' is considered to be the "left"
157    * child of 'F', which will cause 'F' to be the last node visited.
158    */
159
160   tstring = NULL;
161   g_node_traverse (root, G_PRE_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &tstring);
162   TEST (tstring, strcmp (tstring, "ABCDEFGHIJK") == 0);
163   g_free (tstring); tstring = NULL;
164   g_node_traverse (root, G_POST_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &tstring);
165   TEST (tstring, strcmp (tstring, "CDEBHIJKGFA") == 0);
166   g_free (tstring); tstring = NULL;
167   g_node_traverse (root, G_IN_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &tstring);
168   TEST (tstring, strcmp (tstring, "CBDEAHGIJKF") == 0);
169   g_free (tstring); tstring = NULL;
170   g_node_traverse (root, G_LEVEL_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &tstring);
171   TEST (tstring, strcmp (tstring, "ABFCDEGHIJK") == 0);
172   g_free (tstring); tstring = NULL;
173   
174   g_node_traverse (root, G_LEVEL_ORDER, G_TRAVERSE_LEAFS, -1, node_build_string, &tstring);
175   TEST (tstring, strcmp (tstring, "CDEHIJK") == 0);
176   g_free (tstring); tstring = NULL;
177   g_node_traverse (root, G_PRE_ORDER, G_TRAVERSE_NON_LEAFS, -1, node_build_string, &tstring);
178   TEST (tstring, strcmp (tstring, "ABFG") == 0);
179   g_free (tstring); tstring = NULL;
180
181   g_node_reverse_children (node_B);
182   g_node_reverse_children (node_G);
183
184   g_node_traverse (root, G_LEVEL_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &tstring);
185   TEST (tstring, strcmp (tstring, "ABFEDCGKJIH") == 0);
186   g_free (tstring); tstring = NULL;
187
188   cstring = NULL;
189   node = g_node_copy (root);
190   TEST (NULL, g_node_n_nodes (root, G_TRAVERSE_ALL) == g_node_n_nodes (node, G_TRAVERSE_ALL));
191   TEST (NULL, g_node_max_height (root) == g_node_max_height (node));
192   g_node_traverse (root, G_IN_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &tstring);
193   g_node_traverse (node, G_IN_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &cstring);
194   TEST (cstring, strcmp (tstring, cstring) == 0);
195   g_free (tstring); tstring = NULL;
196   g_free (cstring); cstring = NULL;
197   g_node_destroy (node);
198
199   g_node_destroy (root);
200
201   /* allocation tests */
202
203   root = g_node_new (NULL);
204   node = root;
205
206   for (i = 0; i < 2048; i++)
207     {
208       g_node_append (node, g_node_new (NULL));
209       if ((i%5) == 4)
210         node = node->children->next;
211     }
212   TEST (NULL, g_node_max_height (root) > 100);
213   TEST (NULL, g_node_n_nodes (root, G_TRAVERSE_ALL) == 1 + 2048);
214
215   g_node_destroy (root);
216   
217   if (!failed)
218     g_print ("ok\n");
219 }
220
221 static gboolean
222 my_hash_callback_remove (gpointer key,
223                          gpointer value,
224                          gpointer user_data)
225 {
226   int *d = value;
227
228   if ((*d) % 2)
229     return TRUE;
230
231   return FALSE;
232 }
233
234 static void
235 my_hash_callback_remove_test (gpointer key,
236                               gpointer value,
237                               gpointer user_data)
238 {
239   int *d = value;
240
241   if ((*d) % 2)
242     g_print ("bad!\n");
243 }
244
245 static void
246 my_hash_callback (gpointer key,
247                   gpointer value,
248                   gpointer user_data)
249 {
250   int *d = value;
251   *d = 1;
252 }
253
254 static guint
255 my_hash (gconstpointer key)
256 {
257   return (guint) *((const gint*) key);
258 }
259
260 static gboolean
261 my_hash_equal (gconstpointer a,
262                gconstpointer b)
263 {
264   return *((const gint*) a) == *((const gint*) b);
265 }
266
267 static gint
268 my_list_compare_one (gconstpointer a, gconstpointer b)
269 {
270   gint one = *((const gint*)a);
271   gint two = *((const gint*)b);
272   return one-two;
273 }
274
275 static gint
276 my_list_compare_two (gconstpointer a, gconstpointer b)
277 {
278   gint one = *((const gint*)a);
279   gint two = *((const gint*)b);
280   return two-one;
281 }
282
283 /* static void
284 my_list_print (gpointer a, gpointer b)
285 {
286   gint three = *((gint*)a);
287   g_print("%d", three);
288 }; */
289
290 static gint
291 my_compare (gconstpointer a,
292             gconstpointer b)
293 {
294   const char *cha = a;
295   const char *chb = b;
296
297   return *cha - *chb;
298 }
299
300 static gint
301 my_traverse (gpointer key,
302              gpointer value,
303              gpointer data)
304 {
305   char *ch = key;
306   g_print ("%c ", *ch);
307   return FALSE;
308 }
309
310 int
311 main (int   argc,
312       char *argv[])
313 {
314   GList *list, *t;
315   GSList *slist, *st;
316   GHashTable *hash_table;
317   GMemChunk *mem_chunk;
318   GStringChunk *string_chunk;
319   GTimer *timer;
320   gint nums[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
321   gint morenums[10] = { 8, 9, 7, 0, 3, 2, 5, 1, 4, 6};
322   gchar *string;
323
324   gchar *mem[10000], *tmp_string = NULL, *tmp_string_2;
325   gint i, j;
326   GArray *garray;
327   GPtrArray *gparray;
328   GByteArray *gbarray;
329   GString *string1, *string2;
330   GTree *tree;
331   char chars[62];
332   GRelation *relation;
333   GTuples *tuples;
334   gint data [1024];
335   struct {
336     gchar *filename;
337     gchar *dirname;
338   } dirname_checks[] = {
339     { "/", "/" },
340     { "////", "/" },
341     { ".////", "." },
342     { "../", ".." },
343     { "..////", ".." },
344     { "a/b", "a" },
345     { "a/b/", "a/b" },
346     { "c///", "c" },
347 #ifdef G_OS_WIN32
348     { "\\", "\\" },
349     { ".\\\\\\\\", "." },
350     { "..\\", ".." },
351     { "..\\\\\\\\", ".." },
352     { "a\\b", "a" },
353     { "a\\b/", "a\\b" },
354     { "a/b\\", "a/b" },
355     { "c\\\\/", "c" },
356     { "//\\", "/" },
357 #endif
358 #ifdef G_WITH_CYGWIN
359     { "//server/share///x", "//server/share" },
360 #endif
361     { ".", "." },
362     { "..", "." },
363     { "", "." },
364   };
365   guint n_dirname_checks = G_N_ELEMENTS (dirname_checks);
366
367   struct {
368     gchar *filename;
369     gchar *without_root;
370   } skip_root_checks[] = {
371     { "/", "" },
372     { "//", "" },
373     { "/foo", "foo" },
374     { "//foo", "foo" },
375     { "a/b", NULL },
376 #ifdef G_OS_WIN32
377     { "\\", "" },
378     { "\\foo", "foo" },
379     { "\\\\server\\foo", "" },
380     { "\\\\server\\foo\\bar", "bar" },
381     { "a\\b", NULL },
382 #endif
383 #ifdef G_WITH_CYGWIN
384     { "//server/share///x", "//x" },
385 #endif
386     { ".", NULL },
387     { "", NULL },
388   };
389   guint n_skip_root_checks = G_N_ELEMENTS (skip_root_checks);
390
391 #ifndef G_DISABLE_ASSERT
392   guint16 gu16t1 = 0x44afU, gu16t2 = 0xaf44U;
393   guint32 gu32t1 = 0x02a7f109U, gu32t2 = 0x09f1a702U;
394   guint64 gu64t1 = G_GINT64_CONSTANT(0x1d636b02300a7aa7U),
395           gu64t2 = G_GINT64_CONSTANT(0xa77a0a30026b631dU);
396 #endif
397   const char hello[] = "Hello, World";
398   const int hellolen = sizeof (hello) - 1;
399   int fd;
400   char template[32];
401   GError *error;
402   char *name_used;
403 #ifdef G_OS_WIN32
404   gchar *glib_dll = g_strdup_printf ("libglib-%d.%d-%d.dll",
405                                      GLIB_MAJOR_VERSION,
406                                      GLIB_MINOR_VERSION,
407                                      GLIB_MICRO_VERSION - GLIB_BINARY_AGE);
408 #endif
409 #ifdef G_WITH_CYGWIN
410   gchar *glib_dll = g_strdup_printf ("cygglib-%d.%d-%d.dll",
411                                      GLIB_MAJOR_VERSION,
412                                      GLIB_MINOR_VERSION,
413                                      GLIB_MICRO_VERSION - GLIB_BINARY_AGE);
414 #endif
415
416   g_print ("TestGLib v%u.%u.%u (i:%u b:%u)\n",
417            glib_major_version,
418            glib_minor_version,
419            glib_micro_version,
420            glib_interface_age,
421            glib_binary_age);
422
423   string = g_get_current_dir ();
424   g_print ("cwd: %s\n", string);
425   g_free (string);
426   g_print ("user: %s\n", g_get_user_name ());
427   g_print ("real: %s\n", g_get_real_name ());
428   g_print ("home: %s\n", g_get_home_dir ());
429   g_print ("tmp-dir: %s\n", g_get_tmp_dir ());
430
431   /* type sizes */
432   g_print ("checking size of gint8: %d", (int)sizeof (gint8));
433   TEST (NULL, sizeof (gint8) == 1);
434   g_print ("\nchecking size of gint16: %d", (int)sizeof (gint16));
435   TEST (NULL, sizeof (gint16) == 2);
436   g_print ("\nchecking size of gint32: %d", (int)sizeof (gint32));
437   TEST (NULL, sizeof (gint32) == 4);
438   g_print ("\nchecking size of gsize: %d", (int)sizeof (gsize));
439   g_print ("\nchecking size of gint64: %d", (int)sizeof (gint64));
440   TEST (NULL, sizeof (gint64) == 8);
441   g_print ("\n");
442
443   g_print ("checking g_path_get_basename()...");
444   string = g_path_get_basename (G_DIR_SEPARATOR_S "foo" G_DIR_SEPARATOR_S "dir" G_DIR_SEPARATOR_S);
445   g_assert (strcmp (string, "dir") == 0);
446   g_free (string);
447   string = g_path_get_basename (G_DIR_SEPARATOR_S "foo" G_DIR_SEPARATOR_S "file");
448   g_assert (strcmp (string, "file") == 0);
449   g_free (string);
450   g_print ("ok\n");
451 #ifdef G_OS_WIN32
452   string = g_path_get_basename ("/foo/dir/");
453   g_assert (strcmp (string, "dir") == 0);
454   g_free (string);
455   string = g_path_get_basename ("/foo/file");
456   g_assert (strcmp (string, "file") == 0);
457   g_free (string);
458   g_print ("ok\n");
459 #endif
460
461   g_print ("checking g_path_get_dirname()...");
462   for (i = 0; i < n_dirname_checks; i++)
463     {
464       gchar *dirname;
465
466       dirname = g_path_get_dirname (dirname_checks[i].filename);
467       if (strcmp (dirname, dirname_checks[i].dirname) != 0)
468         {
469           g_print ("\nfailed for \"%s\"==\"%s\" (returned: \"%s\")\n",
470                    dirname_checks[i].filename,
471                    dirname_checks[i].dirname,
472                    dirname);
473           n_dirname_checks = 0;
474         }
475       g_free (dirname);
476     }
477   if (n_dirname_checks)
478     g_print ("ok\n");
479
480   g_print ("checking g_path_skip_root()...");
481   for (i = 0; i < n_skip_root_checks; i++)
482     {
483       const gchar *skipped;
484
485       skipped = g_path_skip_root (skip_root_checks[i].filename);
486       if ((skipped && !skip_root_checks[i].without_root) ||
487           (!skipped && skip_root_checks[i].without_root) ||
488           ((skipped && skip_root_checks[i].without_root) &&
489            strcmp (skipped, skip_root_checks[i].without_root)))
490         {
491           g_print ("\nfailed for \"%s\"==\"%s\" (returned: \"%s\")\n",
492                    skip_root_checks[i].filename,
493                    (skip_root_checks[i].without_root ?
494                     skip_root_checks[i].without_root : "<NULL>"),
495                    (skipped ? skipped : "<NULL>"));
496           n_skip_root_checks = 0;
497         }
498     }
499   if (n_skip_root_checks)
500     g_print ("ok\n");
501
502   g_print ("checking doubly linked lists...");
503
504   list = NULL;
505   for (i = 0; i < 10; i++)
506     list = g_list_append (list, &nums[i]);
507   list = g_list_reverse (list);
508
509   for (i = 0; i < 10; i++)
510     {
511       t = g_list_nth (list, i);
512       if (*((gint*) t->data) != (9 - i))
513         g_error ("Regular insert failed");
514     }
515
516   for (i = 0; i < 10; i++)
517     if(g_list_position(list, g_list_nth (list, i)) != i)
518       g_error("g_list_position does not seem to be the inverse of g_list_nth\n");
519
520   g_list_free (list);
521   list = NULL;
522
523   for (i = 0; i < 10; i++)
524     list = g_list_insert_sorted (list, &morenums[i], my_list_compare_one);
525
526   /*
527   g_print("\n");
528   g_list_foreach (list, my_list_print, NULL);
529   */
530
531   for (i = 0; i < 10; i++)
532     {
533       t = g_list_nth (list, i);
534       if (*((gint*) t->data) != i)
535          g_error ("Sorted insert failed");
536     }
537
538   g_list_free (list);
539   list = NULL;
540
541   for (i = 0; i < 10; i++)
542     list = g_list_insert_sorted (list, &morenums[i], my_list_compare_two);
543
544   /*
545   g_print("\n");
546   g_list_foreach (list, my_list_print, NULL);
547   */
548
549   for (i = 0; i < 10; i++)
550     {
551       t = g_list_nth (list, i);
552       if (*((gint*) t->data) != (9 - i))
553          g_error ("Sorted insert failed");
554     }
555
556   g_list_free (list);
557   list = NULL;
558
559   for (i = 0; i < 10; i++)
560     list = g_list_prepend (list, &morenums[i]);
561
562   list = g_list_sort (list, my_list_compare_two);
563
564   /*
565   g_print("\n");
566   g_list_foreach (list, my_list_print, NULL);
567   */
568
569   for (i = 0; i < 10; i++)
570     {
571       t = g_list_nth (list, i);
572       if (*((gint*) t->data) != (9 - i))
573          g_error ("Merge sort failed");
574     }
575
576   g_list_free (list);
577
578   g_print ("ok\n");
579
580
581   g_print ("checking singly linked lists...");
582
583   slist = NULL;
584   for (i = 0; i < 10; i++)
585     slist = g_slist_append (slist, &nums[i]);
586   slist = g_slist_reverse (slist);
587
588   for (i = 0; i < 10; i++)
589     {
590       st = g_slist_nth (slist, i);
591       if (*((gint*) st->data) != (9 - i))
592         g_error ("failed");
593     }
594
595   g_slist_free (slist);
596   slist = NULL;
597
598   for (i = 0; i < 10; i++)
599     slist = g_slist_insert_sorted (slist, &morenums[i], my_list_compare_one);
600
601   /*
602   g_print("\n");
603   g_slist_foreach (slist, my_list_print, NULL);
604   */
605
606   for (i = 0; i < 10; i++)
607     {
608       st = g_slist_nth (slist, i);
609       if (*((gint*) st->data) != i)
610          g_error ("Sorted insert failed");
611     }
612
613   g_slist_free(slist);
614   slist = NULL;
615
616   for (i = 0; i < 10; i++)
617     slist = g_slist_insert_sorted (slist, &morenums[i], my_list_compare_two);
618
619   /*
620   g_print("\n");
621   g_slist_foreach (slist, my_list_print, NULL);
622   */
623
624   for (i = 0; i < 10; i++)
625     {
626       st = g_slist_nth (slist, i);
627       if (*((gint*) st->data) != (9 - i))
628          g_error("Sorted insert failed");
629     }
630
631   g_slist_free(slist);
632   slist = NULL;
633
634   for (i = 0; i < 10; i++)
635     slist = g_slist_prepend (slist, &morenums[i]);
636
637   slist = g_slist_sort (slist, my_list_compare_two);
638
639   /*
640   g_print("\n");
641   g_slist_foreach (slist, my_list_print, NULL);
642   */
643
644   for (i = 0; i < 10; i++)
645     {
646       st = g_slist_nth (slist, i);
647       if (*((gint*) st->data) != (9 - i))
648          g_error("Sorted insert failed");
649     }
650
651   g_slist_free(slist);
652
653   g_print ("ok\n");
654
655
656   g_print ("checking binary trees...\n");
657
658   tree = g_tree_new (my_compare);
659   i = 0;
660   for (j = 0; j < 10; j++, i++)
661     {
662       chars[i] = '0' + j;
663       g_tree_insert (tree, &chars[i], &chars[i]);
664     }
665   for (j = 0; j < 26; j++, i++)
666     {
667       chars[i] = 'A' + j;
668       g_tree_insert (tree, &chars[i], &chars[i]);
669     }
670   for (j = 0; j < 26; j++, i++)
671     {
672       chars[i] = 'a' + j;
673       g_tree_insert (tree, &chars[i], &chars[i]);
674     }
675
676   g_print ("tree height: %d\n", g_tree_height (tree));
677   g_print ("tree nnodes: %d\n", g_tree_nnodes (tree));
678
679   g_print ("tree: ");
680   g_tree_foreach (tree, my_traverse, NULL);
681   g_print ("\n");
682
683   for (i = 0; i < 10; i++)
684     g_tree_remove (tree, &chars[i]);
685
686   g_print ("tree height: %d\n", g_tree_height (tree));
687   g_print ("tree nnodes: %d\n", g_tree_nnodes (tree));
688
689   g_print ("tree: ");
690   g_tree_foreach (tree, my_traverse, NULL);
691   g_print ("\n");
692
693   g_print ("ok\n");
694
695
696   /* check n-way trees */
697   g_node_test ();
698
699   g_print ("checking mem chunks...");
700
701   mem_chunk = g_mem_chunk_new ("test mem chunk", 50, 100, G_ALLOC_AND_FREE);
702
703   for (i = 0; i < 10000; i++)
704     {
705       mem[i] = g_chunk_new (gchar, mem_chunk);
706
707       for (j = 0; j < 50; j++)
708         mem[i][j] = i * j;
709     }
710
711   for (i = 0; i < 10000; i++)
712     {
713       g_mem_chunk_free (mem_chunk, mem[i]);
714     }
715
716   g_print ("ok\n");
717
718
719   g_print ("checking hash tables...");
720
721   hash_table = g_hash_table_new (my_hash, my_hash_equal);
722   for (i = 0; i < 10000; i++)
723     {
724       array[i] = i;
725       g_hash_table_insert (hash_table, &array[i], &array[i]);
726     }
727   g_hash_table_foreach (hash_table, my_hash_callback, NULL);
728
729   for (i = 0; i < 10000; i++)
730     if (array[i] == 0)
731       g_print ("%d\n", i);
732
733   for (i = 0; i < 10000; i++)
734     g_hash_table_remove (hash_table, &array[i]);
735
736   for (i = 0; i < 10000; i++)
737     {
738       array[i] = i;
739       g_hash_table_insert (hash_table, &array[i], &array[i]);
740     }
741
742   if (g_hash_table_foreach_remove (hash_table, my_hash_callback_remove, NULL) != 5000 ||
743       g_hash_table_size (hash_table) != 5000)
744     g_print ("bad!\n");
745
746   g_hash_table_foreach (hash_table, my_hash_callback_remove_test, NULL);
747
748
749   g_hash_table_destroy (hash_table);
750
751   g_print ("ok\n");
752
753
754   g_print ("checking string chunks...");
755
756   string_chunk = g_string_chunk_new (1024);
757
758   for (i = 0; i < 100000; i ++)
759     {
760       tmp_string = g_string_chunk_insert (string_chunk, "hi pete");
761
762       if (strcmp ("hi pete", tmp_string) != 0)
763         g_error ("string chunks are broken.\n");
764     }
765
766   tmp_string_2 = g_string_chunk_insert_const (string_chunk, tmp_string);
767
768   g_assert (tmp_string_2 != tmp_string &&
769             strcmp(tmp_string_2, tmp_string) == 0);
770
771   tmp_string = g_string_chunk_insert_const (string_chunk, tmp_string);
772
773   g_assert (tmp_string_2 == tmp_string);
774
775   g_string_chunk_free (string_chunk);
776
777   g_print ("ok\n");
778
779
780   g_print ("checking arrays...");
781
782   garray = g_array_new (FALSE, FALSE, sizeof (gint));
783   for (i = 0; i < 10000; i++)
784     g_array_append_val (garray, i);
785
786   for (i = 0; i < 10000; i++)
787     if (g_array_index (garray, gint, i) != i)
788       g_print ("uh oh: %d ( %d )\n", g_array_index (garray, gint, i), i);
789
790   g_array_free (garray, TRUE);
791
792   garray = g_array_new (FALSE, FALSE, sizeof (gint));
793   for (i = 0; i < 100; i++)
794     g_array_prepend_val (garray, i);
795
796   for (i = 0; i < 100; i++)
797     if (g_array_index (garray, gint, i) != (100 - i - 1))
798       g_print ("uh oh: %d ( %d )\n", g_array_index (garray, gint, i), 100 - i - 1);
799
800   g_array_free (garray, TRUE);
801
802   g_print ("ok\n");
803
804
805   g_print ("checking strings...");
806
807   string1 = g_string_new ("hi pete!");
808   string2 = g_string_new ("");
809
810   g_assert (strcmp ("hi pete!", string1->str) == 0);
811
812   for (i = 0; i < 10000; i++)
813     g_string_append_c (string1, 'a'+(i%26));
814
815 #ifndef G_OS_WIN32
816   /* MSVC, mingw32 and LCC use the same run-time C library, which doesn't like
817      the %10000.10000f format... */
818   g_string_printf (string2, "%s|%0100d|%s|%s|%0*d|%*.*f|%10000.10000f",
819                    "this pete guy sure is a wuss, like he's the number ",
820                    1,
821                    " wuss.  everyone agrees.\n",
822                    string1->str,
823                    10, 666, 15, 15, 666.666666666, 666.666666666);
824 #else
825   g_string_printf (string2, "%s|%0100d|%s|%s|%0*d|%*.*f|%100.100f",
826                    "this pete guy sure is a wuss, like he's the number ",
827                    1,
828                    " wuss.  everyone agrees.\n",
829                    string1->str,
830                    10, 666, 15, 15, 666.666666666, 666.666666666);
831 #endif
832
833   g_print ("string2 length = %lu...\n", (gulong)string2->len);
834   string2->str[70] = '\0';
835   g_print ("first 70 chars:\n%s\n", string2->str);
836   string2->str[141] = '\0';
837   g_print ("next 70 chars:\n%s\n", string2->str+71);
838   string2->str[212] = '\0';
839   g_print ("and next 70:\n%s\n", string2->str+142);
840   g_print ("last 70 chars:\n%s\n", string2->str+string2->len - 70);
841
842   g_string_free (string1, TRUE);
843   g_string_free (string2, TRUE);
844
845   /* append */
846   string1 = g_string_new ("firsthalf");
847   g_string_append (string1, "lasthalf");
848   g_assert (strcmp (string1->str, "firsthalflasthalf") == 0);
849   g_string_free (string1, TRUE);
850
851   /* append_len */
852
853   string1 = g_string_new ("firsthalf");
854   g_string_append_len (string1, "lasthalfjunkjunk", strlen ("lasthalf"));
855   g_assert (strcmp (string1->str, "firsthalflasthalf") == 0);
856   g_string_free (string1, TRUE);  
857   
858   /* prepend */
859   string1 = g_string_new ("lasthalf");
860   g_string_prepend (string1, "firsthalf");
861   g_assert (strcmp (string1->str, "firsthalflasthalf") == 0);
862   g_string_free (string1, TRUE);
863
864   /* prepend_len */
865   string1 = g_string_new ("lasthalf");
866   g_string_prepend_len (string1, "firsthalfjunkjunk", strlen ("firsthalf"));
867   g_assert (strcmp (string1->str, "firsthalflasthalf") == 0);
868   g_string_free (string1, TRUE);
869   
870   /* insert */
871   string1 = g_string_new ("firstlast");
872   g_string_insert (string1, 5, "middle");
873   g_assert (strcmp (string1->str, "firstmiddlelast") == 0);
874   g_string_free (string1, TRUE);
875
876   /* insert with pos == end of the string */
877   string1 = g_string_new ("firstmiddle");
878   g_string_insert (string1, strlen ("firstmiddle"), "last");
879   g_assert (strcmp (string1->str, "firstmiddlelast") == 0);
880   g_string_free (string1, TRUE);
881   
882   /* insert_len */
883
884   string1 = g_string_new ("firstlast");
885   g_string_insert_len (string1, 5, "middlejunkjunk", strlen ("middle"));
886   g_assert (strcmp (string1->str, "firstmiddlelast") == 0);
887   g_string_free (string1, TRUE);
888
889   /* insert_len with magic -1 pos for append */
890   string1 = g_string_new ("first");
891   g_string_insert_len (string1, -1, "lastjunkjunk", strlen ("last"));
892   g_assert (strcmp (string1->str, "firstlast") == 0);
893   g_string_free (string1, TRUE);
894   
895   /* insert_len with magic -1 len for strlen-the-string */
896   string1 = g_string_new ("first");
897   g_string_insert_len (string1, 5, "last", -1);
898   g_assert (strcmp (string1->str, "firstlast") == 0);
899   g_string_free (string1, TRUE);
900   
901   g_print ("ok\n");
902
903   /* g_string_equal */
904   string1 = g_string_new ("test");
905   string2 = g_string_new ("te");
906   g_assert (! g_string_equal(string1, string2));
907   g_string_append (string2, "st");
908   g_assert (g_string_equal(string1, string2));
909   g_string_free (string1, TRUE);
910   g_string_free (string2, TRUE);
911   
912   /* Check handling of embedded ASCII 0 (NUL) characters in GString. */
913   string1 = g_string_new ("fiddle");
914   string2 = g_string_new ("fiddle");
915   g_assert (g_string_equal(string1, string2));
916   g_string_append_c(string1, '\0');
917   g_assert (! g_string_equal(string1, string2));
918   g_string_append_c(string2, '\0');
919   g_assert (g_string_equal(string1, string2));
920   g_string_append_c(string1, 'x');
921   g_string_append_c(string2, 'y');
922   g_assert (! g_string_equal(string1, string2));
923   g_assert (string1->len == 8);
924   g_string_append(string1, "yzzy");
925   g_assert (string1->len == 12);
926   g_assert ( memcmp(string1->str, "fiddle\0xyzzy", 13) == 0);
927   g_string_insert(string1, 1, "QED");
928   g_assert ( memcmp(string1->str, "fQEDiddle\0xyzzy", 16) == 0);
929   g_string_free (string1, TRUE);
930   g_string_free (string2, TRUE);
931   
932   g_print ("test positional printf formats (not supported): ");
933   string = g_strdup_printf ("%.*s%s", 5, "a", "b");
934   tmp_string = g_strdup_printf ("%2$*1$s", 5, "c");
935   g_print ("%s%s\n", string, tmp_string);
936   g_free (tmp_string);
937   g_free (string);
938
939   g_print ("checking timers...\n");
940   
941   timer = g_timer_new ();
942   g_print ("  spinning for 3 seconds...\n");
943
944   g_timer_start (timer);
945   while (g_timer_elapsed (timer, NULL) < 3)
946     ;
947
948   g_timer_stop (timer);
949   g_timer_destroy (timer);
950
951   g_print ("ok\n");
952
953   g_print ("checking g_ascii_strcasecmp...");
954   g_assert (g_ascii_strcasecmp ("FroboZZ", "frobozz") == 0);
955   g_assert (g_ascii_strcasecmp ("frobozz", "frobozz") == 0);
956   g_assert (g_ascii_strcasecmp ("frobozz", "FROBOZZ") == 0);
957   g_assert (g_ascii_strcasecmp ("FROBOZZ", "froboz") > 0);
958   g_assert (g_ascii_strcasecmp ("", "") == 0);
959   g_assert (g_ascii_strcasecmp ("!#%&/()", "!#%&/()") == 0);
960   g_assert (g_ascii_strcasecmp ("a", "b") < 0);
961   g_assert (g_ascii_strcasecmp ("a", "B") < 0);
962   g_assert (g_ascii_strcasecmp ("A", "b") < 0);
963   g_assert (g_ascii_strcasecmp ("A", "B") < 0);
964   g_assert (g_ascii_strcasecmp ("b", "a") > 0);
965   g_assert (g_ascii_strcasecmp ("b", "A") > 0);
966   g_assert (g_ascii_strcasecmp ("B", "a") > 0);
967   g_assert (g_ascii_strcasecmp ("B", "A") > 0);
968
969   g_print ("ok\n");
970
971   g_print ("checking g_strdup...");
972   g_assert(g_strdup(NULL) == NULL);
973   string = g_strdup(GLIB_TEST_STRING);
974   g_assert(string != NULL);
975   g_assert(strcmp(string, GLIB_TEST_STRING) == 0);
976   g_free(string);
977
978   g_print ("ok\n");
979
980   g_print ("checking g_strconcat...");
981   string = g_strconcat(GLIB_TEST_STRING, NULL);
982   g_assert(string != NULL);
983   g_assert(strcmp(string, GLIB_TEST_STRING) == 0);
984   g_free(string);
985   string = g_strconcat(GLIB_TEST_STRING, GLIB_TEST_STRING, 
986                        GLIB_TEST_STRING, NULL);
987   g_assert(string != NULL);
988   g_assert(strcmp(string, GLIB_TEST_STRING GLIB_TEST_STRING
989                           GLIB_TEST_STRING) == 0);
990   g_free(string);
991   g_print ("ok\n");
992   
993
994   g_print("checking g_strlcpy/g_strlcat...");
995   /* The following is a torture test for strlcpy/strlcat, with lots of
996    * checking; normal users wouldn't use them this way!
997    */
998   string = g_malloc (6);
999   *(string + 5) = 'Z'; /* guard value, shouldn't change during test */
1000   *string = 'q';
1001   g_assert (g_strlcpy(string, "" , 5) == 0);
1002   g_assert ( *string == '\0' );
1003   *string = 'q';
1004   g_assert (g_strlcpy(string, "abc" , 5) == 3);
1005   g_assert ( *(string + 3) == '\0' );
1006   g_assert (g_str_equal(string, "abc"));
1007   g_assert (g_strlcpy(string, "abcd" , 5) == 4);
1008   g_assert ( *(string + 4) == '\0' );
1009   g_assert ( *(string + 5) == 'Z' );
1010   g_assert (g_str_equal(string, "abcd"));
1011   g_assert (g_strlcpy(string, "abcde" , 5) == 5);
1012   g_assert ( *(string + 4) == '\0' );
1013   g_assert ( *(string + 5) == 'Z' );
1014   g_assert (g_str_equal(string, "abcd"));
1015   g_assert (g_strlcpy(string, "abcdef" , 5) == 6);
1016   g_assert ( *(string + 4) == '\0' );
1017   g_assert ( *(string + 5) == 'Z' );
1018   g_assert (g_str_equal(string, "abcd"));
1019   *string = 'Y';
1020   *(string + 1)= '\0';
1021   g_assert (g_strlcpy(string, "Hello" , 0) == 5);
1022   g_assert (*string == 'Y');
1023   *string = '\0';
1024   g_assert (g_strlcat(string, "123" , 5) == 3);
1025   g_assert ( *(string + 3) == '\0' );
1026   g_assert (g_str_equal(string, "123"));
1027   g_assert (g_strlcat(string, "" , 5) == 3);
1028   g_assert ( *(string + 3) == '\0' );
1029   g_assert (g_str_equal(string, "123"));
1030   g_assert (g_strlcat(string, "4", 5) == 4);
1031   g_assert (g_str_equal(string, "1234"));
1032   g_assert (g_strlcat(string, "5", 5) == 5);
1033   g_assert ( *(string + 4) == '\0' );
1034   g_assert (g_str_equal(string, "1234"));
1035   g_assert ( *(string + 5) == 'Z' );
1036   *string = 'Y';
1037   *(string + 1)= '\0';
1038   g_assert (g_strlcat(string, "123" , 0) == 3);
1039   g_assert (*string == 'Y');
1040   
1041   /* A few more tests, demonstrating more "normal" use  */
1042   g_assert (g_strlcpy(string, "hi", 5) == 2);
1043   g_assert (g_str_equal(string, "hi"));
1044   g_assert (g_strlcat(string, "t", 5) == 3);
1045   g_assert (g_str_equal(string, "hit"));
1046   g_free(string);
1047
1048   g_print ("ok\n");
1049   
1050   
1051   g_print ("checking g_strdup_printf...");
1052   string = g_strdup_printf ("%05d %-5s", 21, "test");
1053   g_assert (string != NULL);
1054   g_assert (strcmp(string, "00021 test ") == 0);
1055   g_free (string);
1056
1057   g_print ("ok\n");
1058
1059   /* g_debug (argv[0]); */
1060
1061   /* Relation tests */
1062
1063   g_print ("checking relations...");
1064
1065   relation = g_relation_new (2);
1066
1067   g_relation_index (relation, 0, g_int_hash, g_int_equal);
1068   g_relation_index (relation, 1, g_int_hash, g_int_equal);
1069
1070   for (i = 0; i < 1024; i += 1)
1071     data[i] = i;
1072
1073   for (i = 1; i < 1023; i += 1)
1074     {
1075       g_relation_insert (relation, data + i, data + i + 1);
1076       g_relation_insert (relation, data + i, data + i - 1);
1077     }
1078
1079   for (i = 2; i < 1022; i += 1)
1080     {
1081       g_assert (! g_relation_exists (relation, data + i, data + i));
1082       g_assert (! g_relation_exists (relation, data + i, data + i + 2));
1083       g_assert (! g_relation_exists (relation, data + i, data + i - 2));
1084     }
1085
1086   for (i = 1; i < 1023; i += 1)
1087     {
1088       g_assert (g_relation_exists (relation, data + i, data + i + 1));
1089       g_assert (g_relation_exists (relation, data + i, data + i - 1));
1090     }
1091
1092   for (i = 2; i < 1022; i += 1)
1093     {
1094       g_assert (g_relation_count (relation, data + i, 0) == 2);
1095       g_assert (g_relation_count (relation, data + i, 1) == 2);
1096     }
1097
1098   g_assert (g_relation_count (relation, data, 0) == 0);
1099
1100   g_assert (g_relation_count (relation, data + 42, 0) == 2);
1101   g_assert (g_relation_count (relation, data + 43, 1) == 2);
1102   g_assert (g_relation_count (relation, data + 41, 1) == 2);
1103   g_relation_delete (relation, data + 42, 0);
1104   g_assert (g_relation_count (relation, data + 42, 0) == 0);
1105   g_assert (g_relation_count (relation, data + 43, 1) == 1);
1106   g_assert (g_relation_count (relation, data + 41, 1) == 1);
1107
1108   tuples = g_relation_select (relation, data + 200, 0);
1109
1110   g_assert (tuples->len == 2);
1111
1112 #if 0
1113   for (i = 0; i < tuples->len; i += 1)
1114     {
1115       printf ("%d %d\n",
1116               *(gint*) g_tuples_index (tuples, i, 0),
1117               *(gint*) g_tuples_index (tuples, i, 1));
1118     }
1119 #endif
1120
1121   g_assert (g_relation_exists (relation, data + 300, data + 301));
1122   g_relation_delete (relation, data + 300, 0);
1123   g_assert (!g_relation_exists (relation, data + 300, data + 301));
1124
1125   g_tuples_destroy (tuples);
1126
1127   g_relation_destroy (relation);
1128
1129   relation = NULL;
1130
1131   g_print ("ok\n");
1132
1133   g_print ("checking pointer arrays...");
1134
1135   gparray = g_ptr_array_new ();
1136   for (i = 0; i < 10000; i++)
1137     g_ptr_array_add (gparray, GINT_TO_POINTER (i));
1138
1139   for (i = 0; i < 10000; i++)
1140     if (g_ptr_array_index (gparray, i) != GINT_TO_POINTER (i))
1141       g_print ("array fails: %p ( %p )\n", g_ptr_array_index (gparray, i), GINT_TO_POINTER (i));
1142
1143   g_ptr_array_free (gparray, TRUE);
1144
1145   g_print ("ok\n");
1146
1147
1148   g_print ("checking byte arrays...");
1149
1150   gbarray = g_byte_array_new ();
1151   for (i = 0; i < 10000; i++)
1152     g_byte_array_append (gbarray, (guint8*) "abcd", 4);
1153
1154   for (i = 0; i < 10000; i++)
1155     {
1156       g_assert (gbarray->data[4*i] == 'a');
1157       g_assert (gbarray->data[4*i+1] == 'b');
1158       g_assert (gbarray->data[4*i+2] == 'c');
1159       g_assert (gbarray->data[4*i+3] == 'd');
1160     }
1161
1162   g_byte_array_free (gbarray, TRUE);
1163   g_print ("ok\n");
1164
1165   g_printerr ("g_log tests:");
1166   g_warning ("harmless warning with parameters: %d %s %#x", 42, "Boo", 12345);
1167   g_message ("the next warning is a test:");
1168   string = NULL;
1169   g_print (string);
1170
1171   g_print ("checking endian macros (host is ");
1172 #if G_BYTE_ORDER == G_BIG_ENDIAN
1173   g_print ("big endian)...");
1174 #else
1175   g_print ("little endian)...");
1176 #endif
1177   g_assert (GUINT16_SWAP_LE_BE (gu16t1) == gu16t2);  
1178   g_assert (GUINT32_SWAP_LE_BE (gu32t1) == gu32t2);  
1179   g_assert (GUINT64_SWAP_LE_BE (gu64t1) == gu64t2);  
1180
1181   g_print ("ok\n");
1182
1183   if (g_get_charset (&string))
1184     g_print ("current charset is UTF-8: %s\n", string);
1185   else
1186     g_print ("current charset is not UTF-8: %s\n", string);
1187
1188 #ifdef G_PLATFORM_WIN32
1189   g_print ("current locale: %s\n", g_win32_getlocale ());
1190   g_print ("GLib DLL name tested for: %s\n", glib_dll);
1191
1192   g_print ("GLib installation directory, from Registry entry for %s if available: %s\n",
1193            GETTEXT_PACKAGE,
1194            g_win32_get_package_installation_directory (GETTEXT_PACKAGE, NULL));
1195   g_print ("Ditto, or from GLib DLL name: %s\n",
1196            g_win32_get_package_installation_directory (GETTEXT_PACKAGE, glib_dll));
1197   g_print ("Ditto, only from GLib DLL name: %s\n",
1198            g_win32_get_package_installation_directory (NULL, glib_dll));
1199   g_print ("locale subdirectory of GLib installation directory: %s\n",
1200            g_win32_get_package_installation_subdirectory (NULL, glib_dll, "lib\\locale"));
1201   g_print ("GTK+ 2.0 installation directory, if available: %s\n",
1202            g_win32_get_package_installation_directory ("gtk20", NULL));
1203
1204   g_print ("found more.com as %s\n", g_find_program_in_path ("more.com"));
1205   g_print ("found regedit as %s\n", g_find_program_in_path ("regedit"));
1206
1207 #endif
1208
1209   g_print ("checking file functions...\n");
1210
1211   strcpy (template, "foobar");
1212   fd = g_mkstemp (template);
1213   if (fd != -1)
1214     g_print ("g_mkstemp works even if template doesn't end in XXXXXX\n");
1215   close (fd);
1216   strcpy (template, "fooXXXXXX");
1217   fd = g_mkstemp (template);
1218   if (fd == -1)
1219     g_print ("g_mkstemp didn't work for template %s\n", template);
1220   i = write (fd, hello, hellolen);
1221   if (i == -1)
1222     g_print ("write() failed: %s\n", g_strerror (errno));
1223   else if (i != hellolen)
1224     g_print ("write() should have written %d bytes, wrote %d\n", hellolen, i);
1225
1226   lseek (fd, 0, 0);
1227   i = read (fd, chars, sizeof (chars));
1228   if (i == -1)
1229     g_print ("read() failed: %s\n", g_strerror (errno));
1230   else if (i != hellolen)
1231     g_print ("read() should have read %d bytes, got %d\n", hellolen, i);
1232
1233   chars[i] = 0;
1234   if (strcmp (chars, hello) != 0)
1235     g_print ("wrote '%s', but got '%s'\n", hello, chars);
1236
1237   close (fd);
1238   remove (template);
1239
1240   error = NULL;
1241   strcpy (template, "zap" G_DIR_SEPARATOR_S "barXXXXXX");
1242   fd = g_file_open_tmp (template, &name_used, &error);
1243   if (fd != -1)
1244     g_print ("g_file_open_tmp works even if template contains '%s'\n",
1245              G_DIR_SEPARATOR_S);
1246   else
1247     g_print ("g_file_open_tmp correctly returns error: %s\n",
1248              error->message);
1249   close (fd);
1250   g_clear_error (&error);
1251
1252 #ifdef G_OS_WIN32
1253   strcpy (template, "zap/barXXXXXX");
1254   fd = g_file_open_tmp (template, &name_used, &error);
1255   if (fd != -1)
1256     g_print ("g_file_open_tmp works even if template contains '/'\n");
1257   else
1258     g_print ("g_file_open_tmp correctly returns error: %s\n",
1259              error->message);
1260   close (fd);
1261   g_clear_error (&error);
1262 #endif
1263
1264   strcpy (template, "zapXXXXXX");
1265   fd = g_file_open_tmp (template, &name_used, &error);
1266   if (fd == -1)
1267     g_print ("g_file_open_tmp didn't work for template '%s': %s\n",
1268              template, error->message);
1269   else
1270     g_print ("g_file_open_tmp for template '%s' used name '%s'\n",
1271              template, name_used);
1272   close (fd);
1273   g_clear_error (&error);
1274   remove (name_used);
1275
1276   fd = g_file_open_tmp (NULL, &name_used, &error);
1277   if (fd == -1)
1278     g_print ("g_file_open_tmp didn't work for a NULL template: %s\n",
1279              error->message);
1280   else
1281     g_print ("g_file_open_tmp for NULL template used name '%s'\n",
1282              name_used);
1283   close (fd);
1284   g_clear_error (&error);
1285   remove (name_used);
1286   
1287   return 0;
1288 }
1289