/* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright 2014 Garrett D'Amore */ /* * This program tests that newlocale and uselocale work properly in * multi-threaded programs. In order for it to work, it requires that * some additional locales be installed. */ #include #include #include #include #include #include #include #include #include #include #include #include "test_common.h" /* * Note that on some platforms, different symbols are used. For example, * MacOS Mavericks uses "Eu" for Euro symbol, instead of €. If the locale * data changes, then this program will need to update to reflect that. */ struct ldata { const char *locale; const char *day1; const char *cursym; } ldata[] = { { "C", "Sunday", "" }, { "en_US.UTF-8", "Sunday", "$" }, { "de_DE.UTF-8", "Sonntag", "€" }, { "ru_RU.UTF-8", "воскресенье", "₽" }, { "ja_JP.UTF-8", "日曜日", "¥" }, }; #define NUM_LDATA 5 #define NUMTHR 20 #define NUMITR 200 int extra_debug = 0; void testlocale_thr_one(test_t t, void *arg) { _NOTE(ARGUNUSED(arg)); locale_t cloc, loc; struct lconv *lc; char *day; for (int i = 0; i < NUMITR; i++) { struct ldata *l = &ldata[i % NUM_LDATA]; cloc = uselocale(NULL); loc = newlocale(LC_ALL_MASK, l->locale, NULL); if (loc == NULL) { test_failed(t, "newlocale %s failed", l->locale); } day = nl_langinfo_l(DAY_1, loc); if (strcmp(day, l->day1) != 0) { test_failed(t, "newlocale data mismatch (%s != %s)", day, l->day1); } if (extra_debug) test_debugf(t, "DAY1: %s", day); day = nl_langinfo(DAY_1); if (strcmp(day, "Sunday") != 0) { test_failed(t, "C locale day wrong %s != Sunday", day); } lc = localeconv(); if (strcmp(lc->currency_symbol, "") != 0) { test_failed(t, "C cursym mismatch (%s != %s)", lc->currency_symbol, ""); } /* we sleep a random bit to mix it up */ (void) usleep(rand() % 10); (void) uselocale(loc); day = nl_langinfo(DAY_1); if (strcmp(day, l->day1) != 0) { test_failed(t, "uselocale data mismatch (%s != %s)", day, l->day1); } lc = localeconv(); if (strcmp(lc->currency_symbol, l->cursym) != 0) { test_failed(t, "uselocal cursym %s != %s", lc->currency_symbol, l->cursym); } if (extra_debug) test_debugf(t, "CSYM: %s", lc->currency_symbol); /* we sleep a random bit to mix it up */ (void) usleep(rand() % 10); if (uselocale(cloc) != loc) { test_failed(t, "revert old locale mismatch"); } freelocale(loc); if (uselocale(LC_GLOBAL_LOCALE) != cloc) { test_failed(t, "revert GLOBAL_LOCALE mismatch"); } } test_passed(t); } void test_newlocale_threaded(void) { test_run(NUMTHR, testlocale_thr_one, NULL, "newlocale_threaded"); } void test_newlocale_negative(void) { locale_t loc, bad; char *day; char *tname = "newlocale_negative"; test_t t; t = test_start(tname); loc = newlocale(LC_ALL_MASK, "de_DE.UTF-8", NULL); if (loc == NULL) { test_failed(t, "cannot set de_DE.UTF-8"); } day = nl_langinfo_l(DAY_1, loc); if (strcmp(day, "Sonntag") != 0) { test_failed(t, "incorrect Sonntag != %s", day); } bad = newlocale(LC_ALL_MASK, "cn_US.BIZRRE", loc); if (bad != NULL) { test_failed(t, "passed setting bogus locale"); } day = nl_langinfo_l(DAY_1, loc); if (strcmp(day, "Sonntag") != 0) { test_failed(t, "incorrect Sonntag != %s", day); } test_passed(t); } void test_newlocale_categories(void) { locale_t loc; char *day, *cur, *yes; char *tname = "newlocale_categories"; test_t t; t = test_start(tname); loc = NULL; loc = newlocale(LC_TIME_MASK, "de_DE.UTF-8", loc); loc = newlocale(LC_MESSAGES_MASK, "ru_RU.UTF-8", loc); loc = newlocale(LC_MONETARY_MASK, "en_US.UTF-8", loc); if (loc == NULL) { test_failed(t, "failed to set locale"); } day = nl_langinfo_l(DAY_1, loc); if ((day == NULL) || (strcmp(day, "Sonntag") != 0)) { test_failed(t, "day1 mismatch %s != %s", day, "Sonntag"); } yes = nl_langinfo_l(YESSTR, loc); if ((yes == NULL) || (strcmp(yes, "да") != 0)) { test_failed(t, "currency mismatch"); } cur = nl_langinfo_l(CRNCYSTR, loc); if ((cur == NULL) || (strcmp(cur, "-$") != 0)) { test_failed(t, "currency mismatch [%s] != [%s]", cur, "-$"); } test_passed(t); } void test_newlocale_composite(void) { locale_t loc; char *day, *cur, *yes; char *tname = "newlocale_composite"; test_t t; t = test_start(tname); /* order: CTYPE/NUMERIC/TIME/COLLATE/MONETARY/MESSAGES */ loc = newlocale(LC_ALL_MASK, "C/C/de_DE.UTF-8/C/en_US.UTF-8/ru_RU.UTF-8", NULL); if (loc == NULL) { test_failed(t, "failed to set composite locale"); } day = nl_langinfo_l(DAY_1, loc); if ((day == NULL) || (strcmp(day, "Sonntag") != 0)) { test_failed(t, "day1 mismatch %s != %s", day, "Sonntag"); } yes = nl_langinfo_l(YESSTR, loc); if ((yes == NULL) || (strcmp(yes, "да") != 0)) { test_failed(t, "currency mismatch"); } cur = nl_langinfo_l(CRNCYSTR, loc); if ((cur == NULL) || (strcmp(cur, "-$") != 0)) { test_failed(t, "currency mismatch [%s] != [%s]", cur, "-$"); } test_passed(t); } int main(int argc, char **argv) { int optc; while ((optc = getopt(argc, argv, "Ddf")) != EOF) { switch (optc) { case 'd': test_set_debug(); break; case 'f': test_set_force(); break; case 'D': test_set_debug(); extra_debug++; break; default: (void) fprintf(stderr, "Usage: %s [-df]\n", argv[0]); exit(1); } } test_newlocale_threaded(); test_newlocale_negative(); test_newlocale_categories(); test_newlocale_composite(); exit(0); }