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 <inttypes.h> 21 #include <limits.h> 22 #include <locale.h> 23 #include <math.h> 24 #include <stdint.h> 25 #include <wchar.h> 26 27 #include "utils.h" 28 29 #define NUM_WCHARS(num_bytes) ((num_bytes)/sizeof(wchar_t)) 30 31 TEST(wchar, sizeof_wchar_t) { 32 EXPECT_EQ(4U, sizeof(wchar_t)); 33 EXPECT_EQ(4U, sizeof(wint_t)); 34 } 35 36 TEST(wchar, mbrlen) { 37 char bytes[] = { 'h', 'e', 'l', 'l', 'o', '\0' }; 38 EXPECT_EQ(0U, mbrlen(&bytes[0], 0, NULL)); 39 EXPECT_EQ(1U, mbrlen(&bytes[0], 1, NULL)); 40 41 EXPECT_EQ(1U, mbrlen(&bytes[4], 1, NULL)); 42 EXPECT_EQ(0U, mbrlen(&bytes[5], 1, NULL)); 43 } 44 45 TEST(wchar, wctomb_wcrtomb) { 46 // wctomb and wcrtomb behave differently when s == NULL. 47 EXPECT_EQ(0, wctomb(NULL, L'h')); 48 EXPECT_EQ(0, wctomb(NULL, L'\0')); 49 EXPECT_EQ(1U, wcrtomb(NULL, L'\0', NULL)); 50 EXPECT_EQ(1U, wcrtomb(NULL, L'h', NULL)); 51 52 char bytes[MB_LEN_MAX]; 53 54 // wctomb and wcrtomb behave similarly for the null wide character. 55 EXPECT_EQ(1, wctomb(bytes, L'\0')); 56 EXPECT_EQ(1U, wcrtomb(bytes, L'\0', NULL)); 57 58 // ...and for regular characters. 59 memset(bytes, 0, sizeof(bytes)); 60 EXPECT_EQ(1, wctomb(bytes, L'h')); 61 EXPECT_EQ('h', bytes[0]); 62 memset(bytes, 0, sizeof(bytes)); 63 EXPECT_EQ(1U, wcrtomb(bytes, L'h', NULL)); 64 EXPECT_EQ('h', bytes[0]); 65 66 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8")); 67 uselocale(LC_GLOBAL_LOCALE); 68 69 // 1-byte UTF-8. 70 memset(bytes, 0, sizeof(bytes)); 71 EXPECT_EQ(1U, wcrtomb(bytes, L'h', NULL)); 72 EXPECT_EQ('h', bytes[0]); 73 // 2-byte UTF-8. 74 memset(bytes, 0, sizeof(bytes)); 75 EXPECT_EQ(2U, wcrtomb(bytes, 0x00a2, NULL)); 76 EXPECT_EQ('\xc2', bytes[0]); 77 EXPECT_EQ('\xa2', bytes[1]); 78 // 3-byte UTF-8. 79 memset(bytes, 0, sizeof(bytes)); 80 EXPECT_EQ(3U, wcrtomb(bytes, 0x20ac, NULL)); 81 EXPECT_EQ('\xe2', bytes[0]); 82 EXPECT_EQ('\x82', bytes[1]); 83 EXPECT_EQ('\xac', bytes[2]); 84 // 4-byte UTF-8. 85 memset(bytes, 0, sizeof(bytes)); 86 EXPECT_EQ(4U, wcrtomb(bytes, 0x24b62, NULL)); 87 EXPECT_EQ('\xf0', bytes[0]); 88 EXPECT_EQ('\xa4', bytes[1]); 89 EXPECT_EQ('\xad', bytes[2]); 90 EXPECT_EQ('\xa2', bytes[3]); 91 // Invalid code point. 92 EXPECT_EQ(static_cast<size_t>(-1), wcrtomb(bytes, 0xffffffff, NULL)); 93 EXPECT_EQ(EILSEQ, errno); 94 } 95 96 TEST(wchar, wcrtomb_start_state) { 97 char out[MB_LEN_MAX]; 98 mbstate_t ps; 99 100 // Any non-initial state is invalid when calling wcrtomb. 101 memset(&ps, 0, sizeof(ps)); 102 EXPECT_EQ(static_cast<size_t>(-2), mbrtowc(NULL, "\xc2", 1, &ps)); 103 EXPECT_EQ(static_cast<size_t>(-1), wcrtomb(out, 0x00a2, &ps)); 104 EXPECT_EQ(EILSEQ, errno); 105 106 // If the first argument to wcrtomb is NULL or the second is L'\0' the shift 107 // state should be reset. 108 memset(&ps, 0, sizeof(ps)); 109 EXPECT_EQ(static_cast<size_t>(-2), mbrtowc(NULL, "\xc2", 1, &ps)); 110 EXPECT_EQ(1U, wcrtomb(NULL, 0x00a2, &ps)); 111 EXPECT_TRUE(mbsinit(&ps)); 112 113 memset(&ps, 0, sizeof(ps)); 114 EXPECT_EQ(static_cast<size_t>(-2), mbrtowc(NULL, "\xf0\xa4", 1, &ps)); 115 EXPECT_EQ(1U, wcrtomb(out, L'\0', &ps)); 116 EXPECT_TRUE(mbsinit(&ps)); 117 } 118 119 TEST(wchar, wcstombs_wcrtombs) { 120 const wchar_t chars[] = { L'h', L'e', L'l', L'l', L'o', 0 }; 121 const wchar_t bad_chars[] = { L'h', L'i', static_cast<wchar_t>(0xffffffff), 0 }; 122 const wchar_t* src; 123 char bytes[BUFSIZ]; 124 125 // Given a NULL destination, these functions count valid characters. 126 EXPECT_EQ(5U, wcstombs(NULL, chars, 0)); 127 EXPECT_EQ(5U, wcstombs(NULL, chars, 4)); 128 EXPECT_EQ(5U, wcstombs(NULL, chars, 256)); 129 src = chars; 130 EXPECT_EQ(5U, wcsrtombs(NULL, &src, 0, NULL)); 131 EXPECT_EQ(&chars[0], src); 132 src = chars; 133 EXPECT_EQ(5U, wcsrtombs(NULL, &src, 4, NULL)); 134 EXPECT_EQ(&chars[0], src); 135 src = chars; 136 EXPECT_EQ(5U, wcsrtombs(NULL, &src, 256, NULL)); 137 EXPECT_EQ(&chars[0], src); 138 139 // An unrepresentable char just returns an error from wcstombs... 140 errno = 0; 141 EXPECT_EQ(static_cast<size_t>(-1), wcstombs(NULL, bad_chars, 0)); 142 EXPECT_EQ(EILSEQ, errno); 143 errno = 0; 144 EXPECT_EQ(static_cast<size_t>(-1), wcstombs(NULL, bad_chars, 256)); 145 EXPECT_EQ(EILSEQ, errno); 146 147 // And wcsrtombs doesn't tell us where it got stuck because we didn't ask it 148 // to actually convert anything... 149 errno = 0; 150 src = bad_chars; 151 EXPECT_EQ(static_cast<size_t>(-1), wcsrtombs(NULL, &src, 0, NULL)); 152 EXPECT_EQ(&bad_chars[0], src); 153 EXPECT_EQ(EILSEQ, errno); 154 errno = 0; 155 src = bad_chars; 156 EXPECT_EQ(static_cast<size_t>(-1), wcsrtombs(NULL, &src, 256, NULL)); 157 EXPECT_EQ(&bad_chars[0], src); 158 EXPECT_EQ(EILSEQ, errno); 159 160 // Okay, now let's test actually converting something... 161 memset(bytes, 'x', sizeof(bytes)); 162 EXPECT_EQ(0U, wcstombs(bytes, chars, 0)); 163 memset(bytes, 'x', sizeof(bytes)); 164 EXPECT_EQ(4U, wcstombs(bytes, chars, 4)); 165 bytes[5] = 0; 166 EXPECT_STREQ("hellx", bytes); 167 memset(bytes, 'x', sizeof(bytes)); 168 EXPECT_EQ(5U, wcstombs(bytes, chars, 256)); 169 EXPECT_STREQ("hello", bytes); 170 memset(bytes, 'x', sizeof(bytes)); 171 EXPECT_EQ(5U, wcstombs(bytes, chars, 6)); 172 EXPECT_STREQ("hello", bytes); 173 errno = 0; 174 memset(bytes, 'x', sizeof(bytes)); 175 EXPECT_EQ(static_cast<size_t>(-1), wcstombs(bytes, bad_chars, 256)); 176 EXPECT_EQ(EILSEQ, errno); 177 bytes[3] = 0; 178 EXPECT_STREQ("hix", bytes); 179 180 // wcsrtombs is a bit more informative... 181 memset(bytes, 'x', sizeof(bytes)); 182 src = chars; 183 EXPECT_EQ(0U, wcsrtombs(bytes, &src, 0, NULL)); 184 EXPECT_EQ(&chars[0], src); // No input consumed. 185 EXPECT_EQ(EILSEQ, errno); 186 187 memset(bytes, 'x', sizeof(bytes)); 188 src = chars; 189 EXPECT_EQ(4U, wcsrtombs(bytes, &src, 4, NULL)); 190 EXPECT_EQ(&chars[4], src); // Some input consumed. 191 EXPECT_EQ(EILSEQ, errno); 192 bytes[5] = 0; 193 EXPECT_STREQ("hellx", bytes); 194 195 memset(bytes, 'x', sizeof(bytes)); 196 src = chars; 197 EXPECT_EQ(5U, wcsrtombs(bytes, &src, 256, NULL)); 198 EXPECT_EQ(NULL, src); // All input consumed! 199 EXPECT_EQ(EILSEQ, errno); 200 EXPECT_STREQ("hello", bytes); 201 202 memset(bytes, 'x', sizeof(bytes)); 203 src = chars; 204 EXPECT_EQ(5U, wcsrtombs(bytes, &src, 6, NULL)); 205 EXPECT_EQ(NULL, src); // All input consumed. 206 EXPECT_EQ(EILSEQ, errno); 207 EXPECT_STREQ("hello", bytes); 208 209 memset(bytes, 'x', sizeof(bytes)); 210 src = bad_chars; 211 EXPECT_EQ(static_cast<size_t>(-1), wcsrtombs(bytes, &src, 256, NULL)); 212 EXPECT_EQ(&bad_chars[2], src); 213 EXPECT_EQ(EILSEQ, errno); 214 bytes[3] = 0; 215 EXPECT_STREQ("hix", bytes); 216 217 // Any non-initial state is invalid when calling wcsrtombs. 218 mbstate_t ps; 219 src = chars; 220 memset(&ps, 0, sizeof(ps)); 221 ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(NULL, "\xc2", 1, &ps)); 222 EXPECT_EQ(static_cast<size_t>(-1), wcsrtombs(NULL, &src, 0, &ps)); 223 EXPECT_EQ(EILSEQ, errno); 224 } 225 226 TEST(wchar, limits) { 227 ASSERT_LT(WCHAR_MIN, WCHAR_MAX); 228 } 229 230 TEST(wchar, wcsstr) { 231 const wchar_t* haystack = L"matches hello world, not the second hello world"; 232 const wchar_t* empty_needle = L""; 233 const wchar_t* good_needle = L"ll"; 234 const wchar_t* bad_needle = L"wort"; 235 236 ASSERT_EQ(haystack, wcsstr(haystack, empty_needle)); 237 ASSERT_EQ(&haystack[10], wcsstr(haystack, good_needle)); 238 ASSERT_EQ(NULL, wcsstr(haystack, bad_needle)); 239 } 240 241 TEST(wchar, wcsstr_80199) { 242 // https://code.google.com/p/android/issues/detail?id=80199 243 ASSERT_TRUE(wcsstr(L"romrom", L"rom") != NULL); 244 } 245 246 TEST(wchar, mbtowc) { 247 wchar_t out[8]; 248 249 out[0] = 'x'; 250 ASSERT_EQ(0, mbtowc(out, "hello", 0)); 251 ASSERT_EQ('x', out[0]); 252 253 ASSERT_EQ(0, mbtowc(out, "hello", 0)); 254 ASSERT_EQ(0, mbtowc(out, "", 0)); 255 ASSERT_EQ(1, mbtowc(out, "hello", 1)); 256 ASSERT_EQ(L'h', out[0]); 257 258 ASSERT_EQ(0, mbtowc(NULL, "hello", 0)); 259 ASSERT_EQ(0, mbtowc(NULL, "", 0)); 260 ASSERT_EQ(1, mbtowc(NULL, "hello", 1)); 261 262 ASSERT_EQ(0, mbtowc(NULL, NULL, 0)); 263 } 264 265 TEST(wchar, mbrtowc) { 266 wchar_t out[8]; 267 268 out[0] = 'x'; 269 ASSERT_EQ(0U, mbrtowc(out, "hello", 0, NULL)); 270 ASSERT_EQ('x', out[0]); 271 272 ASSERT_EQ(0U, mbrtowc(out, "hello", 0, NULL)); 273 ASSERT_EQ(0U, mbrtowc(out, "", 0, NULL)); 274 ASSERT_EQ(1U, mbrtowc(out, "hello", 1, NULL)); 275 ASSERT_EQ(L'h', out[0]); 276 277 ASSERT_EQ(0U, mbrtowc(NULL, "hello", 0, NULL)); 278 ASSERT_EQ(0U, mbrtowc(NULL, "", 0, NULL)); 279 ASSERT_EQ(1U, mbrtowc(NULL, "hello", 1, NULL)); 280 281 ASSERT_EQ(0U, mbrtowc(NULL, NULL, 0, NULL)); 282 283 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8")); 284 uselocale(LC_GLOBAL_LOCALE); 285 286 // 1-byte UTF-8. 287 ASSERT_EQ(1U, mbrtowc(out, "abcdef", 6, NULL)); 288 ASSERT_EQ(L'a', out[0]); 289 // 2-byte UTF-8. 290 ASSERT_EQ(2U, mbrtowc(out, "\xc2\xa2" "cdef", 6, NULL)); 291 ASSERT_EQ(static_cast<wchar_t>(0x00a2), out[0]); 292 // 3-byte UTF-8. 293 ASSERT_EQ(3U, mbrtowc(out, "\xe2\x82\xac" "def", 6, NULL)); 294 ASSERT_EQ(static_cast<wchar_t>(0x20ac), out[0]); 295 // 4-byte UTF-8. 296 ASSERT_EQ(4U, mbrtowc(out, "\xf0\xa4\xad\xa2" "ef", 6, NULL)); 297 ASSERT_EQ(static_cast<wchar_t>(0x24b62), out[0]); 298 #if defined(__BIONIC__) // glibc allows this. 299 // Illegal 5-byte UTF-8. 300 ASSERT_EQ(static_cast<size_t>(-1), mbrtowc(out, "\xf8\xa1\xa2\xa3\xa4" "f", 6, NULL)); 301 ASSERT_EQ(EILSEQ, errno); 302 #endif 303 // Illegal over-long sequence. 304 ASSERT_EQ(static_cast<size_t>(-1), mbrtowc(out, "\xf0\x82\x82\xac" "ef", 6, NULL)); 305 ASSERT_EQ(EILSEQ, errno); 306 } 307 308 static void test_mbrtowc_incomplete(mbstate_t* ps) { 309 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8")); 310 uselocale(LC_GLOBAL_LOCALE); 311 312 wchar_t out; 313 // 2-byte UTF-8. 314 ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(&out, "\xc2", 1, ps)); 315 ASSERT_EQ(1U, mbrtowc(&out, "\xa2" "cdef", 5, ps)); 316 ASSERT_EQ(static_cast<wchar_t>(0x00a2), out); 317 ASSERT_TRUE(mbsinit(ps)); 318 // 3-byte UTF-8. 319 ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(&out, "\xe2", 1, ps)); 320 ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(&out, "\x82", 1, ps)); 321 ASSERT_EQ(1U, mbrtowc(&out, "\xac" "def", 4, ps)); 322 ASSERT_EQ(static_cast<wchar_t>(0x20ac), out); 323 ASSERT_TRUE(mbsinit(ps)); 324 // 4-byte UTF-8. 325 ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(&out, "\xf0", 1, ps)); 326 ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(&out, "\xa4\xad", 2, ps)); 327 ASSERT_EQ(1U, mbrtowc(&out, "\xa2" "ef", 3, ps)); 328 ASSERT_EQ(static_cast<wchar_t>(0x24b62), out); 329 ASSERT_TRUE(mbsinit(ps)); 330 331 // Invalid 2-byte 332 ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(&out, "\xc2", 1, ps)); 333 ASSERT_EQ(static_cast<size_t>(-1), mbrtowc(&out, "\x20" "cdef", 5, ps)); 334 ASSERT_EQ(EILSEQ, errno); 335 } 336 337 TEST(wchar, mbrtowc_incomplete) { 338 mbstate_t ps; 339 memset(&ps, 0, sizeof(ps)); 340 341 test_mbrtowc_incomplete(&ps); 342 test_mbrtowc_incomplete(NULL); 343 } 344 345 static void test_mbsrtowcs(mbstate_t* ps) { 346 constexpr const char* VALID = "A" "\xc2\xa2" "\xe2\x82\xac" "\xf0\xa4\xad\xa2" "ef"; 347 constexpr const char* INVALID = "A" "\xc2\x20" "ef"; 348 constexpr const char* INCOMPLETE = "A" "\xc2"; 349 wchar_t out[4]; 350 351 const char* valid = VALID; 352 ASSERT_EQ(4U, mbsrtowcs(out, &valid, 4, ps)); 353 ASSERT_EQ(L'A', out[0]); 354 ASSERT_EQ(static_cast<wchar_t>(0x00a2), out[1]); 355 ASSERT_EQ(static_cast<wchar_t>(0x20ac), out[2]); 356 ASSERT_EQ(static_cast<wchar_t>(0x24b62), out[3]); 357 // Check that valid has advanced to the next unread character. 358 ASSERT_EQ('e', *valid); 359 360 wmemset(out, L'x', NUM_WCHARS(sizeof(out))); 361 ASSERT_EQ(2U, mbsrtowcs(out, &valid, 4, ps)); 362 ASSERT_EQ(L'e', out[0]); 363 ASSERT_EQ(L'f', out[1]); 364 ASSERT_EQ(L'\0', out[2]); 365 // Check that we didn't clobber the rest of out. 366 ASSERT_EQ(L'x', out[3]); 367 // Check that valid has advanced to the end of the string. 368 ASSERT_EQ(nullptr, valid); 369 370 const char* invalid = INVALID; 371 ASSERT_EQ(static_cast<size_t>(-1), mbsrtowcs(out, &invalid, 4, ps)); 372 EXPECT_EQ(EILSEQ, errno); 373 ASSERT_EQ('\xc2', *invalid); 374 375 const char* incomplete = INCOMPLETE; 376 ASSERT_EQ(static_cast<size_t>(-1), mbsrtowcs(out, &incomplete, 2, ps)); 377 EXPECT_EQ(EILSEQ, errno); 378 ASSERT_EQ('\xc2', *incomplete); 379 380 // If dst is null, *src shouldn't be updated. 381 // https://code.google.com/p/android/issues/detail?id=166381 382 const char* mbs = VALID; 383 EXPECT_EQ(6U, mbsrtowcs(nullptr, &mbs, 0, ps)); 384 EXPECT_EQ(VALID, mbs); 385 mbs = INVALID; 386 EXPECT_EQ(static_cast<size_t>(-1), mbsrtowcs(nullptr, &mbs, 0, ps)); 387 EXPECT_EQ(INVALID, mbs); 388 mbs = INCOMPLETE; 389 EXPECT_EQ(static_cast<size_t>(-1), mbsrtowcs(nullptr, &mbs, 0, ps)); 390 EXPECT_EQ(INCOMPLETE, mbs); 391 } 392 393 TEST(wchar, mbsrtowcs) { 394 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8")); 395 uselocale(LC_GLOBAL_LOCALE); 396 397 mbstate_t ps; 398 memset(&ps, 0, sizeof(ps)); 399 test_mbsrtowcs(&ps); 400 test_mbsrtowcs(NULL); 401 402 // Invalid multi byte continuation. 403 const char* invalid = "\x20"; 404 wchar_t out; 405 ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(&out, "\xc2", 1, &ps)); 406 ASSERT_EQ(static_cast<size_t>(-1), mbsrtowcs(&out, &invalid, 1, &ps)); 407 EXPECT_EQ(EILSEQ, errno); 408 ASSERT_EQ('\x20', *invalid); 409 } 410 411 template <typename T> 412 using WcsToIntFn = T (*)(const wchar_t*, wchar_t**, int); 413 414 template <typename T> 415 void TestSingleWcsToInt(WcsToIntFn<T> fn, const wchar_t* str, int base, 416 T expected_value, ptrdiff_t expected_len) { 417 wchar_t* p; 418 ASSERT_EQ(expected_value, fn(str, &p, base)); 419 ASSERT_EQ(expected_len, p - str) << str; 420 } 421 422 template <typename T> 423 void TestWcsToInt(WcsToIntFn<T> fn) { 424 TestSingleWcsToInt(fn, L"123", 10, static_cast<T>(123), 3); 425 TestSingleWcsToInt(fn, L"123", 0, static_cast<T>(123), 3); 426 TestSingleWcsToInt(fn, L"123#", 10, static_cast<T>(123), 3); 427 TestSingleWcsToInt(fn, L"01000", 8, static_cast<T>(512), 5); 428 TestSingleWcsToInt(fn, L"01000", 0, static_cast<T>(512), 5); 429 TestSingleWcsToInt(fn, L" 123 45", 0, static_cast<T>(123), 6); 430 TestSingleWcsToInt(fn, L" -123", 0, static_cast<T>(-123), 6); 431 TestSingleWcsToInt(fn, L"0x10000", 0, static_cast<T>(65536), 7); 432 } 433 434 template <typename T> 435 void TestWcsToIntLimits(WcsToIntFn<T> fn, const wchar_t* min_str, 436 const wchar_t* max_str) { 437 if (std::is_signed<T>::value) { 438 ASSERT_EQ(std::numeric_limits<T>::min(), fn(min_str, nullptr, 0)) << min_str; 439 } else { 440 // If the subject sequence begins with a <hyphen-minus>, the value resulting 441 // from the conversion shall be negated. 442 // http://pubs.opengroup.org/onlinepubs/9699919799/functions/strtoul.html 443 ASSERT_EQ(std::numeric_limits<T>::max(), fn(min_str, nullptr, 0)) << min_str; 444 } 445 ASSERT_EQ(std::numeric_limits<T>::max(), fn(max_str, nullptr, 0)) << max_str; 446 } 447 448 TEST(wchar, wcstol) { 449 TestWcsToInt(wcstol); 450 } 451 452 TEST(wchar, wcstol_limits) { 453 if (sizeof(long) == 8) { 454 TestWcsToIntLimits(wcstol, L"-9223372036854775809", L"9223372036854775808"); 455 } else { 456 TestWcsToIntLimits(wcstol, L"-2147483649", L"2147483648"); 457 } 458 } 459 460 TEST(wchar, wcstoul) { 461 TestWcsToInt(wcstoul); 462 } 463 464 TEST(wchar, wcstoul_limits) { 465 if (sizeof(long) == 8) { 466 TestWcsToIntLimits(wcstoul, L"-1", L"18446744073709551616"); 467 } else { 468 TestWcsToIntLimits(wcstoul, L"-1", L"4294967296"); 469 } 470 } 471 472 TEST(wchar, wcstoll) { 473 TestWcsToInt(wcstoll); 474 } 475 476 TEST(wchar, wcstoll_limits) { 477 TestWcsToIntLimits(wcstoll, L"-9223372036854775809", L"9223372036854775808"); 478 } 479 480 TEST(wchar, wcstoull) { 481 TestWcsToInt(wcstoull); 482 } 483 484 TEST(wchar, wcstoull_limits) { 485 TestWcsToIntLimits(wcstoull, L"-1", L"18446744073709551616"); 486 } 487 488 TEST(wchar, wcstoimax) { 489 TestWcsToInt(wcstoimax); 490 } 491 492 TEST(wchar, wcstoimax_limits) { 493 TestWcsToIntLimits(wcstoimax, L"-9223372036854775809", 494 L"9223372036854775808"); 495 } 496 497 TEST(wchar, wcstoumax) { 498 TestWcsToInt(wcstoumax); 499 } 500 501 TEST(wchar, wcstoumax_limits) { 502 TestWcsToIntLimits(wcstoumax, L"-1", L"18446744073709551616"); 503 } 504 505 TEST(wchar, mbsnrtowcs) { 506 wchar_t dst[128]; 507 const char* s = "hello, world!"; 508 const char* src; 509 510 memset(dst, 0, sizeof(dst)); 511 src = s; 512 ASSERT_EQ(0U, mbsnrtowcs(dst, &src, 0, 0, NULL)); 513 514 memset(dst, 0, sizeof(dst)); 515 src = s; 516 ASSERT_EQ(2U, mbsnrtowcs(dst, &src, 2, 123, NULL)); // glibc chokes on SIZE_MAX here. 517 ASSERT_EQ(L'h', dst[0]); 518 ASSERT_EQ(L'e', dst[1]); 519 ASSERT_EQ(&s[2], src); 520 521 memset(dst, 0, sizeof(dst)); 522 src = s; 523 ASSERT_EQ(3U, mbsnrtowcs(dst, &src, SIZE_MAX, 3, NULL)); 524 ASSERT_EQ(L'h', dst[0]); 525 ASSERT_EQ(L'e', dst[1]); 526 ASSERT_EQ(L'l', dst[2]); 527 ASSERT_EQ(&s[3], src); 528 529 memset(dst, 0, sizeof(dst)); 530 const char* incomplete = "\xc2"; // Incomplete UTF-8 sequence. 531 src = incomplete; 532 errno = 0; 533 ASSERT_EQ(static_cast<size_t>(-1), mbsnrtowcs(dst, &src, SIZE_MAX, 3, nullptr)); 534 ASSERT_EQ(EILSEQ, errno); 535 536 src = incomplete; 537 errno = 0; 538 ASSERT_EQ(static_cast<size_t>(-1), mbsnrtowcs(nullptr, &src, SIZE_MAX, 3, nullptr)); 539 ASSERT_EQ(EILSEQ, errno); 540 } 541 542 TEST(wchar, wcsftime__wcsftime_l) { 543 setenv("TZ", "UTC", 1); 544 545 struct tm t; 546 memset(&t, 0, sizeof(tm)); 547 t.tm_year = 200; 548 t.tm_mon = 2; 549 t.tm_mday = 10; 550 551 wchar_t buf[64]; 552 553 EXPECT_EQ(24U, wcsftime(buf, sizeof(buf), L"%c", &t)); 554 EXPECT_STREQ(L"Sun Mar 10 00:00:00 2100", buf); 555 EXPECT_EQ(24U, wcsftime_l(buf, sizeof(buf), L"%c", &t, LC_GLOBAL_LOCALE)); 556 EXPECT_STREQ(L"Sun Mar 10 00:00:00 2100", buf); 557 } 558 559 TEST(wchar, wmemmove_smoke) { 560 const wchar_t const_wstr[] = L"This is a test of something or other....."; 561 wchar_t wstr[NUM_WCHARS(sizeof(const_wstr))]; 562 563 EXPECT_EQ(wstr, wmemmove(wstr, const_wstr, NUM_WCHARS(sizeof(const_wstr)))); 564 EXPECT_STREQ(const_wstr, wstr); 565 566 EXPECT_EQ(wstr+5, wmemmove(wstr+5, wstr, NUM_WCHARS(sizeof(const_wstr)) - 6)); 567 EXPECT_STREQ(L"This This is a test of something or other", wstr); 568 } 569 570 TEST(wchar, wmemcpy_smoke) { 571 const wchar_t src[] = L"Source string"; 572 wchar_t dst[NUM_WCHARS(sizeof(src))]; 573 574 EXPECT_EQ(dst, wmemcpy(dst, src, NUM_WCHARS(sizeof(src)))); 575 EXPECT_STREQ(dst, src); 576 } 577 578 TEST(wchar, wcpcpy_smoke) { 579 const wchar_t src[] = L"Source string"; 580 wchar_t dst[NUM_WCHARS(sizeof(src))]; 581 582 EXPECT_EQ(dst + NUM_WCHARS(sizeof(src)) - 1, wcpcpy(dst, src)); 583 EXPECT_STREQ(dst, src); 584 } 585 586 TEST(wchar, wcpncpy_smoke) { 587 const wchar_t src[] = L"Source string"; 588 wchar_t dst[NUM_WCHARS(sizeof(src)) + 5]; 589 590 size_t src_len = NUM_WCHARS(sizeof(src)) - 1; 591 EXPECT_EQ(dst + src_len, wcpncpy(dst, src, src_len + 1)); 592 EXPECT_STREQ(dst, src); 593 594 EXPECT_EQ(dst + 6, wcpncpy(dst, src, 6)); 595 dst[6] = L'\0'; 596 EXPECT_STREQ(dst, L"Source"); 597 598 wmemset(dst, L'x', NUM_WCHARS(sizeof(dst))); 599 EXPECT_EQ(dst + src_len, wcpncpy(dst, src, src_len + 4)); 600 EXPECT_STREQ(dst, src); 601 EXPECT_EQ(dst[src_len], L'\0'); 602 EXPECT_EQ(dst[src_len+1], L'\0'); 603 EXPECT_EQ(dst[src_len+2], L'\0'); 604 EXPECT_EQ(dst[src_len+3], L'\0'); 605 EXPECT_EQ(dst[src_len+4], L'x'); 606 } 607 608 TEST(wchar, wcscpy_smoke) { 609 const wchar_t src[] = L"Source string"; 610 wchar_t dst[NUM_WCHARS(sizeof(src))]; 611 612 EXPECT_EQ(dst, wcscpy(dst, src)); 613 EXPECT_STREQ(src, dst); 614 } 615 616 TEST(wchar, wcsncpy_smoke) { 617 const wchar_t src[] = L"Source string"; 618 wchar_t dst[NUM_WCHARS(sizeof(src)) + 5]; 619 620 size_t src_len = NUM_WCHARS(sizeof(src)) - 1; 621 EXPECT_EQ(dst, wcsncpy(dst, src, src_len + 1)); 622 EXPECT_STREQ(dst, src); 623 624 EXPECT_EQ(dst, wcsncpy(dst, src, 6)); 625 dst[6] = L'\0'; 626 EXPECT_STREQ(dst, L"Source"); 627 628 wmemset(dst, L'x', NUM_WCHARS(sizeof(dst))); 629 EXPECT_EQ(dst, wcsncpy(dst, src, src_len + 4)); 630 EXPECT_STREQ(dst, src); 631 EXPECT_EQ(dst[src_len], L'\0'); 632 EXPECT_EQ(dst[src_len+1], L'\0'); 633 EXPECT_EQ(dst[src_len+2], L'\0'); 634 EXPECT_EQ(dst[src_len+3], L'\0'); 635 EXPECT_EQ(dst[src_len+4], L'x'); 636 } 637 638 TEST(wchar, mbrtowc_15439554) { 639 // http://b/15439554 640 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8")); 641 uselocale(LC_GLOBAL_LOCALE); 642 643 ASSERT_GE(static_cast<size_t>(MB_LEN_MAX), MB_CUR_MAX); 644 ASSERT_GE(MB_CUR_MAX, 4U); 645 646 wchar_t wc; 647 size_t n; 648 649 // 1-byte character. 650 n = mbrtowc(&wc, "x", MB_CUR_MAX, NULL); 651 EXPECT_EQ(1U, n); 652 EXPECT_EQ(L'x', wc); 653 // 2-byte character. 654 n = mbrtowc(&wc, "\xc2\xa2", MB_CUR_MAX, NULL); 655 EXPECT_EQ(2U, n); 656 EXPECT_EQ(L'', wc); 657 // 3-byte character. 658 n = mbrtowc(&wc, "\xe2\x82\xac", MB_CUR_MAX, NULL); 659 EXPECT_EQ(3U, n); 660 EXPECT_EQ(L'', wc); 661 // 4-byte character. 662 n = mbrtowc(&wc, "\xf0\xa4\xad\xa2", MB_CUR_MAX, NULL); 663 EXPECT_EQ(4U, n); 664 EXPECT_EQ(L'', wc); 665 } 666 667 TEST(wchar, open_wmemstream) { 668 wchar_t* p = nullptr; 669 size_t size = 0; 670 FILE* fp = open_wmemstream(&p, &size); 671 ASSERT_NE(EOF, fputws(L"hello, world!", fp)); 672 fclose(fp); 673 674 ASSERT_STREQ(L"hello, world!", p); 675 ASSERT_EQ(wcslen(L"hello, world!"), size); 676 free(p); 677 } 678 679 TEST(stdio, open_wmemstream_EINVAL) { 680 #if defined(__BIONIC__) 681 wchar_t* p; 682 size_t size; 683 684 // Invalid buffer. 685 errno = 0; 686 ASSERT_EQ(nullptr, open_wmemstream(nullptr, &size)); 687 ASSERT_EQ(EINVAL, errno); 688 689 // Invalid size. 690 errno = 0; 691 ASSERT_EQ(nullptr, open_wmemstream(&p, nullptr)); 692 ASSERT_EQ(EINVAL, errno); 693 #else 694 GTEST_LOG_(INFO) << "This test does nothing.\n"; 695 #endif 696 } 697 698 TEST(wchar, wcstol_EINVAL) { 699 errno = 0; 700 wcstol(L"123", NULL, -1); 701 ASSERT_EQ(EINVAL, errno); 702 errno = 0; 703 wcstol(L"123", NULL, 1); 704 ASSERT_EQ(EINVAL, errno); 705 errno = 0; 706 wcstol(L"123", NULL, 37); 707 ASSERT_EQ(EINVAL, errno); 708 } 709 710 TEST(wchar, wcstoll_EINVAL) { 711 errno = 0; 712 wcstoll(L"123", NULL, -1); 713 ASSERT_EQ(EINVAL, errno); 714 errno = 0; 715 wcstoll(L"123", NULL, 1); 716 ASSERT_EQ(EINVAL, errno); 717 errno = 0; 718 wcstoll(L"123", NULL, 37); 719 ASSERT_EQ(EINVAL, errno); 720 } 721 722 TEST(wchar, wcstoul_EINVAL) { 723 errno = 0; 724 wcstoul(L"123", NULL, -1); 725 ASSERT_EQ(EINVAL, errno); 726 errno = 0; 727 wcstoul(L"123", NULL, 1); 728 ASSERT_EQ(EINVAL, errno); 729 errno = 0; 730 wcstoul(L"123", NULL, 37); 731 ASSERT_EQ(EINVAL, errno); 732 } 733 734 TEST(wchar, wcstoull_EINVAL) { 735 errno = 0; 736 wcstoull(L"123", NULL, -1); 737 ASSERT_EQ(EINVAL, errno); 738 errno = 0; 739 wcstoull(L"123", NULL, 1); 740 ASSERT_EQ(EINVAL, errno); 741 errno = 0; 742 wcstoull(L"123", NULL, 37); 743 ASSERT_EQ(EINVAL, errno); 744 } 745 746 TEST(wchar, wcstoll_l_EINVAL) { 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, 1, LC_GLOBAL_LOCALE); 752 ASSERT_EQ(EINVAL, errno); 753 errno = 0; 754 wcstoll_l(L"123", NULL, 37, LC_GLOBAL_LOCALE); 755 ASSERT_EQ(EINVAL, errno); 756 } 757 758 TEST(wchar, wcstoull_l_EINVAL) { 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, 1, LC_GLOBAL_LOCALE); 764 ASSERT_EQ(EINVAL, errno); 765 errno = 0; 766 wcstoull_l(L"123", NULL, 37, LC_GLOBAL_LOCALE); 767 ASSERT_EQ(EINVAL, errno); 768 } 769 770 TEST(wchar, wmempcpy) { 771 wchar_t dst[6]; 772 ASSERT_EQ(&dst[4], wmempcpy(dst, L"hello", 4)); 773 } 774 775 template <typename T> 776 using WcsToFloatFn = T (*)(const wchar_t*, wchar_t**); 777 778 template <typename T> 779 void TestSingleWcsToFloat(WcsToFloatFn<T> fn, const wchar_t* str, 780 T expected_value, ptrdiff_t expected_len) { 781 wchar_t* p; 782 ASSERT_EQ(expected_value, fn(str, &p)); 783 ASSERT_EQ(expected_len, p - str); 784 } 785 786 template <typename T> 787 void TestWcsToFloat(WcsToFloatFn<T> fn) { 788 TestSingleWcsToFloat(fn, L"123", static_cast<T>(123.0L), 3); 789 TestSingleWcsToFloat(fn, L"123#", static_cast<T>(123.0L), 3); 790 TestSingleWcsToFloat(fn, L" 123 45", static_cast<T>(123.0L), 6); 791 TestSingleWcsToFloat(fn, L"9.0", static_cast<T>(9.0L), 3); 792 TestSingleWcsToFloat(fn, L"-9.0", static_cast<T>(-9.0L), 4); 793 TestSingleWcsToFloat(fn, L" \t\v\f\r\n9.0", static_cast<T>(9.0L), 9); 794 } 795 796 template <typename T> 797 void TestWcsToFloatHexFloats(WcsToFloatFn<T> fn) { 798 TestSingleWcsToFloat(fn, L"0.9e1", static_cast<T>(9.0L), 5); 799 TestSingleWcsToFloat(fn, L"0x1.2p3", static_cast<T>(9.0L), 7); 800 TestSingleWcsToFloat(fn, L"+1e+100", static_cast<T>(1e100L), 7); 801 TestSingleWcsToFloat(fn, L"0x10000.80", static_cast<T>(65536.50L), 10); 802 } 803 804 template <typename T> 805 void TestWcsToFloatInfNan(WcsToFloatFn<T> fn) { 806 ASSERT_TRUE(isnan(fn(L"+nan", nullptr))); 807 ASSERT_TRUE(isnan(fn(L"nan", nullptr))); 808 ASSERT_TRUE(isnan(fn(L"-nan", nullptr))); 809 810 ASSERT_TRUE(isnan(fn(L"+nan(0xff)", nullptr))); 811 ASSERT_TRUE(isnan(fn(L"nan(0xff)", nullptr))); 812 ASSERT_TRUE(isnan(fn(L"-nan(0xff)", nullptr))); 813 814 wchar_t* p; 815 ASSERT_TRUE(isnan(fn(L"+nanny", &p))); 816 ASSERT_STREQ(L"ny", p); 817 ASSERT_TRUE(isnan(fn(L"nanny", &p))); 818 ASSERT_STREQ(L"ny", p); 819 ASSERT_TRUE(isnan(fn(L"-nanny", &p))); 820 ASSERT_STREQ(L"ny", p); 821 822 ASSERT_EQ(0, fn(L"muppet", &p)); 823 ASSERT_STREQ(L"muppet", p); 824 ASSERT_EQ(0, fn(L" muppet", &p)); 825 ASSERT_STREQ(L" muppet", p); 826 827 ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"+inf", nullptr)); 828 ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"inf", nullptr)); 829 ASSERT_EQ(-std::numeric_limits<T>::infinity(), fn(L"-inf", nullptr)); 830 831 ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"+infinity", nullptr)); 832 ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"infinity", nullptr)); 833 ASSERT_EQ(-std::numeric_limits<T>::infinity(), fn(L"-infinity", nullptr)); 834 835 ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"+infinitude", &p)); 836 ASSERT_STREQ(L"initude", p); 837 ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"infinitude", &p)); 838 ASSERT_STREQ(L"initude", p); 839 ASSERT_EQ(-std::numeric_limits<T>::infinity(), fn(L"-infinitude", &p)); 840 ASSERT_STREQ(L"initude", p); 841 842 // Check case-insensitivity. 843 ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"InFiNiTy", nullptr)); 844 ASSERT_TRUE(isnan(fn(L"NaN", nullptr))); 845 } 846 847 TEST(wchar, wcstof) { 848 TestWcsToFloat(wcstof); 849 } 850 851 TEST(wchar, wcstof_hex_floats) { 852 TestWcsToFloatHexFloats(wcstof); 853 } 854 855 TEST(wchar, wcstof_hex_inf_nan) { 856 TestWcsToFloatInfNan(wcstof); 857 } 858 859 TEST(wchar, wcstod) { 860 TestWcsToFloat(wcstod); 861 } 862 863 TEST(wchar, wcstod_hex_floats) { 864 TestWcsToFloatHexFloats(wcstod); 865 } 866 867 TEST(wchar, wcstod_hex_inf_nan) { 868 TestWcsToFloatInfNan(wcstod); 869 } 870 871 TEST(wchar, wcstold) { 872 TestWcsToFloat(wcstold); 873 } 874 875 TEST(wchar, wcstold_hex_floats) { 876 TestWcsToFloatHexFloats(wcstold); 877 } 878 879 TEST(wchar, wcstold_hex_inf_nan) { 880 TestWcsToFloatInfNan(wcstold); 881 } 882 883 TEST(wchar, wcstod_l) { 884 EXPECT_EQ(1.23, wcstod_l(L"1.23", nullptr, LC_GLOBAL_LOCALE)); 885 } 886 887 TEST(wchar, wcstof_l) { 888 EXPECT_EQ(1.23f, wcstof_l(L"1.23", nullptr, LC_GLOBAL_LOCALE)); 889 } 890 891 TEST(wchar, wcstol_l) { 892 EXPECT_EQ(123L, wcstol_l(L"123", nullptr, 10, LC_GLOBAL_LOCALE)); 893 } 894 895 TEST(wchar, wcstold_l) { 896 EXPECT_EQ(1.23L, wcstold_l(L"1.23", nullptr, LC_GLOBAL_LOCALE)); 897 } 898 899 TEST(wchar, wcstoll_l) { 900 EXPECT_EQ(123LL, wcstoll_l(L"123", nullptr, 10, LC_GLOBAL_LOCALE)); 901 } 902 903 TEST(wchar, wcstoul_l) { 904 EXPECT_EQ(123UL, wcstoul_l(L"123", nullptr, 10, LC_GLOBAL_LOCALE)); 905 } 906 907 TEST(wchar, wcstoull_l) { 908 EXPECT_EQ(123ULL, wcstoul_l(L"123", nullptr, 10, LC_GLOBAL_LOCALE)); 909 } 910 911 static void AssertWcwidthRange(wchar_t begin, wchar_t end, int expected) { 912 for (wchar_t i = begin; i < end; ++i) { 913 EXPECT_EQ(expected, wcwidth(i)) << static_cast<int>(i); 914 } 915 } 916 917 TEST(wchar, wcwidth_NUL) { 918 // NUL is defined to return 0 rather than -1, despite being a C0 control. 919 EXPECT_EQ(0, wcwidth(0)); 920 } 921 922 TEST(wchar, wcwidth_ascii) { 923 AssertWcwidthRange(0x20, 0x7f, 1); // Non-C0 non-DEL ASCII. 924 } 925 926 TEST(wchar, wcwidth_controls) { 927 AssertWcwidthRange(0x01, 0x20, -1); // C0 controls. 928 EXPECT_EQ(-1, wcwidth(0x7f)); // DEL. 929 AssertWcwidthRange(0x80, 0xa0, -1); // C1 controls. 930 } 931 932 TEST(wchar, wcwidth_non_spacing_and_enclosing_marks_and_format) { 933 if (!have_dl()) return; 934 935 EXPECT_EQ(0, wcwidth(0x0300)); // Combining grave. 936 EXPECT_EQ(0, wcwidth(0x20dd)); // Combining enclosing circle. 937 EXPECT_EQ(0, wcwidth(0x00ad)); // Soft hyphen (SHY). 938 EXPECT_EQ(0, wcwidth(0x200b)); // Zero width space. 939 } 940 941 TEST(wchar, wcwidth_cjk) { 942 if (!have_dl()) return; 943 944 EXPECT_EQ(2, wcwidth(0x4e00)); // Start of CJK unified block. 945 EXPECT_EQ(2, wcwidth(0x9fff)); // End of CJK unified block. 946 EXPECT_EQ(2, wcwidth(0x3400)); // Start of CJK extension A block. 947 EXPECT_EQ(2, wcwidth(0x4dbf)); // End of CJK extension A block. 948 EXPECT_EQ(2, wcwidth(0x20000)); // Start of CJK extension B block. 949 EXPECT_EQ(2, wcwidth(0x2a6df)); // End of CJK extension B block. 950 } 951 952 TEST(wchar, wcwidth_korean_combining_jamo) { 953 if (!have_dl()) return; 954 955 AssertWcwidthRange(0x1160, 0x1200, 0); // Original range. 956 EXPECT_EQ(0, wcwidth(0xd7b0)); // Newer. 957 EXPECT_EQ(0, wcwidth(0xd7cb)); 958 } 959 960 TEST(wchar, wcwidth_korean_jeongeul_syllables) { 961 if (!have_dl()) return; 962 963 EXPECT_EQ(2, wcwidth(0xac00)); // Start of block. 964 EXPECT_EQ(2, wcwidth(0xd7a3)); // End of defined code points in Unicode 7. 965 // Undefined characters at the end of the block have width 1. 966 } 967 968 TEST(wchar, wcwidth_kana) { 969 if (!have_dl()) return; 970 971 // Hiragana (most, not undefined). 972 AssertWcwidthRange(0x3041, 0x3097, 2); 973 // Katakana. 974 AssertWcwidthRange(0x30a0, 0x3100, 2); 975 } 976 977 TEST(wchar, wcwidth_circled_two_digit_cjk) { 978 if (!have_dl()) return; 979 980 // Circled two-digit CJK "speed sign" numbers are wide, 981 // though EastAsianWidth is ambiguous. 982 AssertWcwidthRange(0x3248, 0x3250, 2); 983 } 984 985 TEST(wchar, wcwidth_hexagrams) { 986 if (!have_dl()) return; 987 988 // Hexagrams are wide, though EastAsianWidth is neutral. 989 AssertWcwidthRange(0x4dc0, 0x4e00, 2); 990 } 991 992 TEST(wchar, wcwidth_default_ignorables) { 993 if (!have_dl()) return; 994 995 AssertWcwidthRange(0xfff0, 0xfff8, 0); // Unassigned by default ignorable. 996 EXPECT_EQ(0, wcwidth(0xe0000)); // ...through 0xe0fff. 997 } 998 999 TEST(wchar, wcwidth_korean_common_non_syllables) { 1000 if (!have_dl()) return; 1001 1002 EXPECT_EQ(2, wcwidth(L'')); // Korean "crying" emoticon. 1003 EXPECT_EQ(2, wcwidth(L'')); // Korean "laughing" emoticon. 1004 } 1005