wchar_test.cpp revision 3d7a0d9b08ecab054b2dff8332507644de3690b0
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <gtest/gtest.h>
18
19#include <errno.h>
20#include <limits.h>
21#include <stdint.h>
22#include <wchar.h>
23
24TEST(wchar, sizeof_wchar_t) {
25  EXPECT_EQ(4U, sizeof(wchar_t));
26  EXPECT_EQ(4U, sizeof(wint_t));
27}
28
29TEST(wchar, mbrlen) {
30  char bytes[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
31  EXPECT_EQ(0U, mbrlen(&bytes[0], 0, NULL));
32  EXPECT_EQ(1U, mbrlen(&bytes[0], 1, NULL));
33
34  EXPECT_EQ(1U, mbrlen(&bytes[4], 1, NULL));
35  EXPECT_EQ(0U, mbrlen(&bytes[5], 1, NULL));
36}
37
38TEST(wchar, wctomb_wcrtomb) {
39  // wctomb and wcrtomb behave differently when s == NULL.
40  EXPECT_EQ(0, wctomb(NULL, L'h'));
41  EXPECT_EQ(0, wctomb(NULL, L'\0'));
42  EXPECT_EQ(1U, wcrtomb(NULL, L'\0', NULL));
43  EXPECT_EQ(1U, wcrtomb(NULL, L'h', NULL));
44
45  char bytes[MB_LEN_MAX];
46
47  // wctomb and wcrtomb behave similarly for the null wide character.
48  EXPECT_EQ(1, wctomb(bytes, L'\0'));
49  EXPECT_EQ(1U, wcrtomb(bytes, L'\0', NULL));
50
51  // ...and for regular characters.
52  bytes[0] = 'x';
53  EXPECT_EQ(1, wctomb(bytes, L'h'));
54  EXPECT_EQ('h', bytes[0]);
55
56  bytes[0] = 'x';
57  EXPECT_EQ(1U, wcrtomb(bytes, L'h', NULL));
58  EXPECT_EQ('h', bytes[0]);
59}
60
61TEST(wchar, wcstombs_wcrtombs) {
62  const wchar_t chars[] = { L'h', L'e', L'l', L'l', L'o', 0 };
63  const wchar_t bad_chars[] = { L'h', L'i', 666, 0 };
64  const wchar_t* src;
65  char bytes[BUFSIZ];
66
67  // Given a NULL destination, these functions count valid characters.
68  EXPECT_EQ(5U, wcstombs(NULL, chars, 0));
69  EXPECT_EQ(5U, wcstombs(NULL, chars, 4));
70  EXPECT_EQ(5U, wcstombs(NULL, chars, 256));
71  src = chars;
72  EXPECT_EQ(5U, wcsrtombs(NULL, &src, 0, NULL));
73  EXPECT_EQ(&chars[0], src);
74  src = chars;
75  EXPECT_EQ(5U, wcsrtombs(NULL, &src, 4, NULL));
76  EXPECT_EQ(&chars[0], src);
77  src = chars;
78  EXPECT_EQ(5U, wcsrtombs(NULL, &src, 256, NULL));
79  EXPECT_EQ(&chars[0], src);
80
81  // An unrepresentable char just returns an error from wcstombs...
82  errno = 0;
83  EXPECT_EQ(static_cast<size_t>(-1), wcstombs(NULL, bad_chars, 0));
84  EXPECT_EQ(EILSEQ, errno);
85  errno = 0;
86  EXPECT_EQ(static_cast<size_t>(-1), wcstombs(NULL, bad_chars, 256));
87  EXPECT_EQ(EILSEQ, errno);
88
89  // And wcsrtombs doesn't tell us where it got stuck because we didn't ask it
90  // to actually convert anything...
91  errno = 0;
92  src = bad_chars;
93  EXPECT_EQ(static_cast<size_t>(-1), wcsrtombs(NULL, &src, 0, NULL));
94  EXPECT_EQ(&bad_chars[0], src);
95  EXPECT_EQ(EILSEQ, errno);
96  errno = 0;
97  src = bad_chars;
98  EXPECT_EQ(static_cast<size_t>(-1), wcsrtombs(NULL, &src, 256, NULL));
99  EXPECT_EQ(&bad_chars[0], src);
100  EXPECT_EQ(EILSEQ, errno);
101
102  // Okay, now let's test actually converting something...
103  memset(bytes, 'x', sizeof(bytes));
104  EXPECT_EQ(0U, wcstombs(bytes, chars, 0));
105  memset(bytes, 'x', sizeof(bytes));
106  EXPECT_EQ(4U, wcstombs(bytes, chars, 4));
107  bytes[5] = 0;
108  EXPECT_STREQ("hellx", bytes);
109  memset(bytes, 'x', sizeof(bytes));
110  EXPECT_EQ(5U, wcstombs(bytes, chars, 256));
111  EXPECT_STREQ("hello", bytes);
112  memset(bytes, 'x', sizeof(bytes));
113  EXPECT_EQ(5U, wcstombs(bytes, chars, 6));
114  EXPECT_STREQ("hello", bytes);
115  errno = 0;
116  memset(bytes, 'x', sizeof(bytes));
117  EXPECT_EQ(static_cast<size_t>(-1), wcstombs(bytes, bad_chars, 256));
118  EXPECT_EQ(EILSEQ, errno);
119  bytes[3] = 0;
120  EXPECT_STREQ("hix", bytes);
121
122  // wcsrtombs is a bit more informative...
123  memset(bytes, 'x', sizeof(bytes));
124  src = chars;
125  EXPECT_EQ(0U, wcsrtombs(bytes, &src, 0, NULL));
126  EXPECT_EQ(&chars[0], src); // No input consumed.
127  EXPECT_EQ(EILSEQ, errno);
128
129  memset(bytes, 'x', sizeof(bytes));
130  src = chars;
131  EXPECT_EQ(4U, wcsrtombs(bytes, &src, 4, NULL));
132  EXPECT_EQ(&chars[4], src); // Some input consumed.
133  EXPECT_EQ(EILSEQ, errno);
134  bytes[5] = 0;
135  EXPECT_STREQ("hellx", bytes);
136
137  memset(bytes, 'x', sizeof(bytes));
138  src = chars;
139  EXPECT_EQ(5U, wcsrtombs(bytes, &src, 256, NULL));
140  EXPECT_EQ(NULL, src); // All input consumed!
141  EXPECT_EQ(EILSEQ, errno);
142  EXPECT_STREQ("hello", bytes);
143
144  memset(bytes, 'x', sizeof(bytes));
145  src = chars;
146  EXPECT_EQ(5U, wcsrtombs(bytes, &src, 6, NULL));
147  EXPECT_EQ(NULL, src); // All input consumed.
148  EXPECT_EQ(EILSEQ, errno);
149  EXPECT_STREQ("hello", bytes);
150
151  memset(bytes, 'x', sizeof(bytes));
152  src = bad_chars;
153  EXPECT_EQ(static_cast<size_t>(-1), wcsrtombs(bytes, &src, 256, NULL));
154  EXPECT_EQ(&bad_chars[2], src);
155  EXPECT_EQ(EILSEQ, errno);
156  bytes[3] = 0;
157  EXPECT_STREQ("hix", bytes);
158}
159
160TEST(wchar, limits) {
161  ASSERT_LT(WCHAR_MIN, WCHAR_MAX);
162}
163
164TEST(wchar, wcsstr_wcswcs) {
165  const wchar_t* haystack = L"matches hello world, not the second hello world";
166  const wchar_t* empty_needle = L"";
167  const wchar_t* good_needle = L"ll";
168  const wchar_t* bad_needle = L"wort";
169
170  ASSERT_EQ(haystack, wcsstr(haystack, empty_needle));
171  ASSERT_EQ(&haystack[10], wcsstr(haystack, good_needle));
172  ASSERT_EQ(NULL, wcsstr(haystack, bad_needle));
173
174  ASSERT_EQ(haystack, wcswcs(haystack, empty_needle));
175  ASSERT_EQ(&haystack[10], wcswcs(haystack, good_needle));
176  ASSERT_EQ(NULL, wcswcs(haystack, bad_needle));
177}
178
179TEST(wchar, mbtowc) {
180  wchar_t out[8];
181
182  out[0] = 'x';
183  ASSERT_EQ(0, mbtowc(out, "hello", 0));
184  ASSERT_EQ('x', out[0]);
185
186  ASSERT_EQ(0, mbtowc(out, "hello", 0));
187  ASSERT_EQ(0, mbtowc(out, "", 0));
188  ASSERT_EQ(1, mbtowc(out, "hello", 1));
189  ASSERT_EQ(L'h', out[0]);
190
191  ASSERT_EQ(0, mbtowc(NULL, "hello", 0));
192  ASSERT_EQ(0, mbtowc(NULL, "", 0));
193  ASSERT_EQ(1, mbtowc(NULL, "hello", 1));
194
195  ASSERT_EQ(0, mbtowc(NULL, NULL, 0));
196}
197
198TEST(wchar, mbrtowc) {
199  wchar_t out[8];
200
201  out[0] = 'x';
202  ASSERT_EQ(0U, mbrtowc(out, "hello", 0, NULL));
203  ASSERT_EQ('x', out[0]);
204
205  ASSERT_EQ(0U, mbrtowc(out, "hello", 0, NULL));
206  ASSERT_EQ(0U, mbrtowc(out, "", 0, NULL));
207  ASSERT_EQ(1U, mbrtowc(out, "hello", 1, NULL));
208  ASSERT_EQ(L'h', out[0]);
209
210  ASSERT_EQ(0U, mbrtowc(NULL, "hello", 0, NULL));
211  ASSERT_EQ(0U, mbrtowc(NULL, "", 0, NULL));
212  ASSERT_EQ(1U, mbrtowc(NULL, "hello", 1, NULL));
213
214  ASSERT_EQ(0U, mbrtowc(NULL, NULL, 0, NULL));
215}
216
217TEST(wchar, wcstod) {
218  ASSERT_DOUBLE_EQ(1.23, wcstod(L"1.23", NULL));
219}
220
221TEST(wchar, wcstof) {
222  ASSERT_FLOAT_EQ(1.23f, wcstof(L"1.23", NULL));
223}
224
225TEST(wchar, wcstol) {
226  ASSERT_EQ(123L, wcstol(L"123", NULL, 0));
227}
228
229TEST(wchar, wcstoll) {
230  ASSERT_EQ(123LL, wcstol(L"123", NULL, 0));
231}
232
233TEST(wchar, wcstold) {
234  ASSERT_DOUBLE_EQ(1.23L, wcstold(L"1.23", NULL));
235}
236
237TEST(wchar, wcstoul) {
238  ASSERT_EQ(123UL, wcstoul(L"123", NULL, 0));
239}
240
241TEST(wchar, wcstoull) {
242  ASSERT_EQ(123ULL, wcstoul(L"123", NULL, 0));
243}
244
245TEST(wchar, mbsnrtowcs) {
246  wchar_t dst[128];
247  const char* s = "hello, world!";
248  const char* src;
249
250  memset(dst, 0, sizeof(dst));
251  src = s;
252  ASSERT_EQ(0U, mbsnrtowcs(dst, &src, 0, 0, NULL));
253
254  memset(dst, 0, sizeof(dst));
255  src = s;
256  ASSERT_EQ(2U, mbsnrtowcs(dst, &src, 2, 123, NULL)); // glibc chokes on SIZE_MAX here.
257  ASSERT_EQ(L'h', dst[0]);
258  ASSERT_EQ(L'e', dst[1]);
259  ASSERT_EQ(&s[2], src);
260
261  memset(dst, 0, sizeof(dst));
262  src = s;
263  ASSERT_EQ(3U, mbsnrtowcs(dst, &src, SIZE_MAX, 3, NULL));
264  ASSERT_EQ(L'h', dst[0]);
265  ASSERT_EQ(L'e', dst[1]);
266  ASSERT_EQ(L'l', dst[2]);
267  ASSERT_EQ(&s[3], src);
268}
269