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