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 #include <gtest/gtest.h>
18*8d67ca89SAndroid Build Coastguard Worker
19*8d67ca89SAndroid Build Coastguard Worker #include <errno.h>
20*8d67ca89SAndroid Build Coastguard Worker #include <inttypes.h>
21*8d67ca89SAndroid Build Coastguard Worker #include <limits.h>
22*8d67ca89SAndroid Build Coastguard Worker #include <locale.h>
23*8d67ca89SAndroid Build Coastguard Worker #include <math.h>
24*8d67ca89SAndroid Build Coastguard Worker #include <stdint.h>
25*8d67ca89SAndroid Build Coastguard Worker #include <sys/cdefs.h>
26*8d67ca89SAndroid Build Coastguard Worker #include <wchar.h>
27*8d67ca89SAndroid Build Coastguard Worker
28*8d67ca89SAndroid Build Coastguard Worker #include "utils.h"
29*8d67ca89SAndroid Build Coastguard Worker
30*8d67ca89SAndroid Build Coastguard Worker #define NUM_WCHARS(num_bytes) ((num_bytes)/sizeof(wchar_t))
31*8d67ca89SAndroid Build Coastguard Worker
32*8d67ca89SAndroid Build Coastguard Worker #ifdef __GLIBC__
33*8d67ca89SAndroid Build Coastguard Worker // glibc immediately dereferences the locale passed to all wcsto*_l functions,
34*8d67ca89SAndroid Build Coastguard Worker // even if it won't be used, and even if it's LC_GLOBAL_LOCALE, which isn't a
35*8d67ca89SAndroid Build Coastguard Worker // pointer to valid memory.
36*8d67ca89SAndroid Build Coastguard Worker static locale_t SAFE_LC_GLOBAL_LOCALE = duplocale(LC_GLOBAL_LOCALE);
37*8d67ca89SAndroid Build Coastguard Worker #else
38*8d67ca89SAndroid Build Coastguard Worker static locale_t SAFE_LC_GLOBAL_LOCALE = LC_GLOBAL_LOCALE;
39*8d67ca89SAndroid Build Coastguard Worker #endif
40*8d67ca89SAndroid Build Coastguard Worker
41*8d67ca89SAndroid Build Coastguard Worker // Modern versions of UTF-8 (https://datatracker.ietf.org/doc/html/rfc3629 and
42*8d67ca89SAndroid Build Coastguard Worker // newer) explicitly disallow code points beyond U+10FFFF, which exclude all 5-
43*8d67ca89SAndroid Build Coastguard Worker // and 6-byte sequences. Earlier versions of UTF-8 allowed the wider range:
44*8d67ca89SAndroid Build Coastguard Worker // https://datatracker.ietf.org/doc/html/rfc2279.
45*8d67ca89SAndroid Build Coastguard Worker //
46*8d67ca89SAndroid Build Coastguard Worker // Bionic's unicode implementation was written after the high values were
47*8d67ca89SAndroid Build Coastguard Worker // excluded, so it has never supported them. Other implementations (at least
48*8d67ca89SAndroid Build Coastguard Worker // as of glibc 2.36), do support those sequences.
49*8d67ca89SAndroid Build Coastguard Worker #if defined(__ANDROID__) || defined(ANDROID_HOST_MUSL)
50*8d67ca89SAndroid Build Coastguard Worker constexpr bool kLibcRejectsOverLongUtf8Sequences = true;
51*8d67ca89SAndroid Build Coastguard Worker #elif defined(__GLIBC__)
52*8d67ca89SAndroid Build Coastguard Worker constexpr bool kLibcRejectsOverLongUtf8Sequences = false;
53*8d67ca89SAndroid Build Coastguard Worker #else
54*8d67ca89SAndroid Build Coastguard Worker #error kLibcRejectsOverLongUtf8Sequences must be configured for this platform
55*8d67ca89SAndroid Build Coastguard Worker #endif
56*8d67ca89SAndroid Build Coastguard Worker
57*8d67ca89SAndroid Build Coastguard Worker #if defined(__GLIBC__)
58*8d67ca89SAndroid Build Coastguard Worker constexpr bool kLibcSupportsParsingBinaryLiterals = __GLIBC_PREREQ(2, 38);
59*8d67ca89SAndroid Build Coastguard Worker #else
60*8d67ca89SAndroid Build Coastguard Worker constexpr bool kLibcSupportsParsingBinaryLiterals = true;
61*8d67ca89SAndroid Build Coastguard Worker #endif
62*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,sizeof_wchar_t)63*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, sizeof_wchar_t) {
64*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(4U, sizeof(wchar_t));
65*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(4U, sizeof(wint_t));
66*8d67ca89SAndroid Build Coastguard Worker }
67*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,mbrlen)68*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, mbrlen) {
69*8d67ca89SAndroid Build Coastguard Worker char bytes[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
70*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<size_t>(-2), mbrlen(&bytes[0], 0, nullptr));
71*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(1U, mbrlen(&bytes[0], 1, nullptr));
72*8d67ca89SAndroid Build Coastguard Worker
73*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(1U, mbrlen(&bytes[4], 1, nullptr));
74*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(0U, mbrlen(&bytes[5], 1, nullptr));
75*8d67ca89SAndroid Build Coastguard Worker }
76*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wctomb_wcrtomb)77*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wctomb_wcrtomb) {
78*8d67ca89SAndroid Build Coastguard Worker // wctomb and wcrtomb behave differently when s == NULL.
79*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(0, wctomb(nullptr, L'h'));
80*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(0, wctomb(nullptr, L'\0'));
81*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(1U, wcrtomb(nullptr, L'\0', nullptr));
82*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(1U, wcrtomb(nullptr, L'h', nullptr));
83*8d67ca89SAndroid Build Coastguard Worker
84*8d67ca89SAndroid Build Coastguard Worker char bytes[MB_LEN_MAX];
85*8d67ca89SAndroid Build Coastguard Worker
86*8d67ca89SAndroid Build Coastguard Worker // wctomb and wcrtomb behave similarly for the null wide character.
87*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(1, wctomb(bytes, L'\0'));
88*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(1U, wcrtomb(bytes, L'\0', nullptr));
89*8d67ca89SAndroid Build Coastguard Worker
90*8d67ca89SAndroid Build Coastguard Worker // ...and for regular characters.
91*8d67ca89SAndroid Build Coastguard Worker memset(bytes, 0, sizeof(bytes));
92*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(1, wctomb(bytes, L'h'));
93*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ('h', bytes[0]);
94*8d67ca89SAndroid Build Coastguard Worker memset(bytes, 0, sizeof(bytes));
95*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(1U, wcrtomb(bytes, L'h', nullptr));
96*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ('h', bytes[0]);
97*8d67ca89SAndroid Build Coastguard Worker
98*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
99*8d67ca89SAndroid Build Coastguard Worker uselocale(LC_GLOBAL_LOCALE);
100*8d67ca89SAndroid Build Coastguard Worker
101*8d67ca89SAndroid Build Coastguard Worker // 1-byte UTF-8.
102*8d67ca89SAndroid Build Coastguard Worker memset(bytes, 0, sizeof(bytes));
103*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(1U, wcrtomb(bytes, L'h', nullptr));
104*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ('h', bytes[0]);
105*8d67ca89SAndroid Build Coastguard Worker // 2-byte UTF-8.
106*8d67ca89SAndroid Build Coastguard Worker memset(bytes, 0, sizeof(bytes));
107*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(2U, wcrtomb(bytes, 0x00a2, nullptr));
108*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ('\xc2', bytes[0]);
109*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ('\xa2', bytes[1]);
110*8d67ca89SAndroid Build Coastguard Worker // 3-byte UTF-8.
111*8d67ca89SAndroid Build Coastguard Worker memset(bytes, 0, sizeof(bytes));
112*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(3U, wcrtomb(bytes, 0x20ac, nullptr));
113*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ('\xe2', bytes[0]);
114*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ('\x82', bytes[1]);
115*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ('\xac', bytes[2]);
116*8d67ca89SAndroid Build Coastguard Worker // 4-byte UTF-8.
117*8d67ca89SAndroid Build Coastguard Worker memset(bytes, 0, sizeof(bytes));
118*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(4U, wcrtomb(bytes, 0x24b62, nullptr));
119*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ('\xf0', bytes[0]);
120*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ('\xa4', bytes[1]);
121*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ('\xad', bytes[2]);
122*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ('\xa2', bytes[3]);
123*8d67ca89SAndroid Build Coastguard Worker // Invalid code point.
124*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<size_t>(-1), wcrtomb(bytes, 0xffffffff, nullptr));
125*8d67ca89SAndroid Build Coastguard Worker EXPECT_ERRNO(EILSEQ);
126*8d67ca89SAndroid Build Coastguard Worker }
127*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcrtomb_start_state)128*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcrtomb_start_state) {
129*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
130*8d67ca89SAndroid Build Coastguard Worker uselocale(LC_GLOBAL_LOCALE);
131*8d67ca89SAndroid Build Coastguard Worker
132*8d67ca89SAndroid Build Coastguard Worker char out[MB_LEN_MAX];
133*8d67ca89SAndroid Build Coastguard Worker mbstate_t ps;
134*8d67ca89SAndroid Build Coastguard Worker
135*8d67ca89SAndroid Build Coastguard Worker // Any non-initial state is invalid when calling wcrtomb.
136*8d67ca89SAndroid Build Coastguard Worker memset(&ps, 0, sizeof(ps));
137*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<size_t>(-2), mbrtowc(nullptr, "\xc2", 1, &ps));
138*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<size_t>(-1), wcrtomb(out, 0x00a2, &ps));
139*8d67ca89SAndroid Build Coastguard Worker EXPECT_ERRNO(EILSEQ);
140*8d67ca89SAndroid Build Coastguard Worker
141*8d67ca89SAndroid Build Coastguard Worker // If the first argument to wcrtomb is NULL or the second is L'\0' the shift
142*8d67ca89SAndroid Build Coastguard Worker // state should be reset.
143*8d67ca89SAndroid Build Coastguard Worker memset(&ps, 0, sizeof(ps));
144*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<size_t>(-2), mbrtowc(nullptr, "\xc2", 1, &ps));
145*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(1U, wcrtomb(nullptr, 0x00a2, &ps));
146*8d67ca89SAndroid Build Coastguard Worker EXPECT_TRUE(mbsinit(&ps));
147*8d67ca89SAndroid Build Coastguard Worker
148*8d67ca89SAndroid Build Coastguard Worker memset(&ps, 0, sizeof(ps));
149*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<size_t>(-2), mbrtowc(nullptr, "\xf0\xa4", 1, &ps));
150*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(1U, wcrtomb(out, L'\0', &ps));
151*8d67ca89SAndroid Build Coastguard Worker EXPECT_TRUE(mbsinit(&ps));
152*8d67ca89SAndroid Build Coastguard Worker }
153*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstombs_wcrtombs)154*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstombs_wcrtombs) {
155*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
156*8d67ca89SAndroid Build Coastguard Worker uselocale(LC_GLOBAL_LOCALE);
157*8d67ca89SAndroid Build Coastguard Worker
158*8d67ca89SAndroid Build Coastguard Worker const wchar_t chars[] = { L'h', L'e', L'l', L'l', L'o', 0 };
159*8d67ca89SAndroid Build Coastguard Worker const wchar_t bad_chars[] = { L'h', L'i', static_cast<wchar_t>(0xffffffff), 0 };
160*8d67ca89SAndroid Build Coastguard Worker const wchar_t* src;
161*8d67ca89SAndroid Build Coastguard Worker char bytes[BUFSIZ];
162*8d67ca89SAndroid Build Coastguard Worker
163*8d67ca89SAndroid Build Coastguard Worker // Given a NULL destination, these functions count valid characters.
164*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(5U, wcstombs(nullptr, chars, 0));
165*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(5U, wcstombs(nullptr, chars, 4));
166*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(5U, wcstombs(nullptr, chars, 256));
167*8d67ca89SAndroid Build Coastguard Worker src = chars;
168*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(5U, wcsrtombs(nullptr, &src, 0, nullptr));
169*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(&chars[0], src);
170*8d67ca89SAndroid Build Coastguard Worker src = chars;
171*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(5U, wcsrtombs(nullptr, &src, 4, nullptr));
172*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(&chars[0], src);
173*8d67ca89SAndroid Build Coastguard Worker src = chars;
174*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(5U, wcsrtombs(nullptr, &src, 256, nullptr));
175*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(&chars[0], src);
176*8d67ca89SAndroid Build Coastguard Worker
177*8d67ca89SAndroid Build Coastguard Worker // An unrepresentable char just returns an error from wcstombs...
178*8d67ca89SAndroid Build Coastguard Worker errno = 0;
179*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<size_t>(-1), wcstombs(nullptr, bad_chars, 0));
180*8d67ca89SAndroid Build Coastguard Worker EXPECT_ERRNO(EILSEQ);
181*8d67ca89SAndroid Build Coastguard Worker errno = 0;
182*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<size_t>(-1), wcstombs(nullptr, bad_chars, 256));
183*8d67ca89SAndroid Build Coastguard Worker EXPECT_ERRNO(EILSEQ);
184*8d67ca89SAndroid Build Coastguard Worker
185*8d67ca89SAndroid Build Coastguard Worker // And wcsrtombs doesn't tell us where it got stuck because we didn't ask it
186*8d67ca89SAndroid Build Coastguard Worker // to actually convert anything...
187*8d67ca89SAndroid Build Coastguard Worker errno = 0;
188*8d67ca89SAndroid Build Coastguard Worker src = bad_chars;
189*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<size_t>(-1), wcsrtombs(nullptr, &src, 0, nullptr));
190*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(&bad_chars[0], src);
191*8d67ca89SAndroid Build Coastguard Worker EXPECT_ERRNO(EILSEQ);
192*8d67ca89SAndroid Build Coastguard Worker errno = 0;
193*8d67ca89SAndroid Build Coastguard Worker src = bad_chars;
194*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<size_t>(-1), wcsrtombs(nullptr, &src, 256, nullptr));
195*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(&bad_chars[0], src);
196*8d67ca89SAndroid Build Coastguard Worker EXPECT_ERRNO(EILSEQ);
197*8d67ca89SAndroid Build Coastguard Worker
198*8d67ca89SAndroid Build Coastguard Worker // Okay, now let's test actually converting something...
199*8d67ca89SAndroid Build Coastguard Worker memset(bytes, 'x', sizeof(bytes));
200*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(0U, wcstombs(bytes, chars, 0));
201*8d67ca89SAndroid Build Coastguard Worker memset(bytes, 'x', sizeof(bytes));
202*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(4U, wcstombs(bytes, chars, 4));
203*8d67ca89SAndroid Build Coastguard Worker bytes[5] = 0;
204*8d67ca89SAndroid Build Coastguard Worker EXPECT_STREQ("hellx", bytes);
205*8d67ca89SAndroid Build Coastguard Worker memset(bytes, 'x', sizeof(bytes));
206*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(5U, wcstombs(bytes, chars, 256));
207*8d67ca89SAndroid Build Coastguard Worker EXPECT_STREQ("hello", bytes);
208*8d67ca89SAndroid Build Coastguard Worker memset(bytes, 'x', sizeof(bytes));
209*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(5U, wcstombs(bytes, chars, 6));
210*8d67ca89SAndroid Build Coastguard Worker EXPECT_STREQ("hello", bytes);
211*8d67ca89SAndroid Build Coastguard Worker errno = 0;
212*8d67ca89SAndroid Build Coastguard Worker memset(bytes, 'x', sizeof(bytes));
213*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<size_t>(-1), wcstombs(bytes, bad_chars, 256));
214*8d67ca89SAndroid Build Coastguard Worker EXPECT_ERRNO(EILSEQ);
215*8d67ca89SAndroid Build Coastguard Worker bytes[3] = 0;
216*8d67ca89SAndroid Build Coastguard Worker EXPECT_STREQ("hix", bytes);
217*8d67ca89SAndroid Build Coastguard Worker
218*8d67ca89SAndroid Build Coastguard Worker // wcsrtombs is a bit more informative...
219*8d67ca89SAndroid Build Coastguard Worker memset(bytes, 'x', sizeof(bytes));
220*8d67ca89SAndroid Build Coastguard Worker src = chars;
221*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(0U, wcsrtombs(bytes, &src, 0, nullptr));
222*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(&chars[0], src); // No input consumed.
223*8d67ca89SAndroid Build Coastguard Worker EXPECT_ERRNO(EILSEQ);
224*8d67ca89SAndroid Build Coastguard Worker
225*8d67ca89SAndroid Build Coastguard Worker memset(bytes, 'x', sizeof(bytes));
226*8d67ca89SAndroid Build Coastguard Worker src = chars;
227*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(4U, wcsrtombs(bytes, &src, 4, nullptr));
228*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(&chars[4], src); // Some input consumed.
229*8d67ca89SAndroid Build Coastguard Worker EXPECT_ERRNO(EILSEQ);
230*8d67ca89SAndroid Build Coastguard Worker bytes[5] = 0;
231*8d67ca89SAndroid Build Coastguard Worker EXPECT_STREQ("hellx", bytes);
232*8d67ca89SAndroid Build Coastguard Worker
233*8d67ca89SAndroid Build Coastguard Worker memset(bytes, 'x', sizeof(bytes));
234*8d67ca89SAndroid Build Coastguard Worker src = chars;
235*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(5U, wcsrtombs(bytes, &src, 256, nullptr));
236*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(nullptr, src); // All input consumed!
237*8d67ca89SAndroid Build Coastguard Worker EXPECT_ERRNO(EILSEQ);
238*8d67ca89SAndroid Build Coastguard Worker EXPECT_STREQ("hello", bytes);
239*8d67ca89SAndroid Build Coastguard Worker
240*8d67ca89SAndroid Build Coastguard Worker memset(bytes, 'x', sizeof(bytes));
241*8d67ca89SAndroid Build Coastguard Worker src = chars;
242*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(5U, wcsrtombs(bytes, &src, 6, nullptr));
243*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(nullptr, src); // All input consumed.
244*8d67ca89SAndroid Build Coastguard Worker EXPECT_ERRNO(EILSEQ);
245*8d67ca89SAndroid Build Coastguard Worker EXPECT_STREQ("hello", bytes);
246*8d67ca89SAndroid Build Coastguard Worker
247*8d67ca89SAndroid Build Coastguard Worker memset(bytes, 'x', sizeof(bytes));
248*8d67ca89SAndroid Build Coastguard Worker src = bad_chars;
249*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<size_t>(-1), wcsrtombs(bytes, &src, 256, nullptr));
250*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(&bad_chars[2], src);
251*8d67ca89SAndroid Build Coastguard Worker EXPECT_ERRNO(EILSEQ);
252*8d67ca89SAndroid Build Coastguard Worker bytes[3] = 0;
253*8d67ca89SAndroid Build Coastguard Worker EXPECT_STREQ("hix", bytes);
254*8d67ca89SAndroid Build Coastguard Worker
255*8d67ca89SAndroid Build Coastguard Worker // Any non-initial state is invalid when calling wcsrtombs.
256*8d67ca89SAndroid Build Coastguard Worker mbstate_t ps;
257*8d67ca89SAndroid Build Coastguard Worker src = chars;
258*8d67ca89SAndroid Build Coastguard Worker memset(&ps, 0, sizeof(ps));
259*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(nullptr, "\xc2", 1, &ps));
260*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<size_t>(-1), wcsrtombs(nullptr, &src, 0, &ps));
261*8d67ca89SAndroid Build Coastguard Worker EXPECT_ERRNO(EILSEQ);
262*8d67ca89SAndroid Build Coastguard Worker }
263*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,limits)264*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, limits) {
265*8d67ca89SAndroid Build Coastguard Worker ASSERT_LT(WCHAR_MIN, WCHAR_MAX);
266*8d67ca89SAndroid Build Coastguard Worker }
267*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcsstr)268*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcsstr) {
269*8d67ca89SAndroid Build Coastguard Worker const wchar_t* haystack = L"big daddy/giant haystacks!";
270*8d67ca89SAndroid Build Coastguard Worker const wchar_t* empty_haystack = L"";
271*8d67ca89SAndroid Build Coastguard Worker
272*8d67ca89SAndroid Build Coastguard Worker // The empty needle is a special case.
273*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(haystack, wcsstr(haystack, L""));
274*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(empty_haystack, wcsstr(empty_haystack, L""));
275*8d67ca89SAndroid Build Coastguard Worker
276*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(haystack, wcsstr(haystack, L"b"));
277*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(haystack, wcsstr(haystack, L"big"));
278*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(haystack + 9, wcsstr(haystack, L"/"));
279*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(haystack + 9, wcsstr(haystack, L"/giant"));
280*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(haystack + 25, wcsstr(haystack, L"!"));
281*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(haystack + 19, wcsstr(haystack, L"stacks!"));
282*8d67ca89SAndroid Build Coastguard Worker
283*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(nullptr, wcsstr(haystack, L"monkey"));
284*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(nullptr, wcsstr(empty_haystack, L"monkey"));
285*8d67ca89SAndroid Build Coastguard Worker }
286*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcsstr_80199)287*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcsstr_80199) {
288*8d67ca89SAndroid Build Coastguard Worker // https://code.google.com/p/android/issues/detail?id=80199
289*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(wcsstr(L"romrom", L"rom") != nullptr);
290*8d67ca89SAndroid Build Coastguard Worker }
291*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,mbtowc)292*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, mbtowc) {
293*8d67ca89SAndroid Build Coastguard Worker wchar_t out[8];
294*8d67ca89SAndroid Build Coastguard Worker
295*8d67ca89SAndroid Build Coastguard Worker // mbtowc and all the mbrto* APIs behave slightly differently when n is 0:
296*8d67ca89SAndroid Build Coastguard Worker //
297*8d67ca89SAndroid Build Coastguard Worker // mbrtowc returns 0 "if the next n or fewer bytes complete the multibyte
298*8d67ca89SAndroid Build Coastguard Worker // character that corresponds to the null wide character"
299*8d67ca89SAndroid Build Coastguard Worker //
300*8d67ca89SAndroid Build Coastguard Worker // mbrtoc (C23 7.24.7.2.4) says:
301*8d67ca89SAndroid Build Coastguard Worker //
302*8d67ca89SAndroid Build Coastguard Worker // If s is not a null pointer, the mbtowc function either returns 0 (if s
303*8d67ca89SAndroid Build Coastguard Worker // points to the null character), or returns the number of bytes that are
304*8d67ca89SAndroid Build Coastguard Worker // contained in the converted multibyte character (if the next n or fewer
305*8d67ca89SAndroid Build Coastguard Worker // bytes form a valid multibyte character), or returns -1 (if they do not
306*8d67ca89SAndroid Build Coastguard Worker // form a valid multibyte character).
307*8d67ca89SAndroid Build Coastguard Worker //
308*8d67ca89SAndroid Build Coastguard Worker // glibc's interpretation differs from all the BSDs (including macOS) and
309*8d67ca89SAndroid Build Coastguard Worker // bionic (by way of openbsd). glibc returns 0 since s does point to the null
310*8d67ca89SAndroid Build Coastguard Worker // character, whereas the BSDs return -1 because the next 0 bytes do not form
311*8d67ca89SAndroid Build Coastguard Worker // a valid multibyte chatacter. glibc's interpretation is probably more
312*8d67ca89SAndroid Build Coastguard Worker // correct from a strict interpretation of the spec, but considering the other
313*8d67ca89SAndroid Build Coastguard Worker // APIs behave more like the BSD interpretation that may be a bug in the spec.
314*8d67ca89SAndroid Build Coastguard Worker #ifdef __GLIBC__
315*8d67ca89SAndroid Build Coastguard Worker int expected_result_for_zero_length_empty_string = 0;
316*8d67ca89SAndroid Build Coastguard Worker #else
317*8d67ca89SAndroid Build Coastguard Worker int expected_result_for_zero_length_empty_string = -1;
318*8d67ca89SAndroid Build Coastguard Worker #endif
319*8d67ca89SAndroid Build Coastguard Worker
320*8d67ca89SAndroid Build Coastguard Worker out[0] = 'x';
321*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(-1, mbtowc(out, "hello", 0));
322*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ('x', out[0]);
323*8d67ca89SAndroid Build Coastguard Worker
324*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(-1, mbtowc(out, "hello", 0));
325*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(expected_result_for_zero_length_empty_string, mbtowc(out, "", 0));
326*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(1, mbtowc(out, "hello", 1));
327*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(L'h', out[0]);
328*8d67ca89SAndroid Build Coastguard Worker
329*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(-1, mbtowc(nullptr, "hello", 0));
330*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(expected_result_for_zero_length_empty_string, mbtowc(nullptr, "", 0));
331*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(1, mbtowc(nullptr, "hello", 1));
332*8d67ca89SAndroid Build Coastguard Worker
333*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(0, mbtowc(nullptr, nullptr, 0));
334*8d67ca89SAndroid Build Coastguard Worker }
335*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,mbrtowc)336*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, mbrtowc) {
337*8d67ca89SAndroid Build Coastguard Worker wchar_t out[8];
338*8d67ca89SAndroid Build Coastguard Worker
339*8d67ca89SAndroid Build Coastguard Worker out[0] = 'x';
340*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<size_t>(-2), mbrtowc(out, "hello", 0, nullptr));
341*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ('x', out[0]);
342*8d67ca89SAndroid Build Coastguard Worker
343*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<size_t>(-2), mbrtowc(out, "hello", 0, nullptr));
344*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<size_t>(-2), mbrtowc(out, "", 0, nullptr));
345*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(1U, mbrtowc(out, "hello", 1, nullptr));
346*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(L'h', out[0]);
347*8d67ca89SAndroid Build Coastguard Worker
348*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<size_t>(-2), mbrtowc(nullptr, "hello", 0, nullptr));
349*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<size_t>(-2), mbrtowc(nullptr, "", 0, nullptr));
350*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(1U, mbrtowc(nullptr, "hello", 1, nullptr));
351*8d67ca89SAndroid Build Coastguard Worker
352*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(0U, mbrtowc(nullptr, nullptr, 0, nullptr));
353*8d67ca89SAndroid Build Coastguard Worker
354*8d67ca89SAndroid Build Coastguard Worker EXPECT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
355*8d67ca89SAndroid Build Coastguard Worker uselocale(LC_GLOBAL_LOCALE);
356*8d67ca89SAndroid Build Coastguard Worker
357*8d67ca89SAndroid Build Coastguard Worker // 1-byte UTF-8.
358*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(1U, mbrtowc(out, "abcdef", 6, nullptr));
359*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(L'a', out[0]);
360*8d67ca89SAndroid Build Coastguard Worker // 2-byte UTF-8.
361*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(2U, mbrtowc(out,
362*8d67ca89SAndroid Build Coastguard Worker "\xc2\xa2"
363*8d67ca89SAndroid Build Coastguard Worker "cdef",
364*8d67ca89SAndroid Build Coastguard Worker 6, nullptr));
365*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<wchar_t>(0x00a2), out[0]);
366*8d67ca89SAndroid Build Coastguard Worker // 3-byte UTF-8.
367*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(3U, mbrtowc(out,
368*8d67ca89SAndroid Build Coastguard Worker "\xe2\x82\xac"
369*8d67ca89SAndroid Build Coastguard Worker "def",
370*8d67ca89SAndroid Build Coastguard Worker 6, nullptr));
371*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<wchar_t>(0x20ac), out[0]);
372*8d67ca89SAndroid Build Coastguard Worker // 4-byte UTF-8.
373*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(4U, mbrtowc(out,
374*8d67ca89SAndroid Build Coastguard Worker "\xf0\xa4\xad\xa2"
375*8d67ca89SAndroid Build Coastguard Worker "ef",
376*8d67ca89SAndroid Build Coastguard Worker 6, nullptr));
377*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<wchar_t>(0x24b62), out[0]);
378*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__) // glibc allows this.
379*8d67ca89SAndroid Build Coastguard Worker // Illegal 5-byte UTF-8.
380*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<size_t>(-1), mbrtowc(out,
381*8d67ca89SAndroid Build Coastguard Worker "\xf8\xa1\xa2\xa3\xa4"
382*8d67ca89SAndroid Build Coastguard Worker "f",
383*8d67ca89SAndroid Build Coastguard Worker 6, nullptr));
384*8d67ca89SAndroid Build Coastguard Worker EXPECT_ERRNO(EILSEQ);
385*8d67ca89SAndroid Build Coastguard Worker #endif
386*8d67ca89SAndroid Build Coastguard Worker // Illegal over-long sequence.
387*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<size_t>(-1), mbrtowc(out,
388*8d67ca89SAndroid Build Coastguard Worker "\xf0\x82\x82\xac"
389*8d67ca89SAndroid Build Coastguard Worker "ef",
390*8d67ca89SAndroid Build Coastguard Worker 6, nullptr));
391*8d67ca89SAndroid Build Coastguard Worker EXPECT_ERRNO(EILSEQ);
392*8d67ca89SAndroid Build Coastguard Worker }
393*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,mbrtowc_valid_non_characters)394*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, mbrtowc_valid_non_characters) {
395*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
396*8d67ca89SAndroid Build Coastguard Worker uselocale(LC_GLOBAL_LOCALE);
397*8d67ca89SAndroid Build Coastguard Worker
398*8d67ca89SAndroid Build Coastguard Worker wchar_t out[8] = {};
399*8d67ca89SAndroid Build Coastguard Worker
400*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(3U, mbrtowc(out, "\xef\xbf\xbe", 3, nullptr));
401*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<wchar_t>(0xfffe), out[0]);
402*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(3U, mbrtowc(out, "\xef\xbf\xbf", 3, nullptr));
403*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<wchar_t>(0xffff), out[0]);
404*8d67ca89SAndroid Build Coastguard Worker }
405*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,mbrtowc_out_of_range)406*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, mbrtowc_out_of_range) {
407*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
408*8d67ca89SAndroid Build Coastguard Worker uselocale(LC_GLOBAL_LOCALE);
409*8d67ca89SAndroid Build Coastguard Worker
410*8d67ca89SAndroid Build Coastguard Worker wchar_t out[8] = {};
411*8d67ca89SAndroid Build Coastguard Worker errno = 0;
412*8d67ca89SAndroid Build Coastguard Worker auto result = mbrtowc(out, "\xf5\x80\x80\x80", 4, nullptr);
413*8d67ca89SAndroid Build Coastguard Worker if (kLibcRejectsOverLongUtf8Sequences) {
414*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<size_t>(-1), result);
415*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EILSEQ);
416*8d67ca89SAndroid Build Coastguard Worker } else {
417*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(4U, result);
418*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(0);
419*8d67ca89SAndroid Build Coastguard Worker }
420*8d67ca89SAndroid Build Coastguard Worker }
421*8d67ca89SAndroid Build Coastguard Worker
test_mbrtowc_incomplete(mbstate_t * ps)422*8d67ca89SAndroid Build Coastguard Worker static void test_mbrtowc_incomplete(mbstate_t* ps) {
423*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
424*8d67ca89SAndroid Build Coastguard Worker uselocale(LC_GLOBAL_LOCALE);
425*8d67ca89SAndroid Build Coastguard Worker
426*8d67ca89SAndroid Build Coastguard Worker wchar_t out;
427*8d67ca89SAndroid Build Coastguard Worker // 2-byte UTF-8.
428*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(&out, "\xc2", 1, ps));
429*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(1U, mbrtowc(&out, "\xa2" "cdef", 5, ps));
430*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<wchar_t>(0x00a2), out);
431*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(mbsinit(ps));
432*8d67ca89SAndroid Build Coastguard Worker // 3-byte UTF-8.
433*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(&out, "\xe2", 1, ps));
434*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(&out, "\x82", 1, ps));
435*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(1U, mbrtowc(&out, "\xac" "def", 4, ps));
436*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<wchar_t>(0x20ac), out);
437*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(mbsinit(ps));
438*8d67ca89SAndroid Build Coastguard Worker // 4-byte UTF-8.
439*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(&out, "\xf0", 1, ps));
440*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(&out, "\xa4\xad", 2, ps));
441*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(1U, mbrtowc(&out, "\xa2" "ef", 3, ps));
442*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<wchar_t>(0x24b62), out);
443*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(mbsinit(ps));
444*8d67ca89SAndroid Build Coastguard Worker
445*8d67ca89SAndroid Build Coastguard Worker // Invalid 2-byte
446*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(&out, "\xc2", 1, ps));
447*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<size_t>(-1), mbrtowc(&out, "\x20" "cdef", 5, ps));
448*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EILSEQ);
449*8d67ca89SAndroid Build Coastguard Worker }
450*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,mbrtowc_incomplete)451*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, mbrtowc_incomplete) {
452*8d67ca89SAndroid Build Coastguard Worker mbstate_t ps;
453*8d67ca89SAndroid Build Coastguard Worker memset(&ps, 0, sizeof(ps));
454*8d67ca89SAndroid Build Coastguard Worker
455*8d67ca89SAndroid Build Coastguard Worker test_mbrtowc_incomplete(&ps);
456*8d67ca89SAndroid Build Coastguard Worker test_mbrtowc_incomplete(nullptr);
457*8d67ca89SAndroid Build Coastguard Worker }
458*8d67ca89SAndroid Build Coastguard Worker
test_mbsrtowcs(mbstate_t * ps)459*8d67ca89SAndroid Build Coastguard Worker static void test_mbsrtowcs(mbstate_t* ps) {
460*8d67ca89SAndroid Build Coastguard Worker constexpr const char* VALID = "A" "\xc2\xa2" "\xe2\x82\xac" "\xf0\xa4\xad\xa2" "ef";
461*8d67ca89SAndroid Build Coastguard Worker constexpr const char* INVALID = "A" "\xc2\x20" "ef";
462*8d67ca89SAndroid Build Coastguard Worker constexpr const char* INCOMPLETE = "A" "\xc2";
463*8d67ca89SAndroid Build Coastguard Worker wchar_t out[4];
464*8d67ca89SAndroid Build Coastguard Worker
465*8d67ca89SAndroid Build Coastguard Worker const char* valid = VALID;
466*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(4U, mbsrtowcs(out, &valid, 4, ps));
467*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(L'A', out[0]);
468*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<wchar_t>(0x00a2), out[1]);
469*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<wchar_t>(0x20ac), out[2]);
470*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<wchar_t>(0x24b62), out[3]);
471*8d67ca89SAndroid Build Coastguard Worker // Check that valid has advanced to the next unread character.
472*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ('e', *valid);
473*8d67ca89SAndroid Build Coastguard Worker
474*8d67ca89SAndroid Build Coastguard Worker wmemset(out, L'x', NUM_WCHARS(sizeof(out)));
475*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(2U, mbsrtowcs(out, &valid, 4, ps));
476*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(L'e', out[0]);
477*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(L'f', out[1]);
478*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(L'\0', out[2]);
479*8d67ca89SAndroid Build Coastguard Worker // Check that we didn't clobber the rest of out.
480*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(L'x', out[3]);
481*8d67ca89SAndroid Build Coastguard Worker // Check that valid has advanced to the end of the string.
482*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(nullptr, valid);
483*8d67ca89SAndroid Build Coastguard Worker
484*8d67ca89SAndroid Build Coastguard Worker const char* invalid = INVALID;
485*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<size_t>(-1), mbsrtowcs(out, &invalid, 4, ps));
486*8d67ca89SAndroid Build Coastguard Worker EXPECT_ERRNO(EILSEQ);
487*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ('\xc2', *invalid);
488*8d67ca89SAndroid Build Coastguard Worker
489*8d67ca89SAndroid Build Coastguard Worker const char* incomplete = INCOMPLETE;
490*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<size_t>(-1), mbsrtowcs(out, &incomplete, 2, ps));
491*8d67ca89SAndroid Build Coastguard Worker EXPECT_ERRNO(EILSEQ);
492*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ('\xc2', *incomplete);
493*8d67ca89SAndroid Build Coastguard Worker
494*8d67ca89SAndroid Build Coastguard Worker // If dst is null, *src shouldn't be updated.
495*8d67ca89SAndroid Build Coastguard Worker // https://code.google.com/p/android/issues/detail?id=166381
496*8d67ca89SAndroid Build Coastguard Worker const char* mbs = VALID;
497*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(6U, mbsrtowcs(nullptr, &mbs, 0, ps));
498*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(VALID, mbs);
499*8d67ca89SAndroid Build Coastguard Worker mbs = INVALID;
500*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<size_t>(-1), mbsrtowcs(nullptr, &mbs, 0, ps));
501*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(INVALID, mbs);
502*8d67ca89SAndroid Build Coastguard Worker mbs = INCOMPLETE;
503*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<size_t>(-1), mbsrtowcs(nullptr, &mbs, 0, ps));
504*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(INCOMPLETE, mbs);
505*8d67ca89SAndroid Build Coastguard Worker }
506*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,mbsrtowcs)507*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, mbsrtowcs) {
508*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
509*8d67ca89SAndroid Build Coastguard Worker uselocale(LC_GLOBAL_LOCALE);
510*8d67ca89SAndroid Build Coastguard Worker
511*8d67ca89SAndroid Build Coastguard Worker mbstate_t ps;
512*8d67ca89SAndroid Build Coastguard Worker memset(&ps, 0, sizeof(ps));
513*8d67ca89SAndroid Build Coastguard Worker test_mbsrtowcs(&ps);
514*8d67ca89SAndroid Build Coastguard Worker test_mbsrtowcs(nullptr);
515*8d67ca89SAndroid Build Coastguard Worker
516*8d67ca89SAndroid Build Coastguard Worker // Invalid multi byte continuation.
517*8d67ca89SAndroid Build Coastguard Worker const char* invalid = "\x20";
518*8d67ca89SAndroid Build Coastguard Worker wchar_t out;
519*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<size_t>(-2), mbrtowc(&out, "\xc2", 1, &ps));
520*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<size_t>(-1), mbsrtowcs(&out, &invalid, 1, &ps));
521*8d67ca89SAndroid Build Coastguard Worker EXPECT_ERRNO(EILSEQ);
522*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ('\x20', *invalid);
523*8d67ca89SAndroid Build Coastguard Worker }
524*8d67ca89SAndroid Build Coastguard Worker
525*8d67ca89SAndroid Build Coastguard Worker template <typename T>
526*8d67ca89SAndroid Build Coastguard Worker using WcsToIntFn = T (*)(const wchar_t*, wchar_t**, int);
527*8d67ca89SAndroid Build Coastguard Worker
528*8d67ca89SAndroid Build Coastguard Worker template <typename T>
TestSingleWcsToInt(WcsToIntFn<T> fn,const wchar_t * str,int base,T expected_value,ptrdiff_t expected_len)529*8d67ca89SAndroid Build Coastguard Worker void TestSingleWcsToInt(WcsToIntFn<T> fn, const wchar_t* str, int base,
530*8d67ca89SAndroid Build Coastguard Worker T expected_value, ptrdiff_t expected_len) {
531*8d67ca89SAndroid Build Coastguard Worker wchar_t* p;
532*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(expected_value, fn(str, &p, base)) << str << " " << base;
533*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(expected_len, p - str) << str << " " << base;
534*8d67ca89SAndroid Build Coastguard Worker }
535*8d67ca89SAndroid Build Coastguard Worker
536*8d67ca89SAndroid Build Coastguard Worker template <typename T>
TestWcsToInt(WcsToIntFn<T> fn)537*8d67ca89SAndroid Build Coastguard Worker void TestWcsToInt(WcsToIntFn<T> fn) {
538*8d67ca89SAndroid Build Coastguard Worker TestSingleWcsToInt(fn, L"123", 10, static_cast<T>(123), 3);
539*8d67ca89SAndroid Build Coastguard Worker TestSingleWcsToInt(fn, L"123", 0, static_cast<T>(123), 3);
540*8d67ca89SAndroid Build Coastguard Worker TestSingleWcsToInt(fn, L"123#", 10, static_cast<T>(123), 3);
541*8d67ca89SAndroid Build Coastguard Worker TestSingleWcsToInt(fn, L"01000", 8, static_cast<T>(512), 5);
542*8d67ca89SAndroid Build Coastguard Worker TestSingleWcsToInt(fn, L"01000", 0, static_cast<T>(512), 5);
543*8d67ca89SAndroid Build Coastguard Worker TestSingleWcsToInt(fn, L" 123 45", 0, static_cast<T>(123), 6);
544*8d67ca89SAndroid Build Coastguard Worker TestSingleWcsToInt(fn, L" -123", 0, static_cast<T>(-123), 6);
545*8d67ca89SAndroid Build Coastguard Worker TestSingleWcsToInt(fn, L"0x10000", 0, static_cast<T>(65536), 7);
546*8d67ca89SAndroid Build Coastguard Worker if (kLibcSupportsParsingBinaryLiterals) {
547*8d67ca89SAndroid Build Coastguard Worker TestSingleWcsToInt(fn, L"0b1011", 0, static_cast<T>(0b1011), 6);
548*8d67ca89SAndroid Build Coastguard Worker }
549*8d67ca89SAndroid Build Coastguard Worker }
550*8d67ca89SAndroid Build Coastguard Worker
551*8d67ca89SAndroid Build Coastguard Worker template <typename T>
TestWcsToIntLimits(WcsToIntFn<T> fn,const wchar_t * min_str,const wchar_t * max_str)552*8d67ca89SAndroid Build Coastguard Worker void TestWcsToIntLimits(WcsToIntFn<T> fn, const wchar_t* min_str,
553*8d67ca89SAndroid Build Coastguard Worker const wchar_t* max_str) {
554*8d67ca89SAndroid Build Coastguard Worker if (std::is_signed<T>::value) {
555*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(std::numeric_limits<T>::min(), fn(min_str, nullptr, 0)) << min_str;
556*8d67ca89SAndroid Build Coastguard Worker } else {
557*8d67ca89SAndroid Build Coastguard Worker // If the subject sequence begins with a <hyphen-minus>, the value resulting
558*8d67ca89SAndroid Build Coastguard Worker // from the conversion shall be negated.
559*8d67ca89SAndroid Build Coastguard Worker // https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/strtoul.html
560*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(std::numeric_limits<T>::max(), fn(min_str, nullptr, 0)) << min_str;
561*8d67ca89SAndroid Build Coastguard Worker }
562*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(std::numeric_limits<T>::max(), fn(max_str, nullptr, 0)) << max_str;
563*8d67ca89SAndroid Build Coastguard Worker }
564*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstol)565*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstol) {
566*8d67ca89SAndroid Build Coastguard Worker TestWcsToInt(wcstol);
567*8d67ca89SAndroid Build Coastguard Worker }
568*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstol_limits)569*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstol_limits) {
570*8d67ca89SAndroid Build Coastguard Worker if (sizeof(long) == 8) {
571*8d67ca89SAndroid Build Coastguard Worker TestWcsToIntLimits(wcstol, L"-9223372036854775809", L"9223372036854775808");
572*8d67ca89SAndroid Build Coastguard Worker } else {
573*8d67ca89SAndroid Build Coastguard Worker TestWcsToIntLimits(wcstol, L"-2147483649", L"2147483648");
574*8d67ca89SAndroid Build Coastguard Worker }
575*8d67ca89SAndroid Build Coastguard Worker }
576*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstoul)577*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstoul) {
578*8d67ca89SAndroid Build Coastguard Worker TestWcsToInt(wcstoul);
579*8d67ca89SAndroid Build Coastguard Worker }
580*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstoul_limits)581*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstoul_limits) {
582*8d67ca89SAndroid Build Coastguard Worker if (sizeof(long) == 8) {
583*8d67ca89SAndroid Build Coastguard Worker TestWcsToIntLimits(wcstoul, L"-1", L"18446744073709551616");
584*8d67ca89SAndroid Build Coastguard Worker } else {
585*8d67ca89SAndroid Build Coastguard Worker TestWcsToIntLimits(wcstoul, L"-1", L"4294967296");
586*8d67ca89SAndroid Build Coastguard Worker }
587*8d67ca89SAndroid Build Coastguard Worker }
588*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstoll)589*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstoll) {
590*8d67ca89SAndroid Build Coastguard Worker TestWcsToInt(wcstoll);
591*8d67ca89SAndroid Build Coastguard Worker }
592*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstoll_limits)593*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstoll_limits) {
594*8d67ca89SAndroid Build Coastguard Worker TestWcsToIntLimits(wcstoll, L"-9223372036854775809", L"9223372036854775808");
595*8d67ca89SAndroid Build Coastguard Worker }
596*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstoull)597*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstoull) {
598*8d67ca89SAndroid Build Coastguard Worker TestWcsToInt(wcstoull);
599*8d67ca89SAndroid Build Coastguard Worker }
600*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstoull_limits)601*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstoull_limits) {
602*8d67ca89SAndroid Build Coastguard Worker TestWcsToIntLimits(wcstoull, L"-1", L"18446744073709551616");
603*8d67ca89SAndroid Build Coastguard Worker }
604*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstoimax)605*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstoimax) {
606*8d67ca89SAndroid Build Coastguard Worker TestWcsToInt(wcstoimax);
607*8d67ca89SAndroid Build Coastguard Worker }
608*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstoimax_limits)609*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstoimax_limits) {
610*8d67ca89SAndroid Build Coastguard Worker TestWcsToIntLimits(wcstoimax, L"-9223372036854775809",
611*8d67ca89SAndroid Build Coastguard Worker L"9223372036854775808");
612*8d67ca89SAndroid Build Coastguard Worker }
613*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstoumax)614*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstoumax) {
615*8d67ca89SAndroid Build Coastguard Worker TestWcsToInt(wcstoumax);
616*8d67ca89SAndroid Build Coastguard Worker }
617*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstoumax_limits)618*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstoumax_limits) {
619*8d67ca89SAndroid Build Coastguard Worker TestWcsToIntLimits(wcstoumax, L"-1", L"18446744073709551616");
620*8d67ca89SAndroid Build Coastguard Worker }
621*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,mbsnrtowcs)622*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, mbsnrtowcs) {
623*8d67ca89SAndroid Build Coastguard Worker wchar_t dst[128];
624*8d67ca89SAndroid Build Coastguard Worker const char* s = "hello, world!";
625*8d67ca89SAndroid Build Coastguard Worker const char* src;
626*8d67ca89SAndroid Build Coastguard Worker
627*8d67ca89SAndroid Build Coastguard Worker memset(dst, 0, sizeof(dst));
628*8d67ca89SAndroid Build Coastguard Worker src = s;
629*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0U, mbsnrtowcs(dst, &src, 0, 0, nullptr));
630*8d67ca89SAndroid Build Coastguard Worker
631*8d67ca89SAndroid Build Coastguard Worker memset(dst, 0, sizeof(dst));
632*8d67ca89SAndroid Build Coastguard Worker src = s;
633*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(2U, mbsnrtowcs(dst, &src, 2, 123, nullptr)); // glibc chokes on SIZE_MAX here.
634*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(L'h', dst[0]);
635*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(L'e', dst[1]);
636*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(&s[2], src);
637*8d67ca89SAndroid Build Coastguard Worker
638*8d67ca89SAndroid Build Coastguard Worker memset(dst, 0, sizeof(dst));
639*8d67ca89SAndroid Build Coastguard Worker src = s;
640*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(3U, mbsnrtowcs(dst, &src, SIZE_MAX, 3, nullptr));
641*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(L'h', dst[0]);
642*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(L'e', dst[1]);
643*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(L'l', dst[2]);
644*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(&s[3], src);
645*8d67ca89SAndroid Build Coastguard Worker
646*8d67ca89SAndroid Build Coastguard Worker memset(dst, 0, sizeof(dst));
647*8d67ca89SAndroid Build Coastguard Worker const char* incomplete = "\xc2"; // Incomplete UTF-8 sequence.
648*8d67ca89SAndroid Build Coastguard Worker src = incomplete;
649*8d67ca89SAndroid Build Coastguard Worker errno = 0;
650*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<size_t>(-1), mbsnrtowcs(dst, &src, SIZE_MAX, 3, nullptr));
651*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EILSEQ);
652*8d67ca89SAndroid Build Coastguard Worker
653*8d67ca89SAndroid Build Coastguard Worker src = incomplete;
654*8d67ca89SAndroid Build Coastguard Worker errno = 0;
655*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(static_cast<size_t>(-1), mbsnrtowcs(nullptr, &src, SIZE_MAX, 3, nullptr));
656*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EILSEQ);
657*8d67ca89SAndroid Build Coastguard Worker }
658*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcsftime__wcsftime_l)659*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcsftime__wcsftime_l) {
660*8d67ca89SAndroid Build Coastguard Worker setenv("TZ", "UTC", 1);
661*8d67ca89SAndroid Build Coastguard Worker
662*8d67ca89SAndroid Build Coastguard Worker struct tm t;
663*8d67ca89SAndroid Build Coastguard Worker memset(&t, 0, sizeof(tm));
664*8d67ca89SAndroid Build Coastguard Worker t.tm_year = 200;
665*8d67ca89SAndroid Build Coastguard Worker t.tm_mon = 2;
666*8d67ca89SAndroid Build Coastguard Worker t.tm_mday = 10;
667*8d67ca89SAndroid Build Coastguard Worker
668*8d67ca89SAndroid Build Coastguard Worker wchar_t buf[64];
669*8d67ca89SAndroid Build Coastguard Worker
670*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(24U, wcsftime(buf, sizeof(buf), L"%c", &t));
671*8d67ca89SAndroid Build Coastguard Worker EXPECT_STREQ(L"Sun Mar 10 00:00:00 2100", buf);
672*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(24U, wcsftime_l(buf, sizeof(buf), L"%c", &t, SAFE_LC_GLOBAL_LOCALE));
673*8d67ca89SAndroid Build Coastguard Worker EXPECT_STREQ(L"Sun Mar 10 00:00:00 2100", buf);
674*8d67ca89SAndroid Build Coastguard Worker }
675*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wmemmove_smoke)676*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wmemmove_smoke) {
677*8d67ca89SAndroid Build Coastguard Worker const wchar_t const_wstr[] = L"This is a test of something or other.....";
678*8d67ca89SAndroid Build Coastguard Worker wchar_t wstr[NUM_WCHARS(sizeof(const_wstr))];
679*8d67ca89SAndroid Build Coastguard Worker
680*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(wstr, wmemmove(wstr, const_wstr, NUM_WCHARS(sizeof(const_wstr))));
681*8d67ca89SAndroid Build Coastguard Worker EXPECT_STREQ(const_wstr, wstr);
682*8d67ca89SAndroid Build Coastguard Worker
683*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(wstr+5, wmemmove(wstr+5, wstr, NUM_WCHARS(sizeof(const_wstr)) - 6));
684*8d67ca89SAndroid Build Coastguard Worker EXPECT_STREQ(L"This This is a test of something or other", wstr);
685*8d67ca89SAndroid Build Coastguard Worker }
686*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wmemcpy_smoke)687*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wmemcpy_smoke) {
688*8d67ca89SAndroid Build Coastguard Worker const wchar_t src[] = L"Source string";
689*8d67ca89SAndroid Build Coastguard Worker wchar_t dst[NUM_WCHARS(sizeof(src))];
690*8d67ca89SAndroid Build Coastguard Worker
691*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(dst, wmemcpy(dst, src, NUM_WCHARS(sizeof(src))));
692*8d67ca89SAndroid Build Coastguard Worker EXPECT_STREQ(dst, src);
693*8d67ca89SAndroid Build Coastguard Worker }
694*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcpcpy_smoke)695*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcpcpy_smoke) {
696*8d67ca89SAndroid Build Coastguard Worker const wchar_t src[] = L"Source string";
697*8d67ca89SAndroid Build Coastguard Worker wchar_t dst[NUM_WCHARS(sizeof(src))];
698*8d67ca89SAndroid Build Coastguard Worker
699*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(dst + NUM_WCHARS(sizeof(src)) - 1, wcpcpy(dst, src));
700*8d67ca89SAndroid Build Coastguard Worker EXPECT_STREQ(dst, src);
701*8d67ca89SAndroid Build Coastguard Worker }
702*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcpncpy_smoke)703*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcpncpy_smoke) {
704*8d67ca89SAndroid Build Coastguard Worker const wchar_t src[] = L"Source string";
705*8d67ca89SAndroid Build Coastguard Worker wchar_t dst[NUM_WCHARS(sizeof(src)) + 5];
706*8d67ca89SAndroid Build Coastguard Worker
707*8d67ca89SAndroid Build Coastguard Worker size_t src_len = NUM_WCHARS(sizeof(src)) - 1;
708*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(dst + src_len, wcpncpy(dst, src, src_len + 1));
709*8d67ca89SAndroid Build Coastguard Worker EXPECT_STREQ(dst, src);
710*8d67ca89SAndroid Build Coastguard Worker
711*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(dst + 6, wcpncpy(dst, src, 6));
712*8d67ca89SAndroid Build Coastguard Worker dst[6] = L'\0';
713*8d67ca89SAndroid Build Coastguard Worker EXPECT_STREQ(dst, L"Source");
714*8d67ca89SAndroid Build Coastguard Worker
715*8d67ca89SAndroid Build Coastguard Worker wmemset(dst, L'x', NUM_WCHARS(sizeof(dst)));
716*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(dst + src_len, wcpncpy(dst, src, src_len + 4));
717*8d67ca89SAndroid Build Coastguard Worker EXPECT_STREQ(dst, src);
718*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(dst[src_len], L'\0');
719*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(dst[src_len+1], L'\0');
720*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(dst[src_len+2], L'\0');
721*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(dst[src_len+3], L'\0');
722*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(dst[src_len+4], L'x');
723*8d67ca89SAndroid Build Coastguard Worker }
724*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcscpy_smoke)725*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcscpy_smoke) {
726*8d67ca89SAndroid Build Coastguard Worker const wchar_t src[] = L"Source string";
727*8d67ca89SAndroid Build Coastguard Worker wchar_t dst[NUM_WCHARS(sizeof(src))];
728*8d67ca89SAndroid Build Coastguard Worker
729*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(dst, wcscpy(dst, src));
730*8d67ca89SAndroid Build Coastguard Worker EXPECT_STREQ(src, dst);
731*8d67ca89SAndroid Build Coastguard Worker }
732*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcsncpy_smoke)733*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcsncpy_smoke) {
734*8d67ca89SAndroid Build Coastguard Worker const wchar_t src[] = L"Source string";
735*8d67ca89SAndroid Build Coastguard Worker wchar_t dst[NUM_WCHARS(sizeof(src)) + 5];
736*8d67ca89SAndroid Build Coastguard Worker
737*8d67ca89SAndroid Build Coastguard Worker size_t src_len = NUM_WCHARS(sizeof(src)) - 1;
738*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(dst, wcsncpy(dst, src, src_len + 1));
739*8d67ca89SAndroid Build Coastguard Worker EXPECT_STREQ(dst, src);
740*8d67ca89SAndroid Build Coastguard Worker
741*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(dst, wcsncpy(dst, src, 6));
742*8d67ca89SAndroid Build Coastguard Worker dst[6] = L'\0';
743*8d67ca89SAndroid Build Coastguard Worker EXPECT_STREQ(dst, L"Source");
744*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(dst, wcsncpy(dst, L"clobber", 0));
745*8d67ca89SAndroid Build Coastguard Worker EXPECT_STREQ(dst, L"Source");
746*8d67ca89SAndroid Build Coastguard Worker
747*8d67ca89SAndroid Build Coastguard Worker wmemset(dst, L'x', NUM_WCHARS(sizeof(dst)));
748*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(dst, wcsncpy(dst, src, src_len + 4));
749*8d67ca89SAndroid Build Coastguard Worker EXPECT_STREQ(dst, src);
750*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(dst[src_len], L'\0');
751*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(dst[src_len+1], L'\0');
752*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(dst[src_len+2], L'\0');
753*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(dst[src_len+3], L'\0');
754*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(dst[src_len+4], L'x');
755*8d67ca89SAndroid Build Coastguard Worker }
756*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,mbrtowc_15439554)757*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, mbrtowc_15439554) {
758*8d67ca89SAndroid Build Coastguard Worker // http://b/15439554
759*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
760*8d67ca89SAndroid Build Coastguard Worker uselocale(LC_GLOBAL_LOCALE);
761*8d67ca89SAndroid Build Coastguard Worker
762*8d67ca89SAndroid Build Coastguard Worker ASSERT_GE(static_cast<size_t>(MB_LEN_MAX), MB_CUR_MAX);
763*8d67ca89SAndroid Build Coastguard Worker ASSERT_GE(MB_CUR_MAX, 4U);
764*8d67ca89SAndroid Build Coastguard Worker
765*8d67ca89SAndroid Build Coastguard Worker wchar_t wc;
766*8d67ca89SAndroid Build Coastguard Worker size_t n;
767*8d67ca89SAndroid Build Coastguard Worker
768*8d67ca89SAndroid Build Coastguard Worker // 1-byte character.
769*8d67ca89SAndroid Build Coastguard Worker n = mbrtowc(&wc, "x", MB_CUR_MAX, nullptr);
770*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(1U, n);
771*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(L'x', wc);
772*8d67ca89SAndroid Build Coastguard Worker // 2-byte character.
773*8d67ca89SAndroid Build Coastguard Worker n = mbrtowc(&wc, "\xc2\xa2", MB_CUR_MAX, nullptr);
774*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(2U, n);
775*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(L'¢', wc);
776*8d67ca89SAndroid Build Coastguard Worker // 3-byte character.
777*8d67ca89SAndroid Build Coastguard Worker n = mbrtowc(&wc, "\xe2\x82\xac", MB_CUR_MAX, nullptr);
778*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(3U, n);
779*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(L'€', wc);
780*8d67ca89SAndroid Build Coastguard Worker // 4-byte character.
781*8d67ca89SAndroid Build Coastguard Worker n = mbrtowc(&wc, "\xf0\xa4\xad\xa2", MB_CUR_MAX, nullptr);
782*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(4U, n);
783*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(L'', wc);
784*8d67ca89SAndroid Build Coastguard Worker }
785*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,open_wmemstream)786*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, open_wmemstream) {
787*8d67ca89SAndroid Build Coastguard Worker wchar_t* p = nullptr;
788*8d67ca89SAndroid Build Coastguard Worker size_t size = 0;
789*8d67ca89SAndroid Build Coastguard Worker FILE* fp = open_wmemstream(&p, &size);
790*8d67ca89SAndroid Build Coastguard Worker ASSERT_NE(EOF, fputws(L"hello, world!", fp));
791*8d67ca89SAndroid Build Coastguard Worker fclose(fp);
792*8d67ca89SAndroid Build Coastguard Worker
793*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(L"hello, world!", p);
794*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(wcslen(L"hello, world!"), size);
795*8d67ca89SAndroid Build Coastguard Worker free(p);
796*8d67ca89SAndroid Build Coastguard Worker }
797*8d67ca89SAndroid Build Coastguard Worker
TEST(stdio,open_wmemstream_EINVAL)798*8d67ca89SAndroid Build Coastguard Worker TEST(stdio, open_wmemstream_EINVAL) {
799*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
800*8d67ca89SAndroid Build Coastguard Worker wchar_t* p;
801*8d67ca89SAndroid Build Coastguard Worker size_t size;
802*8d67ca89SAndroid Build Coastguard Worker #pragma clang diagnostic push
803*8d67ca89SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wnonnull"
804*8d67ca89SAndroid Build Coastguard Worker // Invalid buffer.
805*8d67ca89SAndroid Build Coastguard Worker errno = 0;
806*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(nullptr, open_wmemstream(nullptr, &size));
807*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EINVAL);
808*8d67ca89SAndroid Build Coastguard Worker
809*8d67ca89SAndroid Build Coastguard Worker // Invalid size.
810*8d67ca89SAndroid Build Coastguard Worker errno = 0;
811*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(nullptr, open_wmemstream(&p, nullptr));
812*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EINVAL);
813*8d67ca89SAndroid Build Coastguard Worker #pragma clang diagnostic pop
814*8d67ca89SAndroid Build Coastguard Worker #else
815*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "This test is bionic-specific";
816*8d67ca89SAndroid Build Coastguard Worker #endif
817*8d67ca89SAndroid Build Coastguard Worker }
818*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstol_EINVAL)819*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstol_EINVAL) {
820*8d67ca89SAndroid Build Coastguard Worker errno = 0;
821*8d67ca89SAndroid Build Coastguard Worker wcstol(L"123", nullptr, -1);
822*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EINVAL);
823*8d67ca89SAndroid Build Coastguard Worker errno = 0;
824*8d67ca89SAndroid Build Coastguard Worker wcstol(L"123", nullptr, 1);
825*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EINVAL);
826*8d67ca89SAndroid Build Coastguard Worker errno = 0;
827*8d67ca89SAndroid Build Coastguard Worker wcstol(L"123", nullptr, 37);
828*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EINVAL);
829*8d67ca89SAndroid Build Coastguard Worker }
830*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstoll_EINVAL)831*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstoll_EINVAL) {
832*8d67ca89SAndroid Build Coastguard Worker errno = 0;
833*8d67ca89SAndroid Build Coastguard Worker wcstoll(L"123", nullptr, -1);
834*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EINVAL);
835*8d67ca89SAndroid Build Coastguard Worker errno = 0;
836*8d67ca89SAndroid Build Coastguard Worker wcstoll(L"123", nullptr, 1);
837*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EINVAL);
838*8d67ca89SAndroid Build Coastguard Worker errno = 0;
839*8d67ca89SAndroid Build Coastguard Worker wcstoll(L"123", nullptr, 37);
840*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EINVAL);
841*8d67ca89SAndroid Build Coastguard Worker }
842*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstoul_EINVAL)843*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstoul_EINVAL) {
844*8d67ca89SAndroid Build Coastguard Worker errno = 0;
845*8d67ca89SAndroid Build Coastguard Worker wcstoul(L"123", nullptr, -1);
846*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EINVAL);
847*8d67ca89SAndroid Build Coastguard Worker errno = 0;
848*8d67ca89SAndroid Build Coastguard Worker wcstoul(L"123", nullptr, 1);
849*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EINVAL);
850*8d67ca89SAndroid Build Coastguard Worker errno = 0;
851*8d67ca89SAndroid Build Coastguard Worker wcstoul(L"123", nullptr, 37);
852*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EINVAL);
853*8d67ca89SAndroid Build Coastguard Worker }
854*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstoull_EINVAL)855*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstoull_EINVAL) {
856*8d67ca89SAndroid Build Coastguard Worker errno = 0;
857*8d67ca89SAndroid Build Coastguard Worker wcstoull(L"123", nullptr, -1);
858*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EINVAL);
859*8d67ca89SAndroid Build Coastguard Worker errno = 0;
860*8d67ca89SAndroid Build Coastguard Worker wcstoull(L"123", nullptr, 1);
861*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EINVAL);
862*8d67ca89SAndroid Build Coastguard Worker errno = 0;
863*8d67ca89SAndroid Build Coastguard Worker wcstoull(L"123", nullptr, 37);
864*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EINVAL);
865*8d67ca89SAndroid Build Coastguard Worker }
866*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstoll_l_EINVAL)867*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstoll_l_EINVAL) {
868*8d67ca89SAndroid Build Coastguard Worker errno = 0;
869*8d67ca89SAndroid Build Coastguard Worker wcstoll_l(L"123", nullptr, -1, SAFE_LC_GLOBAL_LOCALE);
870*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EINVAL);
871*8d67ca89SAndroid Build Coastguard Worker errno = 0;
872*8d67ca89SAndroid Build Coastguard Worker wcstoll_l(L"123", nullptr, 1, SAFE_LC_GLOBAL_LOCALE);
873*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EINVAL);
874*8d67ca89SAndroid Build Coastguard Worker errno = 0;
875*8d67ca89SAndroid Build Coastguard Worker wcstoll_l(L"123", nullptr, 37, SAFE_LC_GLOBAL_LOCALE);
876*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EINVAL);
877*8d67ca89SAndroid Build Coastguard Worker }
878*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstoull_l_EINVAL)879*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstoull_l_EINVAL) {
880*8d67ca89SAndroid Build Coastguard Worker errno = 0;
881*8d67ca89SAndroid Build Coastguard Worker wcstoull_l(L"123", nullptr, -1, SAFE_LC_GLOBAL_LOCALE);
882*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EINVAL);
883*8d67ca89SAndroid Build Coastguard Worker errno = 0;
884*8d67ca89SAndroid Build Coastguard Worker wcstoull_l(L"123", nullptr, 1, SAFE_LC_GLOBAL_LOCALE);
885*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EINVAL);
886*8d67ca89SAndroid Build Coastguard Worker errno = 0;
887*8d67ca89SAndroid Build Coastguard Worker wcstoull_l(L"123", nullptr, 37, SAFE_LC_GLOBAL_LOCALE);
888*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERRNO(EINVAL);
889*8d67ca89SAndroid Build Coastguard Worker }
890*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wmempcpy)891*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wmempcpy) {
892*8d67ca89SAndroid Build Coastguard Worker #if !defined(ANDROID_HOST_MUSL)
893*8d67ca89SAndroid Build Coastguard Worker wchar_t dst[6];
894*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(&dst[4], wmempcpy(dst, L"hello", 4));
895*8d67ca89SAndroid Build Coastguard Worker #else
896*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "musl doesn't have wmempcpy";
897*8d67ca89SAndroid Build Coastguard Worker #endif
898*8d67ca89SAndroid Build Coastguard Worker }
899*8d67ca89SAndroid Build Coastguard Worker
900*8d67ca89SAndroid Build Coastguard Worker template <typename T>
901*8d67ca89SAndroid Build Coastguard Worker using WcsToFloatFn = T (*)(const wchar_t*, wchar_t**);
902*8d67ca89SAndroid Build Coastguard Worker
903*8d67ca89SAndroid Build Coastguard Worker template <typename T>
TestSingleWcsToFloat(WcsToFloatFn<T> fn,const wchar_t * str,T expected_value,ptrdiff_t expected_len)904*8d67ca89SAndroid Build Coastguard Worker void TestSingleWcsToFloat(WcsToFloatFn<T> fn, const wchar_t* str,
905*8d67ca89SAndroid Build Coastguard Worker T expected_value, ptrdiff_t expected_len) {
906*8d67ca89SAndroid Build Coastguard Worker wchar_t* p;
907*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(expected_value, fn(str, &p));
908*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(expected_len, p - str);
909*8d67ca89SAndroid Build Coastguard Worker }
910*8d67ca89SAndroid Build Coastguard Worker
911*8d67ca89SAndroid Build Coastguard Worker template <typename T>
TestWcsToFloat(WcsToFloatFn<T> fn)912*8d67ca89SAndroid Build Coastguard Worker void TestWcsToFloat(WcsToFloatFn<T> fn) {
913*8d67ca89SAndroid Build Coastguard Worker TestSingleWcsToFloat(fn, L"123", static_cast<T>(123.0L), 3);
914*8d67ca89SAndroid Build Coastguard Worker TestSingleWcsToFloat(fn, L"123#", static_cast<T>(123.0L), 3);
915*8d67ca89SAndroid Build Coastguard Worker TestSingleWcsToFloat(fn, L" 123 45", static_cast<T>(123.0L), 6);
916*8d67ca89SAndroid Build Coastguard Worker TestSingleWcsToFloat(fn, L"9.0", static_cast<T>(9.0L), 3);
917*8d67ca89SAndroid Build Coastguard Worker TestSingleWcsToFloat(fn, L"-9.0", static_cast<T>(-9.0L), 4);
918*8d67ca89SAndroid Build Coastguard Worker TestSingleWcsToFloat(fn, L" \t\v\f\r\n9.0", static_cast<T>(9.0L), 9);
919*8d67ca89SAndroid Build Coastguard Worker }
920*8d67ca89SAndroid Build Coastguard Worker
921*8d67ca89SAndroid Build Coastguard Worker template <typename T>
TestWcsToFloatHexFloats(WcsToFloatFn<T> fn)922*8d67ca89SAndroid Build Coastguard Worker void TestWcsToFloatHexFloats(WcsToFloatFn<T> fn) {
923*8d67ca89SAndroid Build Coastguard Worker TestSingleWcsToFloat(fn, L"0.9e1", static_cast<T>(9.0L), 5);
924*8d67ca89SAndroid Build Coastguard Worker TestSingleWcsToFloat(fn, L"0x1.2p3", static_cast<T>(9.0L), 7);
925*8d67ca89SAndroid Build Coastguard Worker TestSingleWcsToFloat(fn, L"+1e+100", static_cast<T>(1e100L), 7);
926*8d67ca89SAndroid Build Coastguard Worker TestSingleWcsToFloat(fn, L"0x10000.80", static_cast<T>(65536.50L), 10);
927*8d67ca89SAndroid Build Coastguard Worker }
928*8d67ca89SAndroid Build Coastguard Worker
929*8d67ca89SAndroid Build Coastguard Worker template <typename T>
TestWcsToFloatInfNan(WcsToFloatFn<T> fn)930*8d67ca89SAndroid Build Coastguard Worker void TestWcsToFloatInfNan(WcsToFloatFn<T> fn) {
931*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(isnan(fn(L"+nan", nullptr)));
932*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(isnan(fn(L"nan", nullptr)));
933*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(isnan(fn(L"-nan", nullptr)));
934*8d67ca89SAndroid Build Coastguard Worker
935*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(isnan(fn(L"+nan(0xff)", nullptr)));
936*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(isnan(fn(L"nan(0xff)", nullptr)));
937*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(isnan(fn(L"-nan(0xff)", nullptr)));
938*8d67ca89SAndroid Build Coastguard Worker
939*8d67ca89SAndroid Build Coastguard Worker wchar_t* p;
940*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(isnan(fn(L"+nanny", &p)));
941*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(L"ny", p);
942*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(isnan(fn(L"nanny", &p)));
943*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(L"ny", p);
944*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(isnan(fn(L"-nanny", &p)));
945*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(L"ny", p);
946*8d67ca89SAndroid Build Coastguard Worker
947*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, fn(L"muppet", &p));
948*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(L"muppet", p);
949*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, fn(L" muppet", &p));
950*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(L" muppet", p);
951*8d67ca89SAndroid Build Coastguard Worker
952*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"+inf", nullptr));
953*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"inf", nullptr));
954*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(-std::numeric_limits<T>::infinity(), fn(L"-inf", nullptr));
955*8d67ca89SAndroid Build Coastguard Worker
956*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"+infinity", nullptr));
957*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"infinity", nullptr));
958*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(-std::numeric_limits<T>::infinity(), fn(L"-infinity", nullptr));
959*8d67ca89SAndroid Build Coastguard Worker
960*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"+infinitude", &p));
961*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(L"initude", p);
962*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"infinitude", &p));
963*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(L"initude", p);
964*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(-std::numeric_limits<T>::infinity(), fn(L"-infinitude", &p));
965*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(L"initude", p);
966*8d67ca89SAndroid Build Coastguard Worker
967*8d67ca89SAndroid Build Coastguard Worker // Check case-insensitivity.
968*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"InFiNiTy", nullptr));
969*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(isnan(fn(L"NaN", nullptr)));
970*8d67ca89SAndroid Build Coastguard Worker }
971*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstof)972*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstof) {
973*8d67ca89SAndroid Build Coastguard Worker TestWcsToFloat(wcstof);
974*8d67ca89SAndroid Build Coastguard Worker }
975*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstof_hex_floats)976*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstof_hex_floats) {
977*8d67ca89SAndroid Build Coastguard Worker TestWcsToFloatHexFloats(wcstof);
978*8d67ca89SAndroid Build Coastguard Worker }
979*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstof_hex_inf_nan)980*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstof_hex_inf_nan) {
981*8d67ca89SAndroid Build Coastguard Worker TestWcsToFloatInfNan(wcstof);
982*8d67ca89SAndroid Build Coastguard Worker }
983*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstod)984*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstod) {
985*8d67ca89SAndroid Build Coastguard Worker TestWcsToFloat(wcstod);
986*8d67ca89SAndroid Build Coastguard Worker }
987*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstod_hex_floats)988*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstod_hex_floats) {
989*8d67ca89SAndroid Build Coastguard Worker TestWcsToFloatHexFloats(wcstod);
990*8d67ca89SAndroid Build Coastguard Worker }
991*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstod_hex_inf_nan)992*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstod_hex_inf_nan) {
993*8d67ca89SAndroid Build Coastguard Worker TestWcsToFloatInfNan(wcstod);
994*8d67ca89SAndroid Build Coastguard Worker }
995*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstold)996*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstold) {
997*8d67ca89SAndroid Build Coastguard Worker TestWcsToFloat(wcstold);
998*8d67ca89SAndroid Build Coastguard Worker }
999*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstold_hex_floats)1000*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstold_hex_floats) {
1001*8d67ca89SAndroid Build Coastguard Worker TestWcsToFloatHexFloats(wcstold);
1002*8d67ca89SAndroid Build Coastguard Worker }
1003*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstold_hex_inf_nan)1004*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstold_hex_inf_nan) {
1005*8d67ca89SAndroid Build Coastguard Worker TestWcsToFloatInfNan(wcstold);
1006*8d67ca89SAndroid Build Coastguard Worker }
1007*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstod_l)1008*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstod_l) {
1009*8d67ca89SAndroid Build Coastguard Worker #if !defined(ANDROID_HOST_MUSL)
1010*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(1.23, wcstod_l(L"1.23", nullptr, SAFE_LC_GLOBAL_LOCALE));
1011*8d67ca89SAndroid Build Coastguard Worker #else
1012*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "musl doesn't have wcstod_l";
1013*8d67ca89SAndroid Build Coastguard Worker #endif
1014*8d67ca89SAndroid Build Coastguard Worker }
1015*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstof_l)1016*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstof_l) {
1017*8d67ca89SAndroid Build Coastguard Worker #if !defined(ANDROID_HOST_MUSL)
1018*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(1.23f, wcstof_l(L"1.23", nullptr, SAFE_LC_GLOBAL_LOCALE));
1019*8d67ca89SAndroid Build Coastguard Worker #else
1020*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "musl doesn't have wcstof_l";
1021*8d67ca89SAndroid Build Coastguard Worker #endif
1022*8d67ca89SAndroid Build Coastguard Worker }
1023*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstol_l)1024*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstol_l) {
1025*8d67ca89SAndroid Build Coastguard Worker #if !defined(ANDROID_HOST_MUSL)
1026*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(123L, wcstol_l(L"123", nullptr, 10, SAFE_LC_GLOBAL_LOCALE));
1027*8d67ca89SAndroid Build Coastguard Worker #else
1028*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "musl doesn't have wcstol_l";
1029*8d67ca89SAndroid Build Coastguard Worker #endif
1030*8d67ca89SAndroid Build Coastguard Worker }
1031*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstold_l)1032*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstold_l) {
1033*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(1.23L, wcstold_l(L"1.23", nullptr, SAFE_LC_GLOBAL_LOCALE));
1034*8d67ca89SAndroid Build Coastguard Worker }
1035*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstoll_l)1036*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstoll_l) {
1037*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(123LL, wcstoll_l(L"123", nullptr, 10, SAFE_LC_GLOBAL_LOCALE));
1038*8d67ca89SAndroid Build Coastguard Worker }
1039*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstoul_l)1040*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstoul_l) {
1041*8d67ca89SAndroid Build Coastguard Worker #if !defined(ANDROID_HOST_MUSL)
1042*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(123UL, wcstoul_l(L"123", nullptr, 10, SAFE_LC_GLOBAL_LOCALE));
1043*8d67ca89SAndroid Build Coastguard Worker #else
1044*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "musl doesn't have wcstoul_l";
1045*8d67ca89SAndroid Build Coastguard Worker #endif
1046*8d67ca89SAndroid Build Coastguard Worker }
1047*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstoull_l)1048*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstoull_l) {
1049*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(123ULL, wcstoull_l(L"123", nullptr, 10, SAFE_LC_GLOBAL_LOCALE));
1050*8d67ca89SAndroid Build Coastguard Worker }
1051*8d67ca89SAndroid Build Coastguard Worker
AssertWcwidthRange(wchar_t begin,wchar_t end,int expected)1052*8d67ca89SAndroid Build Coastguard Worker static void AssertWcwidthRange(wchar_t begin, wchar_t end, int expected) {
1053*8d67ca89SAndroid Build Coastguard Worker for (wchar_t i = begin; i < end; ++i) {
1054*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(expected, wcwidth(i)) << static_cast<int>(i);
1055*8d67ca89SAndroid Build Coastguard Worker }
1056*8d67ca89SAndroid Build Coastguard Worker }
1057*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcwidth_NUL)1058*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcwidth_NUL) {
1059*8d67ca89SAndroid Build Coastguard Worker // NUL is defined to return 0 rather than -1, despite being a C0 control.
1060*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(0, wcwidth(0));
1061*8d67ca89SAndroid Build Coastguard Worker }
1062*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcwidth_ascii)1063*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcwidth_ascii) {
1064*8d67ca89SAndroid Build Coastguard Worker AssertWcwidthRange(0x20, 0x7f, 1); // Non-C0 non-DEL ASCII.
1065*8d67ca89SAndroid Build Coastguard Worker }
1066*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcwidth_controls)1067*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcwidth_controls) {
1068*8d67ca89SAndroid Build Coastguard Worker AssertWcwidthRange(0x01, 0x20, -1); // C0 controls.
1069*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(-1, wcwidth(0x7f)); // DEL.
1070*8d67ca89SAndroid Build Coastguard Worker AssertWcwidthRange(0x80, 0xa0, -1); // C1 controls.
1071*8d67ca89SAndroid Build Coastguard Worker }
1072*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcwidth_non_spacing_and_enclosing_marks_and_format)1073*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcwidth_non_spacing_and_enclosing_marks_and_format) {
1074*8d67ca89SAndroid Build Coastguard Worker if (!have_dl()) return;
1075*8d67ca89SAndroid Build Coastguard Worker
1076*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(0, wcwidth(0x0300)); // Combining grave.
1077*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(0, wcwidth(0x20dd)); // Combining enclosing circle.
1078*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(0, wcwidth(0x200b)); // Zero width space.
1079*8d67ca89SAndroid Build Coastguard Worker }
1080*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcwidth_non_spacing_special_cases)1081*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcwidth_non_spacing_special_cases) {
1082*8d67ca89SAndroid Build Coastguard Worker if (!have_dl()) return;
1083*8d67ca89SAndroid Build Coastguard Worker
1084*8d67ca89SAndroid Build Coastguard Worker // U+00AD is a soft hyphen, which normally shouldn't be rendered at all.
1085*8d67ca89SAndroid Build Coastguard Worker // I think the assumption here is that you elide the soft hyphen character
1086*8d67ca89SAndroid Build Coastguard Worker // completely in that case, and never call wcwidth() if you don't want to
1087*8d67ca89SAndroid Build Coastguard Worker // render it as an actual hyphen. Whereas if you do want to render it,
1088*8d67ca89SAndroid Build Coastguard Worker // you call wcwidth(), and 1 is the right answer. This is what Markus Kuhn's
1089*8d67ca89SAndroid Build Coastguard Worker // original https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c did,
1090*8d67ca89SAndroid Build Coastguard Worker // and glibc and iOS do the same.
1091*8d67ca89SAndroid Build Coastguard Worker // See also: https://en.wikipedia.org/wiki/Soft_hyphen#Text_to_be_formatted_by_the_recipient
1092*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(1, wcwidth(0x00ad)); // Soft hyphen (SHY).
1093*8d67ca89SAndroid Build Coastguard Worker
1094*8d67ca89SAndroid Build Coastguard Worker // U+115F is the Hangeul choseong filler (for a degenerate composed
1095*8d67ca89SAndroid Build Coastguard Worker // character missing an initial consonant (as opposed to one with a
1096*8d67ca89SAndroid Build Coastguard Worker // leading ieung). Since the code points for combining jungseong (medial
1097*8d67ca89SAndroid Build Coastguard Worker // vowels) and jongseong (trailing consonants) have width 0, the choseong
1098*8d67ca89SAndroid Build Coastguard Worker // (initial consonant) has width 2 to cover the entire syllable. So unless
1099*8d67ca89SAndroid Build Coastguard Worker // U+115f has width 2, a degenerate composed "syllable" without an initial
1100*8d67ca89SAndroid Build Coastguard Worker // consonant or ieung would have a total width of 0, which is silly.
1101*8d67ca89SAndroid Build Coastguard Worker // The following sequence is effectively "약" without the leading ieung...
1102*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(2, wcwidth(0x115f)); // Hangeul choseong filler.
1103*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(0, wcwidth(0x1163)); // Hangeul jungseong "ya".
1104*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(0, wcwidth(0x11a8)); // Hangeul jongseong "kiyeok".
1105*8d67ca89SAndroid Build Coastguard Worker
1106*8d67ca89SAndroid Build Coastguard Worker // U+1160, the jungseong filler, has width 0 because it must have been
1107*8d67ca89SAndroid Build Coastguard Worker // preceded by either a choseong or choseong filler.
1108*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(0, wcwidth(0x1160));
1109*8d67ca89SAndroid Build Coastguard Worker }
1110*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcwidth_cjk)1111*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcwidth_cjk) {
1112*8d67ca89SAndroid Build Coastguard Worker if (!have_dl()) return;
1113*8d67ca89SAndroid Build Coastguard Worker
1114*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(2, wcwidth(0x4e00)); // Start of CJK unified block.
1115*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(2, wcwidth(0x9fff)); // End of CJK unified block.
1116*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(2, wcwidth(0x3400)); // Start of CJK extension A block.
1117*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(2, wcwidth(0x4dbf)); // End of CJK extension A block.
1118*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(2, wcwidth(0x20000)); // Start of CJK extension B block.
1119*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(2, wcwidth(0x2a6df)); // End of CJK extension B block.
1120*8d67ca89SAndroid Build Coastguard Worker }
1121*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcwidth_korean_combining_jamo)1122*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcwidth_korean_combining_jamo) {
1123*8d67ca89SAndroid Build Coastguard Worker if (!have_dl()) return;
1124*8d67ca89SAndroid Build Coastguard Worker
1125*8d67ca89SAndroid Build Coastguard Worker AssertWcwidthRange(0x1160, 0x1200, 0); // Original range.
1126*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(0, wcwidth(0xd7b0)); // Newer.
1127*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(0, wcwidth(0xd7cb));
1128*8d67ca89SAndroid Build Coastguard Worker }
1129*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcwidth_korean_jeongeul_syllables)1130*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcwidth_korean_jeongeul_syllables) {
1131*8d67ca89SAndroid Build Coastguard Worker if (!have_dl()) return;
1132*8d67ca89SAndroid Build Coastguard Worker
1133*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(2, wcwidth(0xac00)); // Start of block.
1134*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(2, wcwidth(0xd7a3)); // End of defined code points as of Unicode 15.
1135*8d67ca89SAndroid Build Coastguard Worker
1136*8d67ca89SAndroid Build Coastguard Worker // Undefined characters at the end of the block currently have width 1,
1137*8d67ca89SAndroid Build Coastguard Worker // but since they're undefined, we don't test that.
1138*8d67ca89SAndroid Build Coastguard Worker }
1139*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcwidth_kana)1140*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcwidth_kana) {
1141*8d67ca89SAndroid Build Coastguard Worker if (!have_dl()) return;
1142*8d67ca89SAndroid Build Coastguard Worker
1143*8d67ca89SAndroid Build Coastguard Worker // Hiragana (most, not undefined).
1144*8d67ca89SAndroid Build Coastguard Worker AssertWcwidthRange(0x3041, 0x3097, 2);
1145*8d67ca89SAndroid Build Coastguard Worker // Katakana.
1146*8d67ca89SAndroid Build Coastguard Worker AssertWcwidthRange(0x30a0, 0x3100, 2);
1147*8d67ca89SAndroid Build Coastguard Worker }
1148*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcwidth_circled_two_digit_cjk)1149*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcwidth_circled_two_digit_cjk) {
1150*8d67ca89SAndroid Build Coastguard Worker if (!have_dl()) return;
1151*8d67ca89SAndroid Build Coastguard Worker
1152*8d67ca89SAndroid Build Coastguard Worker // Circled two-digit CJK "speed sign" numbers are wide,
1153*8d67ca89SAndroid Build Coastguard Worker // though EastAsianWidth is ambiguous.
1154*8d67ca89SAndroid Build Coastguard Worker AssertWcwidthRange(0x3248, 0x3250, 2);
1155*8d67ca89SAndroid Build Coastguard Worker }
1156*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcwidth_hexagrams)1157*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcwidth_hexagrams) {
1158*8d67ca89SAndroid Build Coastguard Worker if (!have_dl()) return;
1159*8d67ca89SAndroid Build Coastguard Worker
1160*8d67ca89SAndroid Build Coastguard Worker // Hexagrams are wide, though EastAsianWidth is neutral.
1161*8d67ca89SAndroid Build Coastguard Worker AssertWcwidthRange(0x4dc0, 0x4e00, 2);
1162*8d67ca89SAndroid Build Coastguard Worker }
1163*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcwidth_default_ignorables)1164*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcwidth_default_ignorables) {
1165*8d67ca89SAndroid Build Coastguard Worker if (!have_dl()) return;
1166*8d67ca89SAndroid Build Coastguard Worker
1167*8d67ca89SAndroid Build Coastguard Worker AssertWcwidthRange(0xfff0, 0xfff8, 0); // Unassigned by default ignorable.
1168*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(0, wcwidth(0xe0000)); // ...through 0xe0fff.
1169*8d67ca89SAndroid Build Coastguard Worker }
1170*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcwidth_hangeul_compatibility_jamo)1171*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcwidth_hangeul_compatibility_jamo) {
1172*8d67ca89SAndroid Build Coastguard Worker if (!have_dl()) return;
1173*8d67ca89SAndroid Build Coastguard Worker
1174*8d67ca89SAndroid Build Coastguard Worker // These are actually the *compatibility* jamo code points, *not* the regular
1175*8d67ca89SAndroid Build Coastguard Worker // jamo code points (U+1100-U+11FF) using a jungseong filler. If you use the
1176*8d67ca89SAndroid Build Coastguard Worker // Android IME to type any of these, you get these code points.
1177*8d67ca89SAndroid Build Coastguard Worker
1178*8d67ca89SAndroid Build Coastguard Worker // (Half of) the Korean "crying" emoticon "ㅠㅠ".
1179*8d67ca89SAndroid Build Coastguard Worker // Actually U+3160 "Hangeul Letter Yu" from Hangeul Compatibility Jamo.
1180*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(2, wcwidth(L'ㅠ'));
1181*8d67ca89SAndroid Build Coastguard Worker // The two halves of the Korean internet shorthand "ㄱㅅ" (short for 감사).
1182*8d67ca89SAndroid Build Coastguard Worker // Actually U+3131 "Hangeul Letter Kiyeok" and U+3145 "Hangeul Letter Sios"
1183*8d67ca89SAndroid Build Coastguard Worker // from Hangeul Compatibility Jamo.
1184*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(2, wcwidth(L'ㄱ'));
1185*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(2, wcwidth(L'ㅅ'));
1186*8d67ca89SAndroid Build Coastguard Worker }
1187*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcswidth)1188*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcswidth) {
1189*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(2, wcswidth(L"abc", 2));
1190*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(2, wcswidth(L"ab\t", 2));
1191*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(-1, wcswidth(L"a\tb", 2));
1192*8d67ca89SAndroid Build Coastguard Worker }
1193*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcslcpy)1194*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcslcpy) {
1195*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
1196*8d67ca89SAndroid Build Coastguard Worker wchar_t dst[32];
1197*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(11U, wcslcpy(dst, L"hello world", 3));
1198*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(L"he", dst);
1199*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(11U, wcslcpy(dst, L"hello world", 32));
1200*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(L"hello world", dst);
1201*8d67ca89SAndroid Build Coastguard Worker #else
1202*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "no wcslcpy in glibc";
1203*8d67ca89SAndroid Build Coastguard Worker #endif
1204*8d67ca89SAndroid Build Coastguard Worker }
1205*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcscat)1206*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcscat) {
1207*8d67ca89SAndroid Build Coastguard Worker wchar_t dst[32];
1208*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(dst, wcscat(dst, L"hello"));
1209*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(dst, L"hello");
1210*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(dst, wcscat(dst, L" world"));
1211*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(dst, L"hello world");
1212*8d67ca89SAndroid Build Coastguard Worker }
1213*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcscpy)1214*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcscpy) {
1215*8d67ca89SAndroid Build Coastguard Worker wchar_t dst[32];
1216*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(dst, wcscpy(dst, L"hello"));
1217*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(dst, L"hello");
1218*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(dst, wcscpy(dst, L"world"));
1219*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(dst, L"world");
1220*8d67ca89SAndroid Build Coastguard Worker }
1221*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcscasecmp)1222*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcscasecmp) {
1223*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, wcscasecmp(L"hello", L"HELLO"));
1224*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(wcscasecmp(L"hello1", L"HELLO2") < 0);
1225*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(wcscasecmp(L"hello2", L"HELLO1") > 0);
1226*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(wcscasecmp(L"hello", L"HELL") > 0);
1227*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(wcscasecmp(L"hell", L"HELLO") < 0);
1228*8d67ca89SAndroid Build Coastguard Worker }
1229*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcscspn)1230*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcscspn) {
1231*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0U, wcscspn(L"hello world", L"abcdefghijklmnopqrstuvwxyz"));
1232*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(5U, wcscspn(L"hello world", L" "));
1233*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(11U, wcscspn(L"hello world", L"!"));
1234*8d67ca89SAndroid Build Coastguard Worker }
1235*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcsspn)1236*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcsspn) {
1237*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0U, wcsspn(L"hello world", L"!"));
1238*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(5U, wcsspn(L"hello world", L"abcdefghijklmnopqrstuvwxyz"));
1239*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(11U, wcsspn(L"hello world", L"abcdefghijklmnopqrstuvwxyz "));
1240*8d67ca89SAndroid Build Coastguard Worker }
1241*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcsdup)1242*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcsdup) {
1243*8d67ca89SAndroid Build Coastguard Worker wchar_t* s = wcsdup(L"hello");
1244*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(s, L"hello");
1245*8d67ca89SAndroid Build Coastguard Worker free(s);
1246*8d67ca89SAndroid Build Coastguard Worker }
1247*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcslcat)1248*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcslcat) {
1249*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
1250*8d67ca89SAndroid Build Coastguard Worker wchar_t dst[4] = {};
1251*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(1U, wcslcat(dst, L"a", 4));
1252*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(7U, wcslcat(dst, L"bcdefg", 4));
1253*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(dst, L"abc");
1254*8d67ca89SAndroid Build Coastguard Worker #else
1255*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "no wcslcpy in glibc";
1256*8d67ca89SAndroid Build Coastguard Worker #endif
1257*8d67ca89SAndroid Build Coastguard Worker }
1258*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcsncasecmp)1259*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcsncasecmp) {
1260*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, wcsncasecmp(L"foo", L"bar", 0));
1261*8d67ca89SAndroid Build Coastguard Worker
1262*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, wcsncasecmp(L"hello1", L"HELLO2", 5));
1263*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(wcsncasecmp(L"hello1", L"HELLO2", 6) < 0);
1264*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(wcsncasecmp(L"hello2", L"HELLO1", 6) > 0);
1265*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(wcsncasecmp(L"hello", L"HELL", 5) > 0);
1266*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(wcsncasecmp(L"hell", L"HELLO", 5) < 0);
1267*8d67ca89SAndroid Build Coastguard Worker }
1268*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcsncat)1269*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcsncat) {
1270*8d67ca89SAndroid Build Coastguard Worker wchar_t dst[32];
1271*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(dst, wcsncat(dst, L"hello, world!", 5));
1272*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(dst, L"hello");
1273*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(dst, wcsncat(dst, L"hello, world!", 0));
1274*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(dst, L"hello");
1275*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(dst, wcsncat(dst, L", world!", 8));
1276*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(dst, L"hello, world!");
1277*8d67ca89SAndroid Build Coastguard Worker }
1278*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcsncmp)1279*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcsncmp) {
1280*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, wcsncmp(L"foo", L"bar", 0));
1281*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, wcsncmp(L"aaaa", L"aaab", 3));
1282*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(wcsncmp(L"aaaa", L"aaab", 4) < 0);
1283*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(wcsncmp(L"aaab", L"aaaa", 4) > 0);
1284*8d67ca89SAndroid Build Coastguard Worker }
1285*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcsnlen)1286*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcsnlen) {
1287*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(2U, wcsnlen(L"hello", 2));
1288*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(5U, wcsnlen(L"hello", 5));
1289*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(5U, wcsnlen(L"hello", 666));
1290*8d67ca89SAndroid Build Coastguard Worker }
1291*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcspbrk)1292*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcspbrk) {
1293*8d67ca89SAndroid Build Coastguard Worker const wchar_t* s = L"hello, world!";
1294*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(nullptr, wcspbrk(s, L"-"));
1295*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(s, wcspbrk(s, L"abch"));
1296*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(s + 2, wcspbrk(s, L"l"));
1297*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(s + 5, wcspbrk(s, L",. !"));
1298*8d67ca89SAndroid Build Coastguard Worker }
1299*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wcstok)1300*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wcstok) {
1301*8d67ca89SAndroid Build Coastguard Worker wchar_t s[] = L"this is\ta\nstring";
1302*8d67ca89SAndroid Build Coastguard Worker wchar_t* p;
1303*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(s, wcstok(s, L"\t\n ", &p));
1304*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(s, L"this");
1305*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(p, L"is\ta\nstring");
1306*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(s + 5, wcstok(nullptr, L"\t\n ", &p));
1307*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(s + 5, L"is");
1308*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(p, L"a\nstring");
1309*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(s + 8, wcstok(nullptr, L"\t\n ", &p));
1310*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(s + 8, L"a");
1311*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(p, L"string");
1312*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(s + 10, wcstok(nullptr, L"\t\n ", &p));
1313*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(s + 10, L"string");
1314*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(nullptr, p);
1315*8d67ca89SAndroid Build Coastguard Worker }
1316*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wmemchr)1317*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wmemchr) {
1318*8d67ca89SAndroid Build Coastguard Worker const wchar_t* s = L"hello, world!";
1319*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(s, wmemchr(s, L'h', 13));
1320*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(s + 5, wmemchr(s, L',', 13));
1321*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(s + 12, wmemchr(s, L'!', 13));
1322*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(nullptr, wmemchr(s, L'a', 13));
1323*8d67ca89SAndroid Build Coastguard Worker }
1324*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wmemcmp)1325*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wmemcmp) {
1326*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, wmemcmp(L"aaaa", L"aaab", 3));
1327*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(wmemcmp(L"aaaa", L"aaab", 4) < 0);
1328*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(wmemcmp(L"aaab", L"aaaa", 4) > 0);
1329*8d67ca89SAndroid Build Coastguard Worker }
1330*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wmemcpy)1331*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wmemcpy) {
1332*8d67ca89SAndroid Build Coastguard Worker wchar_t dst[32] = {};
1333*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(dst, wmemcpy(dst, L"hello", 5));
1334*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(dst, L"hello");
1335*8d67ca89SAndroid Build Coastguard Worker }
1336*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wmemmove)1337*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wmemmove) {
1338*8d67ca89SAndroid Build Coastguard Worker wchar_t dst[32] = {};
1339*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(dst, wmemmove(dst, L"hello", 5));
1340*8d67ca89SAndroid Build Coastguard Worker ASSERT_STREQ(dst, L"hello");
1341*8d67ca89SAndroid Build Coastguard Worker }
1342*8d67ca89SAndroid Build Coastguard Worker
TEST(wchar,wmemset)1343*8d67ca89SAndroid Build Coastguard Worker TEST(wchar, wmemset) {
1344*8d67ca89SAndroid Build Coastguard Worker wchar_t dst[4] = {};
1345*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(dst, wmemset(dst, 0x12345678, 3));
1346*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(dst[0], wchar_t(0x12345678));
1347*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(dst[1], wchar_t(0x12345678));
1348*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(dst[2], wchar_t(0x12345678));
1349*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(dst[3], wchar_t(0));
1350*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(dst, wmemset(dst, L'y', 0));
1351*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(dst[0], wchar_t(0x12345678));
1352*8d67ca89SAndroid Build Coastguard Worker }
1353