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 testing::Test {
27 public:
SetUpTestCase()28 static void SetUpTestCase()
29 {
30 GTEST_LOG_(INFO) << "SetUpTestCase";
31 }
32
TearDownTestCase()33 static void TearDownTestCase()
34 {
35 GTEST_LOG_(INFO) << "TearDownCase";
36 }
37
SetUp()38 void SetUp() override
39 {
40 JSRuntimeOptions options;
41 #if PANDA_TARGET_LINUX
42 // for consistency requirement, use ohos_icu4j/data as icu-data-path
43 options.SetIcuDataPath(ICU_PATH);
44 #endif
45 options.SetEnableForceGC(true);
46 instance = JSNApi::CreateEcmaVM(options);
47 instance->SetEnableForceGC(true);
48 ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM";
49 thread = instance->GetJSThread();
50 scope = new EcmaHandleScope(thread);
51 }
52
TearDown()53 void TearDown() override
54 {
55 TestHelper::DestroyEcmaVMWithScope(instance, scope);
56 }
57
58 EcmaVM *instance {nullptr};
59 EcmaHandleScope *scope {nullptr};
60 JSThread *thread {nullptr};
61 };
62
63 // new DateTimeFormat(newTarget is defined)
HWTEST_F_L0(BuiltinsPluralRulesTest,PluralRulesConstructor)64 HWTEST_F_L0(BuiltinsPluralRulesTest, PluralRulesConstructor)
65 {
66 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
67 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
68 JSHandle<JSFunction> newTarget(env->GetPluralRulesFunction());
69
70 JSHandle<JSTaggedValue> localesString(factory->NewFromASCII("en-US"));
71 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*newTarget), 8);
72 ecmaRuntimeCallInfo->SetFunction(newTarget.GetTaggedValue());
73 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
74 ecmaRuntimeCallInfo->SetCallArg(0, localesString.GetTaggedValue());
75 // option tag is default value
76 ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue::Undefined());
77
78 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
79 JSTaggedValue result = BuiltinsPluralRules::PluralRulesConstructor(ecmaRuntimeCallInfo);
80 TestHelper::TearDownFrame(thread, prev);
81
82 EXPECT_TRUE(result.IsJSPluralRules());
83 }
84
JSPluralRulesCreateWithLocaleTest(JSThread * thread,JSHandle<JSTaggedValue> & locale,JSHandle<JSTaggedValue> & typeValue)85 static JSTaggedValue JSPluralRulesCreateWithLocaleTest(JSThread *thread, JSHandle<JSTaggedValue> &locale,
86 JSHandle<JSTaggedValue> &typeValue)
87 {
88 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
89 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
90 JSHandle<JSFunction> newTarget(env->GetPluralRulesFunction());
91 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
92 JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
93
94 JSHandle<JSTaggedValue> typeKey = thread->GlobalConstants()->GetHandledTypeString();
95 JSObject::SetProperty(thread, optionsObj, typeKey, typeValue);
96
97 JSHandle<JSTaggedValue> localesString = locale;
98 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*newTarget), 8);
99 ecmaRuntimeCallInfo->SetFunction(newTarget.GetTaggedValue());
100 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
101 ecmaRuntimeCallInfo->SetCallArg(0, localesString.GetTaggedValue());
102 ecmaRuntimeCallInfo->SetCallArg(1, optionsObj.GetTaggedValue());
103
104 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
105 JSTaggedValue result = BuiltinsPluralRules::PluralRulesConstructor(ecmaRuntimeCallInfo);
106 TestHelper::TearDownFrame(thread, prev);
107
108 EXPECT_TRUE(result.IsJSPluralRules());
109 return result;
110 }
111
112 // select(0, type(cardinal))
HWTEST_F_L0(BuiltinsPluralRulesTest,Select_001)113 HWTEST_F_L0(BuiltinsPluralRulesTest, Select_001)
114 {
115 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
116 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en-US"));
117 JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("cardinal"));
118 JSHandle<JSPluralRules> jsPluralRules =
119 JSHandle<JSPluralRules>(thread, JSPluralRulesCreateWithLocaleTest(thread, locale, typeValue));
120
121 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(0));
122 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
123 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
124 ecmaRuntimeCallInfo->SetThis(jsPluralRules.GetTaggedValue());
125 ecmaRuntimeCallInfo->SetCallArg(0, value.GetTaggedValue());
126
127 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
128 JSTaggedValue result = BuiltinsPluralRules::Select(ecmaRuntimeCallInfo);
129 TestHelper::TearDownFrame(thread, prev);
130
131 EXPECT_TRUE(result.IsString());
132 JSHandle<EcmaString> handleEcmaStr(thread, result);
133 EXPECT_STREQ("other", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
134 }
135
136 // select(1, type(cardinal))
HWTEST_F_L0(BuiltinsPluralRulesTest,Select_002)137 HWTEST_F_L0(BuiltinsPluralRulesTest, Select_002)
138 {
139 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
140 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en-US"));
141 JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("cardinal"));
142 JSHandle<JSPluralRules> jsPluralRules =
143 JSHandle<JSPluralRules>(thread, JSPluralRulesCreateWithLocaleTest(thread, locale, typeValue));
144
145 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
146 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
147 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
148 ecmaRuntimeCallInfo->SetThis(jsPluralRules.GetTaggedValue());
149 ecmaRuntimeCallInfo->SetCallArg(0, value.GetTaggedValue());
150
151 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
152 JSTaggedValue result = BuiltinsPluralRules::Select(ecmaRuntimeCallInfo);
153 TestHelper::TearDownFrame(thread, prev);
154
155 EXPECT_TRUE(result.IsString());
156 JSHandle<EcmaString> handleEcmaStr(thread, result);
157 EXPECT_STREQ("one", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
158 }
159
160 // select(2, type(cardinal))
HWTEST_F_L0(BuiltinsPluralRulesTest,Select_003)161 HWTEST_F_L0(BuiltinsPluralRulesTest, Select_003)
162 {
163 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
164 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en-US"));
165 JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("cardinal"));
166 JSHandle<JSPluralRules> jsPluralRules =
167 JSHandle<JSPluralRules>(thread, JSPluralRulesCreateWithLocaleTest(thread, locale, typeValue));
168
169 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(2));
170 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
171 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
172 ecmaRuntimeCallInfo->SetThis(jsPluralRules.GetTaggedValue());
173 ecmaRuntimeCallInfo->SetCallArg(0, value.GetTaggedValue());
174
175 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
176 JSTaggedValue result = BuiltinsPluralRules::Select(ecmaRuntimeCallInfo);
177 TestHelper::TearDownFrame(thread, prev);
178
179 EXPECT_TRUE(result.IsString());
180 JSHandle<EcmaString> handleEcmaStr(thread, result);
181 EXPECT_STREQ("other", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
182 }
183
184 // select(3, type(ordinal))
HWTEST_F_L0(BuiltinsPluralRulesTest,Select_004)185 HWTEST_F_L0(BuiltinsPluralRulesTest, Select_004)
186 {
187 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
188 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en-US"));
189 JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("ordinal"));
190 JSHandle<JSPluralRules> jsPluralRules =
191 JSHandle<JSPluralRules>(thread, JSPluralRulesCreateWithLocaleTest(thread, locale, typeValue));
192
193 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(3));
194 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
195 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
196 ecmaRuntimeCallInfo->SetThis(jsPluralRules.GetTaggedValue());
197 ecmaRuntimeCallInfo->SetCallArg(0, value.GetTaggedValue());
198
199 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
200 JSTaggedValue result = BuiltinsPluralRules::Select(ecmaRuntimeCallInfo);
201 TestHelper::TearDownFrame(thread, prev);
202
203 EXPECT_TRUE(result.IsString());
204 JSHandle<EcmaString> handleEcmaStr(thread, result);
205 EXPECT_STREQ("few", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
206 }
207
208 // select(2, type(ordinal))
HWTEST_F_L0(BuiltinsPluralRulesTest,Select_005)209 HWTEST_F_L0(BuiltinsPluralRulesTest, Select_005)
210 {
211 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
212 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en-US"));
213 JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("ordinal"));
214 JSHandle<JSPluralRules> jsPluralRules =
215 JSHandle<JSPluralRules>(thread, JSPluralRulesCreateWithLocaleTest(thread, locale, typeValue));
216
217 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(2));
218 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
219 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
220 ecmaRuntimeCallInfo->SetThis(jsPluralRules.GetTaggedValue());
221 ecmaRuntimeCallInfo->SetCallArg(0, value.GetTaggedValue());
222
223 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
224 JSTaggedValue result = BuiltinsPluralRules::Select(ecmaRuntimeCallInfo);
225 TestHelper::TearDownFrame(thread, prev);
226
227 EXPECT_TRUE(result.IsString());
228 JSHandle<EcmaString> handleEcmaStr(thread, result);
229 EXPECT_STREQ("two", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
230 }
231
232 // select(0, type(ordinal))
HWTEST_F_L0(BuiltinsPluralRulesTest,Select_006)233 HWTEST_F_L0(BuiltinsPluralRulesTest, Select_006)
234 {
235 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
236 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en-US"));
237 JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("ordinal"));
238 JSHandle<JSPluralRules> jsPluralRules =
239 JSHandle<JSPluralRules>(thread, JSPluralRulesCreateWithLocaleTest(thread, locale, typeValue));
240
241 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(0));
242 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
243 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
244 ecmaRuntimeCallInfo->SetThis(jsPluralRules.GetTaggedValue());
245 ecmaRuntimeCallInfo->SetCallArg(0, value.GetTaggedValue());
246
247 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
248 JSTaggedValue result = BuiltinsPluralRules::Select(ecmaRuntimeCallInfo);
249 TestHelper::TearDownFrame(thread, prev);
250
251 EXPECT_TRUE(result.IsString());
252 JSHandle<EcmaString> handleEcmaStr(thread, result);
253 EXPECT_STREQ("other", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
254 }
255
256 // select(1, type(ordinal))
HWTEST_F_L0(BuiltinsPluralRulesTest,Select_007)257 HWTEST_F_L0(BuiltinsPluralRulesTest, Select_007)
258 {
259 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
260 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en-US"));
261 JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("ordinal"));
262 JSHandle<JSPluralRules> jsPluralRules =
263 JSHandle<JSPluralRules>(thread, JSPluralRulesCreateWithLocaleTest(thread, locale, typeValue));
264
265 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
266 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
267 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
268 ecmaRuntimeCallInfo->SetThis(jsPluralRules.GetTaggedValue());
269 ecmaRuntimeCallInfo->SetCallArg(0, value.GetTaggedValue());
270
271 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
272 JSTaggedValue result = BuiltinsPluralRules::Select(ecmaRuntimeCallInfo);
273 TestHelper::TearDownFrame(thread, prev);
274
275 EXPECT_TRUE(result.IsString());
276 JSHandle<EcmaString> handleEcmaStr(thread, result);
277 EXPECT_STREQ("one", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
278 }
279
HWTEST_F_L0(BuiltinsPluralRulesTest,SupportedLocalesOf)280 HWTEST_F_L0(BuiltinsPluralRulesTest, SupportedLocalesOf)
281 {
282 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
283 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("id-u-co-pinyin-de-ID"));
284
285 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
286 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
287 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
288 ecmaRuntimeCallInfo->SetCallArg(0, locale.GetTaggedValue());
289 // set the tag is default value
290 ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue::Undefined());
291
292 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
293 JSTaggedValue resultArr = BuiltinsPluralRules::SupportedLocalesOf(ecmaRuntimeCallInfo);
294 TestHelper::TearDownFrame(thread, prev);
295
296 JSHandle<JSArray> resultHandle(thread, resultArr);
297 JSHandle<TaggedArray> elements(thread, resultHandle->GetElements());
298 EXPECT_EQ(elements->GetLength(), 1U);
299 JSHandle<EcmaString> handleEcmaStr(thread, elements->Get(0));
300 EXPECT_STREQ("id-u-co-pinyin-de-id", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
301 }
302
HWTEST_F_L0(BuiltinsPluralRulesTest,ResolvedOptions)303 HWTEST_F_L0(BuiltinsPluralRulesTest, ResolvedOptions)
304 {
305 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
306 auto globalConst = thread->GlobalConstants();
307 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en-US"));
308 JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("ordinal"));
309 JSHandle<JSPluralRules> jsPluralRules =
310 JSHandle<JSPluralRules>(thread, JSPluralRulesCreateWithLocaleTest(thread, locale, typeValue));
311
312 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
313 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
314 ecmaRuntimeCallInfo->SetThis(jsPluralRules.GetTaggedValue());
315
316 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
317 JSTaggedValue result = BuiltinsPluralRules::ResolvedOptions(ecmaRuntimeCallInfo);
318 TestHelper::TearDownFrame(thread, prev);
319
320 JSHandle<JSTaggedValue> resultObj =
321 JSHandle<JSTaggedValue>(thread, JSTaggedValue(static_cast<JSTaggedType>(result.GetRawData())));
322 // judge whether the properties of the object are the same as those of jspluralrulesformat tag
323 JSHandle<JSTaggedValue> localeKey = globalConst->GetHandledLocaleString();
324 JSHandle<JSTaggedValue> localeValue(factory->NewFromASCII("en"));
325 EXPECT_EQ(JSTaggedValue::SameValue(
326 JSObject::GetProperty(thread, resultObj, localeKey).GetValue(), localeValue), true);
327 JSHandle<JSTaggedValue> typeKey = globalConst->GetHandledTypeString();
328 EXPECT_EQ(JSTaggedValue::SameValue(
329 JSObject::GetProperty(thread, resultObj, typeKey).GetValue(), typeValue), true);
330 }
331 } // namespace panda::test
332