• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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