193 lines · cpp
1//===-- Unittests for wcsnrtombs ------------------------------------------===//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/wcsnrtombs.h"13#include "test/UnitTest/ErrnoCheckingTest.h"14#include "test/UnitTest/Test.h"15 16using LlvmLibcWcsnrtombs = 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(LlvmLibcWcsnrtombs, 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::wcsnrtombs(mbs, &cur, 5, 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(LlvmLibcWcsnrtombs, 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::wcsnrtombs(mbs, &cur, 5, 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 cur = src;77 78 // not enough bytes to convert the second character, so only converts one79 ASSERT_EQ(LIBC_NAMESPACE::wcsnrtombs(mbs, &cur, 5, 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(LlvmLibcWcsnrtombs, SrcLimit) {91 mbstate_t state;92 LIBC_NAMESPACE::memset(&state, 0, sizeof(mbstate_t));93 94 /// clown emoji, sigma symbol, y with diaeresis, letter A95 const wchar_t src[] = {static_cast<wchar_t>(0x1f921),96 static_cast<wchar_t>(0x2211),97 static_cast<wchar_t>(0xff), static_cast<wchar_t>(0x41),98 static_cast<wchar_t>(0x0)};99 const wchar_t *cur = src;100 101 char mbs[11];102 LIBC_NAMESPACE::memset(mbs, '\x01', 11); // dummy initial values103 104 auto res = LIBC_NAMESPACE::wcsnrtombs(mbs, &cur, 2, 11, &state);105 ASSERT_ERRNO_SUCCESS();106 ASSERT_EQ(res, static_cast<size_t>(7));107 ASSERT_EQ(cur, src + 2);108 ASSERT_EQ(mbs[0], '\xF0'); // clown begin109 ASSERT_EQ(mbs[1], '\x9F');110 ASSERT_EQ(mbs[2], '\xA4');111 ASSERT_EQ(mbs[3], '\xA1');112 ASSERT_EQ(mbs[4], '\xE2'); // sigma begin113 ASSERT_EQ(mbs[5], '\x88');114 ASSERT_EQ(mbs[6], '\x91');115 ASSERT_EQ(mbs[7], '\x01');116 117 res = LIBC_NAMESPACE::wcsnrtombs(mbs + res, &cur, 100, 11, &state);118 ASSERT_ERRNO_SUCCESS();119 ASSERT_EQ(res, static_cast<size_t>(3));120 ASSERT_EQ(cur, nullptr);121 ASSERT_EQ(mbs[0], '\xF0'); // clown begin122 ASSERT_EQ(mbs[1], '\x9F');123 ASSERT_EQ(mbs[2], '\xA4');124 ASSERT_EQ(mbs[3], '\xA1');125 ASSERT_EQ(mbs[4], '\xE2'); // sigma begin126 ASSERT_EQ(mbs[5], '\x88');127 ASSERT_EQ(mbs[6], '\x91');128 ASSERT_EQ(mbs[7], '\xC3'); // y diaeresis begin129 ASSERT_EQ(mbs[8], '\xBF');130 ASSERT_EQ(mbs[9], '\x41'); // A begin131 ASSERT_EQ(mbs[10], '\0'); // null terminator132}133 134TEST_F(LlvmLibcWcsnrtombs, ErrnoTest) {135 mbstate_t state;136 LIBC_NAMESPACE::memset(&state, 0, sizeof(mbstate_t));137 138 const wchar_t src[] = {static_cast<wchar_t>(0x1f921),139 static_cast<wchar_t>(0x2211),140 static_cast<wchar_t>(0x12ffff), // invalid widechar141 static_cast<wchar_t>(0x0)};142 const wchar_t *cur = src;143 char mbs[11];144 145 // n parameter ignored when dest is null146 ASSERT_EQ(LIBC_NAMESPACE::wcsnrtombs(mbs, &cur, 5, 7, &state),147 static_cast<size_t>(7));148 ASSERT_ERRNO_SUCCESS();149 150 LIBC_NAMESPACE::memset(&state, 0, sizeof(mbstate_t));151 ASSERT_EQ(LIBC_NAMESPACE::wcsnrtombs(mbs, &cur, 5, 100, &state),152 static_cast<size_t>(-1));153 ASSERT_ERRNO_EQ(EILSEQ);154}155 156TEST_F(LlvmLibcWcsnrtombs, NullState) {157 // this test is the same as DestLimit except it uses a nullptr mbstate*158 159 /// clown emoji, sigma symbol, y with diaeresis, letter A160 const wchar_t src[] = {static_cast<wchar_t>(0x1f921),161 static_cast<wchar_t>(0x2211),162 static_cast<wchar_t>(0xff), static_cast<wchar_t>(0x41),163 static_cast<wchar_t>(0x0)};164 const wchar_t *cur = src;165 166 char mbs[11];167 LIBC_NAMESPACE::memset(mbs, '\x01', 11); // dummy initial values168 169 ASSERT_EQ(LIBC_NAMESPACE::wcsnrtombs(mbs, &cur, 5, 4, nullptr),170 static_cast<size_t>(4));171 ASSERT_ERRNO_SUCCESS();172 ASSERT_EQ(cur, src + 1);173 ASSERT_EQ(mbs[0], '\xF0');174 ASSERT_EQ(mbs[1], '\x9F');175 ASSERT_EQ(mbs[2], '\xA4');176 ASSERT_EQ(mbs[3], '\xA1');177 ASSERT_EQ(mbs[4], '\x01'); // didn't write more than 4 bytes178 179 LIBC_NAMESPACE::memset(mbs, '\x01', 11); // dummy initial values180 181 // not enough bytes to convert the second character, so only converts one182 cur = src;183 ASSERT_EQ(LIBC_NAMESPACE::wcsnrtombs(mbs, &cur, 5, 6, nullptr),184 static_cast<size_t>(4));185 ASSERT_ERRNO_SUCCESS();186 ASSERT_EQ(cur, src + 1);187 ASSERT_EQ(mbs[0], '\xF0');188 ASSERT_EQ(mbs[1], '\x9F');189 ASSERT_EQ(mbs[2], '\xA4');190 ASSERT_EQ(mbs[3], '\xA1');191 ASSERT_EQ(mbs[4], '\x01');192}193