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/LocaleWin.h" 33 34 #include <gtest/gtest.h> 35 #include "platform/DateComponents.h" 36 #include "wtf/DateMath.h" 37 #include "wtf/MathExtras.h" 38 #include "wtf/PassOwnPtr.h" 39 #include "wtf/text/CString.h" 40 41 using namespace WebCore; 42 using namespace std; 43 44 class LocaleWinTest : public ::testing::Test { 45 protected: 46 enum { 47 January = 0, February, March, 48 April, May, June, 49 July, August, September, 50 October, November, December, 51 }; 52 53 enum { 54 Sunday = 0, Monday, Tuesday, 55 Wednesday, Thursday, Friday, 56 Saturday, 57 }; 58 59 // See http://msdn.microsoft.com/en-us/goglobal/bb964664.aspx 60 // Note that some locales are country-neutral. 61 enum { 62 ArabicEG = 0x0C01, // ar-eg 63 ChineseCN = 0x0804, // zh-cn 64 ChineseHK = 0x0C04, // zh-hk 65 ChineseTW = 0x0404, // zh-tw 66 German = 0x0407, // de 67 EnglishUS = 0x409, // en-us 68 FrenchFR = 0x40C, // fr 69 JapaneseJP = 0x411, // ja 70 KoreanKR = 0x0412, // ko 71 Persian = 0x0429, // fa 72 Spanish = 0x040A, // es 73 }; 74 75 DateComponents dateComponents(int year, int month, int day) 76 { 77 DateComponents date; 78 date.setMillisecondsSinceEpochForDate(msForDate(year, month, day)); 79 return date; 80 } 81 82 double msForDate(int year, int month, int day) 83 { 84 return dateToDaysFrom1970(year, month, day) * msPerDay; 85 } 86 87 String formatDate(LCID lcid, int year, int month, int day) 88 { 89 OwnPtr<LocaleWin> locale = LocaleWin::create(lcid, true /* defaultsForLocale */); 90 return locale->formatDateTime(dateComponents(year, month, day)); 91 } 92 93 unsigned firstDayOfWeek(LCID lcid) 94 { 95 OwnPtr<LocaleWin> locale = LocaleWin::create(lcid, true /* defaultsForLocale */); 96 return locale->firstDayOfWeek(); 97 } 98 99 String monthLabel(LCID lcid, unsigned index) 100 { 101 OwnPtr<LocaleWin> locale = LocaleWin::create(lcid, true /* defaultsForLocale */); 102 return locale->monthLabels()[index]; 103 } 104 105 String weekDayShortLabel(LCID lcid, unsigned index) 106 { 107 OwnPtr<LocaleWin> locale = LocaleWin::create(lcid, true /* defaultsForLocale */); 108 return locale->weekDayShortLabels()[index]; 109 } 110 111 bool isRTL(LCID lcid) 112 { 113 OwnPtr<LocaleWin> locale = LocaleWin::create(lcid, true /* defaultsForLocale */); 114 return locale->isRTL(); 115 } 116 117 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI) 118 String monthFormat(LCID lcid) 119 { 120 OwnPtr<LocaleWin> locale = LocaleWin::create(lcid, true /* defaultsForLocale */); 121 return locale->monthFormat(); 122 } 123 124 String timeFormat(LCID lcid) 125 { 126 OwnPtr<LocaleWin> locale = LocaleWin::create(lcid, true /* defaultsForLocale */); 127 return locale->timeFormat(); 128 } 129 130 String shortTimeFormat(LCID lcid) 131 { 132 OwnPtr<LocaleWin> locale = LocaleWin::create(lcid, true /* defaultsForLocale */); 133 return locale->shortTimeFormat(); 134 } 135 136 String shortMonthLabel(LCID lcid, unsigned index) 137 { 138 OwnPtr<LocaleWin> locale = LocaleWin::create(lcid, true /* defaultsForLocale */); 139 return locale->shortMonthLabels()[index]; 140 } 141 142 String timeAMPMLabel(LCID lcid, unsigned index) 143 { 144 OwnPtr<LocaleWin> locale = LocaleWin::create(lcid, true /* defaultsForLocale */); 145 return locale->timeAMPMLabels()[index]; 146 } 147 148 String decimalSeparator(LCID lcid) 149 { 150 OwnPtr<LocaleWin> locale = LocaleWin::create(lcid, true /* defaultsForLocale */); 151 return locale->localizedDecimalSeparator(); 152 } 153 #endif 154 }; 155 156 TEST_F(LocaleWinTest, formatDate) 157 { 158 EXPECT_STREQ("04/27/2005", formatDate(EnglishUS, 2005, April, 27).utf8().data()); 159 EXPECT_STREQ("27/04/2005", formatDate(FrenchFR, 2005, April, 27).utf8().data()); 160 EXPECT_STREQ("2005/04/27", formatDate(JapaneseJP, 2005, April, 27).utf8().data()); 161 } 162 163 TEST_F(LocaleWinTest, firstDayOfWeek) 164 { 165 EXPECT_EQ(Sunday, firstDayOfWeek(EnglishUS)); 166 EXPECT_EQ(Monday, firstDayOfWeek(FrenchFR)); 167 EXPECT_EQ(Sunday, firstDayOfWeek(JapaneseJP)); 168 } 169 170 TEST_F(LocaleWinTest, monthLabels) 171 { 172 EXPECT_STREQ("January", monthLabel(EnglishUS, January).utf8().data()); 173 EXPECT_STREQ("June", monthLabel(EnglishUS, June).utf8().data()); 174 EXPECT_STREQ("December", monthLabel(EnglishUS, December).utf8().data()); 175 176 EXPECT_STREQ("janvier", monthLabel(FrenchFR, January).utf8().data()); 177 EXPECT_STREQ("juin", monthLabel(FrenchFR, June).utf8().data()); 178 EXPECT_STREQ("d\xC3\xA9" "cembre", monthLabel(FrenchFR, December).utf8().data()); 179 180 EXPECT_STREQ("1\xE6\x9C\x88", monthLabel(JapaneseJP, January).utf8().data()); 181 EXPECT_STREQ("6\xE6\x9C\x88", monthLabel(JapaneseJP, June).utf8().data()); 182 EXPECT_STREQ("12\xE6\x9C\x88", monthLabel(JapaneseJP, December).utf8().data()); 183 } 184 185 TEST_F(LocaleWinTest, weekDayShortLabels) 186 { 187 EXPECT_STREQ("Sun", weekDayShortLabel(EnglishUS, Sunday).utf8().data()); 188 EXPECT_STREQ("Wed", weekDayShortLabel(EnglishUS, Wednesday).utf8().data()); 189 EXPECT_STREQ("Sat", weekDayShortLabel(EnglishUS, Saturday).utf8().data()); 190 191 EXPECT_STREQ("dim.", weekDayShortLabel(FrenchFR, Sunday).utf8().data()); 192 EXPECT_STREQ("mer.", weekDayShortLabel(FrenchFR, Wednesday).utf8().data()); 193 EXPECT_STREQ("sam.", weekDayShortLabel(FrenchFR, Saturday).utf8().data()); 194 195 EXPECT_STREQ("\xE6\x97\xA5", weekDayShortLabel(JapaneseJP, Sunday).utf8().data()); 196 EXPECT_STREQ("\xE6\xB0\xB4", weekDayShortLabel(JapaneseJP, Wednesday).utf8().data()); 197 EXPECT_STREQ("\xE5\x9C\x9F", weekDayShortLabel(JapaneseJP, Saturday).utf8().data()); 198 } 199 200 TEST_F(LocaleWinTest, isRTL) 201 { 202 EXPECT_TRUE(isRTL(ArabicEG)); 203 EXPECT_FALSE(isRTL(EnglishUS)); 204 } 205 206 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI) 207 TEST_F(LocaleWinTest, dateFormat) 208 { 209 EXPECT_STREQ("y-M-d", LocaleWin::dateFormat("y-M-d").utf8().data()); 210 EXPECT_STREQ("''yy'-'''MM'''-'dd", LocaleWin::dateFormat("''yy-''MM''-dd").utf8().data()); 211 EXPECT_STREQ("yyyy'-''''-'MMM'''''-'dd", LocaleWin::dateFormat("yyyy-''''-MMM''''-dd").utf8().data()); 212 EXPECT_STREQ("yyyy'-'''''MMMM-dd", LocaleWin::dateFormat("yyyy-''''MMMM-dd").utf8().data()); 213 } 214 215 TEST_F(LocaleWinTest, monthFormat) 216 { 217 EXPECT_STREQ("MMMM, yyyy", monthFormat(EnglishUS).utf8().data()); 218 EXPECT_STREQ("MMMM yyyy", monthFormat(FrenchFR).utf8().data()); 219 EXPECT_STREQ("yyyy\xE5\xB9\xB4M\xE6\x9C\x88", monthFormat(JapaneseJP).utf8().data()); 220 } 221 222 TEST_F(LocaleWinTest, timeFormat) 223 { 224 EXPECT_STREQ("h:mm:ss a", timeFormat(EnglishUS).utf8().data()); 225 EXPECT_STREQ("HH:mm:ss", timeFormat(FrenchFR).utf8().data()); 226 EXPECT_STREQ("H:mm:ss", timeFormat(JapaneseJP).utf8().data()); 227 } 228 229 TEST_F(LocaleWinTest, shortTimeFormat) 230 { 231 EXPECT_STREQ("h:mm a", shortTimeFormat(EnglishUS).utf8().data()); 232 EXPECT_STREQ("HH:mm", shortTimeFormat(FrenchFR).utf8().data()); 233 EXPECT_STREQ("H:mm", shortTimeFormat(JapaneseJP).utf8().data()); 234 } 235 236 TEST_F(LocaleWinTest, shortMonthLabels) 237 { 238 EXPECT_STREQ("Jan", shortMonthLabel(EnglishUS, 0).utf8().data()); 239 EXPECT_STREQ("Dec", shortMonthLabel(EnglishUS, 11).utf8().data()); 240 EXPECT_STREQ("janv.", shortMonthLabel(FrenchFR, 0).utf8().data()); 241 EXPECT_STREQ("d\xC3\xA9" "c.", shortMonthLabel(FrenchFR, 11).utf8().data()); 242 EXPECT_STREQ("1", shortMonthLabel(JapaneseJP, 0).utf8().data()); 243 EXPECT_STREQ("12", shortMonthLabel(JapaneseJP, 11).utf8().data()); 244 } 245 246 TEST_F(LocaleWinTest, timeAMPMLabels) 247 { 248 EXPECT_STREQ("AM", timeAMPMLabel(EnglishUS, 0).utf8().data()); 249 EXPECT_STREQ("PM", timeAMPMLabel(EnglishUS, 1).utf8().data()); 250 251 EXPECT_STREQ("", timeAMPMLabel(FrenchFR, 0).utf8().data()); 252 EXPECT_STREQ("", timeAMPMLabel(FrenchFR, 1).utf8().data()); 253 254 EXPECT_STREQ("\xE5\x8D\x88\xE5\x89\x8D", timeAMPMLabel(JapaneseJP, 0).utf8().data()); 255 EXPECT_STREQ("\xE5\x8D\x88\xE5\xBE\x8C", timeAMPMLabel(JapaneseJP, 1).utf8().data()); 256 } 257 258 TEST_F(LocaleWinTest, decimalSeparator) 259 { 260 EXPECT_STREQ(".", decimalSeparator(EnglishUS).utf8().data()); 261 EXPECT_STREQ(",", decimalSeparator(FrenchFR).utf8().data()); 262 } 263 #endif 264 265 static void testNumberIsReversible(LCID lcid, const char* original, const char* shouldHave = 0) 266 { 267 OwnPtr<LocaleWin> locale = LocaleWin::create(lcid, true /* defaultsForLocale */); 268 String localized = locale->convertToLocalizedNumber(original); 269 if (shouldHave) 270 EXPECT_TRUE(localized.contains(shouldHave)); 271 String converted = locale->convertFromLocalizedNumber(localized); 272 EXPECT_STREQ(original, converted.utf8().data()); 273 } 274 275 void testNumbers(LCID lcid) 276 { 277 testNumberIsReversible(lcid, "123456789012345678901234567890"); 278 testNumberIsReversible(lcid, "-123.456"); 279 testNumberIsReversible(lcid, ".456"); 280 testNumberIsReversible(lcid, "-0.456"); 281 } 282 283 TEST_F(LocaleWinTest, localizedNumberRoundTrip) 284 { 285 testNumberIsReversible(EnglishUS, "123456789012345678901234567890"); 286 testNumberIsReversible(EnglishUS, "-123.456", "."); 287 testNumberIsReversible(EnglishUS, ".456", "."); 288 testNumberIsReversible(EnglishUS, "-0.456", "."); 289 290 testNumberIsReversible(FrenchFR, "123456789012345678901234567890"); 291 testNumberIsReversible(FrenchFR, "-123.456", ","); 292 testNumberIsReversible(FrenchFR, ".456", ","); 293 testNumberIsReversible(FrenchFR, "-0.456", ","); 294 295 // Test some of major locales. 296 testNumbers(ArabicEG); 297 testNumbers(German); 298 testNumbers(Spanish); 299 testNumbers(Persian); 300 testNumbers(JapaneseJP); 301 testNumbers(KoreanKR); 302 testNumbers(ChineseCN); 303 testNumbers(ChineseHK); 304 testNumbers(ChineseTW); 305 } 306