1eda3ef2dSRobert Mustacchi /*
2eda3ef2dSRobert Mustacchi  * This file and its contents are supplied under the terms of the
3eda3ef2dSRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4eda3ef2dSRobert Mustacchi  * You may only use this file in accordance with the terms of version
5eda3ef2dSRobert Mustacchi  * 1.0 of the CDDL.
6eda3ef2dSRobert Mustacchi  *
7eda3ef2dSRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8eda3ef2dSRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9eda3ef2dSRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10eda3ef2dSRobert Mustacchi  */
11eda3ef2dSRobert Mustacchi 
12eda3ef2dSRobert Mustacchi /*
13eda3ef2dSRobert Mustacchi  * Copyright 2020 Robert Mustacchi
14eda3ef2dSRobert Mustacchi  */
15eda3ef2dSRobert Mustacchi 
16eda3ef2dSRobert Mustacchi /*
17eda3ef2dSRobert Mustacchi  * Test the implementation of various pieces of uchar.h(3HEAD) functionality.
18eda3ef2dSRobert Mustacchi  */
19eda3ef2dSRobert Mustacchi 
20eda3ef2dSRobert Mustacchi #include <locale.h>
21eda3ef2dSRobert Mustacchi #include <err.h>
22eda3ef2dSRobert Mustacchi #include <stdlib.h>
23eda3ef2dSRobert Mustacchi #include <sys/types.h>
24eda3ef2dSRobert Mustacchi #include <sys/sysmacros.h>
25eda3ef2dSRobert Mustacchi #include <strings.h>
26eda3ef2dSRobert Mustacchi #include <wchar.h>
27eda3ef2dSRobert Mustacchi #include <uchar.h>
28eda3ef2dSRobert Mustacchi #include <errno.h>
29eda3ef2dSRobert Mustacchi 
30eda3ef2dSRobert Mustacchi static const char *uchar_wide = "光";
31eda3ef2dSRobert Mustacchi static const char32_t uchar_value = 0x5149;
32eda3ef2dSRobert Mustacchi static const char *uchar_hello = "hello";
33eda3ef2dSRobert Mustacchi 
34eda3ef2dSRobert Mustacchi static void
update_locale(const char * loc)35eda3ef2dSRobert Mustacchi update_locale(const char *loc)
36eda3ef2dSRobert Mustacchi {
37eda3ef2dSRobert Mustacchi 	const char *newloc = setlocale(LC_CTYPE, loc);
38eda3ef2dSRobert Mustacchi 	if (newloc == NULL) {
39eda3ef2dSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: failed to update locale to %s",
40eda3ef2dSRobert Mustacchi 		    loc);
41eda3ef2dSRobert Mustacchi 	}
42eda3ef2dSRobert Mustacchi 
43eda3ef2dSRobert Mustacchi 	if (strcmp(newloc, loc) != 0) {
44eda3ef2dSRobert Mustacchi 		errx(EXIT_FAILURE, "TEST FAILED: locale set to %s, but got %s",
45eda3ef2dSRobert Mustacchi 		    loc, newloc);
46eda3ef2dSRobert Mustacchi 	}
47eda3ef2dSRobert Mustacchi }
48eda3ef2dSRobert Mustacchi 
49eda3ef2dSRobert Mustacchi static boolean_t
mbrtoc32_ascii(mbstate_t * mbs)50eda3ef2dSRobert Mustacchi mbrtoc32_ascii(mbstate_t *mbs)
51eda3ef2dSRobert Mustacchi {
52eda3ef2dSRobert Mustacchi 	char32_t out;
53eda3ef2dSRobert Mustacchi 	size_t len;
54eda3ef2dSRobert Mustacchi 	boolean_t ret = B_TRUE;
55eda3ef2dSRobert Mustacchi 
56eda3ef2dSRobert Mustacchi 	if ((len = mbrtoc32(&out, uchar_hello, 5, mbs)) != 1) {
57eda3ef2dSRobert Mustacchi 		warnx("expected mbrtoc32 to return 1, returned %zu", len);
58eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
59eda3ef2dSRobert Mustacchi 	}
60eda3ef2dSRobert Mustacchi 
61eda3ef2dSRobert Mustacchi 	if (out != 'h') {
62eda3ef2dSRobert Mustacchi 		warnx("got bad char32_t, expected 0x%x, found 0x%x\n", 'h',
63eda3ef2dSRobert Mustacchi 		    out);
64eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
65eda3ef2dSRobert Mustacchi 	}
66eda3ef2dSRobert Mustacchi 
67eda3ef2dSRobert Mustacchi 	if ((len = mbrtoc32(&out, uchar_hello + 1, 4, mbs)) != 1) {
68eda3ef2dSRobert Mustacchi 		warnx("expected mbrtoc32 to return 1, returned %zu", len);
69eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
70eda3ef2dSRobert Mustacchi 	}
71eda3ef2dSRobert Mustacchi 
72eda3ef2dSRobert Mustacchi 	if (out != 'e') {
73eda3ef2dSRobert Mustacchi 		warnx("got bad char32_t, expected 0x%x, found 0x%x\n", 'h',
74eda3ef2dSRobert Mustacchi 		    out);
75eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
76eda3ef2dSRobert Mustacchi 	}
77eda3ef2dSRobert Mustacchi 
78eda3ef2dSRobert Mustacchi 	return (ret);
79eda3ef2dSRobert Mustacchi }
80eda3ef2dSRobert Mustacchi 
81eda3ef2dSRobert Mustacchi static boolean_t
mbrtoc32_ascii_internal(void)82eda3ef2dSRobert Mustacchi mbrtoc32_ascii_internal(void)
83eda3ef2dSRobert Mustacchi {
84eda3ef2dSRobert Mustacchi 	return (mbrtoc32_ascii(NULL));
85eda3ef2dSRobert Mustacchi }
86eda3ef2dSRobert Mustacchi 
87eda3ef2dSRobert Mustacchi static boolean_t
mbrtoc32_ascii_mbstate(void)88eda3ef2dSRobert Mustacchi mbrtoc32_ascii_mbstate(void)
89eda3ef2dSRobert Mustacchi {
90eda3ef2dSRobert Mustacchi 	mbstate_t mbs;
91eda3ef2dSRobert Mustacchi 
92eda3ef2dSRobert Mustacchi 	bzero(&mbs, sizeof (mbs));
93eda3ef2dSRobert Mustacchi 	return (mbrtoc32_ascii(&mbs));
94eda3ef2dSRobert Mustacchi }
95eda3ef2dSRobert Mustacchi 
96eda3ef2dSRobert Mustacchi static boolean_t
mbrtoc32_badseq_utf8(void)97eda3ef2dSRobert Mustacchi mbrtoc32_badseq_utf8(void)
98eda3ef2dSRobert Mustacchi {
99eda3ef2dSRobert Mustacchi 	mbstate_t mbs;
100eda3ef2dSRobert Mustacchi 	size_t len;
101eda3ef2dSRobert Mustacchi 	char32_t out;
102eda3ef2dSRobert Mustacchi 	boolean_t ret = B_TRUE;
103eda3ef2dSRobert Mustacchi 	char *badstr;
104eda3ef2dSRobert Mustacchi 
105eda3ef2dSRobert Mustacchi 	bzero(&mbs, sizeof (mbs));
106eda3ef2dSRobert Mustacchi 	len = mbrtoc32(&out, "\xa9", 1, &mbs);
107eda3ef2dSRobert Mustacchi 	if (len != (size_t)-1) {
108eda3ef2dSRobert Mustacchi 		warnx("mbrtoc32 returned %zu, not %zu", len, (size_t)-1);
109eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
110eda3ef2dSRobert Mustacchi 	}
111eda3ef2dSRobert Mustacchi 
112eda3ef2dSRobert Mustacchi 	if (errno != EILSEQ) {
113eda3ef2dSRobert Mustacchi 		warnx("found bad errno, expected %d, found %d\n", errno,
114eda3ef2dSRobert Mustacchi 		    EILSEQ);
115eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
116eda3ef2dSRobert Mustacchi 	}
117eda3ef2dSRobert Mustacchi 
118eda3ef2dSRobert Mustacchi 	badstr = strdup(uchar_wide);
119eda3ef2dSRobert Mustacchi 	if (badstr == NULL) {
120eda3ef2dSRobert Mustacchi 		warn("failed to duplicate uchar_wide");
121eda3ef2dSRobert Mustacchi 		return (B_FALSE);
122eda3ef2dSRobert Mustacchi 	}
123eda3ef2dSRobert Mustacchi 
124eda3ef2dSRobert Mustacchi 	badstr[1] = '?';
125eda3ef2dSRobert Mustacchi 	bzero(&mbs, sizeof (mbs));
126eda3ef2dSRobert Mustacchi 	len = mbrtoc32(&out, badstr, strlen(badstr), &mbs);
127eda3ef2dSRobert Mustacchi 	free(badstr);
128eda3ef2dSRobert Mustacchi 	if (len != (size_t)-1) {
129eda3ef2dSRobert Mustacchi 		warnx("mbrtoc32 returned %zu, not %zu", len, (size_t)-1);
130eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
131eda3ef2dSRobert Mustacchi 	}
132eda3ef2dSRobert Mustacchi 
133eda3ef2dSRobert Mustacchi 	if (errno != EILSEQ) {
134eda3ef2dSRobert Mustacchi 		warnx("found bad errno, expected %d, found %d\n", errno,
135eda3ef2dSRobert Mustacchi 		    EILSEQ);
136eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
137eda3ef2dSRobert Mustacchi 	}
138eda3ef2dSRobert Mustacchi 
139eda3ef2dSRobert Mustacchi 	return (ret);
140eda3ef2dSRobert Mustacchi }
141eda3ef2dSRobert Mustacchi 
142eda3ef2dSRobert Mustacchi static boolean_t
mbrtoc32_roundtrip(void)143eda3ef2dSRobert Mustacchi mbrtoc32_roundtrip(void)
144eda3ef2dSRobert Mustacchi {
145eda3ef2dSRobert Mustacchi 	char32_t out;
146eda3ef2dSRobert Mustacchi 	size_t len, clen;
147eda3ef2dSRobert Mustacchi 	mbstate_t mbs;
148eda3ef2dSRobert Mustacchi 	char buf[MB_CUR_MAX];
149eda3ef2dSRobert Mustacchi 	boolean_t ret = B_TRUE;
150eda3ef2dSRobert Mustacchi 
151eda3ef2dSRobert Mustacchi 	bzero(&mbs, sizeof (mbs));
152eda3ef2dSRobert Mustacchi 	len = mbrtoc32(&out, uchar_wide, strlen(uchar_wide), &mbs);
153eda3ef2dSRobert Mustacchi 	if (len != 3) {
154eda3ef2dSRobert Mustacchi 		warnx("mbrtoc32 returned %zu, expected %u", len, 3);
155eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
156eda3ef2dSRobert Mustacchi 	}
157eda3ef2dSRobert Mustacchi 
158eda3ef2dSRobert Mustacchi 	if (out != uchar_value) {
159eda3ef2dSRobert Mustacchi 		warnx("mbrtoc32 converted character to 0x%x not 0x%x",
160eda3ef2dSRobert Mustacchi 		    out, uchar_value);
161eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
162eda3ef2dSRobert Mustacchi 	}
163eda3ef2dSRobert Mustacchi 
164eda3ef2dSRobert Mustacchi 	clen = c32rtomb(buf, out, &mbs);
165eda3ef2dSRobert Mustacchi 	if (clen != len) {
166*6353250fSRobert Mustacchi 		warnx("c32rtomb returned %zu bytes, but we originally used %zu",
167eda3ef2dSRobert Mustacchi 		    clen, len);
168eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
169eda3ef2dSRobert Mustacchi 	}
170eda3ef2dSRobert Mustacchi 
171eda3ef2dSRobert Mustacchi 	if (strncmp(buf, uchar_wide, len) != 0) {
172eda3ef2dSRobert Mustacchi 		warnx("round trip string comparison failed");
173eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
174eda3ef2dSRobert Mustacchi 	}
175eda3ef2dSRobert Mustacchi 
176eda3ef2dSRobert Mustacchi 	return (ret);
177eda3ef2dSRobert Mustacchi }
178eda3ef2dSRobert Mustacchi 
179eda3ef2dSRobert Mustacchi static boolean_t
mbrtoc32_partial(void)180eda3ef2dSRobert Mustacchi mbrtoc32_partial(void)
181eda3ef2dSRobert Mustacchi {
182eda3ef2dSRobert Mustacchi 	char32_t out;
183eda3ef2dSRobert Mustacchi 	size_t len, i;
184eda3ef2dSRobert Mustacchi 	mbstate_t mbs;
185eda3ef2dSRobert Mustacchi 	boolean_t ret = B_TRUE;
186eda3ef2dSRobert Mustacchi 
187eda3ef2dSRobert Mustacchi 	bzero(&mbs, sizeof (mbs));
188eda3ef2dSRobert Mustacchi 	for (i = 0; i < strlen(uchar_wide) - 1; i++) {
189eda3ef2dSRobert Mustacchi 		len = mbrtoc32(&out, uchar_wide + i, 1, &mbs);
190eda3ef2dSRobert Mustacchi 		if (len != (size_t)-2) {
191eda3ef2dSRobert Mustacchi 			warnx("partial mbrtoc32 returned %zu, not -2", len);
192eda3ef2dSRobert Mustacchi 			ret = B_FALSE;
193eda3ef2dSRobert Mustacchi 		}
194eda3ef2dSRobert Mustacchi 	}
195eda3ef2dSRobert Mustacchi 
196eda3ef2dSRobert Mustacchi 	len = mbrtoc32(&out, uchar_wide + i, 1, &mbs);
197eda3ef2dSRobert Mustacchi 	if (len != 1) {
198eda3ef2dSRobert Mustacchi 		warnx("partial mbrtoc32 returned %zu, not 1", len);
199eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
200eda3ef2dSRobert Mustacchi 	}
201eda3ef2dSRobert Mustacchi 
202eda3ef2dSRobert Mustacchi 	if (out != uchar_value) {
203eda3ef2dSRobert Mustacchi 		warnx("mbrtoc32 converted character to 0x%x not 0x%x",
204eda3ef2dSRobert Mustacchi 		    out, uchar_value);
205eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
206eda3ef2dSRobert Mustacchi 	}
207eda3ef2dSRobert Mustacchi 
208eda3ef2dSRobert Mustacchi 	return (ret);
209eda3ef2dSRobert Mustacchi }
210eda3ef2dSRobert Mustacchi 
211eda3ef2dSRobert Mustacchi static boolean_t
mbrtoc32_zero(void)212eda3ef2dSRobert Mustacchi mbrtoc32_zero(void)
213eda3ef2dSRobert Mustacchi {
214eda3ef2dSRobert Mustacchi 	char32_t out, exp = L'\0';
215eda3ef2dSRobert Mustacchi 	size_t len;
216eda3ef2dSRobert Mustacchi 	mbstate_t mbs;
217eda3ef2dSRobert Mustacchi 	boolean_t ret = B_TRUE;
218eda3ef2dSRobert Mustacchi 
219eda3ef2dSRobert Mustacchi 	bzero(&mbs, sizeof (mbs));
220eda3ef2dSRobert Mustacchi 	len = mbrtoc32(&out, "", 1, &mbs);
221eda3ef2dSRobert Mustacchi 	if (len != 0) {
222eda3ef2dSRobert Mustacchi 		warnx("partial mbrtoc32 returned %zu, not 0", len);
223eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
224eda3ef2dSRobert Mustacchi 	}
225eda3ef2dSRobert Mustacchi 
226eda3ef2dSRobert Mustacchi 	if (out != exp) {
227eda3ef2dSRobert Mustacchi 		warnx("mbrtoc32 converted character to 0x%x not 0x%x",
228eda3ef2dSRobert Mustacchi 		    out, exp);
229eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
230eda3ef2dSRobert Mustacchi 	}
231eda3ef2dSRobert Mustacchi 
232eda3ef2dSRobert Mustacchi 	return (ret);
233eda3ef2dSRobert Mustacchi }
234eda3ef2dSRobert Mustacchi 
235eda3ef2dSRobert Mustacchi static boolean_t
mbrtoc32_zero_len(void)236eda3ef2dSRobert Mustacchi mbrtoc32_zero_len(void)
237eda3ef2dSRobert Mustacchi {
238eda3ef2dSRobert Mustacchi 	char32_t out = 0x12345, exp = 0x12345;
239eda3ef2dSRobert Mustacchi 	size_t len;
240eda3ef2dSRobert Mustacchi 	mbstate_t mbs;
241eda3ef2dSRobert Mustacchi 	boolean_t ret = B_TRUE;
242eda3ef2dSRobert Mustacchi 
243eda3ef2dSRobert Mustacchi 	bzero(&mbs, sizeof (mbs));
244eda3ef2dSRobert Mustacchi 	len = mbrtoc32(&out, uchar_wide, 0, &mbs);
245eda3ef2dSRobert Mustacchi 	if (len != (size_t)-2) {
246eda3ef2dSRobert Mustacchi 		warnx("partial mbrtoc32 returned %zu, not -2", len);
247eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
248eda3ef2dSRobert Mustacchi 	}
249eda3ef2dSRobert Mustacchi 
250eda3ef2dSRobert Mustacchi 	if (out != exp) {
251eda3ef2dSRobert Mustacchi 		warnx("mbrtoc32 incorrectly wrote to char32_t value with "
252eda3ef2dSRobert Mustacchi 		    "zero string, found 0x%x not 0x%x", out, exp);
253eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
254eda3ef2dSRobert Mustacchi 	}
255eda3ef2dSRobert Mustacchi 
256eda3ef2dSRobert Mustacchi 	return (ret);
257eda3ef2dSRobert Mustacchi }
258eda3ef2dSRobert Mustacchi 
259eda3ef2dSRobert Mustacchi static boolean_t
mbrtoc32_null(void)260eda3ef2dSRobert Mustacchi mbrtoc32_null(void)
261eda3ef2dSRobert Mustacchi {
262eda3ef2dSRobert Mustacchi 	char32_t out = 0x123456, exp = 0x123456;
263eda3ef2dSRobert Mustacchi 	size_t len;
264eda3ef2dSRobert Mustacchi 	mbstate_t mbs;
265eda3ef2dSRobert Mustacchi 	boolean_t ret = B_TRUE;
266eda3ef2dSRobert Mustacchi 
267eda3ef2dSRobert Mustacchi 	bzero(&mbs, sizeof (mbs));
268eda3ef2dSRobert Mustacchi 	len = mbrtoc32(&out, NULL, 1, &mbs);
269eda3ef2dSRobert Mustacchi 	if (len != 0) {
270eda3ef2dSRobert Mustacchi 		warnx("partial mbrtoc32 returned %zu, not 0", len);
271eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
272eda3ef2dSRobert Mustacchi 	}
273eda3ef2dSRobert Mustacchi 
274eda3ef2dSRobert Mustacchi 	if (out != exp) {
275eda3ef2dSRobert Mustacchi 		warnx("mbrtoc32 incorrectly wrote to char32_t value with "
276eda3ef2dSRobert Mustacchi 		    "null string, found 0x%x not 0x%x", out, exp);
277eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
278eda3ef2dSRobert Mustacchi 	}
279eda3ef2dSRobert Mustacchi 
280eda3ef2dSRobert Mustacchi 	return (ret);
281eda3ef2dSRobert Mustacchi }
282eda3ef2dSRobert Mustacchi 
283eda3ef2dSRobert Mustacchi static boolean_t
mbrtoc16_ascii(mbstate_t * mbs)284eda3ef2dSRobert Mustacchi mbrtoc16_ascii(mbstate_t *mbs)
285eda3ef2dSRobert Mustacchi {
286eda3ef2dSRobert Mustacchi 	char16_t out;
287eda3ef2dSRobert Mustacchi 	size_t len;
288eda3ef2dSRobert Mustacchi 	boolean_t ret = B_TRUE;
289eda3ef2dSRobert Mustacchi 
290eda3ef2dSRobert Mustacchi 	if ((len = mbrtoc16(&out, uchar_hello, 5, mbs)) != 1) {
291eda3ef2dSRobert Mustacchi 		warnx("expected mbrtoc16 to return 1, returned %zu", len);
292eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
293eda3ef2dSRobert Mustacchi 	}
294eda3ef2dSRobert Mustacchi 
295eda3ef2dSRobert Mustacchi 	if (out != 'h') {
296eda3ef2dSRobert Mustacchi 		warnx("got bad char16_t, expected 0x%x, found 0x%x\n", 'h',
297eda3ef2dSRobert Mustacchi 		    out);
298eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
299eda3ef2dSRobert Mustacchi 	}
300eda3ef2dSRobert Mustacchi 
301eda3ef2dSRobert Mustacchi 	if ((len = mbrtoc16(&out, uchar_hello + 1, 4, mbs)) != 1) {
302eda3ef2dSRobert Mustacchi 		warnx("expected mbrtoc16 to return 1, returned %zu", len);
303eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
304eda3ef2dSRobert Mustacchi 	}
305eda3ef2dSRobert Mustacchi 
306eda3ef2dSRobert Mustacchi 	if (out != 'e') {
307eda3ef2dSRobert Mustacchi 		warnx("got bad char16_t, expected 0x%x, found 0x%x\n", 'h',
308eda3ef2dSRobert Mustacchi 		    out);
309eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
310eda3ef2dSRobert Mustacchi 	}
311eda3ef2dSRobert Mustacchi 
312eda3ef2dSRobert Mustacchi 	return (ret);
313eda3ef2dSRobert Mustacchi }
314eda3ef2dSRobert Mustacchi 
315eda3ef2dSRobert Mustacchi static boolean_t
mbrtoc16_ascii_internal(void)316eda3ef2dSRobert Mustacchi mbrtoc16_ascii_internal(void)
317eda3ef2dSRobert Mustacchi {
318eda3ef2dSRobert Mustacchi 	return (mbrtoc16_ascii(NULL));
319eda3ef2dSRobert Mustacchi }
320eda3ef2dSRobert Mustacchi 
321eda3ef2dSRobert Mustacchi static boolean_t
mbrtoc16_ascii_mbstate(void)322eda3ef2dSRobert Mustacchi mbrtoc16_ascii_mbstate(void)
323eda3ef2dSRobert Mustacchi {
324eda3ef2dSRobert Mustacchi 	mbstate_t mbs;
325eda3ef2dSRobert Mustacchi 
326eda3ef2dSRobert Mustacchi 	bzero(&mbs, sizeof (mbs));
327eda3ef2dSRobert Mustacchi 	return (mbrtoc16_ascii(&mbs));
328eda3ef2dSRobert Mustacchi }
329eda3ef2dSRobert Mustacchi 
330eda3ef2dSRobert Mustacchi static boolean_t
mbrtoc16_null(void)331eda3ef2dSRobert Mustacchi mbrtoc16_null(void)
332eda3ef2dSRobert Mustacchi {
333eda3ef2dSRobert Mustacchi 	char16_t out = 0x1234, exp = 0x1234;
334eda3ef2dSRobert Mustacchi 	size_t len;
335eda3ef2dSRobert Mustacchi 	mbstate_t mbs;
336eda3ef2dSRobert Mustacchi 	boolean_t ret = B_TRUE;
337eda3ef2dSRobert Mustacchi 
338eda3ef2dSRobert Mustacchi 	bzero(&mbs, sizeof (mbs));
339eda3ef2dSRobert Mustacchi 	len = mbrtoc16(&out, NULL, 1, &mbs);
340eda3ef2dSRobert Mustacchi 	if (len != 0) {
341eda3ef2dSRobert Mustacchi 		warnx("partial mbrtoc16 returned %zu, not 0", len);
342eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
343eda3ef2dSRobert Mustacchi 	}
344eda3ef2dSRobert Mustacchi 
345eda3ef2dSRobert Mustacchi 	if (out != exp) {
346eda3ef2dSRobert Mustacchi 		warnx("mbrtoc16 incorrectly wrote to char16_t value with "
347eda3ef2dSRobert Mustacchi 		    "null string, found 0x%x not 0x%x", out, exp);
348eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
349eda3ef2dSRobert Mustacchi 	}
350eda3ef2dSRobert Mustacchi 
351eda3ef2dSRobert Mustacchi 	return (ret);
352eda3ef2dSRobert Mustacchi }
353eda3ef2dSRobert Mustacchi 
354eda3ef2dSRobert Mustacchi static boolean_t
mbrtoc16_zero(void)355eda3ef2dSRobert Mustacchi mbrtoc16_zero(void)
356eda3ef2dSRobert Mustacchi {
357eda3ef2dSRobert Mustacchi 	char16_t out, exp = L'\0';
358eda3ef2dSRobert Mustacchi 	size_t len;
359eda3ef2dSRobert Mustacchi 	mbstate_t mbs;
360eda3ef2dSRobert Mustacchi 	boolean_t ret = B_TRUE;
361eda3ef2dSRobert Mustacchi 
362eda3ef2dSRobert Mustacchi 	bzero(&mbs, sizeof (mbs));
363eda3ef2dSRobert Mustacchi 	len = mbrtoc16(&out, "", 1, &mbs);
364eda3ef2dSRobert Mustacchi 	if (len != 0) {
365eda3ef2dSRobert Mustacchi 		warnx("partial mbrtoc16 returned %zu, not 0", len);
366eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
367eda3ef2dSRobert Mustacchi 	}
368eda3ef2dSRobert Mustacchi 
369eda3ef2dSRobert Mustacchi 	if (out != exp) {
370eda3ef2dSRobert Mustacchi 		warnx("mbrtoc16 converted character to 0x%x not 0x%x",
371eda3ef2dSRobert Mustacchi 		    out, exp);
372eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
373eda3ef2dSRobert Mustacchi 	}
374eda3ef2dSRobert Mustacchi 
375eda3ef2dSRobert Mustacchi 	return (ret);
376eda3ef2dSRobert Mustacchi }
377eda3ef2dSRobert Mustacchi 
378eda3ef2dSRobert Mustacchi static boolean_t
mbrtoc16_zero_len(void)379eda3ef2dSRobert Mustacchi mbrtoc16_zero_len(void)
380eda3ef2dSRobert Mustacchi {
381eda3ef2dSRobert Mustacchi 	char16_t out = 0x5432, exp = 0x5432;
382eda3ef2dSRobert Mustacchi 	size_t len;
383eda3ef2dSRobert Mustacchi 	mbstate_t mbs;
384eda3ef2dSRobert Mustacchi 	boolean_t ret = B_TRUE;
385eda3ef2dSRobert Mustacchi 
386eda3ef2dSRobert Mustacchi 	bzero(&mbs, sizeof (mbs));
387eda3ef2dSRobert Mustacchi 	len = mbrtoc16(&out, uchar_wide, 0, &mbs);
388eda3ef2dSRobert Mustacchi 	if (len != (size_t)-2) {
389eda3ef2dSRobert Mustacchi 		warnx("partial mbrtoc16 returned %zu, not -2", len);
390eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
391eda3ef2dSRobert Mustacchi 	}
392eda3ef2dSRobert Mustacchi 
393eda3ef2dSRobert Mustacchi 	if (out != exp) {
394eda3ef2dSRobert Mustacchi 		warnx("mbrtoc16 incorrectly wrote to char16_t value with "
395eda3ef2dSRobert Mustacchi 		    "zero length string, found 0x%x not 0x%x", out, exp);
396eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
397eda3ef2dSRobert Mustacchi 	}
398eda3ef2dSRobert Mustacchi 
399eda3ef2dSRobert Mustacchi 	return (ret);
400eda3ef2dSRobert Mustacchi }
401eda3ef2dSRobert Mustacchi 
402eda3ef2dSRobert Mustacchi static boolean_t
mbrtoc16_roundtrip(void)403eda3ef2dSRobert Mustacchi mbrtoc16_roundtrip(void)
404eda3ef2dSRobert Mustacchi {
405eda3ef2dSRobert Mustacchi 	char16_t out;
406eda3ef2dSRobert Mustacchi 	size_t len, clen;
407eda3ef2dSRobert Mustacchi 	mbstate_t mbs;
408eda3ef2dSRobert Mustacchi 	char buf[MB_CUR_MAX];
409eda3ef2dSRobert Mustacchi 	boolean_t ret = B_TRUE;
410eda3ef2dSRobert Mustacchi 
411eda3ef2dSRobert Mustacchi 	bzero(&mbs, sizeof (mbs));
412eda3ef2dSRobert Mustacchi 	len = mbrtoc16(&out, uchar_wide, strlen(uchar_wide), &mbs);
413eda3ef2dSRobert Mustacchi 	if (len != 3) {
414eda3ef2dSRobert Mustacchi 		warnx("mbrtoc16 returned %zu, expected %u", len, 3);
415eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
416eda3ef2dSRobert Mustacchi 	}
417eda3ef2dSRobert Mustacchi 
418eda3ef2dSRobert Mustacchi 	if (out != uchar_value) {
419eda3ef2dSRobert Mustacchi 		warnx("mbrtoc16 converted character to 0x%x not 0x%x",
420eda3ef2dSRobert Mustacchi 		    out, uchar_value);
421eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
422eda3ef2dSRobert Mustacchi 	}
423eda3ef2dSRobert Mustacchi 
424eda3ef2dSRobert Mustacchi 	clen = c16rtomb(buf, out, &mbs);
425eda3ef2dSRobert Mustacchi 	if (clen != len) {
426*6353250fSRobert Mustacchi 		warnx("c16rtomb returned %zu bytes, but we originally used %zu",
427eda3ef2dSRobert Mustacchi 		    clen, len);
428eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
429eda3ef2dSRobert Mustacchi 	}
430eda3ef2dSRobert Mustacchi 
431eda3ef2dSRobert Mustacchi 	if (strncmp(buf, uchar_wide, len) != 0) {
432eda3ef2dSRobert Mustacchi 		warnx("round trip string comparison failed");
433eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
434eda3ef2dSRobert Mustacchi 	}
435eda3ef2dSRobert Mustacchi 
436eda3ef2dSRobert Mustacchi 	return (ret);
437eda3ef2dSRobert Mustacchi }
438eda3ef2dSRobert Mustacchi 
439eda3ef2dSRobert Mustacchi static boolean_t
mbrtoc16_partial(void)440eda3ef2dSRobert Mustacchi mbrtoc16_partial(void)
441eda3ef2dSRobert Mustacchi {
442eda3ef2dSRobert Mustacchi 	char16_t out;
443eda3ef2dSRobert Mustacchi 	size_t len, i;
444eda3ef2dSRobert Mustacchi 	mbstate_t mbs;
445eda3ef2dSRobert Mustacchi 	boolean_t ret = B_TRUE;
446eda3ef2dSRobert Mustacchi 
447eda3ef2dSRobert Mustacchi 	bzero(&mbs, sizeof (mbs));
448eda3ef2dSRobert Mustacchi 	for (i = 0; i < strlen(uchar_wide) - 1; i++) {
449eda3ef2dSRobert Mustacchi 		len = mbrtoc16(&out, uchar_wide + i, 1, &mbs);
450eda3ef2dSRobert Mustacchi 		if (len != (size_t)-2) {
451eda3ef2dSRobert Mustacchi 			warnx("partial mbrtoc16 returned %zu, not -2", len);
452eda3ef2dSRobert Mustacchi 			ret = B_FALSE;
453eda3ef2dSRobert Mustacchi 		}
454eda3ef2dSRobert Mustacchi 	}
455eda3ef2dSRobert Mustacchi 
456eda3ef2dSRobert Mustacchi 	len = mbrtoc16(&out, uchar_wide + i, 1, &mbs);
457eda3ef2dSRobert Mustacchi 	if (len != 1) {
458eda3ef2dSRobert Mustacchi 		warnx("partial mbrtoc16 returned %zu, not 1", len);
459eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
460eda3ef2dSRobert Mustacchi 	}
461eda3ef2dSRobert Mustacchi 
462eda3ef2dSRobert Mustacchi 	if (out != uchar_value) {
463eda3ef2dSRobert Mustacchi 		warnx("mbrtoc16 converted character to 0x%x not 0x%x",
464eda3ef2dSRobert Mustacchi 		    out, uchar_value);
465eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
466eda3ef2dSRobert Mustacchi 	}
467eda3ef2dSRobert Mustacchi 
468eda3ef2dSRobert Mustacchi 	return (ret);
469eda3ef2dSRobert Mustacchi }
470eda3ef2dSRobert Mustacchi 
471eda3ef2dSRobert Mustacchi static boolean_t
mbrtoc16_surrogate(void)472eda3ef2dSRobert Mustacchi mbrtoc16_surrogate(void)
473eda3ef2dSRobert Mustacchi {
474eda3ef2dSRobert Mustacchi 	char16_t out0, out1;
475eda3ef2dSRobert Mustacchi 	size_t len, clen;
476eda3ef2dSRobert Mustacchi 	mbstate_t mbs;
477eda3ef2dSRobert Mustacchi 	const char *surrogate = "\xF0\x9F\x92\xA9";
478eda3ef2dSRobert Mustacchi 	char16_t exp0 = 0xd83d, exp1 = 0xdca9;
479eda3ef2dSRobert Mustacchi 	size_t slen = strlen(surrogate);
480eda3ef2dSRobert Mustacchi 	boolean_t ret = B_TRUE;
481eda3ef2dSRobert Mustacchi 	char buf[MB_CUR_MAX];
482eda3ef2dSRobert Mustacchi 
483eda3ef2dSRobert Mustacchi 	bzero(&mbs, sizeof (mbs));
484eda3ef2dSRobert Mustacchi 	len = mbrtoc16(&out0, surrogate, slen, &mbs);
485eda3ef2dSRobert Mustacchi 	if (len != slen) {
486*6353250fSRobert Mustacchi 		warnx("mbrtoc16 returned %zu, expected %zu", len, slen);
487eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
488eda3ef2dSRobert Mustacchi 	}
489eda3ef2dSRobert Mustacchi 
490eda3ef2dSRobert Mustacchi 	if (out0 != exp0) {
491eda3ef2dSRobert Mustacchi 		warnx("mbrtoc16 converted character to 0x%x not 0x%x",
492eda3ef2dSRobert Mustacchi 		    out0, exp0);
493eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
494eda3ef2dSRobert Mustacchi 	}
495eda3ef2dSRobert Mustacchi 
496eda3ef2dSRobert Mustacchi 	if (mbsinit(&mbs) != 0) {
497eda3ef2dSRobert Mustacchi 		warnx("mb state with a surrogate character is somehow in the "
498eda3ef2dSRobert Mustacchi 		    "initial state");
499eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
500eda3ef2dSRobert Mustacchi 	}
501eda3ef2dSRobert Mustacchi 
502eda3ef2dSRobert Mustacchi 	len = mbrtoc16(&out1, uchar_wide, strlen(uchar_wide), &mbs);
503eda3ef2dSRobert Mustacchi 	if (len != (size_t)-3) {
504eda3ef2dSRobert Mustacchi 		warnx("mbrtoc16 returned %zu, expected -3", len);
505eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
506eda3ef2dSRobert Mustacchi 	}
507eda3ef2dSRobert Mustacchi 
508eda3ef2dSRobert Mustacchi 	if (mbsinit(&mbs) == 0) {
509eda3ef2dSRobert Mustacchi 		warnx("mb state with after both surrogate characters isn't "
510eda3ef2dSRobert Mustacchi 		    "in initial state");
511eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
512eda3ef2dSRobert Mustacchi 	}
513eda3ef2dSRobert Mustacchi 
514eda3ef2dSRobert Mustacchi 	if (out1 != exp1) {
515eda3ef2dSRobert Mustacchi 		warnx("mbrtoc32 converted character to 0x%x not 0x%x",
516eda3ef2dSRobert Mustacchi 		    out1, exp1);
517eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
518eda3ef2dSRobert Mustacchi 	}
519eda3ef2dSRobert Mustacchi 
520eda3ef2dSRobert Mustacchi 	clen = c16rtomb(buf, out0, &mbs);
521eda3ef2dSRobert Mustacchi 	if (clen != 0) {
522*6353250fSRobert Mustacchi 		warnx("c16rtomb returned %zu bytes, but expected zero for the "
523eda3ef2dSRobert Mustacchi 		    "first surrogate", clen);
524eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
525eda3ef2dSRobert Mustacchi 	}
526eda3ef2dSRobert Mustacchi 
527eda3ef2dSRobert Mustacchi 	if (mbsinit(&mbs) != 0) {
528eda3ef2dSRobert Mustacchi 		warnx("mb state with a surrogate character is somehow in the "
529eda3ef2dSRobert Mustacchi 		    "initial state");
530eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
531eda3ef2dSRobert Mustacchi 	}
532eda3ef2dSRobert Mustacchi 
533eda3ef2dSRobert Mustacchi 	clen = c16rtomb(buf, out1, &mbs);
534eda3ef2dSRobert Mustacchi 	if (clen != slen) {
535*6353250fSRobert Mustacchi 		warnx("c16rtomb returned %zu, expected %zu", len, slen);
536eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
537eda3ef2dSRobert Mustacchi 	}
538eda3ef2dSRobert Mustacchi 
539eda3ef2dSRobert Mustacchi 	if (mbsinit(&mbs) == 0) {
540eda3ef2dSRobert Mustacchi 		warnx("mb state with after both surrogate characters isn't "
541eda3ef2dSRobert Mustacchi 		    "in initial state");
542eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
543eda3ef2dSRobert Mustacchi 	}
544eda3ef2dSRobert Mustacchi 
545eda3ef2dSRobert Mustacchi 	if (strncmp(buf, surrogate, slen) != 0) {
546eda3ef2dSRobert Mustacchi 		warnx("round trip string comparison failed");
547eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
548eda3ef2dSRobert Mustacchi 	}
549eda3ef2dSRobert Mustacchi 
550eda3ef2dSRobert Mustacchi 	return (ret);
551eda3ef2dSRobert Mustacchi }
552eda3ef2dSRobert Mustacchi 
553eda3ef2dSRobert Mustacchi static boolean_t
c32rtomb_eilseq_iso8859(void)554eda3ef2dSRobert Mustacchi c32rtomb_eilseq_iso8859(void)
555eda3ef2dSRobert Mustacchi {
556eda3ef2dSRobert Mustacchi 	char buf[MB_CUR_MAX];
557eda3ef2dSRobert Mustacchi 	mbstate_t mbs;
558eda3ef2dSRobert Mustacchi 	size_t len;
559eda3ef2dSRobert Mustacchi 	boolean_t ret = B_TRUE;
560eda3ef2dSRobert Mustacchi 
561eda3ef2dSRobert Mustacchi 	bzero(&mbs, sizeof (mbs));
562eda3ef2dSRobert Mustacchi 	len = c32rtomb(buf, uchar_value, &mbs);
563eda3ef2dSRobert Mustacchi 	if (len != (size_t)-1) {
564eda3ef2dSRobert Mustacchi 		warnx("c32rtomb returned %zd, expected -1\n", len);
565eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
566eda3ef2dSRobert Mustacchi 	}
567eda3ef2dSRobert Mustacchi 
568eda3ef2dSRobert Mustacchi 	if (errno != EILSEQ) {
569eda3ef2dSRobert Mustacchi 		warnx("expected errno set to %d was %d", EILSEQ, errno);
570eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
571eda3ef2dSRobert Mustacchi 	}
572eda3ef2dSRobert Mustacchi 
573eda3ef2dSRobert Mustacchi 	return (ret);
574eda3ef2dSRobert Mustacchi }
575eda3ef2dSRobert Mustacchi 
576eda3ef2dSRobert Mustacchi static boolean_t
c16rtomb_eilseq_iso8859(void)577eda3ef2dSRobert Mustacchi c16rtomb_eilseq_iso8859(void)
578eda3ef2dSRobert Mustacchi {
579eda3ef2dSRobert Mustacchi 	char buf[MB_CUR_MAX];
580eda3ef2dSRobert Mustacchi 	mbstate_t mbs;
581eda3ef2dSRobert Mustacchi 	size_t len;
582eda3ef2dSRobert Mustacchi 	boolean_t ret = B_TRUE;
583eda3ef2dSRobert Mustacchi 
584eda3ef2dSRobert Mustacchi 	bzero(&mbs, sizeof (mbs));
585eda3ef2dSRobert Mustacchi 	len = c32rtomb(buf, (char16_t)uchar_value, &mbs);
586eda3ef2dSRobert Mustacchi 	if (len != (size_t)-1) {
587eda3ef2dSRobert Mustacchi 		warnx("c32rtomb returned %zd, expected -1\n", len);
588eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
589eda3ef2dSRobert Mustacchi 	}
590eda3ef2dSRobert Mustacchi 
591eda3ef2dSRobert Mustacchi 	if (errno != EILSEQ) {
592eda3ef2dSRobert Mustacchi 		warnx("expected errno set to %d was %d", EILSEQ, errno);
593eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
594eda3ef2dSRobert Mustacchi 	}
595eda3ef2dSRobert Mustacchi 
596eda3ef2dSRobert Mustacchi 	return (ret);
597eda3ef2dSRobert Mustacchi }
598eda3ef2dSRobert Mustacchi 
599eda3ef2dSRobert Mustacchi static boolean_t
c32rtomb_eilseq_utf8(void)600eda3ef2dSRobert Mustacchi c32rtomb_eilseq_utf8(void)
601eda3ef2dSRobert Mustacchi {
602eda3ef2dSRobert Mustacchi 	char buf[MB_CUR_MAX];
603eda3ef2dSRobert Mustacchi 	mbstate_t mbs;
604eda3ef2dSRobert Mustacchi 	size_t len;
605eda3ef2dSRobert Mustacchi 	boolean_t ret = B_TRUE;
606eda3ef2dSRobert Mustacchi 
607eda3ef2dSRobert Mustacchi 	bzero(&mbs, sizeof (mbs));
608eda3ef2dSRobert Mustacchi 	len = c32rtomb(buf, UINT32_MAX, &mbs);
609eda3ef2dSRobert Mustacchi 	if (len != (size_t)-1) {
610eda3ef2dSRobert Mustacchi 		warnx("c32rtomb returned %zd, expected -1\n", len);
611eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
612eda3ef2dSRobert Mustacchi 	}
613eda3ef2dSRobert Mustacchi 
614eda3ef2dSRobert Mustacchi 	if (errno != EILSEQ) {
615eda3ef2dSRobert Mustacchi 		warnx("expected errno set to %d was %d", EILSEQ, errno);
616eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
617eda3ef2dSRobert Mustacchi 	}
618eda3ef2dSRobert Mustacchi 
619eda3ef2dSRobert Mustacchi 	return (ret);
620eda3ef2dSRobert Mustacchi }
621eda3ef2dSRobert Mustacchi 
622eda3ef2dSRobert Mustacchi static boolean_t
c16rtomb_bad_first(void)623eda3ef2dSRobert Mustacchi c16rtomb_bad_first(void)
624eda3ef2dSRobert Mustacchi {
625eda3ef2dSRobert Mustacchi 	char buf[MB_CUR_MAX];
626eda3ef2dSRobert Mustacchi 	mbstate_t mbs;
627eda3ef2dSRobert Mustacchi 	size_t len, i;
628eda3ef2dSRobert Mustacchi 	char16_t first = 0xd83d;
629eda3ef2dSRobert Mustacchi 	char16_t bad[] = { 0x0, 0xd7ff, 0xd83d, 0xd900, 0xffff };
630eda3ef2dSRobert Mustacchi 	boolean_t ret = B_TRUE;
631eda3ef2dSRobert Mustacchi 
632eda3ef2dSRobert Mustacchi 	for (i = 0; i < ARRAY_SIZE(bad); i++) {
633eda3ef2dSRobert Mustacchi 		bzero(&mbs, sizeof (mbs));
634eda3ef2dSRobert Mustacchi 		len = c16rtomb(buf, first, &mbs);
635eda3ef2dSRobert Mustacchi 		if (len != 0) {
636eda3ef2dSRobert Mustacchi 			warnx("c16rtomb returned %zd, expected 0\n", len);
637eda3ef2dSRobert Mustacchi 			ret = B_FALSE;
638eda3ef2dSRobert Mustacchi 		}
639eda3ef2dSRobert Mustacchi 
640eda3ef2dSRobert Mustacchi 		len = c16rtomb(buf, bad[i], &mbs);
641eda3ef2dSRobert Mustacchi 		if (len != (size_t)-1) {
642eda3ef2dSRobert Mustacchi 			warnx("c16rtomb surrogate %x returned %zd, expected "
643eda3ef2dSRobert Mustacchi 			    "-1\n", bad[i], len);
644eda3ef2dSRobert Mustacchi 			ret = B_FALSE;
645eda3ef2dSRobert Mustacchi 		}
646eda3ef2dSRobert Mustacchi 
647eda3ef2dSRobert Mustacchi 		if (errno != EILSEQ) {
648eda3ef2dSRobert Mustacchi 			warnx("expected errno set to %d was %d", EILSEQ, errno);
649eda3ef2dSRobert Mustacchi 			ret = B_FALSE;
650eda3ef2dSRobert Mustacchi 		}
651eda3ef2dSRobert Mustacchi 	}
652eda3ef2dSRobert Mustacchi 
653eda3ef2dSRobert Mustacchi 	return (ret);
654eda3ef2dSRobert Mustacchi }
655eda3ef2dSRobert Mustacchi 
656eda3ef2dSRobert Mustacchi static boolean_t
c16rtomb_bad_second(void)657eda3ef2dSRobert Mustacchi c16rtomb_bad_second(void)
658eda3ef2dSRobert Mustacchi {
659eda3ef2dSRobert Mustacchi 	char buf[MB_CUR_MAX];
660eda3ef2dSRobert Mustacchi 	mbstate_t mbs;
661eda3ef2dSRobert Mustacchi 	size_t len, i;
662eda3ef2dSRobert Mustacchi 	char16_t bad[] = { 0xdc00, 0xdd34, 0xdfff };
663eda3ef2dSRobert Mustacchi 	boolean_t ret = B_TRUE;
664eda3ef2dSRobert Mustacchi 
665eda3ef2dSRobert Mustacchi 	for (i = 0; i < ARRAY_SIZE(bad); i++) {
666eda3ef2dSRobert Mustacchi 		bzero(&mbs, sizeof (mbs));
667eda3ef2dSRobert Mustacchi 		len = c16rtomb(buf, bad[i], &mbs);
668eda3ef2dSRobert Mustacchi 		if (len != (size_t)-1) {
669eda3ef2dSRobert Mustacchi 			warnx("c16rtomb surrogate %x returned %zd, expected "
670eda3ef2dSRobert Mustacchi 			    "-1\n", bad[i], len);
671eda3ef2dSRobert Mustacchi 			ret = B_FALSE;
672eda3ef2dSRobert Mustacchi 		}
673eda3ef2dSRobert Mustacchi 
674eda3ef2dSRobert Mustacchi 		if (errno != EILSEQ) {
675eda3ef2dSRobert Mustacchi 			warnx("expected errno set to %d was %d", EILSEQ, errno);
676eda3ef2dSRobert Mustacchi 			ret = B_FALSE;
677eda3ef2dSRobert Mustacchi 		}
678eda3ef2dSRobert Mustacchi 	}
679eda3ef2dSRobert Mustacchi 
680eda3ef2dSRobert Mustacchi 	return (ret);
681eda3ef2dSRobert Mustacchi }
682eda3ef2dSRobert Mustacchi 
683eda3ef2dSRobert Mustacchi static boolean_t
c32rtomb_null(void)684eda3ef2dSRobert Mustacchi c32rtomb_null(void)
685eda3ef2dSRobert Mustacchi {
686eda3ef2dSRobert Mustacchi 	size_t len;
687eda3ef2dSRobert Mustacchi 	mbstate_t mbs;
688eda3ef2dSRobert Mustacchi 	boolean_t ret = B_TRUE;
689eda3ef2dSRobert Mustacchi 
690eda3ef2dSRobert Mustacchi 	bzero(&mbs, sizeof (mbs));
691eda3ef2dSRobert Mustacchi 	len = c32rtomb(NULL, uchar_value, &mbs);
692eda3ef2dSRobert Mustacchi 	if (len != 1) {
693*6353250fSRobert Mustacchi 		warnx("c32rtomb returned %zu, expected %d", len, 1);
694eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
695eda3ef2dSRobert Mustacchi 	}
696eda3ef2dSRobert Mustacchi 
697eda3ef2dSRobert Mustacchi 	return (ret);
698eda3ef2dSRobert Mustacchi }
699eda3ef2dSRobert Mustacchi 
700eda3ef2dSRobert Mustacchi static boolean_t
c16rtomb_null(void)701eda3ef2dSRobert Mustacchi c16rtomb_null(void)
702eda3ef2dSRobert Mustacchi {
703eda3ef2dSRobert Mustacchi 	size_t len;
704eda3ef2dSRobert Mustacchi 	mbstate_t mbs;
705eda3ef2dSRobert Mustacchi 	boolean_t ret = B_TRUE;
706eda3ef2dSRobert Mustacchi 
707eda3ef2dSRobert Mustacchi 	bzero(&mbs, sizeof (mbs));
708eda3ef2dSRobert Mustacchi 	len = c16rtomb(NULL, uchar_value, &mbs);
709eda3ef2dSRobert Mustacchi 	if (len != 1) {
710*6353250fSRobert Mustacchi 		warnx("c16rtomb returned %zu, expected %d", len, 1);
711eda3ef2dSRobert Mustacchi 		ret = B_FALSE;
712eda3ef2dSRobert Mustacchi 	}
713eda3ef2dSRobert Mustacchi 
714eda3ef2dSRobert Mustacchi 	return (ret);
715eda3ef2dSRobert Mustacchi }
716eda3ef2dSRobert Mustacchi 
717eda3ef2dSRobert Mustacchi typedef boolean_t (*uchar_test_f)(void);
718eda3ef2dSRobert Mustacchi 
719eda3ef2dSRobert Mustacchi typedef struct uchar_test {
720eda3ef2dSRobert Mustacchi 	uchar_test_f	ut_func;
721eda3ef2dSRobert Mustacchi 	const char	*ut_test;
722eda3ef2dSRobert Mustacchi 	const char	*ut_locale;
723eda3ef2dSRobert Mustacchi } uchar_test_t;
724eda3ef2dSRobert Mustacchi 
725eda3ef2dSRobert Mustacchi static const uchar_test_t uchar_tests[] = {
726eda3ef2dSRobert Mustacchi 	{ mbrtoc32_ascii_mbstate, "mbrtoc32: ascii conversion" },
727eda3ef2dSRobert Mustacchi 	{ mbrtoc32_ascii_internal, "mbrtoc32: ascii conversion (internal "
728eda3ef2dSRobert Mustacchi 	    "mbstate_t)" },
729eda3ef2dSRobert Mustacchi 	{ mbrtoc32_badseq_utf8, "mbrtoc32: bad locale sequence (UTF-8)" },
730eda3ef2dSRobert Mustacchi 	{ mbrtoc32_roundtrip, "mbrtoc32: round trip conversion" },
731eda3ef2dSRobert Mustacchi 	{ mbrtoc32_partial, "mbrtoc32: correctly consume partial sequences" },
732eda3ef2dSRobert Mustacchi 	{ mbrtoc32_zero, "mbrtoc32: correctly handle L'\\0'" },
733eda3ef2dSRobert Mustacchi 	{ mbrtoc32_zero_len, "mbrtoc32: correctly handle length of zero" },
734eda3ef2dSRobert Mustacchi 	{ mbrtoc32_null, "mbrtoc32: correctly handle null string" },
735eda3ef2dSRobert Mustacchi 	{ mbrtoc16_ascii_mbstate, "mbrtoc16: ascii conversion" },
736eda3ef2dSRobert Mustacchi 	{ mbrtoc16_ascii_internal, "mbrtoc16: ascii conversion (internal "
737eda3ef2dSRobert Mustacchi 	    "mbstate_t)" },
738eda3ef2dSRobert Mustacchi 	{ mbrtoc16_null, "mbrtoc16: correctly handle null string" },
739eda3ef2dSRobert Mustacchi 	{ mbrtoc16_zero, "mbrtoc16: correctly handle L'\\0'" },
740eda3ef2dSRobert Mustacchi 	{ mbrtoc16_zero_len, "mbrtoc16: correctly handle length of zero" },
741eda3ef2dSRobert Mustacchi 	{ mbrtoc16_roundtrip, "mbrtoc16: round trip conversion" },
742eda3ef2dSRobert Mustacchi 	{ mbrtoc16_partial, "mbrtoc16: correctly consume partial sequences" },
743eda3ef2dSRobert Mustacchi 	{ mbrtoc16_surrogate, "mbrtoc16: correctly generate surrogate pairs "
744eda3ef2dSRobert Mustacchi 	    "and round trip conversion" },
745eda3ef2dSRobert Mustacchi 	{ c32rtomb_eilseq_iso8859, "c32rtomb: character outside of locale is "
746eda3ef2dSRobert Mustacchi 	    "caught", "en_US.ISO8859-1" },
747eda3ef2dSRobert Mustacchi 	{ c16rtomb_eilseq_iso8859, "c16rtomb: character outside of locale is "
748eda3ef2dSRobert Mustacchi 	    "caught", "en_US.ISO8859-1" },
749eda3ef2dSRobert Mustacchi 	{ c32rtomb_eilseq_utf8, "c32rtomb: character outside of locale is "
750eda3ef2dSRobert Mustacchi 	    "caught" },
751eda3ef2dSRobert Mustacchi 	{ c16rtomb_bad_first, "c16rtomb: bad first surrogate pair" },
752eda3ef2dSRobert Mustacchi 	{ c16rtomb_bad_second, "c16rtomb: bad second surrogate pair" },
753eda3ef2dSRobert Mustacchi 	{ c32rtomb_null, "c32rtomb: correctly handle null buffer" },
754eda3ef2dSRobert Mustacchi 	{ c16rtomb_null, "c16rtomb: correctly handle null buffer" },
755eda3ef2dSRobert Mustacchi };
756eda3ef2dSRobert Mustacchi 
757eda3ef2dSRobert Mustacchi int
main(void)758eda3ef2dSRobert Mustacchi main(void)
759eda3ef2dSRobert Mustacchi {
760eda3ef2dSRobert Mustacchi 	uint_t i;
761eda3ef2dSRobert Mustacchi 	uint_t passes = 0;
762eda3ef2dSRobert Mustacchi 	uint_t ntests = ARRAY_SIZE(uchar_tests);
763eda3ef2dSRobert Mustacchi 
764eda3ef2dSRobert Mustacchi 	for (i = 0; i < ntests; i++) {
765eda3ef2dSRobert Mustacchi 		boolean_t r;
766eda3ef2dSRobert Mustacchi 
767eda3ef2dSRobert Mustacchi 		/*
768eda3ef2dSRobert Mustacchi 		 * Default to a standard UTF-8 locale if none is requested by
769eda3ef2dSRobert Mustacchi 		 * the test.
770eda3ef2dSRobert Mustacchi 		 */
771eda3ef2dSRobert Mustacchi 		if (uchar_tests[i].ut_locale != NULL) {
772eda3ef2dSRobert Mustacchi 			update_locale(uchar_tests[i].ut_locale);
773eda3ef2dSRobert Mustacchi 		} else {
774eda3ef2dSRobert Mustacchi 			update_locale("en_US.UTF-8");
775eda3ef2dSRobert Mustacchi 		}
776eda3ef2dSRobert Mustacchi 
777eda3ef2dSRobert Mustacchi 		r = uchar_tests[i].ut_func();
778eda3ef2dSRobert Mustacchi 		(void) fprintf(stderr, "TEST %s: %s\n", r ? "PASSED" : "FAILED",
779eda3ef2dSRobert Mustacchi 		    uchar_tests[i].ut_test);
780eda3ef2dSRobert Mustacchi 		if (r) {
781eda3ef2dSRobert Mustacchi 			passes++;
782eda3ef2dSRobert Mustacchi 		}
783eda3ef2dSRobert Mustacchi 	}
784eda3ef2dSRobert Mustacchi 
785eda3ef2dSRobert Mustacchi 	(void) printf("%d/%d test%s passed\n", passes, ntests,
786eda3ef2dSRobert Mustacchi 	    passes > 1 ? "s" : "");
787eda3ef2dSRobert Mustacchi 	return (passes == ntests ? EXIT_SUCCESS : EXIT_FAILURE);
788eda3ef2dSRobert Mustacchi 
789eda3ef2dSRobert Mustacchi }
790