1132499Stjr/*-
2132499Stjr * Copyright (c) 2002-2004 Tim J. Robbins
3132499Stjr * All rights reserved.
4132499Stjr *
5132499Stjr * Redistribution and use in source and binary forms, with or without
6132499Stjr * modification, are permitted provided that the following conditions
7132499Stjr * are met:
8132499Stjr * 1. Redistributions of source code must retain the above copyright
9132499Stjr *    notice, this list of conditions and the following disclaimer.
10132499Stjr * 2. Redistributions in binary form must reproduce the above copyright
11132499Stjr *    notice, this list of conditions and the following disclaimer in the
12132499Stjr *    documentation and/or other materials provided with the distribution.
13132499Stjr *
14132499Stjr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15132499Stjr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16132499Stjr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17132499Stjr * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18132499Stjr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19132499Stjr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20132499Stjr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21132499Stjr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22132499Stjr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23132499Stjr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24132499Stjr * SUCH DAMAGE.
25132499Stjr */
26132499Stjr
27132499Stjr/*
28132499Stjr * Test program for mbsnrtowcs().
29132499Stjr *
30132499Stjr * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
31132499Stjr * "ja_JP.eucJP". Other encodings are not tested.
32132499Stjr */
33132499Stjr
34132499Stjr#include <sys/cdefs.h>
35132499Stjr__FBSDID("$FreeBSD: releng/11.0/lib/libc/tests/locale/mbsnrtowcs_test.c 290532 2015-11-08 02:06:17Z ngie $");
36132499Stjr
37132499Stjr#include <errno.h>
38132499Stjr#include <limits.h>
39132499Stjr#include <locale.h>
40132499Stjr#include <stdio.h>
41132499Stjr#include <stdlib.h>
42132499Stjr#include <string.h>
43132499Stjr#include <wchar.h>
44132499Stjr
45290532Sngie#include <atf-c.h>
46290532Sngie
47290532SngieATF_TC_WITHOUT_HEAD(mbsnrtowcs_test);
48290532SngieATF_TC_BODY(mbsnrtowcs_test, tc)
49132499Stjr{
50132499Stjr	char srcbuf[128];
51132499Stjr	wchar_t dstbuf[128];
52132499Stjr	char *src;
53132499Stjr	mbstate_t s;
54132499Stjr
55290532Sngie	/* C/POSIX locale. */
56132499Stjr
57132499Stjr	/* Simple null terminated string. */
58132499Stjr	memset(srcbuf, 0xcc, sizeof(srcbuf));
59132499Stjr	strcpy(srcbuf, "hello");
60132499Stjr	wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
61132499Stjr	src = srcbuf;
62132499Stjr	memset(&s, 0, sizeof(s));
63290532Sngie	ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 6, sizeof(dstbuf) /
64132499Stjr	    sizeof(*dstbuf), &s) == 5);
65290532Sngie	ATF_REQUIRE(wcscmp(dstbuf, L"hello") == 0);
66290532Sngie	ATF_REQUIRE(dstbuf[6] == 0xcccc);
67290532Sngie	ATF_REQUIRE(src == NULL);
68132499Stjr
69132499Stjr	/* Simple null terminated string, stopping early. */
70132499Stjr	memset(srcbuf, 0xcc, sizeof(srcbuf));
71132499Stjr	strcpy(srcbuf, "hello");
72132499Stjr	wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
73132499Stjr	src = srcbuf;
74132499Stjr	memset(&s, 0, sizeof(s));
75290532Sngie	ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 4, sizeof(dstbuf) /
76132499Stjr	    sizeof(*dstbuf), &s) == 4);
77290532Sngie	ATF_REQUIRE(wmemcmp(dstbuf, L"hell", 4) == 0);
78290532Sngie	ATF_REQUIRE(dstbuf[5] == 0xcccc);
79290532Sngie	ATF_REQUIRE(src == srcbuf + 4);
80132499Stjr
81132499Stjr	/* Not enough space in destination buffer. */
82132499Stjr	memset(srcbuf, 0xcc, sizeof(srcbuf));
83132499Stjr	strcpy(srcbuf, "hello");
84132499Stjr	wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
85132499Stjr	src = srcbuf;
86132499Stjr	memset(&s, 0, sizeof(s));
87290532Sngie	ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 6, 4, &s) == 4);
88290532Sngie	ATF_REQUIRE(wmemcmp(dstbuf, L"hell", 4) == 0);
89290532Sngie	ATF_REQUIRE(dstbuf[5] == 0xcccc);
90290532Sngie	ATF_REQUIRE(src == srcbuf + 4);
91132499Stjr
92132499Stjr	/* Null terminated string, internal dest. buffer */
93132499Stjr	memset(srcbuf, 0xcc, sizeof(srcbuf));
94132499Stjr	strcpy(srcbuf, "hello");
95132499Stjr	src = srcbuf;
96132499Stjr	memset(&s, 0, sizeof(s));
97290532Sngie	ATF_REQUIRE(mbsnrtowcs(NULL, (const char **)&src, 6, 0, &s) == 5);
98132499Stjr
99132499Stjr	/* Null terminated string, internal dest. buffer, stopping early */
100132499Stjr	memset(srcbuf, 0xcc, sizeof(srcbuf));
101132499Stjr	strcpy(srcbuf, "hello");
102132499Stjr	src = srcbuf;
103132499Stjr	memset(&s, 0, sizeof(s));
104290532Sngie	ATF_REQUIRE(mbsnrtowcs(NULL, (const char **)&src, 4, 0, &s) == 4);
105132499Stjr
106132499Stjr	/* Null terminated string, internal state. */
107132499Stjr	memset(srcbuf, 0xcc, sizeof(srcbuf));
108132499Stjr	strcpy(srcbuf, "hello");
109132499Stjr	wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
110132499Stjr	src = srcbuf;
111290532Sngie	ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 6, sizeof(dstbuf) /
112132499Stjr	    sizeof(*dstbuf), NULL) == 5);
113290532Sngie	ATF_REQUIRE(wcscmp(dstbuf, L"hello") == 0);
114290532Sngie	ATF_REQUIRE(dstbuf[6] == 0xcccc);
115290532Sngie	ATF_REQUIRE(src == NULL);
116132499Stjr
117132499Stjr	/* Null terminated string, internal state, internal dest. buffer. */
118132499Stjr	memset(srcbuf, 0xcc, sizeof(srcbuf));
119132499Stjr	strcpy(srcbuf, "hello");
120132499Stjr	src = srcbuf;
121290532Sngie	ATF_REQUIRE(mbsnrtowcs(NULL, (const char **)&src, 6, 0, NULL) == 5);
122132499Stjr
123132499Stjr	/* Empty source buffer. */
124132499Stjr	memset(srcbuf, 0xcc, sizeof(srcbuf));
125132499Stjr	srcbuf[0] = '\0';
126132499Stjr	src = srcbuf;
127132499Stjr	memset(&s, 0, sizeof(s));
128132499Stjr	wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
129290532Sngie	ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 1, 1, &s) == 0);
130290532Sngie	ATF_REQUIRE(dstbuf[0] == 0);
131290532Sngie	ATF_REQUIRE(dstbuf[1] == 0xcccc);
132290532Sngie	ATF_REQUIRE(src == NULL);
133132499Stjr
134132499Stjr	/* Zero length destination buffer. */
135132499Stjr	memset(srcbuf, 0xcc, sizeof(srcbuf));
136132499Stjr	strcpy(srcbuf, "hello");
137132499Stjr	src = srcbuf;
138132499Stjr	memset(&s, 0, sizeof(s));
139132499Stjr	wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
140290532Sngie	ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 1, 0, &s) == 0);
141290532Sngie	ATF_REQUIRE(dstbuf[0] == 0xcccc);
142290532Sngie	ATF_REQUIRE(src == srcbuf);
143132499Stjr
144132499Stjr	/* Zero length source buffer. */
145132499Stjr	memset(srcbuf, 0xcc, sizeof(srcbuf));
146132499Stjr	src = srcbuf;
147132499Stjr	memset(&s, 0, sizeof(s));
148132499Stjr	wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
149290532Sngie	ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 0, 1, &s) == 0);
150290532Sngie	ATF_REQUIRE(dstbuf[0] == 0xcccc);
151290532Sngie	ATF_REQUIRE(src == srcbuf);
152132499Stjr
153132499Stjr	/*
154132499Stjr	 * Japanese (EUC) locale.
155132499Stjr	 */
156132499Stjr
157290532Sngie	ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
158290532Sngie	ATF_REQUIRE(MB_CUR_MAX > 1);
159132499Stjr
160132499Stjr	memset(srcbuf, 0xcc, sizeof(srcbuf));
161132499Stjr	strcpy(srcbuf, "\xA3\xC1 B \xA3\xC3");
162132499Stjr	src = srcbuf;
163132499Stjr	memset(&s, 0, sizeof(s));
164132499Stjr	wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
165290532Sngie	ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 8, sizeof(dstbuf) /
166132499Stjr	    sizeof(*dstbuf), &s) == 5);
167290532Sngie	ATF_REQUIRE(dstbuf[0] == 0xA3C1 && dstbuf[1] == 0x20 && dstbuf[2] == 0x42 &&
168132499Stjr	    dstbuf[3] == 0x20 && dstbuf[4] == 0xA3C3 && dstbuf[5] == 0);
169290532Sngie	ATF_REQUIRE(src == NULL);
170132499Stjr
171132499Stjr	/* Partial character. */
172132499Stjr	memset(srcbuf, 0xcc, sizeof(srcbuf));
173132499Stjr	strcpy(srcbuf, "\xA3\xC1 B \xA3\xC3");
174132499Stjr	src = srcbuf;
175132499Stjr	memset(&s, 0, sizeof(s));
176132499Stjr	wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
177290532Sngie	ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 6, sizeof(dstbuf) /
178132499Stjr	    sizeof(*dstbuf), &s) == 4);
179290532Sngie	ATF_REQUIRE(src == srcbuf + 6);
180290532Sngie	ATF_REQUIRE(!mbsinit(&s));
181290532Sngie	ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 1, sizeof(dstbuf) /
182132499Stjr	    sizeof(*dstbuf), &s) == 1);
183290532Sngie	ATF_REQUIRE(src == srcbuf + 7);
184290532Sngie	ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 1, sizeof(dstbuf) /
185132499Stjr	    sizeof(*dstbuf), &s) == 0);
186290532Sngie	ATF_REQUIRE(src == NULL);
187290532Sngie}
188132499Stjr
189290532SngieATF_TP_ADD_TCS(tp)
190290532Sngie{
191132499Stjr
192290532Sngie	ATF_TP_ADD_TC(tp, mbsnrtowcs_test);
193290532Sngie
194290532Sngie	return (atf_no_error());
195132499Stjr}
196