• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
JSListFormatCreateWithOptionTest(JSThread * thread,JSHandle<JSTaggedValue> & locale,JSHandle<JSTaggedValue> & typeValue)64 static JSTaggedValue JSListFormatCreateWithOptionTest(JSThread *thread, JSHandle<JSTaggedValue> &locale,
65                                                       JSHandle<JSTaggedValue> &typeValue)
66 {
67     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
68     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
69     JSHandle<JSFunction> newTarget(env->GetListFormatFunction());
70     JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
71     JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
72 
73     JSHandle<JSTaggedValue> typeKey = thread->GlobalConstants()->GetHandledTypeString();
74     JSObject::SetProperty(thread, optionsObj, typeKey, typeValue);
75 
76     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*newTarget), 8);
77     ecmaRuntimeCallInfo->SetFunction(newTarget.GetTaggedValue());
78     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
79     ecmaRuntimeCallInfo->SetCallArg(0, locale.GetTaggedValue());
80     ecmaRuntimeCallInfo->SetCallArg(1, optionsObj.GetTaggedValue());
81 
82     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
83     JSTaggedValue result = BuiltinsListFormat::ListFormatConstructor(ecmaRuntimeCallInfo);
84     TestHelper::TearDownFrame(thread, prev);
85 
86     EXPECT_TRUE(result.IsJSListFormat());
87     return result;
88 }
89 
HWTEST_F_L0(BuiltinsListFormatTest,FormatToParts_001)90 HWTEST_F_L0(BuiltinsListFormatTest, FormatToParts_001)
91 {
92     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
93     JSHandle<JSTaggedValue> locale(factory->NewFromASCII("de-DE"));
94     JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("conjunction"));
95     JSHandle<JSListFormat> jSListFormat =
96         JSHandle<JSListFormat>(thread, JSListFormatCreateWithOptionTest(thread, locale, typeValue));
97     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
98     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
99     ecmaRuntimeCallInfo->SetThis(jSListFormat.GetTaggedValue());
100     ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue::Undefined());
101 
102     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
103     JSTaggedValue result = BuiltinsListFormat::FormatToParts(ecmaRuntimeCallInfo);
104     TestHelper::TearDownFrame(thread, prev);
105 
106     JSHandle<JSArray> resultHandle(thread, result);
107     JSHandle<TaggedArray> elements(thread, resultHandle->GetElements());
108     EXPECT_EQ(elements->GetLength(), 0U); // zero formatters
109 }
110 
111 // FormatToParts(["Apple", "Orange", "Pineapple" ], type(conjunction))
HWTEST_F_L0(BuiltinsListFormatTest,FormatToParts_002)112 HWTEST_F_L0(BuiltinsListFormatTest, FormatToParts_002)
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     JSHandle<JSTaggedValue> listValue1(factory->NewFromStdString("Apple"));
120     JSHandle<JSTaggedValue> listValue2(factory->NewFromStdString("Orange"));
121     JSHandle<JSTaggedValue> listValue3(factory->NewFromStdString("Pineapple"));
122 
123     JSArray *arr = JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetObject<JSArray>();
124     EXPECT_TRUE(arr != nullptr);
125     JSHandle<JSObject> value(thread, arr);
126     JSHandle<JSTaggedValue> key0(thread, JSTaggedValue(0));
127     PropertyDescriptor desc0(thread, listValue1, true, true, true);
128     JSArray::DefineOwnProperty(thread, value, key0, desc0);
129     JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(1));
130     PropertyDescriptor desc1(thread, listValue2, true, true, true);
131     JSArray::DefineOwnProperty(thread, value, key1, desc1);
132     JSHandle<JSTaggedValue> key2(thread, JSTaggedValue(2));
133     PropertyDescriptor desc2(thread, listValue3, true, true, true);
134     JSArray::DefineOwnProperty(thread, value, key2, desc2);
135 
136     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
137     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
138     ecmaRuntimeCallInfo->SetThis(jSListFormat.GetTaggedValue());
139     ecmaRuntimeCallInfo->SetCallArg(0, value.GetTaggedValue());
140 
141     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
142     JSTaggedValue result = BuiltinsListFormat::FormatToParts(ecmaRuntimeCallInfo);
143     TestHelper::TearDownFrame(thread, prev);
144 
145     JSHandle<JSArray> resultHandle(thread, result);
146     JSHandle<TaggedArray> elements(thread, resultHandle->GetElements());
147     EXPECT_EQ(elements->GetLength(), 6U);
148 }
149 
HWTEST_F_L0(BuiltinsListFormatTest,FormatToParts_003)150 HWTEST_F_L0(BuiltinsListFormatTest, FormatToParts_003)
151 {
152     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
153     JSHandle<JSTaggedValue> lengthKey = thread->GlobalConstants()->GetHandledLengthString();
154     JSHandle<JSTaggedValue> locale(factory->NewFromASCII("en-GB"));
155     JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("conjunction")); // the default value
156     JSHandle<JSListFormat> jSListFormat =
157         JSHandle<JSListFormat>(thread, JSListFormatCreateWithOptionTest(thread, locale, typeValue));
158     JSHandle<JSTaggedValue> listValue1(factory->NewFromStdString("Apple"));
159     JSHandle<JSTaggedValue> listValue2(factory->NewFromStdString("Orange"));
160     JSHandle<JSTaggedValue> listValue3(factory->NewFromStdString("Pineapple"));
161 
162     JSArray *arr = JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetObject<JSArray>();
163     EXPECT_TRUE(arr != nullptr);
164     JSHandle<JSObject> value(thread, arr);
165     JSHandle<JSTaggedValue> key0(thread, JSTaggedValue(0));
166     PropertyDescriptor desc0(thread, listValue1, true, true, true);
167     JSArray::DefineOwnProperty(thread, value, key0, desc0);
168     JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(1));
169     PropertyDescriptor desc1(thread, listValue2, true, true, true);
170     JSArray::DefineOwnProperty(thread, value, key1, desc1);
171     JSHandle<JSTaggedValue> key2(thread, JSTaggedValue(2));
172     PropertyDescriptor desc2(thread, listValue3, true, true, true);
173     JSArray::DefineOwnProperty(thread, value, key2, desc2);
174 
175     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
176     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
177     ecmaRuntimeCallInfo->SetThis(jSListFormat.GetTaggedValue());
178     ecmaRuntimeCallInfo->SetCallArg(0, value.GetTaggedValue());
179 
180     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
181     JSTaggedValue result = BuiltinsListFormat::FormatToParts(ecmaRuntimeCallInfo);
182     TestHelper::TearDownFrame(thread, prev);
183     JSTaggedValue valueList(static_cast<JSTaggedType>(result.GetRawData()));
184 
185     ASSERT_TRUE(valueList.IsECMAObject());
186     JSHandle<JSObject> valueHandle(thread, valueList);
187     EXPECT_EQ(JSArray::GetProperty(thread, JSHandle<JSTaggedValue>(valueHandle), lengthKey).GetValue()->GetInt(), 5);
188 }
189 
190 // FormatToParts(["中文", "英文"], type(conjunction))
HWTEST_F_L0(BuiltinsListFormatTest,FormatToParts_004)191 HWTEST_F_L0(BuiltinsListFormatTest, FormatToParts_004)
192 {
193     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
194     JSHandle<JSTaggedValue> locale(factory->NewFromASCII("zh-cn"));
195     JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("conjunction"));
196     JSHandle<JSListFormat> jSListFormat =
197         JSHandle<JSListFormat>(thread, JSListFormatCreateWithOptionTest(thread, locale, typeValue));
198     JSHandle<JSTaggedValue> listValue1(factory->NewFromStdString("中文"));
199     JSHandle<JSTaggedValue> listValue2(factory->NewFromStdString("英文"));
200 
201     JSArray *arr = JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetObject<JSArray>();
202     EXPECT_TRUE(arr != nullptr);
203     JSHandle<JSObject> value(thread, arr);
204     JSHandle<JSTaggedValue> key0(thread, JSTaggedValue(0));
205     PropertyDescriptor desc0(thread, listValue1, true, true, true);
206     JSArray::DefineOwnProperty(thread, value, key0, desc0);
207     JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(1));
208     PropertyDescriptor desc1(thread, listValue2, true, true, true);
209     JSArray::DefineOwnProperty(thread, value, key1, desc1);
210 
211     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
212     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
213     ecmaRuntimeCallInfo->SetThis(jSListFormat.GetTaggedValue());
214     ecmaRuntimeCallInfo->SetCallArg(0, value.GetTaggedValue());
215 
216     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
217     JSTaggedValue result = BuiltinsListFormat::FormatToParts(ecmaRuntimeCallInfo);
218     TestHelper::TearDownFrame(thread, prev);
219 
220     JSHandle<JSArray> resultHandle(thread, result);
221     JSHandle<TaggedArray> elements(thread, resultHandle->GetElements());
222     EXPECT_EQ(elements->GetLength(), 3U);
223 }
224 
225 // FormatToParts(["中文", "英文","韩文","葡萄牙语"], type(disjunction))
HWTEST_F_L0(BuiltinsListFormatTest,FormatToParts_005)226 HWTEST_F_L0(BuiltinsListFormatTest, FormatToParts_005)
227 {
228     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
229     JSHandle<JSTaggedValue> lengthKey = thread->GlobalConstants()->GetHandledLengthString();
230     JSHandle<JSTaggedValue> locale(factory->NewFromASCII("zh-cn"));
231     JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("disjunction"));
232     JSHandle<JSListFormat> jSListFormat =
233         JSHandle<JSListFormat>(thread, JSListFormatCreateWithOptionTest(thread, locale, typeValue));
234     JSHandle<JSTaggedValue> listValue1(factory->NewFromStdString("中文"));
235     JSHandle<JSTaggedValue> listValue2(factory->NewFromStdString("英文"));
236     JSHandle<JSTaggedValue> listValue3(factory->NewFromStdString("韩文"));
237     JSHandle<JSTaggedValue> listValue4(factory->NewFromStdString("葡萄牙语"));
238 
239     JSArray *arr = JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetObject<JSArray>();
240     EXPECT_TRUE(arr != nullptr);
241     JSHandle<JSObject> value(thread, arr);
242     JSHandle<JSTaggedValue> key0(thread, JSTaggedValue(0));
243     PropertyDescriptor desc0(thread, listValue1, true, true, true);
244     JSArray::DefineOwnProperty(thread, value, key0, desc0);
245     JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(1));
246     PropertyDescriptor desc1(thread, listValue2, true, true, true);
247     JSArray::DefineOwnProperty(thread, value, key1, desc1);
248     JSHandle<JSTaggedValue> key2(thread, JSTaggedValue(2));
249     PropertyDescriptor desc2(thread, listValue3, true, true, true);
250     JSArray::DefineOwnProperty(thread, value, key2, desc2);
251     JSHandle<JSTaggedValue> key3(thread, JSTaggedValue(3));
252     PropertyDescriptor desc3(thread, listValue4, true, true, true);
253     JSArray::DefineOwnProperty(thread, value, key3, desc3);
254 
255     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
256     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
257     ecmaRuntimeCallInfo->SetThis(jSListFormat.GetTaggedValue());
258     ecmaRuntimeCallInfo->SetCallArg(0, value.GetTaggedValue());
259 
260     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
261     JSTaggedValue result = BuiltinsListFormat::FormatToParts(ecmaRuntimeCallInfo);
262     TestHelper::TearDownFrame(thread, prev);
263     JSTaggedValue valueList(static_cast<JSTaggedType>(result.GetRawData()));
264 
265     ASSERT_TRUE(valueList.IsECMAObject());
266     JSHandle<JSObject> valueHandle(thread, valueList);
267     EXPECT_EQ(JSArray::GetProperty(thread, JSHandle<JSTaggedValue>(valueHandle), lengthKey).GetValue()->GetInt(), 7);
268 }
269 
270 // SupportedLocalesOf("best fit")
HWTEST_F_L0(BuiltinsListFormatTest,SupportedLocalesOf_001)271 HWTEST_F_L0(BuiltinsListFormatTest, SupportedLocalesOf_001)
272 {
273     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
274     JSHandle<JSTaggedValue> locale(factory->NewFromASCII("id-u-co-pinyin-de-ID"));
275 
276     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
277     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
278     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
279     ecmaRuntimeCallInfo->SetCallArg(0, locale.GetTaggedValue());
280     // set the tag is default value
281     ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue::Undefined());
282 
283     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
284     JSTaggedValue resultArr = BuiltinsListFormat::SupportedLocalesOf(ecmaRuntimeCallInfo);
285     TestHelper::TearDownFrame(thread, prev);
286 
287     JSHandle<JSArray> resultHandle(thread, resultArr);
288     JSHandle<TaggedArray> elements(thread, resultHandle->GetElements());
289     EXPECT_EQ(elements->GetLength(), 1U);
290     JSHandle<EcmaString> handleEcmaStr(thread, elements->Get(0));
291     EXPECT_STREQ("id-u-co-pinyin-de-id", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
292 }
293 
294 // SupportedLocalesOf("look up")
HWTEST_F_L0(BuiltinsListFormatTest,SupportedLocalesOf_002)295 HWTEST_F_L0(BuiltinsListFormatTest, SupportedLocalesOf_002)
296 {
297     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
298     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
299 
300     JSHandle<JSTaggedValue> localeMatcherKey = thread->GlobalConstants()->GetHandledLocaleMatcherString();
301     JSHandle<JSTaggedValue> localeMatcherValue(factory->NewFromASCII("lookup"));
302     JSHandle<JSTaggedValue> locale(factory->NewFromASCII("id-u-co-pinyin-de-DE"));
303 
304     JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
305     JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
306     JSObject::SetProperty(thread, optionsObj, localeMatcherKey, localeMatcherValue);
307 
308     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
309     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
310     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
311     ecmaRuntimeCallInfo->SetCallArg(0, locale.GetTaggedValue());
312     ecmaRuntimeCallInfo->SetCallArg(1, optionsObj.GetTaggedValue());
313 
314     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
315     JSTaggedValue resultArr = BuiltinsListFormat::SupportedLocalesOf(ecmaRuntimeCallInfo);
316     TestHelper::TearDownFrame(thread, prev);
317 
318     JSHandle<JSArray> resultHandle(thread, resultArr);
319     JSHandle<TaggedArray> elements(thread, resultHandle->GetElements());
320     EXPECT_EQ(elements->GetLength(), 1U);
321 
322     JSHandle<EcmaString> resultStr(thread, elements->Get(0));
323     EXPECT_STREQ("id-u-co-pinyin-de", EcmaStringAccessor(resultStr).ToCString().c_str());
324 }
325 
HWTEST_F_L0(BuiltinsListFormatTest,ResolvedOptions)326 HWTEST_F_L0(BuiltinsListFormatTest, ResolvedOptions)
327 {
328     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
329     auto globalConst = thread->GlobalConstants();
330     JSHandle<JSTaggedValue> locale(factory->NewFromASCII("de-DE"));
331     JSHandle<JSTaggedValue> typeValue(factory->NewFromASCII("disjunction"));
332     JSHandle<JSListFormat> jSListFormat =
333         JSHandle<JSListFormat>(thread, JSListFormatCreateWithOptionTest(thread, locale, typeValue));
334 
335     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
336     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
337     ecmaRuntimeCallInfo->SetThis(jSListFormat.GetTaggedValue());
338 
339     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
340     JSTaggedValue result = BuiltinsListFormat::ResolvedOptions(ecmaRuntimeCallInfo);
341     TestHelper::TearDownFrame(thread, prev);
342 
343     JSHandle<JSTaggedValue> resultObj =
344         JSHandle<JSTaggedValue>(thread, JSTaggedValue(static_cast<JSTaggedType>(result.GetRawData())));
345     // judge whether the properties of the object are the same as those of jslistformat tag
346     JSHandle<JSTaggedValue> localeKey = globalConst->GetHandledLocaleString();
347     JSHandle<JSTaggedValue> localeValue(factory->NewFromASCII("de-DE"));
348     EXPECT_EQ(JSTaggedValue::SameValue(
349         JSObject::GetProperty(thread, resultObj, localeKey).GetValue(), localeValue), true);
350     JSHandle<JSTaggedValue> typeKey = globalConst->GetHandledTypeString();
351     EXPECT_EQ(JSTaggedValue::SameValue(
352         JSObject::GetProperty(thread, resultObj, typeKey).GetValue(), typeValue), true);
353 }
354 } // namespace panda::test