Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / web / tests / LocaleMacTest.cpp
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
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
20  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
23  * DAMAGE.
24  */
25
26 #include "config.h"
27 #include "platform/text/LocaleMac.h"
28
29 #include "platform/DateComponents.h"
30 #include "wtf/DateMath.h"
31 #include "wtf/MathExtras.h"
32 #include "wtf/PassOwnPtr.h"
33 #include "wtf/text/CString.h"
34 #include <gtest/gtest.h>
35
36 using namespace WebCore;
37
38 class LocaleMacTest : public ::testing::Test {
39 protected:
40     enum {
41         January = 0, February, March,
42         April, May, June,
43         July, August, September,
44         October, November, December,
45     };
46
47     enum {
48         Sunday = 0, Monday, Tuesday,
49         Wednesday, Thursday, Friday,
50         Saturday,
51     };
52
53     DateComponents dateComponents(int year, int month, int day)
54     {
55         DateComponents date;
56         date.setMillisecondsSinceEpochForDate(msForDate(year, month, day));
57         return date;
58     }
59
60     DateComponents timeComponents(int hour, int minute, int second, int millisecond)
61     {
62         DateComponents date;
63         date.setMillisecondsSinceMidnight(hour * msPerHour + minute * msPerMinute + second * msPerSecond + millisecond);
64         return date;
65     }
66
67     double msForDate(int year, int month, int day)
68     {
69         return dateToDaysFrom1970(year, month, day) * msPerDay;
70     }
71
72     String formatWeek(const String& localeString, const String& isoString)
73     {
74         OwnPtr<LocaleMac> locale = LocaleMac::create(localeString);
75         DateComponents date;
76         unsigned end;
77         date.parseWeek(isoString, 0, end);
78         return locale->formatDateTime(date);
79     }
80
81     String formatMonth(const String& localeString, const String& isoString, bool useShortFormat)
82     {
83         OwnPtr<LocaleMac> locale = LocaleMac::create(localeString);
84         DateComponents date;
85         unsigned end;
86         date.parseMonth(isoString, 0, end);
87         return locale->formatDateTime(date, (useShortFormat ? Locale::FormatTypeShort : Locale::FormatTypeMedium));
88     }
89
90     String formatDate(const String& localeString, int year, int month, int day)
91     {
92         OwnPtr<LocaleMac> locale = LocaleMac::create(localeString);
93         return locale->formatDateTime(dateComponents(year, month, day));
94     }
95
96     String formatTime(const String& localeString, int hour, int minute, int second, int millisecond, bool useShortFormat)
97     {
98         OwnPtr<LocaleMac> locale = LocaleMac::create(localeString);
99         return locale->formatDateTime(timeComponents(hour, minute, second, millisecond), (useShortFormat ? Locale::FormatTypeShort : Locale::FormatTypeMedium));
100     }
101
102     unsigned firstDayOfWeek(const String& localeString)
103     {
104         OwnPtr<LocaleMac> locale = LocaleMac::create(localeString);
105         return locale->firstDayOfWeek();
106     }
107
108     String monthLabel(const String& localeString, unsigned index)
109     {
110         OwnPtr<LocaleMac> locale = LocaleMac::create(localeString);
111         return locale->monthLabels()[index];
112     }
113
114     String weekDayShortLabel(const String& localeString, unsigned index)
115     {
116         OwnPtr<LocaleMac> locale = LocaleMac::create(localeString);
117         return locale->weekDayShortLabels()[index];
118     }
119
120     bool isRTL(const String& localeString)
121     {
122         OwnPtr<LocaleMac> locale = LocaleMac::create(localeString);
123         return locale->isRTL();
124     }
125
126 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
127     String monthFormat(const String& localeString)
128     {
129         OwnPtr<LocaleMac> locale = LocaleMac::create(localeString);
130         return locale->monthFormat();
131     }
132
133     String timeFormat(const String& localeString)
134     {
135         OwnPtr<LocaleMac> locale = LocaleMac::create(localeString);
136         return locale->timeFormat();
137     }
138
139     String shortTimeFormat(const String& localeString)
140     {
141         OwnPtr<LocaleMac> locale = LocaleMac::create(localeString);
142         return locale->shortTimeFormat();
143     }
144
145     String shortMonthLabel(const String& localeString, unsigned index)
146     {
147         OwnPtr<LocaleMac> locale = LocaleMac::create(localeString);
148         return locale->shortMonthLabels()[index];
149     }
150
151     String standAloneMonthLabel(const String& localeString, unsigned index)
152     {
153         OwnPtr<LocaleMac> locale = LocaleMac::create(localeString);
154         return locale->standAloneMonthLabels()[index];
155     }
156
157     String shortStandAloneMonthLabel(const String& localeString, unsigned index)
158     {
159         OwnPtr<LocaleMac> locale = LocaleMac::create(localeString);
160         return locale->shortStandAloneMonthLabels()[index];
161     }
162
163     String timeAMPMLabel(const String& localeString, unsigned index)
164     {
165         OwnPtr<LocaleMac> locale = LocaleMac::create(localeString);
166         return locale->timeAMPMLabels()[index];
167     }
168
169     String decimalSeparator(const String& localeString)
170     {
171         OwnPtr<LocaleMac> locale = LocaleMac::create(localeString);
172         return locale->localizedDecimalSeparator();
173     }
174 #endif
175 };
176
177 TEST_F(LocaleMacTest, formatWeek)
178 {
179     EXPECT_STREQ("Week 04, 2005", formatWeek("en_US", "2005-W04").utf8().data());
180     EXPECT_STREQ("Week 52, 2005", formatWeek("en_US", "2005-W52").utf8().data());
181 }
182
183 TEST_F(LocaleMacTest, formatMonth)
184 {
185     EXPECT_STREQ("April 2005", formatMonth("en_US", "2005-04", false).utf8().data());
186     EXPECT_STREQ("avril 2005", formatMonth("fr_FR", "2005-04", false).utf8().data());
187     EXPECT_STREQ("2005\xE5\xB9\xB4" "04\xE6\x9C\x88", formatMonth("ja_JP", "2005-04", false).utf8().data());
188
189     EXPECT_STREQ("Apr 2005", formatMonth("en_US", "2005-04", true).utf8().data());
190     EXPECT_STREQ("avr. 2005", formatMonth("fr_FR", "2005-04", true).utf8().data());
191     EXPECT_STREQ("2005\xE5\xB9\xB4" "04\xE6\x9C\x88", formatMonth("ja_JP", "2005-04", true).utf8().data());
192 }
193
194 TEST_F(LocaleMacTest, formatDate)
195 {
196     EXPECT_STREQ("04/27/2005", formatDate("en_US", 2005, April, 27).utf8().data());
197     EXPECT_STREQ("27/04/2005", formatDate("fr_FR", 2005, April, 27).utf8().data());
198     // Do not test ja_JP locale. OS X 10.8 and 10.7 have different formats.
199 }
200
201 TEST_F(LocaleMacTest, formatTime)
202 {
203     EXPECT_STREQ("1:23 PM", formatTime("en_US", 13, 23, 00, 000, true).utf8().data());
204     EXPECT_STREQ("13:23", formatTime("fr_FR", 13, 23, 00, 000, true).utf8().data());
205     EXPECT_STREQ("13:23", formatTime("ja_JP", 13, 23, 00, 000, true).utf8().data());
206     EXPECT_STREQ("\xD9\xA1:\xD9\xA2\xD9\xA3 \xD9\x85", formatTime("ar", 13, 23, 00, 000, true).utf8().data());
207     EXPECT_STREQ("\xDB\xB1\xDB\xB3:\xDB\xB2\xDB\xB3", formatTime("fa", 13, 23, 00, 000, true).utf8().data());
208
209     EXPECT_STREQ("12:00 AM", formatTime("en_US", 00, 00, 00, 000, true).utf8().data());
210     EXPECT_STREQ("00:00", formatTime("fr_FR", 00, 00, 00, 000, true).utf8().data());
211     EXPECT_STREQ("0:00", formatTime("ja_JP", 00, 00, 00, 000, true).utf8().data());
212     EXPECT_STREQ("\xD9\xA1\xD9\xA2:\xD9\xA0\xD9\xA0 \xD8\xB5", formatTime("ar", 00, 00, 00, 000, true).utf8().data());
213     EXPECT_STREQ("\xDB\xB0:\xDB\xB0\xDB\xB0", formatTime("fa", 00, 00, 00, 000, true).utf8().data());
214
215     EXPECT_STREQ("7:07:07.007 AM", formatTime("en_US", 07, 07, 07, 007, false).utf8().data());
216     EXPECT_STREQ("07:07:07,007", formatTime("fr_FR", 07, 07, 07, 007, false).utf8().data());
217     EXPECT_STREQ("7:07:07.007", formatTime("ja_JP", 07, 07, 07, 007, false).utf8().data());
218     EXPECT_STREQ("\xD9\xA7:\xD9\xA0\xD9\xA7:\xD9\xA0\xD9\xA7\xD9\xAB\xD9\xA0\xD9\xA0\xD9\xA7 \xD8\xB5", formatTime("ar", 07, 07, 07, 007, false).utf8().data());
219     EXPECT_STREQ("\xDB\xB7:\xDB\xB0\xDB\xB7:\xDB\xB0\xDB\xB7\xD9\xAB\xDB\xB0\xDB\xB0\xDB\xB7", formatTime("fa", 07, 07, 07, 007, false).utf8().data());
220 }
221
222 TEST_F(LocaleMacTest, firstDayOfWeek)
223 {
224     EXPECT_EQ(Sunday, firstDayOfWeek("en_US"));
225     EXPECT_EQ(Monday, firstDayOfWeek("fr_FR"));
226     EXPECT_EQ(Sunday, firstDayOfWeek("ja_JP"));
227 }
228
229 TEST_F(LocaleMacTest, monthLabels)
230 {
231     EXPECT_STREQ("January", monthLabel("en_US", January).utf8().data());
232     EXPECT_STREQ("June", monthLabel("en_US", June).utf8().data());
233     EXPECT_STREQ("December", monthLabel("en_US", December).utf8().data());
234
235     EXPECT_STREQ("janvier", monthLabel("fr_FR", January).utf8().data());
236     EXPECT_STREQ("juin", monthLabel("fr_FR", June).utf8().data());
237     EXPECT_STREQ("d\xC3\xA9" "cembre", monthLabel("fr_FR", December).utf8().data());
238
239     EXPECT_STREQ("1\xE6\x9C\x88", monthLabel("ja_JP", January).utf8().data());
240     EXPECT_STREQ("6\xE6\x9C\x88", monthLabel("ja_JP", June).utf8().data());
241     EXPECT_STREQ("12\xE6\x9C\x88", monthLabel("ja_JP", December).utf8().data());
242 }
243
244 TEST_F(LocaleMacTest, weekDayShortLabels)
245 {
246     EXPECT_STREQ("Sun", weekDayShortLabel("en_US", Sunday).utf8().data());
247     EXPECT_STREQ("Wed", weekDayShortLabel("en_US", Wednesday).utf8().data());
248     EXPECT_STREQ("Sat", weekDayShortLabel("en_US", Saturday).utf8().data());
249
250     EXPECT_STREQ("dim.", weekDayShortLabel("fr_FR", Sunday).utf8().data());
251     EXPECT_STREQ("mer.", weekDayShortLabel("fr_FR", Wednesday).utf8().data());
252     EXPECT_STREQ("sam.", weekDayShortLabel("fr_FR", Saturday).utf8().data());
253
254     EXPECT_STREQ("\xE6\x97\xA5", weekDayShortLabel("ja_JP", Sunday).utf8().data());
255     EXPECT_STREQ("\xE6\xB0\xB4", weekDayShortLabel("ja_JP", Wednesday).utf8().data());
256     EXPECT_STREQ("\xE5\x9C\x9F", weekDayShortLabel("ja_JP", Saturday).utf8().data());
257 }
258
259 TEST_F(LocaleMacTest, isRTL)
260 {
261     EXPECT_TRUE(isRTL("ar-eg"));
262     EXPECT_FALSE(isRTL("en-us"));
263     EXPECT_FALSE(isRTL("ja-jp"));
264     EXPECT_FALSE(isRTL("**invalid**"));
265 }
266
267 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
268 TEST_F(LocaleMacTest, monthFormat)
269 {
270     EXPECT_STREQ("MMMM yyyy", monthFormat("en_US").utf8().data());
271     EXPECT_STREQ("yyyy\xE5\xB9\xB4M\xE6\x9C\x88", monthFormat("ja_JP").utf8().data());
272
273     // fr_FR and ru return different results on OS versions.
274     //  "MMM yyyy" "LLL yyyy" on 10.6 and 10.7
275     //  "MMM y" "LLL y" on 10.8
276 }
277
278 TEST_F(LocaleMacTest, timeFormat)
279 {
280     EXPECT_STREQ("h:mm:ss a", timeFormat("en_US").utf8().data());
281     EXPECT_STREQ("HH:mm:ss", timeFormat("fr_FR").utf8().data());
282     EXPECT_STREQ("H:mm:ss", timeFormat("ja_JP").utf8().data());
283 }
284
285 TEST_F(LocaleMacTest, shortTimeFormat)
286 {
287     EXPECT_STREQ("h:mm a", shortTimeFormat("en_US").utf8().data());
288     EXPECT_STREQ("HH:mm", shortTimeFormat("fr_FR").utf8().data());
289     EXPECT_STREQ("H:mm", shortTimeFormat("ja_JP").utf8().data());
290 }
291
292 TEST_F(LocaleMacTest, standAloneMonthLabels)
293 {
294     EXPECT_STREQ("January", standAloneMonthLabel("en_US", January).utf8().data());
295     EXPECT_STREQ("June", standAloneMonthLabel("en_US", June).utf8().data());
296     EXPECT_STREQ("December", standAloneMonthLabel("en_US", December).utf8().data());
297
298     EXPECT_STREQ("janvier", standAloneMonthLabel("fr_FR", January).utf8().data());
299     EXPECT_STREQ("juin", standAloneMonthLabel("fr_FR", June).utf8().data());
300     EXPECT_STREQ("d\xC3\xA9" "cembre", standAloneMonthLabel("fr_FR", December).utf8().data());
301
302     EXPECT_STREQ("1\xE6\x9C\x88", standAloneMonthLabel("ja_JP", January).utf8().data());
303     EXPECT_STREQ("6\xE6\x9C\x88", standAloneMonthLabel("ja_JP", June).utf8().data());
304     EXPECT_STREQ("12\xE6\x9C\x88", standAloneMonthLabel("ja_JP", December).utf8().data());
305 }
306
307 TEST_F(LocaleMacTest, shortMonthLabels)
308 {
309     EXPECT_STREQ("Jan", shortMonthLabel("en_US", 0).utf8().data());
310     EXPECT_STREQ("Jan", shortStandAloneMonthLabel("en_US", 0).utf8().data());
311     EXPECT_STREQ("Dec", shortMonthLabel("en_US", 11).utf8().data());
312     EXPECT_STREQ("Dec", shortStandAloneMonthLabel("en_US", 11).utf8().data());
313
314     EXPECT_STREQ("janv.", shortMonthLabel("fr_FR", 0).utf8().data());
315     EXPECT_STREQ("janv.", shortStandAloneMonthLabel("fr_FR", 0).utf8().data());
316     EXPECT_STREQ("d\xC3\xA9" "c.", shortMonthLabel("fr_FR", 11).utf8().data());
317     EXPECT_STREQ("d\xC3\xA9" "c.", shortStandAloneMonthLabel("fr_FR", 11).utf8().data());
318
319     EXPECT_STREQ("1\xE6\x9C\x88", shortMonthLabel("ja_JP", 0).utf8().data());
320     EXPECT_STREQ("1\xE6\x9C\x88", shortStandAloneMonthLabel("ja_JP", 0).utf8().data());
321     EXPECT_STREQ("12\xE6\x9C\x88", shortMonthLabel("ja_JP", 11).utf8().data());
322     EXPECT_STREQ("12\xE6\x9C\x88", shortStandAloneMonthLabel("ja_JP", 11).utf8().data());
323
324     EXPECT_STREQ("\xD0\xBC\xD0\xB0\xD1\x80\xD1\x82\xD0\xB0", shortMonthLabel("ru_RU", 2).utf8().data());
325     EXPECT_STREQ("\xD0\xBC\xD0\xB0\xD1\x8F", shortMonthLabel("ru_RU", 4).utf8().data());
326     // The ru_RU locale returns different stand-alone month labels on OS versions.
327     //  "\xD0\xBC\xD0\xB0\xD1\x80\xD1\x82" "\xD0\xBC\xD0\xB0\xD0\xB9" on 10.6 and 10.7
328     //  "\xD0\x9C\xD0\xB0\xD1\x80\xD1\x82" "\xD0\x9C\xD0\xB0\xD0\xB9" on 10.8
329 }
330
331 TEST_F(LocaleMacTest, timeAMPMLabels)
332 {
333     EXPECT_STREQ("AM", timeAMPMLabel("en_US", 0).utf8().data());
334     EXPECT_STREQ("PM", timeAMPMLabel("en_US", 1).utf8().data());
335
336     EXPECT_STREQ("AM", timeAMPMLabel("fr_FR", 0).utf8().data());
337     EXPECT_STREQ("PM", timeAMPMLabel("fr_FR", 1).utf8().data());
338
339     EXPECT_STREQ("\xE5\x8D\x88\xE5\x89\x8D", timeAMPMLabel("ja_JP", 0).utf8().data());
340     EXPECT_STREQ("\xE5\x8D\x88\xE5\xBE\x8C", timeAMPMLabel("ja_JP", 1).utf8().data());
341 }
342
343 TEST_F(LocaleMacTest, decimalSeparator)
344 {
345     EXPECT_STREQ(".", decimalSeparator("en_US").utf8().data());
346     EXPECT_STREQ(",", decimalSeparator("fr_FR").utf8().data());
347 }
348 #endif
349
350 TEST_F(LocaleMacTest, invalidLocale)
351 {
352     EXPECT_STREQ(monthLabel("en_US", January).utf8().data(), monthLabel("foo", January).utf8().data());
353     EXPECT_STREQ(decimalSeparator("en_US").utf8().data(), decimalSeparator("foo").utf8().data());
354 }
355
356 static void testNumberIsReversible(const AtomicString& localeString, const char* original, const char* shouldHave = 0)
357 {
358     OwnPtr<Locale> locale = Locale::create(localeString);
359     String localized = locale->convertToLocalizedNumber(original);
360     if (shouldHave)
361         EXPECT_TRUE(localized.contains(shouldHave));
362     String converted = locale->convertFromLocalizedNumber(localized);
363     EXPECT_STREQ(original, converted.utf8().data());
364 }
365
366 void testNumbers(const AtomicString& localeString, const char* decimalSeparatorShouldBe = 0)
367 {
368     testNumberIsReversible(localeString, "123456789012345678901234567890");
369     testNumberIsReversible(localeString, "-123.456", decimalSeparatorShouldBe);
370     testNumberIsReversible(localeString, ".456", decimalSeparatorShouldBe);
371     testNumberIsReversible(localeString, "-0.456", decimalSeparatorShouldBe);
372 }
373
374 TEST_F(LocaleMacTest, localizedNumberRoundTrip)
375 {
376     // Test some of major locales.
377     testNumbers("en_US", ".");
378     testNumbers("fr_FR", ",");
379     testNumbers("ar");
380     testNumbers("de_DE");
381     testNumbers("es_ES");
382     testNumbers("fa");
383     testNumbers("ja_JP");
384     testNumbers("ko_KR");
385     testNumbers("zh_CN");
386     testNumbers("zh_HK");
387     testNumbers("zh_TW");
388 }