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/tests/test_helper.h"
22
23 using namespace panda::ecmascript;
24
25 namespace panda::test {
26 class JSLocaleTest : public testing::Test {
27 public:
SetUpTestCase()28 static void SetUpTestCase()
29 {
30 GTEST_LOG_(INFO) << "SetUpTestCase";
31 }
32
TearDownTestCase()33 static void TearDownTestCase()
34 {
35 GTEST_LOG_(INFO) << "TearDownCase";
36 }
37
SetUp()38 void SetUp() override
39 {
40 JSRuntimeOptions options;
41 #if PANDA_TARGET_LINUX
42 // for consistency requirement, use ohos_icu4j/data as icu-data-path
43 options.SetIcuDataPath(ICU_PATH);
44 #endif
45 options.SetEnableForceGC(true);
46 instance = JSNApi::CreateEcmaVM(options);
47 instance->SetEnableForceGC(true);
48 ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM";
49 thread = instance->GetJSThread();
50 scope = new EcmaHandleScope(thread);
51 }
52
TearDown()53 void TearDown() override
54 {
55 TestHelper::DestroyEcmaVMWithScope(instance, scope);
56 }
57
58 EcmaVM *instance {nullptr};
59 ecmascript::EcmaHandleScope *scope {nullptr};
60 JSThread *thread {nullptr};
61 };
62
CreateLanguageIterator(std::vector<std::string> & languageTemp)63 void CreateLanguageIterator(std::vector<std::string>& languageTemp)
64 {
65 languageTemp.push_back("zh-Hans-Cn");
66 languageTemp.push_back("ko-kore-kr");
67 languageTemp.push_back("fr-FR");
68 languageTemp.push_back("en-Latn-US");
69 languageTemp.push_back("ja-JP-u-ca-japanese");
70 languageTemp.push_back("ar-EG");
71 }
72
73 /**
74 * @tc.name: JSIntlIteratorTest
75 * @tc.desc: Construct an iterator of JSIntl and then traverse the iterator to compare whether the variable
76 * at each position is equal to the setting.
77 * @tc.type: FUNC
78 * @tc.require:
79 */
HWTEST_F_L0(JSLocaleTest,JSIntlIteratorTest)80 HWTEST_F_L0(JSLocaleTest, JSIntlIteratorTest)
81 {
82 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
83 std::vector<std::string> languageVector;
84 CreateLanguageIterator(languageVector);
85 uint32_t arrayDataLength = languageVector.size();
86 JSHandle<TaggedArray> arrayData = factory->NewTaggedArray(arrayDataLength);
87
88 for (uint32_t i = 0 ; i < arrayDataLength; i++) {
89 JSHandle<JSTaggedValue> languageStr(factory->NewFromASCII(languageVector[i].c_str()));
90 arrayData->Set(thread, i, languageStr);
91 }
92 // construct a JSIntlIterator object
93 JSIntlIterator jsIntlIterator(arrayData, arrayDataLength);
94 EXPECT_TRUE(jsIntlIterator.hasNext());
95 // call "next" function to traverse the container
96 for (uint32_t i = 0 ; i < arrayDataLength; i++) {
97 EXPECT_TRUE(jsIntlIterator.next() != nullptr);
98 EXPECT_STREQ(jsIntlIterator[i].c_str(), languageVector[i].c_str());
99 }
100 EXPECT_FALSE(jsIntlIterator.hasNext());
101 }
102
103 /**
104 * @tc.name: IsPrivateSubTag
105 * @tc.desc: Check whether the string is private subtag through "IsPrivateSubTag" function.
106 * @tc.type: FUNC
107 * @tc.require:
108 */
HWTEST_F_L0(JSLocaleTest,IsPrivateSubTag)109 HWTEST_F_L0(JSLocaleTest, IsPrivateSubTag)
110 {
111 std::string result = "en-GB-oed";
112 EXPECT_FALSE(JSLocale::IsPrivateSubTag(result, result.length()));
113
114 result = "i-ami";
115 EXPECT_TRUE(JSLocale::IsPrivateSubTag(result, result.length()));
116
117 result = "x-default";
118 EXPECT_TRUE(JSLocale::IsPrivateSubTag(result, result.length()));
119 }
120
121 /**
122 * @tc.name: GetIcuField
123 * @tc.desc: Call "NewJSIntlIcuData" function Set locale IcuField,check whether the locale IcuField through
124 * "getBaseName" function is within expectations.
125 * @tc.type: FUNC
126 * @tc.require:
127 */
HWTEST_F_L0(JSLocaleTest,GetIcuField)128 HWTEST_F_L0(JSLocaleTest, GetIcuField)
129 {
130 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
131 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
132 JSHandle<JSTaggedValue> ctor = env->GetLocaleFunction();
133 JSHandle<JSLocale> locale =
134 JSHandle<JSLocale>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor), ctor));
135 // call "NewJSIntlIcuData" function Set IcuField
136 icu::Locale icuLocale("zh", "Hans", "Cn");
137 factory->NewJSIntlIcuData(locale, icuLocale, JSLocale::FreeIcuLocale);
138
139 // call "GetIcuLocale" function Get IcuField
140 icu::Locale *result = locale->GetIcuLocale();
141 EXPECT_STREQ(result->getBaseName(), "zh_Hans_CN");
142 }
143
144 /**
145 * @tc.name: ConvertToStdString
146 * @tc.desc: Convert char* type to std string,check whether the returned string through "ConvertToStdString"
147 * function is within expectations.
148 * @tc.type: FUNC
149 * @tc.require:
150 */
HWTEST_F_L0(JSLocaleTest,ConvertToStdString)151 HWTEST_F_L0(JSLocaleTest, ConvertToStdString)
152 {
153 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
154 JSHandle<EcmaString> handleEcmaStr = factory-> NewFromStdString("一二三四");
155 std::string stdString = JSLocale::ConvertToStdString(handleEcmaStr);
156 EXPECT_STREQ(stdString.c_str(), "一二三四");
157
158 handleEcmaStr = factory-> NewFromStdString("#%!\0@$");
159 stdString = JSLocale::ConvertToStdString(handleEcmaStr);
160 EXPECT_STREQ(stdString.c_str(), "#%!\0@$");
161
162 handleEcmaStr = factory-> NewFromStdString("123456");
163 stdString = JSLocale::ConvertToStdString(handleEcmaStr);
164 EXPECT_STREQ(stdString.c_str(), "123456");
165
166 handleEcmaStr = factory-> NewFromStdString("zhde");
167 stdString = JSLocale::ConvertToStdString(handleEcmaStr);
168 EXPECT_STREQ(stdString.c_str(), "zhde");
169 }
170
171 /**
172 * @tc.name: IsStructurallyValidLanguageTag
173 * @tc.desc: Call "IsStructurallyValidLanguageTag" function check Language-Tag is valid structurally.If the tag contains
174 * the correct language, region, script and extension, return true otherwise, return false.
175 * @tc.type: FUNC
176 * @tc.require:
177 */
HWTEST_F_L0(JSLocaleTest,IsStructurallyValidLanguageTag)178 HWTEST_F_L0(JSLocaleTest, IsStructurallyValidLanguageTag)
179 {
180 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
181 // number-language
182 JSHandle<EcmaString> handleEcmaStr = factory->NewFromStdString("123-de");
183 EXPECT_FALSE(JSLocale::IsStructurallyValidLanguageTag(handleEcmaStr));
184 // only language(zh)
185 handleEcmaStr = factory-> NewFromStdString("zh");
186 EXPECT_TRUE(JSLocale::IsStructurallyValidLanguageTag(handleEcmaStr));
187 // only language and script, region
188 handleEcmaStr = factory-> NewFromStdString("zh-Hans-Cn");
189 EXPECT_TRUE(JSLocale::IsStructurallyValidLanguageTag(handleEcmaStr));
190
191 handleEcmaStr = factory-> NewFromStdString("ja-JP-u-ca-japanese");
192 EXPECT_TRUE(JSLocale::IsStructurallyValidLanguageTag(handleEcmaStr));
193
194 handleEcmaStr = factory-> NewFromStdString("语言脚本地区");
195 EXPECT_FALSE(JSLocale::IsStructurallyValidLanguageTag(handleEcmaStr));
196
197 handleEcmaStr = factory-> NewFromStdString("e-US");
198 EXPECT_FALSE(JSLocale::IsStructurallyValidLanguageTag(handleEcmaStr));
199 }
200
201 /**
202 * @tc.name: CanonicalizeUnicodeLocaleId
203 * @tc.desc: Call "CanonicalizeUnicodeLocaleId" function canonicalize locale(Language-Tag),The English case of language,
204 * region and script is fixed.the language is lowercase.the beginning of region is uppercase, and the script
205 * is lowercase.if locale string is IsUtf16,return empty string.
206 * @tc.type: FUNC
207 * @tc.require:
208 */
HWTEST_F_L0(JSLocaleTest,CanonicalizeUnicodeLocaleId)209 HWTEST_F_L0(JSLocaleTest, CanonicalizeUnicodeLocaleId)
210 {
211 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
212
213 JSHandle<EcmaString> locale = factory-> NewFromStdString("en-Us");
214 JSHandle<EcmaString> canonicalizeLocaleId = JSLocale::CanonicalizeUnicodeLocaleId(thread, locale);
215 EXPECT_STREQ("en-US", EcmaStringAccessor(canonicalizeLocaleId).ToCString().c_str());
216
217 locale = factory-> NewFromStdString("kO-kore-kr");
218 canonicalizeLocaleId = JSLocale::CanonicalizeUnicodeLocaleId(thread, locale);
219 EXPECT_STREQ("ko-Kore-KR", EcmaStringAccessor(canonicalizeLocaleId).ToCString().c_str());
220
221 locale = factory-> NewFromStdString("id-u-co-pinyin-de-ID");
222 canonicalizeLocaleId = JSLocale::CanonicalizeUnicodeLocaleId(thread, locale);
223 EXPECT_STREQ("id-u-co-pinyin-de-id", EcmaStringAccessor(canonicalizeLocaleId).ToCString().c_str());
224 // invalid locale
225 uint16_t localeArr[] = {0x122, 0x104, 0x45, 0x72, 0x97, 0x110, 0x115, 0x45, 0x67, 0x78}; // zh-Hans-CN
226 uint32_t localeArrLength = sizeof(localeArr) / sizeof(localeArr[0]);
227 locale = factory->NewFromUtf16(localeArr, localeArrLength);
228
229 canonicalizeLocaleId = JSLocale::CanonicalizeUnicodeLocaleId(thread, locale);
230 JSHandle<EcmaString> emptyString = factory->GetEmptyString();
231 EXPECT_EQ(EcmaStringAccessor::Compare(*canonicalizeLocaleId, *emptyString), 0);
232 }
233
234 /**
235 * @tc.name: IsValidTimeZoneName
236 * @tc.desc: Call "IsValidTimeZoneName" function check whether the TimeZone is valid.if TimeZone include "GMT-Time"
237 * return true otherwise, return false.
238 * @tc.type: FUNC
239 * @tc.require:
240 */
HWTEST_F_L0(JSLocaleTest,IsValidTimeZoneName)241 HWTEST_F_L0(JSLocaleTest, IsValidTimeZoneName)
242 {
243 icu::UnicodeString stringID1("GMT-8:00");
244 icu::TimeZone *timeZone = icu::TimeZone::createTimeZone(stringID1);
245 EXPECT_TRUE(JSLocale::IsValidTimeZoneName(*timeZone));
246 delete timeZone;
247
248 icu::UnicodeString stringID2("Etc/Unknown");
249 timeZone = icu::TimeZone::createTimeZone(stringID2);
250 EXPECT_FALSE(JSLocale::IsValidTimeZoneName(*timeZone));
251 delete timeZone;
252 }
253
254 /**
255 * @tc.name: CanonicalizeLocaleList
256 * @tc.desc: Create a list of locales and canonicalize the locales in the list through "CanonicalizeUnicodeLocaleId"
257 * function.
258 * @tc.type: FUNC
259 * @tc.require:
260 */
HWTEST_F_L0(JSLocaleTest,CanonicalizeLocaleList)261 HWTEST_F_L0(JSLocaleTest, CanonicalizeLocaleList)
262 {
263 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
264 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
265 JSHandle<JSTaggedValue> ctor = env->GetLocaleFunction();
266 JSHandle<JSLocale> jsLocale =
267 JSHandle<JSLocale>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor), ctor));
268 // Set IcuLocale
269 icu::Locale icuLocale("fr", "Latn", "Fr");
270 factory->NewJSIntlIcuData(jsLocale, icuLocale, JSLocale::FreeIcuLocale);
271 // test locale is jslocale
272 JSHandle<TaggedArray> localeArr = JSLocale::CanonicalizeLocaleList(thread, JSHandle<JSTaggedValue>(jsLocale));
273 EXPECT_EQ(localeArr->GetLength(), 1U);
274 JSHandle<EcmaString> handleEcmaStr(thread, localeArr->Get(0));
275 EXPECT_STREQ("fr-Latn-FR", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
276 // test locale is object
277 JSArray *arr = JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetObject<JSArray>();
278 JSHandle<JSTaggedValue> localeObj(thread, arr);
279
280 JSHandle<JSTaggedValue> localeStr1(factory->NewFromASCII("EN-us"));
281 PropertyDescriptor desc1(thread, localeStr1, true, true, true);
282 JSHandle<JSTaggedValue> key1(factory->NewFromASCII("1"));
283 JSArray::DefineOwnProperty(thread, JSHandle<JSObject>(localeObj), key1, desc1);
284
285 JSHandle<JSTaggedValue> localeStr2(factory->NewFromASCII("en-GB"));
286 PropertyDescriptor desc2(thread, localeStr2, true, true, true);
287 JSHandle<JSTaggedValue> key2(factory->NewFromASCII("2"));
288 JSArray::DefineOwnProperty(thread, JSHandle<JSObject>(localeObj), key2, desc2);
289 // check canonicalized string
290 localeArr = JSLocale::CanonicalizeLocaleList(thread, localeObj);
291 EXPECT_EQ(localeArr->GetLength(), 2U);
292 JSHandle<EcmaString> resultEcmaStr1(thread, localeArr->Get(0));
293 EXPECT_STREQ("en-US", EcmaStringAccessor(resultEcmaStr1).ToCString().c_str());
294 JSHandle<EcmaString> resultEcmaStr2(thread, localeArr->Get(1));
295 EXPECT_STREQ("en-GB", EcmaStringAccessor(resultEcmaStr2).ToCString().c_str());
296 }
297
298 /**
299 * @tc.name: IcuToString
300 * @tc.desc: Call "IcuToString" function Convert UnicodeString to string(Utf16).
301 * @tc.type: FUNC
302 * @tc.require:
303 */
HWTEST_F_L0(JSLocaleTest,IcuToString)304 HWTEST_F_L0(JSLocaleTest, IcuToString)
305 {
306 icu::UnicodeString unicodeString1("GMT-12:00"); // times
307 JSHandle<EcmaString> ecmaString = JSLocale::IcuToString(thread, unicodeString1);
308 EXPECT_STREQ("GMT-12:00", EcmaStringAccessor(ecmaString).ToCString().c_str());
309
310 icu::UnicodeString unicodeString2("周日16:00:00–周五23:00:00"); // date
311 ecmaString = JSLocale::IcuToString(thread, unicodeString2);
312 EXPECT_STREQ("周日16:00:00–周五23:00:00", EcmaStringAccessor(ecmaString).ToCString().c_str());
313
314 icu::UnicodeString unicodeString3("$654K"); // money
315 ecmaString = JSLocale::IcuToString(thread, unicodeString3);
316 EXPECT_STREQ("$654K", EcmaStringAccessor(ecmaString).ToCString().c_str());
317
318 icu::UnicodeString unicodeString4("1 minute ago"); // moment
319 ecmaString = JSLocale::IcuToString(thread, unicodeString4, 0, 2);
320 EXPECT_STREQ("1 ", EcmaStringAccessor(ecmaString).ToCString().c_str());
321 }
322
323 /**
324 * @tc.name: PutElement
325 * @tc.desc: Put elements in empty JSArray and return the JSArray.call "GetProperty" function to get the value and
326 * check whether the value is consistent with the value of the put.
327 * @tc.type: FUNC
328 * @tc.require:
329 */
HWTEST_F_L0(JSLocaleTest,PutElement)330 HWTEST_F_L0(JSLocaleTest, PutElement)
331 {
332 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
333 auto globalConst = thread->GlobalConstants();
334 JSHandle<JSArray> jsArray = factory->NewJSArray();
335 JSHandle<JSTaggedValue> typeString = globalConst->GetHandledTypeString();
336 JSHandle<JSTaggedValue> valueString = globalConst->GetHandledValueString();
337 JSHandle<JSTaggedValue> fieldTypeString = globalConst->GetHandledUnitString();
338 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(static_cast<int>(11)));
339
340 int index = 1;
341 JSHandle<JSObject> recordObj = JSLocale::PutElement(thread, index, jsArray, fieldTypeString, value);
342 EXPECT_EQ(JSTaggedValue::SameValue(
343 JSObject::GetProperty(thread, recordObj, typeString).GetValue(), fieldTypeString), true);
344 EXPECT_EQ(JSObject::GetProperty(thread, recordObj, valueString).GetValue()->GetInt(), 11);
345
346 JSHandle<JSTaggedValue> indexKey(factory->NewFromASCII("1"));
347 EXPECT_TRUE(JSObject::GetProperty(thread, JSHandle<JSObject>(jsArray), indexKey).GetValue()->IsECMAObject());
348 }
349
350 /**
351 * @tc.name: ToLanguageTag
352 * @tc.desc: call "ToLanguageTag" function Convert ICU Locale into language tag.
353 * @tc.type: FUNC
354 * @tc.require:
355 */
HWTEST_F_L0(JSLocaleTest,ToLanguageTag)356 HWTEST_F_L0(JSLocaleTest, ToLanguageTag)
357 {
358 icu::Locale icuLocale1("en", "Latn", "US", "collation=phonebk;currency=euro");
359 JSHandle<EcmaString> languageTag = JSLocale::ToLanguageTag(thread, icuLocale1);
360 EXPECT_STREQ("en-Latn-US-u-co-phonebk-cu-euro", EcmaStringAccessor(languageTag).ToCString().c_str());
361
362 icu::Locale icuLocale2("zh", "Hans", "CN", "collation=phonebk;kn=true");
363 languageTag = JSLocale::ToLanguageTag(thread, icuLocale2);
364 EXPECT_STREQ("zh-Hans-CN-u-co-phonebk-kn", EcmaStringAccessor(languageTag).ToCString().c_str());
365
366 icu::Locale icuLocale3("ja", "Jpan", "JP", "collation=phonebk;co=yes");
367 languageTag = JSLocale::ToLanguageTag(thread, icuLocale3);
368 EXPECT_STREQ("ja-Jpan-JP-u-co", EcmaStringAccessor(languageTag).ToCString().c_str());
369
370 icu::Locale icuLocale4("z", "CN"); // language is fault
371 languageTag = JSLocale::ToLanguageTag(thread, icuLocale4);
372 EXPECT_STREQ("und-CN", EcmaStringAccessor(languageTag).ToCString().c_str());
373
374 icu::Locale icuLocale5("zh", "c"); // script is fault
375 languageTag = JSLocale::ToLanguageTag(thread, icuLocale5);
376 EXPECT_STREQ("zh-x-lvariant-c", EcmaStringAccessor(languageTag).ToCString().c_str());
377
378 icu::Locale icuLocale6("en", "Latn", "E"); // region is fault
379 languageTag = JSLocale::ToLanguageTag(thread, icuLocale6);
380 EXPECT_STREQ("en-Latn-x-lvariant-e", EcmaStringAccessor(languageTag).ToCString().c_str());
381
382 icu::Locale icuLocale7("en", "Latn", "EG", "kf=yes"); // key value is fault
383 languageTag = JSLocale::ToLanguageTag(thread, icuLocale7);
384 EXPECT_STREQ("en-Latn-EG-u-kf", EcmaStringAccessor(languageTag).ToCString().c_str());
385 }
386
387 /**
388 * @tc.name: GetNumberingSystem
389 * @tc.desc: Call "GetNumberingSystem" function get the script from the ICU Locale.
390 * @tc.type: FUNC
391 * @tc.require:
392 */
HWTEST_F_L0(JSLocaleTest,GetNumberingSystem)393 HWTEST_F_L0(JSLocaleTest, GetNumberingSystem)
394 {
395 icu::Locale icuLocale1("en", "US");
396 std::string numberingSystem = JSLocale::GetNumberingSystem(icuLocale1);
397 EXPECT_STREQ("latn", numberingSystem.c_str());
398
399 icu::Locale icuLocale2("zh", "Hans", "CN", "collation=phonebk;numbers=hans");
400 numberingSystem = JSLocale::GetNumberingSystem(icuLocale2);
401 EXPECT_STREQ("hans", numberingSystem.c_str());
402 }
403
404 /**
405 * @tc.name: GetNumberFieldType
406 * @tc.desc: Call "GetNumberFieldType" function get Number Field type.
407 * @tc.type: FUNC
408 * @tc.require:
409 */
HWTEST_F_L0(JSLocaleTest,GetNumberFieldType)410 HWTEST_F_L0(JSLocaleTest, GetNumberFieldType)
411 {
412 auto globalConst = thread->GlobalConstants();
413 int32_t fieldId = 0; // UNUM_INTEGER_FIELD
414
415 JSTaggedValue x(0.0f / 0.0f); // Nan
416 JSHandle<JSTaggedValue> nanString = globalConst->GetHandledNanString();
417 JSHandle<JSTaggedValue> fieldTypeString = JSLocale::GetNumberFieldType(thread, x, fieldId);
418 EXPECT_EQ(JSTaggedValue::SameValue(fieldTypeString, nanString), true);
419
420 JSTaggedValue y(-10); // integer(sign bit)
421 JSHandle<JSTaggedValue> integerString = globalConst->GetHandledIntegerString();
422 fieldTypeString = JSLocale::GetNumberFieldType(thread, y, fieldId);
423 EXPECT_EQ(JSTaggedValue::SameValue(fieldTypeString, integerString), true);
424
425 fieldId = 10; // UNUM_SIGN_FIELD
426 JSHandle<JSTaggedValue> minusSignString = globalConst->GetHandledMinusSignString();
427 fieldTypeString = JSLocale::GetNumberFieldType(thread, y, fieldId);
428 EXPECT_EQ(JSTaggedValue::SameValue(fieldTypeString, minusSignString), true);
429
430 JSTaggedValue z(10); // no sign bit
431 JSHandle<JSTaggedValue> plusSignString = globalConst->GetHandledPlusSignString();
432 fieldTypeString = JSLocale::GetNumberFieldType(thread, z, fieldId);
433 EXPECT_EQ(JSTaggedValue::SameValue(fieldTypeString, plusSignString), true);
434 }
435
436 /**
437 * @tc.name: ApplyOptionsToTag
438 * @tc.desc: Call "ApplyOptionsToTag" function parse information in option into tag string.
439 * @tc.type: FUNC
440 * @tc.require:
441 */
HWTEST_F_L0(JSLocaleTest,ApplyOptionsToTag)442 HWTEST_F_L0(JSLocaleTest, ApplyOptionsToTag)
443 {
444 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
445 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
446 TagElements tagElements;
447 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
448 JSHandle<EcmaString> languageTag = JSLocale::DefaultLocale(thread);
449
450 JSHandle<JSTaggedValue> languageKey = thread->GlobalConstants()->GetHandledLanguageString();
451 JSHandle<JSTaggedValue> regionKey = thread->GlobalConstants()->GetHandledRegionString();
452 JSHandle<JSTaggedValue> scriptKey = thread->GlobalConstants()->GetHandledScriptString();
453 JSHandle<JSTaggedValue> languageValue(factory->NewFromASCII("en"));
454 JSHandle<JSTaggedValue> regionValue(factory->NewFromASCII("US"));
455 JSHandle<JSTaggedValue> scriptValue(factory->NewFromASCII("Latn"));
456
457 JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
458 JSObject::SetProperty(thread, optionsObj, languageKey, languageValue);
459 JSObject::SetProperty(thread, optionsObj, regionKey, regionValue);
460 JSObject::SetProperty(thread, optionsObj, scriptKey, scriptValue);
461 bool result = JSLocale::ApplyOptionsToTag(thread, languageTag, optionsObj, tagElements);
462 EXPECT_TRUE(result);
463 EXPECT_EQ(tagElements.language, languageValue);
464 EXPECT_EQ(tagElements.script, scriptValue);
465 EXPECT_EQ(tagElements.region, regionValue);
466 // fault script
467 JSHandle<JSTaggedValue> scriptValue1(factory->NewFromASCII(""));
468 JSObject::SetProperty(thread, optionsObj, scriptKey, scriptValue1);
469 result = JSLocale::ApplyOptionsToTag(thread, languageTag, optionsObj, tagElements);
470 EXPECT_FALSE(result);
471 }
472
473 /**
474 * @tc.name: HandleLocaleExtension
475 * @tc.desc: Find position of subtag "x" or "u" in Locale through "HandleLocaleExtension" function.
476 * @tc.type: FUNC
477 * @tc.require:
478 */
HWTEST_F_L0(JSLocaleTest,HandleLocaleExtension)479 HWTEST_F_L0(JSLocaleTest, HandleLocaleExtension)
480 {
481 std::string result = "en-Latn-US-u-ca-gregory-co-compat";
482 size_t start = 0;
483 size_t extensionEnd = 0;
484 JSLocale::HandleLocaleExtension(start, extensionEnd, result, result.size());
485 EXPECT_EQ(extensionEnd, 10U); // the position of "u"
486 // private extension("x")
487 result = "de-zh-x-co-phonebk-nu-kali";
488 start = 0;
489 extensionEnd = 0;
490 JSLocale::HandleLocaleExtension(start, extensionEnd, result, result.size());
491 EXPECT_EQ(extensionEnd, 5U); // the position of "x"
492 }
493
494 /**
495 * @tc.name: HandleLocale
496 * @tc.desc: Call "HandleLocale" function handle locale,if Locale has subtag "u" ignore it.If Locale has
497 * both subtag "x" and "u","x" is in front of "u","u" does not ignore,"x" is after "u","u" ignores.
498 * @tc.type: FUNC
499 * @tc.require:
500 */
HWTEST_F_L0(JSLocaleTest,HandleLocale)501 HWTEST_F_L0(JSLocaleTest, HandleLocale)
502 {
503 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
504 // no "u" or "x"
505 JSHandle<EcmaString> localeString = factory->NewFromASCII("en-Latn-US");
506 JSLocale::ParsedLocale parsedResult = JSLocale::HandleLocale(localeString);
507 EXPECT_STREQ(parsedResult.base.c_str(), "en-Latn-US");
508 // only "x"
509 localeString = factory->NewFromASCII("zh-CN-x-ca-pinyin");
510 parsedResult = JSLocale::HandleLocale(localeString);
511 EXPECT_STREQ(parsedResult.base.c_str(), "zh-CN-x-ca-pinyin");
512 // only "u"
513 localeString = factory->NewFromASCII("ko-Kore-KR-u-co-phonebk");
514 parsedResult = JSLocale::HandleLocale(localeString);
515 EXPECT_STREQ(parsedResult.base.c_str(), "ko-Kore-KR");
516 // both "x" and "u"
517 localeString = factory->NewFromASCII("en-Latn-US-u-x-co-phonebk-kn-true");
518 parsedResult = JSLocale::HandleLocale(localeString);
519 EXPECT_STREQ(parsedResult.base.c_str(), "en-Latn-US-x-co-phonebk-kn-true");
520
521 localeString = factory->NewFromASCII("en-Latn-US-x-u-ca-pinyin-co-compat");
522 parsedResult = JSLocale::HandleLocale(localeString);
523 EXPECT_STREQ(parsedResult.base.c_str(), "en-Latn-US-x-u-ca-pinyin-co-compat");
524 }
525
526 /**
527 * @tc.name: ConstructLocaleList
528 * @tc.desc: Get LocaleList numbers through "ConstructLocaleList" function.
529 * @tc.type: FUNC
530 * @tc.require:
531 */
HWTEST_F_L0(JSLocaleTest,ConstructLocaleList)532 HWTEST_F_L0(JSLocaleTest, ConstructLocaleList)
533 {
534 std::vector<std::string> availableLocales = {"zh-Hans-CN", "de-ID", "en-US", "en-GB"};
535 JSHandle<TaggedArray> localeArr = JSLocale::ConstructLocaleList(thread, availableLocales);
536 EXPECT_EQ(localeArr->GetLength(), 4U); // 4 : 4 Number of locales
537 }
538
539 /**
540 * @tc.name: SetNumberFormatDigitOptions
541 * @tc.desc: Call "SetNumberFormatDigitOptions" function parse information in option into attributes
542 * of the JSNumberFormat.
543 * @tc.type: FUNC
544 * @tc.require:
545 */
HWTEST_F_L0(JSLocaleTest,SetNumberFormatDigitOptions_Significant)546 HWTEST_F_L0(JSLocaleTest, SetNumberFormatDigitOptions_Significant)
547 {
548 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
549 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
550 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
551 JSHandle<JSTaggedValue> numberFormatObj = env->GetNumberFormatFunction();
552
553 JSHandle<JSTaggedValue> mnidKey = thread->GlobalConstants()->GetHandledMinimumIntegerDigitsString();
554 JSHandle<JSTaggedValue> mnsdKey = thread->GlobalConstants()->GetHandledMinimumSignificantDigitsString();
555 JSHandle<JSTaggedValue> mxsdKey = thread->GlobalConstants()->GetHandledMaximumSignificantDigitsString();
556 JSHandle<JSTaggedValue> mnidValue(thread, JSTaggedValue(10));
557 JSHandle<JSTaggedValue> maxFraValue(thread, JSTaggedValue(11));
558 JSHandle<JSTaggedValue> minSignValue(thread, JSTaggedValue(12));
559
560 JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
561 JSObject::SetProperty(thread, optionsObj, mnidKey, mnidValue);
562 JSObject::SetProperty(thread, optionsObj, mnsdKey, maxFraValue);
563 JSObject::SetProperty(thread, optionsObj, mxsdKey, minSignValue);
564 JSHandle<JSNumberFormat> jsNumberFormat = JSHandle<JSNumberFormat>::Cast(
565 factory->NewJSObjectByConstructor(JSHandle<JSFunction>(numberFormatObj), numberFormatObj));
566
567 JSLocale::SetNumberFormatDigitOptions(thread, jsNumberFormat, JSHandle<JSTaggedValue>(optionsObj),
568 1, 1, NotationOption::COMPACT);
569 EXPECT_EQ(jsNumberFormat->GetMinimumSignificantDigits().GetInt(), 11);
570 EXPECT_EQ(jsNumberFormat->GetMaximumSignificantDigits().GetInt(), 12);
571 EXPECT_EQ(jsNumberFormat->GetMinimumIntegerDigits().GetInt(), 10);
572 EXPECT_EQ(jsNumberFormat->GetRoundingType(), RoundingType::SIGNIFICANTDIGITS);
573 }
574
HWTEST_F_L0(JSLocaleTest,SetNumberFormatDigitOptions_Fraction)575 HWTEST_F_L0(JSLocaleTest, SetNumberFormatDigitOptions_Fraction)
576 {
577 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
578 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
579 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
580 JSHandle<JSTaggedValue> pluralRulesObj = env->GetPluralRulesFunction();
581
582 JSHandle<JSTaggedValue> mnidKey = thread->GlobalConstants()->GetHandledMinimumIntegerDigitsString();
583 JSHandle<JSTaggedValue> mnidValue(thread, JSTaggedValue(10));
584
585 JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
586 JSObject::SetProperty(thread, optionsObj, mnidKey, mnidValue);
587 JSHandle<JSPluralRules> jsPluralRules = JSHandle<JSPluralRules>::Cast(
588 factory->NewJSObjectByConstructor(JSHandle<JSFunction>(pluralRulesObj), pluralRulesObj));
589
590 JSLocale::SetNumberFormatDigitOptions(thread, jsPluralRules, JSHandle<JSTaggedValue>(optionsObj),
591 10, 13, NotationOption::EXCEPTION);
592 EXPECT_EQ(jsPluralRules->GetMinimumFractionDigits().GetInt(), 10);
593 EXPECT_EQ(jsPluralRules->GetMaximumFractionDigits().GetInt(), 13);
594 EXPECT_EQ(jsPluralRules->GetMinimumIntegerDigits().GetInt(), 10);
595 EXPECT_EQ(jsPluralRules->GetRoundingType(), RoundingType::FRACTIONDIGITS);
596 }
597
598 /**
599 * @tc.name: CheckLocales
600 * @tc.desc: Call "CheckLocales" function check wether language is correct from locale libraries obtained
601 * from different ways.
602 * @tc.type: FUNC
603 * @tc.require:
604 */
HWTEST_F_L0(JSLocaleTest,CheckLocales)605 HWTEST_F_L0(JSLocaleTest, CheckLocales)
606 {
607 bool res = false;
608 const char *path = JSCollator::uIcuDataColl.c_str();
609 // default language
610 bool result = JSLocale::CheckLocales("en", nullptr, path, res);
611 EXPECT_TRUE(result);
612 // fault language
613 result = JSLocale::CheckLocales("e", nullptr, path, res);
614 EXPECT_FALSE(result);
615 // find language in calendar
616 result = JSLocale::CheckLocales("en-US", "calendar", nullptr, res);
617 EXPECT_TRUE(result);
618 // find language in NumberElements
619 result = JSLocale::CheckLocales("en-US", "NumberElements", nullptr, res);
620 EXPECT_TRUE(result);
621 }
622
623 /**
624 * @tc.name: UnicodeExtensionValue
625 * @tc.desc: Call "UnicodeExtensionValue" function get subtag after key in Extension.
626 * @tc.type: FUNC
627 * @tc.require:
628 */
HWTEST_F_L0(JSLocaleTest,UnicodeExtensionValue)629 HWTEST_F_L0(JSLocaleTest, UnicodeExtensionValue)
630 {
631 // extension has one "-"
632 std::string result = JSLocale::UnicodeExtensionValue("-ca=chinese", "ca");
633 EXPECT_STREQ(result.c_str(), "undefined");
634 // extension has one "-" and key value is full
635 result = JSLocale::UnicodeExtensionValue("-ca", "ca");
636 EXPECT_STREQ(result.c_str(), "");
637 // extension has two "-"
638 result = JSLocale::UnicodeExtensionValue("-ca-chinese", "ca");
639 EXPECT_STREQ(result.c_str(), "chinese");
640
641 result = JSLocale::UnicodeExtensionValue("-ca-chinese-co-compat", "co");
642 EXPECT_STREQ(result.c_str(), "compat");
643
644 result = JSLocale::UnicodeExtensionValue("-ca-kn-true", "kn");
645 EXPECT_STREQ(result.c_str(), "true");
646 }
647
648 /**
649 * @tc.name: IsWellCalendar
650 * @tc.desc: Call "IsWellCalendar" function judge whether the calendar is well from locale.
651 * @tc.type: FUNC
652 * @tc.require:
653 */
HWTEST_F_L0(JSLocaleTest,IsWellCalendar)654 HWTEST_F_L0(JSLocaleTest, IsWellCalendar)
655 {
656 EXPECT_TRUE(JSLocale::IsWellCalendar("ar-EG", "islamic"));
657 EXPECT_TRUE(JSLocale::IsWellCalendar("ar-EG", "coptic"));
658 EXPECT_TRUE(JSLocale::IsWellCalendar("zh-CN", "chinese"));
659 EXPECT_TRUE(JSLocale::IsWellCalendar("en-US", "gregory"));
660
661 EXPECT_FALSE(JSLocale::IsWellCalendar("zh-CN", "English"));
662 }
663
664 /**
665 * @tc.name: IsWellCollation
666 * @tc.desc: Call "IsWellCollation" function judge whether the collation is well from locale.
667 * @tc.type: FUNC
668 * @tc.require:
669 */
HWTEST_F_L0(JSLocaleTest,IsWellCollation)670 HWTEST_F_L0(JSLocaleTest, IsWellCollation)
671 {
672 EXPECT_TRUE(JSLocale::IsWellCollation("ar-EG", "compat"));
673
674 EXPECT_FALSE(JSLocale::IsWellCollation("ar-EG", "stroke"));
675 EXPECT_FALSE(JSLocale::IsWellCollation("ar-EG", "pinyin"));
676 EXPECT_FALSE(JSLocale::IsWellCollation("ar-EG", "phonebk"));
677 EXPECT_FALSE(JSLocale::IsWellCollation("ar-EG", "search"));
678 EXPECT_FALSE(JSLocale::IsWellCollation("ar-EG", "standard"));
679 }
680
681 /**
682 * @tc.name: IsWellNumberingSystem
683 * @tc.desc: Call "IsWellNumberingSystem" function judge whether the script is well.
684 * @tc.type: FUNC
685 * @tc.require:
686 */
HWTEST_F_L0(JSLocaleTest,IsWellNumberingSystem)687 HWTEST_F_L0(JSLocaleTest, IsWellNumberingSystem)
688 {
689 EXPECT_FALSE(JSLocale::IsWellNumberingSystem("finance"));
690 EXPECT_FALSE(JSLocale::IsWellNumberingSystem("native"));
691 EXPECT_FALSE(JSLocale::IsWellNumberingSystem("traditio"));
692
693 EXPECT_TRUE(JSLocale::IsWellNumberingSystem("hans"));
694 EXPECT_TRUE(JSLocale::IsWellNumberingSystem("deva"));
695 EXPECT_TRUE(JSLocale::IsWellNumberingSystem("greklow"));
696 }
697
698 /**
699 * @tc.name: DefaultNumberOption
700 * @tc.desc: Call "DefaultNumberOption" function get default number from value.
701 * @tc.type: FUNC
702 * @tc.require:
703 */
HWTEST_F_L0(JSLocaleTest,DefaultNumberOption)704 HWTEST_F_L0(JSLocaleTest, DefaultNumberOption)
705 {
706 JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(static_cast<double>(4.99)));
707 int result = JSLocale::DefaultNumberOption(thread, value1, 1, 5, 1);
708 EXPECT_EQ(result, 4);
709 JSHandle<JSTaggedValue> value2(thread, JSTaggedValue::Undefined());
710 result = JSLocale::DefaultNumberOption(thread, value2, 1, 5, 1);
711 EXPECT_EQ(result, 1);
712 }
713
714 /**
715 * @tc.name: GetOptionOfString
716 * @tc.desc: Call "GetOptionOfString" function get the string from Option value.
717 * @tc.type: FUNC
718 * @tc.require:
719 */
HWTEST_F_L0(JSLocaleTest,GetOptionOfString)720 HWTEST_F_L0(JSLocaleTest, GetOptionOfString)
721 {
722 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
723 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
724 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
725
726 JSHandle<JSTaggedValue> languageProperty = thread->GlobalConstants()->GetHandledLanguageString();
727 JSHandle<JSTaggedValue> regionProperty = thread->GlobalConstants()->GetHandledRegionString();
728 JSHandle<JSTaggedValue> languageValue(factory->NewFromASCII("zh"));
729 JSHandle<JSTaggedValue> regionValue(factory->NewFromASCII("CN"));
730 // Set key value
731 JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
732 JSObject::SetProperty(thread, optionsObj, languageProperty, languageValue);
733 JSObject::SetProperty(thread, optionsObj, regionProperty, regionValue);
734 std::vector<std::string> stringValues = {"zh", "Hans", "CN"};
735 std::string optionValue;
736 // Get language
737 bool result = JSLocale::GetOptionOfString(thread, optionsObj, languageProperty, stringValues, &optionValue);
738 EXPECT_TRUE(result);
739 EXPECT_STREQ(optionValue.c_str(), "zh");
740 // Get region
741 result = JSLocale::GetOptionOfString(thread, optionsObj, regionProperty, stringValues, &optionValue);
742 EXPECT_TRUE(result);
743 EXPECT_STREQ(optionValue.c_str(), "CN");
744 }
745
746 /**
747 * @tc.name: GetOption
748 * @tc.desc: Call "GetOption" function get value of the key from Option.
749 * @tc.type: FUNC
750 * @tc.require:
751 */
HWTEST_F_L0(JSLocaleTest,GetOption)752 HWTEST_F_L0(JSLocaleTest, GetOption)
753 {
754 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
755 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
756 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
757
758 JSHandle<JSTaggedValue> languageProperty = thread->GlobalConstants()->GetHandledLanguageString();
759 JSHandle<JSTaggedValue> regionProperty = thread->GlobalConstants()->GetHandledRegionString();
760 JSHandle<JSTaggedValue> languageValue(factory->NewFromASCII("zh"));
761 JSHandle<JSTaggedValue> regionValue(factory->NewFromASCII("CN"));
762 // Set key value
763 JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
764 JSObject::SetProperty(thread, optionsObj, languageProperty, languageValue);
765
766 JSHandle<TaggedArray> stringValues = factory->NewTaggedArray(3);
767 stringValues->Set(thread, 0, languageValue);
768 stringValues->Set(thread, 1, regionValue);
769 JSHandle<JSTaggedValue> arrayValue(stringValues);
770 JSHandle<JSTaggedValue> fallback(thread, JSTaggedValue::Undefined());
771
772 JSHandle<JSTaggedValue> optionValue =
773 JSLocale::GetOption(thread, optionsObj, languageProperty, OptionType::STRING, arrayValue, fallback);
774 EXPECT_EQ(JSTaggedValue::SameValue(optionValue, languageValue), true);
775
776 optionValue = JSLocale::GetOption(thread, optionsObj, regionProperty, OptionType::STRING, arrayValue, fallback);
777 EXPECT_EQ(JSTaggedValue::SameValue(optionValue, fallback), true);
778 }
779
780 /**
781 * @tc.name: GetOptionOfBool
782 * @tc.desc: Call "GetOptionOfBool" function get the bool value from Option.
783 * @tc.type: FUNC
784 * @tc.require:
785 */
HWTEST_F_L0(JSLocaleTest,GetOptionOfBool)786 HWTEST_F_L0(JSLocaleTest, GetOptionOfBool)
787 {
788 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
789 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
790 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
791
792 JSHandle<JSTaggedValue> numericProperty = thread->GlobalConstants()->GetHandledNumericString();
793 JSHandle<JSTaggedValue> numericValue(thread, JSTaggedValue::True());
794 // Set key value
795 JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
796 JSObject::SetProperty(thread, optionsObj, numericProperty, numericValue);
797 bool res;
798 // Test correct keyValue
799 EXPECT_TRUE(JSLocale::GetOptionOfBool(thread, optionsObj, numericProperty, false, &res));
800 EXPECT_TRUE(res);
801
802 JSHandle<JSTaggedValue> numericValue1(thread, JSTaggedValue(0));
803 JSObject::SetProperty(thread, optionsObj, numericProperty, numericValue1);
804 // Test fault keyValue
805 EXPECT_TRUE(JSLocale::GetOptionOfBool(thread, optionsObj, numericProperty, false, &res));
806 EXPECT_FALSE(res);
807 }
808
809 /**
810 * @tc.name: BestAvailableLocale
811 * @tc.desc: Match the best Locale and return from available locale through "BestAvailableLocale" function.
812 * @tc.type: FUNC
813 * @tc.require:
814 */
HWTEST_F_L0(JSLocaleTest,BestAvailableLocale)815 HWTEST_F_L0(JSLocaleTest, BestAvailableLocale)
816 {
817 const char *path = JSCollator::uIcuDataColl.c_str();
818 // available locales in uIcuDataColl
819 JSHandle<TaggedArray> icuDataAvailableLocales = JSLocale::GetAvailableLocales(thread, nullptr, path);
820 // available locales(calendar)
821 JSHandle<TaggedArray> calendarAvailableLocales = JSLocale::GetAvailableLocales(thread, "calendar", nullptr);
822 // available locales(NumberElements)
823 JSHandle<TaggedArray> numberAvailableLocales = JSLocale::GetAvailableLocales(thread, "NumberElements", nullptr);
824 // "ar-001" is found
825 EXPECT_STREQ(JSLocale::BestAvailableLocale(thread, icuDataAvailableLocales, "ar-001").c_str(), "ar-001");
826 EXPECT_STREQ(JSLocale::BestAvailableLocale(thread, calendarAvailableLocales, "ar-001").c_str(), "ar-001");
827 EXPECT_STREQ(JSLocale::BestAvailableLocale(thread, numberAvailableLocales, "ar-001").c_str(), "ar-001");
828 // "agq-CM" is not found in uIcuDataColl
829 EXPECT_STREQ(JSLocale::BestAvailableLocale(thread, icuDataAvailableLocales, "agq-CM").c_str(), "");
830 EXPECT_STREQ(JSLocale::BestAvailableLocale(thread, calendarAvailableLocales, "agq-CM").c_str(), "agq-CM");
831 EXPECT_STREQ(JSLocale::BestAvailableLocale(thread, numberAvailableLocales, "agq-CM").c_str(), "agq-CM");
832 // language(und)-region(CN)
833 EXPECT_STREQ(JSLocale::BestAvailableLocale(thread, icuDataAvailableLocales, "und-CN").c_str(), "");
834 EXPECT_STREQ(JSLocale::BestAvailableLocale(thread, calendarAvailableLocales, "und-CN").c_str(), "");
835 EXPECT_STREQ(JSLocale::BestAvailableLocale(thread, numberAvailableLocales, "und-CN").c_str(), "");
836 // language(en)-region(001)
837 EXPECT_STREQ(JSLocale::BestAvailableLocale(thread, icuDataAvailableLocales, "en-001").c_str(), "en-001");
838 EXPECT_STREQ(JSLocale::BestAvailableLocale(thread, calendarAvailableLocales, "en-001").c_str(), "en-001");
839 EXPECT_STREQ(JSLocale::BestAvailableLocale(thread, numberAvailableLocales, "en-001").c_str(), "en-001");
840 // language(en)-script(Hans)-region(US)
841 EXPECT_STREQ(JSLocale::BestAvailableLocale(thread, icuDataAvailableLocales, "en-Hans-US").c_str(), "en");
842 EXPECT_STREQ(JSLocale::BestAvailableLocale(thread, calendarAvailableLocales, "en-Hans-US").c_str(), "en");
843 EXPECT_STREQ(JSLocale::BestAvailableLocale(thread, numberAvailableLocales, "en-Hans-US").c_str(), "en");
844 }
845
846 /**
847 * @tc.name: ResolveLocale
848 * @tc.desc: Resolve Locale and return from available locale through "ResolveLocale" function.
849 * @tc.type: FUNC
850 * @tc.require:
851 */
HWTEST_F_L0(JSLocaleTest,ResolveLocale_001)852 HWTEST_F_L0(JSLocaleTest, ResolveLocale_001)
853 {
854 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
855 JSHandle<TaggedArray> availableLocales = factory->EmptyArray();
856 JSHandle<TaggedArray> requestedLocales = factory->EmptyArray();
857 std::set<std::string> relevantExtensionKeys = {"co", "ca"};
858 JSHandle<JSTaggedValue> testLocale1(factory->NewFromASCII("id-u-co-pinyin-ca-gregory-de-ID"));
859 JSHandle<JSTaggedValue> testLocale2(factory->NewFromASCII("en-Latn-US-u-co-phonebk-ca-ethioaa"));
860 // availableLocales and requestLocales is empty
861 ResolvedLocale result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
862 LocaleMatcherOption::BEST_FIT, relevantExtensionKeys);
863 EXPECT_STREQ("en-US", result.locale.c_str()); // default locale
864 // availableLocales and requestLocales is not empty
865 availableLocales = JSLocale::GetAvailableLocales(thread, "calendar", nullptr);
866 requestedLocales = factory->NewTaggedArray(1);
867 // test locale1
868 requestedLocales->Set(thread, 0, testLocale1);
869 result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
870 LocaleMatcherOption::BEST_FIT, relevantExtensionKeys);
871 EXPECT_STREQ("id-u-ca-gregory-co-pinyin-de-id", result.locale.c_str());
872 result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
873 LocaleMatcherOption::LOOKUP, relevantExtensionKeys);
874 EXPECT_STREQ("id-u-ca-gregory-co-pinyin-de-id", result.locale.c_str());
875 result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
876 LocaleMatcherOption::EXCEPTION, relevantExtensionKeys);
877 EXPECT_STREQ("id-u-ca-gregory-co-pinyin-de-id", result.locale.c_str());
878 // test locale2
879 requestedLocales->Set(thread, 0, testLocale2);
880 result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
881 LocaleMatcherOption::BEST_FIT, relevantExtensionKeys);
882 EXPECT_STREQ("en-u-ca-ethioaa-co-phonebk", result.locale.c_str());
883 result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
884 LocaleMatcherOption::LOOKUP, relevantExtensionKeys);
885 EXPECT_STREQ("en-u-ca-ethioaa-co-phonebk", result.locale.c_str());
886 result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
887 LocaleMatcherOption::EXCEPTION, relevantExtensionKeys);
888 EXPECT_STREQ("en-u-ca-ethioaa-co-phonebk", result.locale.c_str());
889 }
890
HWTEST_F_L0(JSLocaleTest,ResolveLocale_002)891 HWTEST_F_L0(JSLocaleTest, ResolveLocale_002)
892 {
893 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
894 JSHandle<TaggedArray> availableLocales = factory->EmptyArray();
895 JSHandle<TaggedArray> requestedLocales = factory->EmptyArray();
896 std::set<std::string> relevantExtensionKeys = {"hc", "lb", "kn", "kf"};
897 JSHandle<JSTaggedValue> testLocale1(factory->NewFromASCII("id-u-kn-false-kf-yes-de-ID"));
898 JSHandle<JSTaggedValue> testLocale2(factory->NewFromASCII("en-US-u-hc-h24-lb-strict"));
899 // availableLocales and requestLocales is empty
900 ResolvedLocale result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
901 LocaleMatcherOption::BEST_FIT, relevantExtensionKeys);
902 EXPECT_STREQ("en-US", result.locale.c_str()); // default locale
903 // availableLocales and requestLocales is not empty
904 availableLocales = JSLocale::GetAvailableLocales(thread, "calendar", nullptr);
905 requestedLocales = factory->NewTaggedArray(1);
906 // test locale1
907 requestedLocales->Set(thread, 0, testLocale1);
908 result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
909 LocaleMatcherOption::BEST_FIT, relevantExtensionKeys);
910 EXPECT_STREQ("id-u-de-id-kf-kn-false", result.locale.c_str());
911 result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
912 LocaleMatcherOption::LOOKUP, relevantExtensionKeys);
913 EXPECT_STREQ("id-u-de-id-kf-kn-false", result.locale.c_str());
914 result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
915 LocaleMatcherOption::EXCEPTION, relevantExtensionKeys);
916 EXPECT_STREQ("id-u-de-id-kf-kn-false", result.locale.c_str());
917 // test locale2
918 requestedLocales->Set(thread, 0, testLocale2);
919 result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
920 LocaleMatcherOption::BEST_FIT, relevantExtensionKeys);
921 EXPECT_STREQ("en-US-u-hc-h24-lb-strict", result.locale.c_str());
922 result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
923 LocaleMatcherOption::LOOKUP, relevantExtensionKeys);
924 EXPECT_STREQ("en-US-u-hc-h24-lb-strict", result.locale.c_str());
925 result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
926 LocaleMatcherOption::EXCEPTION, relevantExtensionKeys);
927 EXPECT_STREQ("en-US-u-hc-h24-lb-strict", result.locale.c_str());
928 }
929 } // namespace panda::test
930