Serenity Operating System
at master 660 lines 19 kB view raw
1/* 2 * Copyright (c) 2021-2022, the SerenityOS developers. 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <LibTest/TestCase.h> 8 9#include <errno.h> 10#include <limits.h> 11#include <string.h> 12#include <time.h> 13#include <wchar.h> 14 15TEST_CASE(wcspbrk) 16{ 17 wchar_t const* input; 18 wchar_t* ret; 19 20 // Test empty haystack. 21 ret = wcspbrk(L"", L"ab"); 22 EXPECT_EQ(ret, nullptr); 23 24 // Test empty needle. 25 ret = wcspbrk(L"ab", L""); 26 EXPECT_EQ(ret, nullptr); 27 28 // Test search for a single character. 29 input = L"abcd"; 30 ret = wcspbrk(input, L"a"); 31 EXPECT_EQ(ret, input); 32 33 // Test search for multiple characters, none matches. 34 ret = wcspbrk(input, L"zxy"); 35 EXPECT_EQ(ret, nullptr); 36 37 // Test search for multiple characters, last matches. 38 ret = wcspbrk(input, L"zxyc"); 39 EXPECT_EQ(ret, input + 2); 40} 41 42TEST_CASE(wcsstr) 43{ 44 wchar_t const* input = L"abcde"; 45 wchar_t* ret; 46 47 // Empty needle should return haystack. 48 ret = wcsstr(input, L""); 49 EXPECT_EQ(ret, input); 50 51 // Test exact match. 52 ret = wcsstr(input, input); 53 EXPECT_EQ(ret, input); 54 55 // Test match at string start. 56 ret = wcsstr(input, L"ab"); 57 EXPECT_EQ(ret, input); 58 59 // Test match at string end. 60 ret = wcsstr(input, L"de"); 61 EXPECT_EQ(ret, input + 3); 62 63 // Test no match. 64 ret = wcsstr(input, L"z"); 65 EXPECT_EQ(ret, nullptr); 66 67 // Test needle that is longer than the haystack. 68 ret = wcsstr(input, L"abcdef"); 69 EXPECT_EQ(ret, nullptr); 70} 71 72TEST_CASE(wmemchr) 73{ 74 wchar_t const* input = L"abcde"; 75 wchar_t* ret; 76 77 // Empty haystack returns nothing. 78 ret = wmemchr(L"", L'c', 0); 79 EXPECT_EQ(ret, nullptr); 80 81 // Not included character returns nothing. 82 ret = wmemchr(input, L'z', 5); 83 EXPECT_EQ(ret, nullptr); 84 85 // Match at string start. 86 ret = wmemchr(input, L'a', 5); 87 EXPECT_EQ(ret, input); 88 89 // Match at string end. 90 ret = wmemchr(input, L'e', 5); 91 EXPECT_EQ(ret, input + 4); 92 93 input = L"abcde\0fg"; 94 95 // Handle finding null characters. 96 ret = wmemchr(input, L'\0', 8); 97 EXPECT_EQ(ret, input + 5); 98 99 // Don't stop at null characters. 100 ret = wmemchr(input, L'f', 8); 101 EXPECT_EQ(ret, input + 6); 102} 103 104TEST_CASE(wmemcpy) 105{ 106 wchar_t const* input = L"abc\0def"; 107 auto buf = static_cast<wchar_t*>(malloc(8 * sizeof(wchar_t))); 108 109 if (!buf) { 110 FAIL("Could not allocate space for copy target"); 111 return; 112 } 113 114 wchar_t* ret = wmemcpy(buf, input, 8); 115 116 EXPECT_EQ(ret, buf); 117 EXPECT_EQ(memcmp(buf, input, 8 * sizeof(wchar_t)), 0); 118} 119 120TEST_CASE(wmemset) 121{ 122 auto buf_length = 8; 123 auto buf = static_cast<wchar_t*>(calloc(buf_length, sizeof(wchar_t))); 124 125 if (!buf) { 126 FAIL("Could not allocate memory for target buffer"); 127 return; 128 } 129 130 wchar_t* ret = wmemset(buf, L'\U0001f41e', buf_length - 1); 131 132 EXPECT_EQ(ret, buf); 133 134 for (int i = 0; i < buf_length - 1; i++) { 135 EXPECT_EQ(buf[i], L'\U0001f41e'); 136 } 137 138 EXPECT_EQ(buf[buf_length - 1], L'\0'); 139 140 free(buf); 141} 142 143TEST_CASE(wmemmove) 144{ 145 wchar_t* ret; 146 wchar_t const* string = L"abc\0def"; 147 auto buf = static_cast<wchar_t*>(calloc(32, sizeof(wchar_t))); 148 149 if (!buf) { 150 FAIL("Could not allocate memory for target buffer"); 151 return; 152 } 153 154 // Test moving to smaller addresses. 155 wmemcpy(buf + 3, string, 8); 156 ret = wmemmove(buf + 1, buf + 3, 8); 157 EXPECT_EQ(ret, buf + 1); 158 EXPECT_EQ(memcmp(string, buf + 1, 8 * sizeof(wchar_t)), 0); 159 160 // Test moving to larger addresses. 161 wmemcpy(buf + 16, string, 8); 162 ret = wmemmove(buf + 18, buf + 16, 8); 163 EXPECT_EQ(ret, buf + 18); 164 EXPECT_EQ(memcmp(string, buf + 18, 8 * sizeof(wchar_t)), 0); 165 166 free(buf); 167} 168 169TEST_CASE(wcscoll) 170{ 171 // Check if wcscoll is sorting correctly. At the moment we are doing raw char comparisons, 172 // so it's digits, then uppercase letters, then lowercase letters. 173 174 // Equalness between equal strings. 175 EXPECT(wcscoll(L"", L"") == 0); 176 EXPECT(wcscoll(L"0", L"0") == 0); 177 178 // Shorter strings before longer strings. 179 EXPECT(wcscoll(L"", L"0") < 0); 180 EXPECT(wcscoll(L"0", L"") > 0); 181 EXPECT(wcscoll(L"123", L"1234") < 0); 182 EXPECT(wcscoll(L"1234", L"123") > 0); 183 184 // Order within digits. 185 EXPECT(wcscoll(L"0", L"9") < 0); 186 EXPECT(wcscoll(L"9", L"0") > 0); 187 188 // Digits before uppercase letters. 189 EXPECT(wcscoll(L"9", L"A") < 0); 190 EXPECT(wcscoll(L"A", L"9") > 0); 191 192 // Order within uppercase letters. 193 EXPECT(wcscoll(L"A", L"Z") < 0); 194 EXPECT(wcscoll(L"Z", L"A") > 0); 195 196 // Uppercase letters before lowercase letters. 197 EXPECT(wcscoll(L"Z", L"a") < 0); 198 EXPECT(wcscoll(L"a", L"Z") > 0); 199 200 // Uppercase letters before lowercase letters. 201 EXPECT(wcscoll(L"a", L"z") < 0); 202 EXPECT(wcscoll(L"z", L"a") > 0); 203} 204 205TEST_CASE(mbsinit) 206{ 207 // Ensure that nullptr is considered an initial state. 208 EXPECT(mbsinit(nullptr) != 0); 209 210 // Ensure that a zero-initialized state is recognized as initial state. 211 mbstate_t state = {}; 212 EXPECT(mbsinit(&state) != 0); 213 214 // Read a partial multibyte sequence (0b11011111 / 0xdf). 215 size_t ret = mbrtowc(nullptr, "\xdf", 1, &state); 216 217 if (ret != -2ul) 218 FAIL(DeprecatedString::formatted("mbrtowc accepted partial multibyte sequence with return code {} (expected -2)", static_cast<ssize_t>(ret))); 219 220 // Ensure that we are not in an initial state. 221 EXPECT(mbsinit(&state) == 0); 222 223 // Read the remaining multibyte sequence (0b10111111 / 0xbf). 224 ret = mbrtowc(nullptr, "\xbf", 1, &state); 225 226 if (ret != 1ul) 227 FAIL(DeprecatedString::formatted("mbrtowc did not consume the expected number of bytes (1), returned {} instead", static_cast<ssize_t>(ret))); 228 229 // Ensure that we are in an initial state again. 230 EXPECT(mbsinit(&state) != 0); 231} 232 233TEST_CASE(mbrtowc) 234{ 235 size_t ret = 0; 236 mbstate_t state = {}; 237 wchar_t wc = 0; 238 239 // Ensure that we can parse normal ASCII characters. 240 ret = mbrtowc(&wc, "Hello", 5, &state); 241 EXPECT_EQ(ret, 1ul); 242 EXPECT_EQ(wc, static_cast<wchar_t>('H')); 243 244 // Try two three-byte codepoints (™™), only one of which should be consumed. 245 ret = mbrtowc(&wc, "\xe2\x84\xa2\xe2\x84\xa2", 6, &state); 246 EXPECT_EQ(ret, 3ul); 247 EXPECT_EQ(wc, static_cast<wchar_t>(0x2122)); 248 249 // Try a null character, which should return 0 and reset the state to the initial state. 250 ret = mbrtowc(&wc, "\x00\x00", 2, &state); 251 EXPECT_EQ(ret, 0ul); 252 EXPECT_EQ(wc, static_cast<wchar_t>(0)); 253 EXPECT_NE(mbsinit(&state), 0); 254 255 // Try an incomplete multibyte character. 256 ret = mbrtowc(&wc, "\xe2\x84", 2, &state); 257 EXPECT_EQ(ret, -2ul); 258 EXPECT_EQ(mbsinit(&state), 0); 259 260 mbstate_t incomplete_state = state; 261 262 // Finish the previous multibyte character. 263 ret = mbrtowc(&wc, "\xa2", 1, &state); 264 EXPECT_EQ(ret, 1ul); 265 EXPECT_EQ(wc, static_cast<wchar_t>(0x2122)); 266 267 // Try an invalid multibyte sequence. 268 // Reset the state afterwards because the effects are undefined. 269 ret = mbrtowc(&wc, "\xff", 1, &state); 270 EXPECT_EQ(ret, -1ul); 271 EXPECT_EQ(errno, EILSEQ); 272 state = {}; 273 274 // Try a successful conversion, but without target address. 275 ret = mbrtowc(nullptr, "\xe2\x84\xa2\xe2\x84\xa2", 6, &state); 276 EXPECT_EQ(ret, 3ul); 277 278 // Test the "null byte shorthand". Ensure that wc is ignored. 279 state = {}; 280 wchar_t old_wc = wc; 281 ret = mbrtowc(&wc, nullptr, 0, &state); 282 EXPECT_EQ(ret, 0ul); 283 EXPECT_EQ(wc, old_wc); 284 285 // Test recognition of incomplete multibyte sequences. 286 ret = mbrtowc(nullptr, nullptr, 0, &incomplete_state); 287 EXPECT_EQ(ret, -1ul); 288 EXPECT_EQ(errno, EILSEQ); 289} 290 291TEST_CASE(wcrtomb) 292{ 293 char buf[MB_LEN_MAX]; 294 size_t ret = 0; 295 296 // Ensure that `wc` is ignored when buf is a nullptr. 297 ret = wcrtomb(nullptr, L'a', nullptr); 298 EXPECT_EQ(ret, 1ul); 299 300 ret = wcrtomb(nullptr, L'\U0001F41E', nullptr); 301 EXPECT_EQ(ret, 1ul); 302 303 // When the buffer is non-null, the multibyte representation is written into it. 304 ret = wcrtomb(buf, L'a', nullptr); 305 EXPECT_EQ(ret, 1ul); 306 EXPECT_EQ(memcmp(buf, "a", ret), 0); 307 308 ret = wcrtomb(buf, L'\U0001F41E', nullptr); 309 EXPECT_EQ(ret, 4ul); 310 EXPECT_EQ(memcmp(buf, "\xf0\x9f\x90\x9e", ret), 0); 311 312 // When the wide character is invalid, -1 is returned and errno is set to EILSEQ. 313 ret = wcrtomb(buf, 0x110000, nullptr); 314 EXPECT_EQ(ret, (size_t)-1); 315 EXPECT_EQ(errno, EILSEQ); 316 317 // Replacement characters and conversion errors are not confused. 318 ret = wcrtomb(buf, L'\uFFFD', nullptr); 319 EXPECT_NE(ret, (size_t)-1); 320} 321 322TEST_CASE(wcsrtombs) 323{ 324 mbstate_t state = {}; 325 char buf[MB_LEN_MAX * 4]; 326 const wchar_t good_chars[] = { L'\U0001F41E', L'\U0001F41E', L'\0' }; 327 const wchar_t bad_chars[] = { L'\U0001F41E', static_cast<wchar_t>(0x1111F41E), L'\0' }; 328 wchar_t const* src; 329 size_t ret = 0; 330 331 // Convert normal and valid wchar_t values. 332 src = good_chars; 333 ret = wcsrtombs(buf, &src, 9, &state); 334 EXPECT_EQ(ret, 8ul); 335 EXPECT_EQ(memcmp(buf, "\xf0\x9f\x90\x9e\xf0\x9f\x90\x9e", 9), 0); 336 EXPECT_EQ(src, nullptr); 337 EXPECT_NE(mbsinit(&state), 0); 338 339 // Stop on invalid wchar values. 340 src = bad_chars; 341 ret = wcsrtombs(buf, &src, 9, &state); 342 EXPECT_EQ(ret, -1ul); 343 EXPECT_EQ(memcmp(buf, "\xf0\x9f\x90\x9e", 4), 0); 344 EXPECT_EQ(errno, EILSEQ); 345 EXPECT_EQ(src, bad_chars + 1); 346 347 // Valid characters but not enough space. 348 src = good_chars; 349 ret = wcsrtombs(buf, &src, 7, &state); 350 EXPECT_EQ(ret, 4ul); 351 EXPECT_EQ(memcmp(buf, "\xf0\x9f\x90\x9e", 4), 0); 352 EXPECT_EQ(src, good_chars + 1); 353 354 // Try a conversion with no destination and too short length. 355 src = good_chars; 356 ret = wcsrtombs(nullptr, &src, 2, &state); 357 EXPECT_EQ(ret, 8ul); 358 EXPECT_EQ(src, nullptr); 359 EXPECT_NE(mbsinit(&state), 0); 360 361 // Try a conversion using the internal anonymous state. 362 src = good_chars; 363 ret = wcsrtombs(buf, &src, 9, nullptr); 364 EXPECT_EQ(ret, 8ul); 365 EXPECT_EQ(memcmp(buf, "\xf0\x9f\x90\x9e\xf0\x9f\x90\x9e", 9), 0); 366 EXPECT_EQ(src, nullptr); 367} 368 369TEST_CASE(wcsnrtombs) 370{ 371 mbstate_t state = {}; 372 const wchar_t good_chars[] = { L'\U0001F41E', L'\U0001F41E', L'\0' }; 373 wchar_t const* src; 374 size_t ret = 0; 375 376 // Convert nothing. 377 src = good_chars; 378 ret = wcsnrtombs(nullptr, &src, 0, 0, &state); 379 EXPECT_EQ(ret, 0ul); 380 EXPECT_EQ(src, good_chars); 381 382 // Convert one wide char. 383 src = good_chars; 384 ret = wcsnrtombs(nullptr, &src, 1, 0, &state); 385 EXPECT_EQ(ret, 4ul); 386 EXPECT_EQ(src, good_chars + 1); 387 388 // Encounter a null character. 389 src = good_chars; 390 ret = wcsnrtombs(nullptr, &src, 4, 0, &state); 391 EXPECT_EQ(ret, 8ul); 392 EXPECT_EQ(src, nullptr); 393} 394 395TEST_CASE(mbsrtowcs) 396{ 397 mbstate_t state = {}; 398 wchar_t buf[4]; 399 char const good_chars[] = "\xf0\x9f\x90\x9e\xf0\x9f\x90\x9e"; 400 char const bad_chars[] = "\xf0\x9f\x90\x9e\xf0\xff\x90\x9e"; 401 char const* src; 402 size_t ret = 0; 403 404 // Convert normal and valid multibyte sequences. 405 src = good_chars; 406 ret = mbsrtowcs(buf, &src, 3, &state); 407 EXPECT_EQ(ret, 2ul); 408 EXPECT_EQ(buf[0], L'\U0001F41E'); 409 EXPECT_EQ(buf[1], L'\U0001F41E'); 410 EXPECT_EQ(buf[2], L'\0'); 411 EXPECT_EQ(src, nullptr); 412 EXPECT_NE(mbsinit(&state), 0); 413 414 // Stop on invalid multibyte sequences. 415 src = bad_chars; 416 ret = mbsrtowcs(buf, &src, 3, &state); 417 EXPECT_EQ(ret, -1ul); 418 EXPECT_EQ(buf[0], L'\U0001F41E'); 419 EXPECT_EQ(errno, EILSEQ); 420 EXPECT_EQ(src, bad_chars + 4); 421 422 // Valid sequence but not enough space. 423 src = good_chars; 424 ret = mbsrtowcs(buf, &src, 1, &state); 425 EXPECT_EQ(ret, 1ul); 426 EXPECT_EQ(buf[0], L'\U0001F41E'); 427 EXPECT_EQ(src, good_chars + 4); 428 429 // Try a conversion with no destination and too short length. 430 src = good_chars; 431 ret = mbsrtowcs(nullptr, &src, 1, &state); 432 EXPECT_EQ(ret, 2ul); 433 EXPECT_EQ(src, nullptr); 434 EXPECT_NE(mbsinit(&state), 0); 435 436 // Try a conversion using the internal anonymous state. 437 src = good_chars; 438 ret = mbsrtowcs(buf, &src, 3, nullptr); 439 EXPECT_EQ(ret, 2ul); 440 EXPECT_EQ(buf[0], L'\U0001F41E'); 441 EXPECT_EQ(buf[1], L'\U0001F41E'); 442 EXPECT_EQ(buf[2], L'\0'); 443 EXPECT_EQ(src, nullptr); 444} 445 446TEST_CASE(mbsnrtowcs) 447{ 448 mbstate_t state = {}; 449 char const good_chars[] = "\xf0\x9f\x90\x9e\xf0\x9f\x90\x9e"; 450 char const* src; 451 size_t ret = 0; 452 453 // Convert nothing. 454 src = good_chars; 455 ret = mbsnrtowcs(nullptr, &src, 0, 0, &state); 456 EXPECT_EQ(ret, 0ul); 457 EXPECT_EQ(src, good_chars); 458 459 // Convert one full wide character. 460 src = good_chars; 461 ret = mbsnrtowcs(nullptr, &src, 4, 0, &state); 462 EXPECT_EQ(ret, 1ul); 463 EXPECT_EQ(src, good_chars + 4); 464 465 // Encounter a null character. 466 src = good_chars; 467 ret = mbsnrtowcs(nullptr, &src, 10, 0, &state); 468 EXPECT_EQ(ret, 2ul); 469 EXPECT_EQ(src, nullptr); 470 471 // Convert an incomplete character. 472 // Make sure that we point past the last processed byte. 473 src = good_chars; 474 ret = mbsnrtowcs(nullptr, &src, 6, 0, &state); 475 EXPECT_EQ(ret, 1ul); 476 EXPECT_EQ(src, good_chars + 6); 477 EXPECT_EQ(mbsinit(&state), 0); 478 479 // Finish converting the incomplete character. 480 ret = mbsnrtowcs(nullptr, &src, 2, 0, &state); 481 EXPECT_EQ(ret, 1ul); 482 EXPECT_EQ(src, good_chars + 8); 483} 484 485TEST_CASE(wcslcpy) 486{ 487 auto buf = static_cast<wchar_t*>(malloc(8 * sizeof(wchar_t))); 488 if (!buf) { 489 FAIL("Could not allocate space for copy target"); 490 return; 491 } 492 493 size_t ret; 494 495 // If buffer is long enough, a straight-forward string copy is performed. 496 ret = wcslcpy(buf, L"abc", 8); 497 EXPECT_EQ(ret, 3ul); 498 EXPECT_EQ(wmemcmp(L"abc", buf, 4), 0); 499 500 // If buffer is (supposedly) too small, the string will be truncated. 501 ret = wcslcpy(buf, L"1234", 4); 502 EXPECT_EQ(ret, 4ul); 503 EXPECT_EQ(wmemcmp(L"123", buf, 4), 0); 504 505 // If the buffer is null, the length of the input is returned. 506 ret = wcslcpy(nullptr, L"abc", 0); 507 EXPECT_EQ(ret, 3ul); 508} 509 510TEST_CASE(mbrlen) 511{ 512 size_t ret = 0; 513 mbstate_t state = {}; 514 515 // Ensure that we can parse normal ASCII characters. 516 ret = mbrlen("Hello", 5, &state); 517 EXPECT_EQ(ret, 1ul); 518 519 // Try two three-byte codepoints (™™), only one of which should be consumed. 520 ret = mbrlen("\xe2\x84\xa2\xe2\x84\xa2", 6, &state); 521 EXPECT_EQ(ret, 3ul); 522 523 // Try a null character, which should return 0 and reset the state to the initial state. 524 ret = mbrlen("\x00\x00", 2, &state); 525 EXPECT_EQ(ret, 0ul); 526 EXPECT_NE(mbsinit(&state), 0); 527 528 // Try an incomplete multibyte character. 529 ret = mbrlen("\xe2\x84", 2, &state); 530 EXPECT_EQ(ret, -2ul); 531 EXPECT_EQ(mbsinit(&state), 0); 532 533 // Finish the previous multibyte character. 534 ret = mbrlen("\xa2", 1, &state); 535 EXPECT_EQ(ret, 1ul); 536 537 // Try an invalid multibyte sequence. 538 // Reset the state afterwards because the effects are undefined. 539 ret = mbrlen("\xff", 1, &state); 540 EXPECT_EQ(ret, -1ul); 541 EXPECT_EQ(errno, EILSEQ); 542 state = {}; 543} 544 545TEST_CASE(mbtowc) 546{ 547 int ret = 0; 548 wchar_t wc = 0; 549 550 // Ensure that we can parse normal ASCII characters. 551 ret = mbtowc(&wc, "Hello", 5); 552 EXPECT_EQ(ret, 1); 553 EXPECT_EQ(wc, static_cast<wchar_t>('H')); 554 555 // Try two three-byte codepoints (™™), only one of which should be consumed. 556 ret = mbtowc(&wc, "\xe2\x84\xa2\xe2\x84\xa2", 6); 557 EXPECT_EQ(ret, 3); 558 EXPECT_EQ(wc, static_cast<wchar_t>(0x2122)); 559 560 // Try a null character, which should return 0. 561 ret = mbtowc(&wc, "\x00\x00", 2); 562 EXPECT_EQ(ret, 0); 563 EXPECT_EQ(wc, static_cast<wchar_t>(0)); 564 565 // Try an incomplete multibyte character. 566 ret = mbtowc(&wc, "\xe2\x84", 2); 567 EXPECT_EQ(ret, -1); 568 EXPECT_EQ(errno, EILSEQ); 569 570 // Ask if we support shift states and reset the internal state in the process. 571 ret = mbtowc(nullptr, nullptr, 2); 572 EXPECT_EQ(ret, 0); // We don't support shift states. 573 ret = mbtowc(nullptr, "\x00", 1); 574 EXPECT_EQ(ret, 0); // No error likely means that the state is working again. 575 576 // Try an invalid multibyte sequence. 577 ret = mbtowc(&wc, "\xff", 1); 578 EXPECT_EQ(ret, -1); 579 EXPECT_EQ(errno, EILSEQ); 580 581 // Try a successful conversion, but without target address. 582 ret = mbtowc(nullptr, "\xe2\x84\xa2\xe2\x84\xa2", 6); 583 EXPECT_EQ(ret, 3); 584} 585 586TEST_CASE(mblen) 587{ 588 int ret = 0; 589 590 // Ensure that we can parse normal ASCII characters. 591 ret = mblen("Hello", 5); 592 EXPECT_EQ(ret, 1); 593 594 // Try two three-byte codepoints (™™), only one of which should be consumed. 595 ret = mblen("\xe2\x84\xa2\xe2\x84\xa2", 6); 596 EXPECT_EQ(ret, 3); 597 598 // Try a null character, which should return 0. 599 ret = mblen("\x00\x00", 2); 600 EXPECT_EQ(ret, 0); 601 602 // Try an incomplete multibyte character. 603 ret = mblen("\xe2\x84", 2); 604 EXPECT_EQ(ret, -1); 605 EXPECT_EQ(errno, EILSEQ); 606 607 // Ask if we support shift states and reset the internal state in the process. 608 ret = mblen(nullptr, 2); 609 EXPECT_EQ(ret, 0); // We don't support shift states. 610 ret = mblen("\x00", 1); 611 EXPECT_EQ(ret, 0); // No error likely means that the state is working again. 612 613 // Try an invalid multibyte sequence. 614 ret = mblen("\xff", 1); 615 EXPECT_EQ(ret, -1); 616 EXPECT_EQ(errno, EILSEQ); 617} 618 619TEST_CASE(wcsftime) 620{ 621 // FIXME: Test actual wide char inputs once those are implemented. 622 623 auto* buf = static_cast<wchar_t*>(malloc(32 * sizeof(wchar_t))); 624 if (!buf) { 625 FAIL("Could not allocate space for copy target"); 626 return; 627 } 628 629 struct tm time = { 630 .tm_sec = 54, 631 .tm_min = 44, 632 .tm_hour = 12, 633 .tm_mday = 27, 634 .tm_mon = 4, 635 .tm_year = 121, 636 .tm_wday = 4, 637 .tm_yday = 0, 638 .tm_isdst = 0, 639 }; 640 641 size_t ret; 642 643 // Normal behavior. 644 ret = wcsftime(buf, 32, L"%a, %d %b %Y %H:%M:%S", &time); 645 EXPECT_EQ(ret, 25ul); 646 EXPECT_EQ(wcscmp(buf, L"Thu, 27 May 2021 12:44:54"), 0); 647 648 // String fits exactly. 649 ret = wcsftime(buf, 26, L"%a, %d %b %Y %H:%M:%S", &time); 650 EXPECT_EQ(ret, 25ul); 651 EXPECT_EQ(wcscmp(buf, L"Thu, 27 May 2021 12:44:54"), 0); 652 653 // Buffer is too small. 654 ret = wcsftime(buf, 25, L"%a, %d %b %Y %H:%M:%S", &time); 655 EXPECT_EQ(ret, 0ul); 656 ret = wcsftime(buf, 1, L"%a, %d %b %Y %H:%M:%S", &time); 657 EXPECT_EQ(ret, 0ul); 658 ret = wcsftime(nullptr, 0, L"%a, %d %b %Y %H:%M:%S", &time); 659 EXPECT_EQ(ret, 0ul); 660}