tizen: kdbus: make i explicitly positive in make_single_header_vector
[platform/upstream/glib.git] / glib / tests / utils.c
1 /* Unit tests for utilities
2  * Copyright (C) 2010 Red Hat, Inc.
3  *
4  * SPDX-License-Identifier: LicenseRef-old-glib-tests
5  *
6  * This work is provided "as is"; redistribution and modification
7  * in whole or in part, in any medium, physical or electronic is
8  * permitted without restriction.
9  *
10  * This work is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  *
14  * In no event shall the authors or contributors be liable for any
15  * direct, indirect, incidental, special, exemplary, or consequential
16  * damages (including, but not limited to, procurement of substitute
17  * goods or services; loss of use, data, or profits; or business
18  * interruption) however caused and on any theory of liability, whether
19  * in contract, strict liability, or tort (including negligence or
20  * otherwise) arising in any way out of the use of this software, even
21  * if advised of the possibility of such damage.
22  *
23  * Author: Matthias Clasen
24  */
25
26 #ifndef GLIB_DISABLE_DEPRECATION_WARNINGS
27 #define GLIB_DISABLE_DEPRECATION_WARNINGS
28 #endif
29
30 #include "glib.h"
31 #include "glib-private.h"
32 #include "gutilsprivate.h"
33 #include "glib/gstdio.h"
34
35 #include <stdlib.h>
36 #include <string.h>
37 #include <stdarg.h>
38 #ifdef G_OS_UNIX
39 #include <sys/utsname.h>
40 #endif
41 #ifdef G_OS_WIN32
42 #include <windows.h>
43 #endif
44
45 static gboolean
46 strv_check (const gchar * const *strv, ...)
47 {
48   va_list args;
49   gchar *s;
50   gint i;
51
52   va_start (args, strv);
53   for (i = 0; strv[i]; i++)
54     {
55       s = va_arg (args, gchar*);
56       if (g_strcmp0 (strv[i], s) != 0)
57         {
58           va_end (args);
59           return FALSE;
60         }
61     }
62
63   va_end (args);
64
65   return TRUE;
66 }
67
68 static void
69 test_language_names (void)
70 {
71   const gchar * const *names;
72
73   g_setenv ("LANGUAGE", "de:en_US", TRUE);
74   names = g_get_language_names ();
75   g_assert (strv_check (names, "de", "en_US", "en", "C", NULL));
76
77   g_setenv ("LANGUAGE", "tt_RU.UTF-8@iqtelif", TRUE);
78   names = g_get_language_names ();
79   g_assert (strv_check (names,
80                         "tt_RU.UTF-8@iqtelif",
81                         "tt_RU@iqtelif",
82                         "tt.UTF-8@iqtelif",
83                         "tt@iqtelif",
84                         "tt_RU.UTF-8",
85                         "tt_RU",
86                         "tt.UTF-8",
87                         "tt",
88                         "C",
89                         NULL));
90 }
91
92 static void
93 test_locale_variants (void)
94 {
95   char **v;
96
97   v = g_get_locale_variants ("fr_BE");
98   g_assert (strv_check ((const gchar * const *) v, "fr_BE", "fr", NULL));
99   g_strfreev (v);
100
101   v = g_get_locale_variants ("sr_SR@latin");
102   g_assert (strv_check ((const gchar * const *) v, "sr_SR@latin", "sr@latin", "sr_SR", "sr", NULL));
103   g_strfreev (v);
104 }
105
106 static void
107 test_version (void)
108 {
109   if (g_test_verbose ())
110     g_printerr ("(header %d.%d.%d library %d.%d.%d) ",
111               GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION,
112               glib_major_version, glib_minor_version, glib_micro_version);
113
114   g_assert (glib_check_version (GLIB_MAJOR_VERSION,
115                                 GLIB_MINOR_VERSION,
116                                 GLIB_MICRO_VERSION) == NULL);
117   g_assert (glib_check_version (GLIB_MAJOR_VERSION,
118                                 GLIB_MINOR_VERSION,
119                                 0) == NULL);
120   g_assert (glib_check_version (GLIB_MAJOR_VERSION - 1,
121                                 0,
122                                 0) != NULL);
123   g_assert (glib_check_version (GLIB_MAJOR_VERSION + 1,
124                                 0,
125                                 0) != NULL);
126   g_assert (glib_check_version (GLIB_MAJOR_VERSION,
127                                 GLIB_MINOR_VERSION + 1,
128                                 0) != NULL);
129   /* don't use + 1 here, since a +/-1 difference can
130    * happen due to post-release version bumps in git
131    */
132   g_assert (glib_check_version (GLIB_MAJOR_VERSION,
133                                 GLIB_MINOR_VERSION,
134                                 GLIB_MICRO_VERSION + 3) != NULL);
135 }
136
137 static const gchar *argv0;
138
139 static void
140 test_appname (void)
141 {
142   const gchar *prgname;
143   const gchar *appname;
144
145   prgname = g_get_prgname ();
146   appname = g_get_application_name ();
147   g_assert_cmpstr (prgname, ==, argv0);
148   g_assert_cmpstr (appname, ==, prgname);
149
150   g_set_prgname ("prgname");
151
152   prgname = g_get_prgname ();
153   appname = g_get_application_name ();
154   g_assert_cmpstr (prgname, ==, "prgname");
155   g_assert_cmpstr (appname, ==, "prgname");
156
157   g_set_application_name ("appname");
158
159   prgname = g_get_prgname ();
160   appname = g_get_application_name ();
161   g_assert_cmpstr (prgname, ==, "prgname");
162   g_assert_cmpstr (appname, ==, "appname");
163 }
164
165 static gpointer
166 thread_prgname_check (gpointer data)
167 {
168   gint *n_threads_got_prgname = (gint *) data;
169   const gchar *old_prgname;
170
171   old_prgname = g_get_prgname ();
172   g_assert_cmpstr (old_prgname, ==, "prgname");
173
174   g_atomic_int_inc (n_threads_got_prgname);
175
176   while (g_strcmp0 (g_get_prgname (), "prgname2") != 0);
177
178   return NULL;
179 }
180
181 static void
182 test_prgname_thread_safety (void)
183 {
184   gsize i;
185   gint n_threads_got_prgname;
186   GThread *threads[4];
187
188   g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/847");
189   g_test_summary ("Test that threads racing to get and set the program name "
190                   "always receive a valid program name.");
191
192   g_set_prgname ("prgname");
193   g_atomic_int_set (&n_threads_got_prgname, 0);
194
195   for (i = 0; i < G_N_ELEMENTS (threads); i++)
196     threads[i] = g_thread_new (NULL, thread_prgname_check, &n_threads_got_prgname);
197
198   while (g_atomic_int_get (&n_threads_got_prgname) != G_N_ELEMENTS (threads))
199     g_usleep (50);
200
201   g_set_prgname ("prgname2");
202
203   /* Wait for all the workers to exit. */
204   for (i = 0; i < G_N_ELEMENTS (threads); i++)
205     g_thread_join (threads[i]);
206
207   /* reset prgname */
208   g_set_prgname ("prgname");
209 }
210
211 static void
212 test_tmpdir (void)
213 {
214   char **envp = NULL;
215
216   g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=627969");
217   g_test_summary ("Test that g_get_tmp_dir() returns a correct default if TMPDIR is set to the empty string");
218
219   if (g_test_subprocess ())
220     {
221       g_assert_cmpstr (g_get_tmp_dir (), !=, "");
222       return;
223     }
224
225   envp = g_get_environ ();
226
227   envp = g_environ_setenv (g_steal_pointer (&envp), "TMPDIR", "", TRUE);
228   envp = g_environ_unsetenv (g_steal_pointer (&envp), "TMP");
229   envp = g_environ_unsetenv (g_steal_pointer (&envp), "TEMP");
230
231   g_test_trap_subprocess_with_envp (NULL, (const gchar * const *) envp,
232                                     0, G_TEST_SUBPROCESS_DEFAULT);
233   g_test_trap_assert_passed ();
234   g_strfreev (envp);
235 }
236
237 #if defined(__GNUC__) && (__GNUC__ >= 4)
238 #define TEST_BUILTINS 1
239 #else
240 #define TEST_BUILTINS 0
241 #endif
242
243 #if TEST_BUILTINS
244 static gint
245 builtin_bit_nth_lsf1 (gulong mask, gint nth_bit)
246 {
247   if (nth_bit >= 0)
248     {
249       if (G_LIKELY (nth_bit < GLIB_SIZEOF_LONG * 8 - 1))
250         mask &= -(1UL << (nth_bit + 1));
251       else
252         mask = 0;
253     }
254   return __builtin_ffsl (mask) - 1;
255 }
256
257 static gint
258 builtin_bit_nth_lsf2 (gulong mask, gint nth_bit)
259 {
260   if (nth_bit >= 0)
261     {
262       if (G_LIKELY (nth_bit < GLIB_SIZEOF_LONG * 8 - 1))
263         mask &= -(1UL << (nth_bit + 1));
264       else
265         mask = 0;
266     }
267   return mask ? __builtin_ctzl (mask) : -1;
268 }
269
270 static gint
271 builtin_bit_nth_msf (gulong mask, gint nth_bit)
272 {
273   if (nth_bit >= 0 && nth_bit < GLIB_SIZEOF_LONG * 8)
274     mask &= (1UL << nth_bit) - 1;
275   return mask ? GLIB_SIZEOF_LONG * 8 - 1 - __builtin_clzl (mask) : -1;
276 }
277
278 static guint
279 builtin_bit_storage (gulong number)
280 {
281   return number ? GLIB_SIZEOF_LONG * 8 - __builtin_clzl (number) : 1;
282 }
283 #endif
284
285 static gint
286 naive_bit_nth_lsf (gulong mask, gint nth_bit)
287 {
288   if (G_UNLIKELY (nth_bit < -1))
289     nth_bit = -1;
290   while (nth_bit < ((GLIB_SIZEOF_LONG * 8) - 1))
291     {
292       nth_bit++;
293       if (mask & (1UL << nth_bit))
294         return nth_bit;
295     }
296   return -1;
297 }
298
299 static gint
300 naive_bit_nth_msf (gulong mask, gint nth_bit)
301 {
302   if (nth_bit < 0 || G_UNLIKELY (nth_bit > GLIB_SIZEOF_LONG * 8))
303     nth_bit = GLIB_SIZEOF_LONG * 8;
304   while (nth_bit > 0)
305     {
306       nth_bit--;
307       if (mask & (1UL << nth_bit))
308         return nth_bit;
309     }
310   return -1;
311 }
312
313 static guint
314 naive_bit_storage (gulong number)
315 {
316   guint n_bits = 0;
317
318   do
319     {
320       n_bits++;
321       number >>= 1;
322     }
323   while (number);
324   return n_bits;
325 }
326
327 static void
328 test_basic_bits (void)
329 {
330   gulong i;
331   gint nth_bit;
332
333   /* we loop like this: 0, -1, 1, -2, 2, -3, 3, ... */
334   for (i = 0; (glong) i < 1500; i = -(i + ((glong) i >= 0)))
335     {
336       guint naive_bit_storage_i = naive_bit_storage (i);
337
338       /* Test the g_bit_*() implementations against the compiler builtins (if
339        * available), and against a slow-but-correct ‘naive’ implementation.
340        * They should all agree.
341        *
342        * The macro and function versions of the g_bit_*() functions are tested,
343        * hence one call with the function name in brackets (to avoid it being
344        * expanded as a macro). */
345 #if TEST_BUILTINS
346       g_assert_cmpint (naive_bit_storage_i, ==, builtin_bit_storage (i));
347 #endif
348       g_assert_cmpint (naive_bit_storage_i, ==, g_bit_storage (i));
349       g_assert_cmpint (naive_bit_storage_i, ==, (g_bit_storage) (i));
350
351       for (nth_bit = -3; nth_bit <= 2 + GLIB_SIZEOF_LONG * 8; nth_bit++)
352         {
353           gint naive_bit_nth_lsf_i_nth_bit = naive_bit_nth_lsf (i, nth_bit);
354           gint naive_bit_nth_msf_i_nth_bit = naive_bit_nth_msf (i, nth_bit);
355
356 #if TEST_BUILTINS
357           g_assert_cmpint (naive_bit_nth_lsf_i_nth_bit, ==,
358                            builtin_bit_nth_lsf1 (i, nth_bit));
359           g_assert_cmpint (naive_bit_nth_lsf_i_nth_bit, ==,
360                            builtin_bit_nth_lsf2 (i, nth_bit));
361 #endif
362           g_assert_cmpint (naive_bit_nth_lsf_i_nth_bit, ==,
363                            g_bit_nth_lsf (i, nth_bit));
364           g_assert_cmpint (naive_bit_nth_lsf_i_nth_bit, ==,
365                            (g_bit_nth_lsf) (i, nth_bit));
366
367 #if TEST_BUILTINS
368           g_assert_cmpint (naive_bit_nth_msf_i_nth_bit, ==,
369                            builtin_bit_nth_msf (i, nth_bit));
370 #endif
371           g_assert_cmpint (naive_bit_nth_msf_i_nth_bit, ==,
372                            g_bit_nth_msf (i, nth_bit));
373           g_assert_cmpint (naive_bit_nth_msf_i_nth_bit, ==,
374                            (g_bit_nth_msf) (i, nth_bit));
375         }
376     }
377 }
378
379 static void
380 test_bits (void)
381 {
382   gulong mask;
383   gint max_bit;
384   gint i, pos;
385
386   pos = g_bit_nth_lsf (0, -1);
387   g_assert_cmpint (pos, ==, -1);
388
389   max_bit = sizeof (gulong) * 8;
390   for (i = 0; i < max_bit; i++)
391     {
392       mask = 1UL << i;
393
394       pos = g_bit_nth_lsf (mask, -1);
395       g_assert_cmpint (pos, ==, i);
396
397       pos = g_bit_nth_lsf (mask, i - 3);
398       g_assert_cmpint (pos , ==, i);
399
400       pos = g_bit_nth_lsf (mask, i);
401       g_assert_cmpint (pos , ==, -1);
402
403       pos = g_bit_nth_lsf (mask, i + 1);
404       g_assert_cmpint (pos , ==, -1);
405     }
406
407   pos = g_bit_nth_msf (0, -1);
408   g_assert_cmpint (pos, ==, -1);
409
410   for (i = 0; i < max_bit; i++)
411     {
412       mask = 1UL << i;
413
414       pos = g_bit_nth_msf (mask, -1);
415       g_assert_cmpint (pos, ==, i);
416
417       pos = g_bit_nth_msf (mask, i + 3);
418       g_assert_cmpint (pos , ==, i);
419
420       pos = g_bit_nth_msf (mask, i);
421       g_assert_cmpint (pos , ==, -1);
422
423       if (i > 0)
424         {
425           pos = g_bit_nth_msf (mask, i - 1);
426           g_assert_cmpint (pos , ==, -1);
427         }
428     }
429 }
430
431 static void
432 test_swap (void)
433 {
434   guint16 a16, b16;
435   guint32 a32, b32;
436   guint64 a64, b64;
437
438   a16 = 0xaabb;
439   b16 = 0xbbaa;
440
441   g_assert_cmpint (GUINT16_SWAP_LE_BE (a16), ==, b16);
442
443   a32 = 0xaaaabbbb;
444   b32 = 0xbbbbaaaa;
445
446   g_assert_cmpint (GUINT32_SWAP_LE_BE (a32), ==, b32);
447
448   a64 = G_GUINT64_CONSTANT(0xaaaaaaaabbbbbbbb);
449   b64 = G_GUINT64_CONSTANT(0xbbbbbbbbaaaaaaaa);
450
451   g_assert_cmpint (GUINT64_SWAP_LE_BE (a64), ==, b64);
452 }
453
454 static void
455 test_find_program (void)
456 {
457   gchar *res;
458
459 #ifdef G_OS_UNIX
460   gchar *relative_path;
461   gchar *absolute_path;
462   gchar *cwd;
463   gsize i;
464
465   res = g_find_program_in_path ("sh");
466   g_assert (res != NULL);
467   g_free (res);
468
469   res = g_find_program_in_path ("/bin/sh");
470   g_assert (res != NULL);
471   g_free (res);
472
473   /* Resolve any symlinks in the CWD as that breaks the test e.g.
474    * with the FreeBSD /home/ -> /usr/home symlink. */
475   cwd = realpath (".", NULL);
476   absolute_path = g_find_program_in_path ("sh");
477   relative_path = g_strdup (absolute_path);
478   for (i = 0; cwd[i] != '\0'; i++)
479     {
480       if (cwd[i] == '/' && cwd[i + 1] != '\0')
481         {
482           gchar *relative_path_2 = g_strconcat ("../", relative_path, NULL);
483           g_free (relative_path);
484           relative_path = relative_path_2;
485         }
486     }
487   res = g_find_program_in_path (relative_path);
488   g_assert_nonnull (res);
489   g_assert_true (g_path_is_absolute (res));
490   g_free (cwd);
491   g_free (absolute_path);
492   g_free (relative_path);
493   g_free (res);
494
495 #else
496   /* There's not a lot we can search for that would reliably work both
497    * on real Windows and mingw.
498    */
499 #endif
500
501   res = g_find_program_in_path ("this_program_does_not_exit");
502   g_assert (res == NULL);
503
504   res = g_find_program_in_path ("/bin");
505   g_assert (res == NULL);
506
507   res = g_find_program_in_path ("/etc/passwd");
508   g_assert (res == NULL);
509 }
510
511 static char *
512 find_program_for_path (const char *program,
513                        const char *path,
514                        const char *working_dir)
515 {
516   return GLIB_PRIVATE_CALL(g_find_program_for_path) (program, path, working_dir);
517 }
518
519 static void
520 test_find_program_for_path (void)
521 {
522   GError *error = NULL;
523   /* Using .cmd extension to make windows to consider it an executable */
524   const char *command_to_find = "just-an-exe-file.cmd";
525   char *path;
526   char *exe_path;
527   char *found_path;
528   char *old_cwd;
529   char *tmp;
530
531   tmp = g_dir_make_tmp ("find_program_for_path_XXXXXXX", &error);
532   g_assert_no_error (error);
533
534   path = g_build_filename (tmp, "sub-path", NULL);
535   g_mkdir (path, 0700);
536   g_assert_true (g_file_test (path, G_FILE_TEST_IS_DIR));
537
538   exe_path = g_build_filename (path, command_to_find, NULL);
539   g_file_set_contents (exe_path, "", -1, &error);
540   g_assert_no_error (error);
541   g_assert_true (g_file_test (exe_path, G_FILE_TEST_EXISTS));
542
543 #ifdef G_OS_UNIX
544   g_assert_no_errno (g_chmod (exe_path, 0500));
545 #endif
546   g_assert_true (g_file_test (exe_path, G_FILE_TEST_IS_EXECUTABLE));
547
548   g_assert_null (g_find_program_in_path (command_to_find));
549   g_assert_null (find_program_for_path (command_to_find, NULL, NULL));
550
551   found_path = find_program_for_path (command_to_find, path, NULL);
552 #ifdef __APPLE__
553   g_assert_nonnull (found_path);
554   g_assert_true (g_str_has_suffix (found_path, exe_path));
555 #else
556   g_assert_cmpstr (exe_path, ==, found_path);
557 #endif
558   g_clear_pointer (&found_path, g_free);
559
560   found_path = find_program_for_path (command_to_find, path, path);
561 #ifdef __APPLE__
562   g_assert_nonnull (found_path);
563   g_assert_true (g_str_has_suffix (found_path, exe_path));
564 #else
565   g_assert_cmpstr (exe_path, ==, found_path);
566 #endif
567   g_clear_pointer (&found_path, g_free);
568
569   found_path = find_program_for_path (command_to_find, NULL, path);
570 #ifdef __APPLE__
571   g_assert_nonnull (found_path);
572   g_assert_true (g_str_has_suffix (found_path, exe_path));
573 #else
574   g_assert_cmpstr (exe_path, ==, found_path);
575 #endif
576   g_clear_pointer (&found_path, g_free);
577
578   found_path = find_program_for_path (command_to_find, "::", path);
579 #ifdef __APPLE__
580   g_assert_nonnull (found_path);
581   g_assert_true (g_str_has_suffix (found_path, exe_path));
582 #else
583   g_assert_cmpstr (exe_path, ==, found_path);
584 #endif
585   g_clear_pointer (&found_path, g_free);
586
587   old_cwd = g_get_current_dir ();
588   g_chdir (path);
589   found_path =
590     find_program_for_path (command_to_find,
591       G_SEARCHPATH_SEPARATOR_S G_SEARCHPATH_SEPARATOR_S, NULL);
592   g_chdir (old_cwd);
593   g_clear_pointer (&old_cwd, g_free);
594 #ifdef __APPLE__
595   g_assert_nonnull (found_path);
596   g_assert_true (g_str_has_suffix (found_path, exe_path));
597 #else
598   g_assert_cmpstr (exe_path, ==, found_path);
599 #endif
600   g_clear_pointer (&found_path, g_free);
601
602   old_cwd = g_get_current_dir ();
603   g_chdir (tmp);
604   found_path =
605     find_program_for_path (command_to_find,
606       G_SEARCHPATH_SEPARATOR_S G_SEARCHPATH_SEPARATOR_S, "sub-path");
607   g_chdir (old_cwd);
608   g_clear_pointer (&old_cwd, g_free);
609 #ifdef __APPLE__
610   g_assert_nonnull (found_path);
611   g_assert_true (g_str_has_suffix (found_path, exe_path));
612 #else
613   g_assert_cmpstr (exe_path, ==, found_path);
614 #endif
615   g_clear_pointer (&found_path, g_free);
616
617   g_assert_null (
618     find_program_for_path (command_to_find,
619       G_SEARCHPATH_SEPARATOR_S G_SEARCHPATH_SEPARATOR_S, "other-sub-path"));
620
621   found_path = find_program_for_path (command_to_find,
622     G_SEARCHPATH_SEPARATOR_S "sub-path" G_SEARCHPATH_SEPARATOR_S, tmp);
623 #ifdef __APPLE__
624   g_assert_nonnull (found_path);
625   g_assert_true (g_str_has_suffix (found_path, exe_path));
626 #else
627   g_assert_cmpstr (exe_path, ==, found_path);
628 #endif
629   g_clear_pointer (&found_path, g_free);
630
631   g_assert_null (find_program_for_path (command_to_find,
632     G_SEARCHPATH_SEPARATOR_S "other-sub-path" G_SEARCHPATH_SEPARATOR_S, tmp));
633
634 #ifdef G_OS_UNIX
635   found_path = find_program_for_path ("sh", NULL, tmp);
636   g_assert_nonnull (found_path);
637   g_clear_pointer (&found_path, g_free);
638
639   old_cwd = g_get_current_dir ();
640   g_chdir ("/");
641   found_path = find_program_for_path ("sh", "sbin:bin:usr/bin:usr/sbin", NULL);
642   g_chdir (old_cwd);
643   g_clear_pointer (&old_cwd, g_free);
644   g_assert_nonnull (found_path);
645   g_clear_pointer (&found_path, g_free);
646
647   found_path = find_program_for_path ("sh", "sbin:bin:usr/bin:usr/sbin", "/");
648   g_assert_nonnull (found_path);
649   g_clear_pointer (&found_path, g_free);
650 #endif /* G_OS_UNIX */
651
652   g_clear_pointer (&exe_path, g_free);
653   g_clear_pointer (&path, g_free);
654   g_clear_pointer (&tmp, g_free);
655   g_clear_error (&error);
656 }
657
658 static void
659 test_debug (void)
660 {
661   GDebugKey keys[] = {
662     { "key1", 1 },
663     { "key2", 2 },
664     { "key3", 4 },
665   };
666   guint res;
667
668   res = g_parse_debug_string (NULL, keys, G_N_ELEMENTS (keys));
669   g_assert_cmpint (res, ==, 0);
670
671   res = g_parse_debug_string ("foobabla;#!%!$%112 223", keys, G_N_ELEMENTS (keys));
672   g_assert_cmpint (res, ==, 0);
673
674   res = g_parse_debug_string ("key1:key2", keys, G_N_ELEMENTS (keys));
675   g_assert_cmpint (res, ==, 3);
676
677   res = g_parse_debug_string ("key1;key2", keys, G_N_ELEMENTS (keys));
678   g_assert_cmpint (res, ==, 3);
679
680   res = g_parse_debug_string ("key1,key2", keys, G_N_ELEMENTS (keys));
681   g_assert_cmpint (res, ==, 3);
682
683   res = g_parse_debug_string ("key1   key2", keys, G_N_ELEMENTS (keys));
684   g_assert_cmpint (res, ==, 3);
685
686   res = g_parse_debug_string ("key1\tkey2", keys, G_N_ELEMENTS (keys));
687   g_assert_cmpint (res, ==, 3);
688
689   res = g_parse_debug_string ("all", keys, G_N_ELEMENTS (keys));
690   g_assert_cmpint (res, ==, 7);
691
692   if (g_test_subprocess ())
693     {
694       res = g_parse_debug_string ("help", keys, G_N_ELEMENTS (keys));
695       g_assert_cmpint (res, ==, 0);
696       return;
697     }
698   g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
699   g_test_trap_assert_passed ();
700   g_test_trap_assert_stderr ("*Supported debug values: key1 key2 key3 all help*");
701 }
702
703 static void
704 test_codeset (void)
705 {
706   gchar *c;
707   const gchar *c2;
708
709   c = g_get_codeset ();
710   g_get_charset (&c2);
711
712   g_assert_cmpstr (c, ==, c2);
713
714   g_free (c);
715 }
716
717 static void
718 test_codeset2 (void)
719 {
720   if (g_test_subprocess ())
721     {
722       const gchar *c;
723       g_setenv ("CHARSET", "UTF-8", TRUE);
724       g_get_charset (&c);
725       g_assert_cmpstr (c, ==, "UTF-8");
726       return;
727     }
728   g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
729   g_test_trap_assert_passed ();
730 }
731
732 static void
733 test_console_charset (void)
734 {
735   const gchar *c1;
736   const gchar *c2;
737
738 #ifdef G_OS_WIN32
739   /* store current environment and unset $LANG to make sure it does not interfere */
740   const unsigned int initial_cp = GetConsoleOutputCP ();
741   gchar *initial_lang = g_strdup (g_getenv ("LANG"));
742   g_unsetenv ("LANG");
743
744   /* set console output codepage to something specific (ISO-8859-1 aka CP28591) and query it */
745   SetConsoleOutputCP (28591);
746   g_get_console_charset (&c1);
747   g_assert_cmpstr (c1, ==, "ISO-8859-1");
748
749   /* set $LANG to something specific (should override the console output codepage) and query it */
750   g_setenv ("LANG", "de_DE.ISO-8859-15@euro", TRUE);
751   g_get_console_charset (&c2);
752   g_assert_cmpstr (c2, ==, "ISO-8859-15");
753
754   /* reset environment */
755   if (initial_cp)
756     SetConsoleOutputCP (initial_cp);
757   if (initial_lang)
758     g_setenv ("LANG", initial_lang, TRUE);
759   g_free (initial_lang);
760 #else
761   g_get_charset (&c1);
762   g_get_console_charset (&c2);
763
764   g_assert_cmpstr (c1, ==, c2);
765 #endif
766 }
767
768 extern const gchar *glib_pgettext (const gchar *msgidctxt, gsize msgidoffset);
769
770 static void
771 test_gettext (void)
772 {
773   const gchar *am0, *am1, *am2, *am3;
774
775   am0 = glib_pgettext ("GDateTime\004AM", strlen ("GDateTime") + 1);
776   am1 = g_dpgettext ("glib20", "GDateTime\004AM", strlen ("GDateTime") + 1);
777   am2 = g_dpgettext ("glib20", "GDateTime|AM", 0);
778   am3 = g_dpgettext2 ("glib20", "GDateTime", "AM");
779
780   g_assert_cmpstr (am0, ==, am1);
781   g_assert_cmpstr (am1, ==, am2);
782   g_assert_cmpstr (am2, ==, am3);
783 }
784
785 static void
786 test_username (void)
787 {
788   const gchar *name;
789
790   name = g_get_user_name ();
791
792   g_assert (name != NULL);
793 }
794
795 static void
796 test_realname (void)
797 {
798   const gchar *name;
799
800   name = g_get_real_name ();
801
802   g_assert (name != NULL);
803 }
804
805 static void
806 test_hostname (void)
807 {
808   const gchar *name;
809
810   name = g_get_host_name ();
811
812   g_assert (name != NULL);
813   g_assert_true (g_utf8_validate (name, -1, NULL));
814 }
815
816 #ifdef G_OS_UNIX
817 static void
818 test_xdg_dirs (void)
819 {
820   gchar *xdg;
821   const gchar *dir;
822   const gchar * const *dirs;
823   gchar *s;
824
825   xdg = g_strdup (g_getenv ("XDG_CONFIG_HOME"));
826   if (!xdg)
827     xdg = g_build_filename (g_get_home_dir (), ".config", NULL);
828
829   dir = g_get_user_config_dir ();
830
831   g_assert_cmpstr (dir, ==, xdg);
832   g_free (xdg);
833
834   xdg = g_strdup (g_getenv ("XDG_DATA_HOME"));
835   if (!xdg)
836     xdg = g_build_filename (g_get_home_dir (), ".local", "share", NULL);
837
838   dir = g_get_user_data_dir ();
839
840   g_assert_cmpstr (dir, ==, xdg);
841   g_free (xdg);
842
843   xdg = g_strdup (g_getenv ("XDG_CACHE_HOME"));
844   if (!xdg)
845     xdg = g_build_filename (g_get_home_dir (), ".cache", NULL);
846
847   dir = g_get_user_cache_dir ();
848
849   g_assert_cmpstr (dir, ==, xdg);
850   g_free (xdg);
851
852   xdg = g_strdup (g_getenv ("XDG_STATE_HOME"));
853   if (!xdg)
854     xdg = g_build_filename (g_get_home_dir (), ".local/state", NULL);
855
856   dir = g_get_user_state_dir ();
857
858   g_assert_cmpstr (dir, ==, xdg);
859   g_free (xdg);
860
861   xdg = g_strdup (g_getenv ("XDG_RUNTIME_DIR"));
862   if (!xdg)
863     xdg = g_strdup (g_get_user_cache_dir ());
864
865   dir = g_get_user_runtime_dir ();
866
867   g_assert_cmpstr (dir, ==, xdg);
868   g_free (xdg);
869
870   xdg = (gchar *)g_getenv ("XDG_CONFIG_DIRS");
871   if (!xdg)
872     xdg = "/etc/xdg";
873
874   dirs = g_get_system_config_dirs ();
875
876   s = g_strjoinv (":", (gchar **)dirs);
877
878   g_assert_cmpstr (s, ==, xdg);
879
880   g_free (s);
881 }
882 #endif
883
884 static void
885 test_special_dir (void)
886 {
887   const gchar *dir, *dir2;
888
889   dir = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
890   g_reload_user_special_dirs_cache ();
891   dir2 = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
892
893   g_assert_cmpstr (dir, ==, dir2);
894 }
895
896 static void
897 test_desktop_special_dir (void)
898 {
899   const gchar *dir, *dir2;
900
901   dir = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
902   g_assert (dir != NULL);
903
904   g_reload_user_special_dirs_cache ();
905   dir2 = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
906   g_assert (dir2 != NULL);
907 }
908
909 static void
910 test_os_info (void)
911 {
912   gchar *name;
913   gchar *contents = NULL;
914 #if defined (G_OS_UNIX) && !(defined (G_OS_WIN32) || defined (__APPLE__))
915   struct utsname info;
916 #endif
917
918   /* Whether this is implemented or not, it must not crash */
919   name = g_get_os_info (G_OS_INFO_KEY_NAME);
920   g_test_message ("%s: %s",
921                   G_OS_INFO_KEY_NAME,
922                   name == NULL ? "(null)" : name);
923
924 #if defined (G_OS_WIN32) || defined (__APPLE__)
925   /* These OSs have a special case so NAME should always succeed */
926   g_assert_nonnull (name);
927 #elif defined (G_OS_UNIX)
928   if (g_file_get_contents ("/etc/os-release", &contents, NULL, NULL) ||
929       g_file_get_contents ("/usr/lib/os-release", &contents, NULL, NULL) ||
930       uname (&info) == 0)
931     g_assert_nonnull (name);
932   else
933     g_test_skip ("os-release(5) API not implemented on this platform");
934 #else
935   g_test_skip ("g_get_os_info() not supported on this platform");
936 #endif
937
938   g_free (name);
939   g_free (contents);
940 }
941
942 static void
943 source_test (gpointer data)
944 {
945   g_assert_not_reached ();
946 }
947
948 static void
949 test_clear_source (void)
950 {
951   guint id;
952
953   id = g_idle_add_once (source_test, NULL);
954   g_assert_cmpuint (id, >, 0);
955
956   g_clear_handle_id (&id, g_source_remove);
957   g_assert_cmpuint (id, ==, 0);
958
959   id = g_timeout_add_once (100, source_test, NULL);
960   g_assert_cmpuint (id, >, 0);
961
962   g_clear_handle_id (&id, g_source_remove);
963   g_assert_cmpuint (id, ==, 0);
964 }
965
966 static void
967 test_clear_pointer (void)
968 {
969   gpointer a;
970
971   a = g_malloc (5);
972   g_clear_pointer (&a, g_free);
973   g_assert (a == NULL);
974
975   a = g_malloc (5);
976   (g_clear_pointer) (&a, g_free);
977   g_assert (a == NULL);
978 }
979
980 /* Test that g_clear_pointer() works with a GDestroyNotify which contains a cast.
981  * See https://gitlab.gnome.org/GNOME/glib/issues/1425 */
982 static void
983 test_clear_pointer_cast (void)
984 {
985   GHashTable *hash_table = NULL;
986
987   hash_table = g_hash_table_new (g_str_hash, g_str_equal);
988
989   g_assert_nonnull (hash_table);
990
991   g_clear_pointer (&hash_table, (void (*) (GHashTable *)) g_hash_table_destroy);
992
993   g_assert_null (hash_table);
994 }
995
996 /* Test that the macro version of g_clear_pointer() only evaluates its argument
997  * once, just like the function version would. */
998 static void
999 test_clear_pointer_side_effects (void)
1000 {
1001   gchar **my_string_array, **i;
1002
1003   my_string_array = g_new0 (gchar*, 3);
1004   my_string_array[0] = g_strdup ("hello");
1005   my_string_array[1] = g_strdup ("there");
1006   my_string_array[2] = NULL;
1007
1008   i = my_string_array;
1009
1010   g_clear_pointer (i++, g_free);
1011
1012   g_assert_true (i == &my_string_array[1]);
1013   g_assert_null (my_string_array[0]);
1014   g_assert_nonnull (my_string_array[1]);
1015   g_assert_null (my_string_array[2]);
1016
1017   g_free (my_string_array[1]);
1018   g_free (my_string_array[2]);
1019   g_free (my_string_array);
1020 }
1021
1022 static int obj_count;
1023
1024 static void
1025 get_obj (gpointer *obj_out)
1026 {
1027   gpointer obj = g_malloc (5);
1028   obj_count++;
1029
1030   if (obj_out)
1031     *obj_out = g_steal_pointer (&obj);
1032
1033   if (obj)
1034     {
1035       g_free (obj);
1036       obj_count--;
1037     }
1038 }
1039
1040 static void
1041 test_take_pointer (void)
1042 {
1043   gpointer a;
1044   gpointer b;
1045
1046   get_obj (NULL);
1047
1048   get_obj (&a);
1049   g_assert (a);
1050
1051   /* ensure that it works to skip the macro */
1052   b = (g_steal_pointer) (&a);
1053   g_assert (!a);
1054   obj_count--;
1055   g_free (b);
1056
1057   g_assert (!obj_count);
1058 }
1059
1060 static void
1061 test_misc_mem (void)
1062 {
1063   gpointer a;
1064
1065   a = g_try_malloc (0);
1066   g_assert (a == NULL);
1067
1068   a = g_try_malloc0 (0);
1069   g_assert (a == NULL);
1070
1071   a = g_malloc (16);
1072   a = g_try_realloc (a, 20);
1073   a = g_try_realloc (a, 0);
1074
1075   g_assert (a == NULL);
1076 }
1077
1078 static void
1079 aligned_alloc_nz (void)
1080 {
1081   gpointer a;
1082
1083   /* Test an alignment that’s zero */
1084   a = g_aligned_alloc (16, sizeof(char), 0);
1085   g_aligned_free (a);
1086   exit (0);
1087 }
1088
1089 static void
1090 aligned_alloc_npot (void)
1091 {
1092   gpointer a;
1093
1094   /* Test an alignment that’s not a power of two */
1095   a = g_aligned_alloc (16, sizeof(char), 15);
1096   g_aligned_free (a);
1097   exit (0);
1098 }
1099
1100 static void
1101 aligned_alloc_nmov (void)
1102 {
1103   gpointer a;
1104
1105   /* Test an alignment that’s not a multiple of sizeof(void*) */
1106   a = g_aligned_alloc (16, sizeof(char), sizeof(void *) / 2);
1107   g_aligned_free (a);
1108   exit (0);
1109 }
1110
1111 static void
1112 test_aligned_mem (void)
1113 {
1114   gpointer a;
1115
1116   g_test_summary ("Aligned memory allocator");
1117
1118   a = g_aligned_alloc (0, sizeof (int), MAX (sizeof (void *), 8));
1119   g_assert_null (a);
1120
1121   a = g_aligned_alloc0 (0, sizeof (int), MAX (sizeof (void *), 8));
1122   g_assert_null (a);
1123
1124   a = g_aligned_alloc (16, 0, MAX (sizeof (void *), 8));
1125   g_assert_null (a);
1126
1127 #define CHECK_SUBPROCESS_FAIL(name,msg) do { \
1128       if (g_test_undefined ()) \
1129         { \
1130           g_test_message (msg); \
1131           g_test_trap_subprocess ("/utils/aligned-mem/subprocess/" #name, 0, \
1132                                   G_TEST_SUBPROCESS_DEFAULT); \
1133           g_test_trap_assert_failed (); \
1134         } \
1135     } while (0)
1136
1137   CHECK_SUBPROCESS_FAIL (aligned_alloc_nz, "Alignment must not be zero");
1138   CHECK_SUBPROCESS_FAIL (aligned_alloc_npot, "Alignment must be a power of two");
1139   CHECK_SUBPROCESS_FAIL (aligned_alloc_nmov, "Alignment must be a multiple of sizeof(void*)");
1140 }
1141
1142 static void
1143 test_aligned_mem_alignment (void)
1144 {
1145   gchar *p;
1146
1147   g_test_summary ("Check that g_aligned_alloc() returns a correctly aligned pointer");
1148
1149   p = g_aligned_alloc (5, sizeof (*p), 256);
1150   g_assert_nonnull (p);
1151   g_assert_cmpuint (((guintptr) p) % 256, ==, 0);
1152
1153   g_aligned_free (p);
1154 }
1155
1156 static void
1157 test_aligned_mem_zeroed (void)
1158 {
1159   gsize n_blocks = 10;
1160   guint *p;
1161   gsize i;
1162
1163   g_test_summary ("Check that g_aligned_alloc0() zeroes out its allocation");
1164
1165   p = g_aligned_alloc0 (n_blocks, sizeof (*p), 16);
1166   g_assert_nonnull (p);
1167
1168   for (i = 0; i < n_blocks; i++)
1169     g_assert_cmpuint (p[i], ==, 0);
1170
1171   g_aligned_free (p);
1172 }
1173
1174 static void
1175 test_aligned_mem_free_sized (void)
1176 {
1177   gsize n_blocks = 10;
1178   guint *p;
1179
1180   g_test_summary ("Check that g_aligned_free_sized() works");
1181
1182   p = g_aligned_alloc (n_blocks, sizeof (*p), 16);
1183   g_assert_nonnull (p);
1184
1185   g_aligned_free_sized (p, sizeof (*p), n_blocks * 16);
1186
1187   /* NULL should be ignored */
1188   g_aligned_free_sized (NULL, sizeof (*p), n_blocks * 16);
1189 }
1190
1191 static void
1192 test_free_sized (void)
1193 {
1194   gpointer p;
1195
1196   g_test_summary ("Check that g_free_sized() works");
1197
1198   p = g_malloc (123);
1199   g_assert_nonnull (p);
1200
1201   g_free_sized (p, 123);
1202
1203   /* NULL should be ignored */
1204   g_free_sized (NULL, 123);
1205 }
1206
1207 static void
1208 test_nullify (void)
1209 {
1210   gpointer p = &test_nullify;
1211
1212   g_assert (p != NULL);
1213
1214   g_nullify_pointer (&p);
1215
1216   g_assert (p == NULL);
1217 }
1218
1219 static void
1220 atexit_func (void)
1221 {
1222   g_print ("atexit called");
1223 }
1224
1225 static void
1226 test_atexit (void)
1227 {
1228   if (g_test_subprocess ())
1229     {
1230       g_atexit (atexit_func);
1231       return;
1232     }
1233   g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
1234   g_test_trap_assert_passed ();
1235   g_test_trap_assert_stdout ("*atexit called*");
1236 }
1237
1238 static void
1239 test_check_setuid (void)
1240 {
1241   gboolean res;
1242
1243   res = GLIB_PRIVATE_CALL(g_check_setuid) ();
1244   g_assert (!res);
1245 }
1246
1247 /* Test the defined integer limits are correct, as some compilers have had
1248  * problems with signed/unsigned conversion in the past. These limits should not
1249  * vary between platforms, compilers or architectures.
1250  *
1251  * Use string comparisons to avoid the same systematic problems with unary minus
1252  * application in C++. See https://gitlab.gnome.org/GNOME/glib/issues/1663. */
1253 static void
1254 test_int_limits (void)
1255 {
1256   gchar *str = NULL;
1257
1258   g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1663");
1259
1260   str = g_strdup_printf ("%d %d %u\n"
1261                          "%" G_GINT16_FORMAT " %" G_GINT16_FORMAT " %" G_GUINT16_FORMAT "\n"
1262                          "%" G_GINT32_FORMAT " %" G_GINT32_FORMAT " %" G_GUINT32_FORMAT "\n"
1263                          "%" G_GINT64_FORMAT " %" G_GINT64_FORMAT " %" G_GUINT64_FORMAT "\n",
1264                          G_MININT8, G_MAXINT8, G_MAXUINT8,
1265                          G_MININT16, G_MAXINT16, G_MAXUINT16,
1266                          G_MININT32, G_MAXINT32, G_MAXUINT32,
1267                          G_MININT64, G_MAXINT64, G_MAXUINT64);
1268
1269   g_assert_cmpstr (str, ==,
1270                    "-128 127 255\n"
1271                    "-32768 32767 65535\n"
1272                    "-2147483648 2147483647 4294967295\n"
1273                    "-9223372036854775808 9223372036854775807 18446744073709551615\n");
1274   g_free (str);
1275 }
1276
1277 static void
1278 test_clear_list (void)
1279 {
1280     GList *list = NULL;
1281
1282     g_clear_list (&list, NULL);
1283     g_assert_null (list);
1284
1285     list = g_list_prepend (list, "test");
1286     g_assert_nonnull (list);
1287
1288     g_clear_list (&list, NULL);
1289     g_assert_null (list);
1290
1291     g_clear_list (&list, g_free);
1292     g_assert_null (list);
1293
1294     list = g_list_prepend (list, g_malloc (16));
1295     g_assert_nonnull (list);
1296
1297     g_clear_list (&list, g_free);
1298     g_assert_null (list);
1299 }
1300
1301 static void
1302 test_clear_slist (void)
1303 {
1304     GSList *slist = NULL;
1305
1306     g_clear_slist (&slist, NULL);
1307     g_assert_null (slist);
1308
1309     slist = g_slist_prepend (slist, "test");
1310     g_assert_nonnull (slist);
1311
1312     g_clear_slist (&slist, NULL);
1313     g_assert_null (slist);
1314
1315     g_clear_slist (&slist, g_free);
1316     g_assert_null (slist);
1317
1318     slist = g_slist_prepend (slist, g_malloc (16));
1319     g_assert_nonnull (slist);
1320
1321     g_clear_slist (&slist, g_free);
1322     g_assert_null (slist);
1323 }
1324
1325 int
1326 main (int   argc,
1327       char *argv[])
1328 {
1329   argv0 = argv[0];
1330
1331   /* g_test_init() only calls g_set_prgname() if g_get_prgname()
1332    * returns %NULL, but g_get_prgname() on Windows never returns NULL.
1333    * So we need to do this by hand to make test_appname() work on
1334    * Windows.
1335    */
1336   g_set_prgname (argv[0]);
1337
1338   g_test_init (&argc, &argv, NULL);
1339
1340   g_test_add_func ("/utils/language-names", test_language_names);
1341   g_test_add_func ("/utils/locale-variants", test_locale_variants);
1342   g_test_add_func ("/utils/version", test_version);
1343   g_test_add_func ("/utils/appname", test_appname);
1344   g_test_add_func ("/utils/prgname-thread-safety", test_prgname_thread_safety);
1345   g_test_add_func ("/utils/tmpdir", test_tmpdir);
1346   g_test_add_func ("/utils/basic_bits", test_basic_bits);
1347   g_test_add_func ("/utils/bits", test_bits);
1348   g_test_add_func ("/utils/swap", test_swap);
1349   g_test_add_func ("/utils/find-program", test_find_program);
1350   g_test_add_func ("/utils/find-program-for-path", test_find_program_for_path);
1351   g_test_add_func ("/utils/debug", test_debug);
1352   g_test_add_func ("/utils/codeset", test_codeset);
1353   g_test_add_func ("/utils/codeset2", test_codeset2);
1354   g_test_add_func ("/utils/console-charset", test_console_charset);
1355   g_test_add_func ("/utils/gettext", test_gettext);
1356   g_test_add_func ("/utils/username", test_username);
1357   g_test_add_func ("/utils/realname", test_realname);
1358   g_test_add_func ("/utils/hostname", test_hostname);
1359 #ifdef G_OS_UNIX
1360   g_test_add_func ("/utils/xdgdirs", test_xdg_dirs);
1361 #endif
1362   g_test_add_func ("/utils/specialdir", test_special_dir);
1363   g_test_add_func ("/utils/specialdir/desktop", test_desktop_special_dir);
1364   g_test_add_func ("/utils/os-info", test_os_info);
1365   g_test_add_func ("/utils/clear-pointer", test_clear_pointer);
1366   g_test_add_func ("/utils/clear-pointer-cast", test_clear_pointer_cast);
1367   g_test_add_func ("/utils/clear-pointer/side-effects", test_clear_pointer_side_effects);
1368   g_test_add_func ("/utils/take-pointer", test_take_pointer);
1369   g_test_add_func ("/utils/clear-source", test_clear_source);
1370   g_test_add_func ("/utils/misc-mem", test_misc_mem);
1371   g_test_add_func ("/utils/aligned-mem", test_aligned_mem);
1372   g_test_add_func ("/utils/aligned-mem/subprocess/aligned_alloc_nz", aligned_alloc_nz);
1373   g_test_add_func ("/utils/aligned-mem/subprocess/aligned_alloc_npot", aligned_alloc_npot);
1374   g_test_add_func ("/utils/aligned-mem/subprocess/aligned_alloc_nmov", aligned_alloc_nmov);
1375   g_test_add_func ("/utils/aligned-mem/alignment", test_aligned_mem_alignment);
1376   g_test_add_func ("/utils/aligned-mem/zeroed", test_aligned_mem_zeroed);
1377   g_test_add_func ("/utils/aligned-mem/free-sized", test_aligned_mem_free_sized);
1378   g_test_add_func ("/utils/free-sized", test_free_sized);
1379   g_test_add_func ("/utils/nullify", test_nullify);
1380   g_test_add_func ("/utils/atexit", test_atexit);
1381   g_test_add_func ("/utils/check-setuid", test_check_setuid);
1382   g_test_add_func ("/utils/int-limits", test_int_limits);
1383   g_test_add_func ("/utils/clear-list", test_clear_list);
1384   g_test_add_func ("/utils/clear-slist", test_clear_slist);
1385
1386   return g_test_run ();
1387 }