xref: /titanic_52/usr/src/test/libc-tests/tests/newlocale/newlocale_test.c (revision 538aa54d819fa7751ca82bcc30d4ed8c57ec2ef2)
12d08521bSGarrett D'Amore /*
22d08521bSGarrett D'Amore  * This file and its contents are supplied under the terms of the
32d08521bSGarrett D'Amore  * Common Development and Distribution License ("CDDL"), version 1.0.
42d08521bSGarrett D'Amore  * You may only use this file in accordance with the terms of version
52d08521bSGarrett D'Amore  * 1.0 of the CDDL.
62d08521bSGarrett D'Amore  *
72d08521bSGarrett D'Amore  * A full copy of the text of the CDDL should have accompanied this
82d08521bSGarrett D'Amore  * source.  A copy of the CDDL is also available via the Internet at
92d08521bSGarrett D'Amore  * http://www.illumos.org/license/CDDL.
102d08521bSGarrett D'Amore  */
112d08521bSGarrett D'Amore 
122d08521bSGarrett D'Amore /*
132d08521bSGarrett D'Amore  * Copyright 2014 Garrett D'Amore <garrett@damore.org>
142d08521bSGarrett D'Amore  */
152d08521bSGarrett D'Amore 
162d08521bSGarrett D'Amore /*
172d08521bSGarrett D'Amore  * This program tests that newlocale and uselocale work properly in
182d08521bSGarrett D'Amore  * multi-threaded programs.  In order for it to work, it requires that
192d08521bSGarrett D'Amore  * some additional locales be installed.
202d08521bSGarrett D'Amore  */
212d08521bSGarrett D'Amore 
222d08521bSGarrett D'Amore #include <stdio.h>
232d08521bSGarrett D'Amore #include <stdlib.h>
242d08521bSGarrett D'Amore #include <string.h>
252d08521bSGarrett D'Amore #include <locale.h>
262d08521bSGarrett D'Amore #include <libintl.h>
272d08521bSGarrett D'Amore #include <langinfo.h>
282d08521bSGarrett D'Amore #include <nl_types.h>
292d08521bSGarrett D'Amore #include <err.h>
302d08521bSGarrett D'Amore #include <unistd.h>
312d08521bSGarrett D'Amore #include <pthread.h>
32*538aa54dSGarrett D'Amore #include <note.h>
33*538aa54dSGarrett D'Amore #include "test_common.h"
342d08521bSGarrett D'Amore 
352d08521bSGarrett D'Amore /*
362d08521bSGarrett D'Amore  * Note that on some platforms, different symbols are used.  For example,
372d08521bSGarrett D'Amore  * MacOS Mavericks uses "Eu" for Euro symbol, instead of €.  If the locale
382d08521bSGarrett D'Amore  * data changes, then this program will need to update to reflect that.
392d08521bSGarrett D'Amore  */
402d08521bSGarrett D'Amore struct ldata {
412d08521bSGarrett D'Amore 	const char *locale;
422d08521bSGarrett D'Amore 	const char *day1;
432d08521bSGarrett D'Amore 	const char *cursym;
442d08521bSGarrett D'Amore } ldata[] = {
452d08521bSGarrett D'Amore 	{ "C", "Sunday", "" },
462d08521bSGarrett D'Amore 	{ "en_US.UTF-8", "Sunday", "$" },
472d08521bSGarrett D'Amore 	{ "de_DE.UTF-8", "Sonntag", "€" },
482d08521bSGarrett D'Amore 	{ "ru_RU.UTF-8", "воскресенье", "руб." },
492d08521bSGarrett D'Amore 	{ "ja_JP.UTF-8", "日曜日", "¥" },
502d08521bSGarrett D'Amore };
512d08521bSGarrett D'Amore 
522d08521bSGarrett D'Amore #define	NUM_LDATA	5
532d08521bSGarrett D'Amore #define	NUMTHR	20
542d08521bSGarrett D'Amore #define	NUMITR	200
552d08521bSGarrett D'Amore 
56*538aa54dSGarrett D'Amore int extra_debug = 0;
57*538aa54dSGarrett D'Amore 
58*538aa54dSGarrett D'Amore void
59*538aa54dSGarrett D'Amore testlocale_thr_one(test_t t, void *arg)
602d08521bSGarrett D'Amore {
61*538aa54dSGarrett D'Amore 	_NOTE(ARGUNUSED(arg));
622d08521bSGarrett D'Amore 	locale_t	cloc, loc;
632d08521bSGarrett D'Amore 	struct lconv	*lc;
642d08521bSGarrett D'Amore 	char		*day;
652d08521bSGarrett D'Amore 
662d08521bSGarrett D'Amore 	for (int i = 0; i < NUMITR; i++) {
672d08521bSGarrett D'Amore 		struct ldata *l = &ldata[i % NUM_LDATA];
682d08521bSGarrett D'Amore 		cloc = uselocale(NULL);
692d08521bSGarrett D'Amore 
702d08521bSGarrett D'Amore 		loc = newlocale(LC_ALL_MASK, l->locale, NULL);
712d08521bSGarrett D'Amore 		if (loc == NULL) {
72*538aa54dSGarrett D'Amore 			test_failed(t, "newlocale %s failed", l->locale);
732d08521bSGarrett D'Amore 		}
742d08521bSGarrett D'Amore 		day = nl_langinfo_l(DAY_1, loc);
752d08521bSGarrett D'Amore 		if (strcmp(day, l->day1) != 0) {
76*538aa54dSGarrett D'Amore 			test_failed(t, "newlocale data mismatch (%s != %s)",
772d08521bSGarrett D'Amore 			    day, l->day1);
782d08521bSGarrett D'Amore 		}
79*538aa54dSGarrett D'Amore 		if (extra_debug)
80*538aa54dSGarrett D'Amore 			test_debugf(t, "DAY1: %s", day);
812d08521bSGarrett D'Amore 
822d08521bSGarrett D'Amore 		day = nl_langinfo(DAY_1);
832d08521bSGarrett D'Amore 		if (strcmp(day, "Sunday") != 0) {
84*538aa54dSGarrett D'Amore 			test_failed(t, "C locale day wrong %s != Sunday",
852d08521bSGarrett D'Amore 			    day);
862d08521bSGarrett D'Amore 		}
872d08521bSGarrett D'Amore 		lc = localeconv();
882d08521bSGarrett D'Amore 		if (strcmp(lc->currency_symbol, "") != 0) {
89*538aa54dSGarrett D'Amore 			test_failed(t, "C cursym mismatch (%s != %s)",
902d08521bSGarrett D'Amore 			    lc->currency_symbol, "");
912d08521bSGarrett D'Amore 		}
922d08521bSGarrett D'Amore 
932d08521bSGarrett D'Amore 		/* we sleep a random bit to mix it up */
942d08521bSGarrett D'Amore 		(void) usleep(rand() % 10);
952d08521bSGarrett D'Amore 
962d08521bSGarrett D'Amore 		(void) uselocale(loc);
972d08521bSGarrett D'Amore 		day = nl_langinfo(DAY_1);
982d08521bSGarrett D'Amore 		if (strcmp(day, l->day1) != 0) {
99*538aa54dSGarrett D'Amore 			test_failed(t, "uselocale data mismatch (%s != %s)",
1002d08521bSGarrett D'Amore 			    day, l->day1);
1012d08521bSGarrett D'Amore 		}
1022d08521bSGarrett D'Amore 
1032d08521bSGarrett D'Amore 		lc = localeconv();
1042d08521bSGarrett D'Amore 		if (strcmp(lc->currency_symbol, l->cursym) != 0) {
105*538aa54dSGarrett D'Amore 			test_failed(t, "uselocal cursym %s != %s",
1062d08521bSGarrett D'Amore 			    lc->currency_symbol, l->cursym);
1072d08521bSGarrett D'Amore 		}
108*538aa54dSGarrett D'Amore 		if (extra_debug)
109*538aa54dSGarrett D'Amore 			test_debugf(t, "CSYM: %s", lc->currency_symbol);
1102d08521bSGarrett D'Amore 
1112d08521bSGarrett D'Amore 		/* we sleep a random bit to mix it up */
1122d08521bSGarrett D'Amore 		(void) usleep(rand() % 10);
1132d08521bSGarrett D'Amore 
1142d08521bSGarrett D'Amore 		if (uselocale(cloc) != loc) {
115*538aa54dSGarrett D'Amore 			test_failed(t, "revert old locale mismatch");
1162d08521bSGarrett D'Amore 		}
1172d08521bSGarrett D'Amore 		freelocale(loc);
1182d08521bSGarrett D'Amore 		if (uselocale(LC_GLOBAL_LOCALE) != cloc) {
119*538aa54dSGarrett D'Amore 			test_failed(t, "revert GLOBAL_LOCALE mismatch");
1202d08521bSGarrett D'Amore 		}
1212d08521bSGarrett D'Amore 	}
122*538aa54dSGarrett D'Amore 	test_passed(t);
1232d08521bSGarrett D'Amore }
1242d08521bSGarrett D'Amore 
1252d08521bSGarrett D'Amore 
1262d08521bSGarrett D'Amore void
127*538aa54dSGarrett D'Amore test_newlocale_threaded(void)
1282d08521bSGarrett D'Amore {
129*538aa54dSGarrett D'Amore 	test_run(NUMTHR, testlocale_thr_one, NULL, "newlocale_threaded");
1302d08521bSGarrett D'Amore }
1312d08521bSGarrett D'Amore 
132*538aa54dSGarrett D'Amore void
133*538aa54dSGarrett D'Amore test_newlocale_negative(void)
134*538aa54dSGarrett D'Amore {
135*538aa54dSGarrett D'Amore 	locale_t loc, bad;
136*538aa54dSGarrett D'Amore 	char *day;
137*538aa54dSGarrett D'Amore 	char *tname = "newlocale_negative";
138*538aa54dSGarrett D'Amore 	test_t t;
139*538aa54dSGarrett D'Amore 
140*538aa54dSGarrett D'Amore 	t = test_start(tname);
141*538aa54dSGarrett D'Amore 	loc = newlocale(LC_ALL_MASK, "de_DE.UTF-8", NULL);
142*538aa54dSGarrett D'Amore 	if (loc == NULL) {
143*538aa54dSGarrett D'Amore 		test_failed(t, "cannot set de_DE.UTF-8");
1442d08521bSGarrett D'Amore 	}
145*538aa54dSGarrett D'Amore 	day = nl_langinfo_l(DAY_1, loc);
146*538aa54dSGarrett D'Amore 	if (strcmp(day, "Sonntag") != 0) {
147*538aa54dSGarrett D'Amore 		test_failed(t, "incorrect Sonntag != %s", day);
148*538aa54dSGarrett D'Amore 	}
149*538aa54dSGarrett D'Amore 
150*538aa54dSGarrett D'Amore 	bad = newlocale(LC_ALL_MASK, "cn_US.BIZRRE", loc);
151*538aa54dSGarrett D'Amore 	if (bad != NULL) {
152*538aa54dSGarrett D'Amore 		test_failed(t, "passed setting bogus locale");
153*538aa54dSGarrett D'Amore 	}
154*538aa54dSGarrett D'Amore 	day = nl_langinfo_l(DAY_1, loc);
155*538aa54dSGarrett D'Amore 	if (strcmp(day, "Sonntag") != 0) {
156*538aa54dSGarrett D'Amore 		test_failed(t, "incorrect Sonntag != %s", day);
157*538aa54dSGarrett D'Amore 	}
158*538aa54dSGarrett D'Amore 	test_passed(t);
159*538aa54dSGarrett D'Amore }
160*538aa54dSGarrett D'Amore 
161*538aa54dSGarrett D'Amore void
162*538aa54dSGarrett D'Amore test_newlocale_categories(void)
163*538aa54dSGarrett D'Amore {
164*538aa54dSGarrett D'Amore 	locale_t loc;
165*538aa54dSGarrett D'Amore 	char *day, *cur, *yes;
166*538aa54dSGarrett D'Amore 	char *tname = "newlocale_categories";
167*538aa54dSGarrett D'Amore 	test_t t;
168*538aa54dSGarrett D'Amore 
169*538aa54dSGarrett D'Amore 	t = test_start(tname);
170*538aa54dSGarrett D'Amore 
171*538aa54dSGarrett D'Amore 	loc = NULL;
172*538aa54dSGarrett D'Amore 	loc = newlocale(LC_TIME_MASK, "de_DE.UTF-8", loc);
173*538aa54dSGarrett D'Amore 	loc = newlocale(LC_MESSAGES_MASK, "ru_RU.UTF-8", loc);
174*538aa54dSGarrett D'Amore 	loc = newlocale(LC_MONETARY_MASK, "en_US.UTF-8", loc);
175*538aa54dSGarrett D'Amore 
176*538aa54dSGarrett D'Amore 	if (loc == NULL) {
177*538aa54dSGarrett D'Amore 		test_failed(t, "failed to set locale");
178*538aa54dSGarrett D'Amore 	}
179*538aa54dSGarrett D'Amore 
180*538aa54dSGarrett D'Amore 	day = nl_langinfo_l(DAY_1, loc);
181*538aa54dSGarrett D'Amore 	if ((day == NULL) || (strcmp(day, "Sonntag") != 0)) {
182*538aa54dSGarrett D'Amore 		test_failed(t, "day1 mismatch %s != %s", day, "Sonntag");
183*538aa54dSGarrett D'Amore 	}
184*538aa54dSGarrett D'Amore 	yes = nl_langinfo_l(YESSTR, loc);
185*538aa54dSGarrett D'Amore 	if ((yes == NULL) || (strcmp(yes, "да") != 0)) {
186*538aa54dSGarrett D'Amore 		test_failed(t, "currency mismatch");
187*538aa54dSGarrett D'Amore 	}
188*538aa54dSGarrett D'Amore 	cur = nl_langinfo_l(CRNCYSTR, loc);
189*538aa54dSGarrett D'Amore 	if ((cur == NULL) || (strcmp(cur, "-$") != 0)) {
190*538aa54dSGarrett D'Amore 		test_failed(t, "currency mismatch [%s] != [%s]", cur, "-$");
191*538aa54dSGarrett D'Amore 	}
192*538aa54dSGarrett D'Amore 
193*538aa54dSGarrett D'Amore 	test_passed(t);
194*538aa54dSGarrett D'Amore }
195*538aa54dSGarrett D'Amore 
196*538aa54dSGarrett D'Amore void
197*538aa54dSGarrett D'Amore test_newlocale_composite(void)
198*538aa54dSGarrett D'Amore {
199*538aa54dSGarrett D'Amore 	locale_t loc;
200*538aa54dSGarrett D'Amore 	char *day, *cur, *yes;
201*538aa54dSGarrett D'Amore 	char *tname = "newlocale_composite";
202*538aa54dSGarrett D'Amore 	test_t t;
203*538aa54dSGarrett D'Amore 
204*538aa54dSGarrett D'Amore 	t = test_start(tname);
205*538aa54dSGarrett D'Amore 
206*538aa54dSGarrett D'Amore 	/* order: CTYPE/NUMERIC/TIME/COLLATE/MONETARY/MESSAGES */
207*538aa54dSGarrett D'Amore 	loc = newlocale(LC_ALL_MASK,
208*538aa54dSGarrett D'Amore 	    "C/C/de_DE.UTF-8/C/en_US.UTF-8/ru_RU.UTF-8", NULL);
209*538aa54dSGarrett D'Amore 
210*538aa54dSGarrett D'Amore 	if (loc == NULL) {
211*538aa54dSGarrett D'Amore 		test_failed(t, "failed to set composite locale");
212*538aa54dSGarrett D'Amore 	}
213*538aa54dSGarrett D'Amore 
214*538aa54dSGarrett D'Amore 	day = nl_langinfo_l(DAY_1, loc);
215*538aa54dSGarrett D'Amore 	if ((day == NULL) || (strcmp(day, "Sonntag") != 0)) {
216*538aa54dSGarrett D'Amore 		test_failed(t, "day1 mismatch %s != %s", day, "Sonntag");
217*538aa54dSGarrett D'Amore 	}
218*538aa54dSGarrett D'Amore 	yes = nl_langinfo_l(YESSTR, loc);
219*538aa54dSGarrett D'Amore 	if ((yes == NULL) || (strcmp(yes, "да") != 0)) {
220*538aa54dSGarrett D'Amore 		test_failed(t, "currency mismatch");
221*538aa54dSGarrett D'Amore 	}
222*538aa54dSGarrett D'Amore 	cur = nl_langinfo_l(CRNCYSTR, loc);
223*538aa54dSGarrett D'Amore 	if ((cur == NULL) || (strcmp(cur, "-$") != 0)) {
224*538aa54dSGarrett D'Amore 		test_failed(t, "currency mismatch [%s] != [%s]", cur, "-$");
225*538aa54dSGarrett D'Amore 	}
226*538aa54dSGarrett D'Amore 
227*538aa54dSGarrett D'Amore 	test_passed(t);
2282d08521bSGarrett D'Amore }
2292d08521bSGarrett D'Amore 
2302d08521bSGarrett D'Amore int
2312d08521bSGarrett D'Amore main(int argc, char **argv)
2322d08521bSGarrett D'Amore {
2332d08521bSGarrett D'Amore 	int optc;
2342d08521bSGarrett D'Amore 
235*538aa54dSGarrett D'Amore 	while ((optc = getopt(argc, argv, "Ddf")) != EOF) {
2362d08521bSGarrett D'Amore 		switch (optc) {
2372d08521bSGarrett D'Amore 		case 'd':
238*538aa54dSGarrett D'Amore 			test_set_debug();
239*538aa54dSGarrett D'Amore 			break;
240*538aa54dSGarrett D'Amore 		case 'f':
241*538aa54dSGarrett D'Amore 			test_set_force();
242*538aa54dSGarrett D'Amore 			break;
243*538aa54dSGarrett D'Amore 		case 'D':
244*538aa54dSGarrett D'Amore 			test_set_debug();
245*538aa54dSGarrett D'Amore 			extra_debug++;
2462d08521bSGarrett D'Amore 			break;
2472d08521bSGarrett D'Amore 		default:
248*538aa54dSGarrett D'Amore 			(void) fprintf(stderr, "Usage: %s [-df]\n", argv[0]);
2492d08521bSGarrett D'Amore 			exit(1);
2502d08521bSGarrett D'Amore 		}
2512d08521bSGarrett D'Amore 	}
2522d08521bSGarrett D'Amore 
253*538aa54dSGarrett D'Amore 	test_newlocale_threaded();
254*538aa54dSGarrett D'Amore 	test_newlocale_negative();
255*538aa54dSGarrett D'Amore 	test_newlocale_categories();
256*538aa54dSGarrett D'Amore 	test_newlocale_composite();
2572d08521bSGarrett D'Amore 
2582d08521bSGarrett D'Amore 	exit(0);
2592d08521bSGarrett D'Amore }
260