• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "config.h"
32 #include "platform/text/LocaleICU.h"
33 
34 #include <gtest/gtest.h>
35 #include "wtf/PassOwnPtr.h"
36 #include "wtf/text/StringBuilder.h"
37 
38 using namespace WebCore;
39 
40 class LocaleICUTest : public ::testing::Test {
41 public:
42     // Labels class is used for printing results in EXPECT_EQ macro.
43     class Labels {
44     public:
Labels(const Vector<String> labels)45         Labels(const Vector<String> labels)
46             : m_labels(labels)
47         {
48         }
49 
50         // FIXME: We should use Vector<T>::operator==() if it works.
operator ==(const Labels & other) const51         bool operator==(const Labels& other) const
52         {
53             if (m_labels.size() != other.m_labels.size())
54                 return false;
55             for (unsigned index = 0; index < m_labels.size(); ++index)
56                 if (m_labels[index] != other.m_labels[index])
57                     return false;
58             return true;
59         }
60 
toString() const61         String toString() const
62         {
63             StringBuilder builder;
64             builder.append("labels(");
65             for (unsigned index = 0; index < m_labels.size(); ++index) {
66                 if (index)
67                     builder.append(", ");
68                 builder.append('"');
69                 builder.append(m_labels[index]);
70                 builder.append('"');
71             }
72             builder.append(')');
73             return builder.toString();
74         }
75 
76     private:
77         Vector<String> m_labels;
78     };
79 
80 protected:
labels(const String & element1,const String & element2)81     Labels labels(const String& element1, const String& element2)
82     {
83         Vector<String> labels = Vector<String>();
84         labels.append(element1);
85         labels.append(element2);
86         return Labels(labels);
87     }
88 
89 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
monthFormat(const char * localeString)90     String monthFormat(const char* localeString)
91     {
92         OwnPtr<LocaleICU> locale = LocaleICU::create(localeString);
93         return locale->monthFormat();
94     }
95 
localizedDateFormatText(const char * localeString)96     String localizedDateFormatText(const char* localeString)
97     {
98         OwnPtr<LocaleICU> locale = LocaleICU::create(localeString);
99         return locale->timeFormat();
100     }
101 
localizedShortDateFormatText(const char * localeString)102     String localizedShortDateFormatText(const char* localeString)
103     {
104         OwnPtr<LocaleICU> locale = LocaleICU::create(localeString);
105         return locale->shortTimeFormat();
106     }
107 
shortMonthLabel(const char * localeString,unsigned index)108     String shortMonthLabel(const char* localeString, unsigned index)
109     {
110         OwnPtr<LocaleICU> locale = LocaleICU::create(localeString);
111         return locale->shortMonthLabels()[index];
112     }
113 
shortStandAloneMonthLabel(const char * localeString,unsigned index)114     String shortStandAloneMonthLabel(const char* localeString, unsigned index)
115     {
116         OwnPtr<LocaleICU> locale = LocaleICU::create(localeString);
117         return locale->shortStandAloneMonthLabels()[index];
118     }
119 
standAloneMonthLabel(const char * localeString,unsigned index)120     String standAloneMonthLabel(const char* localeString, unsigned index)
121     {
122         OwnPtr<LocaleICU> locale = LocaleICU::create(localeString);
123         return locale->standAloneMonthLabels()[index];
124     }
125 
timeAMPMLabels(const char * localeString)126     Labels timeAMPMLabels(const char* localeString)
127     {
128         OwnPtr<LocaleICU> locale = LocaleICU::create(localeString);
129         return Labels(locale->timeAMPMLabels());
130     }
131 
isRTL(const char * localeString)132     bool isRTL(const char* localeString)
133     {
134         OwnPtr<LocaleICU> locale = LocaleICU::create(localeString);
135         return locale->isRTL();
136     }
137 #endif
138 };
139 
operator <<(std::ostream & os,const LocaleICUTest::Labels & labels)140 std::ostream& operator<<(std::ostream& os, const LocaleICUTest::Labels& labels)
141 {
142     return os << labels.toString().utf8().data();
143 }
144 
145 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
TEST_F(LocaleICUTest,isRTL)146 TEST_F(LocaleICUTest, isRTL)
147 {
148     EXPECT_TRUE(isRTL("ar-EG"));
149     EXPECT_FALSE(isRTL("en-us"));
150     EXPECT_FALSE(isRTL("ja-jp"));
151     EXPECT_FALSE(isRTL("**invalid**"));
152 }
153 
TEST_F(LocaleICUTest,monthFormat)154 TEST_F(LocaleICUTest, monthFormat)
155 {
156     EXPECT_STREQ("MMMM yyyy", monthFormat("en_US").utf8().data());
157     EXPECT_STREQ("MMMM yyyy", monthFormat("fr").utf8().data());
158     EXPECT_STREQ("yyyy\xE5\xB9\xB4M\xE6\x9C\x88", monthFormat("ja").utf8().data());
159 }
160 
TEST_F(LocaleICUTest,localizedDateFormatText)161 TEST_F(LocaleICUTest, localizedDateFormatText)
162 {
163     // Note: EXPECT_EQ(String, String) doesn't print result as string.
164     EXPECT_STREQ("h:mm:ss a", localizedDateFormatText("en_US").utf8().data());
165     EXPECT_STREQ("HH:mm:ss", localizedDateFormatText("fr").utf8().data());
166     EXPECT_STREQ("H:mm:ss", localizedDateFormatText("ja").utf8().data());
167 }
168 
TEST_F(LocaleICUTest,localizedShortDateFormatText)169 TEST_F(LocaleICUTest, localizedShortDateFormatText)
170 {
171     EXPECT_STREQ("h:mm a", localizedShortDateFormatText("en_US").utf8().data());
172     EXPECT_STREQ("HH:mm", localizedShortDateFormatText("fr").utf8().data());
173     EXPECT_STREQ("H:mm", localizedShortDateFormatText("ja").utf8().data());
174 }
175 
TEST_F(LocaleICUTest,standAloneMonthLabels)176 TEST_F(LocaleICUTest, standAloneMonthLabels)
177 {
178     EXPECT_STREQ("January", standAloneMonthLabel("en_US", 0).utf8().data());
179     EXPECT_STREQ("June", standAloneMonthLabel("en_US", 5).utf8().data());
180     EXPECT_STREQ("December", standAloneMonthLabel("en_US", 11).utf8().data());
181 
182     EXPECT_STREQ("janvier", standAloneMonthLabel("fr_FR", 0).utf8().data());
183     EXPECT_STREQ("juin", standAloneMonthLabel("fr_FR", 5).utf8().data());
184     EXPECT_STREQ("d\xC3\xA9" "cembre", standAloneMonthLabel("fr_FR", 11).utf8().data());
185 
186     EXPECT_STREQ("1\xE6\x9C\x88", standAloneMonthLabel("ja_JP", 0).utf8().data());
187     EXPECT_STREQ("6\xE6\x9C\x88", standAloneMonthLabel("ja_JP", 5).utf8().data());
188     EXPECT_STREQ("12\xE6\x9C\x88", standAloneMonthLabel("ja_JP", 11).utf8().data());
189 
190     EXPECT_STREQ("\xD0\x9C\xD0\xB0\xD1\x80\xD1\x82", standAloneMonthLabel("ru_RU", 2).utf8().data());
191     EXPECT_STREQ("\xD0\x9C\xD0\xB0\xD0\xB9", standAloneMonthLabel("ru_RU", 4).utf8().data());
192 }
193 
TEST_F(LocaleICUTest,shortMonthLabels)194 TEST_F(LocaleICUTest, shortMonthLabels)
195 {
196     EXPECT_STREQ("Jan", shortMonthLabel("en_US", 0).utf8().data());
197     EXPECT_STREQ("Jan", shortStandAloneMonthLabel("en_US", 0).utf8().data());
198     EXPECT_STREQ("Dec", shortMonthLabel("en_US", 11).utf8().data());
199     EXPECT_STREQ("Dec", shortStandAloneMonthLabel("en_US", 11).utf8().data());
200 
201     EXPECT_STREQ("janv.", shortMonthLabel("fr_FR", 0).utf8().data());
202     EXPECT_STREQ("janv.", shortStandAloneMonthLabel("fr_FR", 0).utf8().data());
203     EXPECT_STREQ("d\xC3\xA9" "c.", shortMonthLabel("fr_FR", 11).utf8().data());
204     EXPECT_STREQ("d\xC3\xA9" "c.", shortStandAloneMonthLabel("fr_FR", 11).utf8().data());
205 
206     EXPECT_STREQ("1\xE6\x9C\x88", shortMonthLabel("ja_JP", 0).utf8().data());
207     EXPECT_STREQ("1\xE6\x9C\x88", shortStandAloneMonthLabel("ja_JP", 0).utf8().data());
208     EXPECT_STREQ("12\xE6\x9C\x88", shortMonthLabel("ja_JP", 11).utf8().data());
209     EXPECT_STREQ("12\xE6\x9C\x88", shortStandAloneMonthLabel("ja_JP", 11).utf8().data());
210 
211     EXPECT_STREQ("\xD0\xBC\xD0\xB0\xD1\x80\xD1\x82\xD0\xB0", shortMonthLabel("ru_RU", 2).utf8().data());
212     EXPECT_STREQ("\xD0\xBC\xD0\xB0\xD1\x80\xD1\x82", shortStandAloneMonthLabel("ru_RU", 2).utf8().data());
213     EXPECT_STREQ("\xD0\xBC\xD0\xB0\xD1\x8F", shortMonthLabel("ru_RU", 4).utf8().data());
214     EXPECT_STREQ("\xD0\xBC\xD0\xB0\xD0\xB9", shortStandAloneMonthLabel("ru_RU", 4).utf8().data());
215 }
216 
TEST_F(LocaleICUTest,timeAMPMLabels)217 TEST_F(LocaleICUTest, timeAMPMLabels)
218 {
219     EXPECT_EQ(labels("AM", "PM"), timeAMPMLabels("en_US"));
220     EXPECT_EQ(labels("AM", "PM"), timeAMPMLabels("fr"));
221 
222     UChar jaAM[3] = { 0x5348, 0x524d, 0 };
223     UChar jaPM[3] = { 0x5348, 0x5F8C, 0 };
224     EXPECT_EQ(labels(String(jaAM), String(jaPM)), timeAMPMLabels("ja"));
225 }
226 
testDecimalSeparator(const AtomicString & localeIdentifier)227 static String testDecimalSeparator(const AtomicString& localeIdentifier)
228 {
229     OwnPtr<Locale> locale = Locale::create(localeIdentifier);
230     return locale->localizedDecimalSeparator();
231 }
232 
TEST_F(LocaleICUTest,localizedDecimalSeparator)233 TEST_F(LocaleICUTest, localizedDecimalSeparator)
234 {
235     EXPECT_EQ(String("."), testDecimalSeparator("en_US"));
236     EXPECT_EQ(String(","), testDecimalSeparator("fr"));
237 }
238 #endif
239 
testNumberIsReversible(const AtomicString & localeIdentifier,const char * original,const char * shouldHave=0)240 void testNumberIsReversible(const AtomicString& localeIdentifier, const char* original, const char* shouldHave = 0)
241 {
242     OwnPtr<Locale> locale = Locale::create(localeIdentifier);
243     String localized = locale->convertToLocalizedNumber(original);
244     if (shouldHave)
245         EXPECT_TRUE(localized.contains(shouldHave));
246     String converted = locale->convertFromLocalizedNumber(localized);
247     EXPECT_EQ(original, converted);
248 }
249 
testNumbers(const char * localeString)250 void testNumbers(const char* localeString)
251 {
252     testNumberIsReversible(localeString, "123456789012345678901234567890");
253     testNumberIsReversible(localeString, "-123.456");
254     testNumberIsReversible(localeString, ".456");
255     testNumberIsReversible(localeString, "-0.456");
256 }
257 
TEST_F(LocaleICUTest,reversible)258 TEST_F(LocaleICUTest, reversible)
259 {
260     testNumberIsReversible("en_US", "123456789012345678901234567890");
261     testNumberIsReversible("en_US", "-123.456", ".");
262     testNumberIsReversible("en_US", ".456", ".");
263     testNumberIsReversible("en_US", "-0.456", ".");
264 
265     testNumberIsReversible("fr", "123456789012345678901234567890");
266     testNumberIsReversible("fr", "-123.456", ",");
267     testNumberIsReversible("fr", ".456", ",");
268     testNumberIsReversible("fr", "-0.456", ",");
269 
270     // Persian locale has a negative prefix and a negative suffix.
271     testNumbers("fa");
272 
273     // Test some of major locales.
274     testNumbers("ar");
275     testNumbers("de_DE");
276     testNumbers("es_ES");
277     testNumbers("ja_JP");
278     testNumbers("ko_KR");
279     testNumbers("zh_CN");
280     testNumbers("zh_HK");
281     testNumbers("zh_TW");
282 }
283