brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.4 KiB · 2d431ed Raw
214 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/errno_macros.h"10#include "hdr/types/size_t.h"11#include "hdr/types/wchar_t.h"12#include "src/__support/error_or.h"13#include "src/__support/macros/null_check.h"14#include "src/__support/macros/properties/os.h"15#include "src/__support/wchar/mbstate.h"16#include "src/__support/wchar/wcsnrtombs.h"17#include "test/UnitTest/Test.h"18 19// TODO: add support for 16-bit widechars to remove this macro20#ifdef LIBC_TARGET_OS_IS_WINDOWS21TEST(LlvmLibcStringConverterTest, Windows) {22  // pass on windows for now23}24 25#else26 27TEST(LlvmLibcWcsnrtombs, AllMultibyteLengths) {28  LIBC_NAMESPACE::internal::mbstate state;29 30  /// clown emoji, sigma symbol, y with diaeresis, letter A31  const wchar_t src[] = {static_cast<wchar_t>(0x1f921),32                         static_cast<wchar_t>(0x2211),33                         static_cast<wchar_t>(0xff), static_cast<wchar_t>(0x41),34                         static_cast<wchar_t>(0x0)};35  const wchar_t *cur = src;36  char mbs[11];37 38  auto res = LIBC_NAMESPACE::internal::wcsnrtombs(mbs, &cur, 5, 11, &state);39  ASSERT_TRUE(res.has_value());40  ASSERT_EQ(res.value(), static_cast<size_t>(10));41  ASSERT_EQ(cur, nullptr);42  ASSERT_EQ(mbs[0], '\xF0'); // clown begin43  ASSERT_EQ(mbs[1], '\x9F');44  ASSERT_EQ(mbs[2], '\xA4');45  ASSERT_EQ(mbs[3], '\xA1');46  ASSERT_EQ(mbs[4], '\xE2'); // sigma begin47  ASSERT_EQ(mbs[5], '\x88');48  ASSERT_EQ(mbs[6], '\x91');49  ASSERT_EQ(mbs[7], '\xC3'); // y diaeresis begin50  ASSERT_EQ(mbs[8], '\xBF');51  ASSERT_EQ(mbs[9], '\x41'); // A begin52  ASSERT_EQ(mbs[10], '\0');  // null terminator53}54 55TEST(LlvmLibcWcsnrtombs, DestLimit) {56  LIBC_NAMESPACE::internal::mbstate state1;57 58  /// clown emoji, sigma symbol, y with diaeresis, letter A59  const wchar_t src[] = {static_cast<wchar_t>(0x1f921),60                         static_cast<wchar_t>(0x2211),61                         static_cast<wchar_t>(0xff), static_cast<wchar_t>(0x41),62                         static_cast<wchar_t>(0x0)};63  const wchar_t *cur = src;64 65  char mbs[11];66  for (int i = 0; i < 11; ++i)67    mbs[i] = '\x01'; // dummy initial values68 69  auto res = LIBC_NAMESPACE::internal::wcsnrtombs(mbs, &cur, 5, 4, &state1);70  ASSERT_TRUE(res.has_value());71  ASSERT_EQ(res.value(), static_cast<size_t>(4));72  ASSERT_EQ(cur, src + 1);73  ASSERT_EQ(mbs[0], '\xF0');74  ASSERT_EQ(mbs[1], '\x9F');75  ASSERT_EQ(mbs[2], '\xA4');76  ASSERT_EQ(mbs[3], '\xA1');77  ASSERT_EQ(mbs[4], '\x01'); // didn't write more than 4 bytes78 79  for (int i = 0; i < 11; ++i)80    mbs[i] = '\x01'; // dummy initial values81  LIBC_NAMESPACE::internal::mbstate state2;82 83  // not enough bytes to convert the second character, so only converts one84  cur = src;85  res = LIBC_NAMESPACE::internal::wcsnrtombs(mbs, &cur, 5, 6, &state2);86  ASSERT_TRUE(res.has_value());87  ASSERT_EQ(res.value(), static_cast<size_t>(4));88  ASSERT_EQ(cur, src + 1);89  ASSERT_EQ(mbs[0], '\xF0');90  ASSERT_EQ(mbs[1], '\x9F');91  ASSERT_EQ(mbs[2], '\xA4');92  ASSERT_EQ(mbs[3], '\xA1');93  ASSERT_EQ(mbs[4], '\x01');94}95 96TEST(LlvmLibcWcsnrtombs, SrcLimit) {97  LIBC_NAMESPACE::internal::mbstate state;98 99  /// clown emoji, sigma symbol, y with diaeresis, letter A100  const wchar_t src[] = {static_cast<wchar_t>(0x1f921),101                         static_cast<wchar_t>(0x2211),102                         static_cast<wchar_t>(0xff), static_cast<wchar_t>(0x41),103                         static_cast<wchar_t>(0x0)};104  const wchar_t *cur = src;105 106  char mbs[11];107  for (int i = 0; i < 11; ++i)108    mbs[i] = '\x01'; // dummy initial values109 110  auto res = LIBC_NAMESPACE::internal::wcsnrtombs(mbs, &cur, 2, 11, &state);111  ASSERT_TRUE(res.has_value());112  ASSERT_EQ(res.value(), static_cast<size_t>(7));113  ASSERT_EQ(cur, src + 2);114  ASSERT_EQ(mbs[0], '\xF0'); // clown begin115  ASSERT_EQ(mbs[1], '\x9F');116  ASSERT_EQ(mbs[2], '\xA4');117  ASSERT_EQ(mbs[3], '\xA1');118  ASSERT_EQ(mbs[4], '\xE2'); // sigma begin119  ASSERT_EQ(mbs[5], '\x88');120  ASSERT_EQ(mbs[6], '\x91');121  ASSERT_EQ(mbs[7], '\x01');122 123  res = LIBC_NAMESPACE::internal::wcsnrtombs(mbs + res.value(), &cur, 100, 11,124                                             &state);125  ASSERT_TRUE(res.has_value());126  ASSERT_EQ(res.value(), static_cast<size_t>(3));127  ASSERT_EQ(cur, nullptr);128  ASSERT_EQ(mbs[0], '\xF0'); // clown begin129  ASSERT_EQ(mbs[1], '\x9F');130  ASSERT_EQ(mbs[2], '\xA4');131  ASSERT_EQ(mbs[3], '\xA1');132  ASSERT_EQ(mbs[4], '\xE2'); // sigma begin133  ASSERT_EQ(mbs[5], '\x88');134  ASSERT_EQ(mbs[6], '\x91');135  ASSERT_EQ(mbs[7], '\xC3'); // y diaeresis begin136  ASSERT_EQ(mbs[8], '\xBF');137  ASSERT_EQ(mbs[9], '\x41'); // A begin138  ASSERT_EQ(mbs[10], '\0');  // null terminator139}140 141TEST(LlvmLibcWcsnrtombs, NullDest) {142  LIBC_NAMESPACE::internal::mbstate state1;143 144  const wchar_t src[] = {static_cast<wchar_t>(0x1f921),145                         static_cast<wchar_t>(0x2211),146                         static_cast<wchar_t>(0xff), static_cast<wchar_t>(0x41),147                         static_cast<wchar_t>(0x0)};148  const wchar_t *cur = src;149 150  // n parameter ignored when dest is null151  auto res = LIBC_NAMESPACE::internal::wcsnrtombs(nullptr, &cur, 5, 1, &state1);152  ASSERT_TRUE(res.has_value());153  ASSERT_EQ(res.value(), static_cast<size_t>(10));154  ASSERT_EQ(cur, src); // pointer not updated when dest = null155 156  LIBC_NAMESPACE::internal::mbstate state2;157  res = LIBC_NAMESPACE::internal::wcsnrtombs(nullptr, &cur, 5, 100, &state2);158  ASSERT_TRUE(res.has_value());159  ASSERT_EQ(res.value(), static_cast<size_t>(10));160  ASSERT_EQ(cur, src);161}162 163TEST(LlvmLibcWcsnrtombs, InvalidState) {164  // this is more thoroughly tested by CharacterConverter165  LIBC_NAMESPACE::internal::mbstate state;166  state.total_bytes = 100;167 168  const wchar_t src[] = {static_cast<wchar_t>(0x1f921),169                         static_cast<wchar_t>(0x2211),170                         static_cast<wchar_t>(0xff), static_cast<wchar_t>(0x41),171                         static_cast<wchar_t>(0x0)};172  const wchar_t *cur = src;173 174  // n parameter ignored when dest is null175  auto res = LIBC_NAMESPACE::internal::wcsnrtombs(nullptr, &cur, 5, 1, &state);176  ASSERT_FALSE(res.has_value());177  ASSERT_EQ(res.error(), EINVAL);178}179 180TEST(LlvmLibcWcsnrtombs, InvalidCharacter) {181  LIBC_NAMESPACE::internal::mbstate state1;182 183  const wchar_t src[] = {static_cast<wchar_t>(0x1f921),184                         static_cast<wchar_t>(0x2211),185                         static_cast<wchar_t>(0x12ffff), // invalid widechar186                         static_cast<wchar_t>(0x0)};187  const wchar_t *cur = src;188  char mbs[11];189 190  // n parameter ignored when dest is null191  auto res = LIBC_NAMESPACE::internal::wcsnrtombs(mbs, &cur, 5, 7, &state1);192  ASSERT_TRUE(res.has_value());193  ASSERT_EQ(res.value(), static_cast<size_t>(7));194 195  LIBC_NAMESPACE::internal::mbstate state2;196  cur = src;197  res = LIBC_NAMESPACE::internal::wcsnrtombs(mbs, &cur, 5, 11, &state2);198  ASSERT_FALSE(res.has_value());199  ASSERT_EQ(res.error(), EILSEQ);200}201 202#if defined(LIBC_ADD_NULL_CHECKS) && !defined(LIBC_HAS_SANITIZER)203TEST(LlvmLibcWcsnrtombs, NullSrc) {204  EXPECT_DEATH(205      [] {206        LIBC_NAMESPACE::internal::mbstate state;207        char mbs[10];208        LIBC_NAMESPACE::internal::wcsnrtombs(mbs, nullptr, 1, 1, &state);209      },210      WITH_SIGNAL(-1));211}212#endif // LIBC_HAS_ADDRESS_SANITIZER213#endif214