xref: /aosp_15_r20/bionic/tests/locale_test.cpp (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker  * Copyright (C) 2014 The Android Open Source Project
3*8d67ca89SAndroid Build Coastguard Worker  *
4*8d67ca89SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*8d67ca89SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*8d67ca89SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*8d67ca89SAndroid Build Coastguard Worker  *
8*8d67ca89SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*8d67ca89SAndroid Build Coastguard Worker  *
10*8d67ca89SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*8d67ca89SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*8d67ca89SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8d67ca89SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*8d67ca89SAndroid Build Coastguard Worker  * limitations under the License.
15*8d67ca89SAndroid Build Coastguard Worker  */
16*8d67ca89SAndroid Build Coastguard Worker 
17*8d67ca89SAndroid Build Coastguard Worker #include <gtest/gtest.h>
18*8d67ca89SAndroid Build Coastguard Worker 
19*8d67ca89SAndroid Build Coastguard Worker #include <errno.h>
20*8d67ca89SAndroid Build Coastguard Worker #include <limits.h>
21*8d67ca89SAndroid Build Coastguard Worker #include <locale.h>
22*8d67ca89SAndroid Build Coastguard Worker 
23*8d67ca89SAndroid Build Coastguard Worker #include "utils.h"
24*8d67ca89SAndroid Build Coastguard Worker 
TEST(locale,localeconv)25*8d67ca89SAndroid Build Coastguard Worker TEST(locale, localeconv) {
26*8d67ca89SAndroid Build Coastguard Worker   EXPECT_STREQ(".", localeconv()->decimal_point);
27*8d67ca89SAndroid Build Coastguard Worker   EXPECT_STREQ("", localeconv()->thousands_sep);
28*8d67ca89SAndroid Build Coastguard Worker   EXPECT_STREQ("", localeconv()->grouping);
29*8d67ca89SAndroid Build Coastguard Worker   EXPECT_STREQ("", localeconv()->int_curr_symbol);
30*8d67ca89SAndroid Build Coastguard Worker   EXPECT_STREQ("", localeconv()->currency_symbol);
31*8d67ca89SAndroid Build Coastguard Worker   EXPECT_STREQ("", localeconv()->mon_decimal_point);
32*8d67ca89SAndroid Build Coastguard Worker   EXPECT_STREQ("", localeconv()->mon_thousands_sep);
33*8d67ca89SAndroid Build Coastguard Worker   EXPECT_STREQ("", localeconv()->mon_grouping);
34*8d67ca89SAndroid Build Coastguard Worker   EXPECT_STREQ("", localeconv()->positive_sign);
35*8d67ca89SAndroid Build Coastguard Worker   EXPECT_STREQ("", localeconv()->negative_sign);
36*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(CHAR_MAX, localeconv()->int_frac_digits);
37*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(CHAR_MAX, localeconv()->frac_digits);
38*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(CHAR_MAX, localeconv()->p_cs_precedes);
39*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(CHAR_MAX, localeconv()->p_sep_by_space);
40*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(CHAR_MAX, localeconv()->n_cs_precedes);
41*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(CHAR_MAX, localeconv()->n_sep_by_space);
42*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(CHAR_MAX, localeconv()->p_sign_posn);
43*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(CHAR_MAX, localeconv()->n_sign_posn);
44*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(CHAR_MAX, localeconv()->int_p_cs_precedes);
45*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(CHAR_MAX, localeconv()->int_p_sep_by_space);
46*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(CHAR_MAX, localeconv()->int_n_cs_precedes);
47*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(CHAR_MAX, localeconv()->int_n_sep_by_space);
48*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(CHAR_MAX, localeconv()->int_p_sign_posn);
49*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(CHAR_MAX, localeconv()->int_n_sign_posn);
50*8d67ca89SAndroid Build Coastguard Worker }
51*8d67ca89SAndroid Build Coastguard Worker 
TEST(locale,setlocale)52*8d67ca89SAndroid Build Coastguard Worker TEST(locale, setlocale) {
53*8d67ca89SAndroid Build Coastguard Worker   EXPECT_STREQ("C.UTF-8", setlocale(LC_ALL, nullptr));
54*8d67ca89SAndroid Build Coastguard Worker   EXPECT_STREQ("C.UTF-8", setlocale(LC_CTYPE, nullptr));
55*8d67ca89SAndroid Build Coastguard Worker 
56*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
57*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, setlocale(-1, nullptr));
58*8d67ca89SAndroid Build Coastguard Worker   EXPECT_ERRNO(EINVAL);
59*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
60*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, setlocale(13, nullptr));
61*8d67ca89SAndroid Build Coastguard Worker   EXPECT_ERRNO(EINVAL);
62*8d67ca89SAndroid Build Coastguard Worker 
63*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
64*8d67ca89SAndroid Build Coastguard Worker   // The "" locale is implementation-defined. For bionic, it's the C.UTF-8 locale, which is
65*8d67ca89SAndroid Build Coastguard Worker   // pretty much all we support anyway.
66*8d67ca89SAndroid Build Coastguard Worker   // glibc will give us something like "en_US.UTF-8", depending on the user's configuration.
67*8d67ca89SAndroid Build Coastguard Worker   EXPECT_STREQ("C.UTF-8", setlocale(LC_ALL, ""));
68*8d67ca89SAndroid Build Coastguard Worker #endif
69*8d67ca89SAndroid Build Coastguard Worker   EXPECT_STREQ("C", setlocale(LC_ALL, "C"));
70*8d67ca89SAndroid Build Coastguard Worker   EXPECT_STREQ("C", setlocale(LC_ALL, "POSIX"));
71*8d67ca89SAndroid Build Coastguard Worker 
72*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
73*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, setlocale(LC_ALL, "this-is-not-a-locale"));
74*8d67ca89SAndroid Build Coastguard Worker   EXPECT_ERRNO(ENOENT);  // POSIX specified, not an implementation detail!
75*8d67ca89SAndroid Build Coastguard Worker }
76*8d67ca89SAndroid Build Coastguard Worker 
TEST(locale,newlocale_invalid_category_mask)77*8d67ca89SAndroid Build Coastguard Worker TEST(locale, newlocale_invalid_category_mask) {
78*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
79*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, newlocale(1 << 20, "C", nullptr));
80*8d67ca89SAndroid Build Coastguard Worker   EXPECT_ERRNO(EINVAL);
81*8d67ca89SAndroid Build Coastguard Worker }
82*8d67ca89SAndroid Build Coastguard Worker 
TEST(locale,newlocale_NULL_locale_name)83*8d67ca89SAndroid Build Coastguard Worker TEST(locale, newlocale_NULL_locale_name) {
84*8d67ca89SAndroid Build Coastguard Worker #pragma clang diagnostic push
85*8d67ca89SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wnonnull"
86*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
87*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, newlocale(LC_ALL, nullptr, nullptr));
88*8d67ca89SAndroid Build Coastguard Worker   EXPECT_ERRNO(EINVAL);
89*8d67ca89SAndroid Build Coastguard Worker #pragma clang diagnostic pop
90*8d67ca89SAndroid Build Coastguard Worker }
91*8d67ca89SAndroid Build Coastguard Worker 
TEST(locale,newlocale_bad_locale_name)92*8d67ca89SAndroid Build Coastguard Worker TEST(locale, newlocale_bad_locale_name) {
93*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
94*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, newlocale(LC_ALL, "this-is-not-a-locale", nullptr));
95*8d67ca89SAndroid Build Coastguard Worker   EXPECT_ERRNO(ENOENT);  // POSIX specified, not an implementation detail!
96*8d67ca89SAndroid Build Coastguard Worker }
97*8d67ca89SAndroid Build Coastguard Worker 
TEST(locale,newlocale)98*8d67ca89SAndroid Build Coastguard Worker TEST(locale, newlocale) {
99*8d67ca89SAndroid Build Coastguard Worker   locale_t l = newlocale(LC_ALL, "C", nullptr);
100*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(l != nullptr);
101*8d67ca89SAndroid Build Coastguard Worker   freelocale(l);
102*8d67ca89SAndroid Build Coastguard Worker }
103*8d67ca89SAndroid Build Coastguard Worker 
TEST(locale,duplocale)104*8d67ca89SAndroid Build Coastguard Worker TEST(locale, duplocale) {
105*8d67ca89SAndroid Build Coastguard Worker   locale_t cloned_global = duplocale(LC_GLOBAL_LOCALE);
106*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(cloned_global != nullptr);
107*8d67ca89SAndroid Build Coastguard Worker   freelocale(cloned_global);
108*8d67ca89SAndroid Build Coastguard Worker }
109*8d67ca89SAndroid Build Coastguard Worker 
TEST(locale,uselocale)110*8d67ca89SAndroid Build Coastguard Worker TEST(locale, uselocale) {
111*8d67ca89SAndroid Build Coastguard Worker   locale_t original = uselocale(nullptr);
112*8d67ca89SAndroid Build Coastguard Worker   EXPECT_FALSE(original == nullptr);
113*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(LC_GLOBAL_LOCALE, original);
114*8d67ca89SAndroid Build Coastguard Worker 
115*8d67ca89SAndroid Build Coastguard Worker   locale_t n = newlocale(LC_ALL, "C", nullptr);
116*8d67ca89SAndroid Build Coastguard Worker   EXPECT_FALSE(n == nullptr);
117*8d67ca89SAndroid Build Coastguard Worker   EXPECT_FALSE(n == original);
118*8d67ca89SAndroid Build Coastguard Worker 
119*8d67ca89SAndroid Build Coastguard Worker   locale_t old = uselocale(n);
120*8d67ca89SAndroid Build Coastguard Worker   EXPECT_TRUE(old == original);
121*8d67ca89SAndroid Build Coastguard Worker 
122*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(n, uselocale(nullptr));
123*8d67ca89SAndroid Build Coastguard Worker }
124*8d67ca89SAndroid Build Coastguard Worker 
TEST(locale,mb_cur_max)125*8d67ca89SAndroid Build Coastguard Worker TEST(locale, mb_cur_max) {
126*8d67ca89SAndroid Build Coastguard Worker   // We can't reliably test the behavior with setlocale(3) or the behavior for
127*8d67ca89SAndroid Build Coastguard Worker   // initial program conditions because (unless we're the only test that was
128*8d67ca89SAndroid Build Coastguard Worker   // run), another test has almost certainly called uselocale(3) in this thread.
129*8d67ca89SAndroid Build Coastguard Worker   // See b/16685652.
130*8d67ca89SAndroid Build Coastguard Worker   locale_t cloc = newlocale(LC_ALL, "C", nullptr);
131*8d67ca89SAndroid Build Coastguard Worker   locale_t cloc_utf8 = newlocale(LC_ALL, "C.UTF-8", nullptr);
132*8d67ca89SAndroid Build Coastguard Worker 
133*8d67ca89SAndroid Build Coastguard Worker   locale_t old_locale = uselocale(cloc);
134*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(1U, MB_CUR_MAX);
135*8d67ca89SAndroid Build Coastguard Worker   uselocale(cloc_utf8);
136*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(4U, MB_CUR_MAX);
137*8d67ca89SAndroid Build Coastguard Worker 
138*8d67ca89SAndroid Build Coastguard Worker   uselocale(old_locale);
139*8d67ca89SAndroid Build Coastguard Worker   freelocale(cloc);
140*8d67ca89SAndroid Build Coastguard Worker   freelocale(cloc_utf8);
141*8d67ca89SAndroid Build Coastguard Worker }
142