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