blob: a7e49e8c692cc1d07442b9593662e9237d190cd5 [file] [log] [blame]
Elliott Hughes77e944f2014-04-04 17:34:51 -07001/*
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
Elliott Hughes05493712014-04-17 17:30:03 -070019#include <errno.h>
Dan Albert6805c2d2017-08-09 14:55:27 -070020#include <inttypes.h>
Elliott Hughes77e944f2014-04-04 17:34:51 -070021#include <limits.h>
Elliott Hughes5a0aa3d2014-04-30 22:03:12 -070022#include <locale.h>
Elliott Hughes3d7a0d92014-04-29 14:46:56 -070023#include <stdint.h>
Elliott Hughes77e944f2014-04-04 17:34:51 -070024#include <wchar.h>
25
Elliott Hughes7f0849f2016-08-26 16:17:17 -070026#include "math_data_test.h"
27
Chih-Hung Hsiehd61ca372016-06-03 10:18:07 -070028#define NUM_WCHARS(num_bytes) ((num_bytes)/sizeof(wchar_t))
Christopher Ferris5c7d9582014-11-13 15:48:39 -080029
Elliott Hughes77e944f2014-04-04 17:34:51 -070030TEST(wchar, sizeof_wchar_t) {
31 EXPECT_EQ(4U, sizeof(wchar_t));
32 EXPECT_EQ(4U, sizeof(wint_t));
33}
34
35TEST(wchar, mbrlen) {
36 char bytes[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
37 EXPECT_EQ(0U, mbrlen(&bytes[0], 0, NULL));
38 EXPECT_EQ(1U, mbrlen(&bytes[0], 1, NULL));
39
40 EXPECT_EQ(1U, mbrlen(&bytes[4], 1, NULL));
41 EXPECT_EQ(0U, mbrlen(&bytes[5], 1, NULL));
42}
43
44TEST(wchar, wctomb_wcrtomb) {
45 // wctomb and wcrtomb behave differently when s == NULL.
46 EXPECT_EQ(0, wctomb(NULL, L'h'));
47 EXPECT_EQ(0, wctomb(NULL, L'\0'));
48 EXPECT_EQ(1U, wcrtomb(NULL, L'\0', NULL));
49 EXPECT_EQ(1U, wcrtomb(NULL, L'h', NULL));
50
51 char bytes[MB_LEN_MAX];
52
53 // wctomb and wcrtomb behave similarly for the null wide character.
54 EXPECT_EQ(1, wctomb(bytes, L'\0'));
55 EXPECT_EQ(1U, wcrtomb(bytes, L'\0', NULL));
56
57 // ...and for regular characters.
Elliott Hughes5a0aa3d2014-04-30 22:03:12 -070058 memset(bytes, 0, sizeof(bytes));
Elliott Hughes77e944f2014-04-04 17:34:51 -070059 EXPECT_EQ(1, wctomb(bytes, L'h'));
60 EXPECT_EQ('h', bytes[0]);
Elliott Hughes5a0aa3d2014-04-30 22:03:12 -070061 memset(bytes, 0, sizeof(bytes));
Elliott Hughes77e944f2014-04-04 17:34:51 -070062 EXPECT_EQ(1U, wcrtomb(bytes, L'h', NULL));
63 EXPECT_EQ('h', bytes[0]);
Elliott Hughes5a0aa3d2014-04-30 22:03:12 -070064
65 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
66 uselocale(LC_GLOBAL_LOCALE);
67
68 // 1-byte UTF-8.
69 memset(bytes, 0, sizeof(bytes));
70 EXPECT_EQ(1U, wcrtomb(bytes, L'h', NULL));
71 EXPECT_EQ('h', bytes[0]);
72 // 2-byte UTF-8.
73 memset(bytes, 0, sizeof(bytes));
74 EXPECT_EQ(2U, wcrtomb(bytes, 0x00a2, NULL));
75 EXPECT_EQ('\xc2', bytes[0]);
76 EXPECT_EQ('\xa2', bytes[1]);
77 // 3-byte UTF-8.
78 memset(bytes, 0, sizeof(bytes));
79 EXPECT_EQ(3U, wcrtomb(bytes, 0x20ac, NULL));
80 EXPECT_EQ('\xe2', bytes[0]);
81 EXPECT_EQ('\x82', bytes[1]);
82 EXPECT_EQ('\xac', bytes[2]);
83 // 4-byte UTF-8.
84 memset(bytes, 0, sizeof(bytes));
85 EXPECT_EQ(4U, wcrtomb(bytes, 0x24b62, NULL));
86 EXPECT_EQ('\xf0', bytes[0]);
87 EXPECT_EQ('\xa4', bytes[1]);
88 EXPECT_EQ('\xad', bytes[2]);
89 EXPECT_EQ('\xa2', bytes[3]);
90 // Invalid code point.
91 EXPECT_EQ(static_cast<size_t>(-1), wcrtomb(bytes, 0xffffffff, NULL));
92 EXPECT_EQ(EILSEQ, errno);
Elliott Hughes77e944f2014-04-04 17:34:51 -070093}
Elliott Hughes05493712014-04-17 17:30:03 -070094
Calin Juravle15a63102014-05-08 14:38:35 +010095TEST(wchar, wcrtomb_start_state) {
96 char out[MB_LEN_MAX];
97 mbstate_t ps;
98
99 // Any non-initial state is invalid when calling wcrtomb.
100 memset(&ps, 0, sizeof(ps));
101 EXPECT_EQ(static_cast<size_t>(-2), mbrtowc(NULL, "\xc2", 1, &ps));
102 EXPECT_EQ(static_cast<size_t>(-1), wcrtomb(out, 0x00a2, &ps));
103 EXPECT_EQ(EILSEQ, errno);
104
105 // If the first argument to wcrtomb is NULL or the second is L'\0' the shift
106 // state should be reset.
107 memset(&ps, 0, sizeof(ps));
108 EXPECT_EQ(static_cast<size_t>(-2), mbrtowc(NULL, "\xc2", 1, &ps));
109 EXPECT_EQ(1U, wcrtomb(NULL, 0x00a2, &ps));
110 EXPECT_TRUE(mbsinit(&ps));
111
112 memset(&ps, 0, sizeof(ps));
113 EXPECT_EQ(static_cast<size_t>(-2), mbrtowc(NULL, "\xf0\xa4", 1, &ps));
114 EXPECT_EQ(1U, wcrtomb(out, L'\0', &ps));
115 EXPECT_TRUE(mbsinit(&ps));
116}
117
Elliott Hughes05493712014-04-17 17:30:03 -0700118TEST(wchar, wcstombs_wcrtombs) {
Elliott Hughes1b836ee2014-04-18 13:32:33 -0700119 const wchar_t chars[] = { L'h', L'e', L'l', L'l', L'o', 0 };
Elliott Hughesf83e6442014-05-01 17:14:59 -0700120 const wchar_t bad_chars[] = { L'h', L'i', static_cast<wchar_t>(0xffffffff), 0 };
Elliott Hughes05493712014-04-17 17:30:03 -0700121 const wchar_t* src;
122 char bytes[BUFSIZ];
123
124 // Given a NULL destination, these functions count valid characters.
125 EXPECT_EQ(5U, wcstombs(NULL, chars, 0));
126 EXPECT_EQ(5U, wcstombs(NULL, chars, 4));
127 EXPECT_EQ(5U, wcstombs(NULL, chars, 256));
128 src = chars;
129 EXPECT_EQ(5U, wcsrtombs(NULL, &src, 0, NULL));
130 EXPECT_EQ(&chars[0], src);
131 src = chars;
132 EXPECT_EQ(5U, wcsrtombs(NULL, &src, 4, NULL));
133 EXPECT_EQ(&chars[0], src);
134 src = chars;
135 EXPECT_EQ(5U, wcsrtombs(NULL, &src, 256, NULL));
136 EXPECT_EQ(&chars[0], src);
137
138 // An unrepresentable char just returns an error from wcstombs...
139 errno = 0;
140 EXPECT_EQ(static_cast<size_t>(-1), wcstombs(NULL, bad_chars, 0));
141 EXPECT_EQ(EILSEQ, errno);
142 errno = 0;
143 EXPECT_EQ(static_cast<size_t>(-1), wcstombs(NULL, bad_chars, 256));
144 EXPECT_EQ(EILSEQ, errno);
145
146 // And wcsrtombs doesn't tell us where it got stuck because we didn't ask it
147 // to actually convert anything...
148 errno = 0;
149 src = bad_chars;
150 EXPECT_EQ(static_cast<size_t>(-1), wcsrtombs(NULL, &src, 0, NULL));
151 EXPECT_EQ(&bad_chars[0], src);
152 EXPECT_EQ(EILSEQ, errno);
153 errno = 0;
154 src = bad_chars;
155 EXPECT_EQ(static_cast<size_t>(-1), wcsrtombs(NULL, &src, 256, NULL));
156 EXPECT_EQ(&bad_chars[0], src);
157 EXPECT_EQ(EILSEQ, errno);
158
159 // Okay, now let's test actually converting something...
160 memset(bytes, 'x', sizeof(bytes));
161 EXPECT_EQ(0U, wcstombs(bytes, chars, 0));
162 memset(bytes, 'x', sizeof(bytes));
163 EXPECT_EQ(4U, wcstombs(bytes, chars, 4));
164 bytes[5] = 0;
165 EXPECT_STREQ("hellx", bytes);
166 memset(bytes, 'x', sizeof(bytes));
167 EXPECT_EQ(5U, wcstombs(bytes, chars, 256));
168 EXPECT_STREQ("hello", bytes);
169 memset(bytes, 'x', sizeof(bytes));
170 EXPECT_EQ(5U, wcstombs(bytes, chars, 6));
171 EXPECT_STREQ("hello", bytes);
172 errno = 0;
173 memset(bytes, 'x', sizeof(bytes));
174 EXPECT_EQ(static_cast<size_t>(-1), wcstombs(bytes, bad_chars, 256));
175 EXPECT_EQ(EILSEQ, errno);
176 bytes[3] = 0;
177 EXPECT_STREQ("hix", bytes);
178
179 // wcsrtombs is a bit more informative...
180 memset(bytes, 'x', sizeof(bytes));
181 src = chars;
182 EXPECT_EQ(0U, wcsrtombs(bytes, &src, 0, NULL));
183 EXPECT_EQ(&chars[0], src); // No input consumed.
184 EXPECT_EQ(EILSEQ, errno);
185
186 memset(bytes, 'x', sizeof(bytes));
187 src = chars;
188 EXPECT_EQ(4U, wcsrtombs(bytes, &src, 4, NULL));
189 EXPECT_EQ(&chars[4], src); // Some input consumed.
190 EXPECT_EQ(EILSEQ, errno);
191 bytes[5] = 0;
192 EXPECT_STREQ("hellx", bytes);
193
194 memset(bytes, 'x', sizeof(bytes));
195 src = chars;
196 EXPECT_EQ(5U, wcsrtombs(bytes, &src, 256, NULL));
197 EXPECT_EQ(NULL, src); // All input consumed!
198 EXPECT_EQ(EILSEQ, errno);
199 EXPECT_STREQ("hello", bytes);
200
201 memset(bytes, 'x', sizeof(bytes));
202 src = chars;
203 EXPECT_EQ(5U, wcsrtombs(bytes, &src, 6, NULL));
204 EXPECT_EQ(NULL, src); // All input consumed.
205 EXPECT_EQ(EILSEQ, errno);
206 EXPECT_STREQ("hello", bytes);
207
208 memset(bytes, 'x', sizeof(bytes));
209 src = bad_chars;
210 EXPECT_EQ(static_cast<size_t>(-1), wcsrtombs(bytes, &src, 256, NULL));
211 EXPECT_EQ(&bad_chars[2], src);
212 EXPECT_EQ(EILSEQ, errno);
213 bytes[3] = 0;
214 EXPECT_STREQ("hix", bytes);
Calin Juravle15a63102014-05-08 14:38:35 +0100215
216 // Any non-initial state is invalid when calling wcsrtombs.
217 mbstate_t ps;
218 src = chars;
219 memset(&ps, 0, sizeof(ps));
220 ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(NULL, "\xc2", 1, &ps));
221 EXPECT_EQ(static_cast<size_t>(-1), wcsrtombs(NULL, &src, 0, &ps));
222 EXPECT_EQ(EILSEQ, errno);
Elliott Hughes05493712014-04-17 17:30:03 -0700223}
Elliott Hughes83c07b52014-04-21 18:09:46 -0700224
225TEST(wchar, limits) {
226 ASSERT_LT(WCHAR_MIN, WCHAR_MAX);
227}
Elliott Hughesd299bcf2014-04-28 16:28:51 -0700228
Dan Albert001f8f02014-06-04 09:53:06 -0700229TEST(wchar, wcsstr) {
Elliott Hughesd299bcf2014-04-28 16:28:51 -0700230 const wchar_t* haystack = L"matches hello world, not the second hello world";
231 const wchar_t* empty_needle = L"";
232 const wchar_t* good_needle = L"ll";
233 const wchar_t* bad_needle = L"wort";
234
235 ASSERT_EQ(haystack, wcsstr(haystack, empty_needle));
236 ASSERT_EQ(&haystack[10], wcsstr(haystack, good_needle));
237 ASSERT_EQ(NULL, wcsstr(haystack, bad_needle));
Elliott Hughesd299bcf2014-04-28 16:28:51 -0700238}
Elliott Hughes0a5e26d2014-04-28 17:51:13 -0700239
Elliott Hughese1f9dda2015-02-14 14:11:50 -0800240TEST(wchar, wcsstr_80199) {
241 // https://code.google.com/p/android/issues/detail?id=80199
242 ASSERT_TRUE(wcsstr(L"romrom", L"rom") != NULL);
243}
244
Elliott Hughes0a5e26d2014-04-28 17:51:13 -0700245TEST(wchar, mbtowc) {
246 wchar_t out[8];
247
248 out[0] = 'x';
249 ASSERT_EQ(0, mbtowc(out, "hello", 0));
250 ASSERT_EQ('x', out[0]);
251
252 ASSERT_EQ(0, mbtowc(out, "hello", 0));
253 ASSERT_EQ(0, mbtowc(out, "", 0));
254 ASSERT_EQ(1, mbtowc(out, "hello", 1));
255 ASSERT_EQ(L'h', out[0]);
256
257 ASSERT_EQ(0, mbtowc(NULL, "hello", 0));
258 ASSERT_EQ(0, mbtowc(NULL, "", 0));
259 ASSERT_EQ(1, mbtowc(NULL, "hello", 1));
260
261 ASSERT_EQ(0, mbtowc(NULL, NULL, 0));
262}
263
264TEST(wchar, mbrtowc) {
265 wchar_t out[8];
266
267 out[0] = 'x';
268 ASSERT_EQ(0U, mbrtowc(out, "hello", 0, NULL));
269 ASSERT_EQ('x', out[0]);
270
271 ASSERT_EQ(0U, mbrtowc(out, "hello", 0, NULL));
272 ASSERT_EQ(0U, mbrtowc(out, "", 0, NULL));
273 ASSERT_EQ(1U, mbrtowc(out, "hello", 1, NULL));
274 ASSERT_EQ(L'h', out[0]);
275
276 ASSERT_EQ(0U, mbrtowc(NULL, "hello", 0, NULL));
277 ASSERT_EQ(0U, mbrtowc(NULL, "", 0, NULL));
278 ASSERT_EQ(1U, mbrtowc(NULL, "hello", 1, NULL));
279
280 ASSERT_EQ(0U, mbrtowc(NULL, NULL, 0, NULL));
Elliott Hughes5a0aa3d2014-04-30 22:03:12 -0700281
282 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
283 uselocale(LC_GLOBAL_LOCALE);
284
285 // 1-byte UTF-8.
286 ASSERT_EQ(1U, mbrtowc(out, "abcdef", 6, NULL));
287 ASSERT_EQ(L'a', out[0]);
288 // 2-byte UTF-8.
289 ASSERT_EQ(2U, mbrtowc(out, "\xc2\xa2" "cdef", 6, NULL));
Yongqin Liua5c6b2e2014-05-08 23:21:01 +0800290 ASSERT_EQ(static_cast<wchar_t>(0x00a2), out[0]);
Elliott Hughes5a0aa3d2014-04-30 22:03:12 -0700291 // 3-byte UTF-8.
292 ASSERT_EQ(3U, mbrtowc(out, "\xe2\x82\xac" "def", 6, NULL));
Yongqin Liua5c6b2e2014-05-08 23:21:01 +0800293 ASSERT_EQ(static_cast<wchar_t>(0x20ac), out[0]);
Elliott Hughes5a0aa3d2014-04-30 22:03:12 -0700294 // 4-byte UTF-8.
295 ASSERT_EQ(4U, mbrtowc(out, "\xf0\xa4\xad\xa2" "ef", 6, NULL));
Yongqin Liua5c6b2e2014-05-08 23:21:01 +0800296 ASSERT_EQ(static_cast<wchar_t>(0x24b62), out[0]);
Elliott Hughes063525c2014-05-13 11:19:57 -0700297#if defined(__BIONIC__) // glibc allows this.
Elliott Hughes5a0aa3d2014-04-30 22:03:12 -0700298 // Illegal 5-byte UTF-8.
299 ASSERT_EQ(static_cast<size_t>(-1), mbrtowc(out, "\xf8\xa1\xa2\xa3\xa4" "f", 6, NULL));
300 ASSERT_EQ(EILSEQ, errno);
301#endif
302 // Illegal over-long sequence.
303 ASSERT_EQ(static_cast<size_t>(-1), mbrtowc(out, "\xf0\x82\x82\xac" "ef", 6, NULL));
304 ASSERT_EQ(EILSEQ, errno);
Elliott Hughes0a5e26d2014-04-28 17:51:13 -0700305}
Elliott Hughes3d7a0d92014-04-29 14:46:56 -0700306
Elliott Hughes89e29ee2016-09-29 17:21:43 -0700307static void test_mbrtowc_incomplete(mbstate_t* ps) {
Calin Juravle15a63102014-05-08 14:38:35 +0100308 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
309 uselocale(LC_GLOBAL_LOCALE);
310
311 wchar_t out;
312 // 2-byte UTF-8.
313 ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(&out, "\xc2", 1, ps));
314 ASSERT_EQ(1U, mbrtowc(&out, "\xa2" "cdef", 5, ps));
Ben Chengcaff5f22014-05-19 14:27:31 -0700315 ASSERT_EQ(static_cast<wchar_t>(0x00a2), out);
Calin Juravle15a63102014-05-08 14:38:35 +0100316 ASSERT_TRUE(mbsinit(ps));
317 // 3-byte UTF-8.
318 ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(&out, "\xe2", 1, ps));
319 ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(&out, "\x82", 1, ps));
320 ASSERT_EQ(1U, mbrtowc(&out, "\xac" "def", 4, ps));
Ben Chengcaff5f22014-05-19 14:27:31 -0700321 ASSERT_EQ(static_cast<wchar_t>(0x20ac), out);
Calin Juravle15a63102014-05-08 14:38:35 +0100322 ASSERT_TRUE(mbsinit(ps));
323 // 4-byte UTF-8.
324 ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(&out, "\xf0", 1, ps));
325 ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(&out, "\xa4\xad", 2, ps));
326 ASSERT_EQ(1U, mbrtowc(&out, "\xa2" "ef", 3, ps));
Ben Chengcaff5f22014-05-19 14:27:31 -0700327 ASSERT_EQ(static_cast<wchar_t>(0x24b62), out);
Calin Juravle15a63102014-05-08 14:38:35 +0100328 ASSERT_TRUE(mbsinit(ps));
329
330 // Invalid 2-byte
331 ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(&out, "\xc2", 1, ps));
332 ASSERT_EQ(static_cast<size_t>(-1), mbrtowc(&out, "\x20" "cdef", 5, ps));
333 ASSERT_EQ(EILSEQ, errno);
334}
335
336TEST(wchar, mbrtowc_incomplete) {
337 mbstate_t ps;
338 memset(&ps, 0, sizeof(ps));
339
340 test_mbrtowc_incomplete(&ps);
341 test_mbrtowc_incomplete(NULL);
342}
343
Elliott Hughes89e29ee2016-09-29 17:21:43 -0700344static void test_mbsrtowcs(mbstate_t* ps) {
345 constexpr const char* VALID = "A" "\xc2\xa2" "\xe2\x82\xac" "\xf0\xa4\xad\xa2" "ef";
346 constexpr const char* INVALID = "A" "\xc2\x20" "ef";
347 constexpr const char* INCOMPLETE = "A" "\xc2";
Calin Juravle15a63102014-05-08 14:38:35 +0100348 wchar_t out[4];
349
Elliott Hughes89e29ee2016-09-29 17:21:43 -0700350 const char* valid = VALID;
Calin Juravle15a63102014-05-08 14:38:35 +0100351 ASSERT_EQ(4U, mbsrtowcs(out, &valid, 4, ps));
352 ASSERT_EQ(L'A', out[0]);
Ben Chengcaff5f22014-05-19 14:27:31 -0700353 ASSERT_EQ(static_cast<wchar_t>(0x00a2), out[1]);
354 ASSERT_EQ(static_cast<wchar_t>(0x20ac), out[2]);
355 ASSERT_EQ(static_cast<wchar_t>(0x24b62), out[3]);
Dan Albert6b55ba52014-07-20 11:51:26 -0700356 // Check that valid has advanced to the next unread character.
Calin Juravle15a63102014-05-08 14:38:35 +0100357 ASSERT_EQ('e', *valid);
358
Christopher Ferris5c7d9582014-11-13 15:48:39 -0800359 wmemset(out, L'x', NUM_WCHARS(sizeof(out)));
Dan Albert6b55ba52014-07-20 11:51:26 -0700360 ASSERT_EQ(2U, mbsrtowcs(out, &valid, 4, ps));
361 ASSERT_EQ(L'e', out[0]);
362 ASSERT_EQ(L'f', out[1]);
363 ASSERT_EQ(L'\0', out[2]);
364 // Check that we didn't clobber the rest of out.
365 ASSERT_EQ(L'x', out[3]);
366 // Check that valid has advanced to the end of the string.
Dan Albertb6cc8e02014-07-31 11:31:03 -0700367 ASSERT_EQ(nullptr, valid);
Dan Albert6b55ba52014-07-20 11:51:26 -0700368
Elliott Hughes89e29ee2016-09-29 17:21:43 -0700369 const char* invalid = INVALID;
Calin Juravle15a63102014-05-08 14:38:35 +0100370 ASSERT_EQ(static_cast<size_t>(-1), mbsrtowcs(out, &invalid, 4, ps));
371 EXPECT_EQ(EILSEQ, errno);
372 ASSERT_EQ('\xc2', *invalid);
373
Elliott Hughes89e29ee2016-09-29 17:21:43 -0700374 const char* incomplete = INCOMPLETE;
Calin Juravle15a63102014-05-08 14:38:35 +0100375 ASSERT_EQ(static_cast<size_t>(-1), mbsrtowcs(out, &incomplete, 2, ps));
376 EXPECT_EQ(EILSEQ, errno);
377 ASSERT_EQ('\xc2', *incomplete);
Elliott Hughes89e29ee2016-09-29 17:21:43 -0700378
379 // If dst is null, *src shouldn't be updated.
380 // https://code.google.com/p/android/issues/detail?id=166381
381 const char* mbs = VALID;
382 EXPECT_EQ(6U, mbsrtowcs(nullptr, &mbs, 0, ps));
383 EXPECT_EQ(VALID, mbs);
384 mbs = INVALID;
385 EXPECT_EQ(static_cast<size_t>(-1), mbsrtowcs(nullptr, &mbs, 0, ps));
386 EXPECT_EQ(INVALID, mbs);
387 mbs = INCOMPLETE;
388 EXPECT_EQ(static_cast<size_t>(-1), mbsrtowcs(nullptr, &mbs, 0, ps));
389 EXPECT_EQ(INCOMPLETE, mbs);
Calin Juravle15a63102014-05-08 14:38:35 +0100390}
391
392TEST(wchar, mbsrtowcs) {
393 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
394 uselocale(LC_GLOBAL_LOCALE);
395
396 mbstate_t ps;
397 memset(&ps, 0, sizeof(ps));
398 test_mbsrtowcs(&ps);
399 test_mbsrtowcs(NULL);
400
401 // Invalid multi byte continuation.
402 const char* invalid = "\x20";
403 wchar_t out;
404 ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(&out, "\xc2", 1, &ps));
405 ASSERT_EQ(static_cast<size_t>(-1), mbsrtowcs(&out, &invalid, 1, &ps));
406 EXPECT_EQ(EILSEQ, errno);
407 ASSERT_EQ('\x20', *invalid);
408}
409
Dan Albert6805c2d2017-08-09 14:55:27 -0700410template <typename T>
411using WcsToIntFn = T (*)(const wchar_t*, wchar_t**, int);
412
413template <typename T>
414void TestSingleWcsToInt(WcsToIntFn<T> fn, const wchar_t* str, int base,
415 T expected_value, ptrdiff_t expected_len) {
416 wchar_t* p;
417 ASSERT_EQ(expected_value, fn(str, &p, base));
418 ASSERT_EQ(expected_len, p - str) << str;
Elliott Hughes3d7a0d92014-04-29 14:46:56 -0700419}
420
Dan Albert6805c2d2017-08-09 14:55:27 -0700421template <typename T>
422void TestWcsToInt(WcsToIntFn<T> fn) {
423 TestSingleWcsToInt(fn, L"123", 10, static_cast<T>(123), 3);
424 TestSingleWcsToInt(fn, L"123", 0, static_cast<T>(123), 3);
425 TestSingleWcsToInt(fn, L"123#", 10, static_cast<T>(123), 3);
426 TestSingleWcsToInt(fn, L"01000", 8, static_cast<T>(512), 5);
427 TestSingleWcsToInt(fn, L"01000", 0, static_cast<T>(512), 5);
428 TestSingleWcsToInt(fn, L" 123 45", 0, static_cast<T>(123), 6);
429 TestSingleWcsToInt(fn, L" -123", 0, static_cast<T>(-123), 6);
430 TestSingleWcsToInt(fn, L"0x10000", 0, static_cast<T>(65536), 7);
431}
432
433template <typename T>
434void TestWcsToIntLimits(WcsToIntFn<T> fn, const wchar_t* min_str,
435 const wchar_t* max_str) {
436 if (std::is_signed<T>::value) {
437 ASSERT_EQ(std::numeric_limits<T>::min(), fn(min_str, nullptr, 0)) << min_str;
438 } else {
439 // If the subject sequence begins with a <hyphen-minus>, the value resulting
440 // from the conversion shall be negated.
441 // http://pubs.opengroup.org/onlinepubs/9699919799/functions/strtoul.html
442 ASSERT_EQ(std::numeric_limits<T>::max(), fn(min_str, nullptr, 0)) << min_str;
443 }
444 ASSERT_EQ(std::numeric_limits<T>::max(), fn(max_str, nullptr, 0)) << max_str;
445}
446
447TEST(wchar, wcstol) {
448 TestWcsToInt(wcstol);
449}
450
451TEST(wchar, wcstol_limits) {
452 if (sizeof(long) == 8) {
453 TestWcsToIntLimits(wcstol, L"-9223372036854775809", L"9223372036854775808");
454 } else {
455 TestWcsToIntLimits(wcstol, L"-2147483649", L"2147483648");
456 }
Elliott Hughes3d7a0d92014-04-29 14:46:56 -0700457}
458
Elliott Hughes3d7a0d92014-04-29 14:46:56 -0700459TEST(wchar, wcstoul) {
Dan Albert6805c2d2017-08-09 14:55:27 -0700460 TestWcsToInt(wcstoul);
461}
462
463TEST(wchar, wcstoul_limits) {
464 if (sizeof(long) == 8) {
465 TestWcsToIntLimits(wcstoul, L"-1", L"18446744073709551616");
466 } else {
467 TestWcsToIntLimits(wcstoul, L"-1", L"4294967296");
468 }
469}
470
471TEST(wchar, wcstoll) {
472 TestWcsToInt(wcstoll);
473}
474
475TEST(wchar, wcstoll_limits) {
476 TestWcsToIntLimits(wcstoll, L"-9223372036854775809", L"9223372036854775808");
Elliott Hughes3d7a0d92014-04-29 14:46:56 -0700477}
478
479TEST(wchar, wcstoull) {
Dan Albert6805c2d2017-08-09 14:55:27 -0700480 TestWcsToInt(wcstoull);
481}
482
483TEST(wchar, wcstoull_limits) {
484 TestWcsToIntLimits(wcstoull, L"-1", L"18446744073709551616");
485}
486
487TEST(wchar, wcstoimax) {
488 TestWcsToInt(wcstoimax);
489}
490
491TEST(wchar, wcstoimax_limits) {
492 TestWcsToIntLimits(wcstoimax, L"-9223372036854775809",
493 L"9223372036854775808");
494}
495
496TEST(wchar, wcstoumax) {
497 TestWcsToInt(wcstoumax);
498}
499
500TEST(wchar, wcstoumax_limits) {
501 TestWcsToIntLimits(wcstoumax, L"-1", L"18446744073709551616");
Elliott Hughes3d7a0d92014-04-29 14:46:56 -0700502}
503
504TEST(wchar, mbsnrtowcs) {
505 wchar_t dst[128];
506 const char* s = "hello, world!";
507 const char* src;
508
509 memset(dst, 0, sizeof(dst));
510 src = s;
511 ASSERT_EQ(0U, mbsnrtowcs(dst, &src, 0, 0, NULL));
512
513 memset(dst, 0, sizeof(dst));
514 src = s;
515 ASSERT_EQ(2U, mbsnrtowcs(dst, &src, 2, 123, NULL)); // glibc chokes on SIZE_MAX here.
516 ASSERT_EQ(L'h', dst[0]);
517 ASSERT_EQ(L'e', dst[1]);
518 ASSERT_EQ(&s[2], src);
519
520 memset(dst, 0, sizeof(dst));
521 src = s;
522 ASSERT_EQ(3U, mbsnrtowcs(dst, &src, SIZE_MAX, 3, NULL));
523 ASSERT_EQ(L'h', dst[0]);
524 ASSERT_EQ(L'e', dst[1]);
525 ASSERT_EQ(L'l', dst[2]);
526 ASSERT_EQ(&s[3], src);
Elliott Hughes697f42a2017-07-14 17:00:05 -0700527
528 memset(dst, 0, sizeof(dst));
529 const char* incomplete = "\xc2"; // Incomplete UTF-8 sequence.
530 src = incomplete;
531 errno = 0;
532 ASSERT_EQ(static_cast<size_t>(-1), mbsnrtowcs(dst, &src, SIZE_MAX, 3, nullptr));
533 ASSERT_EQ(EILSEQ, errno);
534
535 src = incomplete;
536 errno = 0;
537 ASSERT_EQ(static_cast<size_t>(-1), mbsnrtowcs(nullptr, &src, SIZE_MAX, 3, nullptr));
538 ASSERT_EQ(EILSEQ, errno);
Elliott Hughes3d7a0d92014-04-29 14:46:56 -0700539}
Elliott Hughesefaa4612014-05-02 15:53:03 -0700540
541TEST(wchar, wcsftime) {
542 setenv("TZ", "UTC", 1);
543
544 struct tm t;
545 memset(&t, 0, sizeof(tm));
546 t.tm_year = 200;
547 t.tm_mon = 2;
548 t.tm_mday = 10;
549
550 wchar_t buf[64];
551
552 EXPECT_EQ(24U, wcsftime(buf, sizeof(buf), L"%c", &t));
553 EXPECT_STREQ(L"Sun Mar 10 00:00:00 2100", buf);
554}
Bernhard Rosenkraenzer6f2bde32014-05-23 17:44:18 +0200555
Christopher Ferris5c7d9582014-11-13 15:48:39 -0800556TEST(wchar, wmemmove_smoke) {
Bernhard Rosenkraenzer6f2bde32014-05-23 17:44:18 +0200557 const wchar_t const_wstr[] = L"This is a test of something or other.....";
Christopher Ferris5c7d9582014-11-13 15:48:39 -0800558 wchar_t wstr[NUM_WCHARS(sizeof(const_wstr))];
Bernhard Rosenkraenzer6f2bde32014-05-23 17:44:18 +0200559
Christopher Ferris5c7d9582014-11-13 15:48:39 -0800560 EXPECT_EQ(wstr, wmemmove(wstr, const_wstr, NUM_WCHARS(sizeof(const_wstr))));
Bernhard Rosenkraenzer6f2bde32014-05-23 17:44:18 +0200561 EXPECT_STREQ(const_wstr, wstr);
562
Christopher Ferris5c7d9582014-11-13 15:48:39 -0800563 EXPECT_EQ(wstr+5, wmemmove(wstr+5, wstr, NUM_WCHARS(sizeof(const_wstr)) - 6));
Christopher Ferris8bf50d52014-05-29 15:42:42 -0700564 EXPECT_STREQ(L"This This is a test of something or other", wstr);
Bernhard Rosenkraenzer6f2bde32014-05-23 17:44:18 +0200565}
Elliott Hughes69f05d22014-06-05 20:10:09 -0700566
Christopher Ferris5c7d9582014-11-13 15:48:39 -0800567TEST(wchar, wmemcpy_smoke) {
568 const wchar_t src[] = L"Source string";
569 wchar_t dst[NUM_WCHARS(sizeof(src))];
570
571 EXPECT_EQ(dst, wmemcpy(dst, src, NUM_WCHARS(sizeof(src))));
572 EXPECT_STREQ(dst, src);
573}
574
575TEST(wchar, wcpcpy_smoke) {
576 const wchar_t src[] = L"Source string";
577 wchar_t dst[NUM_WCHARS(sizeof(src))];
578
579 EXPECT_EQ(dst + NUM_WCHARS(sizeof(src)) - 1, wcpcpy(dst, src));
580 EXPECT_STREQ(dst, src);
581}
582
583TEST(wchar, wcpncpy_smoke) {
584 const wchar_t src[] = L"Source string";
585 wchar_t dst[NUM_WCHARS(sizeof(src)) + 5];
586
587 size_t src_len = NUM_WCHARS(sizeof(src)) - 1;
588 EXPECT_EQ(dst + src_len, wcpncpy(dst, src, src_len + 1));
589 EXPECT_STREQ(dst, src);
590
591 EXPECT_EQ(dst + 6, wcpncpy(dst, src, 6));
592 dst[6] = L'\0';
593 EXPECT_STREQ(dst, L"Source");
594
595 wmemset(dst, L'x', NUM_WCHARS(sizeof(dst)));
596 EXPECT_EQ(dst + src_len, wcpncpy(dst, src, src_len + 4));
597 EXPECT_STREQ(dst, src);
598 EXPECT_EQ(dst[src_len], L'\0');
599 EXPECT_EQ(dst[src_len+1], L'\0');
600 EXPECT_EQ(dst[src_len+2], L'\0');
601 EXPECT_EQ(dst[src_len+3], L'\0');
602 EXPECT_EQ(dst[src_len+4], L'x');
603}
604
605TEST(wchar, wcscpy_smoke) {
606 const wchar_t src[] = L"Source string";
607 wchar_t dst[NUM_WCHARS(sizeof(src))];
608
609 EXPECT_EQ(dst, wcscpy(dst, src));
610 EXPECT_STREQ(src, dst);
611}
612
613TEST(wchar, wcsncpy_smoke) {
614 const wchar_t src[] = L"Source string";
615 wchar_t dst[NUM_WCHARS(sizeof(src)) + 5];
616
617 size_t src_len = NUM_WCHARS(sizeof(src)) - 1;
618 EXPECT_EQ(dst, wcsncpy(dst, src, src_len + 1));
619 EXPECT_STREQ(dst, src);
620
621 EXPECT_EQ(dst, wcsncpy(dst, src, 6));
622 dst[6] = L'\0';
623 EXPECT_STREQ(dst, L"Source");
624
625 wmemset(dst, L'x', NUM_WCHARS(sizeof(dst)));
626 EXPECT_EQ(dst, wcsncpy(dst, src, src_len + 4));
627 EXPECT_STREQ(dst, src);
628 EXPECT_EQ(dst[src_len], L'\0');
629 EXPECT_EQ(dst[src_len+1], L'\0');
630 EXPECT_EQ(dst[src_len+2], L'\0');
631 EXPECT_EQ(dst[src_len+3], L'\0');
632 EXPECT_EQ(dst[src_len+4], L'x');
633}
634
Elliott Hughes69f05d22014-06-05 20:10:09 -0700635TEST(wchar, mbrtowc_15439554) {
636 // http://b/15439554
637 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
638 uselocale(LC_GLOBAL_LOCALE);
639
640 ASSERT_GE(static_cast<size_t>(MB_LEN_MAX), MB_CUR_MAX);
641 ASSERT_GE(MB_CUR_MAX, 4U);
642
643 wchar_t wc;
644 size_t n;
645
646 // 1-byte character.
647 n = mbrtowc(&wc, "x", MB_CUR_MAX, NULL);
648 EXPECT_EQ(1U, n);
649 EXPECT_EQ(L'x', wc);
650 // 2-byte character.
651 n = mbrtowc(&wc, "\xc2\xa2", MB_CUR_MAX, NULL);
652 EXPECT_EQ(2U, n);
653 EXPECT_EQ(L'¢', wc);
654 // 3-byte character.
655 n = mbrtowc(&wc, "\xe2\x82\xac", MB_CUR_MAX, NULL);
656 EXPECT_EQ(3U, n);
657 EXPECT_EQ(L'€', wc);
658 // 4-byte character.
659 n = mbrtowc(&wc, "\xf0\xa4\xad\xa2", MB_CUR_MAX, NULL);
660 EXPECT_EQ(4U, n);
661 EXPECT_EQ(L'𤭢', wc);
662}
Elliott Hughes6b841db2014-08-20 16:10:49 -0700663
664TEST(wchar, open_wmemstream) {
665 wchar_t* p = nullptr;
666 size_t size = 0;
667 FILE* fp = open_wmemstream(&p, &size);
668 ASSERT_NE(EOF, fputws(L"hello, world!", fp));
669 fclose(fp);
670
671 ASSERT_STREQ(L"hello, world!", p);
672 ASSERT_EQ(wcslen(L"hello, world!"), size);
673 free(p);
674}
675
676TEST(stdio, open_wmemstream_EINVAL) {
677#if defined(__BIONIC__)
678 wchar_t* p;
679 size_t size;
680
681 // Invalid buffer.
682 errno = 0;
683 ASSERT_EQ(nullptr, open_wmemstream(nullptr, &size));
684 ASSERT_EQ(EINVAL, errno);
685
686 // Invalid size.
687 errno = 0;
688 ASSERT_EQ(nullptr, open_wmemstream(&p, nullptr));
689 ASSERT_EQ(EINVAL, errno);
690#else
691 GTEST_LOG_(INFO) << "This test does nothing.\n";
692#endif
693}
Elliott Hughesb05ec5a2014-09-23 14:53:10 -0700694
695TEST(wchar, wcstol_EINVAL) {
696 errno = 0;
697 wcstol(L"123", NULL, -1);
698 ASSERT_EQ(EINVAL, errno);
699 errno = 0;
700 wcstol(L"123", NULL, 1);
701 ASSERT_EQ(EINVAL, errno);
702 errno = 0;
703 wcstol(L"123", NULL, 37);
704 ASSERT_EQ(EINVAL, errno);
705}
706
707TEST(wchar, wcstoll_EINVAL) {
708 errno = 0;
709 wcstoll(L"123", NULL, -1);
710 ASSERT_EQ(EINVAL, errno);
711 errno = 0;
712 wcstoll(L"123", NULL, 1);
713 ASSERT_EQ(EINVAL, errno);
714 errno = 0;
715 wcstoll(L"123", NULL, 37);
716 ASSERT_EQ(EINVAL, errno);
717}
718
719TEST(wchar, wcstoul_EINVAL) {
720 errno = 0;
721 wcstoul(L"123", NULL, -1);
722 ASSERT_EQ(EINVAL, errno);
723 errno = 0;
724 wcstoul(L"123", NULL, 1);
725 ASSERT_EQ(EINVAL, errno);
726 errno = 0;
727 wcstoul(L"123", NULL, 37);
728 ASSERT_EQ(EINVAL, errno);
729}
730
731TEST(wchar, wcstoull_EINVAL) {
732 errno = 0;
733 wcstoull(L"123", NULL, -1);
734 ASSERT_EQ(EINVAL, errno);
735 errno = 0;
736 wcstoull(L"123", NULL, 1);
737 ASSERT_EQ(EINVAL, errno);
738 errno = 0;
739 wcstoull(L"123", NULL, 37);
740 ASSERT_EQ(EINVAL, errno);
741}
742
743TEST(wchar, wcstoll_l_EINVAL) {
744 errno = 0;
745 wcstoll_l(L"123", NULL, -1, LC_GLOBAL_LOCALE);
746 ASSERT_EQ(EINVAL, errno);
747 errno = 0;
748 wcstoll_l(L"123", NULL, 1, LC_GLOBAL_LOCALE);
749 ASSERT_EQ(EINVAL, errno);
750 errno = 0;
751 wcstoll_l(L"123", NULL, 37, LC_GLOBAL_LOCALE);
752 ASSERT_EQ(EINVAL, errno);
753}
754
755TEST(wchar, wcstoull_l_EINVAL) {
756 errno = 0;
757 wcstoull_l(L"123", NULL, -1, LC_GLOBAL_LOCALE);
758 ASSERT_EQ(EINVAL, errno);
759 errno = 0;
760 wcstoull_l(L"123", NULL, 1, LC_GLOBAL_LOCALE);
761 ASSERT_EQ(EINVAL, errno);
762 errno = 0;
763 wcstoull_l(L"123", NULL, 37, LC_GLOBAL_LOCALE);
764 ASSERT_EQ(EINVAL, errno);
765}
Elliott Hughes3cfb52a2015-02-18 21:29:13 -0800766
767TEST(wchar, wmempcpy) {
768 wchar_t dst[6];
769 ASSERT_EQ(&dst[4], wmempcpy(dst, L"hello", 4));
770}
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700771
772template <typename T>
Dan Albert6805c2d2017-08-09 14:55:27 -0700773using WcsToFloatFn = T (*)(const wchar_t*, wchar_t**);
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700774
Dan Albert6805c2d2017-08-09 14:55:27 -0700775template <typename T>
776void TestSingleWcsToFloat(WcsToFloatFn<T> fn, const wchar_t* str,
777 T expected_value, ptrdiff_t expected_len) {
Dan Albertf6346552016-12-02 12:02:03 -0800778 wchar_t* p;
Dan Albert6805c2d2017-08-09 14:55:27 -0700779 ASSERT_EQ(expected_value, fn(str, &p));
780 ASSERT_EQ(expected_len, p - str);
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700781}
782
Dan Albert6805c2d2017-08-09 14:55:27 -0700783template <typename T>
784void TestWcsToFloat(WcsToFloatFn<T> fn) {
785 TestSingleWcsToFloat(fn, L"123", static_cast<T>(123.0), 3);
786 TestSingleWcsToFloat(fn, L"123#", static_cast<T>(123.0), 3);
787 TestSingleWcsToFloat(fn, L" 123 45", static_cast<T>(123.0), 6);
788 TestSingleWcsToFloat(fn, L"9.0", static_cast<T>(9.0), 3);
789 TestSingleWcsToFloat(fn, L"-9.0", static_cast<T>(-9.0), 4);
790 TestSingleWcsToFloat(fn, L" \t\v\f\r\n9.0", static_cast<T>(9.0), 9);
791}
792
793template <typename T>
794void TestWcsToFloatHexFloats(WcsToFloatFn<T> fn) {
795 TestSingleWcsToFloat(fn, L"0.9e1", static_cast<T>(9.0), 5);
796 TestSingleWcsToFloat(fn, L"0x1.2p3", static_cast<T>(9.0), 7);
797 TestSingleWcsToFloat(fn, L"+1e+100", static_cast<T>(1e100), 7);
798 TestSingleWcsToFloat(fn, L"0x10000.80", static_cast<T>(65536.50), 10);
799}
800
801template <typename T>
802void TestWcsToFloatInfNan(WcsToFloatFn<T> fn) {
803 ASSERT_TRUE(isnan(fn(L"+nan", nullptr)));
804 ASSERT_TRUE(isnan(fn(L"nan", nullptr)));
805 ASSERT_TRUE(isnan(fn(L"-nan", nullptr)));
806
807 ASSERT_TRUE(isnan(fn(L"+nan(0xff)", nullptr)));
808 ASSERT_TRUE(isnan(fn(L"nan(0xff)", nullptr)));
809 ASSERT_TRUE(isnan(fn(L"-nan(0xff)", nullptr)));
810
811 wchar_t* p;
812 ASSERT_TRUE(isnan(fn(L"+nanny", &p)));
813 ASSERT_STREQ(L"ny", p);
814 ASSERT_TRUE(isnan(fn(L"nanny", &p)));
815 ASSERT_STREQ(L"ny", p);
816 ASSERT_TRUE(isnan(fn(L"-nanny", &p)));
817 ASSERT_STREQ(L"ny", p);
818
819 ASSERT_EQ(0, fn(L"muppet", &p));
820 ASSERT_STREQ(L"muppet", p);
821 ASSERT_EQ(0, fn(L" muppet", &p));
822 ASSERT_STREQ(L" muppet", p);
823
824 ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"+inf", nullptr));
825 ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"inf", nullptr));
826 ASSERT_EQ(-std::numeric_limits<T>::infinity(), fn(L"-inf", nullptr));
827
828 ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"+infinity", nullptr));
829 ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"infinity", nullptr));
830 ASSERT_EQ(-std::numeric_limits<T>::infinity(), fn(L"-infinity", nullptr));
831
832 ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"+infinitude", &p));
833 ASSERT_STREQ(L"initude", p);
834 ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"infinitude", &p));
835 ASSERT_STREQ(L"initude", p);
836 ASSERT_EQ(-std::numeric_limits<T>::infinity(), fn(L"-infinitude", &p));
837 ASSERT_STREQ(L"initude", p);
838
839 // Check case-insensitivity.
840 ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"InFiNiTy", nullptr));
841 ASSERT_TRUE(isnan(fn(L"NaN", nullptr)));
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700842}
843
844TEST(wchar, wcstof) {
Dan Albert6805c2d2017-08-09 14:55:27 -0700845 TestWcsToFloat(wcstof);
846}
847
848TEST(wchar, wcstof_hex_floats) {
849 TestWcsToFloatHexFloats(wcstof);
850}
851
852TEST(wchar, wcstof_hex_inf_nan) {
853 TestWcsToFloatInfNan(wcstof);
854}
855
856TEST(wchar, wcstod) {
857 TestWcsToFloat(wcstod);
858}
859
860TEST(wchar, wcstod_hex_floats) {
861 TestWcsToFloatHexFloats(wcstod);
862}
863
864TEST(wchar, wcstod_hex_inf_nan) {
865 TestWcsToFloatInfNan(wcstod);
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700866}
867
868TEST(wchar, wcstold) {
Dan Albert6805c2d2017-08-09 14:55:27 -0700869 TestWcsToFloat(wcstold);
870}
871
872TEST(wchar, wcstold_hex_floats) {
873 TestWcsToFloatHexFloats(wcstold);
874}
875
876TEST(wchar, wcstold_hex_inf_nan) {
877 TestWcsToFloatInfNan(wcstold);
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700878}
Elliott Hughesc41b5602017-07-27 17:08:08 -0700879
880static void AssertWcwidthRange(wchar_t begin, wchar_t end, int expected) {
881 for (wchar_t i = begin; i < end; ++i) {
882 EXPECT_EQ(expected, wcwidth(i)) << static_cast<int>(i);
883 }
884}
885
886TEST(wchar, wcwidth_NUL) {
887 // NUL is defined to return 0 rather than -1, despite being a C0 control.
888 EXPECT_EQ(0, wcwidth(0));
889}
890
891TEST(wchar, wcwidth_ascii) {
892 AssertWcwidthRange(0x20, 0x7f, 1); // Non-C0 non-DEL ASCII.
893}
894
895TEST(wchar, wcwidth_controls) {
896 AssertWcwidthRange(0x01, 0x20, -1); // C0 controls.
897 EXPECT_EQ(-1, wcwidth(0x7f)); // DEL.
898 AssertWcwidthRange(0x80, 0xa0, -1); // C1 controls.
899}
900
901TEST(wchar, wcwidth_non_spacing_and_enclosing_marks_and_format) {
902 EXPECT_EQ(0, wcwidth(0x0300)); // Combining grave.
903 EXPECT_EQ(0, wcwidth(0x20dd)); // Combining enclosing circle.
904 EXPECT_EQ(0, wcwidth(0x00ad)); // Soft hyphen (SHY).
905 EXPECT_EQ(0, wcwidth(0x200b)); // Zero width space.
906}
907
908TEST(wchar, wcwidth_cjk) {
909 EXPECT_EQ(2, wcwidth(0x4e00)); // Start of CJK unified block.
910 EXPECT_EQ(2, wcwidth(0x9fff)); // End of CJK unified block.
911 EXPECT_EQ(2, wcwidth(0x3400)); // Start of CJK extension A block.
912 EXPECT_EQ(2, wcwidth(0x4dbf)); // End of CJK extension A block.
913 EXPECT_EQ(2, wcwidth(0x20000)); // Start of CJK extension B block.
914 EXPECT_EQ(2, wcwidth(0x2a6df)); // End of CJK extension B block.
915}
916
917TEST(wchar, wcwidth_korean_combining_jamo) {
918 AssertWcwidthRange(0x1160, 0x1200, 0); // Original range.
919 EXPECT_EQ(0, wcwidth(0xd7b0)); // Newer.
920 EXPECT_EQ(0, wcwidth(0xd7cb));
921}
922
923TEST(wchar, wcwidth_korean_jeongeul_syllables) {
924 EXPECT_EQ(2, wcwidth(0xac00)); // Start of block.
925 EXPECT_EQ(2, wcwidth(0xd7a3)); // End of defined code points in Unicode 7.
926 // Undefined characters at the end of the block have width 1.
927}
928
929TEST(wchar, wcwidth_kana) {
930 // Hiragana (most, not undefined).
931 AssertWcwidthRange(0x3041, 0x3097, 2);
932 // Katakana.
933 AssertWcwidthRange(0x30a0, 0x3100, 2);
934}
935
936TEST(wchar, wcwidth_circled_two_digit_cjk) {
937 // Circled two-digit CJK "speed sign" numbers are wide,
938 // though EastAsianWidth is ambiguous.
939 AssertWcwidthRange(0x3248, 0x3250, 2);
940}
941
942TEST(wchar, wcwidth_hexagrams) {
943 // Hexagrams are wide, though EastAsianWidth is neutral.
944 AssertWcwidthRange(0x4dc0, 0x4e00, 2);
945}
946
947TEST(wchar, wcwidth_default_ignorables) {
948 AssertWcwidthRange(0xfff0, 0xfff8, 0); // Unassigned by default ignorable.
949 EXPECT_EQ(0, wcwidth(0xe0000)); // ...through 0xe0fff.
950}
951
952TEST(wchar, wcwidth_korean_common_non_syllables) {
953 EXPECT_EQ(2, wcwidth(L'ㅜ')); // Korean "crying" emoticon.
954 EXPECT_EQ(2, wcwidth(L'ㅋ')); // Korean "laughing" emoticon.
955}