Line data Source code
1 : /* Test of gl_locale_name function and its variants. 2 : Copyright (C) 2007-2020 Free Software Foundation, Inc. 3 : 4 : This program is free software: you can redistribute it and/or modify 5 : it under the terms of the GNU General Public License as published by 6 : the Free Software Foundation; either version 3 of the License, or 7 : (at your option) any later version. 8 : 9 : This program 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 12 : GNU General Public License for more details. 13 : 14 : You should have received a copy of the GNU General Public License 15 : along with this program. If not, see <https://www.gnu.org/licenses/>. */ 16 : 17 : /* Written by Bruno Haible <bruno@clisp.org>, 2007. */ 18 : 19 : #include <config.h> 20 : 21 : #include "localename.h" 22 : 23 : #include <locale.h> 24 : #include <stdlib.h> 25 : #include <string.h> 26 : 27 : #include "macros.h" 28 : 29 : #if HAVE_WORKING_NEWLOCALE && HAVE_WORKING_USELOCALE && !HAVE_FAKE_LOCALES 30 : # define HAVE_GOOD_USELOCALE 1 31 : #endif 32 : 33 : 34 : #if HAVE_GOOD_USELOCALE 35 : 36 : static struct { int cat; int mask; const char *string; } const categories[] = 37 : { 38 : { LC_CTYPE, LC_CTYPE_MASK, "LC_CTYPE" }, 39 : { LC_NUMERIC, LC_NUMERIC_MASK, "LC_NUMERIC" }, 40 : { LC_TIME, LC_TIME_MASK, "LC_TIME" }, 41 : { LC_COLLATE, LC_COLLATE_MASK, "LC_COLLATE" }, 42 : { LC_MONETARY, LC_MONETARY_MASK, "LC_MONETARY" }, 43 : { LC_MESSAGES, LC_MESSAGES_MASK, "LC_MESSAGES" } 44 : # ifdef LC_PAPER 45 : , { LC_PAPER, LC_PAPER_MASK, "LC_PAPER" } 46 : # endif 47 : # ifdef LC_NAME 48 : , { LC_NAME, LC_NAME_MASK, "LC_NAME" } 49 : # endif 50 : # ifdef LC_ADDRESS 51 : , { LC_ADDRESS, LC_ADDRESS_MASK, "LC_ADDRESS" } 52 : # endif 53 : # ifdef LC_TELEPHONE 54 : , { LC_TELEPHONE, LC_TELEPHONE_MASK, "LC_TELEPHONE" } 55 : # endif 56 : # ifdef LC_MEASUREMENT 57 : , { LC_MEASUREMENT, LC_MEASUREMENT_MASK, "LC_MEASUREMENT" } 58 : # endif 59 : # ifdef LC_IDENTIFICATION 60 : , { LC_IDENTIFICATION, LC_IDENTIFICATION_MASK, "LC_IDENTIFICATION" } 61 : # endif 62 : }; 63 : 64 : #endif 65 : 66 : /* Test the gl_locale_name() function. */ 67 : static void 68 1 : test_locale_name (void) 69 : { 70 : const char *ret; 71 : const char *name; 72 : 73 : /* Check that gl_locale_name returns non-NULL. */ 74 1 : ASSERT (gl_locale_name (LC_MESSAGES, "LC_MESSAGES") != NULL); 75 : 76 : /* Get into a defined state, */ 77 1 : setlocale (LC_ALL, "en_US.UTF-8"); 78 : #if HAVE_GOOD_USELOCALE 79 1 : uselocale (LC_GLOBAL_LOCALE); 80 : #endif 81 : 82 : /* Check that when all environment variables are unset, 83 : gl_locale_name returns the default locale. */ 84 1 : unsetenv ("LC_ALL"); 85 1 : unsetenv ("LC_CTYPE"); 86 1 : unsetenv ("LC_MESSAGES"); 87 1 : unsetenv ("LC_NUMERIC"); 88 1 : unsetenv ("LANG"); 89 : /* Need also to unset all environment variables that specify standard or 90 : non-standard locale categories. Otherwise, on glibc systems, when some 91 : of these variables are set and reference a nonexistent locale, the 92 : setlocale (LC_ALL, "") call below would fail. */ 93 1 : unsetenv ("LC_COLLATE"); 94 1 : unsetenv ("LC_MONETARY"); 95 1 : unsetenv ("LC_TIME"); 96 1 : unsetenv ("LC_ADDRESS"); 97 1 : unsetenv ("LC_IDENTIFICATION"); 98 1 : unsetenv ("LC_MEASUREMENT"); 99 1 : unsetenv ("LC_NAME"); 100 1 : unsetenv ("LC_PAPER"); 101 1 : unsetenv ("LC_TELEPHONE"); 102 1 : ret = setlocale (LC_ALL, ""); 103 1 : ASSERT (ret != NULL); 104 1 : ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"), 105 : gl_locale_name_default ()) == 0); 106 1 : ASSERT (strcmp (gl_locale_name (LC_NUMERIC, "LC_NUMERIC"), 107 : gl_locale_name_default ()) == 0); 108 : 109 : /* Check that an empty environment variable is treated like an unset 110 : environment variable. */ 111 : 112 1 : setenv ("LC_ALL", "", 1); 113 1 : unsetenv ("LC_CTYPE"); 114 1 : unsetenv ("LC_MESSAGES"); 115 1 : unsetenv ("LANG"); 116 1 : setlocale (LC_ALL, ""); 117 1 : ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"), 118 : gl_locale_name_default ()) == 0); 119 : 120 1 : unsetenv ("LC_ALL"); 121 1 : setenv ("LC_CTYPE", "", 1); 122 1 : unsetenv ("LC_MESSAGES"); 123 1 : unsetenv ("LANG"); 124 1 : setlocale (LC_ALL, ""); 125 1 : ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"), 126 : gl_locale_name_default ()) == 0); 127 : 128 1 : unsetenv ("LC_ALL"); 129 1 : unsetenv ("LC_CTYPE"); 130 1 : setenv ("LC_MESSAGES", "", 1); 131 1 : unsetenv ("LANG"); 132 1 : setlocale (LC_ALL, ""); 133 1 : ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"), 134 : gl_locale_name_default ()) == 0); 135 : 136 1 : unsetenv ("LC_ALL"); 137 1 : unsetenv ("LC_CTYPE"); 138 1 : unsetenv ("LC_MESSAGES"); 139 1 : setenv ("LANG", "", 1); 140 1 : setlocale (LC_ALL, ""); 141 1 : ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"), 142 : gl_locale_name_default ()) == 0); 143 : 144 : /* Check that LC_ALL overrides the others, and LANG is overridden by the 145 : others. */ 146 : 147 1 : setenv ("LC_ALL", "C", 1); 148 1 : unsetenv ("LC_CTYPE"); 149 1 : unsetenv ("LC_MESSAGES"); 150 1 : unsetenv ("LANG"); 151 1 : setlocale (LC_ALL, ""); 152 1 : ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"), "C") == 0); 153 : 154 1 : unsetenv ("LC_ALL"); 155 1 : setenv ("LC_CTYPE", "C", 1); 156 1 : setenv ("LC_MESSAGES", "C", 1); 157 1 : unsetenv ("LANG"); 158 1 : setlocale (LC_ALL, ""); 159 1 : ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"), "C") == 0); 160 : 161 1 : unsetenv ("LC_ALL"); 162 1 : unsetenv ("LC_CTYPE"); 163 1 : unsetenv ("LC_MESSAGES"); 164 1 : setenv ("LANG", "C", 1); 165 1 : setlocale (LC_ALL, ""); 166 1 : ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"), "C") == 0); 167 : 168 : /* Check mixed situations. */ 169 : 170 1 : unsetenv ("LC_ALL"); 171 1 : unsetenv ("LC_CTYPE"); 172 1 : setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1); 173 1 : setenv ("LANG", "de_DE.UTF-8", 1); 174 1 : if (setlocale (LC_ALL, "") != NULL) 175 : { 176 0 : name = gl_locale_name (LC_CTYPE, "LC_CTYPE"); 177 : #if defined _WIN32 && !defined __CYGWIN__ 178 : /* On native Windows, here, 179 : gl_locale_name_thread (LC_CTYPE, "LC_CTYPE") 180 : returns NULL and 181 : gl_locale_name_posix (LC_CTYPE, "LC_CTYPE") 182 : returns either "de_DE" or "de_DE.UTF-8". */ 183 : ASSERT (strcmp (name, "de_DE") == 0 || strcmp (name, "de_DE.UTF-8") == 0); 184 : #else 185 0 : ASSERT (strcmp (name, "de_DE.UTF-8") == 0); 186 : #endif 187 0 : name = gl_locale_name (LC_MESSAGES, "LC_MESSAGES"); 188 0 : ASSERT (strcmp (name, "fr_FR.UTF-8") == 0); 189 : } 190 : 191 1 : unsetenv ("LC_ALL"); 192 1 : unsetenv ("LC_CTYPE"); 193 1 : setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1); 194 1 : unsetenv ("LANG"); 195 1 : if (setlocale (LC_ALL, "") != NULL) 196 : { 197 0 : name = gl_locale_name (LC_CTYPE, "LC_CTYPE"); 198 0 : ASSERT (strcmp (name, gl_locale_name_default ()) == 0); 199 0 : name = gl_locale_name (LC_MESSAGES, "LC_MESSAGES"); 200 0 : ASSERT (strcmp (name, "fr_FR.UTF-8") == 0); 201 : } 202 : 203 : #if HAVE_GOOD_USELOCALE 204 : /* Check that gl_locale_name considers the thread locale. */ 205 : { 206 1 : locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL); 207 1 : if (locale != NULL) 208 : { 209 0 : uselocale (locale); 210 0 : name = gl_locale_name (LC_CTYPE, "LC_CTYPE"); 211 0 : ASSERT (strcmp (name, "fr_FR.UTF-8") == 0); 212 0 : name = gl_locale_name (LC_MESSAGES, "LC_MESSAGES"); 213 0 : ASSERT (strcmp (name, "fr_FR.UTF-8") == 0); 214 0 : uselocale (LC_GLOBAL_LOCALE); 215 0 : freelocale (locale); 216 : } 217 : } 218 : 219 : /* Check that gl_locale_name distinguishes different categories of the 220 : thread locale, and that the name is the right one for each. */ 221 : { 222 : unsigned int i; 223 : 224 13 : for (i = 0; i < SIZEOF (categories); i++) 225 : { 226 12 : int category_mask = categories[i].mask; 227 12 : locale_t loc = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL); 228 12 : if (loc != NULL) 229 : { 230 0 : locale_t locale = newlocale (category_mask, "de_DE.UTF-8", loc); 231 0 : if (locale == NULL) 232 0 : freelocale (loc); 233 : else 234 : { 235 : unsigned int j; 236 : 237 0 : uselocale (locale); 238 0 : for (j = 0; j < SIZEOF (categories); j++) 239 : { 240 : const char *name_j = 241 0 : gl_locale_name (categories[j].cat, categories[j].string); 242 0 : if (j == i) 243 0 : ASSERT (strcmp (name_j, "de_DE.UTF-8") == 0); 244 : else 245 0 : ASSERT (strcmp (name_j, "fr_FR.UTF-8") == 0); 246 : } 247 0 : uselocale (LC_GLOBAL_LOCALE); 248 0 : freelocale (locale); 249 : } 250 : } 251 : } 252 : } 253 : #endif 254 1 : } 255 : 256 : /* Test the gl_locale_name_thread() function. */ 257 : static void 258 1 : test_locale_name_thread (void) 259 : { 260 : /* Get into a defined state, */ 261 1 : setlocale (LC_ALL, "en_US.UTF-8"); 262 : 263 : #if HAVE_GOOD_USELOCALE 264 : /* Check that gl_locale_name_thread returns NULL when no thread locale is 265 : set. */ 266 1 : uselocale (LC_GLOBAL_LOCALE); 267 1 : ASSERT (gl_locale_name_thread (LC_CTYPE, "LC_CTYPE") == NULL); 268 1 : ASSERT (gl_locale_name_thread (LC_MESSAGES, "LC_MESSAGES") == NULL); 269 : 270 : /* Check that gl_locale_name_thread considers the thread locale. */ 271 : { 272 1 : locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL); 273 1 : if (locale != NULL) 274 : { 275 : const char *name; 276 : 277 0 : uselocale (locale); 278 0 : name = gl_locale_name_thread (LC_CTYPE, "LC_CTYPE"); 279 0 : ASSERT (strcmp (name, "fr_FR.UTF-8") == 0); 280 0 : name = gl_locale_name_thread (LC_MESSAGES, "LC_MESSAGES"); 281 0 : ASSERT (strcmp (name, "fr_FR.UTF-8") == 0); 282 0 : uselocale (LC_GLOBAL_LOCALE); 283 0 : freelocale (locale); 284 : } 285 : } 286 : 287 : /* Check that gl_locale_name_thread distinguishes different categories of the 288 : thread locale, and that the name is the right one for each. */ 289 : { 290 : unsigned int i; 291 : 292 13 : for (i = 0; i < SIZEOF (categories); i++) 293 : { 294 12 : int category_mask = categories[i].mask; 295 12 : locale_t loc = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL); 296 12 : if (loc != NULL) 297 : { 298 0 : locale_t locale = newlocale (category_mask, "de_DE.UTF-8", loc); 299 0 : if (locale == NULL) 300 0 : freelocale (loc); 301 : else 302 : { 303 : unsigned int j; 304 : 305 0 : uselocale (locale); 306 0 : for (j = 0; j < SIZEOF (categories); j++) 307 : { 308 : const char *name_j = 309 0 : gl_locale_name_thread (categories[j].cat, 310 : categories[j].string); 311 0 : if (j == i) 312 0 : ASSERT (strcmp (name_j, "de_DE.UTF-8") == 0); 313 : else 314 0 : ASSERT (strcmp (name_j, "fr_FR.UTF-8") == 0); 315 : } 316 0 : uselocale (LC_GLOBAL_LOCALE); 317 0 : freelocale (locale); 318 : } 319 : } 320 : } 321 : } 322 : 323 : /* Check that gl_locale_name_thread returns a string that is allocated with 324 : indefinite extent. */ 325 : { 326 : /* Try many locale names in turn, in order to defeat possible caches. */ 327 : static const char * const choices[] = 328 : { 329 : "C", 330 : "POSIX", 331 : "af_ZA", 332 : "af_ZA.UTF-8", 333 : "am_ET", 334 : "am_ET.UTF-8", 335 : "be_BY", 336 : "be_BY.UTF-8", 337 : "bg_BG", 338 : "bg_BG.UTF-8", 339 : "ca_ES", 340 : "ca_ES.UTF-8", 341 : "cs_CZ", 342 : "cs_CZ.UTF-8", 343 : "da_DK", 344 : "da_DK.UTF-8", 345 : "de_AT", 346 : "de_AT.UTF-8", 347 : "de_CH", 348 : "de_CH.UTF-8", 349 : "de_DE", 350 : "de_DE.UTF-8", 351 : "el_GR", 352 : "el_GR.UTF-8", 353 : "en_AU", 354 : "en_AU.UTF-8", 355 : "en_CA", 356 : "en_CA.UTF-8", 357 : "en_GB", 358 : "en_GB.UTF-8", 359 : "en_IE", 360 : "en_IE.UTF-8", 361 : "en_NZ", 362 : "en_NZ.UTF-8", 363 : "en_US", 364 : "en_US.UTF-8", 365 : "es_ES", 366 : "es_ES.UTF-8", 367 : "et_EE", 368 : "et_EE.UTF-8", 369 : "eu_ES", 370 : "eu_ES.UTF-8", 371 : "fi_FI", 372 : "fi_FI.UTF-8", 373 : "fr_BE", 374 : "fr_BE.UTF-8", 375 : "fr_CA", 376 : "fr_CA.UTF-8", 377 : "fr_CH", 378 : "fr_CH.UTF-8", 379 : "fr_FR", 380 : "fr_FR.UTF-8", 381 : "he_IL", 382 : "he_IL.UTF-8", 383 : "hr_HR", 384 : "hr_HR.UTF-8", 385 : "hu_HU", 386 : "hu_HU.UTF-8", 387 : "hy_AM", 388 : "is_IS", 389 : "is_IS.UTF-8", 390 : "it_CH", 391 : "it_CH.UTF-8", 392 : "it_IT", 393 : "it_IT.UTF-8", 394 : "ja_JP.UTF-8", 395 : "kk_KZ", 396 : "kk_KZ.UTF-8", 397 : "ko_KR.UTF-8", 398 : "lt_LT", 399 : "lt_LT.UTF-8", 400 : "nl_BE", 401 : "nl_BE.UTF-8", 402 : "nl_NL", 403 : "nl_NL.UTF-8", 404 : "no_NO", 405 : "no_NO.UTF-8", 406 : "pl_PL", 407 : "pl_PL.UTF-8", 408 : "pt_BR", 409 : "pt_BR.UTF-8", 410 : "pt_PT", 411 : "pt_PT.UTF-8", 412 : "ro_RO", 413 : "ro_RO.UTF-8", 414 : "ru_RU", 415 : "ru_RU.UTF-8", 416 : "sk_SK", 417 : "sk_SK.UTF-8", 418 : "sl_SI", 419 : "sl_SI.UTF-8", 420 : "sv_SE", 421 : "sv_SE.UTF-8", 422 : "tr_TR", 423 : "tr_TR.UTF-8", 424 : "uk_UA", 425 : "uk_UA.UTF-8", 426 : "zh_CN", 427 : "zh_CN.UTF-8", 428 : "zh_HK", 429 : "zh_HK.UTF-8", 430 : "zh_TW", 431 : "zh_TW.UTF-8" 432 : }; 433 : /* Remember which locales are available. */ 434 : unsigned char /* bool */ available[SIZEOF (choices)]; 435 : /* Array of remembered results of gl_locale_name_thread. */ 436 : const char *unsaved_names[SIZEOF (choices)][SIZEOF (categories)]; 437 : /* Array of remembered results of gl_locale_name_thread, stored in safe 438 : memory. */ 439 : char *saved_names[SIZEOF (choices)][SIZEOF (categories)]; 440 : unsigned int j; 441 : 442 104 : for (j = 0; j < SIZEOF (choices); j++) 443 : { 444 103 : locale_t locale = newlocale (LC_ALL_MASK, choices[j], NULL); 445 103 : available[j] = (locale != NULL); 446 103 : if (locale != NULL) 447 : { 448 : unsigned int i; 449 : 450 3 : uselocale (locale); 451 39 : for (i = 0; i < SIZEOF (categories); i++) 452 : { 453 36 : unsaved_names[j][i] = gl_locale_name_thread (categories[i].cat, categories[i].string); 454 36 : saved_names[j][i] = strdup (unsaved_names[j][i]); 455 : } 456 3 : uselocale (LC_GLOBAL_LOCALE); 457 3 : freelocale (locale); 458 : } 459 : } 460 : /* Verify the unsaved_names are still valid. */ 461 104 : for (j = 0; j < SIZEOF (choices); j++) 462 103 : if (available[j]) 463 : { 464 : unsigned int i; 465 : 466 39 : for (i = 0; i < SIZEOF (categories); i++) 467 36 : ASSERT (strcmp (unsaved_names[j][i], saved_names[j][i]) == 0); 468 : } 469 : /* Allocate many locales, without freeing them. This is an attempt at 470 : overwriting as much of the previously allocated memory as possible. */ 471 104 : for (j = SIZEOF (choices); j > 0; ) 472 : { 473 103 : j--; 474 103 : if (available[j]) 475 : { 476 3 : locale_t locale = newlocale (LC_ALL_MASK, choices[j], NULL); 477 : unsigned int i; 478 : 479 3 : ASSERT (locale != NULL); 480 3 : uselocale (locale); 481 39 : for (i = 0; i < SIZEOF (categories); i++) 482 : { 483 36 : const char *name = gl_locale_name_thread (categories[i].cat, categories[i].string); 484 36 : ASSERT (strcmp (unsaved_names[j][i], name) == 0); 485 : } 486 3 : uselocale (LC_GLOBAL_LOCALE); 487 3 : freelocale (locale); 488 : } 489 : } 490 : /* Verify the unsaved_names are still valid. */ 491 104 : for (j = 0; j < SIZEOF (choices); j++) 492 103 : if (available[j]) 493 : { 494 : unsigned int i; 495 : 496 39 : for (i = 0; i < SIZEOF (categories); i++) 497 : { 498 36 : ASSERT (strcmp (unsaved_names[j][i], saved_names[j][i]) == 0); 499 36 : free (saved_names[j][i]); 500 : } 501 : } 502 : } 503 : #else 504 : /* Check that gl_locale_name_thread always returns NULL. */ 505 : ASSERT (gl_locale_name_thread (LC_CTYPE, "LC_CTYPE") == NULL); 506 : ASSERT (gl_locale_name_thread (LC_MESSAGES, "LC_MESSAGES") == NULL); 507 : #endif 508 1 : } 509 : 510 : /* Test the gl_locale_name_posix() function. */ 511 : static void 512 1 : test_locale_name_posix (void) 513 : { 514 : const char *ret; 515 : const char *name; 516 : 517 : /* Get into a defined state, */ 518 1 : setlocale (LC_ALL, "en_US.UTF-8"); 519 : #if HAVE_GOOD_USELOCALE 520 1 : uselocale (LC_GLOBAL_LOCALE); 521 : #endif 522 : 523 : /* Check that when all environment variables are unset, 524 : gl_locale_name_posix returns either NULL or the default locale. */ 525 1 : unsetenv ("LC_ALL"); 526 1 : unsetenv ("LC_CTYPE"); 527 1 : unsetenv ("LC_MESSAGES"); 528 1 : unsetenv ("LC_NUMERIC"); 529 1 : unsetenv ("LANG"); 530 : /* Need also to unset all environment variables that specify standard or 531 : non-standard locale categories. Otherwise, on glibc systems, when some 532 : of these variables are set and reference a nonexistent locale, the 533 : setlocale (LC_ALL, "") call below would fail. */ 534 1 : unsetenv ("LC_COLLATE"); 535 1 : unsetenv ("LC_MONETARY"); 536 1 : unsetenv ("LC_TIME"); 537 1 : unsetenv ("LC_ADDRESS"); 538 1 : unsetenv ("LC_IDENTIFICATION"); 539 1 : unsetenv ("LC_MEASUREMENT"); 540 1 : unsetenv ("LC_NAME"); 541 1 : unsetenv ("LC_PAPER"); 542 1 : unsetenv ("LC_TELEPHONE"); 543 1 : ret = setlocale (LC_ALL, ""); 544 1 : ASSERT (ret != NULL); 545 1 : name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES"); 546 1 : ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0); 547 1 : name = gl_locale_name_posix (LC_NUMERIC, "LC_NUMERIC"); 548 1 : ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0); 549 : 550 : /* Check that an empty environment variable is treated like an unset 551 : environment variable. */ 552 : 553 1 : setenv ("LC_ALL", "", 1); 554 1 : unsetenv ("LC_CTYPE"); 555 1 : unsetenv ("LC_MESSAGES"); 556 1 : unsetenv ("LANG"); 557 1 : setlocale (LC_ALL, ""); 558 1 : name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES"); 559 1 : ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0); 560 : 561 1 : unsetenv ("LC_ALL"); 562 1 : setenv ("LC_CTYPE", "", 1); 563 1 : unsetenv ("LC_MESSAGES"); 564 1 : unsetenv ("LANG"); 565 1 : setlocale (LC_ALL, ""); 566 1 : name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES"); 567 1 : ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0); 568 : 569 1 : unsetenv ("LC_ALL"); 570 1 : unsetenv ("LC_CTYPE"); 571 1 : setenv ("LC_MESSAGES", "", 1); 572 1 : unsetenv ("LANG"); 573 1 : setlocale (LC_ALL, ""); 574 1 : name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES"); 575 1 : ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0); 576 : 577 1 : unsetenv ("LC_ALL"); 578 1 : unsetenv ("LC_CTYPE"); 579 1 : unsetenv ("LC_MESSAGES"); 580 1 : setenv ("LANG", "", 1); 581 1 : setlocale (LC_ALL, ""); 582 1 : name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES"); 583 1 : ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0); 584 : 585 : /* Check that LC_ALL overrides the others, and LANG is overridden by the 586 : others. */ 587 : 588 1 : setenv ("LC_ALL", "C", 1); 589 1 : unsetenv ("LC_CTYPE"); 590 1 : unsetenv ("LC_MESSAGES"); 591 1 : unsetenv ("LANG"); 592 1 : setlocale (LC_ALL, ""); 593 1 : name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES"); 594 1 : ASSERT (strcmp (name, "C") == 0); 595 : 596 1 : unsetenv ("LC_ALL"); 597 1 : setenv ("LC_CTYPE", "C", 1); 598 1 : setenv ("LC_MESSAGES", "C", 1); 599 1 : unsetenv ("LANG"); 600 1 : setlocale (LC_ALL, ""); 601 1 : name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES"); 602 1 : ASSERT (strcmp (name, "C") == 0); 603 : 604 1 : unsetenv ("LC_ALL"); 605 1 : unsetenv ("LC_CTYPE"); 606 1 : unsetenv ("LC_MESSAGES"); 607 1 : setenv ("LANG", "C", 1); 608 1 : setlocale (LC_ALL, ""); 609 1 : name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES"); 610 1 : ASSERT (strcmp (name, "C") == 0); 611 : 612 : /* Check mixed situations. */ 613 : 614 1 : unsetenv ("LC_ALL"); 615 1 : unsetenv ("LC_CTYPE"); 616 1 : setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1); 617 1 : setenv ("LANG", "de_DE.UTF-8", 1); 618 1 : if (setlocale (LC_ALL, "") != NULL) 619 : { 620 0 : name = gl_locale_name_posix (LC_CTYPE, "LC_CTYPE"); 621 : #if defined _WIN32 && !defined __CYGWIN__ 622 : ASSERT (strcmp (name, "de_DE") == 0 || strcmp (name, "de_DE.UTF-8") == 0); 623 : #else 624 0 : ASSERT (strcmp (name, "de_DE.UTF-8") == 0); 625 : #endif 626 0 : name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES"); 627 0 : ASSERT (strcmp (name, "fr_FR.UTF-8") == 0); 628 : } 629 : 630 1 : unsetenv ("LC_ALL"); 631 1 : unsetenv ("LC_CTYPE"); 632 1 : setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1); 633 1 : unsetenv ("LANG"); 634 1 : if (setlocale (LC_ALL, "") != NULL) 635 : { 636 0 : name = gl_locale_name_posix (LC_CTYPE, "LC_CTYPE"); 637 0 : ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0); 638 0 : name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES"); 639 0 : ASSERT (strcmp (name, "fr_FR.UTF-8") == 0); 640 : } 641 : 642 : #if HAVE_GOOD_USELOCALE 643 : /* Check that gl_locale_name_posix ignores the thread locale. */ 644 : { 645 1 : locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL); 646 1 : if (locale != NULL) 647 : { 648 0 : unsetenv ("LC_ALL"); 649 0 : unsetenv ("LC_CTYPE"); 650 0 : unsetenv ("LC_MESSAGES"); 651 0 : setenv ("LANG", "C", 1); 652 0 : setlocale (LC_ALL, ""); 653 0 : uselocale (locale); 654 0 : name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES"); 655 0 : ASSERT (strcmp (name, "C") == 0); 656 0 : uselocale (LC_GLOBAL_LOCALE); 657 0 : freelocale (locale); 658 : } 659 : } 660 : #endif 661 1 : } 662 : 663 : /* Test the gl_locale_name_environ() function. */ 664 : static void 665 1 : test_locale_name_environ (void) 666 : { 667 : const char *name; 668 : 669 : /* Get into a defined state, */ 670 1 : setlocale (LC_ALL, "en_US.UTF-8"); 671 : #if HAVE_GOOD_USELOCALE 672 1 : uselocale (LC_GLOBAL_LOCALE); 673 : #endif 674 : 675 : /* Check that when all environment variables are unset, 676 : gl_locale_name_environ returns NULL. */ 677 1 : unsetenv ("LC_ALL"); 678 1 : unsetenv ("LC_CTYPE"); 679 1 : unsetenv ("LC_MESSAGES"); 680 1 : unsetenv ("LC_NUMERIC"); 681 1 : unsetenv ("LANG"); 682 1 : ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL); 683 1 : ASSERT (gl_locale_name_environ (LC_NUMERIC, "LC_NUMERIC") == NULL); 684 : 685 : /* Check that an empty environment variable is treated like an unset 686 : environment variable. */ 687 : 688 1 : setenv ("LC_ALL", "", 1); 689 1 : unsetenv ("LC_CTYPE"); 690 1 : unsetenv ("LC_MESSAGES"); 691 1 : unsetenv ("LANG"); 692 1 : ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL); 693 : 694 1 : unsetenv ("LC_ALL"); 695 1 : setenv ("LC_CTYPE", "", 1); 696 1 : unsetenv ("LC_MESSAGES"); 697 1 : unsetenv ("LANG"); 698 1 : ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL); 699 : 700 1 : unsetenv ("LC_ALL"); 701 1 : unsetenv ("LC_CTYPE"); 702 1 : setenv ("LC_MESSAGES", "", 1); 703 1 : unsetenv ("LANG"); 704 1 : ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL); 705 : 706 1 : unsetenv ("LC_ALL"); 707 1 : unsetenv ("LC_CTYPE"); 708 1 : unsetenv ("LC_MESSAGES"); 709 1 : setenv ("LANG", "", 1); 710 1 : ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL); 711 : 712 : /* Check that LC_ALL overrides the others, and LANG is overridden by the 713 : others. */ 714 : 715 1 : setenv ("LC_ALL", "C", 1); 716 1 : unsetenv ("LC_CTYPE"); 717 1 : unsetenv ("LC_MESSAGES"); 718 1 : unsetenv ("LANG"); 719 1 : name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES"); 720 1 : ASSERT (strcmp (name, "C") == 0); 721 : 722 1 : unsetenv ("LC_ALL"); 723 1 : setenv ("LC_CTYPE", "C", 1); 724 1 : setenv ("LC_MESSAGES", "C", 1); 725 1 : unsetenv ("LANG"); 726 1 : name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES"); 727 1 : ASSERT (strcmp (name, "C") == 0); 728 : 729 1 : unsetenv ("LC_ALL"); 730 1 : unsetenv ("LC_CTYPE"); 731 1 : unsetenv ("LC_MESSAGES"); 732 1 : setenv ("LANG", "C", 1); 733 1 : name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES"); 734 1 : ASSERT (strcmp (name, "C") == 0); 735 : 736 : /* Check mixed situations. */ 737 : 738 1 : unsetenv ("LC_ALL"); 739 1 : unsetenv ("LC_CTYPE"); 740 1 : setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1); 741 1 : setenv ("LANG", "de_DE.UTF-8", 1); 742 1 : name = gl_locale_name_environ (LC_CTYPE, "LC_CTYPE"); 743 1 : ASSERT (strcmp (name, "de_DE.UTF-8") == 0); 744 1 : name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES"); 745 1 : ASSERT (strcmp (name, "fr_FR.UTF-8") == 0); 746 : 747 1 : unsetenv ("LC_ALL"); 748 1 : unsetenv ("LC_CTYPE"); 749 1 : setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1); 750 1 : unsetenv ("LANG"); 751 1 : name = gl_locale_name_environ (LC_CTYPE, "LC_CTYPE"); 752 1 : ASSERT (name == NULL); 753 1 : name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES"); 754 1 : ASSERT (strcmp (name, "fr_FR.UTF-8") == 0); 755 : 756 : #if HAVE_GOOD_USELOCALE 757 : /* Check that gl_locale_name_environ ignores the thread locale. */ 758 : { 759 1 : locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL); 760 1 : if (locale != NULL) 761 : { 762 0 : unsetenv ("LC_ALL"); 763 0 : unsetenv ("LC_CTYPE"); 764 0 : unsetenv ("LC_MESSAGES"); 765 0 : setenv ("LANG", "C", 1); 766 0 : setlocale (LC_ALL, ""); 767 0 : uselocale (locale); 768 0 : name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES"); 769 0 : ASSERT (strcmp (name, "C") == 0); 770 0 : uselocale (LC_GLOBAL_LOCALE); 771 0 : freelocale (locale); 772 : } 773 : } 774 : #endif 775 1 : } 776 : 777 : /* Test the gl_locale_name_default() function. */ 778 : static void 779 1 : test_locale_name_default (void) 780 : { 781 1 : const char *name = gl_locale_name_default (); 782 : 783 1 : ASSERT (name != NULL); 784 : 785 : /* Only Mac OS X and Windows have a facility for the user to set the default 786 : locale. */ 787 : #if !((defined __APPLE__ && defined __MACH__) || (defined _WIN32 || defined __CYGWIN__)) 788 1 : ASSERT (strcmp (name, "C") == 0); 789 : #endif 790 : 791 : #if HAVE_GOOD_USELOCALE 792 : /* Check that gl_locale_name_default ignores the thread locale. */ 793 : { 794 1 : locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL); 795 1 : if (locale != NULL) 796 : { 797 0 : uselocale (locale); 798 0 : ASSERT (strcmp (gl_locale_name_default (), name) == 0); 799 0 : uselocale (LC_GLOBAL_LOCALE); 800 0 : freelocale (locale); 801 : } 802 : } 803 : #endif 804 1 : } 805 : 806 : int 807 1 : main () 808 : { 809 1 : test_locale_name (); 810 1 : test_locale_name_thread (); 811 1 : test_locale_name_posix (); 812 1 : test_locale_name_environ (); 813 1 : test_locale_name_default (); 814 : 815 1 : return 0; 816 : }