1*538aa54dSGarrett D'Amore /*
2*538aa54dSGarrett D'Amore  * This file and its contents are supplied under the terms of the
3*538aa54dSGarrett D'Amore  * Common Development and Distribution License ("CDDL"), version 1.0.
4*538aa54dSGarrett D'Amore  * You may only use this file in accordance with the terms of version
5*538aa54dSGarrett D'Amore  * 1.0 of the CDDL.
6*538aa54dSGarrett D'Amore  *
7*538aa54dSGarrett D'Amore  * A full copy of the text of the CDDL should have accompanied this
8*538aa54dSGarrett D'Amore  * source.  A copy of the CDDL is also available via the Internet at
9*538aa54dSGarrett D'Amore  * http://www.illumos.org/license/CDDL.
10*538aa54dSGarrett D'Amore  */
11*538aa54dSGarrett D'Amore 
12*538aa54dSGarrett D'Amore /*
13*538aa54dSGarrett D'Amore  * Copyright 2014 Garrett D'Amore <garrett@damore.org>
14*538aa54dSGarrett D'Amore  */
15*538aa54dSGarrett D'Amore 
16*538aa54dSGarrett D'Amore /*
17*538aa54dSGarrett D'Amore  * This program tests that wcsrtombs and friends work properly.
18*538aa54dSGarrett D'Amore  * In order for it to work, it requires that some additional locales
19*538aa54dSGarrett D'Amore  * be installed.
20*538aa54dSGarrett D'Amore  */
21*538aa54dSGarrett D'Amore 
22*538aa54dSGarrett D'Amore #include <stdio.h>
23*538aa54dSGarrett D'Amore #include <stdlib.h>
24*538aa54dSGarrett D'Amore #include <string.h>
25*538aa54dSGarrett D'Amore #include <locale.h>
26*538aa54dSGarrett D'Amore #include <wchar.h>
27*538aa54dSGarrett D'Amore #include <err.h>
28*538aa54dSGarrett D'Amore #include <errno.h>
29*538aa54dSGarrett D'Amore #include <unistd.h>
30*538aa54dSGarrett D'Amore #include <xlocale.h>
31*538aa54dSGarrett D'Amore #include <note.h>
32*538aa54dSGarrett D'Amore #include "test_common.h"
33*538aa54dSGarrett D'Amore 
34*538aa54dSGarrett D'Amore int extra_debug = 0;
35*538aa54dSGarrett D'Amore 
36*538aa54dSGarrett D'Amore #define	NUMTHR	300
37*538aa54dSGarrett D'Amore #define	NUMITR	300
38*538aa54dSGarrett D'Amore 
39*538aa54dSGarrett D'Amore /*
40*538aa54dSGarrett D'Amore  * Note that this file is easiest edited with a UTF-8 capable editor,
41*538aa54dSGarrett D'Amore  * as there are embedded UTF-8 symbols in some of the strings.
42*538aa54dSGarrett D'Amore  */
43*538aa54dSGarrett D'Amore struct wcsrtombs_test {
44*538aa54dSGarrett D'Amore 	char		mbs[32];
45*538aa54dSGarrett D'Amore 	wchar_t		wcs[32];
46*538aa54dSGarrett D'Amore };
47*538aa54dSGarrett D'Amore 
48*538aa54dSGarrett D'Amore #define	TESTING_MBS	"TESTING"
49*538aa54dSGarrett D'Amore #define	TESTING_WCS 	{ 'T', 'E', 'S', 'T', 'I', 'N', 'G', 0 }
50*538aa54dSGarrett D'Amore #define	HELLO_RU_MBS	"ПРИВЕТ"
51*538aa54dSGarrett D'Amore #define	HELLO_RU_WCS	{ 1055, 1056, 1048, 1042, 1045, 1058, 0 }
52*538aa54dSGarrett D'Amore #define	HELLO_EN_MBS	"HELLO"
53*538aa54dSGarrett D'Amore #define	HELLO_EN_WCS	{ 'H', 'E', 'L', 'L', 'O', 0 }
54*538aa54dSGarrett D'Amore 
55*538aa54dSGarrett D'Amore /* Unicode values never have the high order bit set */
56*538aa54dSGarrett D'Amore #define	BAD_WCS		{ 'B', 'A', 'D', (wchar_t)0xf000f000, 'W', 'C', 'S' }
57*538aa54dSGarrett D'Amore 
58*538aa54dSGarrett D'Amore struct wcsrtombs_test C_data[] = {
59*538aa54dSGarrett D'Amore 	{ TESTING_MBS,	TESTING_WCS },
60*538aa54dSGarrett D'Amore 	{ HELLO_EN_MBS,	HELLO_EN_WCS },
61*538aa54dSGarrett D'Amore 	{ 0, 0 },
62*538aa54dSGarrett D'Amore };
63*538aa54dSGarrett D'Amore 
64*538aa54dSGarrett D'Amore struct wcsrtombs_test utf8_data[] = {
65*538aa54dSGarrett D'Amore 	{ TESTING_MBS,	TESTING_WCS },
66*538aa54dSGarrett D'Amore 	{ HELLO_EN_MBS,	HELLO_EN_WCS },
67*538aa54dSGarrett D'Amore 	{ HELLO_RU_MBS,	HELLO_RU_WCS },
68*538aa54dSGarrett D'Amore 	{ 0, 0 },
69*538aa54dSGarrett D'Amore };
70*538aa54dSGarrett D'Amore 
71*538aa54dSGarrett D'Amore struct {
72*538aa54dSGarrett D'Amore 	const char *locale;
73*538aa54dSGarrett D'Amore 	struct wcsrtombs_test *test;
74*538aa54dSGarrett D'Amore } locales[] =  {
75*538aa54dSGarrett D'Amore 	{ "C",			C_data },
76*538aa54dSGarrett D'Amore 	{ "en_US.UTF-8",	utf8_data },
77*538aa54dSGarrett D'Amore 	{ NULL, 		NULL }
78*538aa54dSGarrett D'Amore };
79*538aa54dSGarrett D'Amore 
80*538aa54dSGarrett D'Amore void
test_wcsrtombs_1(const char * locale,struct wcsrtombs_test * test)81*538aa54dSGarrett D'Amore test_wcsrtombs_1(const char *locale, struct wcsrtombs_test *test)
82*538aa54dSGarrett D'Amore {
83*538aa54dSGarrett D'Amore 	test_t		t;
84*538aa54dSGarrett D'Amore 	char 		*v;
85*538aa54dSGarrett D'Amore 	mbstate_t	ms;
86*538aa54dSGarrett D'Amore 
87*538aa54dSGarrett D'Amore 	t = test_start("wcsrtombs (locale %s)", locale);
88*538aa54dSGarrett D'Amore 
89*538aa54dSGarrett D'Amore 	v = setlocale(LC_ALL, locale);
90*538aa54dSGarrett D'Amore 	if (v == NULL) {
91*538aa54dSGarrett D'Amore 		test_failed(t, "setlocale failed: %s", strerror(errno));
92*538aa54dSGarrett D'Amore 	}
93*538aa54dSGarrett D'Amore 	if (strcmp(v, locale) != 0) {
94*538aa54dSGarrett D'Amore 		test_failed(t, "setlocale got %s instead of %s", v, locale);
95*538aa54dSGarrett D'Amore 	}
96*538aa54dSGarrett D'Amore 
97*538aa54dSGarrett D'Amore 	for (int i = 0; test[i].mbs[0] != 0; i++) {
98*538aa54dSGarrett D'Amore 		char mbs[32];
99*538aa54dSGarrett D'Amore 		const wchar_t *wcs = test[i].wcs;
100*538aa54dSGarrett D'Amore 		size_t cnt;
101*538aa54dSGarrett D'Amore 
102*538aa54dSGarrett D'Amore 		(void) memset(&ms, 0, sizeof (ms));
103*538aa54dSGarrett D'Amore 		(void) memset(mbs, 0, sizeof (mbs));
104*538aa54dSGarrett D'Amore 		cnt = wcsrtombs(mbs, &wcs, sizeof (mbs), &ms);
105*538aa54dSGarrett D'Amore 		if (cnt != strlen(test[i].mbs)) {
106*538aa54dSGarrett D'Amore 			test_failed(t, "incorrect return value: %d != %d",
107*538aa54dSGarrett D'Amore 			    cnt, strlen(test[i].mbs));
108*538aa54dSGarrett D'Amore 		}
109*538aa54dSGarrett D'Amore 		if (strcmp(mbs, test[i].mbs) != 0) {
110*538aa54dSGarrett D'Amore 			test_failed(t, "wrong result: %s != %s",
111*538aa54dSGarrett D'Amore 			    mbs, test[i].mbs);
112*538aa54dSGarrett D'Amore 		}
113*538aa54dSGarrett D'Amore 		if (extra_debug) {
114*538aa54dSGarrett D'Amore 			test_debugf(t, "mbs is %s", mbs);
115*538aa54dSGarrett D'Amore 		}
116*538aa54dSGarrett D'Amore 	}
117*538aa54dSGarrett D'Amore 	test_passed(t);
118*538aa54dSGarrett D'Amore }
119*538aa54dSGarrett D'Amore 
120*538aa54dSGarrett D'Amore void
test_wcsrtombs_l(const char * locale,struct wcsrtombs_test * test)121*538aa54dSGarrett D'Amore test_wcsrtombs_l(const char *locale, struct wcsrtombs_test *test)
122*538aa54dSGarrett D'Amore {
123*538aa54dSGarrett D'Amore 	test_t	t;
124*538aa54dSGarrett D'Amore 	locale_t loc;
125*538aa54dSGarrett D'Amore 	char 	*v;
126*538aa54dSGarrett D'Amore 	mbstate_t	ms;
127*538aa54dSGarrett D'Amore 
128*538aa54dSGarrett D'Amore 	t = test_start("wcsrtombs_l (locale %s)", locale);
129*538aa54dSGarrett D'Amore 
130*538aa54dSGarrett D'Amore 	v = setlocale(LC_ALL, "C");
131*538aa54dSGarrett D'Amore 	if (v == NULL) {
132*538aa54dSGarrett D'Amore 		test_failed(t, "setlocale failed: %s", strerror(errno));
133*538aa54dSGarrett D'Amore 	}
134*538aa54dSGarrett D'Amore 	if (strcmp(v, "C") != 0) {
135*538aa54dSGarrett D'Amore 		test_failed(t, "setlocale got %s instead of %s", v, "C");
136*538aa54dSGarrett D'Amore 	}
137*538aa54dSGarrett D'Amore 
138*538aa54dSGarrett D'Amore 	loc = newlocale(LC_ALL_MASK, locale, NULL);
139*538aa54dSGarrett D'Amore 	if (loc == NULL) {
140*538aa54dSGarrett D'Amore 		test_failed(t, "newlocale failed: %s", strerror(errno));
141*538aa54dSGarrett D'Amore 	}
142*538aa54dSGarrett D'Amore 
143*538aa54dSGarrett D'Amore 	for (int i = 0; test[i].mbs[0] != 0; i++) {
144*538aa54dSGarrett D'Amore 		char mbs[32];
145*538aa54dSGarrett D'Amore 		const wchar_t *wcs = test[i].wcs;
146*538aa54dSGarrett D'Amore 		size_t cnt;
147*538aa54dSGarrett D'Amore 
148*538aa54dSGarrett D'Amore 		(void) memset(&ms, 0, sizeof (ms));
149*538aa54dSGarrett D'Amore 		(void) memset(mbs, 0, sizeof (mbs));
150*538aa54dSGarrett D'Amore 		cnt = wcsrtombs_l(mbs, &wcs, sizeof (mbs), &ms, loc);
151*538aa54dSGarrett D'Amore 		if (cnt != strlen(test[i].mbs)) {
152*538aa54dSGarrett D'Amore 			test_failed(t, "incorrect return value: %d != %d",
153*538aa54dSGarrett D'Amore 			    cnt, strlen(test[i].mbs));
154*538aa54dSGarrett D'Amore 		}
155*538aa54dSGarrett D'Amore 		if (strcmp(mbs, test[i].mbs) != 0) {
156*538aa54dSGarrett D'Amore 			test_failed(t, "wrong result: %s != %s", mbs,
157*538aa54dSGarrett D'Amore 			    test[i].mbs);
158*538aa54dSGarrett D'Amore 		}
159*538aa54dSGarrett D'Amore 		if (extra_debug) {
160*538aa54dSGarrett D'Amore 			test_debugf(t, "mbs is %s", mbs);
161*538aa54dSGarrett D'Amore 		}
162*538aa54dSGarrett D'Amore 	}
163*538aa54dSGarrett D'Amore 	test_passed(t);
164*538aa54dSGarrett D'Amore }
165*538aa54dSGarrett D'Amore 
166*538aa54dSGarrett D'Amore void
test_wcsrtombs_thr_iter(test_t t,const char * locale,struct wcsrtombs_test * test)167*538aa54dSGarrett D'Amore test_wcsrtombs_thr_iter(test_t t, const char *locale,
168*538aa54dSGarrett D'Amore     struct wcsrtombs_test *test)
169*538aa54dSGarrett D'Amore {
170*538aa54dSGarrett D'Amore 	locale_t loc;
171*538aa54dSGarrett D'Amore 	mbstate_t	ms;
172*538aa54dSGarrett D'Amore 
173*538aa54dSGarrett D'Amore 	loc = newlocale(LC_ALL_MASK, locale, NULL);
174*538aa54dSGarrett D'Amore 	if (loc == NULL) {
175*538aa54dSGarrett D'Amore 		test_failed(t, "newlocale failed: %s", strerror(errno));
176*538aa54dSGarrett D'Amore 	}
177*538aa54dSGarrett D'Amore 
178*538aa54dSGarrett D'Amore 	for (int i = 0; test[i].mbs[0] != 0; i++) {
179*538aa54dSGarrett D'Amore 		char mbs[32];
180*538aa54dSGarrett D'Amore 		const wchar_t *wcs = test[i].wcs;
181*538aa54dSGarrett D'Amore 		size_t cnt;
182*538aa54dSGarrett D'Amore 
183*538aa54dSGarrett D'Amore 		(void) memset(&ms, 0, sizeof (ms));
184*538aa54dSGarrett D'Amore 		(void) memset(mbs, 0, sizeof (mbs));
185*538aa54dSGarrett D'Amore 		cnt = wcsrtombs_l(mbs, &wcs, sizeof (mbs), &ms, loc);
186*538aa54dSGarrett D'Amore 		if (cnt != strlen(test[i].mbs)) {
187*538aa54dSGarrett D'Amore 			test_failed(t, "incorrect return value: %d != %d",
188*538aa54dSGarrett D'Amore 			    cnt, strlen(test[i].mbs));
189*538aa54dSGarrett D'Amore 		}
190*538aa54dSGarrett D'Amore 		if (strcmp(mbs, test[i].mbs) != 0) {
191*538aa54dSGarrett D'Amore 			test_failed(t, "wrong result: %s != %s", mbs,
192*538aa54dSGarrett D'Amore 			    test[i].mbs);
193*538aa54dSGarrett D'Amore 		}
194*538aa54dSGarrett D'Amore 		if (extra_debug) {
195*538aa54dSGarrett D'Amore 			test_debugf(t, "mbs is %s", mbs);
196*538aa54dSGarrett D'Amore 		}
197*538aa54dSGarrett D'Amore 	}
198*538aa54dSGarrett D'Amore 
199*538aa54dSGarrett D'Amore 	freelocale(loc);
200*538aa54dSGarrett D'Amore }
201*538aa54dSGarrett D'Amore 
202*538aa54dSGarrett D'Amore void
test_wcsrtombs_thr_work(test_t t,void * arg)203*538aa54dSGarrett D'Amore test_wcsrtombs_thr_work(test_t t, void *arg)
204*538aa54dSGarrett D'Amore {
205*538aa54dSGarrett D'Amore 	_NOTE(ARGUNUSED(arg));
206*538aa54dSGarrett D'Amore 	for (int j = 0; j < NUMITR; j++) {
207*538aa54dSGarrett D'Amore 		test_debugf(t, "iteration %d", j);
208*538aa54dSGarrett D'Amore 		for (int i = 0; locales[i].locale != NULL; i++) {
209*538aa54dSGarrett D'Amore 			test_wcsrtombs_thr_iter(t, locales[i].locale,
210*538aa54dSGarrett D'Amore 			    locales[i].test);
211*538aa54dSGarrett D'Amore 		}
212*538aa54dSGarrett D'Amore 	}
213*538aa54dSGarrett D'Amore 	test_passed(t);
214*538aa54dSGarrett D'Amore }
215*538aa54dSGarrett D'Amore 
216*538aa54dSGarrett D'Amore void
test_wcsrtombs_threaded(void)217*538aa54dSGarrett D'Amore test_wcsrtombs_threaded(void)
218*538aa54dSGarrett D'Amore {
219*538aa54dSGarrett D'Amore 	(void) setlocale(LC_ALL, "C");
220*538aa54dSGarrett D'Amore 	test_run(NUMTHR, test_wcsrtombs_thr_work, NULL, "wcsrtombs_threaded");
221*538aa54dSGarrett D'Amore }
222*538aa54dSGarrett D'Amore 
223*538aa54dSGarrett D'Amore void
test_wcsrtombs_partial(void)224*538aa54dSGarrett D'Amore test_wcsrtombs_partial(void)
225*538aa54dSGarrett D'Amore {
226*538aa54dSGarrett D'Amore 	test_t		t;
227*538aa54dSGarrett D'Amore 	mbstate_t	ms;
228*538aa54dSGarrett D'Amore 	wchar_t		src[32] = HELLO_RU_WCS;
229*538aa54dSGarrett D'Amore 	char		mbs[32];
230*538aa54dSGarrett D'Amore 	char		*dst;
231*538aa54dSGarrett D'Amore 	const wchar_t	*wcs;
232*538aa54dSGarrett D'Amore 	size_t 		cnt;
233*538aa54dSGarrett D'Amore 
234*538aa54dSGarrett D'Amore 
235*538aa54dSGarrett D'Amore 	(void) memset(&ms, 0, sizeof (ms));
236*538aa54dSGarrett D'Amore 	t = test_start("wcsrtombs_partial");
237*538aa54dSGarrett D'Amore 
238*538aa54dSGarrett D'Amore 	if (setlocale(LC_ALL, "ru_RU.UTF-8") == NULL) {
239*538aa54dSGarrett D'Amore 		test_failed(t, "setlocale failed: %s", strerror(errno));
240*538aa54dSGarrett D'Amore 	}
241*538aa54dSGarrett D'Amore 
242*538aa54dSGarrett D'Amore 	wcs = src;
243*538aa54dSGarrett D'Amore 	dst = mbs;
244*538aa54dSGarrett D'Amore 	cnt = wcsrtombs(dst, &wcs, 1, &ms);
245*538aa54dSGarrett D'Amore 	if (cnt != 0) {
246*538aa54dSGarrett D'Amore 		test_failed(t, "gave back a conversion cnt %d != 0", cnt);
247*538aa54dSGarrett D'Amore 	}
248*538aa54dSGarrett D'Amore 	if (wcs != src) {
249*538aa54dSGarrett D'Amore 		test_failed(t, "incorrectly advanced wcs");
250*538aa54dSGarrett D'Amore 	}
251*538aa54dSGarrett D'Amore 
252*538aa54dSGarrett D'Amore 	cnt = wcsrtombs(dst, &wcs, 2, &ms);
253*538aa54dSGarrett D'Amore 	if (cnt != 2) {
254*538aa54dSGarrett D'Amore 		test_failed(t, "gave back a conversion cnt %d != 2", cnt);
255*538aa54dSGarrett D'Amore 	}
256*538aa54dSGarrett D'Amore 	dst += cnt;
257*538aa54dSGarrett D'Amore 
258*538aa54dSGarrett D'Amore 	cnt = wcsrtombs(dst, &wcs, 4, &ms);
259*538aa54dSGarrett D'Amore 	dst += cnt;
260*538aa54dSGarrett D'Amore 
261*538aa54dSGarrett D'Amore 	cnt = wcsrtombs(dst, &wcs, sizeof (mbs) - strlen(mbs), &ms);
262*538aa54dSGarrett D'Amore 	if (extra_debug) {
263*538aa54dSGarrett D'Amore 		test_debugf(t, "mbs is %s", mbs);
264*538aa54dSGarrett D'Amore 	}
265*538aa54dSGarrett D'Amore 	if (strcmp(mbs, HELLO_RU_MBS) != 0) {
266*538aa54dSGarrett D'Amore 		test_failed(t, "wrong result: %s != %s", mbs, HELLO_RU_MBS);
267*538aa54dSGarrett D'Amore 	}
268*538aa54dSGarrett D'Amore 	test_passed(t);
269*538aa54dSGarrett D'Amore }
270*538aa54dSGarrett D'Amore 
271*538aa54dSGarrett D'Amore void
test_wcsrtombs_negative(void)272*538aa54dSGarrett D'Amore test_wcsrtombs_negative(void)
273*538aa54dSGarrett D'Amore {
274*538aa54dSGarrett D'Amore 	mbstate_t	ms;
275*538aa54dSGarrett D'Amore 	const wchar_t	*wcs;
276*538aa54dSGarrett D'Amore 	char		mbs[32];
277*538aa54dSGarrett D'Amore 	char		*dst;
278*538aa54dSGarrett D'Amore 	int		e;
279*538aa54dSGarrett D'Amore 	wchar_t		src[32] = BAD_WCS;
280*538aa54dSGarrett D'Amore 	test_t		t;
281*538aa54dSGarrett D'Amore 	int		cnt;
282*538aa54dSGarrett D'Amore 
283*538aa54dSGarrett D'Amore 	t = test_start("wcsrtombs_negative");
284*538aa54dSGarrett D'Amore 
285*538aa54dSGarrett D'Amore 	(void) memset(&ms, 0, sizeof (ms));
286*538aa54dSGarrett D'Amore 	if (setlocale(LC_ALL, "ru_RU.UTF-8") == NULL) {
287*538aa54dSGarrett D'Amore 		test_failed(t, "setlocale failed: %s", strerror(errno));
288*538aa54dSGarrett D'Amore 	}
289*538aa54dSGarrett D'Amore 
290*538aa54dSGarrett D'Amore 	wcs = src;
291*538aa54dSGarrett D'Amore 	dst = mbs;
292*538aa54dSGarrett D'Amore 	cnt = wcsrtombs(dst, &wcs, sizeof (mbs), &ms);
293*538aa54dSGarrett D'Amore 	if (cnt != -1) {
294*538aa54dSGarrett D'Amore 		test_failed(t, "bogus success (%d)", cnt);
295*538aa54dSGarrett D'Amore 	}
296*538aa54dSGarrett D'Amore 	if ((e = errno) != EILSEQ) {
297*538aa54dSGarrett D'Amore 		test_failed(t, "wrong errno, wanted %d (EILSEQ), got %d: %s",
298*538aa54dSGarrett D'Amore 		    EILSEQ, e, strerror(e));
299*538aa54dSGarrett D'Amore 	}
300*538aa54dSGarrett D'Amore 	test_passed(t);
301*538aa54dSGarrett D'Amore }
302*538aa54dSGarrett D'Amore 
303*538aa54dSGarrett D'Amore void
test_wcsnrtombs_partial(void)304*538aa54dSGarrett D'Amore test_wcsnrtombs_partial(void)
305*538aa54dSGarrett D'Amore {
306*538aa54dSGarrett D'Amore 	test_t		t;
307*538aa54dSGarrett D'Amore 	mbstate_t	ms;
308*538aa54dSGarrett D'Amore 	wchar_t		src[32] = HELLO_RU_WCS;
309*538aa54dSGarrett D'Amore 	char		mbs[32];
310*538aa54dSGarrett D'Amore 	char		*dst;
311*538aa54dSGarrett D'Amore 	const wchar_t	*wcs;
312*538aa54dSGarrett D'Amore 	size_t 		cnt;
313*538aa54dSGarrett D'Amore 
314*538aa54dSGarrett D'Amore 
315*538aa54dSGarrett D'Amore 	(void) memset(&ms, 0, sizeof (ms));
316*538aa54dSGarrett D'Amore 	t = test_start("wcsrntombs_partial");
317*538aa54dSGarrett D'Amore 
318*538aa54dSGarrett D'Amore 	if (setlocale(LC_ALL, "ru_RU.UTF-8") == NULL) {
319*538aa54dSGarrett D'Amore 		test_failed(t, "setlocale failed: %s", strerror(errno));
320*538aa54dSGarrett D'Amore 	}
321*538aa54dSGarrett D'Amore 
322*538aa54dSGarrett D'Amore 	wcs = src;
323*538aa54dSGarrett D'Amore 	dst = mbs;
324*538aa54dSGarrett D'Amore 	cnt = wcsnrtombs(dst, &wcs, 1, 1, &ms);
325*538aa54dSGarrett D'Amore 	if (cnt != 0) {
326*538aa54dSGarrett D'Amore 		test_failed(t, "gave back a conversion cnt %d != 0", cnt);
327*538aa54dSGarrett D'Amore 	}
328*538aa54dSGarrett D'Amore 	if (wcs != src) {
329*538aa54dSGarrett D'Amore 		test_failed(t, "incorrectly advanced wcs");
330*538aa54dSGarrett D'Amore 	}
331*538aa54dSGarrett D'Amore 
332*538aa54dSGarrett D'Amore 	/* we should get just 2 wide characters (expanding to 4 bytes) */
333*538aa54dSGarrett D'Amore 	cnt = wcsnrtombs(dst, &wcs, 2, sizeof (mbs), &ms);
334*538aa54dSGarrett D'Amore 	if (cnt != 4) {
335*538aa54dSGarrett D'Amore 		test_failed(t, "gave back a conversion cnt %d != 4", cnt);
336*538aa54dSGarrett D'Amore 	}
337*538aa54dSGarrett D'Amore 	dst += cnt;
338*538aa54dSGarrett D'Amore 
339*538aa54dSGarrett D'Amore 	cnt = wcsnrtombs(dst, &wcs, 32, sizeof (mbs) - strlen(mbs), &ms);
340*538aa54dSGarrett D'Amore 	if (extra_debug) {
341*538aa54dSGarrett D'Amore 		test_debugf(t, "mbs is %s", mbs);
342*538aa54dSGarrett D'Amore 	}
343*538aa54dSGarrett D'Amore 	if (strcmp(mbs, HELLO_RU_MBS) != 0) {
344*538aa54dSGarrett D'Amore 		test_failed(t, "wrong result: %s != %s", mbs, HELLO_RU_MBS);
345*538aa54dSGarrett D'Amore 	}
346*538aa54dSGarrett D'Amore 	test_passed(t);
347*538aa54dSGarrett D'Amore }
348*538aa54dSGarrett D'Amore 
349*538aa54dSGarrett D'Amore void
test_wcsrtombs(void)350*538aa54dSGarrett D'Amore test_wcsrtombs(void)
351*538aa54dSGarrett D'Amore {
352*538aa54dSGarrett D'Amore 	for (int i = 0; locales[i].locale != NULL; i++) {
353*538aa54dSGarrett D'Amore 		test_wcsrtombs_1(locales[i].locale, locales[i].test);
354*538aa54dSGarrett D'Amore 		test_wcsrtombs_l(locales[i].locale, locales[i].test);
355*538aa54dSGarrett D'Amore 	}
356*538aa54dSGarrett D'Amore }
357*538aa54dSGarrett D'Amore 
358*538aa54dSGarrett D'Amore int
main(int argc,char ** argv)359*538aa54dSGarrett D'Amore main(int argc, char **argv)
360*538aa54dSGarrett D'Amore {
361*538aa54dSGarrett D'Amore 	int optc;
362*538aa54dSGarrett D'Amore 
363*538aa54dSGarrett D'Amore 	while ((optc = getopt(argc, argv, "dfD")) != EOF) {
364*538aa54dSGarrett D'Amore 		switch (optc) {
365*538aa54dSGarrett D'Amore 		case 'd':
366*538aa54dSGarrett D'Amore 			test_set_debug();
367*538aa54dSGarrett D'Amore 			break;
368*538aa54dSGarrett D'Amore 		case 'f':
369*538aa54dSGarrett D'Amore 			test_set_force();
370*538aa54dSGarrett D'Amore 			break;
371*538aa54dSGarrett D'Amore 		case 'D':
372*538aa54dSGarrett D'Amore 			test_set_debug();
373*538aa54dSGarrett D'Amore 			extra_debug++;
374*538aa54dSGarrett D'Amore 			break;
375*538aa54dSGarrett D'Amore 		default:
376*538aa54dSGarrett D'Amore 			(void) fprintf(stderr, "Usage: %s [-dfD]\n", argv[0]);
377*538aa54dSGarrett D'Amore 			exit(1);
378*538aa54dSGarrett D'Amore 		}
379*538aa54dSGarrett D'Amore 	}
380*538aa54dSGarrett D'Amore 
381*538aa54dSGarrett D'Amore 	test_wcsrtombs();
382*538aa54dSGarrett D'Amore 	test_wcsrtombs_partial();
383*538aa54dSGarrett D'Amore 	test_wcsrtombs_negative();
384*538aa54dSGarrett D'Amore 	test_wcsrtombs_threaded();
385*538aa54dSGarrett D'Amore 	test_wcsnrtombs_partial();
386*538aa54dSGarrett D'Amore 
387*538aa54dSGarrett D'Amore 	exit(0);
388*538aa54dSGarrett D'Amore }