1//===-- Unittests for wcrtomb --------------------------------------------===//
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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "hdr/types/mbstate_t.h"
10#include "hdr/types/wchar_t.h"
11#include "src/__support/libc_errno.h"
12#include "src/__support/wchar/mbstate.h"
13#include "src/string/memset.h"
14#include "src/wchar/wcrtomb.h"
15#include "test/UnitTest/ErrnoCheckingTest.h"
16#include "test/UnitTest/Test.h"
17
18using LlvmLibcWCRToMBTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
19
20TEST_F(LlvmLibcWCRToMBTest, OneByte) {
21 mbstate_t state;
22 LIBC_NAMESPACE::memset(&state, 0, sizeof(mbstate_t));
23 wchar_t wc = L'U';
24 char mb[4];
25 size_t cnt = LIBC_NAMESPACE::wcrtomb(mb, wc, &state);
26 ASSERT_EQ(cnt, static_cast<size_t>(1));
27 ASSERT_EQ(mb[0], 'U');
28 ASSERT_ERRNO_SUCCESS();
29}
30
31TEST_F(LlvmLibcWCRToMBTest, TwoByte) {
32 mbstate_t state;
33 LIBC_NAMESPACE::memset(&state, 0, sizeof(mbstate_t));
34 // testing utf32: 0xff -> utf8: 0xc3 0xbf
35 wchar_t wc = 0xff;
36 char mb[4];
37 size_t cnt = LIBC_NAMESPACE::wcrtomb(mb, wc, &state);
38 ASSERT_EQ(cnt, static_cast<size_t>(2));
39 ASSERT_EQ(mb[0], static_cast<char>(0xc3));
40 ASSERT_EQ(mb[1], static_cast<char>(0xbf));
41 ASSERT_ERRNO_SUCCESS();
42}
43
44TEST_F(LlvmLibcWCRToMBTest, ThreeByte) {
45 mbstate_t state;
46 LIBC_NAMESPACE::memset(&state, 0, sizeof(mbstate_t));
47 // testing utf32: 0xac15 -> utf8: 0xea 0xb0 0x95
48 wchar_t wc = 0xac15;
49 char mb[4];
50 size_t cnt = LIBC_NAMESPACE::wcrtomb(mb, wc, &state);
51 ASSERT_EQ(cnt, static_cast<size_t>(3));
52 ASSERT_EQ(mb[0], static_cast<char>(0xea));
53 ASSERT_EQ(mb[1], static_cast<char>(0xb0));
54 ASSERT_EQ(mb[2], static_cast<char>(0x95));
55 ASSERT_ERRNO_SUCCESS();
56}
57
58TEST_F(LlvmLibcWCRToMBTest, FourByte) {
59 mbstate_t state;
60 LIBC_NAMESPACE::memset(&state, 0, sizeof(mbstate_t));
61 // testing utf32: 0x1f921 -> utf8: 0xf0 0x9f 0xa4 0xa1
62 wchar_t wc = 0x1f921;
63 char mb[4];
64 size_t cnt = LIBC_NAMESPACE::wcrtomb(mb, wc, &state);
65 ASSERT_EQ(cnt, static_cast<size_t>(4));
66 ASSERT_EQ(mb[0], static_cast<char>(0xf0));
67 ASSERT_EQ(mb[1], static_cast<char>(0x9f));
68 ASSERT_EQ(mb[2], static_cast<char>(0xa4));
69 ASSERT_EQ(mb[3], static_cast<char>(0xa1));
70 ASSERT_ERRNO_SUCCESS();
71}
72
73TEST_F(LlvmLibcWCRToMBTest, NullString) {
74 mbstate_t state;
75 LIBC_NAMESPACE::memset(&state, 0, sizeof(mbstate_t));
76 wchar_t wc = L'A';
77 char mb[4];
78
79 // should be equivalent to the call wcrtomb(buf, L'\0', state)
80 size_t cnt1 = LIBC_NAMESPACE::wcrtomb(nullptr, wc, &state);
81 ASSERT_ERRNO_SUCCESS();
82 size_t cnt2 = LIBC_NAMESPACE::wcrtomb(mb, L'\0', &state);
83 ASSERT_ERRNO_SUCCESS();
84
85 ASSERT_EQ(cnt1, cnt2);
86}
87
88TEST_F(LlvmLibcWCRToMBTest, NullState) {
89 wchar_t wc = L'A';
90 char mb[4];
91 size_t cnt = LIBC_NAMESPACE::wcrtomb(mb, wc, nullptr);
92 ASSERT_ERRNO_SUCCESS();
93 ASSERT_EQ(cnt, static_cast<size_t>(1));
94}
95
96TEST_F(LlvmLibcWCRToMBTest, InvalidWchar) {
97 mbstate_t state;
98 LIBC_NAMESPACE::memset(&state, 0, sizeof(mbstate_t));
99 wchar_t wc = 0x12ffff;
100 char mb[4];
101 size_t cnt = LIBC_NAMESPACE::wcrtomb(mb, wc, &state);
102 ASSERT_EQ(cnt, static_cast<size_t>(-1));
103 ASSERT_ERRNO_EQ(EILSEQ);
104}
105
106TEST_F(LlvmLibcWCRToMBTest, InvalidMBState) {
107 mbstate_t *state;
108 LIBC_NAMESPACE::internal::mbstate inv;
109 inv.total_bytes = 6;
110 state = reinterpret_cast<mbstate_t *>(&inv);
111 wchar_t wc = L'A';
112 char mb[4];
113 size_t cnt = LIBC_NAMESPACE::wcrtomb(mb, wc, state);
114 ASSERT_EQ(cnt, static_cast<size_t>(-1));
115 ASSERT_ERRNO_EQ(EINVAL);
116}
117

source code of libc/test/src/wchar/wcrtomb_test.cpp