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/builtins/builtins_list_format.h"
17
18 #include "ecmascript/global_env.h"
19 #include "ecmascript/js_list_format.h"
20 #include "ecmascript/js_array.h"
21 #include "ecmascript/tests/test_helper.h"
22
23 using namespace panda::ecmascript;
24 using namespace panda::ecmascript::builtins;
25
26 namespace panda::test {
27 class BuiltinsListFormatTest : 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/icudt67l.dat 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 EcmaHandleScope *scope {nullptr};
61 JSThread *thread {nullptr};
62 };
63
64 // new Intl.ListFormat(locales)
HWTEST_F_L0(BuiltinsListFormatTest,ListFormatConstructor)65 HWTEST_F_L0(BuiltinsListFormatTest, ListFormatConstructor)
66 {
67 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
68 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
69 JSHandle<JSFunction> newTarget(env->GetListFormatFunction());
70
71 JSHandle<JSTaggedValue> localesString(factory->NewFromASCII("en-GB"));
72 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*newTarget), 8);
73 ecmaRuntimeCallInfo->SetFunction(newTarget.GetTaggedValue());
74 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
75 ecmaRuntimeCallInfo->SetCallArg(0, localesString.GetTaggedValue());
76 // option tag is default value
77 ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue::Undefined());
78
79 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
80 JSTaggedValue result = BuiltinsListFormat::ListFormatConstructor(ecmaRuntimeCallInfo);
81 TestHelper::TearDownFrame(thread, prev);
82 EXPECT_TRUE(result.IsJSListFormat());
83 }
84
JSListFormatCreateWithOptionTest(JSThread * thread,JSHandle<JSTaggedValue> & locale,JSHandle<JSTaggedValue> & typeValue)85 static JSTaggedValue JSListFormatCreateWithOptionTest(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->GetListFormatFunction());
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 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*newTarget), 8);
98 ecmaRuntimeCallInfo->SetFunction(newTarget.GetTaggedValue());
99 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
100 ecmaRuntimeCallInfo->SetCallArg(0, locale.GetTaggedValue());
101 ecmaRuntimeCallInfo->SetCallArg(1, optionsObj.GetTaggedValue());
102
103 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
104 JSTaggedValue result = BuiltinsListFormat::ListFormatConstructor(ecmaRuntimeCallInfo);
105 TestHelper::TearDownFrame(thread, prev);
106
107 EXPECT_TRUE(result.IsJSListFormat());
108 return result;
109 }
110
111 // Format("Motorcycle" ,type(conjunction))
HWTEST_F_L0(BuiltinsListFormatTest,Format_001)112 HWTEST_F_L0(BuiltinsListFormatTest, Format_001)
113 {
114 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
115 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en-GB"));
116 JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("conjunction")); // the default value
117 JSHandle<JSListFormat> jSListFormat =
118 JSHandle<JSListFormat>(thread, JSListFormatCreateWithOptionTest(thread, locale, typeValue));
119
120 JSHandle<JSTaggedValue> listValue(factory->NewFromASCII("Motorcycle"));
121 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
122 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
123 ecmaRuntimeCallInfo->SetThis(jSListFormat.GetTaggedValue());
124 ecmaRuntimeCallInfo->SetCallArg(0, listValue.GetTaggedValue());
125
126 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
127 JSTaggedValue result = BuiltinsListFormat::Format(ecmaRuntimeCallInfo);
128 TestHelper::TearDownFrame(thread, prev);
129
130 JSHandle<EcmaString> handleEcmaStr(thread, result);
131 EXPECT_STREQ("M, o, t, o, r, c, y, c, l and e", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
132 }
133
134 // Format(["Motorcycle", "Bus", "Car" ], type(conjunction))
HWTEST_F_L0(BuiltinsListFormatTest,Format_002)135 HWTEST_F_L0(BuiltinsListFormatTest, Format_002)
136 {
137 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
138 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en-GB"));
139 JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("conjunction")); // the default value
140 JSHandle<JSListFormat> jSListFormat =
141 JSHandle<JSListFormat>(thread, JSListFormatCreateWithOptionTest(thread, locale, typeValue));
142 JSHandle<JSTaggedValue> listValue1(factory->NewFromStdString("Motorcycle"));
143 JSHandle<JSTaggedValue> listValue2(factory->NewFromStdString("Bus"));
144 JSHandle<JSTaggedValue> listValue3(factory->NewFromStdString("Car"));
145
146 JSArray *arr = JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetObject<JSArray>();
147 EXPECT_TRUE(arr != nullptr);
148 JSHandle<JSObject> value(thread, arr);
149 JSHandle<JSTaggedValue> key0(thread, JSTaggedValue(0));
150 PropertyDescriptor desc0(thread, listValue1, true, true, true);
151 JSArray::DefineOwnProperty(thread, value, key0, desc0);
152 JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(1));
153 PropertyDescriptor desc1(thread, listValue2, true, true, true);
154 JSArray::DefineOwnProperty(thread, value, key1, desc1);
155 JSHandle<JSTaggedValue> key2(thread, JSTaggedValue(2));
156 PropertyDescriptor desc2(thread, listValue3, true, true, true);
157 JSArray::DefineOwnProperty(thread, value, key2, desc2);
158
159 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
160 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
161 ecmaRuntimeCallInfo->SetThis(jSListFormat.GetTaggedValue());
162 ecmaRuntimeCallInfo->SetCallArg(0, value.GetTaggedValue());
163
164 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
165 JSTaggedValue result = BuiltinsListFormat::Format(ecmaRuntimeCallInfo);
166 TestHelper::TearDownFrame(thread, prev);
167
168 JSHandle<EcmaString> handleEcmaStr(thread, result);
169 EXPECT_STREQ("Motorcycle, Bus and Car", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
170 }
171
172 // Format(["Motorcycle", "Bus", "Car" ], type(disjunction))
HWTEST_F_L0(BuiltinsListFormatTest,Format_003)173 HWTEST_F_L0(BuiltinsListFormatTest, Format_003)
174 {
175 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
176 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en-GB"));
177 JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("disjunction")); // the default value
178 JSHandle<JSListFormat> jSListFormat =
179 JSHandle<JSListFormat>(thread, JSListFormatCreateWithOptionTest(thread, locale, typeValue));
180 JSHandle<JSTaggedValue> listValue1(factory->NewFromStdString("Motorcycle"));
181 JSHandle<JSTaggedValue> listValue2(factory->NewFromStdString("Bus"));
182 JSHandle<JSTaggedValue> listValue3(factory->NewFromStdString("Car"));
183
184 JSArray *arr = JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetObject<JSArray>();
185 EXPECT_TRUE(arr != nullptr);
186 JSHandle<JSObject> value(thread, arr);
187 JSHandle<JSTaggedValue> key0(thread, JSTaggedValue(0));
188 PropertyDescriptor desc0(thread, listValue1, true, true, true);
189 JSArray::DefineOwnProperty(thread, value, key0, desc0);
190 JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(1));
191 PropertyDescriptor desc1(thread, listValue2, true, true, true);
192 JSArray::DefineOwnProperty(thread, value, key1, desc1);
193 JSHandle<JSTaggedValue> key2(thread, JSTaggedValue(2));
194 PropertyDescriptor desc2(thread, listValue3, true, true, true);
195 JSArray::DefineOwnProperty(thread, value, key2, desc2);
196
197 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
198 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
199 ecmaRuntimeCallInfo->SetThis(jSListFormat.GetTaggedValue());
200 ecmaRuntimeCallInfo->SetCallArg(0, value.GetTaggedValue());
201
202 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
203 JSTaggedValue result = BuiltinsListFormat::Format(ecmaRuntimeCallInfo);
204 TestHelper::TearDownFrame(thread, prev);
205
206 JSHandle<EcmaString> handleEcmaStr(thread, result);
207 EXPECT_STREQ("Motorcycle, Bus or Car", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
208 }
209
210 // Format(["中文英文" ], type(disjunction))
HWTEST_F_L0(BuiltinsListFormatTest,Format_004)211 HWTEST_F_L0(BuiltinsListFormatTest, Format_004)
212 {
213 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
214 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("zh-cn"));
215 JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("disjunction")); // the default value
216 JSHandle<JSListFormat> jSListFormat =
217 JSHandle<JSListFormat>(thread, JSListFormatCreateWithOptionTest(thread, locale, typeValue));
218 JSHandle<JSTaggedValue> listValue1(factory->NewFromStdString("中文英文"));
219
220 JSArray *arr = JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetObject<JSArray>();
221 EXPECT_TRUE(arr != nullptr);
222 JSHandle<JSObject> value(thread, arr);
223 JSHandle<JSTaggedValue> key0(thread, JSTaggedValue(0));
224 PropertyDescriptor desc0(thread, listValue1, true, true, true);
225 JSArray::DefineOwnProperty(thread, value, key0, desc0);
226
227 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
228 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
229 ecmaRuntimeCallInfo->SetThis(jSListFormat.GetTaggedValue());
230 ecmaRuntimeCallInfo->SetCallArg(0, value.GetTaggedValue());
231
232 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
233 JSTaggedValue result = BuiltinsListFormat::Format(ecmaRuntimeCallInfo);
234 TestHelper::TearDownFrame(thread, prev);
235
236 JSHandle<EcmaString> handleEcmaStr(thread, result);
237 EXPECT_STREQ("中文英文", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
238 }
239
240 // Format(["中文", "英文", "韩文" ], type(conjunction))
HWTEST_F_L0(BuiltinsListFormatTest,Format_005)241 HWTEST_F_L0(BuiltinsListFormatTest, Format_005)
242 {
243 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
244 JSHandle<JSTaggedValue> locale(factory->NewFromASCII("zh-cn"));
245 JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("conjunction")); // the default value
246 JSHandle<JSListFormat> jSListFormat =
247 JSHandle<JSListFormat>(thread, JSListFormatCreateWithOptionTest(thread, locale, typeValue));
248 JSHandle<JSTaggedValue> listValue1(factory->NewFromStdString("中文"));
249 JSHandle<JSTaggedValue> listValue2(factory->NewFromStdString("英文"));
250 JSHandle<JSTaggedValue> listValue3(factory->NewFromStdString("韩文"));
251
252 JSArray *arr = JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetObject<JSArray>();
253 EXPECT_TRUE(arr != nullptr);
254 JSHandle<JSObject> value(thread, arr);
255 JSHandle<JSTaggedValue> key0(thread, JSTaggedValue(0));
256 PropertyDescriptor desc0(thread, listValue1, true, true, true);
257 JSArray::DefineOwnProperty(thread, value, key0, desc0);
258 JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(1));
259 PropertyDescriptor desc1(thread, listValue2, true, true, true);
260 JSArray::DefineOwnProperty(thread, value, key1, desc1);
261 JSHandle<JSTaggedValue> key2(thread, JSTaggedValue(2));
262 PropertyDescriptor desc2(thread, listValue3, true, true, true);
263 JSArray::DefineOwnProperty(thread, value, key2, desc2);
264
265 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
266 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
267 ecmaRuntimeCallInfo->SetThis(jSListFormat.GetTaggedValue());
268 ecmaRuntimeCallInfo->SetCallArg(0, value.GetTaggedValue());
269
270 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
271 JSTaggedValue result = BuiltinsListFormat::Format(ecmaRuntimeCallInfo);
272 TestHelper::TearDownFrame(thread, prev);
273
274 JSHandle<EcmaString> handleEcmaStr(thread, result);
275 EXPECT_STREQ("中文、英文和韩文", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
276 }
277 } // namespace panda::test
278