xref: /aosp_15_r20/bionic/tests/uchar_test.cpp (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker  * Copyright (C) 2014 The Android Open Source Project
3*8d67ca89SAndroid Build Coastguard Worker  *
4*8d67ca89SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*8d67ca89SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*8d67ca89SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*8d67ca89SAndroid Build Coastguard Worker  *
8*8d67ca89SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*8d67ca89SAndroid Build Coastguard Worker  *
10*8d67ca89SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*8d67ca89SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*8d67ca89SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8d67ca89SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*8d67ca89SAndroid Build Coastguard Worker  * limitations under the License.
15*8d67ca89SAndroid Build Coastguard Worker  */
16*8d67ca89SAndroid Build Coastguard Worker 
17*8d67ca89SAndroid Build Coastguard Worker 
18*8d67ca89SAndroid Build Coastguard Worker #include <uchar.h>
19*8d67ca89SAndroid Build Coastguard Worker 
20*8d67ca89SAndroid Build Coastguard Worker #include <gtest/gtest.h>
21*8d67ca89SAndroid Build Coastguard Worker 
22*8d67ca89SAndroid Build Coastguard Worker #include <errno.h>
23*8d67ca89SAndroid Build Coastguard Worker #include <limits.h>
24*8d67ca89SAndroid Build Coastguard Worker #include <locale.h>
25*8d67ca89SAndroid Build Coastguard Worker #include <stdint.h>
26*8d67ca89SAndroid Build Coastguard Worker 
27*8d67ca89SAndroid Build Coastguard Worker #include "utils.h"
28*8d67ca89SAndroid Build Coastguard Worker 
29*8d67ca89SAndroid Build Coastguard Worker // Modern versions of UTF-8 (https://datatracker.ietf.org/doc/html/rfc3629 and
30*8d67ca89SAndroid Build Coastguard Worker // newer) explicitly disallow code points beyond U+10FFFF, which exclude all 5-
31*8d67ca89SAndroid Build Coastguard Worker // and 6-byte sequences. Earlier versions of UTF-8 allowed the wider range:
32*8d67ca89SAndroid Build Coastguard Worker // https://datatracker.ietf.org/doc/html/rfc2279.
33*8d67ca89SAndroid Build Coastguard Worker //
34*8d67ca89SAndroid Build Coastguard Worker // Bionic's unicode implementation was written after the high values were
35*8d67ca89SAndroid Build Coastguard Worker // excluded, so it has never supported them. Other implementations (at least
36*8d67ca89SAndroid Build Coastguard Worker // as of glibc 2.36), do support those sequences.
37*8d67ca89SAndroid Build Coastguard Worker #if defined(__ANDROID__) || defined(ANDROID_HOST_MUSL)
38*8d67ca89SAndroid Build Coastguard Worker constexpr bool kLibcRejectsOverLongUtf8Sequences = true;
39*8d67ca89SAndroid Build Coastguard Worker #elif defined(__GLIBC__)
40*8d67ca89SAndroid Build Coastguard Worker constexpr bool kLibcRejectsOverLongUtf8Sequences = false;
41*8d67ca89SAndroid Build Coastguard Worker #else
42*8d67ca89SAndroid Build Coastguard Worker #error kLibcRejectsOverLongUtf8Sequences must be configured for this platform
43*8d67ca89SAndroid Build Coastguard Worker #endif
44*8d67ca89SAndroid Build Coastguard Worker 
TEST(uchar,sizeof_uchar_t)45*8d67ca89SAndroid Build Coastguard Worker TEST(uchar, sizeof_uchar_t) {
46*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(2U, sizeof(char16_t));
47*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(4U, sizeof(char32_t));
48*8d67ca89SAndroid Build Coastguard Worker }
49*8d67ca89SAndroid Build Coastguard Worker 
TEST(uchar,start_state)50*8d67ca89SAndroid Build Coastguard Worker TEST(uchar, start_state) {
51*8d67ca89SAndroid Build Coastguard Worker   // C23 does not appear to specify the behavior of the conversion functions if
52*8d67ca89SAndroid Build Coastguard Worker   // a state is reused before the character is completed. In the wchar.h section
53*8d67ca89SAndroid Build Coastguard Worker   // (7.31.6.3) it says:
54*8d67ca89SAndroid Build Coastguard Worker   //
55*8d67ca89SAndroid Build Coastguard Worker   //     If an mbstate_t object has been altered by any of the functions
56*8d67ca89SAndroid Build Coastguard Worker   //     described in this subclause, and is then used with a different
57*8d67ca89SAndroid Build Coastguard Worker   //     multibyte character sequence, or in the other conversion direction, or
58*8d67ca89SAndroid Build Coastguard Worker   //     with a different LC_CTYPE category setting than on earlier function
59*8d67ca89SAndroid Build Coastguard Worker   //     calls, the behavior is undefined.
60*8d67ca89SAndroid Build Coastguard Worker   //
61*8d67ca89SAndroid Build Coastguard Worker   // But "described in this subclause" refers to the wchar.h functions, not the
62*8d67ca89SAndroid Build Coastguard Worker   // uchar.h ones.
63*8d67ca89SAndroid Build Coastguard Worker   //
64*8d67ca89SAndroid Build Coastguard Worker   // Since C has no opinion, we need to make a choice. While no caller should
65*8d67ca89SAndroid Build Coastguard Worker   // ever do this (what does it mean to begin decoding a UTF-32 character while
66*8d67ca89SAndroid Build Coastguard Worker   // still in the middle of a UTF-8 sequence?), considering that a decoding
67*8d67ca89SAndroid Build Coastguard Worker   // error seems the least surprising. Bionic and glibc both have that behavior.
68*8d67ca89SAndroid Build Coastguard Worker   // musl ignores the state (it also doesn't make much sense to read the state
69*8d67ca89SAndroid Build Coastguard Worker   // when the entire conversion completes in a single call) and decodes the
70*8d67ca89SAndroid Build Coastguard Worker   // UTF-32 character.
71*8d67ca89SAndroid Build Coastguard Worker #if !defined(ANDROID_HOST_MUSL)
72*8d67ca89SAndroid Build Coastguard Worker   ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
73*8d67ca89SAndroid Build Coastguard Worker   uselocale(LC_GLOBAL_LOCALE);
74*8d67ca89SAndroid Build Coastguard Worker 
75*8d67ca89SAndroid Build Coastguard Worker   char out[MB_LEN_MAX];
76*8d67ca89SAndroid Build Coastguard Worker   mbstate_t ps;
77*8d67ca89SAndroid Build Coastguard Worker 
78*8d67ca89SAndroid Build Coastguard Worker   memset(&ps, 0, sizeof(ps));
79*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<size_t>(-2), mbrtoc32(nullptr, "\xc2", 1, &ps));
80*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
81*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<size_t>(-1), c32rtomb(out, 0x00a2, &ps));
82*8d67ca89SAndroid Build Coastguard Worker   EXPECT_ERRNO(EILSEQ);
83*8d67ca89SAndroid Build Coastguard Worker 
84*8d67ca89SAndroid Build Coastguard Worker   // Similarly (but not in compliance with the standard afaict), musl seems to
85*8d67ca89SAndroid Build Coastguard Worker   // ignore the state entirely for the UTF-32 functions rather than reset it.
86*8d67ca89SAndroid Build Coastguard Worker 
87*8d67ca89SAndroid Build Coastguard Worker   // If the first argument to c32rtomb is nullptr or the second is L'\0' the shift
88*8d67ca89SAndroid Build Coastguard Worker   // state should be reset.
89*8d67ca89SAndroid Build Coastguard Worker   memset(&ps, 0, sizeof(ps));
90*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<size_t>(-2), mbrtoc32(nullptr, "\xc2", 1, &ps));
91*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(1U, c32rtomb(nullptr, 0x00a2, &ps));
92*8d67ca89SAndroid Build Coastguard Worker   EXPECT_TRUE(mbsinit(&ps));
93*8d67ca89SAndroid Build Coastguard Worker 
94*8d67ca89SAndroid Build Coastguard Worker   memset(&ps, 0, sizeof(ps));
95*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<size_t>(-2), mbrtoc32(nullptr, "\xf0\xa4", 1, &ps));
96*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(1U, c32rtomb(out, L'\0', &ps));
97*8d67ca89SAndroid Build Coastguard Worker   EXPECT_TRUE(mbsinit(&ps));
98*8d67ca89SAndroid Build Coastguard Worker #endif
99*8d67ca89SAndroid Build Coastguard Worker }
100*8d67ca89SAndroid Build Coastguard Worker 
TEST(uchar,c16rtomb_null_out)101*8d67ca89SAndroid Build Coastguard Worker TEST(uchar, c16rtomb_null_out) {
102*8d67ca89SAndroid Build Coastguard Worker   ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
103*8d67ca89SAndroid Build Coastguard Worker   uselocale(LC_GLOBAL_LOCALE);
104*8d67ca89SAndroid Build Coastguard Worker 
105*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(1U, c16rtomb(nullptr, L'\0', nullptr));
106*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(1U, c16rtomb(nullptr, L'h', nullptr));
107*8d67ca89SAndroid Build Coastguard Worker }
108*8d67ca89SAndroid Build Coastguard Worker 
TEST(uchar,c16rtomb_null_char)109*8d67ca89SAndroid Build Coastguard Worker TEST(uchar, c16rtomb_null_char) {
110*8d67ca89SAndroid Build Coastguard Worker   ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
111*8d67ca89SAndroid Build Coastguard Worker   uselocale(LC_GLOBAL_LOCALE);
112*8d67ca89SAndroid Build Coastguard Worker 
113*8d67ca89SAndroid Build Coastguard Worker   char bytes[MB_LEN_MAX];
114*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(1U, c16rtomb(bytes, L'\0', nullptr));
115*8d67ca89SAndroid Build Coastguard Worker }
116*8d67ca89SAndroid Build Coastguard Worker 
TEST(uchar,c16rtomb)117*8d67ca89SAndroid Build Coastguard Worker TEST(uchar, c16rtomb) {
118*8d67ca89SAndroid Build Coastguard Worker   char bytes[MB_LEN_MAX];
119*8d67ca89SAndroid Build Coastguard Worker 
120*8d67ca89SAndroid Build Coastguard Worker   memset(bytes, 0, sizeof(bytes));
121*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(1U, c16rtomb(bytes, L'h', nullptr));
122*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('h', bytes[0]);
123*8d67ca89SAndroid Build Coastguard Worker 
124*8d67ca89SAndroid Build Coastguard Worker   ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
125*8d67ca89SAndroid Build Coastguard Worker   uselocale(LC_GLOBAL_LOCALE);
126*8d67ca89SAndroid Build Coastguard Worker 
127*8d67ca89SAndroid Build Coastguard Worker   // 1-byte UTF-8.
128*8d67ca89SAndroid Build Coastguard Worker   memset(bytes, 0, sizeof(bytes));
129*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(1U, c16rtomb(bytes, L'h', nullptr));
130*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('h', bytes[0]);
131*8d67ca89SAndroid Build Coastguard Worker   // 2-byte UTF-8.
132*8d67ca89SAndroid Build Coastguard Worker   memset(bytes, 0, sizeof(bytes));
133*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(2U, c16rtomb(bytes, 0x00a2, nullptr));
134*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('\xc2', bytes[0]);
135*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('\xa2', bytes[1]);
136*8d67ca89SAndroid Build Coastguard Worker   // 3-byte UTF-8.
137*8d67ca89SAndroid Build Coastguard Worker   memset(bytes, 0, sizeof(bytes));
138*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(3U, c16rtomb(bytes, 0x20ac, nullptr));
139*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('\xe2', bytes[0]);
140*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('\x82', bytes[1]);
141*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('\xac', bytes[2]);
142*8d67ca89SAndroid Build Coastguard Worker   // 4-byte UTF-8 from a surrogate pair...
143*8d67ca89SAndroid Build Coastguard Worker   memset(bytes, 0, sizeof(bytes));
144*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(0U, c16rtomb(bytes, 0xdbea, nullptr));
145*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(4U, c16rtomb(bytes, 0xdfcd, nullptr));
146*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('\xf4', bytes[0]);
147*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('\x8a', bytes[1]);
148*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('\xaf', bytes[2]);
149*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('\x8d', bytes[3]);
150*8d67ca89SAndroid Build Coastguard Worker }
151*8d67ca89SAndroid Build Coastguard Worker 
TEST(uchar,c16rtomb_invalid)152*8d67ca89SAndroid Build Coastguard Worker TEST(uchar, c16rtomb_invalid) {
153*8d67ca89SAndroid Build Coastguard Worker   ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
154*8d67ca89SAndroid Build Coastguard Worker   uselocale(LC_GLOBAL_LOCALE);
155*8d67ca89SAndroid Build Coastguard Worker 
156*8d67ca89SAndroid Build Coastguard Worker   char bytes[MB_LEN_MAX];
157*8d67ca89SAndroid Build Coastguard Worker 
158*8d67ca89SAndroid Build Coastguard Worker   memset(bytes, 0, sizeof(bytes));
159*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<size_t>(-1), c16rtomb(bytes, 0xdfcd, nullptr));
160*8d67ca89SAndroid Build Coastguard Worker 
161*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(0U, c16rtomb(bytes, 0xdbea, nullptr));
162*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<size_t>(-1), c16rtomb(bytes, 0xdbea, nullptr));
163*8d67ca89SAndroid Build Coastguard Worker }
164*8d67ca89SAndroid Build Coastguard Worker 
TEST(uchar,mbrtoc16_null)165*8d67ca89SAndroid Build Coastguard Worker TEST(uchar, mbrtoc16_null) {
166*8d67ca89SAndroid Build Coastguard Worker   ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
167*8d67ca89SAndroid Build Coastguard Worker   uselocale(LC_GLOBAL_LOCALE);
168*8d67ca89SAndroid Build Coastguard Worker 
169*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0U, mbrtoc16(nullptr, nullptr, 0, nullptr));
170*8d67ca89SAndroid Build Coastguard Worker }
171*8d67ca89SAndroid Build Coastguard Worker 
TEST(uchar,mbrtoc16_zero_len)172*8d67ca89SAndroid Build Coastguard Worker TEST(uchar, mbrtoc16_zero_len) {
173*8d67ca89SAndroid Build Coastguard Worker   ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
174*8d67ca89SAndroid Build Coastguard Worker   uselocale(LC_GLOBAL_LOCALE);
175*8d67ca89SAndroid Build Coastguard Worker 
176*8d67ca89SAndroid Build Coastguard Worker   char16_t out;
177*8d67ca89SAndroid Build Coastguard Worker 
178*8d67ca89SAndroid Build Coastguard Worker   out = L'x';
179*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<size_t>(-2), mbrtoc16(&out, "hello", 0, nullptr));
180*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(L'x', out);
181*8d67ca89SAndroid Build Coastguard Worker 
182*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<size_t>(-2), mbrtoc16(&out, "hello", 0, nullptr));
183*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<size_t>(-2), mbrtoc16(&out, "", 0, nullptr));
184*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(1U, mbrtoc16(&out, "hello", 1, nullptr));
185*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(L'h', out);
186*8d67ca89SAndroid Build Coastguard Worker }
187*8d67ca89SAndroid Build Coastguard Worker 
TEST(uchar,mbrtoc16)188*8d67ca89SAndroid Build Coastguard Worker TEST(uchar, mbrtoc16) {
189*8d67ca89SAndroid Build Coastguard Worker   char16_t out;
190*8d67ca89SAndroid Build Coastguard Worker 
191*8d67ca89SAndroid Build Coastguard Worker   ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
192*8d67ca89SAndroid Build Coastguard Worker   uselocale(LC_GLOBAL_LOCALE);
193*8d67ca89SAndroid Build Coastguard Worker 
194*8d67ca89SAndroid Build Coastguard Worker   // 1-byte UTF-8.
195*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(1U, mbrtoc16(&out, "abcdef", 6, nullptr));
196*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(L'a', out);
197*8d67ca89SAndroid Build Coastguard Worker   // 2-byte UTF-8.
198*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(2U, mbrtoc16(&out, "\xc2\xa2" "cdef", 6, nullptr));
199*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<char16_t>(0x00a2), out);
200*8d67ca89SAndroid Build Coastguard Worker   // 3-byte UTF-8.
201*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(3U, mbrtoc16(&out, "\xe2\x82\xac" "def", 6, nullptr));
202*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<char16_t>(0x20ac), out);
203*8d67ca89SAndroid Build Coastguard Worker   // 4-byte UTF-8 will be returned as a surrogate pair...
204*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(4U, mbrtoc16(&out, "\xf4\x8a\xaf\x8d", 6, nullptr));
205*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<char16_t>(0xdbea), out);
206*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(-3), mbrtoc16(&out,
207*8d67ca89SAndroid Build Coastguard Worker                                               "\xf4\x8a\xaf\x8d"
208*8d67ca89SAndroid Build Coastguard Worker                                               "ef",
209*8d67ca89SAndroid Build Coastguard Worker                                               6, nullptr));
210*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<char16_t>(0xdfcd), out);
211*8d67ca89SAndroid Build Coastguard Worker }
212*8d67ca89SAndroid Build Coastguard Worker 
TEST(uchar,mbrtoc16_long_sequences)213*8d67ca89SAndroid Build Coastguard Worker TEST(uchar, mbrtoc16_long_sequences) {
214*8d67ca89SAndroid Build Coastguard Worker   ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
215*8d67ca89SAndroid Build Coastguard Worker   uselocale(LC_GLOBAL_LOCALE);
216*8d67ca89SAndroid Build Coastguard Worker 
217*8d67ca89SAndroid Build Coastguard Worker   char16_t out = u'\0';
218*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
219*8d67ca89SAndroid Build Coastguard Worker   auto result = mbrtoc16(&out, "\xf8\xa1\xa2\xa3\xa4", 5, nullptr);
220*8d67ca89SAndroid Build Coastguard Worker   if (kLibcRejectsOverLongUtf8Sequences) {
221*8d67ca89SAndroid Build Coastguard Worker     EXPECT_EQ(static_cast<size_t>(-1), result);
222*8d67ca89SAndroid Build Coastguard Worker     EXPECT_ERRNO(EILSEQ);
223*8d67ca89SAndroid Build Coastguard Worker     EXPECT_EQ(u'\0', out);
224*8d67ca89SAndroid Build Coastguard Worker   } else {
225*8d67ca89SAndroid Build Coastguard Worker     EXPECT_EQ(5U, result);
226*8d67ca89SAndroid Build Coastguard Worker     EXPECT_ERRNO(0);
227*8d67ca89SAndroid Build Coastguard Worker     EXPECT_EQ(u'\uf94a', out);
228*8d67ca89SAndroid Build Coastguard Worker   }
229*8d67ca89SAndroid Build Coastguard Worker }
230*8d67ca89SAndroid Build Coastguard Worker 
TEST(uchar,mbrtoc16_reserved_range)231*8d67ca89SAndroid Build Coastguard Worker TEST(uchar, mbrtoc16_reserved_range) {
232*8d67ca89SAndroid Build Coastguard Worker   ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
233*8d67ca89SAndroid Build Coastguard Worker   uselocale(LC_GLOBAL_LOCALE);
234*8d67ca89SAndroid Build Coastguard Worker 
235*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
236*8d67ca89SAndroid Build Coastguard Worker   char16_t out = u'\0';
237*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<size_t>(-1), mbrtoc16(&out, "\xf0\x80\xbf\xbf", 6, nullptr));
238*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(u'\0', out);
239*8d67ca89SAndroid Build Coastguard Worker   EXPECT_ERRNO(EILSEQ);
240*8d67ca89SAndroid Build Coastguard Worker }
241*8d67ca89SAndroid Build Coastguard Worker 
TEST(uchar,mbrtoc16_beyond_range)242*8d67ca89SAndroid Build Coastguard Worker TEST(uchar, mbrtoc16_beyond_range) {
243*8d67ca89SAndroid Build Coastguard Worker   ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
244*8d67ca89SAndroid Build Coastguard Worker   uselocale(LC_GLOBAL_LOCALE);
245*8d67ca89SAndroid Build Coastguard Worker 
246*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
247*8d67ca89SAndroid Build Coastguard Worker   char16_t out = u'\0';
248*8d67ca89SAndroid Build Coastguard Worker   auto result = mbrtoc16(&out, "\xf5\x80\x80\x80", 6, nullptr);
249*8d67ca89SAndroid Build Coastguard Worker   if (kLibcRejectsOverLongUtf8Sequences) {
250*8d67ca89SAndroid Build Coastguard Worker     EXPECT_EQ(static_cast<size_t>(-1), result);
251*8d67ca89SAndroid Build Coastguard Worker     EXPECT_EQ(u'\0', out);
252*8d67ca89SAndroid Build Coastguard Worker     EXPECT_ERRNO(EILSEQ);
253*8d67ca89SAndroid Build Coastguard Worker   } else {
254*8d67ca89SAndroid Build Coastguard Worker     EXPECT_EQ(4U, result);
255*8d67ca89SAndroid Build Coastguard Worker     EXPECT_EQ(u'\xdcc0', out);
256*8d67ca89SAndroid Build Coastguard Worker     EXPECT_ERRNO(0);
257*8d67ca89SAndroid Build Coastguard Worker   }
258*8d67ca89SAndroid Build Coastguard Worker }
259*8d67ca89SAndroid Build Coastguard Worker 
test_mbrtoc16_incomplete(mbstate_t * ps)260*8d67ca89SAndroid Build Coastguard Worker void test_mbrtoc16_incomplete(mbstate_t* ps) {
261*8d67ca89SAndroid Build Coastguard Worker   ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
262*8d67ca89SAndroid Build Coastguard Worker   uselocale(LC_GLOBAL_LOCALE);
263*8d67ca89SAndroid Build Coastguard Worker 
264*8d67ca89SAndroid Build Coastguard Worker   char16_t out;
265*8d67ca89SAndroid Build Coastguard Worker   // 2-byte UTF-8.
266*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(-2), mbrtoc16(&out, "\xc2", 1, ps));
267*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(1U, mbrtoc16(&out, "\xa2" "cdef", 5, ps));
268*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<char16_t>(0x00a2), out);
269*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(mbsinit(ps));
270*8d67ca89SAndroid Build Coastguard Worker   // 3-byte UTF-8.
271*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(-2), mbrtoc16(&out, "\xe2", 1, ps));
272*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(-2), mbrtoc16(&out, "\x82", 1, ps));
273*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(1U, mbrtoc16(&out, "\xac" "def", 4, ps));
274*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<char16_t>(0x20ac), out);
275*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(mbsinit(ps));
276*8d67ca89SAndroid Build Coastguard Worker   // 4-byte UTF-8.
277*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(-2), mbrtoc16(&out, "\xf4", 1, ps));
278*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(-2), mbrtoc16(&out, "\x8a\xaf", 2, ps));
279*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(1U, mbrtoc16(&out,
280*8d67ca89SAndroid Build Coastguard Worker                          "\x8d"
281*8d67ca89SAndroid Build Coastguard Worker                          "ef",
282*8d67ca89SAndroid Build Coastguard Worker                          3, ps));
283*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<char16_t>(0xdbea), out);
284*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(-3), mbrtoc16(&out,
285*8d67ca89SAndroid Build Coastguard Worker                                               "\x80"
286*8d67ca89SAndroid Build Coastguard Worker                                               "ef",
287*8d67ca89SAndroid Build Coastguard Worker                                               3, ps));
288*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<char16_t>(0xdfcd), out);
289*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(mbsinit(ps));
290*8d67ca89SAndroid Build Coastguard Worker 
291*8d67ca89SAndroid Build Coastguard Worker   // Invalid 2-byte
292*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(-2), mbrtoc16(&out, "\xc2", 1, ps));
293*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
294*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(-1), mbrtoc16(&out, "\x20" "cdef", 5, ps));
295*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(EILSEQ);
296*8d67ca89SAndroid Build Coastguard Worker }
297*8d67ca89SAndroid Build Coastguard Worker 
TEST(uchar,mbrtoc16_incomplete)298*8d67ca89SAndroid Build Coastguard Worker TEST(uchar, mbrtoc16_incomplete) {
299*8d67ca89SAndroid Build Coastguard Worker   ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
300*8d67ca89SAndroid Build Coastguard Worker   uselocale(LC_GLOBAL_LOCALE);
301*8d67ca89SAndroid Build Coastguard Worker 
302*8d67ca89SAndroid Build Coastguard Worker   mbstate_t ps;
303*8d67ca89SAndroid Build Coastguard Worker   memset(&ps, 0, sizeof(ps));
304*8d67ca89SAndroid Build Coastguard Worker 
305*8d67ca89SAndroid Build Coastguard Worker   test_mbrtoc16_incomplete(&ps);
306*8d67ca89SAndroid Build Coastguard Worker   test_mbrtoc16_incomplete(nullptr);
307*8d67ca89SAndroid Build Coastguard Worker }
308*8d67ca89SAndroid Build Coastguard Worker 
TEST(uchar,c32rtomb)309*8d67ca89SAndroid Build Coastguard Worker TEST(uchar, c32rtomb) {
310*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(1U, c32rtomb(nullptr, L'\0', nullptr));
311*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(1U, c32rtomb(nullptr, L'h', nullptr));
312*8d67ca89SAndroid Build Coastguard Worker 
313*8d67ca89SAndroid Build Coastguard Worker   char bytes[MB_LEN_MAX];
314*8d67ca89SAndroid Build Coastguard Worker 
315*8d67ca89SAndroid Build Coastguard Worker   memset(bytes, 1, sizeof(bytes));
316*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(1U, c32rtomb(bytes, L'\0', nullptr));
317*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('\0', bytes[0]);
318*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('\x01', bytes[1]);
319*8d67ca89SAndroid Build Coastguard Worker 
320*8d67ca89SAndroid Build Coastguard Worker   memset(bytes, 0, sizeof(bytes));
321*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(1U, c32rtomb(bytes, L'h', nullptr));
322*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('h', bytes[0]);
323*8d67ca89SAndroid Build Coastguard Worker 
324*8d67ca89SAndroid Build Coastguard Worker   ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
325*8d67ca89SAndroid Build Coastguard Worker   uselocale(LC_GLOBAL_LOCALE);
326*8d67ca89SAndroid Build Coastguard Worker 
327*8d67ca89SAndroid Build Coastguard Worker   // 1-byte UTF-8.
328*8d67ca89SAndroid Build Coastguard Worker   memset(bytes, 0, sizeof(bytes));
329*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(1U, c32rtomb(bytes, L'h', nullptr));
330*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('h', bytes[0]);
331*8d67ca89SAndroid Build Coastguard Worker   // 2-byte UTF-8.
332*8d67ca89SAndroid Build Coastguard Worker   memset(bytes, 0, sizeof(bytes));
333*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(2U, c32rtomb(bytes, 0x00a2, nullptr));
334*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('\xc2', bytes[0]);
335*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('\xa2', bytes[1]);
336*8d67ca89SAndroid Build Coastguard Worker   // 3-byte UTF-8.
337*8d67ca89SAndroid Build Coastguard Worker   memset(bytes, 0, sizeof(bytes));
338*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(3U, c32rtomb(bytes, 0x20ac, nullptr));
339*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('\xe2', bytes[0]);
340*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('\x82', bytes[1]);
341*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('\xac', bytes[2]);
342*8d67ca89SAndroid Build Coastguard Worker   // 4-byte UTF-8.
343*8d67ca89SAndroid Build Coastguard Worker   memset(bytes, 0, sizeof(bytes));
344*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(4U, c32rtomb(bytes, 0x24b62, nullptr));
345*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('\xf0', bytes[0]);
346*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('\xa4', bytes[1]);
347*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('\xad', bytes[2]);
348*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ('\xa2', bytes[3]);
349*8d67ca89SAndroid Build Coastguard Worker   // Invalid code point.
350*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
351*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<size_t>(-1), c32rtomb(bytes, 0xffffffff, nullptr));
352*8d67ca89SAndroid Build Coastguard Worker   EXPECT_ERRNO(EILSEQ);
353*8d67ca89SAndroid Build Coastguard Worker }
354*8d67ca89SAndroid Build Coastguard Worker 
TEST(uchar,mbrtoc32_valid_non_characters)355*8d67ca89SAndroid Build Coastguard Worker TEST(uchar, mbrtoc32_valid_non_characters) {
356*8d67ca89SAndroid Build Coastguard Worker   ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
357*8d67ca89SAndroid Build Coastguard Worker   uselocale(LC_GLOBAL_LOCALE);
358*8d67ca89SAndroid Build Coastguard Worker 
359*8d67ca89SAndroid Build Coastguard Worker   char32_t out[8] = {};
360*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(3U, mbrtoc32(out, "\xef\xbf\xbe", 3, nullptr));
361*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0xfffeU, out[0]);
362*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(3U, mbrtoc32(out, "\xef\xbf\xbf", 3, nullptr));
363*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0xffffU, out[0]);
364*8d67ca89SAndroid Build Coastguard Worker }
365*8d67ca89SAndroid Build Coastguard Worker 
TEST(uchar,mbrtoc32_out_of_range)366*8d67ca89SAndroid Build Coastguard Worker TEST(uchar, mbrtoc32_out_of_range) {
367*8d67ca89SAndroid Build Coastguard Worker   ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
368*8d67ca89SAndroid Build Coastguard Worker   uselocale(LC_GLOBAL_LOCALE);
369*8d67ca89SAndroid Build Coastguard Worker 
370*8d67ca89SAndroid Build Coastguard Worker   char32_t out = U'\0';
371*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
372*8d67ca89SAndroid Build Coastguard Worker   auto result = mbrtoc32(&out, "\xf5\x80\x80\x80", 4, nullptr);
373*8d67ca89SAndroid Build Coastguard Worker   if (kLibcRejectsOverLongUtf8Sequences) {
374*8d67ca89SAndroid Build Coastguard Worker     EXPECT_EQ(static_cast<size_t>(-1), result);
375*8d67ca89SAndroid Build Coastguard Worker     EXPECT_ERRNO(EILSEQ);
376*8d67ca89SAndroid Build Coastguard Worker     EXPECT_EQ(U'\0', out);
377*8d67ca89SAndroid Build Coastguard Worker   } else {
378*8d67ca89SAndroid Build Coastguard Worker     EXPECT_EQ(4U, result);
379*8d67ca89SAndroid Build Coastguard Worker     EXPECT_ERRNO(0);
380*8d67ca89SAndroid Build Coastguard Worker     EXPECT_EQ(U'\x140000', out);
381*8d67ca89SAndroid Build Coastguard Worker   }
382*8d67ca89SAndroid Build Coastguard Worker }
383*8d67ca89SAndroid Build Coastguard Worker 
TEST(uchar,mbrtoc32)384*8d67ca89SAndroid Build Coastguard Worker TEST(uchar, mbrtoc32) {
385*8d67ca89SAndroid Build Coastguard Worker   char32_t out[8];
386*8d67ca89SAndroid Build Coastguard Worker 
387*8d67ca89SAndroid Build Coastguard Worker   out[0] = L'x';
388*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<size_t>(-2), mbrtoc32(out, "hello", 0, nullptr));
389*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<char32_t>(L'x'), out[0]);
390*8d67ca89SAndroid Build Coastguard Worker 
391*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<size_t>(-2), mbrtoc32(out, "hello", 0, nullptr));
392*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<size_t>(-2), mbrtoc32(out, "", 0, nullptr));
393*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(1U, mbrtoc32(out, "hello", 1, nullptr));
394*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<char32_t>(L'h'), out[0]);
395*8d67ca89SAndroid Build Coastguard Worker 
396*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<size_t>(-2), mbrtoc32(nullptr, "hello", 0, nullptr));
397*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<size_t>(-2), mbrtoc32(nullptr, "", 0, nullptr));
398*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(1U, mbrtoc32(nullptr, "hello", 1, nullptr));
399*8d67ca89SAndroid Build Coastguard Worker 
400*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(0U, mbrtoc32(nullptr, nullptr, 0, nullptr));
401*8d67ca89SAndroid Build Coastguard Worker 
402*8d67ca89SAndroid Build Coastguard Worker   ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
403*8d67ca89SAndroid Build Coastguard Worker   uselocale(LC_GLOBAL_LOCALE);
404*8d67ca89SAndroid Build Coastguard Worker 
405*8d67ca89SAndroid Build Coastguard Worker   // 1-byte UTF-8.
406*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(1U, mbrtoc32(out, "abcdef", 6, nullptr));
407*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<char32_t>(L'a'), out[0]);
408*8d67ca89SAndroid Build Coastguard Worker   // 2-byte UTF-8.
409*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(2U, mbrtoc32(out,
410*8d67ca89SAndroid Build Coastguard Worker                          "\xc2\xa2"
411*8d67ca89SAndroid Build Coastguard Worker                          "cdef",
412*8d67ca89SAndroid Build Coastguard Worker                          6, nullptr));
413*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<char32_t>(0x00a2), out[0]);
414*8d67ca89SAndroid Build Coastguard Worker   // 3-byte UTF-8.
415*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(3U, mbrtoc32(out,
416*8d67ca89SAndroid Build Coastguard Worker                          "\xe2\x82\xac"
417*8d67ca89SAndroid Build Coastguard Worker                          "def",
418*8d67ca89SAndroid Build Coastguard Worker                          6, nullptr));
419*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<char32_t>(0x20ac), out[0]);
420*8d67ca89SAndroid Build Coastguard Worker   // 4-byte UTF-8.
421*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(4U, mbrtoc32(out,
422*8d67ca89SAndroid Build Coastguard Worker                          "\xf0\xa4\xad\xa2"
423*8d67ca89SAndroid Build Coastguard Worker                          "ef",
424*8d67ca89SAndroid Build Coastguard Worker                          6, nullptr));
425*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<char32_t>(0x24b62), out[0]);
426*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__) // glibc allows this.
427*8d67ca89SAndroid Build Coastguard Worker   // Illegal 5-byte UTF-8.
428*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
429*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<size_t>(-1), mbrtoc32(out,
430*8d67ca89SAndroid Build Coastguard Worker                                               "\xf8\xa1\xa2\xa3\xa4"
431*8d67ca89SAndroid Build Coastguard Worker                                               "f",
432*8d67ca89SAndroid Build Coastguard Worker                                               6, nullptr));
433*8d67ca89SAndroid Build Coastguard Worker   EXPECT_ERRNO(EILSEQ);
434*8d67ca89SAndroid Build Coastguard Worker #endif
435*8d67ca89SAndroid Build Coastguard Worker   // Illegal over-long sequence.
436*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
437*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(static_cast<size_t>(-1), mbrtoc32(out,
438*8d67ca89SAndroid Build Coastguard Worker                                               "\xf0\x82\x82\xac"
439*8d67ca89SAndroid Build Coastguard Worker                                               "ef",
440*8d67ca89SAndroid Build Coastguard Worker                                               6, nullptr));
441*8d67ca89SAndroid Build Coastguard Worker   EXPECT_ERRNO(EILSEQ);
442*8d67ca89SAndroid Build Coastguard Worker }
443*8d67ca89SAndroid Build Coastguard Worker 
test_mbrtoc32_incomplete(mbstate_t * ps)444*8d67ca89SAndroid Build Coastguard Worker void test_mbrtoc32_incomplete(mbstate_t* ps) {
445*8d67ca89SAndroid Build Coastguard Worker   ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
446*8d67ca89SAndroid Build Coastguard Worker   uselocale(LC_GLOBAL_LOCALE);
447*8d67ca89SAndroid Build Coastguard Worker 
448*8d67ca89SAndroid Build Coastguard Worker   char32_t out;
449*8d67ca89SAndroid Build Coastguard Worker   // 2-byte UTF-8.
450*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(-2), mbrtoc32(&out, "\xc2", 1, ps));
451*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(1U, mbrtoc32(&out, "\xa2" "cdef", 5, ps));
452*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<char32_t>(0x00a2), out);
453*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(mbsinit(ps));
454*8d67ca89SAndroid Build Coastguard Worker   // 3-byte UTF-8.
455*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(-2), mbrtoc32(&out, "\xe2", 1, ps));
456*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(-2), mbrtoc32(&out, "\x82", 1, ps));
457*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(1U, mbrtoc32(&out, "\xac" "def", 4, ps));
458*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<char32_t>(0x20ac), out);
459*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(mbsinit(ps));
460*8d67ca89SAndroid Build Coastguard Worker   // 4-byte UTF-8.
461*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(-2), mbrtoc32(&out, "\xf0", 1, ps));
462*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(-2), mbrtoc32(&out, "\xa4\xad", 2, ps));
463*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(1U, mbrtoc32(&out, "\xa2" "ef", 3, ps));
464*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<char32_t>(0x24b62), out);
465*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(mbsinit(ps));
466*8d67ca89SAndroid Build Coastguard Worker 
467*8d67ca89SAndroid Build Coastguard Worker   // Invalid 2-byte
468*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(-2), mbrtoc32(&out, "\xc2", 1, ps));
469*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
470*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(static_cast<size_t>(-1), mbrtoc32(&out, "\x20" "cdef", 5, ps));
471*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(EILSEQ);
472*8d67ca89SAndroid Build Coastguard Worker }
473*8d67ca89SAndroid Build Coastguard Worker 
TEST(uchar,mbrtoc32_incomplete)474*8d67ca89SAndroid Build Coastguard Worker TEST(uchar, mbrtoc32_incomplete) {
475*8d67ca89SAndroid Build Coastguard Worker   ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
476*8d67ca89SAndroid Build Coastguard Worker   uselocale(LC_GLOBAL_LOCALE);
477*8d67ca89SAndroid Build Coastguard Worker 
478*8d67ca89SAndroid Build Coastguard Worker   mbstate_t ps;
479*8d67ca89SAndroid Build Coastguard Worker   memset(&ps, 0, sizeof(ps));
480*8d67ca89SAndroid Build Coastguard Worker 
481*8d67ca89SAndroid Build Coastguard Worker   test_mbrtoc32_incomplete(&ps);
482*8d67ca89SAndroid Build Coastguard Worker   test_mbrtoc32_incomplete(nullptr);
483*8d67ca89SAndroid Build Coastguard Worker }
484