1/*
2 * Copyright (c) 2021 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/builtins/builtins_locale.h"
17
18#include "ecmascript/global_env.h"
19#include "ecmascript/js_locale.h"
20#include "ecmascript/tests/test_helper.h"
21
22using namespace panda::ecmascript;
23using namespace panda::ecmascript::builtins;
24
25namespace panda::test {
26class BuiltinsLocaleTest : public BaseTestWithScope<true> {
27};
28
29// new locale( [ options ] )
30HWTEST_F_L0(BuiltinsLocaleTest, LocaleConstructor)
31{
32    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
33    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
34    JSHandle<JSFunction> newTarget(env->GetLocaleFunction());
35    JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
36
37    JSHandle<JSTaggedValue> languageKey = thread->GlobalConstants()->GetHandledLanguageString();
38    JSHandle<JSTaggedValue> regionKey = thread->GlobalConstants()->GetHandledRegionString();
39    JSHandle<JSTaggedValue> numericKey = thread->GlobalConstants()->GetHandledNumericString();
40    JSHandle<JSTaggedValue> scriptKey = thread->GlobalConstants()->GetHandledScriptString();
41    JSHandle<JSTaggedValue> languageValue(factory->NewFromASCII("cn"));
42    JSHandle<JSTaggedValue> regionValue(factory->NewFromASCII("CN"));
43    JSHandle<JSTaggedValue> scriptValue(factory->NewFromASCII("Chin"));
44    JSHandle<JSTaggedValue> numericValue(thread, JSTaggedValue::True());
45    JSHandle<JSTaggedValue> localeString(factory->NewFromASCII("zh-Hans-CN"));
46
47    JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
48    JSObject::SetProperty(thread, optionsObj, numericKey, numericValue);
49    JSObject::SetProperty(thread, optionsObj, regionKey, regionValue);
50    JSObject::SetProperty(thread, optionsObj, languageKey, languageValue);
51    JSObject::SetProperty(thread, optionsObj, scriptKey, scriptValue);
52
53    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*newTarget), 8);
54    ecmaRuntimeCallInfo->SetFunction(newTarget.GetTaggedValue());
55    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
56    ecmaRuntimeCallInfo->SetCallArg(0, localeString.GetTaggedValue());
57    ecmaRuntimeCallInfo->SetCallArg(1, optionsObj.GetTaggedValue());
58
59    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
60    JSTaggedValue result = BuiltinsLocale::LocaleConstructor(ecmaRuntimeCallInfo);
61    TestHelper::TearDownFrame(thread, prev);
62
63    EXPECT_TRUE(result.IsJSLocale());
64}
65
66static JSTaggedValue JSLocaleCreateWithOptionTest(JSThread *thread)
67{
68    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
69    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
70    JSHandle<JSFunction> newTarget(env->GetLocaleFunction());
71    JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
72
73    JSHandle<JSTaggedValue> languageKey = thread->GlobalConstants()->GetHandledLanguageString();
74    JSHandle<JSTaggedValue> regionKey = thread->GlobalConstants()->GetHandledRegionString();
75    JSHandle<JSTaggedValue> scriptKey = thread->GlobalConstants()->GetHandledScriptString();
76    JSHandle<JSTaggedValue> languageValue(factory->NewFromASCII("en"));
77    JSHandle<JSTaggedValue> regionValue(factory->NewFromASCII("US"));
78    JSHandle<JSTaggedValue> scriptValue(factory->NewFromASCII("Latn"));
79    JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en-Latn-US"));
80    // set option(language, region, script)
81    JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
82    JSObject::SetProperty(thread, optionsObj, languageKey, languageValue);
83    JSObject::SetProperty(thread, optionsObj, regionKey, regionValue);
84    JSObject::SetProperty(thread, optionsObj, scriptKey, scriptValue);
85
86    JSHandle<JSTaggedValue> calendarValue(factory->NewFromASCII("chinese"));
87    JSHandle<JSTaggedValue> calendarKey = thread->GlobalConstants()->GetHandledCalendarString();
88    JSObject::SetProperty(thread, optionsObj, calendarKey, calendarValue); // test chinese calendar
89
90    JSHandle<JSTaggedValue> hourCycleKey = thread->GlobalConstants()->GetHandledHourCycleString();
91    JSHandle<JSTaggedValue> hourCycleValue(factory->NewFromASCII("h24"));
92    JSObject::SetProperty(thread, optionsObj, hourCycleKey, hourCycleValue); // test h24
93
94    JSHandle<JSTaggedValue> numericKey = thread->GlobalConstants()->GetHandledNumericString();
95    JSHandle<JSTaggedValue> numericValue(factory->NewFromASCII("true"));
96    JSObject::SetProperty(thread, optionsObj, numericKey, numericValue); // test true
97
98    JSHandle<JSTaggedValue> numberingSystemKey = thread->GlobalConstants()->GetHandledNumberingSystemString();
99    JSHandle<JSTaggedValue> numberingSystemValue(factory->NewFromASCII("mong"));
100    JSObject::SetProperty(thread, optionsObj, numberingSystemKey, numberingSystemValue); // test mong
101
102    JSHandle<JSTaggedValue> collationKey = thread->GlobalConstants()->GetHandledCollationString();
103    JSHandle<JSTaggedValue> collationValue(factory->NewFromASCII("compat"));
104    JSObject::SetProperty(thread, optionsObj, collationKey, collationValue); // test compat
105
106    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*newTarget), 8);
107    ecmaRuntimeCallInfo->SetFunction(newTarget.GetTaggedValue());
108    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
109    ecmaRuntimeCallInfo->SetCallArg(0, locale.GetTaggedValue());
110    ecmaRuntimeCallInfo->SetCallArg(1, optionsObj.GetTaggedValue());
111
112    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
113    JSTaggedValue result = BuiltinsLocale::LocaleConstructor(ecmaRuntimeCallInfo);
114    TestHelper::TearDownFrame(thread, prev);
115    return result;
116}
117
118enum class AlgorithmType {
119    TO_STRING,
120    GET_BASE_NAME,
121    GET_HOUR_CYCLE,
122    GET_CALENDAR,
123    GET_CASE_FIRST,
124    GET_COLLATION,
125    GET_NUMERIC,
126    GET_NUMBERING_SYSTEM,
127    GET_LANGUAGE,
128    GET_SCRIPT,
129    GET_REGION,
130    MAXI_MIZE,
131    MINI_MIZE,
132};
133
134JSTaggedValue AlgorithmOther(EcmaRuntimeCallInfo *ecmaRuntimeCallInfo, AlgorithmType type)
135{
136    switch (type) {
137        case AlgorithmType::TO_STRING:
138            return BuiltinsLocale::ToString(ecmaRuntimeCallInfo);
139        case AlgorithmType::MAXI_MIZE:
140            return BuiltinsLocale::Maximize(ecmaRuntimeCallInfo);
141        case AlgorithmType::MINI_MIZE:
142            return BuiltinsLocale::Minimize(ecmaRuntimeCallInfo);
143        default:
144            return JSTaggedValue();
145    }
146}
147
148JSTaggedValue LocaleAlgorithm(JSThread *thread, JSTaggedValue thisArg, std::vector<JSTaggedValue>& args,
149    int32_t argLen, AlgorithmType type)
150{
151    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), argLen);
152    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
153    ecmaRuntimeCallInfo->SetThis(thisArg);
154    for (size_t i = 0; i < args.size(); i++) {
155        ecmaRuntimeCallInfo->SetCallArg(i, args[i]);
156    }
157    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
158    JSTaggedValue result;
159    switch (type) {
160        case AlgorithmType::GET_BASE_NAME:
161            result = BuiltinsLocale::GetBaseName(ecmaRuntimeCallInfo);
162            break;
163        case AlgorithmType::GET_HOUR_CYCLE:
164            result = BuiltinsLocale::GetHourCycle(ecmaRuntimeCallInfo);
165            break;
166        case AlgorithmType::GET_CALENDAR:
167            result = BuiltinsLocale::GetCalendar(ecmaRuntimeCallInfo);
168            break;
169        case AlgorithmType::GET_CASE_FIRST:
170            result = BuiltinsLocale::GetCaseFirst(ecmaRuntimeCallInfo);
171            break;
172        case AlgorithmType::GET_COLLATION:
173            result = BuiltinsLocale::GetCollation(ecmaRuntimeCallInfo);
174            break;
175        case AlgorithmType::GET_NUMERIC:
176            result = BuiltinsLocale::GetNumeric(ecmaRuntimeCallInfo);
177            break;
178        case AlgorithmType::GET_NUMBERING_SYSTEM:
179            result = BuiltinsLocale::GetNumberingSystem(ecmaRuntimeCallInfo);
180            break;
181        case AlgorithmType::GET_LANGUAGE:
182            result = BuiltinsLocale::GetLanguage(ecmaRuntimeCallInfo);
183            break;
184        case AlgorithmType::GET_SCRIPT:
185            result = BuiltinsLocale::GetScript(ecmaRuntimeCallInfo);
186            break;
187        case AlgorithmType::GET_REGION:
188            result = BuiltinsLocale::GetRegion(ecmaRuntimeCallInfo);
189            break;
190        default:
191            result = AlgorithmOther(ecmaRuntimeCallInfo, type);
192            break;
193    }
194    TestHelper::TearDownFrame(thread, prev);
195    return result;
196}
197
198HWTEST_F_L0(BuiltinsLocaleTest, ToString)
199{
200    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
201    JSHandle<JSLocale> jsLocale = JSHandle<JSLocale>(thread, JSLocaleCreateWithOptionTest(thread));
202    std::vector<JSTaggedValue> args{};
203    auto result = LocaleAlgorithm(thread, jsLocale.GetTaggedValue(), args, 4, AlgorithmType::TO_STRING); // 4 : arg len
204
205    EXPECT_TRUE(result.IsString());
206    JSHandle<EcmaString> handleEcmaStr(thread, result);
207    JSHandle<EcmaString> resultStr(
208        factory->NewFromASCII("en-Latn-US-u-ca-chinese-co-compat-hc-h24-kn-nu-mong"));
209    EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr, resultStr), 0);
210}
211
212HWTEST_F_L0(BuiltinsLocaleTest, GetBaseName)
213{
214    JSHandle<JSLocale> jsLocale = JSHandle<JSLocale>(thread, JSLocaleCreateWithOptionTest(thread));
215
216    std::vector<JSTaggedValue> args{};
217    auto result =
218        LocaleAlgorithm(thread, jsLocale.GetTaggedValue(), args, 4, AlgorithmType::GET_BASE_NAME);  // 4 : arg len
219
220    EXPECT_TRUE(result.IsString());
221    JSHandle<EcmaString> handleEcmaStr(thread, result);
222    EXPECT_STREQ("en-Latn-US", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
223}
224
225HWTEST_F_L0(BuiltinsLocaleTest, GetHourCycle)
226{
227    JSHandle<JSLocale> jsLocale = JSHandle<JSLocale>(thread, JSLocaleCreateWithOptionTest(thread));
228
229    std::vector<JSTaggedValue> args{};
230    auto result =
231        LocaleAlgorithm(thread, jsLocale.GetTaggedValue(), args, 4, AlgorithmType::GET_HOUR_CYCLE);  // 4 : arg len
232
233    EXPECT_TRUE(result.IsString());
234    JSHandle<EcmaString> handleEcmaStr(thread, result);
235    EXPECT_STREQ("h24", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
236}
237
238HWTEST_F_L0(BuiltinsLocaleTest, GetCalendar)
239{
240    JSHandle<JSLocale> jsLocale = JSHandle<JSLocale>(thread, JSLocaleCreateWithOptionTest(thread));
241    std::vector<JSTaggedValue> args{};
242    auto result =
243        LocaleAlgorithm(thread, jsLocale.GetTaggedValue(), args, 4, AlgorithmType::GET_CALENDAR);  // 4 : arg len
244
245    EXPECT_TRUE(result.IsString());
246    JSHandle<EcmaString> handleEcmaStr(thread, result);
247    EXPECT_STREQ("chinese", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
248}
249
250HWTEST_F_L0(BuiltinsLocaleTest, GetCaseFirst)
251{
252    JSHandle<JSLocale> jsLocale = JSHandle<JSLocale>(thread, JSLocaleCreateWithOptionTest(thread));
253
254    std::vector<JSTaggedValue> args{};
255    auto result =
256        LocaleAlgorithm(thread, jsLocale.GetTaggedValue(), args, 4, AlgorithmType::GET_CASE_FIRST);  // 4 : arg len
257
258    EXPECT_TRUE(result.IsUndefined());
259}
260
261HWTEST_F_L0(BuiltinsLocaleTest, GetCollation)
262{
263    JSHandle<JSLocale> jsLocale = JSHandle<JSLocale>(thread, JSLocaleCreateWithOptionTest(thread));
264
265    std::vector<JSTaggedValue> args{};
266    auto result =
267        LocaleAlgorithm(thread, jsLocale.GetTaggedValue(), args, 4, AlgorithmType::GET_COLLATION);  // 4 : arg len
268
269    EXPECT_TRUE(result.IsString());
270    JSHandle<EcmaString> handleEcmaStr(thread, result);
271    EXPECT_STREQ("compat", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
272}
273
274HWTEST_F_L0(BuiltinsLocaleTest, GetNumeric)
275{
276    JSHandle<JSLocale> jsLocale = JSHandle<JSLocale>(thread, JSLocaleCreateWithOptionTest(thread));
277
278    std::vector<JSTaggedValue> args{};
279    auto result =
280        LocaleAlgorithm(thread, jsLocale.GetTaggedValue(), args, 4, AlgorithmType::GET_NUMERIC);  // 4 : arg len
281
282    EXPECT_EQ(result.GetRawData(), JSTaggedValue::True().GetRawData());
283}
284
285HWTEST_F_L0(BuiltinsLocaleTest, GetNumberingSystem)
286{
287    JSHandle<JSLocale> jsLocale = JSHandle<JSLocale>(thread, JSLocaleCreateWithOptionTest(thread));
288
289    std::vector<JSTaggedValue> args{};
290    auto result = LocaleAlgorithm(thread, jsLocale.GetTaggedValue(), args, 4,
291                                  AlgorithmType::GET_NUMBERING_SYSTEM);  // 4 : arg len
292
293    EXPECT_TRUE(result.IsString());
294    JSHandle<EcmaString> handleEcmaStr(thread, result);
295    EXPECT_STREQ("mong", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
296}
297
298HWTEST_F_L0(BuiltinsLocaleTest, GetLanguage)
299{
300    JSHandle<JSLocale> jsLocale = JSHandle<JSLocale>(thread, JSLocaleCreateWithOptionTest(thread));
301
302    std::vector<JSTaggedValue> args{};
303    auto result =
304        LocaleAlgorithm(thread, jsLocale.GetTaggedValue(), args, 4, AlgorithmType::GET_LANGUAGE);  // 4 : arg len
305
306    EXPECT_TRUE(result.IsString());
307    JSHandle<EcmaString> handleEcmaStr(thread, result);
308    EXPECT_STREQ("en", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
309}
310
311HWTEST_F_L0(BuiltinsLocaleTest, GetScript)
312{
313    JSHandle<JSLocale> jsLocale = JSHandle<JSLocale>(thread, JSLocaleCreateWithOptionTest(thread));
314
315    std::vector<JSTaggedValue> args{};
316    auto result = LocaleAlgorithm(thread, jsLocale.GetTaggedValue(), args, 4, AlgorithmType::GET_SCRIPT); // 4 : arg len
317
318    EXPECT_TRUE(result.IsString());
319    JSHandle<EcmaString> handleEcmaStr(thread, result);
320    EXPECT_STREQ("Latn", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
321}
322
323HWTEST_F_L0(BuiltinsLocaleTest, GetRegion)
324{
325    JSHandle<JSLocale> jsLocale = JSHandle<JSLocale>(thread, JSLocaleCreateWithOptionTest(thread));
326
327    std::vector<JSTaggedValue> args{};
328    auto result = LocaleAlgorithm(thread, jsLocale.GetTaggedValue(), args, 4, AlgorithmType::GET_REGION); // 4 : arg len
329
330    EXPECT_TRUE(result.IsString());
331    JSHandle<EcmaString> handleEcmaStr(thread, result);
332    EXPECT_STREQ("US", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
333}
334
335static JSTaggedValue JSLocaleCreateWithOptionsTagsTest(JSThread *thread, JSHandle<JSTaggedValue> &value)
336{
337    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
338    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
339    JSHandle<JSFunction> newTarget(env->GetLocaleFunction());
340    JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
341
342    JSHandle<JSTaggedValue> languageKey = thread->GlobalConstants()->GetHandledLanguageString();
343    JSHandle<JSTaggedValue> languageValue = JSHandle<JSTaggedValue>(value);
344    JSHandle<EcmaString> locale = factory->NewFromASCII("zh");
345    // set option(language)
346    JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
347    JSObject::SetProperty(thread, optionsObj, languageKey, languageValue);
348
349    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*newTarget), 8);
350    ecmaRuntimeCallInfo->SetFunction(newTarget.GetTaggedValue());
351    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
352    ecmaRuntimeCallInfo->SetCallArg(0, locale.GetTaggedValue());
353    ecmaRuntimeCallInfo->SetCallArg(1, optionsObj.GetTaggedValue());
354
355    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
356    JSTaggedValue result = BuiltinsLocale::LocaleConstructor(ecmaRuntimeCallInfo);
357    EXPECT_TRUE(result.IsJSLocale());
358    TestHelper::TearDownFrame(thread, prev);
359    return result;
360}
361
362HWTEST_F_L0(BuiltinsLocaleTest, Maximize_001)
363{
364    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
365    // set language,then call Maximize function get language,script and region
366    JSHandle<JSTaggedValue> languageValue(factory->NewFromASCII("zh"));
367    JSHandle<JSLocale> jsLocale = JSHandle<JSLocale>(thread, JSLocaleCreateWithOptionsTagsTest(thread, languageValue));
368
369    std::vector<JSTaggedValue> args{};
370    auto resultObj =
371        LocaleAlgorithm(thread, jsLocale.GetTaggedValue(), args, 4, AlgorithmType::MAXI_MIZE);  // 4 : arg len
372
373    JSHandle<JSLocale> resultLocale(thread, resultObj);
374    auto result =
375        LocaleAlgorithm(thread, resultLocale.GetTaggedValue(), args, 4, AlgorithmType::GET_BASE_NAME);  // 4 : arg len
376
377    EXPECT_TRUE(result.IsString());
378    JSHandle<EcmaString> handleEcmaStr(thread, result);
379    EXPECT_STREQ("zh-Hans-CN", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
380}
381
382HWTEST_F_L0(BuiltinsLocaleTest, Maximize_002)
383{
384    // set language,script,region and numeric and it's maximized
385    JSHandle<JSLocale> jsLocale = JSHandle<JSLocale>(thread, JSLocaleCreateWithOptionTest(thread));
386
387    std::vector<JSTaggedValue> args{};
388    auto resultObj =
389        LocaleAlgorithm(thread, jsLocale.GetTaggedValue(), args, 4, AlgorithmType::MAXI_MIZE);  // 4 : arg len
390    JSHandle<JSLocale> resultLocale(thread, resultObj);
391    auto result =
392        LocaleAlgorithm(thread, resultLocale.GetTaggedValue(), args, 4, AlgorithmType::GET_BASE_NAME);  // 4 : arg len
393
394    EXPECT_TRUE(result.IsString());
395    JSHandle<EcmaString> handleEcmaStr(thread, result);
396    EXPECT_STREQ("en-Latn-US", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
397}
398
399HWTEST_F_L0(BuiltinsLocaleTest, Minimize_001)
400{
401    // set language, script, region, and it's maximized,then call Minimize function get language
402    JSHandle<JSLocale> jsLocale = JSHandle<JSLocale>(thread, JSLocaleCreateWithOptionTest(thread));
403
404    std::vector<JSTaggedValue> args{};
405    auto resultObj =
406        LocaleAlgorithm(thread, jsLocale.GetTaggedValue(), args, 4, AlgorithmType::MINI_MIZE);  // 4 : arg len
407
408    JSHandle<JSLocale> resultLocale(thread, resultObj);
409    auto result =
410        LocaleAlgorithm(thread, resultLocale.GetTaggedValue(), args, 4, AlgorithmType::GET_BASE_NAME);  // 4 : arg len
411
412    EXPECT_TRUE(result.IsString());
413    JSHandle<EcmaString> handleEcmaStr(thread, result);
414    EXPECT_STREQ("en", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
415}
416
417HWTEST_F_L0(BuiltinsLocaleTest, Minimize_002)
418{
419    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
420    // set language and it's minimized
421    JSHandle<JSTaggedValue> languageValue(factory->NewFromASCII("zh"));
422    JSHandle<JSLocale> jsLocale = JSHandle<JSLocale>(thread, JSLocaleCreateWithOptionsTagsTest(thread, languageValue));
423
424    std::vector<JSTaggedValue> args{};
425    auto resultObj =
426        LocaleAlgorithm(thread, jsLocale.GetTaggedValue(), args, 4, AlgorithmType::MINI_MIZE);  // 4 : arg len
427
428    JSHandle<JSLocale> resultLocale(thread, resultObj);
429    auto result =
430        LocaleAlgorithm(thread, resultLocale.GetTaggedValue(), args, 4, AlgorithmType::TO_STRING);  // 4 : arg len
431
432    EXPECT_TRUE(result.IsString());
433    JSHandle<EcmaString> handleEcmaStr(thread, result);
434    EXPECT_STREQ("zh", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
435}
436
437// test NormalizeKeywordValue(kf is not setted "yes")
438HWTEST_F_L0(BuiltinsLocaleTest, NormalizeKeywordValue)
439{
440    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
441    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
442    JSHandle<JSFunction> newTarget(env->GetLocaleFunction());
443    JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
444
445    JSHandle<JSTaggedValue> caseFirstKey = thread->GlobalConstants()->GetHandledCaseFirstString();
446    JSHandle<JSTaggedValue> caseFirstValue(factory->NewFromASCII("false"));
447    JSHandle<EcmaString> locale = factory->NewFromASCII("en-US");
448
449    JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
450    JSObject::SetProperty(thread, optionsObj, caseFirstKey, caseFirstValue);
451
452    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*newTarget), 8);
453    ecmaRuntimeCallInfo->SetFunction(newTarget.GetTaggedValue());
454    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
455    ecmaRuntimeCallInfo->SetCallArg(0, locale.GetTaggedValue());
456    ecmaRuntimeCallInfo->SetCallArg(1, optionsObj.GetTaggedValue());
457
458    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
459    JSTaggedValue result = BuiltinsLocale::LocaleConstructor(ecmaRuntimeCallInfo);
460    TestHelper::TearDownFrame(thread, prev);
461
462    JSHandle<JSLocale> jsInitLocale(thread, result);
463    JSTaggedValue keyWords = JSLocale::NormalizeKeywordValue(thread, jsInitLocale, "kf");
464    EXPECT_STREQ("false", EcmaStringAccessor(keyWords).ToCString().c_str());
465}
466}  // namespace panda::test
467