brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.1 KiB · 125683a Raw
172 lines · cpp
1//===-- Unittests for mbstowcs --------------------------------------------===//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/wchar_t.h"11#include "src/__support/macros/null_check.h"12#include "src/stdlib/mbstowcs.h"13#include "test/UnitTest/ErrnoCheckingTest.h"14#include "test/UnitTest/Test.h"15 16using LlvmLibcMBSToWCSTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;17 18TEST_F(LlvmLibcMBSToWCSTest, OneByteOneChar) {19  const char *ch = "A";20  const char *original = ch;21  wchar_t dest[2];22  size_t n = LIBC_NAMESPACE::mbstowcs(dest, ch, 1);23  ASSERT_EQ(static_cast<char>(*dest), 'A');24  ASSERT_EQ(static_cast<int>(n), 1);25  // Making sure the pointer is not getting updated26  ASSERT_EQ(ch, original);27  ASSERT_ERRNO_SUCCESS();28 29  n = LIBC_NAMESPACE::mbstowcs(dest + 1, ch + 1, 1);30  ASSERT_EQ(static_cast<char>(dest[1]), '\0');31  // Should not include null terminator32  ASSERT_EQ(static_cast<int>(n), 0);33  // Making sure the pointer is not getting updated34  ASSERT_EQ(ch, original);35  ASSERT_ERRNO_SUCCESS();36}37 38TEST_F(LlvmLibcMBSToWCSTest, FourByteOneChar) {39  const char *src = "\xf0\x9f\x98\xb9"; // laughing cat emoji 😹40  const char *original = src;41  wchar_t dest[2];42  size_t n = LIBC_NAMESPACE::mbstowcs(dest, src, 2);43  ASSERT_ERRNO_SUCCESS();44  ASSERT_EQ(static_cast<int>(dest[0]), 128569);45  ASSERT_TRUE(dest[1] == L'\0');46  // Should not count null terminator in number47  ASSERT_EQ(static_cast<int>(n), 1);48  // Making sure the pointer is not getting updated49  ASSERT_EQ(src, original);50}51 52TEST_F(LlvmLibcMBSToWCSTest, MultiByteTwoCharacters) {53  // Two laughing cat emojis "😹😹"54  const char *src = "\xf0\x9f\x98\xb9\xf0\x9f\x98\xb9";55  const char *original = src;56  wchar_t dest[3];57  size_t n = LIBC_NAMESPACE::mbstowcs(dest, src, 3);58  ASSERT_ERRNO_SUCCESS();59  ASSERT_EQ(static_cast<int>(dest[0]), 128569);60  ASSERT_EQ(static_cast<int>(dest[1]), 128569);61  ASSERT_TRUE(dest[2] == L'\0');62  // Should not count null terminator in number63  ASSERT_EQ(static_cast<int>(n), 2);64  // Making sure the pointer is not getting updated65  ASSERT_EQ(src, original);66}67 68TEST_F(LlvmLibcMBSToWCSTest, MixedNumberOfBytes) {69  // 'A', sigma symbol 'Σ', recycling symbol '♻', laughing cat emoji '😹'70  const char *src = "A\xce\xa3\xe2\x99\xbb\xf0\x9f\x98\xb9";71  const char *original = src;72  wchar_t dest[5];73  size_t n = LIBC_NAMESPACE::mbstowcs(dest, src, 5);74  ASSERT_ERRNO_SUCCESS();75  ASSERT_EQ(static_cast<char>(dest[0]), 'A');76  ASSERT_EQ(static_cast<int>(dest[1]), 931);77  ASSERT_EQ(static_cast<int>(dest[2]), 9851);78  ASSERT_EQ(static_cast<int>(dest[3]), 128569);79  ASSERT_TRUE(dest[4] == L'\0');80  // Should not count null terminator in number81  ASSERT_EQ(static_cast<int>(n), 4);82  // Making sure the pointer is not getting updated83  ASSERT_EQ(src, original);84}85 86TEST_F(LlvmLibcMBSToWCSTest, ReadLessThanStringLength) {87  // Four laughing cat emojis "😹😹😹😹"88  const char *src =89      "\xf0\x9f\x98\xb9\xf0\x9f\x98\xb9\xf0\x9f\x98\xb9\xf0\x9f\x98\xb9";90  const char *original = src;91  wchar_t dest[5] = {L'a', L'b', L'c', L'd', L'e'};92  size_t n = LIBC_NAMESPACE::mbstowcs(dest, src, 3);93  ASSERT_ERRNO_SUCCESS();94  // Should have read 3 emojis95  ASSERT_EQ(static_cast<int>(n), 3);96  ASSERT_EQ(static_cast<int>(dest[0]), 128569);97  ASSERT_EQ(static_cast<int>(dest[1]), 128569);98  ASSERT_EQ(static_cast<int>(dest[2]), 128569);99  ASSERT_TRUE(dest[3] == L'd');100  ASSERT_TRUE(dest[4] == L'e');101  // Making sure the pointer is not getting updated102  ASSERT_EQ(src, original);103}104 105TEST_F(LlvmLibcMBSToWCSTest, InvalidFirstByte) {106  // 0x80 is invalid first byte of mb character107  const char *src =108      "\x80\x9f\x98\xb9\xf0\x9f\x98\xb9\xf0\x9f\x98\xb9\xf0\x9f\x98\xb9";109  wchar_t dest[3];110  size_t n = LIBC_NAMESPACE::mbstowcs(dest, src, 3);111  // Should return error and set errno112  ASSERT_EQ(static_cast<int>(n), -1);113  ASSERT_ERRNO_EQ(EILSEQ);114}115 116TEST_F(LlvmLibcMBSToWCSTest, InvalidMiddleByte) {117  // The 7th byte is invalid for a 4 byte character118  const char *src =119      "\xf0\x9f\x98\xb9\xf0\x9f\xf0\xb9\xf0\x9f\x98\xb9\xf0\x9f\x98\xb9";120  const char *original = src;121  wchar_t dest[3];122  size_t n = LIBC_NAMESPACE::mbstowcs(dest, src, 5);123  // Should return error and set errno124  ASSERT_EQ(static_cast<int>(n), -1);125  ASSERT_ERRNO_EQ(EILSEQ);126  // Making sure the pointer is not getting updated127  ASSERT_EQ(src, original);128}129 130TEST_F(LlvmLibcMBSToWCSTest, NullDestination) {131  // Four laughing cat emojis "😹😹😹😹"132  const char *src =133      "\xf0\x9f\x98\xb9\xf0\x9f\x98\xb9\xf0\x9f\x98\xb9\xf0\x9f\x98\xb9";134  const char *original = src;135  size_t n = LIBC_NAMESPACE::mbstowcs(nullptr, src, 2);136  ASSERT_ERRNO_SUCCESS();137  // Null destination should ignore len and read till end of string138  ASSERT_EQ(static_cast<int>(n), 4);139  // Making sure the pointer is not getting updated140  ASSERT_EQ(src, original);141}142 143TEST_F(LlvmLibcMBSToWCSTest, ErrnoChecks) {144  // Two laughing cat emojis and invalid 3rd mb char (3rd byte of it)145  const char *src =146      "\xf0\x9f\x98\xb9\xf0\x9f\x98\xb9\xf0\x9f\xf0\xb9\xf0\x9f\x98\xb9";147  const char *original = src;148  wchar_t dest[5];149  // First two bytes are valid --> should not set errno150  size_t n = LIBC_NAMESPACE::mbstowcs(dest, src, 2);151  ASSERT_ERRNO_SUCCESS();152  ASSERT_EQ(static_cast<int>(n), 2);153  ASSERT_EQ(static_cast<int>(dest[0]), 128569);154  ASSERT_EQ(static_cast<int>(dest[1]), 128569);155  // Making sure the pointer is not getting updated156  ASSERT_EQ(src, original);157  // Trying to read the 3rd byte should set errno158  n = LIBC_NAMESPACE::mbstowcs(dest, src + 2, 2);159  ASSERT_ERRNO_EQ(EILSEQ);160  ASSERT_EQ(static_cast<int>(n), -1);161  // Making sure the pointer is not getting updated162  ASSERT_EQ(src, original);163}164 165#if defined(LIBC_ADD_NULL_CHECKS)166TEST(LlvmLibcMBSToWCSTest, NullptrCrash) {167  // Passing in a nullptr should crash the program.168  EXPECT_DEATH([] { LIBC_NAMESPACE::mbstowcs(nullptr, nullptr, 1); },169               WITH_SIGNAL(-1));170}171#endif // LIBC_ADD_NULL_CHECKS172