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 | #ifndef GLIB_DISABLE_DEPRECATION_WARNINGS |
25 | #define GLIB_DISABLE_DEPRECATION_WARNINGS |
26 | #endif |
27 | |
28 | #include "glib.h" |
29 | #include "glib-private.h" |
30 | |
31 | #include <stdlib.h> |
32 | #include <string.h> |
33 | #include <stdarg.h> |
34 | #ifdef G_OS_UNIX |
35 | #include <sys/utsname.h> |
36 | #endif |
37 | #ifdef G_OS_WIN32 |
38 | #include <windows.h> |
39 | #endif |
40 | |
41 | static gboolean |
42 | strv_check (const gchar * const *strv, ...) |
43 | { |
44 | va_list args; |
45 | gchar *s; |
46 | gint i; |
47 | |
48 | va_start (args, strv); |
49 | for (i = 0; strv[i]; i++) |
50 | { |
51 | s = va_arg (args, gchar*); |
52 | if (g_strcmp0 (str1: strv[i], str2: s) != 0) |
53 | { |
54 | va_end (args); |
55 | return FALSE; |
56 | } |
57 | } |
58 | |
59 | va_end (args); |
60 | |
61 | return TRUE; |
62 | } |
63 | |
64 | static void |
65 | test_language_names (void) |
66 | { |
67 | const gchar * const *names; |
68 | |
69 | g_setenv (variable: "LANGUAGE" , value: "de:en_US" , TRUE); |
70 | names = g_get_language_names (); |
71 | g_assert (strv_check (names, "de" , "en_US" , "en" , "C" , NULL)); |
72 | |
73 | g_setenv (variable: "LANGUAGE" , value: "tt_RU.UTF-8@iqtelif" , TRUE); |
74 | names = g_get_language_names (); |
75 | g_assert (strv_check (names, |
76 | "tt_RU.UTF-8@iqtelif" , |
77 | "tt_RU@iqtelif" , |
78 | "tt.UTF-8@iqtelif" , |
79 | "tt@iqtelif" , |
80 | "tt_RU.UTF-8" , |
81 | "tt_RU" , |
82 | "tt.UTF-8" , |
83 | "tt" , |
84 | "C" , |
85 | NULL)); |
86 | } |
87 | |
88 | static void |
89 | test_locale_variants (void) |
90 | { |
91 | char **v; |
92 | |
93 | v = g_get_locale_variants (locale: "fr_BE" ); |
94 | g_assert (strv_check ((const gchar * const *) v, "fr_BE" , "fr" , NULL)); |
95 | g_strfreev (str_array: v); |
96 | |
97 | v = g_get_locale_variants (locale: "sr_SR@latin" ); |
98 | g_assert (strv_check ((const gchar * const *) v, "sr_SR@latin" , "sr@latin" , "sr_SR" , "sr" , NULL)); |
99 | g_strfreev (str_array: v); |
100 | } |
101 | |
102 | static void |
103 | test_version (void) |
104 | { |
105 | if (g_test_verbose ()) |
106 | g_printerr (format: "(header %d.%d.%d library %d.%d.%d) " , |
107 | GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION, |
108 | glib_major_version, glib_minor_version, glib_micro_version); |
109 | |
110 | g_assert (glib_check_version (GLIB_MAJOR_VERSION, |
111 | GLIB_MINOR_VERSION, |
112 | GLIB_MICRO_VERSION) == NULL); |
113 | g_assert (glib_check_version (GLIB_MAJOR_VERSION, |
114 | GLIB_MINOR_VERSION, |
115 | 0) == NULL); |
116 | g_assert (glib_check_version (GLIB_MAJOR_VERSION - 1, |
117 | 0, |
118 | 0) != NULL); |
119 | g_assert (glib_check_version (GLIB_MAJOR_VERSION + 1, |
120 | 0, |
121 | 0) != NULL); |
122 | g_assert (glib_check_version (GLIB_MAJOR_VERSION, |
123 | GLIB_MINOR_VERSION + 1, |
124 | 0) != NULL); |
125 | /* don't use + 1 here, since a +/-1 difference can |
126 | * happen due to post-release version bumps in git |
127 | */ |
128 | g_assert (glib_check_version (GLIB_MAJOR_VERSION, |
129 | GLIB_MINOR_VERSION, |
130 | GLIB_MICRO_VERSION + 3) != NULL); |
131 | } |
132 | |
133 | static const gchar *argv0; |
134 | |
135 | static void |
136 | test_appname (void) |
137 | { |
138 | const gchar *prgname; |
139 | const gchar *appname; |
140 | |
141 | prgname = g_get_prgname (); |
142 | appname = g_get_application_name (); |
143 | g_assert_cmpstr (prgname, ==, argv0); |
144 | g_assert_cmpstr (appname, ==, prgname); |
145 | |
146 | g_set_prgname (prgname: "prgname" ); |
147 | |
148 | prgname = g_get_prgname (); |
149 | appname = g_get_application_name (); |
150 | g_assert_cmpstr (prgname, ==, "prgname" ); |
151 | g_assert_cmpstr (appname, ==, "prgname" ); |
152 | |
153 | g_set_application_name (application_name: "appname" ); |
154 | |
155 | prgname = g_get_prgname (); |
156 | appname = g_get_application_name (); |
157 | g_assert_cmpstr (prgname, ==, "prgname" ); |
158 | g_assert_cmpstr (appname, ==, "appname" ); |
159 | } |
160 | |
161 | static void |
162 | test_tmpdir (void) |
163 | { |
164 | g_test_bug (bug_uri_snippet: "627969" ); |
165 | g_assert_cmpstr (g_get_tmp_dir (), !=, "" ); |
166 | } |
167 | |
168 | static void |
169 | test_bits (void) |
170 | { |
171 | gulong mask; |
172 | gint max_bit; |
173 | gint i, pos; |
174 | |
175 | pos = g_bit_nth_lsf (0, -1); |
176 | g_assert_cmpint (pos, ==, -1); |
177 | |
178 | max_bit = sizeof (gulong) * 8; |
179 | for (i = 0; i < max_bit; i++) |
180 | { |
181 | mask = 1UL << i; |
182 | |
183 | pos = g_bit_nth_lsf (mask, -1); |
184 | g_assert_cmpint (pos, ==, i); |
185 | |
186 | pos = g_bit_nth_lsf (mask, i - 3); |
187 | g_assert_cmpint (pos , ==, i); |
188 | |
189 | pos = g_bit_nth_lsf (mask, i); |
190 | g_assert_cmpint (pos , ==, -1); |
191 | |
192 | pos = g_bit_nth_lsf (mask, i + 1); |
193 | g_assert_cmpint (pos , ==, -1); |
194 | } |
195 | |
196 | pos = g_bit_nth_msf (0, -1); |
197 | g_assert_cmpint (pos, ==, -1); |
198 | |
199 | for (i = 0; i < max_bit; i++) |
200 | { |
201 | mask = 1UL << i; |
202 | |
203 | pos = g_bit_nth_msf (mask, -1); |
204 | g_assert_cmpint (pos, ==, i); |
205 | |
206 | pos = g_bit_nth_msf (mask, i + 3); |
207 | g_assert_cmpint (pos , ==, i); |
208 | |
209 | pos = g_bit_nth_msf (mask, i); |
210 | g_assert_cmpint (pos , ==, -1); |
211 | |
212 | if (i > 0) |
213 | { |
214 | pos = g_bit_nth_msf (mask, i - 1); |
215 | g_assert_cmpint (pos , ==, -1); |
216 | } |
217 | } |
218 | } |
219 | |
220 | static void |
221 | test_swap (void) |
222 | { |
223 | guint16 a16, b16; |
224 | guint32 a32, b32; |
225 | guint64 a64, b64; |
226 | |
227 | a16 = 0xaabb; |
228 | b16 = 0xbbaa; |
229 | |
230 | g_assert_cmpint (GUINT16_SWAP_LE_BE (a16), ==, b16); |
231 | |
232 | a32 = 0xaaaabbbb; |
233 | b32 = 0xbbbbaaaa; |
234 | |
235 | g_assert_cmpint (GUINT32_SWAP_LE_BE (a32), ==, b32); |
236 | |
237 | a64 = G_GUINT64_CONSTANT(0xaaaaaaaabbbbbbbb); |
238 | b64 = G_GUINT64_CONSTANT(0xbbbbbbbbaaaaaaaa); |
239 | |
240 | g_assert_cmpint (GUINT64_SWAP_LE_BE (a64), ==, b64); |
241 | } |
242 | |
243 | static void |
244 | test_find_program (void) |
245 | { |
246 | gchar *res; |
247 | |
248 | #ifdef G_OS_UNIX |
249 | res = g_find_program_in_path (program: "sh" ); |
250 | g_assert (res != NULL); |
251 | g_free (mem: res); |
252 | |
253 | res = g_find_program_in_path (program: "/bin/sh" ); |
254 | g_assert (res != NULL); |
255 | g_free (mem: res); |
256 | #else |
257 | /* There's not a lot we can search for that would reliably work both |
258 | * on real Windows and mingw. |
259 | */ |
260 | #endif |
261 | |
262 | res = g_find_program_in_path (program: "this_program_does_not_exit" ); |
263 | g_assert (res == NULL); |
264 | |
265 | res = g_find_program_in_path (program: "/bin" ); |
266 | g_assert (res == NULL); |
267 | |
268 | res = g_find_program_in_path (program: "/etc/passwd" ); |
269 | g_assert (res == NULL); |
270 | } |
271 | |
272 | static void |
273 | test_debug (void) |
274 | { |
275 | GDebugKey keys[] = { |
276 | { "key1" , 1 }, |
277 | { "key2" , 2 }, |
278 | { "key3" , 4 }, |
279 | }; |
280 | guint res; |
281 | |
282 | res = g_parse_debug_string (NULL, keys, G_N_ELEMENTS (keys)); |
283 | g_assert_cmpint (res, ==, 0); |
284 | |
285 | res = g_parse_debug_string (string: "foobabla;#!%!$%112 223" , keys, G_N_ELEMENTS (keys)); |
286 | g_assert_cmpint (res, ==, 0); |
287 | |
288 | res = g_parse_debug_string (string: "key1:key2" , keys, G_N_ELEMENTS (keys)); |
289 | g_assert_cmpint (res, ==, 3); |
290 | |
291 | res = g_parse_debug_string (string: "key1;key2" , keys, G_N_ELEMENTS (keys)); |
292 | g_assert_cmpint (res, ==, 3); |
293 | |
294 | res = g_parse_debug_string (string: "key1,key2" , keys, G_N_ELEMENTS (keys)); |
295 | g_assert_cmpint (res, ==, 3); |
296 | |
297 | res = g_parse_debug_string (string: "key1 key2" , keys, G_N_ELEMENTS (keys)); |
298 | g_assert_cmpint (res, ==, 3); |
299 | |
300 | res = g_parse_debug_string (string: "key1\tkey2" , keys, G_N_ELEMENTS (keys)); |
301 | g_assert_cmpint (res, ==, 3); |
302 | |
303 | res = g_parse_debug_string (string: "all" , keys, G_N_ELEMENTS (keys)); |
304 | g_assert_cmpint (res, ==, 7); |
305 | |
306 | if (g_test_subprocess ()) |
307 | { |
308 | res = g_parse_debug_string (string: "help" , keys, G_N_ELEMENTS (keys)); |
309 | g_assert_cmpint (res, ==, 0); |
310 | return; |
311 | } |
312 | g_test_trap_subprocess (NULL, usec_timeout: 0, test_flags: 0); |
313 | g_test_trap_assert_passed (); |
314 | g_test_trap_assert_stderr ("*Supported debug values: key1 key2 key3 all help*" ); |
315 | } |
316 | |
317 | static void |
318 | test_codeset (void) |
319 | { |
320 | gchar *c; |
321 | const gchar *c2; |
322 | |
323 | c = g_get_codeset (); |
324 | g_get_charset (charset: &c2); |
325 | |
326 | g_assert_cmpstr (c, ==, c2); |
327 | |
328 | g_free (mem: c); |
329 | } |
330 | |
331 | static void |
332 | test_codeset2 (void) |
333 | { |
334 | if (g_test_subprocess ()) |
335 | { |
336 | const gchar *c; |
337 | g_setenv (variable: "CHARSET" , value: "UTF-8" , TRUE); |
338 | g_get_charset (charset: &c); |
339 | g_assert_cmpstr (c, ==, "UTF-8" ); |
340 | return; |
341 | } |
342 | g_test_trap_subprocess (NULL, usec_timeout: 0, test_flags: 0); |
343 | g_test_trap_assert_passed (); |
344 | } |
345 | |
346 | static void |
347 | test_console_charset (void) |
348 | { |
349 | const gchar *c1; |
350 | const gchar *c2; |
351 | |
352 | #ifdef G_OS_WIN32 |
353 | /* store current environment and unset $LANG to make sure it does not interfere */ |
354 | const unsigned int initial_cp = GetConsoleOutputCP (); |
355 | gchar *initial_lang = g_strdup (g_getenv ("LANG" )); |
356 | g_unsetenv ("LANG" ); |
357 | |
358 | /* set console output codepage to something specific (ISO-8859-1 aka CP28591) and query it */ |
359 | SetConsoleOutputCP (28591); |
360 | g_get_console_charset (&c1); |
361 | g_assert_cmpstr (c1, ==, "ISO-8859-1" ); |
362 | |
363 | /* set $LANG to something specific (should override the console output codepage) and query it */ |
364 | g_setenv ("LANG" , "de_DE.ISO-8859-15@euro" , TRUE); |
365 | g_get_console_charset (&c2); |
366 | g_assert_cmpstr (c2, ==, "ISO-8859-15" ); |
367 | |
368 | /* reset environment */ |
369 | if (initial_cp) |
370 | SetConsoleOutputCP (initial_cp); |
371 | if (initial_lang) |
372 | g_setenv ("LANG" , initial_lang, TRUE); |
373 | g_free (initial_lang); |
374 | #else |
375 | g_get_charset (charset: &c1); |
376 | g_get_console_charset (charset: &c2); |
377 | |
378 | g_assert_cmpstr (c1, ==, c2); |
379 | #endif |
380 | } |
381 | |
382 | static void |
383 | test_basename (void) |
384 | { |
385 | const gchar *path = "/path/to/a/file/deep/down.sh" ; |
386 | const gchar *b; |
387 | |
388 | b = g_basename (file_name: path); |
389 | |
390 | g_assert_cmpstr (b, ==, "down.sh" ); |
391 | } |
392 | |
393 | extern const gchar *glib_pgettext (const gchar *msgidctxt, gsize msgidoffset); |
394 | |
395 | static void |
396 | test_gettext (void) |
397 | { |
398 | const gchar *am0, *am1, *am2, *am3; |
399 | |
400 | am0 = glib_pgettext (msgidctxt: "GDateTime\004AM" , msgidoffset: strlen (s: "GDateTime" ) + 1); |
401 | am1 = g_dpgettext (domain: "glib20" , msgctxtid: "GDateTime\004AM" , msgidoffset: strlen (s: "GDateTime" ) + 1); |
402 | am2 = g_dpgettext (domain: "glib20" , msgctxtid: "GDateTime|AM" , msgidoffset: 0); |
403 | am3 = g_dpgettext2 (domain: "glib20" , context: "GDateTime" , msgid: "AM" ); |
404 | |
405 | g_assert_cmpstr (am0, ==, am1); |
406 | g_assert_cmpstr (am1, ==, am2); |
407 | g_assert_cmpstr (am2, ==, am3); |
408 | } |
409 | |
410 | static void |
411 | test_username (void) |
412 | { |
413 | const gchar *name; |
414 | |
415 | name = g_get_user_name (); |
416 | |
417 | g_assert (name != NULL); |
418 | } |
419 | |
420 | static void |
421 | test_realname (void) |
422 | { |
423 | const gchar *name; |
424 | |
425 | name = g_get_real_name (); |
426 | |
427 | g_assert (name != NULL); |
428 | } |
429 | |
430 | static void |
431 | test_hostname (void) |
432 | { |
433 | const gchar *name; |
434 | |
435 | name = g_get_host_name (); |
436 | |
437 | g_assert (name != NULL); |
438 | g_assert_true (g_utf8_validate (name, -1, NULL)); |
439 | } |
440 | |
441 | #ifdef G_OS_UNIX |
442 | static void |
443 | test_xdg_dirs (void) |
444 | { |
445 | gchar *xdg; |
446 | const gchar *dir; |
447 | const gchar * const *dirs; |
448 | gchar *s; |
449 | |
450 | xdg = g_strdup (str: g_getenv (variable: "XDG_CONFIG_HOME" )); |
451 | if (!xdg) |
452 | xdg = g_build_filename (first_element: g_get_home_dir (), ".config" , NULL); |
453 | |
454 | dir = g_get_user_config_dir (); |
455 | |
456 | g_assert_cmpstr (dir, ==, xdg); |
457 | g_free (mem: xdg); |
458 | |
459 | xdg = g_strdup (str: g_getenv (variable: "XDG_DATA_HOME" )); |
460 | if (!xdg) |
461 | xdg = g_build_filename (first_element: g_get_home_dir (), ".local" , "share" , NULL); |
462 | |
463 | dir = g_get_user_data_dir (); |
464 | |
465 | g_assert_cmpstr (dir, ==, xdg); |
466 | g_free (mem: xdg); |
467 | |
468 | xdg = g_strdup (str: g_getenv (variable: "XDG_CACHE_HOME" )); |
469 | if (!xdg) |
470 | xdg = g_build_filename (first_element: g_get_home_dir (), ".cache" , NULL); |
471 | |
472 | dir = g_get_user_cache_dir (); |
473 | |
474 | g_assert_cmpstr (dir, ==, xdg); |
475 | g_free (mem: xdg); |
476 | |
477 | xdg = g_strdup (str: g_getenv (variable: "XDG_RUNTIME_DIR" )); |
478 | if (!xdg) |
479 | xdg = g_strdup (str: g_get_user_cache_dir ()); |
480 | |
481 | dir = g_get_user_runtime_dir (); |
482 | |
483 | g_assert_cmpstr (dir, ==, xdg); |
484 | g_free (mem: xdg); |
485 | |
486 | xdg = (gchar *)g_getenv (variable: "XDG_CONFIG_DIRS" ); |
487 | if (!xdg) |
488 | xdg = "/etc/xdg" ; |
489 | |
490 | dirs = g_get_system_config_dirs (); |
491 | |
492 | s = g_strjoinv (separator: ":" , str_array: (gchar **)dirs); |
493 | |
494 | g_assert_cmpstr (s, ==, xdg); |
495 | |
496 | g_free (mem: s); |
497 | } |
498 | #endif |
499 | |
500 | static void |
501 | test_special_dir (void) |
502 | { |
503 | const gchar *dir, *dir2; |
504 | |
505 | dir = g_get_user_special_dir (directory: G_USER_DIRECTORY_DESKTOP); |
506 | g_reload_user_special_dirs_cache (); |
507 | dir2 = g_get_user_special_dir (directory: G_USER_DIRECTORY_DESKTOP); |
508 | |
509 | g_assert_cmpstr (dir, ==, dir2); |
510 | } |
511 | |
512 | static void |
513 | test_desktop_special_dir (void) |
514 | { |
515 | const gchar *dir, *dir2; |
516 | |
517 | dir = g_get_user_special_dir (directory: G_USER_DIRECTORY_DESKTOP); |
518 | g_assert (dir != NULL); |
519 | |
520 | g_reload_user_special_dirs_cache (); |
521 | dir2 = g_get_user_special_dir (directory: G_USER_DIRECTORY_DESKTOP); |
522 | g_assert (dir2 != NULL); |
523 | } |
524 | |
525 | static void |
526 | test_os_info (void) |
527 | { |
528 | gchar *name; |
529 | gchar *contents = NULL; |
530 | #ifdef G_OS_UNIX |
531 | struct utsname info; |
532 | #endif |
533 | |
534 | /* Whether this is implemented or not, it must not crash */ |
535 | name = g_get_os_info (G_OS_INFO_KEY_NAME); |
536 | g_test_message (format: "%s: %s" , |
537 | G_OS_INFO_KEY_NAME, |
538 | name == NULL ? "(null)" : name); |
539 | |
540 | #if defined (G_OS_WIN32) || defined (__APPLE__) |
541 | /* These OSs have a special case so NAME should always succeed */ |
542 | g_assert_nonnull (name); |
543 | #elif defined (G_OS_UNIX) |
544 | if (g_file_get_contents (filename: "/etc/os-release" , contents: &contents, NULL, NULL) || |
545 | g_file_get_contents (filename: "/usr/lib/os-release" , contents: &contents, NULL, NULL) || |
546 | uname (name: &info) == 0) |
547 | g_assert_nonnull (name); |
548 | else |
549 | g_test_skip (msg: "os-release(5) API not implemented on this platform" ); |
550 | #else |
551 | g_test_skip ("g_get_os_info() not supported on this platform" ); |
552 | #endif |
553 | |
554 | g_free (mem: name); |
555 | g_free (mem: contents); |
556 | } |
557 | |
558 | static gboolean |
559 | source_test (gpointer data) |
560 | { |
561 | g_assert_not_reached (); |
562 | return G_SOURCE_REMOVE; |
563 | } |
564 | |
565 | static void |
566 | test_clear_source (void) |
567 | { |
568 | guint id; |
569 | |
570 | id = g_idle_add (function: source_test, NULL); |
571 | g_assert_cmpuint (id, >, 0); |
572 | |
573 | g_clear_handle_id (&id, g_source_remove); |
574 | g_assert_cmpuint (id, ==, 0); |
575 | |
576 | id = g_timeout_add (interval: 100, function: source_test, NULL); |
577 | g_assert_cmpuint (id, >, 0); |
578 | |
579 | g_clear_handle_id (&id, g_source_remove); |
580 | g_assert_cmpuint (id, ==, 0); |
581 | } |
582 | |
583 | static void |
584 | test_clear_pointer (void) |
585 | { |
586 | gpointer a; |
587 | |
588 | a = g_malloc (n_bytes: 5); |
589 | g_clear_pointer (&a, g_free); |
590 | g_assert (a == NULL); |
591 | |
592 | a = g_malloc (n_bytes: 5); |
593 | (g_clear_pointer) (pp: &a, destroy: g_free); |
594 | g_assert (a == NULL); |
595 | } |
596 | |
597 | /* Test that g_clear_pointer() works with a GDestroyNotify which contains a cast. |
598 | * See https://gitlab.gnome.org/GNOME/glib/issues/1425 */ |
599 | static void |
600 | test_clear_pointer_cast (void) |
601 | { |
602 | GHashTable *hash_table = NULL; |
603 | |
604 | hash_table = g_hash_table_new (hash_func: g_str_hash, key_equal_func: g_str_equal); |
605 | |
606 | g_assert_nonnull (hash_table); |
607 | |
608 | g_clear_pointer (&hash_table, (void (*) (GHashTable *)) g_hash_table_destroy); |
609 | |
610 | g_assert_null (hash_table); |
611 | } |
612 | |
613 | /* Test that the macro version of g_clear_pointer() only evaluates its argument |
614 | * once, just like the function version would. */ |
615 | static void |
616 | test_clear_pointer_side_effects (void) |
617 | { |
618 | gchar **my_string_array, **i; |
619 | |
620 | my_string_array = g_new0 (gchar*, 3); |
621 | my_string_array[0] = g_strdup (str: "hello" ); |
622 | my_string_array[1] = g_strdup (str: "there" ); |
623 | my_string_array[2] = NULL; |
624 | |
625 | i = my_string_array; |
626 | |
627 | g_clear_pointer (i++, g_free); |
628 | |
629 | g_assert_true (i == &my_string_array[1]); |
630 | g_assert_null (my_string_array[0]); |
631 | g_assert_nonnull (my_string_array[1]); |
632 | g_assert_null (my_string_array[2]); |
633 | |
634 | g_free (mem: my_string_array[1]); |
635 | g_free (mem: my_string_array[2]); |
636 | g_free (mem: my_string_array); |
637 | } |
638 | |
639 | static int obj_count; |
640 | |
641 | static void |
642 | get_obj (gpointer *obj_out) |
643 | { |
644 | gpointer obj = g_malloc (n_bytes: 5); |
645 | obj_count++; |
646 | |
647 | if (obj_out) |
648 | *obj_out = g_steal_pointer (&obj); |
649 | |
650 | if (obj) |
651 | { |
652 | g_free (mem: obj); |
653 | obj_count--; |
654 | } |
655 | } |
656 | |
657 | static void |
658 | test_take_pointer (void) |
659 | { |
660 | gpointer a; |
661 | gpointer b; |
662 | |
663 | get_obj (NULL); |
664 | |
665 | get_obj (obj_out: &a); |
666 | g_assert (a); |
667 | |
668 | /* ensure that it works to skip the macro */ |
669 | b = (g_steal_pointer) (pp: &a); |
670 | g_assert (!a); |
671 | obj_count--; |
672 | g_free (mem: b); |
673 | |
674 | g_assert (!obj_count); |
675 | } |
676 | |
677 | static void |
678 | test_misc_mem (void) |
679 | { |
680 | gpointer a; |
681 | |
682 | a = g_try_malloc (n_bytes: 0); |
683 | g_assert (a == NULL); |
684 | |
685 | a = g_try_malloc0 (n_bytes: 0); |
686 | g_assert (a == NULL); |
687 | |
688 | a = g_malloc (n_bytes: 16); |
689 | a = g_try_realloc (mem: a, n_bytes: 20); |
690 | a = g_try_realloc (mem: a, n_bytes: 0); |
691 | |
692 | g_assert (a == NULL); |
693 | } |
694 | |
695 | static void |
696 | test_nullify (void) |
697 | { |
698 | gpointer p = &test_nullify; |
699 | |
700 | g_assert (p != NULL); |
701 | |
702 | g_nullify_pointer (nullify_location: &p); |
703 | |
704 | g_assert (p == NULL); |
705 | } |
706 | |
707 | static void |
708 | atexit_func (void) |
709 | { |
710 | g_print (format: "atexit called" ); |
711 | } |
712 | |
713 | static void |
714 | test_atexit (void) |
715 | { |
716 | if (g_test_subprocess ()) |
717 | { |
718 | g_atexit (func: atexit_func); |
719 | return; |
720 | } |
721 | g_test_trap_subprocess (NULL, usec_timeout: 0, test_flags: 0); |
722 | g_test_trap_assert_passed (); |
723 | g_test_trap_assert_stdout ("*atexit called*" ); |
724 | } |
725 | |
726 | static void |
727 | test_check_setuid (void) |
728 | { |
729 | gboolean res; |
730 | |
731 | res = GLIB_PRIVATE_CALL(g_check_setuid) (); |
732 | g_assert (!res); |
733 | } |
734 | |
735 | /* Test the defined integer limits are correct, as some compilers have had |
736 | * problems with signed/unsigned conversion in the past. These limits should not |
737 | * vary between platforms, compilers or architectures. |
738 | * |
739 | * Use string comparisons to avoid the same systematic problems with unary minus |
740 | * application in C++. See https://gitlab.gnome.org/GNOME/glib/issues/1663. */ |
741 | static void |
742 | test_int_limits (void) |
743 | { |
744 | gchar *str = NULL; |
745 | |
746 | g_test_bug (bug_uri_snippet: "https://gitlab.gnome.org/GNOME/glib/issues/1663" ); |
747 | |
748 | str = g_strdup_printf (format: "%d %d %u\n" |
749 | "%" G_GINT16_FORMAT " %" G_GINT16_FORMAT " %" G_GUINT16_FORMAT "\n" |
750 | "%" G_GINT32_FORMAT " %" G_GINT32_FORMAT " %" G_GUINT32_FORMAT "\n" |
751 | "%" G_GINT64_FORMAT " %" G_GINT64_FORMAT " %" G_GUINT64_FORMAT "\n" , |
752 | G_MININT8, G_MAXINT8, G_MAXUINT8, |
753 | G_MININT16, G_MAXINT16, G_MAXUINT16, |
754 | G_MININT32, G_MAXINT32, G_MAXUINT32, |
755 | G_MININT64, G_MAXINT64, G_MAXUINT64); |
756 | |
757 | g_assert_cmpstr (str, ==, |
758 | "-128 127 255\n" |
759 | "-32768 32767 65535\n" |
760 | "-2147483648 2147483647 4294967295\n" |
761 | "-9223372036854775808 9223372036854775807 18446744073709551615\n" ); |
762 | g_free (mem: str); |
763 | } |
764 | |
765 | static void |
766 | test_clear_list (void) |
767 | { |
768 | GList *list = NULL; |
769 | |
770 | g_clear_list (&list, NULL); |
771 | g_assert_null (list); |
772 | |
773 | list = g_list_prepend (list, data: "test" ); |
774 | g_assert_nonnull (list); |
775 | |
776 | g_clear_list (&list, NULL); |
777 | g_assert_null (list); |
778 | |
779 | g_clear_list (&list, g_free); |
780 | g_assert_null (list); |
781 | |
782 | list = g_list_prepend (list, data: g_malloc (n_bytes: 16)); |
783 | g_assert_nonnull (list); |
784 | |
785 | g_clear_list (&list, g_free); |
786 | g_assert_null (list); |
787 | } |
788 | |
789 | static void |
790 | test_clear_slist (void) |
791 | { |
792 | GSList *slist = NULL; |
793 | |
794 | g_clear_slist (&slist, NULL); |
795 | g_assert_null (slist); |
796 | |
797 | slist = g_slist_prepend (list: slist, data: "test" ); |
798 | g_assert_nonnull (slist); |
799 | |
800 | g_clear_slist (&slist, NULL); |
801 | g_assert_null (slist); |
802 | |
803 | g_clear_slist (&slist, g_free); |
804 | g_assert_null (slist); |
805 | |
806 | slist = g_slist_prepend (list: slist, data: g_malloc (n_bytes: 16)); |
807 | g_assert_nonnull (slist); |
808 | |
809 | g_clear_slist (&slist, g_free); |
810 | g_assert_null (slist); |
811 | } |
812 | |
813 | int |
814 | main (int argc, |
815 | char *argv[]) |
816 | { |
817 | argv0 = argv[0]; |
818 | |
819 | /* for tmpdir test, need to do this early before g_get_any_init */ |
820 | g_setenv (variable: "TMPDIR" , value: "" , TRUE); |
821 | g_unsetenv (variable: "TMP" ); |
822 | g_unsetenv (variable: "TEMP" ); |
823 | |
824 | /* g_test_init() only calls g_set_prgname() if g_get_prgname() |
825 | * returns %NULL, but g_get_prgname() on Windows never returns NULL. |
826 | * So we need to do this by hand to make test_appname() work on |
827 | * Windows. |
828 | */ |
829 | g_set_prgname (prgname: argv[0]); |
830 | |
831 | g_test_init (argc: &argc, argv: &argv, NULL); |
832 | g_test_bug_base (uri_pattern: "http://bugzilla.gnome.org/" ); |
833 | |
834 | g_test_add_func (testpath: "/utils/language-names" , test_func: test_language_names); |
835 | g_test_add_func (testpath: "/utils/locale-variants" , test_func: test_locale_variants); |
836 | g_test_add_func (testpath: "/utils/version" , test_func: test_version); |
837 | g_test_add_func (testpath: "/utils/appname" , test_func: test_appname); |
838 | g_test_add_func (testpath: "/utils/tmpdir" , test_func: test_tmpdir); |
839 | g_test_add_func (testpath: "/utils/bits" , test_func: test_bits); |
840 | g_test_add_func (testpath: "/utils/swap" , test_func: test_swap); |
841 | g_test_add_func (testpath: "/utils/find-program" , test_func: test_find_program); |
842 | g_test_add_func (testpath: "/utils/debug" , test_func: test_debug); |
843 | g_test_add_func (testpath: "/utils/codeset" , test_func: test_codeset); |
844 | g_test_add_func (testpath: "/utils/codeset2" , test_func: test_codeset2); |
845 | g_test_add_func (testpath: "/utils/console-charset" , test_func: test_console_charset); |
846 | g_test_add_func (testpath: "/utils/basename" , test_func: test_basename); |
847 | g_test_add_func (testpath: "/utils/gettext" , test_func: test_gettext); |
848 | g_test_add_func (testpath: "/utils/username" , test_func: test_username); |
849 | g_test_add_func (testpath: "/utils/realname" , test_func: test_realname); |
850 | g_test_add_func (testpath: "/utils/hostname" , test_func: test_hostname); |
851 | #ifdef G_OS_UNIX |
852 | g_test_add_func (testpath: "/utils/xdgdirs" , test_func: test_xdg_dirs); |
853 | #endif |
854 | g_test_add_func (testpath: "/utils/specialdir" , test_func: test_special_dir); |
855 | g_test_add_func (testpath: "/utils/specialdir/desktop" , test_func: test_desktop_special_dir); |
856 | g_test_add_func (testpath: "/utils/os-info" , test_func: test_os_info); |
857 | g_test_add_func (testpath: "/utils/clear-pointer" , test_func: test_clear_pointer); |
858 | g_test_add_func (testpath: "/utils/clear-pointer-cast" , test_func: test_clear_pointer_cast); |
859 | g_test_add_func (testpath: "/utils/clear-pointer/side-effects" , test_func: test_clear_pointer_side_effects); |
860 | g_test_add_func (testpath: "/utils/take-pointer" , test_func: test_take_pointer); |
861 | g_test_add_func (testpath: "/utils/clear-source" , test_func: test_clear_source); |
862 | g_test_add_func (testpath: "/utils/misc-mem" , test_func: test_misc_mem); |
863 | g_test_add_func (testpath: "/utils/nullify" , test_func: test_nullify); |
864 | g_test_add_func (testpath: "/utils/atexit" , test_func: test_atexit); |
865 | g_test_add_func (testpath: "/utils/check-setuid" , test_func: test_check_setuid); |
866 | g_test_add_func (testpath: "/utils/int-limits" , test_func: test_int_limits); |
867 | g_test_add_func (testpath: "/utils/clear-list" , test_func: test_clear_list); |
868 | g_test_add_func (testpath: "/utils/clear-slist" , test_func: test_clear_slist); |
869 | |
870 | return g_test_run (); |
871 | } |
872 | |