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