1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <wctype.h>
18
19 #include <dlfcn.h>
20
21 #include <gtest/gtest.h>
22
23 #include "utils.h"
24
25 class UtfLocale {
26 public:
UtfLocale()27 UtfLocale() : l(newlocale(LC_ALL, "C.UTF-8", nullptr)) {}
~UtfLocale()28 ~UtfLocale() { freelocale(l); }
29 locale_t l;
30 };
31
TestIsWideFn(int fn (wint_t),int fn_l (wint_t,locale_t),const wchar_t * trues,const wchar_t * falses)32 static void TestIsWideFn(int fn(wint_t),
33 int fn_l(wint_t, locale_t),
34 const wchar_t* trues,
35 const wchar_t* falses) {
36 UtfLocale l;
37 for (const wchar_t* p = trues; *p; ++p) {
38 const wchar_t val_ch = *p;
39 const int val_int = static_cast<int>(val_ch);
40
41 EXPECT_TRUE(fn(val_ch)) << val_int;
42 EXPECT_TRUE(fn_l(val_ch, l.l)) << val_int;
43 }
44 for (const wchar_t* p = falses; *p; ++p) {
45 const wchar_t val_ch = *p;
46 const int val_int = static_cast<int>(val_ch);
47
48 EXPECT_FALSE(fn(val_ch)) << val_int;
49 EXPECT_FALSE(fn_l(val_ch, l.l)) << val_int;
50 }
51 }
52
TEST(wctype,iswalnum)53 TEST(wctype, iswalnum) {
54 TestIsWideFn(iswalnum, iswalnum_l, L"1aAÇçΔδ", L"! \b");
55 }
56
TEST(wctype,iswalpha)57 TEST(wctype, iswalpha) {
58 TestIsWideFn(iswalpha, iswalpha_l, L"aAÇçΔδ", L"1! \b");
59 }
60
TEST(wctype,iswblank)61 TEST(wctype, iswblank) {
62 TestIsWideFn(iswblank, iswblank_l, L" \t", L"1aA!\bÇçΔδ");
63 }
64
TEST(wctype,iswcntrl)65 TEST(wctype, iswcntrl) {
66 TestIsWideFn(iswcntrl, iswcntrl_l, L"\b\u009f", L"1aA! ÇçΔδ");
67 }
68
TEST(wctype,iswdigit)69 TEST(wctype, iswdigit) {
70 TestIsWideFn(iswdigit, iswdigit_l, L"1", L"aA! \bÇçΔδ");
71 }
72
TEST(wctype,iswgraph)73 TEST(wctype, iswgraph) {
74 TestIsWideFn(iswgraph, iswgraph_l, L"1aA!ÇçΔδ", L" \b");
75 }
76
TEST(wctype,iswlower)77 TEST(wctype, iswlower) {
78 TestIsWideFn(iswlower, iswlower_l, L"açδ", L"1A! \bÇΔ");
79 }
80
TEST(wctype,iswprint)81 TEST(wctype, iswprint) {
82 TestIsWideFn(iswprint, iswprint_l, L"1aA! ÇçΔδ", L"\b");
83 }
84
TEST(wctype,iswpunct)85 TEST(wctype, iswpunct) {
86 TestIsWideFn(iswpunct, iswpunct_l, L"!", L"1aA \bÇçΔδ");
87 }
88
TEST(wctype,iswspace)89 TEST(wctype, iswspace) {
90 TestIsWideFn(iswspace, iswspace_l, L" \f\t", L"1aA!\bÇçΔδ");
91 }
92
TEST(wctype,iswupper)93 TEST(wctype, iswupper) {
94 TestIsWideFn(iswupper, iswupper_l, L"AÇΔ", L"1a! \bçδ");
95 }
96
TEST(wctype,iswxdigit)97 TEST(wctype, iswxdigit) {
98 TestIsWideFn(iswxdigit, iswxdigit_l, L"01aA", L"xg! \b");
99 }
100
TEST(wctype,towlower)101 TEST(wctype, towlower) {
102 EXPECT_EQ(WEOF, towlower(WEOF));
103 EXPECT_EQ(wint_t('!'), towlower(L'!'));
104 EXPECT_EQ(wint_t('a'), towlower(L'a'));
105 EXPECT_EQ(wint_t('a'), towlower(L'A'));
106 EXPECT_EQ(wint_t('z'), towlower(L'z'));
107 EXPECT_EQ(wint_t('z'), towlower(L'Z'));
108 EXPECT_EQ(wint_t(L'ç'), towlower(L'ç'));
109 EXPECT_EQ(wint_t(L'ç'), towlower(L'Ç'));
110 EXPECT_EQ(wint_t(L'δ'), towlower(L'δ'));
111 EXPECT_EQ(wint_t(L'δ'), towlower(L'Δ'));
112 }
113
TEST(wctype,towlower_l)114 TEST(wctype, towlower_l) {
115 UtfLocale l;
116 EXPECT_EQ(WEOF, towlower(WEOF));
117 EXPECT_EQ(wint_t('!'), towlower_l(L'!', l.l));
118 EXPECT_EQ(wint_t('a'), towlower_l(L'a', l.l));
119 EXPECT_EQ(wint_t('a'), towlower_l(L'A', l.l));
120 EXPECT_EQ(wint_t('z'), towlower_l(L'z', l.l));
121 EXPECT_EQ(wint_t('z'), towlower_l(L'Z', l.l));
122 EXPECT_EQ(wint_t(L'ç'), towlower_l(L'ç', l.l));
123 EXPECT_EQ(wint_t(L'ç'), towlower_l(L'Ç', l.l));
124 EXPECT_EQ(wint_t(L'δ'), towlower_l(L'δ', l.l));
125 EXPECT_EQ(wint_t(L'δ'), towlower_l(L'Δ', l.l));
126 }
127
TEST(wctype,towupper)128 TEST(wctype, towupper) {
129 EXPECT_EQ(WEOF, towupper(WEOF));
130 EXPECT_EQ(wint_t('!'), towupper(L'!'));
131 EXPECT_EQ(wint_t('A'), towupper(L'a'));
132 EXPECT_EQ(wint_t('A'), towupper(L'A'));
133 EXPECT_EQ(wint_t('Z'), towupper(L'z'));
134 EXPECT_EQ(wint_t('Z'), towupper(L'Z'));
135 EXPECT_EQ(wint_t(L'Ç'), towupper(L'ç'));
136 EXPECT_EQ(wint_t(L'Ç'), towupper(L'Ç'));
137 EXPECT_EQ(wint_t(L'Δ'), towupper(L'δ'));
138 EXPECT_EQ(wint_t(L'Δ'), towupper(L'Δ'));
139 }
140
TEST(wctype,towupper_l)141 TEST(wctype, towupper_l) {
142 UtfLocale l;
143 EXPECT_EQ(WEOF, towupper_l(WEOF, l.l));
144 EXPECT_EQ(wint_t('!'), towupper_l(L'!', l.l));
145 EXPECT_EQ(wint_t('A'), towupper_l(L'a', l.l));
146 EXPECT_EQ(wint_t('A'), towupper_l(L'A', l.l));
147 EXPECT_EQ(wint_t('Z'), towupper_l(L'z', l.l));
148 EXPECT_EQ(wint_t('Z'), towupper_l(L'Z', l.l));
149 EXPECT_EQ(wint_t(L'Ç'), towupper_l(L'ç', l.l));
150 EXPECT_EQ(wint_t(L'Ç'), towupper_l(L'Ç', l.l));
151 EXPECT_EQ(wint_t(L'Δ'), towupper_l(L'δ', l.l));
152 EXPECT_EQ(wint_t(L'Δ'), towupper_l(L'Δ', l.l));
153 }
154
TEST(wctype,wctype)155 TEST(wctype, wctype) {
156 EXPECT_TRUE(wctype("alnum") != 0);
157 EXPECT_TRUE(wctype("alpha") != 0);
158 EXPECT_TRUE(wctype("blank") != 0);
159 EXPECT_TRUE(wctype("cntrl") != 0);
160 EXPECT_TRUE(wctype("digit") != 0);
161 EXPECT_TRUE(wctype("graph") != 0);
162 EXPECT_TRUE(wctype("lower") != 0);
163 EXPECT_TRUE(wctype("print") != 0);
164 EXPECT_TRUE(wctype("punct") != 0);
165 EXPECT_TRUE(wctype("space") != 0);
166 EXPECT_TRUE(wctype("upper") != 0);
167 EXPECT_TRUE(wctype("xdigit") != 0);
168
169 EXPECT_TRUE(wctype("monkeys") == 0);
170 }
171
TEST(wctype,wctype_l)172 TEST(wctype, wctype_l) {
173 UtfLocale l;
174 EXPECT_TRUE(wctype_l("alnum", l.l) != 0);
175 EXPECT_TRUE(wctype_l("alpha", l.l) != 0);
176 EXPECT_TRUE(wctype_l("blank", l.l) != 0);
177 EXPECT_TRUE(wctype_l("cntrl", l.l) != 0);
178 EXPECT_TRUE(wctype_l("digit", l.l) != 0);
179 EXPECT_TRUE(wctype_l("graph", l.l) != 0);
180 EXPECT_TRUE(wctype_l("lower", l.l) != 0);
181 EXPECT_TRUE(wctype_l("print", l.l) != 0);
182 EXPECT_TRUE(wctype_l("punct", l.l) != 0);
183 EXPECT_TRUE(wctype_l("space", l.l) != 0);
184 EXPECT_TRUE(wctype_l("upper", l.l) != 0);
185 EXPECT_TRUE(wctype_l("xdigit", l.l) != 0);
186
187 EXPECT_TRUE(wctype_l("monkeys", l.l) == 0);
188 }
189
TEST(wctype,iswctype)190 TEST(wctype, iswctype) {
191 EXPECT_TRUE(iswctype(L'a', wctype("alnum")));
192 EXPECT_TRUE(iswctype(L'1', wctype("alnum")));
193 EXPECT_FALSE(iswctype(L' ', wctype("alnum")));
194
195 EXPECT_EQ(0, iswctype(WEOF, wctype("alnum")));
196 }
197
TEST(wctype,iswctype_l)198 TEST(wctype, iswctype_l) {
199 UtfLocale l;
200 EXPECT_TRUE(iswctype_l(L'a', wctype_l("alnum", l.l), l.l));
201 EXPECT_TRUE(iswctype_l(L'1', wctype_l("alnum", l.l), l.l));
202 EXPECT_FALSE(iswctype_l(L' ', wctype_l("alnum", l.l), l.l));
203
204 EXPECT_EQ(0, iswctype_l(WEOF, wctype_l("alnum", l.l), l.l));
205 }
206
TEST(wctype,wctrans)207 TEST(wctype, wctrans) {
208 EXPECT_TRUE(wctrans("tolower") != nullptr);
209 EXPECT_TRUE(wctrans("toupper") != nullptr);
210
211 errno = 0;
212 EXPECT_TRUE(wctrans("monkeys") == nullptr);
213 #if defined(__BIONIC__)
214 // Android/FreeBSD/iOS set errno, but musl/glibc don't.
215 EXPECT_ERRNO(EINVAL);
216 #endif
217 }
218
TEST(wctype,wctrans_l)219 TEST(wctype, wctrans_l) {
220 UtfLocale l;
221 EXPECT_TRUE(wctrans_l("tolower", l.l) != nullptr);
222 EXPECT_TRUE(wctrans_l("toupper", l.l) != nullptr);
223
224 errno = 0;
225 EXPECT_TRUE(wctrans_l("monkeys", l.l) == nullptr);
226 #if defined(__BIONIC__)
227 // Android/FreeBSD/iOS set errno, but musl/glibc don't.
228 EXPECT_ERRNO(EINVAL);
229 #endif
230 }
231
TEST(wctype,towctrans)232 TEST(wctype, towctrans) {
233 wctrans_t lower = wctrans("tolower");
234 EXPECT_EQ(wint_t('a'), towctrans(L'A', lower));
235 EXPECT_EQ(WEOF, towctrans(WEOF, lower));
236
237 wctrans_t upper = wctrans("toupper");
238 EXPECT_EQ(wint_t('A'), towctrans(L'a', upper));
239 EXPECT_EQ(WEOF, towctrans(WEOF, upper));
240
241 wctrans_t invalid = wctrans("monkeys");
242 errno = 0;
243 EXPECT_EQ(wint_t('a'), towctrans(L'a', invalid));
244 #if defined(__BIONIC__)
245 // Android/FreeBSD/iOS set errno, but musl/glibc don't.
246 EXPECT_ERRNO(EINVAL);
247 #endif
248 }
249
TEST(wctype,towctrans_l)250 TEST(wctype, towctrans_l) {
251 UtfLocale l;
252 wctrans_t lower = wctrans_l("tolower", l.l);
253 EXPECT_EQ(wint_t('a'), towctrans_l(L'A', lower, l.l));
254 EXPECT_EQ(WEOF, towctrans_l(WEOF, lower, l.l));
255
256 wctrans_t upper = wctrans_l("toupper", l.l);
257 EXPECT_EQ(wint_t('A'), towctrans_l(L'a', upper, l.l));
258 EXPECT_EQ(WEOF, towctrans_l(WEOF, upper, l.l));
259
260 wctrans_t invalid = wctrans_l("monkeys", l.l);
261 errno = 0;
262 EXPECT_EQ(wint_t('a'), towctrans_l(L'a', invalid, l.l));
263 #if defined(__BIONIC__)
264 // Android/FreeBSD/iOS set errno, but musl/glibc don't.
265 EXPECT_ERRNO(EINVAL);
266 #endif
267 }
268