| Pavel Chupin | 50282f7 | 2014-03-25 13:43:04 +0400 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright (C) 2014 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 <gtest/gtest.h> | 
|  | 18 |  | 
| Elliott Hughes | c4936e2 | 2014-04-08 17:05:05 -0700 | [diff] [blame] | 19 | #include <errno.h> | 
| Elliott Hughes | 5363a45 | 2014-04-08 14:34:12 -0700 | [diff] [blame] | 20 | #include <limits.h> | 
| Pavel Chupin | 50282f7 | 2014-03-25 13:43:04 +0400 | [diff] [blame] | 21 | #include <locale.h> | 
|  | 22 |  | 
|  | 23 | TEST(locale, localeconv) { | 
| Elliott Hughes | 5363a45 | 2014-04-08 14:34:12 -0700 | [diff] [blame] | 24 | EXPECT_STREQ(".", localeconv()->decimal_point); | 
|  | 25 | EXPECT_STREQ("", localeconv()->thousands_sep); | 
|  | 26 | EXPECT_STREQ("", localeconv()->grouping); | 
|  | 27 | EXPECT_STREQ("", localeconv()->int_curr_symbol); | 
|  | 28 | EXPECT_STREQ("", localeconv()->currency_symbol); | 
|  | 29 | EXPECT_STREQ("", localeconv()->mon_decimal_point); | 
|  | 30 | EXPECT_STREQ("", localeconv()->mon_thousands_sep); | 
|  | 31 | EXPECT_STREQ("", localeconv()->mon_grouping); | 
|  | 32 | EXPECT_STREQ("", localeconv()->positive_sign); | 
|  | 33 | EXPECT_STREQ("", localeconv()->negative_sign); | 
|  | 34 | EXPECT_EQ(CHAR_MAX, localeconv()->int_frac_digits); | 
|  | 35 | EXPECT_EQ(CHAR_MAX, localeconv()->frac_digits); | 
|  | 36 | EXPECT_EQ(CHAR_MAX, localeconv()->p_cs_precedes); | 
|  | 37 | EXPECT_EQ(CHAR_MAX, localeconv()->p_sep_by_space); | 
|  | 38 | EXPECT_EQ(CHAR_MAX, localeconv()->n_cs_precedes); | 
|  | 39 | EXPECT_EQ(CHAR_MAX, localeconv()->n_sep_by_space); | 
|  | 40 | EXPECT_EQ(CHAR_MAX, localeconv()->p_sign_posn); | 
|  | 41 | EXPECT_EQ(CHAR_MAX, localeconv()->n_sign_posn); | 
|  | 42 | EXPECT_EQ(CHAR_MAX, localeconv()->int_p_cs_precedes); | 
|  | 43 | EXPECT_EQ(CHAR_MAX, localeconv()->int_p_sep_by_space); | 
|  | 44 | EXPECT_EQ(CHAR_MAX, localeconv()->int_n_cs_precedes); | 
|  | 45 | EXPECT_EQ(CHAR_MAX, localeconv()->int_n_sep_by_space); | 
|  | 46 | EXPECT_EQ(CHAR_MAX, localeconv()->int_p_sign_posn); | 
|  | 47 | EXPECT_EQ(CHAR_MAX, localeconv()->int_n_sign_posn); | 
| Pavel Chupin | 50282f7 | 2014-03-25 13:43:04 +0400 | [diff] [blame] | 48 | } | 
| Elliott Hughes | c4936e2 | 2014-04-08 17:05:05 -0700 | [diff] [blame] | 49 |  | 
|  | 50 | TEST(locale, setlocale) { | 
| Dan Albert | 1aec7c1 | 2014-07-30 10:53:48 -0700 | [diff] [blame] | 51 | EXPECT_STREQ("C.UTF-8", setlocale(LC_ALL, NULL)); | 
|  | 52 | EXPECT_STREQ("C.UTF-8", setlocale(LC_CTYPE, NULL)); | 
| Elliott Hughes | c4936e2 | 2014-04-08 17:05:05 -0700 | [diff] [blame] | 53 |  | 
|  | 54 | errno = 0; | 
|  | 55 | EXPECT_EQ(NULL, setlocale(-1, NULL)); | 
|  | 56 | EXPECT_EQ(EINVAL, errno); | 
|  | 57 | errno = 0; | 
|  | 58 | EXPECT_EQ(NULL, setlocale(13, NULL)); | 
|  | 59 | EXPECT_EQ(EINVAL, errno); | 
|  | 60 |  | 
| Elliott Hughes | 063525c | 2014-05-13 11:19:57 -0700 | [diff] [blame] | 61 | #if defined(__BIONIC__) | 
| Elliott Hughes | c4936e2 | 2014-04-08 17:05:05 -0700 | [diff] [blame] | 62 | // The "" locale is implementation-defined. For bionic, it's the C locale. | 
|  | 63 | // glibc will give us something like "en_US.UTF-8", depending on the user's configuration. | 
|  | 64 | EXPECT_STREQ("C", setlocale(LC_ALL, "")); | 
|  | 65 | #endif | 
|  | 66 | EXPECT_STREQ("C", setlocale(LC_ALL, "C")); | 
|  | 67 | EXPECT_STREQ("C", setlocale(LC_ALL, "POSIX")); | 
|  | 68 |  | 
|  | 69 | errno = 0; | 
|  | 70 | EXPECT_EQ(NULL, setlocale(LC_ALL, "this-is-not-a-locale")); | 
|  | 71 | EXPECT_EQ(ENOENT, errno); // POSIX specified, not an implementation detail! | 
|  | 72 | } | 
|  | 73 |  | 
| Elliott Hughes | 7e0d0f8 | 2014-11-04 18:03:44 -0800 | [diff] [blame] | 74 | TEST(locale, newlocale_invalid_category_mask) { | 
| Elliott Hughes | c4936e2 | 2014-04-08 17:05:05 -0700 | [diff] [blame] | 75 | errno = 0; | 
|  | 76 | EXPECT_EQ(0, newlocale(1 << 20, "C", 0)); | 
|  | 77 | EXPECT_EQ(EINVAL, errno); | 
| Elliott Hughes | 7e0d0f8 | 2014-11-04 18:03:44 -0800 | [diff] [blame] | 78 | } | 
| Elliott Hughes | c4936e2 | 2014-04-08 17:05:05 -0700 | [diff] [blame] | 79 |  | 
| Elliott Hughes | 7e0d0f8 | 2014-11-04 18:03:44 -0800 | [diff] [blame] | 80 | TEST(locale, newlocale_NULL_locale_name) { | 
|  | 81 | errno = 0; | 
|  | 82 | EXPECT_EQ(0, newlocale(LC_ALL, NULL, 0)); | 
|  | 83 | EXPECT_EQ(EINVAL, errno); | 
|  | 84 | } | 
| Elliott Hughes | c4936e2 | 2014-04-08 17:05:05 -0700 | [diff] [blame] | 85 |  | 
| Elliott Hughes | 7e0d0f8 | 2014-11-04 18:03:44 -0800 | [diff] [blame] | 86 | TEST(locale, newlocale_bad_locale_name) { | 
| Elliott Hughes | c4936e2 | 2014-04-08 17:05:05 -0700 | [diff] [blame] | 87 | errno = 0; | 
|  | 88 | EXPECT_EQ(0, newlocale(LC_ALL, "this-is-not-a-locale", 0)); | 
|  | 89 | EXPECT_EQ(ENOENT, errno); // POSIX specified, not an implementation detail! | 
|  | 90 | } | 
|  | 91 |  | 
| Elliott Hughes | 7e0d0f8 | 2014-11-04 18:03:44 -0800 | [diff] [blame] | 92 | TEST(locale, newlocale) { | 
|  | 93 | locale_t l = newlocale(LC_ALL, "C", 0); | 
|  | 94 | ASSERT_TRUE(l != NULL); | 
|  | 95 | freelocale(l); | 
|  | 96 | } | 
|  | 97 |  | 
| Elliott Hughes | c4936e2 | 2014-04-08 17:05:05 -0700 | [diff] [blame] | 98 | TEST(locale, duplocale) { | 
|  | 99 | locale_t cloned_global = duplocale(LC_GLOBAL_LOCALE); | 
|  | 100 | ASSERT_TRUE(cloned_global != NULL); | 
|  | 101 | freelocale(cloned_global); | 
|  | 102 | } | 
|  | 103 |  | 
|  | 104 | TEST(locale, uselocale) { | 
|  | 105 | locale_t original = uselocale(NULL); | 
|  | 106 | EXPECT_FALSE(original == 0); | 
|  | 107 | EXPECT_EQ(LC_GLOBAL_LOCALE, original); | 
|  | 108 |  | 
|  | 109 | locale_t n = newlocale(LC_ALL, "C", 0); | 
|  | 110 | EXPECT_FALSE(n == 0); | 
|  | 111 | EXPECT_FALSE(n == original); | 
|  | 112 |  | 
|  | 113 | locale_t old = uselocale(n); | 
|  | 114 | EXPECT_TRUE(old == original); | 
|  | 115 |  | 
|  | 116 | EXPECT_EQ(n, uselocale(NULL)); | 
|  | 117 | } | 
| Dan Albert | 1aec7c1 | 2014-07-30 10:53:48 -0700 | [diff] [blame] | 118 |  | 
|  | 119 | TEST(locale, mb_cur_max) { | 
|  | 120 | // We can't reliably test the behavior with setlocale(3) or the behavior for | 
|  | 121 | // initial program conditions because (unless we're the only test that was | 
|  | 122 | // run), another test has almost certainly called uselocale(3) in this thread. | 
|  | 123 | // See b/16685652. | 
|  | 124 | locale_t cloc = newlocale(LC_ALL, "C", 0); | 
|  | 125 | locale_t cloc_utf8 = newlocale(LC_ALL, "C.UTF-8", 0); | 
|  | 126 |  | 
| Wally Yau | a40fdbd | 2014-08-26 09:47:23 -0700 | [diff] [blame] | 127 | locale_t old_locale = uselocale(cloc); | 
| Dan Albert | 1aec7c1 | 2014-07-30 10:53:48 -0700 | [diff] [blame] | 128 | ASSERT_EQ(1U, MB_CUR_MAX); | 
|  | 129 | uselocale(cloc_utf8); | 
|  | 130 | ASSERT_EQ(4U, MB_CUR_MAX); | 
|  | 131 |  | 
| Wally Yau | a40fdbd | 2014-08-26 09:47:23 -0700 | [diff] [blame] | 132 | uselocale(old_locale); | 
| Dan Albert | 1aec7c1 | 2014-07-30 10:53:48 -0700 | [diff] [blame] | 133 | freelocale(cloc); | 
|  | 134 | freelocale(cloc_utf8); | 
|  | 135 | } |