|
1 | | -//===-- Unittests for mblen -----------------------------------------------===// |
| 1 | +//===-- Unittests for mbrlen ----------------------------------------------===// |
2 | 2 | // |
3 | 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | 4 | // See https://llvm.org/LICENSE.txt for license information. |
|
8 | 8 |
|
9 | 9 | #include "hdr/types/wchar_t.h" |
10 | 10 | #include "src/__support/libc_errno.h" |
11 | | -#include "src/wchar/mblen.h" |
| 11 | +#include "src/__support/wchar/mbstate.h" |
| 12 | +#include "src/string/memset.h" |
| 13 | +#include "src/wchar/mbrlen.h" |
12 | 14 | #include "test/UnitTest/ErrnoCheckingTest.h" |
13 | 15 | #include "test/UnitTest/Test.h" |
14 | 16 |
|
15 | | -using LlvmLibcMBLenTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest; |
| 17 | +using LlvmLibcMBRLenTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest; |
16 | 18 |
|
17 | | -TEST_F(LlvmLibcMBLenTest, OneByte) { |
| 19 | +TEST_F(LlvmLibcMBRLenTest, OneByte) { |
18 | 20 | const char *ch = "A"; |
19 | | - int n = LIBC_NAMESPACE::mblen(ch, 1); |
| 21 | + mbstate_t mb; |
| 22 | + LIBC_NAMESPACE::memset(&mb, 0, sizeof(mbstate_t)); |
| 23 | + size_t n = LIBC_NAMESPACE::mbrlen(ch, 1, &mb); |
20 | 24 | ASSERT_ERRNO_SUCCESS(); |
21 | | - ASSERT_EQ(n, 1); |
| 25 | + ASSERT_EQ(n, static_cast<size_t>(1)); |
22 | 26 |
|
23 | 27 | // Should fail since we have not read enough |
24 | | - n = LIBC_NAMESPACE::mblen(ch, 0); |
| 28 | + n = LIBC_NAMESPACE::mbrlen(ch, 0, &mb); |
25 | 29 | ASSERT_ERRNO_SUCCESS(); |
26 | | - ASSERT_EQ(n, -1); |
| 30 | + ASSERT_EQ(n, static_cast<size_t>(-2)); |
27 | 31 | } |
28 | 32 |
|
29 | | -TEST_F(LlvmLibcMBLenTest, TwoByte) { |
| 33 | +TEST_F(LlvmLibcMBRLenTest, TwoByte) { |
30 | 34 | const char ch[2] = {static_cast<char>(0xC2), |
31 | 35 | static_cast<char>(0x8E)}; // car symbol |
32 | | - int n = LIBC_NAMESPACE::mblen(ch, 4); |
| 36 | + mbstate_t mb; |
| 37 | + LIBC_NAMESPACE::memset(&mb, 0, sizeof(mbstate_t)); |
| 38 | + size_t n = LIBC_NAMESPACE::mbrlen(ch, 4, nullptr); |
33 | 39 | ASSERT_ERRNO_SUCCESS(); |
34 | | - ASSERT_EQ(n, 2); |
| 40 | + ASSERT_EQ(static_cast<int>(n), 2); |
35 | 41 |
|
36 | 42 | // Should fail since we have not read enough |
37 | | - n = LIBC_NAMESPACE::mblen(ch, 1); |
38 | | - ASSERT_EQ(n, -1); |
| 43 | + n = LIBC_NAMESPACE::mbrlen(ch, 1, &mb); |
| 44 | + ASSERT_EQ(static_cast<int>(n), -2); |
| 45 | + ASSERT_ERRNO_SUCCESS(); |
| 46 | + // Should pass after trying to read next byte |
| 47 | + n = LIBC_NAMESPACE::mbrlen(ch + 1, 1, &mb); |
| 48 | + ASSERT_EQ(static_cast<int>(n), 1); |
39 | 49 | ASSERT_ERRNO_SUCCESS(); |
40 | | - // Should fail after trying to read next byte too |
41 | | - n = LIBC_NAMESPACE::mblen(ch + 1, 1); |
42 | | - ASSERT_EQ(n, -1); |
43 | | - // This one should be an invalid starting byte so should set errno |
44 | | - ASSERT_ERRNO_EQ(EILSEQ); |
45 | 50 | } |
46 | 51 |
|
47 | | -TEST_F(LlvmLibcMBLenTest, ThreeByte) { |
| 52 | +TEST_F(LlvmLibcMBRLenTest, ThreeByte) { |
48 | 53 | const char ch[3] = {static_cast<char>(0xE2), static_cast<char>(0x88), |
49 | 54 | static_cast<char>(0x91)}; // ∑ sigma symbol |
50 | | - int n = LIBC_NAMESPACE::mblen(ch, 3); |
51 | | - ASSERT_EQ(n, 3); |
| 55 | + mbstate_t mb; |
| 56 | + LIBC_NAMESPACE::memset(&mb, 0, sizeof(mbstate_t)); |
| 57 | + size_t n = LIBC_NAMESPACE::mbrlen(ch, 3, &mb); |
| 58 | + ASSERT_EQ(static_cast<int>(n), 3); |
52 | 59 | ASSERT_ERRNO_SUCCESS(); |
53 | 60 |
|
54 | 61 | // Should fail since we have not read enough |
55 | | - n = LIBC_NAMESPACE::mblen(ch, 2); |
56 | | - ASSERT_EQ(n, -1); |
| 62 | + n = LIBC_NAMESPACE::mbrlen(ch, 2, &mb); |
| 63 | + ASSERT_EQ(static_cast<int>(n), -2); |
57 | 64 | ASSERT_ERRNO_SUCCESS(); |
58 | 65 | } |
59 | 66 |
|
60 | | -TEST_F(LlvmLibcMBLenTest, FourByte) { |
| 67 | +TEST_F(LlvmLibcMBRLenTest, FourByte) { |
61 | 68 | const char ch[4] = {static_cast<char>(0xF0), static_cast<char>(0x9F), |
62 | 69 | static_cast<char>(0xA4), |
63 | 70 | static_cast<char>(0xA1)}; // 🤡 clown emoji |
64 | | - int n = LIBC_NAMESPACE::mblen(ch, 4); |
65 | | - ASSERT_EQ(n, 4); |
| 71 | + mbstate_t mb; |
| 72 | + LIBC_NAMESPACE::memset(&mb, 0, sizeof(mbstate_t)); |
| 73 | + size_t n = LIBC_NAMESPACE::mbrlen(ch, 4, &mb); |
| 74 | + ASSERT_EQ(static_cast<int>(n), 4); |
| 75 | + ASSERT_ERRNO_SUCCESS(); |
| 76 | + |
| 77 | + // Should fail since we have not read enough |
| 78 | + n = LIBC_NAMESPACE::mbrlen(ch, 2, &mb); |
| 79 | + ASSERT_EQ(static_cast<int>(n), -2); |
66 | 80 | ASSERT_ERRNO_SUCCESS(); |
67 | 81 |
|
68 | 82 | // Should fail since we have not read enough |
69 | | - n = LIBC_NAMESPACE::mblen(ch, 2); |
70 | | - ASSERT_EQ(n, -1); |
| 83 | + n = LIBC_NAMESPACE::mbrlen(ch + 2, 1, &mb); |
| 84 | + ASSERT_EQ(static_cast<int>(n), -2); |
| 85 | + ASSERT_ERRNO_SUCCESS(); |
| 86 | + |
| 87 | + // Should pass after reading final byte |
| 88 | + n = LIBC_NAMESPACE::mbrlen(ch + 3, 5, &mb); |
| 89 | + ASSERT_EQ(static_cast<int>(n), 1); |
71 | 90 | ASSERT_ERRNO_SUCCESS(); |
72 | 91 | } |
73 | 92 |
|
74 | | -TEST_F(LlvmLibcMBLenTest, InvalidByte) { |
| 93 | +TEST_F(LlvmLibcMBRLenTest, InvalidByte) { |
75 | 94 | const char ch[1] = {static_cast<char>(0x80)}; |
76 | | - int n = LIBC_NAMESPACE::mblen(ch, 1); |
77 | | - ASSERT_EQ(n, -1); |
| 95 | + size_t n = LIBC_NAMESPACE::mbrlen(ch, 1, nullptr); |
| 96 | + ASSERT_EQ(static_cast<int>(n), -1); |
78 | 97 | ASSERT_ERRNO_EQ(EILSEQ); |
79 | 98 | } |
80 | 99 |
|
81 | | -TEST_F(LlvmLibcMBLenTest, InvalidMultiByte) { |
| 100 | +TEST_F(LlvmLibcMBRLenTest, InvalidMultiByte) { |
82 | 101 | const char ch[4] = {static_cast<char>(0x80), static_cast<char>(0x00), |
83 | 102 | static_cast<char>(0x80), |
84 | 103 | static_cast<char>(0x00)}; // invalid sequence of bytes |
| 104 | + mbstate_t mb; |
| 105 | + LIBC_NAMESPACE::memset(&mb, 0, sizeof(mbstate_t)); |
85 | 106 | // Trying to push all 4 should error |
86 | | - int n = LIBC_NAMESPACE::mblen(ch, 4); |
87 | | - ASSERT_EQ(n, -1); |
| 107 | + size_t n = LIBC_NAMESPACE::mbrlen(ch, 4, &mb); |
| 108 | + ASSERT_EQ(static_cast<int>(n), -1); |
88 | 109 | ASSERT_ERRNO_EQ(EILSEQ); |
89 | 110 |
|
90 | 111 | // Trying to push the second and third should correspond to null wc |
91 | | - n = LIBC_NAMESPACE::mblen(ch + 1, 2); |
92 | | - ASSERT_EQ(n, 0); |
| 112 | + n = LIBC_NAMESPACE::mbrlen(ch + 1, 2, &mb); |
| 113 | + ASSERT_EQ(static_cast<int>(n), 0); |
93 | 114 | ASSERT_ERRNO_SUCCESS(); |
94 | 115 | } |
95 | 116 |
|
96 | | -TEST_F(LlvmLibcMBLenTest, NullString) { |
| 117 | +TEST_F(LlvmLibcMBRLenTest, NullString) { |
97 | 118 | // reading on nullptr should return 0 |
98 | | - int n = LIBC_NAMESPACE::mblen(nullptr, 2); |
99 | | - ASSERT_EQ(n, 0); |
| 119 | + size_t n = LIBC_NAMESPACE::mbrlen(nullptr, 2, nullptr); |
| 120 | + ASSERT_EQ(static_cast<int>(n), 0); |
100 | 121 | ASSERT_ERRNO_SUCCESS(); |
101 | 122 | // reading a null terminator should return 0 |
102 | 123 | const char *ch = "\0"; |
103 | | - n = LIBC_NAMESPACE::mblen(ch, 1); |
104 | | - ASSERT_EQ(n, 0); |
| 124 | + n = LIBC_NAMESPACE::mbrlen(ch, 1, nullptr); |
| 125 | + ASSERT_EQ(static_cast<int>(n), 0); |
| 126 | +} |
| 127 | + |
| 128 | +TEST_F(LlvmLibcMBRLenTest, InvalidMBState) { |
| 129 | + const char ch[4] = {static_cast<char>(0xC2), static_cast<char>(0x8E), |
| 130 | + static_cast<char>(0xC7), static_cast<char>(0x8C)}; |
| 131 | + mbstate_t *mb; |
| 132 | + LIBC_NAMESPACE::internal::mbstate inv; |
| 133 | + inv.total_bytes = 6; |
| 134 | + mb = reinterpret_cast<mbstate_t *>(&inv); |
| 135 | + // invalid mbstate should error |
| 136 | + size_t n = LIBC_NAMESPACE::mbrlen(ch, 2, mb); |
| 137 | + ASSERT_EQ(static_cast<int>(n), -1); |
| 138 | + ASSERT_ERRNO_EQ(EINVAL); |
105 | 139 | } |
0 commit comments