151 lines · cpp
1//===-- Unittests for wcsrtombs -------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "hdr/types/mbstate_t.h"10#include "src/__support/macros/null_check.h"11#include "src/string/memset.h"12#include "src/wchar/wcsrtombs.h"13#include "test/UnitTest/ErrnoCheckingTest.h"14#include "test/UnitTest/Test.h"15 16using LlvmLibcWcsrtombs = LIBC_NAMESPACE::testing::ErrnoCheckingTest;17 18// these tests are fairly simple as this function just calls into the internal19// wcsnrtombs which is more thoroughly tested20 21TEST_F(LlvmLibcWcsrtombs, AllMultibyteLengths) {22 mbstate_t state;23 LIBC_NAMESPACE::memset(&state, 0, sizeof(mbstate_t));24 25 /// clown emoji, sigma symbol, y with diaeresis, letter A26 const wchar_t src[] = {static_cast<wchar_t>(0x1f921),27 static_cast<wchar_t>(0x2211),28 static_cast<wchar_t>(0xff), static_cast<wchar_t>(0x41),29 static_cast<wchar_t>(0x0)};30 const wchar_t *cur = src;31 char mbs[11];32 33 ASSERT_EQ(LIBC_NAMESPACE::wcsrtombs(mbs, &cur, 11, &state),34 static_cast<size_t>(10));35 ASSERT_ERRNO_SUCCESS();36 ASSERT_EQ(cur, nullptr);37 ASSERT_EQ(mbs[0], '\xF0'); // clown begin38 ASSERT_EQ(mbs[1], '\x9F');39 ASSERT_EQ(mbs[2], '\xA4');40 ASSERT_EQ(mbs[3], '\xA1');41 ASSERT_EQ(mbs[4], '\xE2'); // sigma begin42 ASSERT_EQ(mbs[5], '\x88');43 ASSERT_EQ(mbs[6], '\x91');44 ASSERT_EQ(mbs[7], '\xC3'); // y diaeresis begin45 ASSERT_EQ(mbs[8], '\xBF');46 ASSERT_EQ(mbs[9], '\x41'); // A begin47 ASSERT_EQ(mbs[10], '\0'); // null terminator48}49 50TEST_F(LlvmLibcWcsrtombs, DestLimit) {51 mbstate_t state;52 LIBC_NAMESPACE::memset(&state, 0, sizeof(mbstate_t));53 54 /// clown emoji, sigma symbol, y with diaeresis, letter A55 const wchar_t src[] = {static_cast<wchar_t>(0x1f921),56 static_cast<wchar_t>(0x2211),57 static_cast<wchar_t>(0xff), static_cast<wchar_t>(0x41),58 static_cast<wchar_t>(0x0)};59 const wchar_t *cur = src;60 61 char mbs[11];62 LIBC_NAMESPACE::memset(mbs, '\x01', 11); // dummy initial values63 64 ASSERT_EQ(LIBC_NAMESPACE::wcsrtombs(mbs, &cur, 4, &state),65 static_cast<size_t>(4));66 ASSERT_ERRNO_SUCCESS();67 ASSERT_EQ(cur, src + 1);68 ASSERT_EQ(mbs[0], '\xF0');69 ASSERT_EQ(mbs[1], '\x9F');70 ASSERT_EQ(mbs[2], '\xA4');71 ASSERT_EQ(mbs[3], '\xA1');72 ASSERT_EQ(mbs[4], '\x01'); // didn't write more than 4 bytes73 74 LIBC_NAMESPACE::memset(mbs, '\x01', 11); // dummy initial values75 LIBC_NAMESPACE::memset(&state, 0, sizeof(mbstate_t));76 77 // not enough bytes to convert the second character, so only converts one78 cur = src;79 ASSERT_EQ(LIBC_NAMESPACE::wcsrtombs(mbs, &cur, 6, &state),80 static_cast<size_t>(4));81 ASSERT_ERRNO_SUCCESS();82 ASSERT_EQ(cur, src + 1);83 ASSERT_EQ(mbs[0], '\xF0');84 ASSERT_EQ(mbs[1], '\x9F');85 ASSERT_EQ(mbs[2], '\xA4');86 ASSERT_EQ(mbs[3], '\xA1');87 ASSERT_EQ(mbs[4], '\x01');88}89 90TEST_F(LlvmLibcWcsrtombs, ErrnoTest) {91 mbstate_t state;92 LIBC_NAMESPACE::memset(&state, 0, sizeof(mbstate_t));93 94 const wchar_t src[] = {static_cast<wchar_t>(0x1f921),95 static_cast<wchar_t>(0x2211),96 static_cast<wchar_t>(0x12ffff), // invalid widechar97 static_cast<wchar_t>(0x0)};98 const wchar_t *cur = src;99 char mbs[11];100 101 // n parameter ignored when dest is null102 ASSERT_EQ(LIBC_NAMESPACE::wcsrtombs(mbs, &cur, 7, &state),103 static_cast<size_t>(7));104 ASSERT_ERRNO_SUCCESS();105 106 LIBC_NAMESPACE::memset(&state, 0, sizeof(mbstate_t));107 cur = src;108 109 ASSERT_EQ(LIBC_NAMESPACE::wcsrtombs(mbs, &cur, 100, &state),110 static_cast<size_t>(-1));111 ASSERT_ERRNO_EQ(EILSEQ);112}113 114TEST_F(LlvmLibcWcsrtombs, NullState) {115 // this test is the same as DestLimit except it uses a nullptr mbstate*116 117 /// clown emoji, sigma symbol, y with diaeresis, letter A118 const wchar_t src[] = {static_cast<wchar_t>(0x1f921),119 static_cast<wchar_t>(0x2211),120 static_cast<wchar_t>(0xff), static_cast<wchar_t>(0x41),121 static_cast<wchar_t>(0x0)};122 const wchar_t *cur = src;123 124 char mbs[11];125 LIBC_NAMESPACE::memset(mbs, '\x01', 11); // dummy initial values126 127 ASSERT_EQ(LIBC_NAMESPACE::wcsrtombs(mbs, &cur, 4, nullptr),128 static_cast<size_t>(4));129 ASSERT_ERRNO_SUCCESS();130 ASSERT_EQ(cur, src + 1);131 ASSERT_EQ(mbs[0], '\xF0');132 ASSERT_EQ(mbs[1], '\x9F');133 ASSERT_EQ(mbs[2], '\xA4');134 ASSERT_EQ(mbs[3], '\xA1');135 ASSERT_EQ(mbs[4], '\x01'); // didn't write more than 4 bytes136 137 LIBC_NAMESPACE::memset(mbs, '\x01', 11); // dummy initial values138 139 // not enough bytes to convert the second character, so only converts one140 cur = src;141 ASSERT_EQ(LIBC_NAMESPACE::wcsrtombs(mbs, &cur, 6, nullptr),142 static_cast<size_t>(4));143 ASSERT_ERRNO_SUCCESS();144 ASSERT_EQ(cur, src + 1);145 ASSERT_EQ(mbs[0], '\xF0');146 ASSERT_EQ(mbs[1], '\x9F');147 ASSERT_EQ(mbs[2], '\xA4');148 ASSERT_EQ(mbs[3], '\xA1');149 ASSERT_EQ(mbs[4], '\x01');150}151