• 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: IsValidTimeZoneName
146  * @tc.desc: Call "IsValidTimeZoneName" function check whether the TimeZone is valid.if TimeZone include "GMT-Time"
147  *           return true otherwise, return false.
148  * @tc.type: FUNC
149  * @tc.require:
150  */
HWTEST_F_L0(JSLocaleTest,IsValidTimeZoneName)151 HWTEST_F_L0(JSLocaleTest, IsValidTimeZoneName)
152 {
153     icu::UnicodeString stringID1("GMT-8:00");
154     icu::TimeZone *timeZone = icu::TimeZone::createTimeZone(stringID1);
155     EXPECT_TRUE(JSLocale::IsValidTimeZoneName(*timeZone));
156     delete timeZone;
157 
158     icu::UnicodeString stringID2("Etc/Unknown");
159     timeZone = icu::TimeZone::createTimeZone(stringID2);
160     EXPECT_FALSE(JSLocale::IsValidTimeZoneName(*timeZone));
161     delete timeZone;
162 }
163 
164 /**
165  * @tc.name: PutElement
166  * @tc.desc: Put elements in empty JSArray and return the JSArray.call "GetProperty" function to get the value and
167  *           check whether the value is consistent with the value of the put.
168  * @tc.type: FUNC
169  * @tc.require:
170  */
HWTEST_F_L0(JSLocaleTest,PutElement)171 HWTEST_F_L0(JSLocaleTest, PutElement)
172 {
173     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
174     auto globalConst = thread->GlobalConstants();
175     JSHandle<JSArray> jsArray = factory->NewJSArray();
176     JSHandle<JSTaggedValue> typeString = globalConst->GetHandledTypeString();
177     JSHandle<JSTaggedValue> valueString = globalConst->GetHandledValueString();
178     JSHandle<JSTaggedValue> fieldTypeString = globalConst->GetHandledUnitString();
179     JSHandle<JSTaggedValue> value(thread, JSTaggedValue(static_cast<int>(11)));
180 
181     int index = 1;
182     JSHandle<JSObject> recordObj = JSLocale::PutElement(thread, index, jsArray, fieldTypeString, value);
183     EXPECT_EQ(JSTaggedValue::SameValue(
184               JSObject::GetProperty(thread, recordObj, typeString).GetValue(), fieldTypeString), true);
185     EXPECT_EQ(JSObject::GetProperty(thread, recordObj, valueString).GetValue()->GetInt(), 11);
186 
187     JSHandle<JSTaggedValue> indexKey(factory->NewFromASCII("1"));
188     EXPECT_TRUE(JSObject::GetProperty(thread, JSHandle<JSObject>(jsArray), indexKey).GetValue()->IsECMAObject());
189 }
190 
191 /**
192  * @tc.name: GetNumberingSystem
193  * @tc.desc: Call "GetNumberingSystem" function get the script from the ICU Locale.
194  * @tc.type: FUNC
195  * @tc.require:
196  */
HWTEST_F_L0(JSLocaleTest,GetNumberingSystem)197 HWTEST_F_L0(JSLocaleTest, GetNumberingSystem)
198 {
199     icu::Locale icuLocale1("en", "US");
200     std::string numberingSystem = JSLocale::GetNumberingSystem(icuLocale1);
201     EXPECT_STREQ("latn", numberingSystem.c_str());
202 
203     icu::Locale icuLocale2("zh", "Hans", "CN", "collation=phonebk;numbers=hans");
204     numberingSystem = JSLocale::GetNumberingSystem(icuLocale2);
205     EXPECT_STREQ("hans", numberingSystem.c_str());
206 }
207 
208 /**
209  * @tc.name: GetNumberFieldType
210  * @tc.desc: Call "GetNumberFieldType" function get Number Field type.
211  * @tc.type: FUNC
212  * @tc.require:
213  */
HWTEST_F_L0(JSLocaleTest,GetNumberFieldType)214 HWTEST_F_L0(JSLocaleTest, GetNumberFieldType)
215 {
216     auto globalConst = thread->GlobalConstants();
217     int32_t fieldId = 0; // UNUM_INTEGER_FIELD
218 
219     JSTaggedValue x(0.0f / 0.0f); // Nan
220     JSHandle<JSTaggedValue> nanString = globalConst->GetHandledNanString();
221     JSHandle<JSTaggedValue> fieldTypeString = JSLocale::GetNumberFieldType(thread, x, fieldId);
222     EXPECT_EQ(JSTaggedValue::SameValue(fieldTypeString, nanString), true);
223 
224     JSTaggedValue y(-10); // integer(sign bit)
225     JSHandle<JSTaggedValue> integerString = globalConst->GetHandledIntegerString();
226     fieldTypeString = JSLocale::GetNumberFieldType(thread, y, fieldId);
227     EXPECT_EQ(JSTaggedValue::SameValue(fieldTypeString, integerString), true);
228 
229     fieldId = 10; // UNUM_SIGN_FIELD
230     JSHandle<JSTaggedValue> minusSignString = globalConst->GetHandledMinusSignString();
231     fieldTypeString = JSLocale::GetNumberFieldType(thread, y, fieldId);
232     EXPECT_EQ(JSTaggedValue::SameValue(fieldTypeString, minusSignString), true);
233 
234     JSTaggedValue z(10); // no sign bit
235     JSHandle<JSTaggedValue> plusSignString = globalConst->GetHandledPlusSignString();
236     fieldTypeString = JSLocale::GetNumberFieldType(thread, z, fieldId);
237     EXPECT_EQ(JSTaggedValue::SameValue(fieldTypeString, plusSignString), true);
238 }
239 
240 /**
241  * @tc.name: ApplyOptionsToTag
242  * @tc.desc: Call "ApplyOptionsToTag" function parse information in option into tag string.
243  * @tc.type: FUNC
244  * @tc.require:
245  */
HWTEST_F_L0(JSLocaleTest,ApplyOptionsToTag)246 HWTEST_F_L0(JSLocaleTest, ApplyOptionsToTag)
247 {
248     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
249     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
250     TagElements tagElements;
251     JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
252     JSHandle<EcmaString> languageTag = intl::LocaleHelper::DefaultLocale(thread);
253 
254     JSHandle<JSTaggedValue> languageKey = thread->GlobalConstants()->GetHandledLanguageString();
255     JSHandle<JSTaggedValue> regionKey = thread->GlobalConstants()->GetHandledRegionString();
256     JSHandle<JSTaggedValue> scriptKey = thread->GlobalConstants()->GetHandledScriptString();
257     JSHandle<JSTaggedValue> languageValue(factory->NewFromASCII("en"));
258     JSHandle<JSTaggedValue> regionValue(factory->NewFromASCII("US"));
259     JSHandle<JSTaggedValue> scriptValue(factory->NewFromASCII("Latn"));
260 
261     JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
262     JSObject::SetProperty(thread, optionsObj, languageKey, languageValue);
263     JSObject::SetProperty(thread, optionsObj, regionKey, regionValue);
264     JSObject::SetProperty(thread, optionsObj, scriptKey, scriptValue);
265     bool result = JSLocale::ApplyOptionsToTag(thread, languageTag, optionsObj, tagElements);
266     EXPECT_TRUE(result);
267     EXPECT_EQ(tagElements.language, languageValue);
268     EXPECT_EQ(tagElements.script, scriptValue);
269     EXPECT_EQ(tagElements.region, regionValue);
270     // fault script
271     JSHandle<JSTaggedValue> scriptValue1(factory->NewFromASCII(""));
272     JSObject::SetProperty(thread, optionsObj, scriptKey, scriptValue1);
273     result = JSLocale::ApplyOptionsToTag(thread, languageTag, optionsObj, tagElements);
274     EXPECT_FALSE(result);
275 }
276 
277 /**
278  * @tc.name: ConstructLocaleList
279  * @tc.desc: Get LocaleList numbers through "ConstructLocaleList" function.
280  * @tc.type: FUNC
281  * @tc.require:
282  */
HWTEST_F_L0(JSLocaleTest,ConstructLocaleList)283 HWTEST_F_L0(JSLocaleTest, ConstructLocaleList)
284 {
285     std::vector<std::string> availableLocales = {"zh-Hans-CN", "de-ID", "en-US", "en-GB"};
286     JSHandle<TaggedArray> localeArr = JSLocale::ConstructLocaleList(thread, availableLocales);
287     EXPECT_EQ(localeArr->GetLength(), 4U); // 4 : 4 Number of locales
288 }
289 
290 /**
291  * @tc.name: SetNumberFormatDigitOptions
292  * @tc.desc: Call "SetNumberFormatDigitOptions" function parse information in option into attributes
293  *           of the JSNumberFormat.
294  * @tc.type: FUNC
295  * @tc.require:
296  */
HWTEST_F_L0(JSLocaleTest,SetNumberFormatDigitOptions_Significant)297 HWTEST_F_L0(JSLocaleTest, SetNumberFormatDigitOptions_Significant)
298 {
299     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
300     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
301     JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
302     JSHandle<JSTaggedValue> numberFormatObj = env->GetNumberFormatFunction();
303 
304     JSHandle<JSTaggedValue> mnidKey = thread->GlobalConstants()->GetHandledMinimumIntegerDigitsString();
305     JSHandle<JSTaggedValue> mnsdKey = thread->GlobalConstants()->GetHandledMinimumSignificantDigitsString();
306     JSHandle<JSTaggedValue> mxsdKey = thread->GlobalConstants()->GetHandledMaximumSignificantDigitsString();
307     JSHandle<JSTaggedValue> mnidValue(thread, JSTaggedValue(10));
308     JSHandle<JSTaggedValue> maxFraValue(thread, JSTaggedValue(11));
309     JSHandle<JSTaggedValue> minSignValue(thread, JSTaggedValue(12));
310 
311     JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
312     JSObject::SetProperty(thread, optionsObj, mnidKey, mnidValue);
313     JSObject::SetProperty(thread, optionsObj, mnsdKey, maxFraValue);
314     JSObject::SetProperty(thread, optionsObj, mxsdKey, minSignValue);
315     JSHandle<JSNumberFormat> jsNumberFormat = JSHandle<JSNumberFormat>::Cast(
316         factory->NewJSObjectByConstructor(JSHandle<JSFunction>(numberFormatObj), numberFormatObj));
317 
318     JSLocale::SetNumberFormatDigitOptions(thread, jsNumberFormat, JSHandle<JSTaggedValue>(optionsObj),
319                                                    1, 1, NotationOption::COMPACT);
320     EXPECT_EQ(jsNumberFormat->GetMinimumSignificantDigits().GetInt(), 11);
321     EXPECT_EQ(jsNumberFormat->GetMaximumSignificantDigits().GetInt(), 12);
322     EXPECT_EQ(jsNumberFormat->GetMinimumIntegerDigits().GetInt(), 10);
323     EXPECT_EQ(jsNumberFormat->GetRoundingType(), RoundingType::SIGNIFICANTDIGITS);
324 }
325 
HWTEST_F_L0(JSLocaleTest,SetNumberFormatDigitOptions_Fraction)326 HWTEST_F_L0(JSLocaleTest, SetNumberFormatDigitOptions_Fraction)
327 {
328     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
329     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
330     JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
331     JSHandle<JSTaggedValue> pluralRulesObj = env->GetPluralRulesFunction();
332 
333     JSHandle<JSTaggedValue> mnidKey = thread->GlobalConstants()->GetHandledMinimumIntegerDigitsString();
334     JSHandle<JSTaggedValue> mnidValue(thread, JSTaggedValue(10));
335 
336     JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
337     JSObject::SetProperty(thread, optionsObj, mnidKey, mnidValue);
338     JSHandle<JSPluralRules> jsPluralRules = JSHandle<JSPluralRules>::Cast(
339         factory->NewJSObjectByConstructor(JSHandle<JSFunction>(pluralRulesObj), pluralRulesObj));
340 
341     JSLocale::SetNumberFormatDigitOptions(thread, jsPluralRules, JSHandle<JSTaggedValue>(optionsObj),
342                                                   10, 13, NotationOption::EXCEPTION);
343     EXPECT_EQ(jsPluralRules->GetMinimumFractionDigits().GetInt(), 10);
344     EXPECT_EQ(jsPluralRules->GetMaximumFractionDigits().GetInt(), 13);
345     EXPECT_EQ(jsPluralRules->GetMinimumIntegerDigits().GetInt(), 10);
346     EXPECT_EQ(jsPluralRules->GetRoundingType(), RoundingType::FRACTIONDIGITS);
347 }
348 
349 /**
350  * @tc.name: CheckLocales
351  * @tc.desc: Call "CheckLocales" function check wether language is correct from locale libraries obtained
352  *           from different ways.
353  * @tc.type: FUNC
354  * @tc.require:
355  */
HWTEST_F_L0(JSLocaleTest,CheckLocales)356 HWTEST_F_L0(JSLocaleTest, CheckLocales)
357 {
358     bool res = false;
359     const char *path = JSCollator::uIcuDataColl.c_str();
360     // default language
361     bool result = JSLocale::CheckLocales("en", nullptr, path, res);
362     EXPECT_TRUE(result);
363     // fault language
364     result = JSLocale::CheckLocales("e", nullptr, path, res);
365     EXPECT_FALSE(result);
366     // find language in calendar
367     result = JSLocale::CheckLocales("en-US", "calendar", nullptr, res);
368     EXPECT_TRUE(result);
369     // find language in NumberElements
370     result = JSLocale::CheckLocales("en-US", "NumberElements", nullptr, res);
371     EXPECT_TRUE(result);
372 }
373 
374 /**
375  * @tc.name: UnicodeExtensionValue
376  * @tc.desc: Call "UnicodeExtensionValue" function get subtag after key in Extension.
377  * @tc.type: FUNC
378  * @tc.require:
379  */
HWTEST_F_L0(JSLocaleTest,UnicodeExtensionValue)380 HWTEST_F_L0(JSLocaleTest, UnicodeExtensionValue)
381 {
382     // extension has one "-"
383     std::string result = JSLocale::UnicodeExtensionValue("-ca=chinese", "ca");
384     EXPECT_STREQ(result.c_str(), "undefined");
385     // extension has one "-" and key value is full
386     result = JSLocale::UnicodeExtensionValue("-ca", "ca");
387     EXPECT_STREQ(result.c_str(), "");
388     // extension has two "-"
389     result = JSLocale::UnicodeExtensionValue("-ca-chinese", "ca");
390     EXPECT_STREQ(result.c_str(), "chinese");
391 
392     result = JSLocale::UnicodeExtensionValue("-ca-chinese-co-compat", "co");
393     EXPECT_STREQ(result.c_str(), "compat");
394 
395     result = JSLocale::UnicodeExtensionValue("-ca-kn-true", "kn");
396     EXPECT_STREQ(result.c_str(), "true");
397 }
398 
399 /**
400  * @tc.name: IsWellCalendar
401  * @tc.desc: Call "IsWellCalendar" function judge whether the calendar is well from locale.
402  * @tc.type: FUNC
403  * @tc.require:
404  */
HWTEST_F_L0(JSLocaleTest,IsWellCalendar)405 HWTEST_F_L0(JSLocaleTest, IsWellCalendar)
406 {
407     EXPECT_TRUE(JSLocale::IsWellCalendar("ar-EG", "islamic"));
408     EXPECT_TRUE(JSLocale::IsWellCalendar("ar-EG", "coptic"));
409     EXPECT_TRUE(JSLocale::IsWellCalendar("zh-CN", "chinese"));
410     EXPECT_TRUE(JSLocale::IsWellCalendar("en-US", "gregory"));
411 
412     EXPECT_FALSE(JSLocale::IsWellCalendar("zh-CN", "English"));
413 }
414 
415 /**
416  * @tc.name: IsWellCollation
417  * @tc.desc: Call "IsWellCollation" function judge whether the collation is well from locale.
418  * @tc.type: FUNC
419  * @tc.require:
420  */
HWTEST_F_L0(JSLocaleTest,IsWellCollation)421 HWTEST_F_L0(JSLocaleTest, IsWellCollation)
422 {
423     EXPECT_TRUE(JSLocale::IsWellCollation("ar-EG", "compat"));
424 
425     EXPECT_FALSE(JSLocale::IsWellCollation("ar-EG", "stroke"));
426     EXPECT_FALSE(JSLocale::IsWellCollation("ar-EG", "pinyin"));
427     EXPECT_FALSE(JSLocale::IsWellCollation("ar-EG", "phonebk"));
428     EXPECT_FALSE(JSLocale::IsWellCollation("ar-EG", "search"));
429     EXPECT_FALSE(JSLocale::IsWellCollation("ar-EG", "standard"));
430 }
431 
432 /**
433  * @tc.name: IsWellNumberingSystem
434  * @tc.desc: Call "IsWellNumberingSystem" function judge whether the script is well.
435  * @tc.type: FUNC
436  * @tc.require:
437  */
HWTEST_F_L0(JSLocaleTest,IsWellNumberingSystem)438 HWTEST_F_L0(JSLocaleTest, IsWellNumberingSystem)
439 {
440     EXPECT_FALSE(JSLocale::IsWellNumberingSystem("finance"));
441     EXPECT_FALSE(JSLocale::IsWellNumberingSystem("native"));
442     EXPECT_FALSE(JSLocale::IsWellNumberingSystem("traditio"));
443 
444     EXPECT_TRUE(JSLocale::IsWellNumberingSystem("hans"));
445     EXPECT_TRUE(JSLocale::IsWellNumberingSystem("deva"));
446     EXPECT_TRUE(JSLocale::IsWellNumberingSystem("greklow"));
447 }
448 
449 /**
450  * @tc.name: DefaultNumberOption
451  * @tc.desc: Call "DefaultNumberOption" function get default number from value.
452  * @tc.type: FUNC
453  * @tc.require:
454  */
HWTEST_F_L0(JSLocaleTest,DefaultNumberOption)455 HWTEST_F_L0(JSLocaleTest, DefaultNumberOption)
456 {
457     JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(static_cast<double>(4.99)));
458     int result = JSLocale::DefaultNumberOption(thread, value1, 1, 5, 1);
459     EXPECT_EQ(result, 4);
460     JSHandle<JSTaggedValue> value2(thread, JSTaggedValue::Undefined());
461     result = JSLocale::DefaultNumberOption(thread, value2, 1, 5, 1);
462     EXPECT_EQ(result, 1);
463 }
464 
465 /**
466  * @tc.name: GetOptionOfString
467  * @tc.desc: Call "GetOptionOfString" function get the string from Option value.
468  * @tc.type: FUNC
469  * @tc.require:
470  */
HWTEST_F_L0(JSLocaleTest,GetOptionOfString)471 HWTEST_F_L0(JSLocaleTest, GetOptionOfString)
472 {
473     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
474     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
475     JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
476 
477     JSHandle<JSTaggedValue> languageProperty = thread->GlobalConstants()->GetHandledLanguageString();
478     JSHandle<JSTaggedValue> regionProperty = thread->GlobalConstants()->GetHandledRegionString();
479     JSHandle<JSTaggedValue> languageValue(factory->NewFromASCII("zh"));
480     JSHandle<JSTaggedValue> regionValue(factory->NewFromASCII("CN"));
481     // Set key value
482     JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
483     JSObject::SetProperty(thread, optionsObj, languageProperty, languageValue);
484     JSObject::SetProperty(thread, optionsObj, regionProperty, regionValue);
485     std::vector<std::string> stringValues = {"zh", "Hans", "CN"};
486     std::string optionValue;
487     // Get language
488     bool result = JSLocale::GetOptionOfString(thread, optionsObj, languageProperty, stringValues, &optionValue);
489     EXPECT_TRUE(result);
490     EXPECT_STREQ(optionValue.c_str(), "zh");
491     // Get region
492     result = JSLocale::GetOptionOfString(thread, optionsObj, regionProperty, stringValues, &optionValue);
493     EXPECT_TRUE(result);
494     EXPECT_STREQ(optionValue.c_str(), "CN");
495 }
496 
497 /**
498  * @tc.name: GetOption
499  * @tc.desc: Call "GetOption" function get value of the key from Option.
500  * @tc.type: FUNC
501  * @tc.require:
502  */
HWTEST_F_L0(JSLocaleTest,GetOption)503 HWTEST_F_L0(JSLocaleTest, GetOption)
504 {
505     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
506     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
507     JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
508 
509     JSHandle<JSTaggedValue> languageProperty = thread->GlobalConstants()->GetHandledLanguageString();
510     JSHandle<JSTaggedValue> regionProperty = thread->GlobalConstants()->GetHandledRegionString();
511     JSHandle<JSTaggedValue> languageValue(factory->NewFromASCII("zh"));
512     JSHandle<JSTaggedValue> regionValue(factory->NewFromASCII("CN"));
513     // Set key value
514     JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
515     JSObject::SetProperty(thread, optionsObj, languageProperty, languageValue);
516 
517     JSHandle<TaggedArray> stringValues = factory->NewTaggedArray(3);
518     stringValues->Set(thread, 0, languageValue);
519     stringValues->Set(thread, 1, regionValue);
520     JSHandle<JSTaggedValue> arrayValue(stringValues);
521     JSHandle<JSTaggedValue> fallback(thread, JSTaggedValue::Undefined());
522 
523     JSHandle<JSTaggedValue> optionValue =
524         JSLocale::GetOption(thread, optionsObj, languageProperty, OptionType::STRING, arrayValue, fallback);
525     EXPECT_EQ(JSTaggedValue::SameValue(optionValue, languageValue), true);
526 
527     optionValue = JSLocale::GetOption(thread, optionsObj, regionProperty, OptionType::STRING, arrayValue, fallback);
528     EXPECT_EQ(JSTaggedValue::SameValue(optionValue, fallback), true);
529 }
530 
531 /**
532  * @tc.name: GetOptionOfBool
533  * @tc.desc: Call "GetOptionOfBool" function get the bool value from Option.
534  * @tc.type: FUNC
535  * @tc.require:
536  */
HWTEST_F_L0(JSLocaleTest,GetOptionOfBool)537 HWTEST_F_L0(JSLocaleTest, GetOptionOfBool)
538 {
539     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
540     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
541     JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
542 
543     JSHandle<JSTaggedValue> numericProperty = thread->GlobalConstants()->GetHandledNumericString();
544     JSHandle<JSTaggedValue> numericValue(thread, JSTaggedValue::True());
545     // Set key value
546     JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
547     JSObject::SetProperty(thread, optionsObj, numericProperty, numericValue);
548     bool res;
549     // Test correct keyValue
550     EXPECT_TRUE(JSLocale::GetOptionOfBool(thread, optionsObj, numericProperty, false, &res));
551     EXPECT_TRUE(res);
552 
553     JSHandle<JSTaggedValue> numericValue1(thread, JSTaggedValue(0));
554     JSObject::SetProperty(thread, optionsObj, numericProperty, numericValue1);
555     // Test fault keyValue
556     EXPECT_TRUE(JSLocale::GetOptionOfBool(thread, optionsObj, numericProperty, false, &res));
557     EXPECT_FALSE(res);
558 }
559 
560 /**
561  * @tc.name: ResolveLocale
562  * @tc.desc: Resolve Locale and return from available locale through "ResolveLocale" function.
563  * @tc.type: FUNC
564  * @tc.require:
565  */
HWTEST_F_L0(JSLocaleTest,ResolveLocale_001)566 HWTEST_F_L0(JSLocaleTest, ResolveLocale_001)
567 {
568     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
569     JSHandle<TaggedArray> availableLocales = factory->EmptyArray();
570     JSHandle<TaggedArray> requestedLocales = factory->EmptyArray();
571     std::set<std::string> relevantExtensionKeys = {"co", "ca"};
572     JSHandle<JSTaggedValue> testLocale1(factory->NewFromASCII("id-u-co-pinyin-ca-gregory-de-ID"));
573     JSHandle<JSTaggedValue> testLocale2(factory->NewFromASCII("en-Latn-US-u-co-phonebk-ca-ethioaa"));
574     // availableLocales and requestLocales is empty
575     ResolvedLocale result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
576                                                     LocaleMatcherOption::BEST_FIT, relevantExtensionKeys);
577     EXPECT_STREQ("en-US", result.locale.c_str()); // default locale
578     // availableLocales and requestLocales is not empty
579     std::vector<std::string> availableStringLocales =
580         intl::LocaleHelper::GetAvailableLocales(thread, "calendar", nullptr);
581     availableLocales = JSLocale::ConstructLocaleList(thread, availableStringLocales);
582     requestedLocales = factory->NewTaggedArray(1);
583     // test locale1
584     requestedLocales->Set(thread, 0, testLocale1);
585     result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
586                                                     LocaleMatcherOption::BEST_FIT, relevantExtensionKeys);
587     EXPECT_STREQ("id-u-ca-gregory-co-pinyin-de-id", result.locale.c_str());
588     result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
589                                                     LocaleMatcherOption::LOOKUP, relevantExtensionKeys);
590     EXPECT_STREQ("id-u-ca-gregory-co-pinyin-de-id", result.locale.c_str());
591     result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
592                                                     LocaleMatcherOption::EXCEPTION, relevantExtensionKeys);
593     EXPECT_STREQ("id-u-ca-gregory-co-pinyin-de-id", result.locale.c_str());
594     // test locale2
595     requestedLocales->Set(thread, 0, testLocale2);
596     result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
597                                      LocaleMatcherOption::BEST_FIT, relevantExtensionKeys);
598     EXPECT_STREQ("en-u-ca-ethioaa-co-phonebk", result.locale.c_str());
599     result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
600                                      LocaleMatcherOption::LOOKUP, relevantExtensionKeys);
601     EXPECT_STREQ("en-u-ca-ethioaa-co-phonebk", result.locale.c_str());
602     result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
603                                      LocaleMatcherOption::EXCEPTION, relevantExtensionKeys);
604     EXPECT_STREQ("en-u-ca-ethioaa-co-phonebk", result.locale.c_str());
605 }
606 
HWTEST_F_L0(JSLocaleTest,ResolveLocale_002)607 HWTEST_F_L0(JSLocaleTest, ResolveLocale_002)
608 {
609     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
610     JSHandle<TaggedArray> availableLocales = factory->EmptyArray();
611     JSHandle<TaggedArray> requestedLocales = factory->EmptyArray();
612     std::set<std::string> relevantExtensionKeys = {"hc", "lb", "kn", "kf"};
613     JSHandle<JSTaggedValue> testLocale1(factory->NewFromASCII("id-u-kn-false-kf-yes-de-ID"));
614     JSHandle<JSTaggedValue> testLocale2(factory->NewFromASCII("en-US-u-hc-h24-lb-strict"));
615     // availableLocales and requestLocales is empty
616     ResolvedLocale result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
617                                                     LocaleMatcherOption::BEST_FIT, relevantExtensionKeys);
618     EXPECT_STREQ("en-US", result.locale.c_str()); // default locale
619     // availableLocales and requestLocales is not empty
620     std::vector<std::string> availableStringLocales =
621         intl::LocaleHelper::GetAvailableLocales(thread, "calendar", nullptr);
622     availableLocales = JSLocale::ConstructLocaleList(thread, availableStringLocales);
623     requestedLocales = factory->NewTaggedArray(1);
624     // test locale1
625     requestedLocales->Set(thread, 0, testLocale1);
626     result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
627                                                     LocaleMatcherOption::BEST_FIT, relevantExtensionKeys);
628     EXPECT_STREQ("id-u-de-id-kf-kn-false", result.locale.c_str());
629     result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
630                                                     LocaleMatcherOption::LOOKUP, relevantExtensionKeys);
631     EXPECT_STREQ("id-u-de-id-kf-kn-false", result.locale.c_str());
632     result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
633                                                     LocaleMatcherOption::EXCEPTION, relevantExtensionKeys);
634     EXPECT_STREQ("id-u-de-id-kf-kn-false", result.locale.c_str());
635     // test locale2
636     requestedLocales->Set(thread, 0, testLocale2);
637     result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
638                                      LocaleMatcherOption::BEST_FIT, relevantExtensionKeys);
639     EXPECT_STREQ("en-US-u-hc-h24-lb-strict", result.locale.c_str());
640     result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
641                                      LocaleMatcherOption::LOOKUP, relevantExtensionKeys);
642     EXPECT_STREQ("en-US-u-hc-h24-lb-strict", result.locale.c_str());
643     result = JSLocale::ResolveLocale(thread, availableLocales, requestedLocales,
644                                      LocaleMatcherOption::EXCEPTION, relevantExtensionKeys);
645     EXPECT_STREQ("en-US-u-hc-h24-lb-strict", result.locale.c_str());
646 }
647 }  // namespace panda::test
648