1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "ecmascript/js_locale.h" 17#include "ecmascript/js_collator.h" 18#include "ecmascript/js_number_format.h" 19#include "ecmascript/js_plural_rules.h" 20#include "ecmascript/global_env.h" 21#include "ecmascript/object_factory-inl.h" 22#include "ecmascript/tests/test_helper.h" 23 24using namespace panda::ecmascript; 25 26namespace panda::test { 27class JSLocaleTest : public BaseTestWithScope<true> { 28}; 29 30void CreateLanguageIterator(std::vector<std::string>& languageTemp) 31{ 32 languageTemp.push_back("zh-Hans-Cn"); 33 languageTemp.push_back("ko-kore-kr"); 34 languageTemp.push_back("fr-FR"); 35 languageTemp.push_back("en-Latn-US"); 36 languageTemp.push_back("ja-JP-u-ca-japanese"); 37 languageTemp.push_back("ar-EG"); 38} 39 40/** 41 * @tc.name: JSIntlIteratorTest 42 * @tc.desc: Construct an iterator of JSIntl and then traverse the iterator to compare whether the variable 43 * at each position is equal to the setting. 44 * @tc.type: FUNC 45 * @tc.require: 46 */ 47HWTEST_F_L0(JSLocaleTest, JSIntlIteratorTest) 48{ 49 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 50 std::vector<std::string> languageVector; 51 CreateLanguageIterator(languageVector); 52 uint32_t arrayDataLength = languageVector.size(); 53 JSHandle<TaggedArray> arrayData = factory->NewTaggedArray(arrayDataLength); 54 55 for (uint32_t i = 0; i < arrayDataLength; i++) { 56 JSHandle<JSTaggedValue> languageStr(factory->NewFromASCII(languageVector[i].c_str())); 57 arrayData->Set(thread, i, languageStr); 58 } 59 // construct a JSIntlIterator object 60 JSIntlIterator jsIntlIterator(arrayData, arrayDataLength); 61 EXPECT_TRUE(jsIntlIterator.hasNext()); 62 // call "next" function to traverse the container 63 for (uint32_t i = 0; i < arrayDataLength; i++) { 64 EXPECT_TRUE(jsIntlIterator.next() != nullptr); 65 EXPECT_STREQ(jsIntlIterator[i].c_str(), languageVector[i].c_str()); 66 } 67 EXPECT_FALSE(jsIntlIterator.hasNext()); 68} 69 70/** 71 * @tc.name: IsPrivateSubTag 72 * @tc.desc: Check whether the string is private subtag through "IsPrivateSubTag" function. 73 * @tc.type: FUNC 74 * @tc.require: 75 */ 76HWTEST_F_L0(JSLocaleTest, IsPrivateSubTag) 77{ 78 std::string result = "en-GB-oed"; 79 EXPECT_FALSE(JSLocale::IsPrivateSubTag(result, result.length())); 80 81 result = "i-ami"; 82 EXPECT_TRUE(JSLocale::IsPrivateSubTag(result, result.length())); 83 84 result = "x-default"; 85 EXPECT_TRUE(JSLocale::IsPrivateSubTag(result, result.length())); 86} 87 88/** 89 * @tc.name: GetIcuField 90 * @tc.desc: Call "NewJSIntlIcuData" function Set locale IcuField,check whether the locale IcuField through 91 * "getBaseName" function is within expectations. 92 * @tc.type: FUNC 93 * @tc.require: 94 */ 95HWTEST_F_L0(JSLocaleTest, GetIcuField) 96{ 97 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 98 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 99 JSHandle<JSTaggedValue> ctor = env->GetLocaleFunction(); 100 JSHandle<JSLocale> locale = 101 JSHandle<JSLocale>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor), ctor)); 102 // call "NewJSIntlIcuData" function Set IcuField 103 icu::Locale icuLocale("zh", "Hans", "Cn"); 104 factory->NewJSIntlIcuData(locale, icuLocale, JSLocale::FreeIcuLocale); 105 106 // call "GetIcuLocale" function Get IcuField 107 icu::Locale *result = locale->GetIcuLocale(); 108 EXPECT_STREQ(result->getBaseName(), "zh_Hans_CN"); 109} 110 111/** 112 * @tc.name: IsValidTimeZoneName 113 * @tc.desc: Call "IsValidTimeZoneName" function check whether the TimeZone is valid.if TimeZone include "GMT-Time" 114 * return true otherwise, return false. 115 * @tc.type: FUNC 116 * @tc.require: 117 */ 118HWTEST_F_L0(JSLocaleTest, IsValidTimeZoneName) 119{ 120 icu::UnicodeString stringID1("GMT-8:00"); 121 icu::TimeZone *timeZone = icu::TimeZone::createTimeZone(stringID1); 122 EXPECT_TRUE(JSLocale::IsValidTimeZoneName(*timeZone)); 123 delete timeZone; 124 125 icu::UnicodeString stringID2("Etc/Unknown"); 126 timeZone = icu::TimeZone::createTimeZone(stringID2); 127 EXPECT_FALSE(JSLocale::IsValidTimeZoneName(*timeZone)); 128 delete timeZone; 129} 130 131/** 132 * @tc.name: PutElement 133 * @tc.desc: Put elements in empty JSArray and return the JSArray.call "GetProperty" function to get the value and 134 * check whether the value is consistent with the value of the put. 135 * @tc.type: FUNC 136 * @tc.require: 137 */ 138HWTEST_F_L0(JSLocaleTest, PutElement) 139{ 140 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 141 auto globalConst = thread->GlobalConstants(); 142 JSHandle<JSArray> jsArray = factory->NewJSArray(); 143 JSHandle<JSTaggedValue> typeString = globalConst->GetHandledTypeString(); 144 JSHandle<JSTaggedValue> valueString = globalConst->GetHandledValueString(); 145 JSHandle<JSTaggedValue> fieldTypeString = globalConst->GetHandledUnitString(); 146 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(static_cast<int>(11))); 147 148 int index = 1; 149 JSHandle<JSObject> recordObj = JSLocale::PutElement(thread, index, jsArray, fieldTypeString, value); 150 EXPECT_EQ(JSTaggedValue::SameValue( 151 JSObject::GetProperty(thread, recordObj, typeString).GetValue(), fieldTypeString), true); 152 EXPECT_EQ(JSObject::GetProperty(thread, recordObj, valueString).GetValue()->GetInt(), 11); 153 154 JSHandle<JSTaggedValue> indexKey(factory->NewFromASCII("1")); 155 EXPECT_TRUE(JSObject::GetProperty(thread, JSHandle<JSObject>(jsArray), indexKey).GetValue()->IsECMAObject()); 156} 157 158/** 159 * @tc.name: GetNumberingSystem 160 * @tc.desc: Call "GetNumberingSystem" function get the script from the ICU Locale. 161 * @tc.type: FUNC 162 * @tc.require: 163 */ 164HWTEST_F_L0(JSLocaleTest, GetNumberingSystem) 165{ 166 icu::Locale icuLocale1("en", "US"); 167 std::string numberingSystem = JSLocale::GetNumberingSystem(icuLocale1); 168 EXPECT_STREQ("latn", numberingSystem.c_str()); 169 170 icu::Locale icuLocale2("zh", "Hans", "CN", "collation=phonebk;numbers=hans"); 171 numberingSystem = JSLocale::GetNumberingSystem(icuLocale2); 172 EXPECT_STREQ("hans", numberingSystem.c_str()); 173} 174 175/** 176 * @tc.name: GetNumberFieldType 177 * @tc.desc: Call "GetNumberFieldType" function get Number Field type. 178 * @tc.type: FUNC 179 * @tc.require: 180 */ 181HWTEST_F_L0(JSLocaleTest, GetNumberFieldType) 182{ 183 auto globalConst = thread->GlobalConstants(); 184 int32_t fieldId = 0; // UNUM_INTEGER_FIELD 185 186 JSTaggedValue x(0.0f / 0.0f); // Nan 187 JSHandle<JSTaggedValue> nanString = globalConst->GetHandledNanString(); 188 JSHandle<JSTaggedValue> fieldTypeString = JSLocale::GetNumberFieldType(thread, x, fieldId); 189 EXPECT_EQ(JSTaggedValue::SameValue(fieldTypeString, nanString), true); 190 191 JSTaggedValue y(-10); // integer(sign bit) 192 JSHandle<JSTaggedValue> integerString = globalConst->GetHandledIntegerString(); 193 fieldTypeString = JSLocale::GetNumberFieldType(thread, y, fieldId); 194 EXPECT_EQ(JSTaggedValue::SameValue(fieldTypeString, integerString), true); 195 196 fieldId = 10; // UNUM_SIGN_FIELD 197 JSHandle<JSTaggedValue> minusSignString = globalConst->GetHandledMinusSignString(); 198 fieldTypeString = JSLocale::GetNumberFieldType(thread, y, fieldId); 199 EXPECT_EQ(JSTaggedValue::SameValue(fieldTypeString, minusSignString), true); 200 201 JSTaggedValue z(10); // no sign bit 202 JSHandle<JSTaggedValue> plusSignString = globalConst->GetHandledPlusSignString(); 203 fieldTypeString = JSLocale::GetNumberFieldType(thread, z, fieldId); 204 EXPECT_EQ(JSTaggedValue::SameValue(fieldTypeString, plusSignString), true); 205} 206 207/** 208 * @tc.name: ApplyOptionsToTag 209 * @tc.desc: Call "ApplyOptionsToTag" function parse information in option into tag string. 210 * @tc.type: FUNC 211 * @tc.require: 212 */ 213HWTEST_F_L0(JSLocaleTest, ApplyOptionsToTag) 214{ 215 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 216 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 217 TagElements tagElements; 218 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction(); 219 JSHandle<EcmaString> languageTag = intl::LocaleHelper::DefaultLocale(thread); 220 221 JSHandle<JSTaggedValue> languageKey = thread->GlobalConstants()->GetHandledLanguageString(); 222 JSHandle<JSTaggedValue> regionKey = thread->GlobalConstants()->GetHandledRegionString(); 223 JSHandle<JSTaggedValue> scriptKey = thread->GlobalConstants()->GetHandledScriptString(); 224 JSHandle<JSTaggedValue> languageValue(factory->NewFromASCII("en")); 225 JSHandle<JSTaggedValue> regionValue(factory->NewFromASCII("US")); 226 JSHandle<JSTaggedValue> scriptValue(factory->NewFromASCII("Latn")); 227 228 JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun); 229 JSObject::SetProperty(thread, optionsObj, languageKey, languageValue); 230 JSObject::SetProperty(thread, optionsObj, regionKey, regionValue); 231 JSObject::SetProperty(thread, optionsObj, scriptKey, scriptValue); 232 bool result = JSLocale::ApplyOptionsToTag(thread, languageTag, optionsObj, tagElements); 233 EXPECT_TRUE(result); 234 EXPECT_EQ(tagElements.language, languageValue); 235 EXPECT_EQ(tagElements.script, scriptValue); 236 EXPECT_EQ(tagElements.region, regionValue); 237 // fault script 238 JSHandle<JSTaggedValue> scriptValue1(factory->NewFromASCII("")); 239 JSObject::SetProperty(thread, optionsObj, scriptKey, scriptValue1); 240 result = JSLocale::ApplyOptionsToTag(thread, languageTag, optionsObj, tagElements); 241 EXPECT_FALSE(result); 242} 243 244/** 245 * @tc.name: ConstructLocaleList 246 * @tc.desc: Get LocaleList numbers through "ConstructLocaleList" function. 247 * @tc.type: FUNC 248 * @tc.require: 249 */ 250HWTEST_F_L0(JSLocaleTest, ConstructLocaleList) 251{ 252 std::vector<std::string> availableLocales = {"zh-Hans-CN", "de-ID", "en-US", "en-GB"}; 253 JSHandle<TaggedArray> localeArr = JSLocale::ConstructLocaleList(thread, availableLocales); 254 EXPECT_EQ(localeArr->GetLength(), 4U); // 4 : 4 Number of locales 255} 256 257/** 258 * @tc.name: SetNumberFormatDigitOptions 259 * @tc.desc: Call "SetNumberFormatDigitOptions" function parse information in option into attributes 260 * of the JSNumberFormat. 261 * @tc.type: FUNC 262 * @tc.require: 263 */ 264HWTEST_F_L0(JSLocaleTest, SetNumberFormatDigitOptions_Significant) 265{ 266 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 267 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 268 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction(); 269 JSHandle<JSTaggedValue> numberFormatObj = env->GetNumberFormatFunction(); 270 271 JSHandle<JSTaggedValue> mnidKey = thread->GlobalConstants()->GetHandledMinimumIntegerDigitsString(); 272 JSHandle<JSTaggedValue> mnsdKey = thread->GlobalConstants()->GetHandledMinimumSignificantDigitsString(); 273 JSHandle<JSTaggedValue> mxsdKey = thread->GlobalConstants()->GetHandledMaximumSignificantDigitsString(); 274 JSHandle<JSTaggedValue> mnidValue(thread, JSTaggedValue(10)); 275 JSHandle<JSTaggedValue> maxFraValue(thread, JSTaggedValue(11)); 276 JSHandle<JSTaggedValue> minSignValue(thread, JSTaggedValue(12)); 277 278 JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun); 279 JSObject::SetProperty(thread, optionsObj, mnidKey, mnidValue); 280 JSObject::SetProperty(thread, optionsObj, mnsdKey, maxFraValue); 281 JSObject::SetProperty(thread, optionsObj, mxsdKey, minSignValue); 282 JSHandle<JSNumberFormat> jsNumberFormat = JSHandle<JSNumberFormat>::Cast( 283 factory->NewJSObjectByConstructor(JSHandle<JSFunction>(numberFormatObj), numberFormatObj)); 284 285 JSLocale::SetNumberFormatDigitOptions(thread, jsNumberFormat, JSHandle<JSTaggedValue>(optionsObj), 286 1, 1, NotationOption::COMPACT); 287 EXPECT_EQ(jsNumberFormat->GetMinimumSignificantDigits().GetInt(), 11); 288 EXPECT_EQ(jsNumberFormat->GetMaximumSignificantDigits().GetInt(), 12); 289 EXPECT_EQ(jsNumberFormat->GetMinimumIntegerDigits().GetInt(), 10); 290 EXPECT_EQ(jsNumberFormat->GetRoundingType(), RoundingType::SIGNIFICANTDIGITS); 291} 292 293HWTEST_F_L0(JSLocaleTest, SetNumberFormatDigitOptions_Fraction) 294{ 295 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 296 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 297 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction(); 298 JSHandle<JSTaggedValue> pluralRulesObj = env->GetPluralRulesFunction(); 299 300 JSHandle<JSTaggedValue> mnidKey = thread->GlobalConstants()->GetHandledMinimumIntegerDigitsString(); 301 JSHandle<JSTaggedValue> mnidValue(thread, JSTaggedValue(10)); 302 303 JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun); 304 JSObject::SetProperty(thread, optionsObj, mnidKey, mnidValue); 305 JSHandle<JSPluralRules> jsPluralRules = JSHandle<JSPluralRules>::Cast( 306 factory->NewJSObjectByConstructor(JSHandle<JSFunction>(pluralRulesObj), pluralRulesObj)); 307 308 JSLocale::SetNumberFormatDigitOptions(thread, jsPluralRules, JSHandle<JSTaggedValue>(optionsObj), 309 10, 13, NotationOption::EXCEPTION); 310 EXPECT_EQ(jsPluralRules->GetMinimumFractionDigits().GetInt(), 10); 311 EXPECT_EQ(jsPluralRules->GetMaximumFractionDigits().GetInt(), 13); 312 EXPECT_EQ(jsPluralRules->GetMinimumIntegerDigits().GetInt(), 10); 313 EXPECT_EQ(jsPluralRules->GetRoundingType(), RoundingType::FRACTIONDIGITS); 314} 315 316/** 317 * @tc.name: CheckLocales 318 * @tc.desc: Call "CheckLocales" function check wether language is correct from locale libraries obtained 319 * from different ways. 320 * @tc.type: FUNC 321 * @tc.require: 322 */ 323HWTEST_F_L0(JSLocaleTest, CheckLocales) 324{ 325 bool res = false; 326 const char *path = JSCollator::uIcuDataColl.c_str(); 327 // default language 328 bool result = JSLocale::CheckLocales("en", nullptr, path, res); 329 EXPECT_TRUE(result); 330 // fault language 331 result = JSLocale::CheckLocales("e", nullptr, path, res); 332 EXPECT_FALSE(result); 333 // find language in calendar 334 result = JSLocale::CheckLocales("en-US", "calendar", nullptr, res); 335 EXPECT_TRUE(result); 336 // find language in NumberElements 337 result = JSLocale::CheckLocales("en-US", "NumberElements", nullptr, res); 338 EXPECT_TRUE(result); 339} 340 341/** 342 * @tc.name: UnicodeExtensionValue 343 * @tc.desc: Call "UnicodeExtensionValue" function get subtag after key in Extension. 344 * @tc.type: FUNC 345 * @tc.require: 346 */ 347HWTEST_F_L0(JSLocaleTest, UnicodeExtensionValue) 348{ 349 // extension has one "-" 350 std::string result = JSLocale::UnicodeExtensionValue("-ca=chinese", "ca"); 351 EXPECT_STREQ(result.c_str(), "undefined"); 352 // extension has one "-" and key value is full 353 result = JSLocale::UnicodeExtensionValue("-ca", "ca"); 354 EXPECT_STREQ(result.c_str(), ""); 355 // extension has two "-" 356 result = JSLocale::UnicodeExtensionValue("-ca-chinese", "ca"); 357 EXPECT_STREQ(result.c_str(), "chinese"); 358 359 result = JSLocale::UnicodeExtensionValue("-ca-chinese-co-compat", "co"); 360 EXPECT_STREQ(result.c_str(), "compat"); 361 362 result = JSLocale::UnicodeExtensionValue("-ca-kn-true", "kn"); 363 EXPECT_STREQ(result.c_str(), "true"); 364} 365 366/** 367 * @tc.name: IsWellCalendar 368 * @tc.desc: Call "IsWellCalendar" function judge whether the calendar is well from locale. 369 * @tc.type: FUNC 370 * @tc.require: 371 */ 372HWTEST_F_L0(JSLocaleTest, IsWellCalendar) 373{ 374 EXPECT_TRUE(JSLocale::IsWellCalendar("ar-EG", "islamic")); 375 EXPECT_TRUE(JSLocale::IsWellCalendar("ar-EG", "coptic")); 376 EXPECT_TRUE(JSLocale::IsWellCalendar("zh-CN", "chinese")); 377 EXPECT_TRUE(JSLocale::IsWellCalendar("en-US", "gregory")); 378 379 EXPECT_FALSE(JSLocale::IsWellCalendar("zh-CN", "English")); 380} 381 382/** 383 * @tc.name: IsWellCollation 384 * @tc.desc: Call "IsWellCollation" function judge whether the collation is well from locale. 385 * @tc.type: FUNC 386 * @tc.require: 387 */ 388HWTEST_F_L0(JSLocaleTest, IsWellCollation) 389{ 390 EXPECT_TRUE(JSLocale::IsWellCollation("ar-EG", "compat")); 391 392 EXPECT_FALSE(JSLocale::IsWellCollation("ar-EG", "stroke")); 393 EXPECT_FALSE(JSLocale::IsWellCollation("ar-EG", "pinyin")); 394 EXPECT_FALSE(JSLocale::IsWellCollation("ar-EG", "phonebk")); 395 EXPECT_FALSE(JSLocale::IsWellCollation("ar-EG", "search")); 396 EXPECT_FALSE(JSLocale::IsWellCollation("ar-EG", "standard")); 397} 398 399/** 400 * @tc.name: IsWellNumberingSystem 401 * @tc.desc: Call "IsWellNumberingSystem" function judge whether the script is well. 402 * @tc.type: FUNC 403 * @tc.require: 404 */ 405HWTEST_F_L0(JSLocaleTest, IsWellNumberingSystem) 406{ 407 EXPECT_FALSE(JSLocale::IsWellNumberingSystem("finance")); 408 EXPECT_FALSE(JSLocale::IsWellNumberingSystem("native")); 409 EXPECT_FALSE(JSLocale::IsWellNumberingSystem("traditio")); 410 411 EXPECT_TRUE(JSLocale::IsWellNumberingSystem("hans")); 412 EXPECT_TRUE(JSLocale::IsWellNumberingSystem("deva")); 413 EXPECT_TRUE(JSLocale::IsWellNumberingSystem("greklow")); 414} 415 416/** 417 * @tc.name: DefaultNumberOption 418 * @tc.desc: Call "DefaultNumberOption" function get default number from value. 419 * @tc.type: FUNC 420 * @tc.require: 421 */ 422HWTEST_F_L0(JSLocaleTest, DefaultNumberOption) 423{ 424 JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(static_cast<double>(4.99))); 425 int result = JSLocale::DefaultNumberOption(thread, value1, 1, 5, 1); 426 EXPECT_EQ(result, 4); 427 JSHandle<JSTaggedValue> value2(thread, JSTaggedValue::Undefined()); 428 result = JSLocale::DefaultNumberOption(thread, value2, 1, 5, 1); 429 EXPECT_EQ(result, 1); 430} 431 432JSHandle<JSObject> GetOptionCommon(JSThread *thread, JSHandle<JSTaggedValue>& languageProperty, 433 JSHandle<JSTaggedValue>& languageValue) 434{ 435 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 436 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 437 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction(); 438 // Set key value 439 JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun); 440 JSObject::SetProperty(thread, optionsObj, languageProperty, languageValue); 441 return optionsObj; 442} 443/** 444 * @tc.name: GetOptionOfString 445 * @tc.desc: Call "GetOptionOfString" function get the string from Option value. 446 * @tc.type: FUNC 447 * @tc.require: 448 */ 449HWTEST_F_L0(JSLocaleTest, GetOptionOfString) 450{ 451 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 452 JSHandle<JSTaggedValue> languageProperty = thread->GlobalConstants()->GetHandledLanguageString(); 453 JSHandle<JSTaggedValue> regionProperty = thread->GlobalConstants()->GetHandledRegionString(); 454 JSHandle<JSTaggedValue> regionValue(factory->NewFromASCII("CN")); 455 JSHandle<JSTaggedValue> languageValue(factory->NewFromASCII("zh")); 456 // Set key value 457 JSHandle<JSObject> optionsObj = GetOptionCommon(thread, languageProperty, languageValue); 458 JSObject::SetProperty(thread, optionsObj, regionProperty, regionValue); 459 std::vector<std::string> stringValues = {"zh", "Hans", "CN"}; 460 std::string optionValue; 461 // Get language 462 bool result = JSLocale::GetOptionOfString(thread, optionsObj, languageProperty, stringValues, &optionValue); 463 EXPECT_TRUE(result); 464 EXPECT_STREQ(optionValue.c_str(), "zh"); 465 // Get region 466 result = JSLocale::GetOptionOfString(thread, optionsObj, regionProperty, stringValues, &optionValue); 467 EXPECT_TRUE(result); 468 EXPECT_STREQ(optionValue.c_str(), "CN"); 469} 470 471/** 472 * @tc.name: GetOption 473 * @tc.desc: Call "GetOption" function get value of the key from Option. 474 * @tc.type: FUNC 475 * @tc.require: 476 */ 477HWTEST_F_L0(JSLocaleTest, GetOption) 478{ 479 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 480 JSHandle<JSTaggedValue> languageProperty = thread->GlobalConstants()->GetHandledLanguageString(); 481 JSHandle<JSTaggedValue> regionProperty = thread->GlobalConstants()->GetHandledRegionString(); 482 JSHandle<JSTaggedValue> regionValue(factory->NewFromASCII("CN")); 483 JSHandle<JSTaggedValue> languageValue(factory->NewFromASCII("zh")); 484 // Set key value 485 JSHandle<JSObject> optionsObj = GetOptionCommon(thread, languageProperty, languageValue); 486 JSHandle<TaggedArray> stringValues = factory->NewTaggedArray(3); 487 stringValues->Set(thread, 0, languageValue); 488 stringValues->Set(thread, 1, regionValue); 489 JSHandle<JSTaggedValue> arrayValue(stringValues); 490 JSHandle<JSTaggedValue> fallback(thread, JSTaggedValue::Undefined()); 491 492 JSHandle<JSTaggedValue> optionValue = 493 JSLocale::GetOption(thread, optionsObj, languageProperty, OptionType::STRING, arrayValue, fallback); 494 EXPECT_EQ(JSTaggedValue::SameValue(optionValue, languageValue), true); 495 496 optionValue = JSLocale::GetOption(thread, optionsObj, regionProperty, OptionType::STRING, arrayValue, fallback); 497 EXPECT_EQ(JSTaggedValue::SameValue(optionValue, fallback), true); 498} 499 500/** 501 * @tc.name: GetOptionOfBool 502 * @tc.desc: Call "GetOptionOfBool" function get the bool value from Option. 503 * @tc.type: FUNC 504 * @tc.require: 505 */ 506HWTEST_F_L0(JSLocaleTest, GetOptionOfBool) 507{ 508 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 509 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 510 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction(); 511 512 JSHandle<JSTaggedValue> numericProperty = thread->GlobalConstants()->GetHandledNumericString(); 513 JSHandle<JSTaggedValue> numericValue(thread, JSTaggedValue::True()); 514 // Set key value 515 JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun); 516 JSObject::SetProperty(thread, optionsObj, numericProperty, numericValue); 517 bool res; 518 // Test correct keyValue 519 EXPECT_TRUE(JSLocale::GetOptionOfBool(thread, optionsObj, numericProperty, false, &res)); 520 EXPECT_TRUE(res); 521 522 JSHandle<JSTaggedValue> numericValue1(thread, JSTaggedValue(0)); 523 JSObject::SetProperty(thread, optionsObj, numericProperty, numericValue1); 524 // Test fault keyValue 525 EXPECT_TRUE(JSLocale::GetOptionOfBool(thread, optionsObj, numericProperty, false, &res)); 526 EXPECT_FALSE(res); 527} 528 529ResolvedLocale ResolveLocaleCommon(JSThread *thread, JSHandle<TaggedArray> &availableLocales, 530 JSHandle<TaggedArray> &requestedLocales, 531 std::set<std::string> &relevantExtensionKeys, JSHandle<JSTaggedValue> &testLocale1) 532{ 533 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 534 ResolvedLocale result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales, 535 LocaleMatcherOption::BEST_FIT, relevantExtensionKeys); 536 EXPECT_STREQ("en-US", result.locale.c_str()); // default locale 537 // availableLocales and requestLocales is not empty 538 std::vector<std::string> availableStringLocales = 539 intl::LocaleHelper::GetAvailableLocales(thread, "calendar", nullptr); 540 availableLocales = JSLocale::ConstructLocaleList(thread, availableStringLocales); 541 requestedLocales = factory->NewTaggedArray(1); 542 // test locale1 543 requestedLocales->Set(thread, 0, testLocale1); 544 result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales, LocaleMatcherOption::BEST_FIT, 545 relevantExtensionKeys); 546 return result; 547} 548 549/** 550 * @tc.name: ResolveLocale 551 * @tc.desc: Resolve Locale and return from available locale through "ResolveLocale" function. 552 * @tc.type: FUNC 553 * @tc.require: 554 */ 555HWTEST_F_L0(JSLocaleTest, ResolveLocale_001) 556{ 557 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 558 JSHandle<TaggedArray> availableLocales = factory->EmptyArray(); 559 JSHandle<TaggedArray> requestedLocales = factory->EmptyArray(); 560 std::set<std::string> relevantExtensionKeys = {"co", "ca"}; 561 JSHandle<JSTaggedValue> testLocale1(factory->NewFromASCII("id-u-co-pinyin-ca-gregory-de-ID")); 562 JSHandle<JSTaggedValue> testLocale2(factory->NewFromASCII("en-Latn-US-u-co-phonebk-ca-ethioaa")); 563 // availableLocales and requestLocales is empty 564 auto result = ResolveLocaleCommon(thread, availableLocales, requestedLocales, relevantExtensionKeys, testLocale1); 565 EXPECT_STREQ("id-u-ca-gregory-co-pinyin-de-id", result.locale.c_str()); 566 result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales, 567 LocaleMatcherOption::LOOKUP, relevantExtensionKeys); 568 EXPECT_STREQ("id-u-ca-gregory-co-pinyin-de-id", result.locale.c_str()); 569 result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales, 570 LocaleMatcherOption::EXCEPTION, relevantExtensionKeys); 571 EXPECT_STREQ("id-u-ca-gregory-co-pinyin-de-id", result.locale.c_str()); 572 // test locale2 573 requestedLocales->Set(thread, 0, testLocale2); 574 result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales, 575 LocaleMatcherOption::BEST_FIT, relevantExtensionKeys); 576 EXPECT_STREQ("en-u-ca-ethioaa-co-phonebk", result.locale.c_str()); 577 result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales, 578 LocaleMatcherOption::LOOKUP, relevantExtensionKeys); 579 EXPECT_STREQ("en-u-ca-ethioaa-co-phonebk", result.locale.c_str()); 580 result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales, 581 LocaleMatcherOption::EXCEPTION, relevantExtensionKeys); 582 EXPECT_STREQ("en-u-ca-ethioaa-co-phonebk", result.locale.c_str()); 583} 584 585HWTEST_F_L0(JSLocaleTest, ResolveLocale_002) 586{ 587 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 588 JSHandle<TaggedArray> availableLocales = factory->EmptyArray(); 589 JSHandle<TaggedArray> requestedLocales = factory->EmptyArray(); 590 std::set<std::string> relevantExtensionKeys = {"hc", "lb", "kn", "kf"}; 591 JSHandle<JSTaggedValue> testLocale1(factory->NewFromASCII("id-u-kn-false-kf-yes-de-ID")); 592 JSHandle<JSTaggedValue> testLocale2(factory->NewFromASCII("en-US-u-hc-h24-lb-strict")); 593 // availableLocales and requestLocales is empty 594 auto result = ResolveLocaleCommon(thread, availableLocales, requestedLocales, relevantExtensionKeys, testLocale1); 595 EXPECT_STREQ("id-u-de-id-kf-kn-false", result.locale.c_str()); 596 result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales, 597 LocaleMatcherOption::LOOKUP, relevantExtensionKeys); 598 EXPECT_STREQ("id-u-de-id-kf-kn-false", result.locale.c_str()); 599 result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales, 600 LocaleMatcherOption::EXCEPTION, relevantExtensionKeys); 601 EXPECT_STREQ("id-u-de-id-kf-kn-false", result.locale.c_str()); 602 // test locale2 603 requestedLocales->Set(thread, 0, testLocale2); 604 result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales, 605 LocaleMatcherOption::BEST_FIT, relevantExtensionKeys); 606 EXPECT_STREQ("en-US-u-hc-h24-lb-strict", result.locale.c_str()); 607 result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales, 608 LocaleMatcherOption::LOOKUP, relevantExtensionKeys); 609 EXPECT_STREQ("en-US-u-hc-h24-lb-strict", result.locale.c_str()); 610 result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales, 611 LocaleMatcherOption::EXCEPTION, relevantExtensionKeys); 612 EXPECT_STREQ("en-US-u-hc-h24-lb-strict", result.locale.c_str()); 613} 614} // namespace panda::test 615