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_plural_rules.h"
17 
18 #include "ecmascript/global_env.h"
19 #include "ecmascript/js_plural_rules.h"
20 #include "ecmascript/tests/test_helper.h"
21 
22 using namespace panda::ecmascript;
23 using namespace panda::ecmascript::builtins;
24 
25 namespace panda::test {
26 class BuiltinsPluralRulesTest : public BaseTestWithScope<true> {
27 };
28 
29 // new DateTimeFormat(newTarget is defined)
HWTEST_F_L0(BuiltinsPluralRulesTest, PluralRulesConstructor)30 HWTEST_F_L0(BuiltinsPluralRulesTest, PluralRulesConstructor)
31 {
32     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
33     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
34     JSHandle<JSFunction> newTarget(env->GetPluralRulesFunction());
35 
36     JSHandle<JSTaggedValue> localesString(factory->NewFromASCII("en-US"));
37     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*newTarget), 8);
38     ecmaRuntimeCallInfo->SetFunction(newTarget.GetTaggedValue());
39     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
40     ecmaRuntimeCallInfo->SetCallArg(0, localesString.GetTaggedValue());
41     // option tag is default value
42     ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue::Undefined());
43 
44     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
45     JSTaggedValue result = BuiltinsPluralRules::PluralRulesConstructor(ecmaRuntimeCallInfo);
46     TestHelper::TearDownFrame(thread, prev);
47 
48     EXPECT_TRUE(result.IsJSPluralRules());
49 }
50 
JSPluralRulesCreateWithLocaleTest(JSThread *thread, JSHandle<JSTaggedValue> &locale, JSHandle<JSTaggedValue> &typeValue)51 static JSTaggedValue JSPluralRulesCreateWithLocaleTest(JSThread *thread, JSHandle<JSTaggedValue> &locale,
52                                                        JSHandle<JSTaggedValue> &typeValue)
53 {
54     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
55     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
56     JSHandle<JSFunction> newTarget(env->GetPluralRulesFunction());
57     JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
58     JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
59 
60     JSHandle<JSTaggedValue> typeKey = thread->GlobalConstants()->GetHandledTypeString();
61     JSObject::SetProperty(thread, optionsObj, typeKey, typeValue);
62 
63     JSHandle<JSTaggedValue> localesString = locale;
64     std::vector<JSTaggedValue> args{ localesString.GetTaggedValue(), optionsObj.GetTaggedValue()};
65     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, newTarget, args, 8);
66 
67     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
68     JSTaggedValue result = BuiltinsPluralRules::PluralRulesConstructor(ecmaRuntimeCallInfo);
69     TestHelper::TearDownFrame(thread, prev);
70 
71     EXPECT_TRUE(result.IsJSPluralRules());
72     return result;
73 }
74 
SelectTest(JSThread *thread, std::string_view data, std::string_view expectStr, int v)75 static void SelectTest(JSThread *thread, std::string_view data, std::string_view expectStr, int v)
76 {
77     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
78     JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en-US"));
79     JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII(data));
80     JSHandle<JSPluralRules> jsPluralRules =
81         JSHandle<JSPluralRules>(thread, JSPluralRulesCreateWithLocaleTest(thread, locale, typeValue));
82 
83     JSHandle<JSTaggedValue> value(thread, JSTaggedValue(v));
84     auto ecmaRuntimeCallInfo =
85         TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);  // 6 : argv length
86     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
87     ecmaRuntimeCallInfo->SetThis(jsPluralRules.GetTaggedValue());
88     ecmaRuntimeCallInfo->SetCallArg(0, value.GetTaggedValue());
89 
90     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
91     JSTaggedValue result = BuiltinsPluralRules::Select(ecmaRuntimeCallInfo);
92     TestHelper::TearDownFrame(thread, prev);
93 
94     EXPECT_TRUE(result.IsString());
95     JSHandle<EcmaString> handleEcmaStr(thread, result);
96     EXPECT_STREQ(expectStr.data(), EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
97 }
98 
99 // select(0, type(cardinal))
HWTEST_F_L0(BuiltinsPluralRulesTest, Select_001)100 HWTEST_F_L0(BuiltinsPluralRulesTest, Select_001)
101 {
102     SelectTest(thread, "cardinal", "other", 0);
103 }
104 
105 // select(1, type(cardinal))
HWTEST_F_L0(BuiltinsPluralRulesTest, Select_002)106 HWTEST_F_L0(BuiltinsPluralRulesTest, Select_002)
107 {
108     SelectTest(thread, "cardinal", "one", 1);
109 }
110 
111 // select(2, type(cardinal))
HWTEST_F_L0(BuiltinsPluralRulesTest, Select_003)112 HWTEST_F_L0(BuiltinsPluralRulesTest, Select_003)
113 {
114     SelectTest(thread, "cardinal", "other", 2);
115 }
116 
117 // select(3, type(ordinal))
HWTEST_F_L0(BuiltinsPluralRulesTest, Select_004)118 HWTEST_F_L0(BuiltinsPluralRulesTest, Select_004)
119 {
120     SelectTest(thread, "ordinal", "few", 3);
121 }
122 
123 // select(2, type(ordinal))
HWTEST_F_L0(BuiltinsPluralRulesTest, Select_005)124 HWTEST_F_L0(BuiltinsPluralRulesTest, Select_005)
125 {
126     SelectTest(thread, "ordinal", "two", 2);
127 }
128 
129 // select(0, type(ordinal))
HWTEST_F_L0(BuiltinsPluralRulesTest, Select_006)130 HWTEST_F_L0(BuiltinsPluralRulesTest, Select_006)
131 {
132     SelectTest(thread, "ordinal", "other", 0);
133 }
134 
135 // select(1, type(ordinal))
HWTEST_F_L0(BuiltinsPluralRulesTest, Select_007)136 HWTEST_F_L0(BuiltinsPluralRulesTest, Select_007)
137 {
138     SelectTest(thread, "ordinal", "one", 1);
139 }
140 
HWTEST_F_L0(BuiltinsPluralRulesTest, SupportedLocalesOf)141 HWTEST_F_L0(BuiltinsPluralRulesTest, SupportedLocalesOf)
142 {
143     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
144     JSHandle<JSTaggedValue> locale(factory->NewFromASCII("id-u-co-pinyin-de-ID"));
145 
146     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
147     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
148     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
149     ecmaRuntimeCallInfo->SetCallArg(0, locale.GetTaggedValue());
150     // set the tag is default value
151     ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue::Undefined());
152 
153     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
154     JSTaggedValue resultArr = BuiltinsPluralRules::SupportedLocalesOf(ecmaRuntimeCallInfo);
155     TestHelper::TearDownFrame(thread, prev);
156 
157     JSHandle<JSArray> resultHandle(thread, resultArr);
158     JSHandle<TaggedArray> elements(thread, resultHandle->GetElements());
159     EXPECT_EQ(elements->GetLength(), 1U);
160     JSHandle<EcmaString> handleEcmaStr(thread, elements->Get(0));
161     EXPECT_STREQ("id-u-co-pinyin-de-id", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
162 }
163 
HWTEST_F_L0(BuiltinsPluralRulesTest, ResolvedOptions)164 HWTEST_F_L0(BuiltinsPluralRulesTest, ResolvedOptions)
165 {
166     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
167     auto globalConst = thread->GlobalConstants();
168     JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en-US"));
169     JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("ordinal"));
170     JSHandle<JSPluralRules> jsPluralRules =
171         JSHandle<JSPluralRules>(thread, JSPluralRulesCreateWithLocaleTest(thread, locale, typeValue));
172 
173     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
174     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
175     ecmaRuntimeCallInfo->SetThis(jsPluralRules.GetTaggedValue());
176 
177     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
178     JSTaggedValue result = BuiltinsPluralRules::ResolvedOptions(ecmaRuntimeCallInfo);
179     TestHelper::TearDownFrame(thread, prev);
180 
181     JSHandle<JSTaggedValue> resultObj =
182         JSHandle<JSTaggedValue>(thread, JSTaggedValue(static_cast<JSTaggedType>(result.GetRawData())));
183     // judge whether the properties of the object are the same as those of jspluralrulesformat tag
184     JSHandle<JSTaggedValue> localeKey = globalConst->GetHandledLocaleString();
185     JSHandle<JSTaggedValue> localeValue(factory->NewFromASCII("en"));
186     EXPECT_EQ(JSTaggedValue::SameValue(
187         JSObject::GetProperty(thread, resultObj, localeKey).GetValue(), localeValue), true);
188     JSHandle<JSTaggedValue> typeKey = globalConst->GetHandledTypeString();
189     EXPECT_EQ(JSTaggedValue::SameValue(
190         JSObject::GetProperty(thread, resultObj, typeKey).GetValue(), typeValue), true);
191 }
192 } // namespace panda::test
193