glib-unix: add function to ensure an fd is sealed
[platform/upstream/glib.git] / glib / tests / utils.c
1 /* Unit tests for utilities
2  * Copyright (C) 2010 Red Hat, Inc.
3  *
4  * This work is provided "as is"; redistribution and modification
5  * in whole or in part, in any medium, physical or electronic is
6  * permitted without restriction.
7  *
8  * This work is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  *
12  * In no event shall the authors or contributors be liable for any
13  * direct, indirect, incidental, special, exemplary, or consequential
14  * damages (including, but not limited to, procurement of substitute
15  * goods or services; loss of use, data, or profits; or business
16  * interruption) however caused and on any theory of liability, whether
17  * in contract, strict liability, or tort (including negligence or
18  * otherwise) arising in any way out of the use of this software, even
19  * if advised of the possibility of such damage.
20  *
21  * Author: Matthias Clasen
22  */
23
24 #define GLIB_DISABLE_DEPRECATION_WARNINGS
25
26 #include "glib.h"
27 #include "glib-private.h"
28
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdarg.h>
32
33 static gboolean
34 strv_check (const gchar * const *strv, ...)
35 {
36   va_list args;
37   gchar *s;
38   gint i;
39
40   va_start (args, strv);
41   for (i = 0; strv[i]; i++)
42     {
43       s = va_arg (args, gchar*);
44       if (g_strcmp0 (strv[i], s) != 0)
45         {
46           va_end (args);
47           return FALSE;
48         }
49     }
50
51   va_end (args);
52
53   return TRUE;
54 }
55
56 static void
57 test_language_names (void)
58 {
59   const gchar * const *names;
60
61   g_setenv ("LANGUAGE", "de:en_US", TRUE);
62   names = g_get_language_names ();
63   g_assert (strv_check (names, "de", "en_US", "en", "C", NULL));
64
65   g_setenv ("LANGUAGE", "tt_RU.UTF-8@iqtelif", TRUE);
66   names = g_get_language_names ();
67   g_assert (strv_check (names,
68                         "tt_RU.UTF-8@iqtelif",
69                         "tt_RU@iqtelif",
70                         "tt.UTF-8@iqtelif",
71                         "tt@iqtelif",
72                         "tt_RU.UTF-8",
73                         "tt_RU",
74                         "tt.UTF-8",
75                         "tt",
76                         "C",
77                         NULL));
78 }
79
80 static void
81 test_locale_variants (void)
82 {
83   char **v;
84
85   v = g_get_locale_variants ("fr_BE");
86   g_assert (strv_check ((const gchar * const *) v, "fr_BE", "fr", NULL));
87   g_strfreev (v);
88
89   v = g_get_locale_variants ("sr_SR@latin");
90   g_assert (strv_check ((const gchar * const *) v, "sr_SR@latin", "sr@latin", "sr_SR", "sr", NULL));
91   g_strfreev (v);
92 }
93
94 static void
95 test_version (void)
96 {
97   if (g_test_verbose ())
98     g_print ("(header %d.%d.%d library %d.%d.%d) ",
99               GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION,
100               glib_major_version, glib_minor_version, glib_micro_version);
101
102   g_assert (glib_check_version (GLIB_MAJOR_VERSION,
103                                 GLIB_MINOR_VERSION,
104                                 GLIB_MICRO_VERSION) == NULL);
105   g_assert (glib_check_version (GLIB_MAJOR_VERSION,
106                                 GLIB_MINOR_VERSION,
107                                 0) == NULL);
108   g_assert (glib_check_version (GLIB_MAJOR_VERSION - 1,
109                                 0,
110                                 0) != NULL);
111   g_assert (glib_check_version (GLIB_MAJOR_VERSION + 1,
112                                 0,
113                                 0) != NULL);
114   g_assert (glib_check_version (GLIB_MAJOR_VERSION,
115                                 GLIB_MINOR_VERSION + 1,
116                                 0) != NULL);
117   /* don't use + 1 here, since a +/-1 difference can
118    * happen due to post-release version bumps in git
119    */
120   g_assert (glib_check_version (GLIB_MAJOR_VERSION,
121                                 GLIB_MINOR_VERSION,
122                                 GLIB_MICRO_VERSION + 3) != NULL);
123 }
124
125 static const gchar *argv0;
126
127 static void
128 test_appname (void)
129 {
130   const gchar *prgname;
131   const gchar *appname;
132
133   prgname = g_get_prgname ();
134   appname = g_get_application_name ();
135   g_assert_cmpstr (prgname, ==, argv0);
136   g_assert_cmpstr (appname, ==, prgname);
137
138   g_set_prgname ("prgname");
139
140   prgname = g_get_prgname ();
141   appname = g_get_application_name ();
142   g_assert_cmpstr (prgname, ==, "prgname");
143   g_assert_cmpstr (appname, ==, "prgname");
144
145   g_set_application_name ("appname");
146
147   prgname = g_get_prgname ();
148   appname = g_get_application_name ();
149   g_assert_cmpstr (prgname, ==, "prgname");
150   g_assert_cmpstr (appname, ==, "appname");
151 }
152
153 static void
154 test_tmpdir (void)
155 {
156   g_test_bug ("627969");
157   g_assert_cmpstr (g_get_tmp_dir (), !=, "");
158 }
159
160 static void
161 test_bits (void)
162 {
163   gulong mask;
164   gint max_bit;
165   gint i, pos;
166
167   pos = g_bit_nth_lsf (0, -1);
168   g_assert_cmpint (pos, ==, -1);
169
170   max_bit = sizeof (gulong) * 8;
171   for (i = 0; i < max_bit; i++)
172     {
173       mask = 1UL << i;
174
175       pos = g_bit_nth_lsf (mask, -1);
176       g_assert_cmpint (pos, ==, i);
177
178       pos = g_bit_nth_lsf (mask, i - 3);
179       g_assert_cmpint (pos , ==, i);
180
181       pos = g_bit_nth_lsf (mask, i);
182       g_assert_cmpint (pos , ==, -1);
183
184       pos = g_bit_nth_lsf (mask, i + 1);
185       g_assert_cmpint (pos , ==, -1);
186     }
187
188   pos = g_bit_nth_msf (0, -1);
189   g_assert_cmpint (pos, ==, -1);
190
191   for (i = 0; i < max_bit; i++)
192     {
193       mask = 1UL << i;
194
195       pos = g_bit_nth_msf (mask, -1);
196       g_assert_cmpint (pos, ==, i);
197
198       pos = g_bit_nth_msf (mask, i + 3);
199       g_assert_cmpint (pos , ==, i);
200
201       pos = g_bit_nth_msf (mask, i);
202       g_assert_cmpint (pos , ==, -1);
203
204       if (i > 0)
205         {
206           pos = g_bit_nth_msf (mask, i - 1);
207           g_assert_cmpint (pos , ==, -1);
208         }
209     }
210 }
211
212 static void
213 test_swap (void)
214 {
215   guint16 a16, b16;
216   guint32 a32, b32;
217   guint64 a64, b64;
218
219   a16 = 0xaabb;
220   b16 = 0xbbaa;
221
222   g_assert_cmpint (GUINT16_SWAP_LE_BE (a16), ==, b16);
223
224   a32 = 0xaaaabbbb;
225   b32 = 0xbbbbaaaa;
226
227   g_assert_cmpint (GUINT32_SWAP_LE_BE (a32), ==, b32);
228
229   a64 = G_GUINT64_CONSTANT(0xaaaaaaaabbbbbbbb);
230   b64 = G_GUINT64_CONSTANT(0xbbbbbbbbaaaaaaaa);
231
232   g_assert_cmpint (GUINT64_SWAP_LE_BE (a64), ==, b64);
233 }
234
235 static void
236 test_find_program (void)
237 {
238   gchar *res;
239
240 #ifdef G_OS_UNIX
241   res = g_find_program_in_path ("sh");
242   g_assert (res != NULL);
243   g_free (res);
244
245   res = g_find_program_in_path ("/bin/sh");
246   g_assert (res != NULL);
247   g_free (res);
248 #else
249   /* There's not a lot we can search for that would reliably work both
250    * on real Windows and mingw.
251    */
252 #endif
253
254   res = g_find_program_in_path ("this_program_does_not_exit");
255   g_assert (res == NULL);
256
257   res = g_find_program_in_path ("/bin");
258   g_assert (res == NULL);
259
260   res = g_find_program_in_path ("/etc/passwd");
261   g_assert (res == NULL);
262 }
263
264 static void
265 test_debug (void)
266 {
267   GDebugKey keys[] = {
268     { "key1", 1 },
269     { "key2", 2 },
270     { "key3", 4 },
271   };
272   guint res;
273
274   res = g_parse_debug_string (NULL, keys, G_N_ELEMENTS (keys));
275   g_assert_cmpint (res, ==, 0);
276
277   res = g_parse_debug_string ("foobabla;#!%!$%112 223", keys, G_N_ELEMENTS (keys));
278   g_assert_cmpint (res, ==, 0);
279
280   res = g_parse_debug_string ("key1:key2", keys, G_N_ELEMENTS (keys));
281   g_assert_cmpint (res, ==, 3);
282
283   res = g_parse_debug_string ("key1;key2", keys, G_N_ELEMENTS (keys));
284   g_assert_cmpint (res, ==, 3);
285
286   res = g_parse_debug_string ("key1,key2", keys, G_N_ELEMENTS (keys));
287   g_assert_cmpint (res, ==, 3);
288
289   res = g_parse_debug_string ("key1   key2", keys, G_N_ELEMENTS (keys));
290   g_assert_cmpint (res, ==, 3);
291
292   res = g_parse_debug_string ("key1\tkey2", keys, G_N_ELEMENTS (keys));
293   g_assert_cmpint (res, ==, 3);
294
295   res = g_parse_debug_string ("all", keys, G_N_ELEMENTS (keys));
296   g_assert_cmpint (res, ==, 7);
297
298   if (g_test_subprocess ())
299     {
300       res = g_parse_debug_string ("help", keys, G_N_ELEMENTS (keys));
301       g_assert_cmpint (res, ==, 0);
302       return;
303     }
304   g_test_trap_subprocess (NULL, 0, 0);
305   g_test_trap_assert_passed ();
306   g_test_trap_assert_stderr ("*Supported debug values: key1 key2 key3 all help*");
307 }
308
309 static void
310 test_codeset (void)
311 {
312   gchar *c;
313   const gchar *c2;
314
315   c = g_get_codeset ();
316   g_get_charset (&c2);
317
318   g_assert_cmpstr (c, ==, c2);
319
320   g_free (c);
321 }
322
323 static void
324 test_codeset2 (void)
325 {
326   if (g_test_subprocess ())
327     {
328       const gchar *c;
329       g_setenv ("CHARSET", "UTF-8", TRUE);
330       g_get_charset (&c);
331       g_assert_cmpstr (c, ==, "UTF-8");
332       return;
333     }
334   g_test_trap_subprocess (NULL, 0, 0);
335   g_test_trap_assert_passed ();
336 }
337
338 static void
339 test_basename (void)
340 {
341   const gchar *path = "/path/to/a/file/deep/down.sh";
342   const gchar *b;
343
344   b = g_basename (path);
345
346   g_assert_cmpstr (b, ==, "down.sh");
347 }
348
349 extern const gchar *glib_pgettext (const gchar *msgidctxt, gsize msgidoffset);
350
351 static void
352 test_gettext (void)
353 {
354   const gchar *am0, *am1, *am2, *am3;
355
356   am0 = glib_pgettext ("GDateTime\004AM", strlen ("GDateTime") + 1);
357   am1 = g_dpgettext ("glib20", "GDateTime\004AM", strlen ("GDateTime") + 1);
358   am2 = g_dpgettext ("glib20", "GDateTime|AM", 0);
359   am3 = g_dpgettext2 ("glib20", "GDateTime", "AM");
360
361   g_assert_cmpstr (am0, ==, am1);
362   g_assert_cmpstr (am1, ==, am2);
363   g_assert_cmpstr (am2, ==, am3);
364 }
365
366 static void
367 test_username (void)
368 {
369   const gchar *name;
370
371   name = g_get_user_name ();
372
373   g_assert (name != NULL);
374 }
375
376 static void
377 test_realname (void)
378 {
379   const gchar *name;
380
381   name = g_get_real_name ();
382
383   g_assert (name != NULL);
384 }
385
386 static void
387 test_hostname (void)
388 {
389   const gchar *name;
390
391   name = g_get_host_name ();
392
393   g_assert (name != NULL);
394 }
395
396 #ifdef G_OS_UNIX
397 static void
398 test_xdg_dirs (void)
399 {
400   gchar *xdg;
401   const gchar *dir;
402   const gchar * const *dirs;
403   gchar *s;
404
405   xdg = g_strdup (g_getenv ("XDG_CONFIG_HOME"));
406   if (!xdg)
407     xdg = g_build_filename (g_get_home_dir (), ".config", NULL);
408
409   dir = g_get_user_config_dir ();
410
411   g_assert_cmpstr (dir, ==, xdg);
412   g_free (xdg);
413
414   xdg = g_strdup (g_getenv ("XDG_DATA_HOME"));
415   if (!xdg)
416     xdg = g_build_filename (g_get_home_dir (), ".local", "share", NULL);
417
418   dir = g_get_user_data_dir ();
419
420   g_assert_cmpstr (dir, ==, xdg);
421   g_free (xdg);
422
423   xdg = g_strdup (g_getenv ("XDG_CACHE_HOME"));
424   if (!xdg)
425     xdg = g_build_filename (g_get_home_dir (), ".cache", NULL);
426
427   dir = g_get_user_cache_dir ();
428
429   g_assert_cmpstr (dir, ==, xdg);
430   g_free (xdg);
431
432   xdg = g_strdup (g_getenv ("XDG_RUNTIME_DIR"));
433   if (!xdg)
434     xdg = g_strdup (g_get_user_cache_dir ());
435
436   dir = g_get_user_runtime_dir ();
437
438   g_assert_cmpstr (dir, ==, xdg);
439   g_free (xdg);
440
441   xdg = (gchar *)g_getenv ("XDG_CONFIG_DIRS");
442   if (!xdg)
443     xdg = "/etc/xdg";
444
445   dirs = g_get_system_config_dirs ();
446
447   s = g_strjoinv (":", (gchar **)dirs);
448
449   g_assert_cmpstr (s, ==, xdg);
450
451   g_free (s);
452 }
453 #endif
454
455 static void
456 test_special_dir (void)
457 {
458   const gchar *dir, *dir2;
459
460   dir = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
461   g_reload_user_special_dirs_cache ();
462   dir2 = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
463
464   g_assert_cmpstr (dir, ==, dir2);
465 }
466
467 static void
468 test_desktop_special_dir (void)
469 {
470   const gchar *dir, *dir2;
471
472   dir = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
473   g_assert (dir != NULL);
474
475   g_reload_user_special_dirs_cache ();
476   dir2 = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
477   g_assert (dir2 != NULL);
478 }
479
480 static void
481 test_clear_pointer (void)
482 {
483   gpointer a;
484
485   a = g_malloc (5);
486   g_clear_pointer (&a, g_free);
487   g_assert (a == NULL);
488
489   a = g_malloc (5);
490   (g_clear_pointer) (&a, g_free);
491   g_assert (a == NULL);
492 }
493
494 static void
495 test_misc_mem (void)
496 {
497   gpointer a;
498
499   a = g_try_malloc (0);
500   g_assert (a == NULL);
501
502   a = g_try_malloc0 (0);
503   g_assert (a == NULL);
504
505   a = g_malloc (16);
506   a = g_try_realloc (a, 20);
507   a = g_try_realloc (a, 0);
508
509   g_assert (a == NULL);
510 }
511
512 static void
513 test_nullify (void)
514 {
515   gpointer p = &test_nullify;
516
517   g_assert (p != NULL);
518
519   g_nullify_pointer (&p);
520
521   g_assert (p == NULL);
522 }
523
524 static void
525 atexit_func (void)
526 {
527   g_print ("atexit called");
528 }
529
530 static void
531 test_atexit (void)
532 {
533   if (g_test_subprocess ())
534     {
535       g_atexit (atexit_func);
536       return;
537     }
538   g_test_trap_subprocess (NULL, 0, 0);
539   g_test_trap_assert_passed ();
540   g_test_trap_assert_stdout ("*atexit called*");
541 }
542
543 static void
544 test_check_setuid (void)
545 {
546   gboolean res;
547
548   res = GLIB_PRIVATE_CALL(g_check_setuid) ();
549   g_assert (!res);
550 }
551
552 int
553 main (int   argc,
554       char *argv[])
555 {
556   argv0 = argv[0];
557
558   /* for tmpdir test, need to do this early before g_get_any_init */
559   g_setenv ("TMPDIR", "", TRUE);
560   g_unsetenv ("TMP");
561   g_unsetenv ("TEMP");
562
563   /* g_test_init() only calls g_set_prgname() if g_get_prgname()
564    * returns %NULL, but g_get_prgname() on Windows never returns NULL.
565    * So we need to do this by hand to make test_appname() work on
566    * Windows.
567    */
568   g_set_prgname (argv[0]);
569
570   g_test_init (&argc, &argv, NULL);
571   g_test_bug_base ("http://bugzilla.gnome.org/");
572
573   g_test_add_func ("/utils/language-names", test_language_names);
574   g_test_add_func ("/utils/locale-variants", test_locale_variants);
575   g_test_add_func ("/utils/version", test_version);
576   g_test_add_func ("/utils/appname", test_appname);
577   g_test_add_func ("/utils/tmpdir", test_tmpdir);
578   g_test_add_func ("/utils/bits", test_bits);
579   g_test_add_func ("/utils/swap", test_swap);
580   g_test_add_func ("/utils/find-program", test_find_program);
581   g_test_add_func ("/utils/debug", test_debug);
582   g_test_add_func ("/utils/codeset", test_codeset);
583   g_test_add_func ("/utils/codeset2", test_codeset2);
584   g_test_add_func ("/utils/basename", test_basename);
585   g_test_add_func ("/utils/gettext", test_gettext);
586   g_test_add_func ("/utils/username", test_username);
587   g_test_add_func ("/utils/realname", test_realname);
588   g_test_add_func ("/utils/hostname", test_hostname);
589 #ifdef G_OS_UNIX
590   g_test_add_func ("/utils/xdgdirs", test_xdg_dirs);
591 #endif
592   g_test_add_func ("/utils/specialdir", test_special_dir);
593   g_test_add_func ("/utils/specialdir/desktop", test_desktop_special_dir);
594   g_test_add_func ("/utils/clear-pointer", test_clear_pointer);
595   g_test_add_func ("/utils/misc-mem", test_misc_mem);
596   g_test_add_func ("/utils/nullify", test_nullify);
597   g_test_add_func ("/utils/atexit", test_atexit);
598   g_test_add_func ("/utils/check-setuid", test_check_setuid);
599
600   return g_test_run ();
601 }