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