• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 #ifndef ECMA_TEST_COMMON_H
16 #define ECMA_TEST_COMMON_H
17 #include <functional>
18 #include "ecmascript/containers/containers_private.h"
19 #include "ecmascript/ecma_string-inl.h"
20 #include "ecmascript/global_env.h"
21 #include "ecmascript/js_date_time_format.h"
22 #include "ecmascript/js_tagged_value.h"
23 #include "ecmascript/object_factory.h"
24 #include "ecmascript/tagged_tree.h"
25 #include "ecmascript/tests/ecma_container_common.h"
26 #include "ecmascript/tests/test_common.h"
27 
28 namespace panda::test {
29 
30 using namespace panda;
31 using namespace panda::ecmascript;
32 using ecmascript::base::BuiltinsBase;
33 
34 constexpr uint32_t g_numberFive = 5;
35 constexpr uint32_t g_numberNine = 9;
36 constexpr uint32_t g_nintyNine = 99;
37 constexpr uint32_t g_hundred = 100;
38 constexpr uint32_t g_hundredAndOne = 101;
39 static uint8_t g_arrayFrontU8[] = {"abcdef"};
40 static uint32_t g_lenFrontU8 = sizeof(g_arrayFrontU8) - 1;
41 
42 class EcmaTestCommon {
43 public:
44     using CreateStringFunc =
45         std::function<EcmaString *(const EcmaVM *vm, const uint8_t *utf8Data, size_t length, bool canBeCompress)>;
46     using CreateStringUtf16Func =
47         std::function<EcmaString *(const EcmaVM *vm, const uint16_t *utf8Data, size_t length, bool canBeCompress)>;
48     using StringAreEqualUtf16Func =
49         std::function<bool(JSThread*, const EcmaString *str1, const uint16_t *utf16Data, uint32_t utf16Len)>;
50     using StringIsEqualUint8Func =
51         std::function<bool(JSThread*, const EcmaString *str1, const uint8_t *dataAddr,
52                            uint32_t dataLen, bool canBeCompress)>;
53     using Compare =
54         std::function<int32_t(const EcmaVM *vm, const JSHandle<EcmaString> &left, const JSHandle<EcmaString> &right)>;
55 
ConcatCommonCase2(JSThread * thread,const EcmaVM * instance)56     static void ConcatCommonCase2(JSThread *thread, const EcmaVM *instance)
57     {
58         uint16_t arrayBackU16NotComp[] = {88, 768, 1, 270, 345, 333};
59         uint32_t lengthEcmaStrBackU16NotComp = sizeof(arrayBackU16NotComp) / sizeof(arrayBackU16NotComp[0]);
60 
61         EcmaString *ecmaFrontU8 = EcmaStringAccessor::CreateFromUtf8(instance, &g_arrayFrontU8[0], g_lenFrontU8, true);
62         JSHandle<EcmaString> handleEcmaStrFrontU8(thread, ecmaFrontU8);
63         JSHandle<EcmaString> handleEcmaStrBackU16NotComp(
64             thread,
65             EcmaStringAccessor::CreateFromUtf16(instance, &arrayBackU16NotComp[0], lengthEcmaStrBackU16NotComp, false));
66         JSHandle<EcmaString> handleEcmaStrConcatU8U16NotComp(
67             thread, EcmaStringAccessor::Concat(instance, handleEcmaStrFrontU8, handleEcmaStrBackU16NotComp));
68         EXPECT_TRUE(EcmaStringAccessor(handleEcmaStrConcatU8U16NotComp).IsUtf16());
69         for (uint32_t i = 0; i < g_lenFrontU8; i++) {
70             EXPECT_EQ(EcmaStringAccessor(handleEcmaStrConcatU8U16NotComp).Get(thread, i), g_arrayFrontU8[i]);
71         }
72         for (uint32_t i = 0; i < lengthEcmaStrBackU16NotComp; i++) {
73             EXPECT_EQ(EcmaStringAccessor(handleEcmaStrConcatU8U16NotComp).Get(thread, i + g_lenFrontU8),
74                       arrayBackU16NotComp[i]);
75         }
76         EXPECT_EQ(EcmaStringAccessor(handleEcmaStrConcatU8U16NotComp).GetLength(),
77                   g_lenFrontU8 + lengthEcmaStrBackU16NotComp);
78     }
79 
FastSubStringCommonCase(JSThread * thread,const EcmaVM * instance,std::vector<uint8_t> & data,CreateStringFunc createStringFunc)80     static void FastSubStringCommonCase(JSThread *thread, const EcmaVM *instance, std::vector<uint8_t> &data,
81                                         CreateStringFunc createStringFunc)
82     {
83         EcmaString *frontEcmaStr = createStringFunc(instance, data.data(), data.size(), true);
84         JSHandle<EcmaString> handleEcmaStrU8(thread, frontEcmaStr);
85         uint32_t indexStartSubU8 = 2;  // 2: sub index
86         uint32_t lengthSubU8 = 2;      // 2: length
87         JSHandle<EcmaString> handleEcmaStrSubU8(
88             thread, EcmaStringAccessor::FastSubString(instance, handleEcmaStrU8, indexStartSubU8, lengthSubU8));
89         for (uint32_t i = 0; i < lengthSubU8; i++) {
90             EXPECT_EQ(EcmaStringAccessor(handleEcmaStrSubU8).Get(thread, i),
91                       EcmaStringAccessor(handleEcmaStrU8).Get(thread, i + indexStartSubU8));
92         }
93         EXPECT_EQ(EcmaStringAccessor(handleEcmaStrSubU8).GetLength(), lengthSubU8);
94     }
95 
IndexOfCommonCase(JSThread * thread,const EcmaVM * instance,std::vector<uint16_t> & dataU16,std::vector<uint8_t> & dataU8,CreateStringFunc createStringFunc)96     static void IndexOfCommonCase(JSThread *thread, const EcmaVM *instance, std::vector<uint16_t> &dataU16,
97                                   std::vector<uint8_t> &dataU8, CreateStringFunc createStringFunc)
98     {
99         JSHandle<EcmaString> ecmaU16(
100             thread, EcmaStringAccessor::CreateFromUtf16(instance, dataU16.data(), dataU16.size(), true));
101 
102         EcmaString *ecmaStr = createStringFunc(instance, dataU8.data(), dataU8.size(), true);
103         JSHandle<EcmaString> ecmaU8(thread, ecmaStr);
104 
105         int32_t posStart = 0;
106         EXPECT_EQ(EcmaStringAccessor::IndexOf(instance, ecmaU8, ecmaU16, posStart), 3);  // 3: value
107         EXPECT_EQ(EcmaStringAccessor::IndexOf(instance, ecmaU16, ecmaU8, posStart), -1);
108         posStart = -1;
109         EXPECT_EQ(EcmaStringAccessor::IndexOf(instance, ecmaU8, ecmaU16, posStart), 3);  // 3: value
110         posStart = 1;
111         EXPECT_EQ(EcmaStringAccessor::IndexOf(instance, ecmaU8, ecmaU16, posStart), 3);  // 3: value
112         posStart = 3;                                                                    // 3: pos start
113         EXPECT_EQ(EcmaStringAccessor::IndexOf(instance, ecmaU8, ecmaU16, posStart), 3);  // 3: value
114         posStart = 4;                                                                    // 4: pos start
115         EXPECT_EQ(EcmaStringAccessor::IndexOf(instance, ecmaU8, ecmaU16, posStart), -1);
116     }
117 
StringIsEqualCommonCase(JSThread * thread,const EcmaVM * instance,StringIsEqualUint8Func stringIsEqualFunc)118     static void StringIsEqualCommonCase(JSThread *thread, const EcmaVM *instance,
119                                         StringIsEqualUint8Func stringIsEqualFunc)
120     {
121         uint8_t arrayU8No1[4] = {45, 92, 78};
122         uint16_t arrayU16NotCompNo1[] = {45, 92, 78};
123         uint16_t arrayU16NotCompNo2[] = {45, 92, 78, 24};
124         uint16_t arrayU16NotCompNo3[] = {45, 92};
125         uint16_t arrayU16NotCompNo4[] = {25645, 25692, 25678};
126         uint32_t lengthEcmaStrU8No1 = sizeof(arrayU8No1) - 1;
127         uint32_t lengthEcmaStrU16NotCompNo1 = sizeof(arrayU16NotCompNo1) / sizeof(arrayU16NotCompNo1[0]);
128         uint32_t lengthEcmaStrU16NotCompNo2 = sizeof(arrayU16NotCompNo2) / sizeof(arrayU16NotCompNo2[0]);
129         uint32_t lengthEcmaStrU16NotCompNo3 = sizeof(arrayU16NotCompNo3) / sizeof(arrayU16NotCompNo3[0]);
130         uint32_t lengthEcmaStrU16NotCompNo4 = sizeof(arrayU16NotCompNo4) / sizeof(arrayU16NotCompNo4[0]);
131         JSHandle<EcmaString> handleEcmaStrU16NotCompNo1(
132             thread,
133             EcmaStringAccessor::CreateFromUtf16(instance, &arrayU16NotCompNo1[0], lengthEcmaStrU16NotCompNo1, true));
134         JSHandle<EcmaString> handleEcmaStrU16NotCompNo2(
135             thread,
136             EcmaStringAccessor::CreateFromUtf16(instance, &arrayU16NotCompNo2[0], lengthEcmaStrU16NotCompNo2, true));
137         JSHandle<EcmaString> handleEcmaStrU16NotCompNo3(
138             thread,
139             EcmaStringAccessor::CreateFromUtf16(instance, &arrayU16NotCompNo3[0], lengthEcmaStrU16NotCompNo3, true));
140         JSHandle<EcmaString> handleEcmaStrU16NotCompNo4(
141             thread,
142             EcmaStringAccessor::CreateFromUtf16(instance, &arrayU16NotCompNo4[0], lengthEcmaStrU16NotCompNo4, false));
143         EXPECT_FALSE(stringIsEqualFunc(thread, *handleEcmaStrU16NotCompNo1, &arrayU8No1[0], lengthEcmaStrU8No1, false));
144         EXPECT_TRUE(stringIsEqualFunc(thread, *handleEcmaStrU16NotCompNo1, &arrayU8No1[0], lengthEcmaStrU8No1, true));
145         EXPECT_FALSE(stringIsEqualFunc(thread, *handleEcmaStrU16NotCompNo2, &arrayU8No1[0], lengthEcmaStrU8No1, false));
146         EXPECT_FALSE(stringIsEqualFunc(thread, *handleEcmaStrU16NotCompNo3, &arrayU8No1[0], lengthEcmaStrU8No1, false));
147         EXPECT_FALSE(stringIsEqualFunc(thread, *handleEcmaStrU16NotCompNo4, &arrayU8No1[0], lengthEcmaStrU8No1, false));
148     }
149 
TryLowerCommonCase(JSThread * thread,const EcmaVM * instance,JSHandle<EcmaString> & lowerStr,std::vector<JSHandle<EcmaString>> caseStrings)150     static void TryLowerCommonCase(JSThread *thread, const EcmaVM *instance, JSHandle<EcmaString> &lowerStr,
151                                    std::vector<JSHandle<EcmaString>> caseStrings)
152     {
153         {
154             JSHandle<EcmaString> lowerEcmaString(thread, EcmaStringAccessor::TryToLower(instance, lowerStr));
155             EXPECT_TRUE(JSTaggedValue::SameValue(thread, lowerStr.GetTaggedValue(), lowerEcmaString.GetTaggedValue()));
156             EXPECT_EQ(EcmaStringAccessor(lowerStr).GetLength(), EcmaStringAccessor(lowerEcmaString).GetLength());
157             EXPECT_TRUE(EcmaStringAccessor(lowerEcmaString).IsUtf8());
158             EXPECT_FALSE(EcmaStringAccessor(lowerEcmaString).IsUtf16());
159         }
160 
161         for (size_t i = 0; i < caseStrings.size(); i++) {
162             JSHandle<EcmaString> lowerEcmaString(thread, EcmaStringAccessor::TryToLower(instance, caseStrings[i]));
163             EXPECT_TRUE(JSTaggedValue::SameValue(thread, lowerStr.GetTaggedValue(), lowerEcmaString.GetTaggedValue()));
164             EXPECT_EQ(EcmaStringAccessor(lowerStr).GetLength(), EcmaStringAccessor(lowerEcmaString).GetLength());
165             EXPECT_TRUE(EcmaStringAccessor(lowerEcmaString).IsUtf8());
166             EXPECT_FALSE(EcmaStringAccessor(lowerEcmaString).IsUtf16());
167         }
168     }
169 
CompareCommonCase(JSThread * thread,const EcmaVM * instance,CreateStringFunc createUtf8,CreateStringUtf16Func createUtf16,Compare compare)170     static void CompareCommonCase(JSThread *thread, const EcmaVM *instance, CreateStringFunc createUtf8,
171                                   CreateStringUtf16Func createUtf16, Compare compare)
172     {
173         // Compare(). EcmaString made by CreateFromUtf8() and EcmaString made by CreateFromUtf16( , , , true).
174         uint8_t arrayU8No1[3] = {1, 23};
175         uint8_t arrayU8No2[4] = {1, 23, 49};
176         uint16_t arrayU16CompNo1[] = {1, 23};
177         uint16_t arrayU16CompNo2[] = {1, 23, 49};
178         uint16_t arrayU16CompNo3[] = {1, 23, 45, 97, 127};
179         uint32_t lengthEcmaStrU8No1 = sizeof(arrayU8No1) - 1;
180         uint32_t lengthEcmaStrU8No2 = sizeof(arrayU8No2) - 1;
181         uint32_t lengthEcmaStrU16CompNo1 = sizeof(arrayU16CompNo1) / sizeof(arrayU16CompNo1[0]);
182         uint32_t lengthEcmaStrU16CompNo2 = sizeof(arrayU16CompNo2) / sizeof(arrayU16CompNo2[0]);
183         uint32_t lengthEcmaStrU16CompNo3 = sizeof(arrayU16CompNo3) / sizeof(arrayU16CompNo3[0]);
184         JSHandle<EcmaString> handleEcmaStrU8No1(thread, createUtf8(instance, &arrayU8No1[0], lengthEcmaStrU8No1, true));
185         JSHandle<EcmaString> handleEcmaStrU8No2(thread, createUtf8(instance, &arrayU8No2[0], lengthEcmaStrU8No2, true));
186         JSHandle<EcmaString> handleEcmaStrU16CompNo1(
187             thread, createUtf16(instance, &arrayU16CompNo1[0], lengthEcmaStrU16CompNo1, true));
188         JSHandle<EcmaString> handleEcmaStrU16CompNo2(
189             thread, createUtf16(instance, &arrayU16CompNo2[0], lengthEcmaStrU16CompNo2, true));
190         JSHandle<EcmaString> handleEcmaStrU16CompNo3(
191             thread, createUtf16(instance, &arrayU16CompNo3[0], lengthEcmaStrU16CompNo3, true));
192         EXPECT_EQ(compare(instance, handleEcmaStrU8No1, handleEcmaStrU16CompNo1), 0);
193         EXPECT_EQ(compare(instance, handleEcmaStrU16CompNo1, handleEcmaStrU8No1), 0);
194         EXPECT_EQ(compare(instance, handleEcmaStrU8No1, handleEcmaStrU16CompNo2), -1);
195         EXPECT_EQ(compare(instance, handleEcmaStrU16CompNo2, handleEcmaStrU8No1), 1);
196         EXPECT_EQ(compare(instance, handleEcmaStrU8No2, handleEcmaStrU16CompNo3), 49 - 45);  // 49: value, 45: value
197         EXPECT_EQ(compare(instance, handleEcmaStrU16CompNo3, handleEcmaStrU8No2), 45 - 49);  // 49: value, 45: value
198     }
199 
200     static void GcCommonCase(JSThread *thread, Heap *heap, bool nonMovable = true)
201     {
202         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
203         size_t oldNativeSize = heap->GetNativeBindingSize();
204         size_t newNativeSize = heap->GetNativeBindingSize();
205         constexpr int32_t nums = 1024;
206         {
207             [[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
208             auto newData = thread->GetEcmaVM()->GetNativeAreaAllocator()->AllocateBuffer(1 * nums * nums);
209             [[maybe_unused]] JSHandle<JSNativePointer> obj = factory->NewJSNativePointer(
210                 newData, NativeAreaAllocator::FreeBufferFunc, nullptr, nonMovable, 1 * nums * nums);
211             newNativeSize = heap->GetNativeBindingSize();
212             EXPECT_EQ(newNativeSize - oldNativeSize, 1UL * nums * nums);
213             auto newData1 = thread->GetEcmaVM()->GetNativeAreaAllocator()->AllocateBuffer(1 * nums * nums);
214             [[maybe_unused]] JSHandle<JSNativePointer> obj2 = factory->NewJSNativePointer(
215                 newData1, NativeAreaAllocator::FreeBufferFunc, nullptr, false, 1 * nums * nums);
216 
217             EXPECT_TRUE(newNativeSize - oldNativeSize > 0);
218             EXPECT_TRUE(newNativeSize - oldNativeSize <= 2 * nums * nums);  // 2: value
219             for (int i = 0; i < 2048; i++) {                                // 2048: loop count
220                 [[maybe_unused]] ecmascript::EcmaHandleScope baseScopeForeach(thread);
221                 auto newData2 = thread->GetEcmaVM()->GetNativeAreaAllocator()->AllocateBuffer(1 * nums);
222                 // malloc size is smaller to avoid test fail in the small devices.
223                 [[maybe_unused]] JSHandle<JSNativePointer> obj3 = factory->NewJSNativePointer(
224                     newData2, NativeAreaAllocator::FreeBufferFunc, nullptr, true, 1 * nums * nums);
225             }
226             newNativeSize = heap->GetNativeBindingSize();
227             // Old GC should be trigger here, so the size should be reduced.
228             EXPECT_TRUE(newNativeSize - oldNativeSize < 2048 * nums * nums);  // 2048: value
229         }
230     }
231 
GcCommonCase(JSThread * thread)232     static size_t GcCommonCase(JSThread *thread)
233     {
234         {
235             [[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
236             for (int i = 0; i < g_hundred; i++) {  // g_hundred: run count
237                 [[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(
238                     10 * 1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);  // 10: value, 1024: value
239             }
240         }
241         return thread->GetEcmaVM()->GetHeap()->GetCommittedSize();
242     }
243 
244     template <class T>
ListAddHasCommon(JSThread * thread,JSHandle<T> & toor,JSMutableHandle<JSTaggedValue> & value,std::string myValue,int32_t numbers)245     static void ListAddHasCommon(JSThread *thread, JSHandle<T> &toor, JSMutableHandle<JSTaggedValue> &value,
246                                  std::string myValue, int32_t numbers)
247     {
248         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
249         for (int32_t i = 0; i < numbers; i++) {
250             std::string ivalue = myValue + std::to_string(i);
251             value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
252 
253             JSTaggedValue gValue = toor->Get(thread, i);
254             EXPECT_EQ(gValue, value.GetTaggedValue());
255         }
256         JSTaggedValue gValue = toor->Get(thread, 10);  // 10: index
257         EXPECT_EQ(gValue, JSTaggedValue::Undefined());
258 
259         std::string ivalue = myValue + std::to_string(1);
260         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
261         EXPECT_TRUE(toor->Has(thread, value.GetTaggedValue()));
262     }
263 
264     template <class T>
ListGetLastCommon(JSThread * thread,JSHandle<T> & toor)265     static JSMutableHandle<JSTaggedValue> ListGetLastCommon(JSThread *thread, JSHandle<T> &toor)
266     {
267         constexpr uint32_t NODE_NUMBERS = 9;
268         JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
269         EXPECT_EQ(toor->GetLast(thread), JSTaggedValue::Undefined());
270         EXPECT_EQ(toor->GetFirst(thread), JSTaggedValue::Undefined());
271         for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
272             value.Update(JSTaggedValue(i + 1));
273             T::Add(thread, toor, value);
274         }
275         EXPECT_EQ(toor->GetLast(thread).GetInt(), g_numberNine);
276         EXPECT_EQ(toor->GetFirst(thread).GetInt(), 1);
277 
278         value.Update(JSTaggedValue(g_nintyNine));
279         int len = toor->Length(thread);
280         toor->Insert(thread, toor, value, len);
281         return value;
282     }
283 
284     template <class T>
GetIndexOfAndGetLastIndexOfCommon(JSThread * thread,JSHandle<T> & toor)285     static void GetIndexOfAndGetLastIndexOfCommon(JSThread *thread, JSHandle<T> &toor)
286     {
287         auto value = ListGetLastCommon<T>(thread, toor);
288         EXPECT_EQ(toor->GetIndexOf(thread, value.GetTaggedValue()).GetInt(), g_numberNine);
289         EXPECT_EQ(toor->GetLastIndexOf(thread, value.GetTaggedValue()).GetInt(), g_numberNine);
290         EXPECT_EQ(toor->Length(thread), 10);  // 10: len
291 
292         value.Update(JSTaggedValue(g_hundred));
293         toor->Insert(thread, toor, value, 0);
294         EXPECT_EQ(toor->GetIndexOf(thread, value.GetTaggedValue()).GetInt(), 0);
295         EXPECT_EQ(toor->GetLastIndexOf(thread, value.GetTaggedValue()).GetInt(), 0);
296         EXPECT_EQ(toor->Length(thread), 11);  // 11: len
297 
298         value.Update(JSTaggedValue(g_hundredAndOne));
299         toor->Insert(thread, toor, value, g_numberFive);
300         EXPECT_EQ(toor->GetIndexOf(thread, value.GetTaggedValue()).GetInt(), g_numberFive);
301         EXPECT_EQ(toor->GetLastIndexOf(thread, value.GetTaggedValue()).GetInt(), g_numberFive);
302         EXPECT_EQ(toor->Length(thread), 12);  // 12: len
303 
304         toor->Dump(thread);
305     }
306 
307     template <class T>
InsertAndGetLastCommon(JSThread * thread,JSHandle<T> & toor)308     static void InsertAndGetLastCommon(JSThread *thread, JSHandle<T> &toor)
309     {
310         auto value = ListGetLastCommon<T>(thread, toor);
311         EXPECT_EQ(toor->GetLast(thread).GetInt(), g_nintyNine);
312         EXPECT_EQ(toor->Length(thread), 10);  // 10: len
313 
314         value.Update(JSTaggedValue(g_hundred));
315         toor->Insert(thread, toor, value, 0);
316         EXPECT_EQ(toor->GetFirst(thread).GetInt(), g_hundred);
317         EXPECT_EQ(toor->Length(thread), 11);  // 11: len
318 
319         toor->Dump(thread);
320 
321         value.Update(JSTaggedValue(g_hundredAndOne));
322         toor->Insert(thread, toor, value, g_numberFive);
323         EXPECT_EQ(toor->Length(thread), 12);  // 12: len
324         toor->Dump(thread);
325         EXPECT_EQ(toor->Get(thread, g_numberFive).GetInt(), g_hundredAndOne);
326     }
327 
328     template <class T>
ListRemoveCommon(JSThread * thread,JSHandle<T> & toor,JSMutableHandle<JSTaggedValue> & value)329     static void ListRemoveCommon(JSThread *thread, JSHandle<T> &toor, JSMutableHandle<JSTaggedValue> &value)
330     {
331         constexpr uint32_t NODE_NUMBERS = 20;
332         EXPECT_EQ(toor->GetLast(thread), JSTaggedValue::Undefined());
333         EXPECT_EQ(toor->GetFirst(thread), JSTaggedValue::Undefined());
334         for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
335             value.Update(JSTaggedValue(i));
336             T::Add(thread, toor, value);
337         }
338         EXPECT_EQ(toor->Length(thread), NODE_NUMBERS);
339         for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
340             value.Update(JSTaggedValue(i));
341             JSTaggedValue gValue = toor->Get(thread, i);
342             EXPECT_EQ(gValue, value.GetTaggedValue());
343         }
344     }
345 
SetDateOptionsTest(JSThread * thread,JSHandle<JSObject> & optionsObj,std::map<std::string,std::string> & dateOptions)346     static void SetDateOptionsTest(JSThread *thread, JSHandle<JSObject> &optionsObj,
347                                    std::map<std::string, std::string> &dateOptions)
348     {
349         auto factory = thread->GetEcmaVM()->GetFactory();
350         auto globalConst = thread->GlobalConstants();
351         // Date options keys.
352         JSHandle<JSTaggedValue> weekdayKey = globalConst->GetHandledWeekdayString();
353         JSHandle<JSTaggedValue> yearKey = globalConst->GetHandledYearString();
354         JSHandle<JSTaggedValue> monthKey = globalConst->GetHandledMonthString();
355         JSHandle<JSTaggedValue> dayKey = globalConst->GetHandledDayString();
356         // Date options values.
357         JSHandle<JSTaggedValue> weekdayValue(factory->NewFromASCII(dateOptions["weekday"].c_str()));
358         JSHandle<JSTaggedValue> yearValue(factory->NewFromASCII(dateOptions["year"].c_str()));
359         JSHandle<JSTaggedValue> monthValue(factory->NewFromASCII(dateOptions["month"].c_str()));
360         JSHandle<JSTaggedValue> dayValue(factory->NewFromASCII(dateOptions["day"].c_str()));
361         // Set date options.
362         JSObject::SetProperty(thread, optionsObj, weekdayKey, weekdayValue);
363         JSObject::SetProperty(thread, optionsObj, yearKey, yearValue);
364         JSObject::SetProperty(thread, optionsObj, monthKey, monthValue);
365         JSObject::SetProperty(thread, optionsObj, dayKey, dayValue);
366     }
367 
SetTimeOptionsTest(JSThread * thread,JSHandle<JSObject> & optionsObj,std::map<std::string,std::string> & timeOptionsMap)368     static void SetTimeOptionsTest(JSThread *thread, JSHandle<JSObject> &optionsObj,
369                                    std::map<std::string, std::string> &timeOptionsMap)
370     {
371         auto factory = thread->GetEcmaVM()->GetFactory();
372         auto globalConst = thread->GlobalConstants();
373         // Time options keys.
374         JSHandle<JSTaggedValue> dayPeriodKey = globalConst->GetHandledDayPeriodString();
375         JSHandle<JSTaggedValue> hourKey = globalConst->GetHandledHourString();
376         JSHandle<JSTaggedValue> minuteKey = globalConst->GetHandledMinuteString();
377         JSHandle<JSTaggedValue> secondKey = globalConst->GetHandledSecondString();
378         JSHandle<JSTaggedValue> fractionalSecondDigitsKey = globalConst->GetHandledFractionalSecondDigitsString();
379         // Time options values.
380         JSHandle<JSTaggedValue> dayPeriodValue(factory->NewFromASCII(timeOptionsMap["dayPeriod"].c_str()));
381         JSHandle<JSTaggedValue> hourValue(factory->NewFromASCII(timeOptionsMap["hour"].c_str()));
382         JSHandle<JSTaggedValue> minuteValue(factory->NewFromASCII(timeOptionsMap["minute"].c_str()));
383         JSHandle<JSTaggedValue> secondValue(factory->NewFromASCII(timeOptionsMap["second"].c_str()));
384         JSHandle<JSTaggedValue> fractionalSecondDigitsValue(
385             factory->NewFromASCII(timeOptionsMap["fractionalSecond"].c_str()));
386         // Set time options.
387         JSObject::SetProperty(thread, optionsObj, dayPeriodKey, dayPeriodValue);
388         JSObject::SetProperty(thread, optionsObj, hourKey, hourValue);
389         JSObject::SetProperty(thread, optionsObj, minuteKey, minuteValue);
390         JSObject::SetProperty(thread, optionsObj, secondKey, secondValue);
391         JSObject::SetProperty(thread, optionsObj, fractionalSecondDigitsKey, fractionalSecondDigitsValue);
392     }
393 
CreateDateTimeFormatTest(JSThread * thread,icu::Locale icuLocale,JSHandle<JSObject> options)394     static JSHandle<JSDateTimeFormat> CreateDateTimeFormatTest(JSThread *thread, icu::Locale icuLocale,
395                                                                JSHandle<JSObject> options)
396     {
397         auto factory = thread->GetEcmaVM()->GetFactory();
398 
399         JSHandle<JSTaggedValue> localeCtor = thread->GetEcmaVM()->GetGlobalEnv()->GetLocaleFunction();
400         JSHandle<JSTaggedValue> dtfCtor = thread->GetEcmaVM()->GetGlobalEnv()->GetDateTimeFormatFunction();
401         JSHandle<JSLocale> locales =
402             JSHandle<JSLocale>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(localeCtor), localeCtor));
403         JSHandle<JSDateTimeFormat> dtf =
404             JSHandle<JSDateTimeFormat>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dtfCtor), dtfCtor));
405 
406         JSHandle<JSTaggedValue> optionsVal = JSHandle<JSTaggedValue>::Cast(options);
407         factory->NewJSIntlIcuData(locales, icuLocale, JSLocale::FreeIcuLocale);
408         dtf =
409             JSDateTimeFormat::InitializeDateTimeFormat(thread, dtf, JSHandle<JSTaggedValue>::Cast(locales), optionsVal);
410         return dtf;
411     }
412 
SetHourCycleKeyValue(JSThread * thread,std::string & cycle,std::string & zone)413     static JSHandle<JSObject> SetHourCycleKeyValue(JSThread *thread, std::string &cycle, std::string &zone)
414     {
415         auto factory = thread->GetEcmaVM()->GetFactory();
416         JSHandle<JSTaggedValue> objFun = thread->GetEcmaVM()->GetGlobalEnv()->GetObjectFunction();
417         JSHandle<JSObject> options = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
418         JSHandle<JSTaggedValue> hourCycleKey = thread->GlobalConstants()->GetHandledHourCycleString();
419         JSHandle<JSTaggedValue> hourCycleValue(factory->NewFromASCII(cycle));
420         JSHandle<JSTaggedValue> timeZoneKey = thread->GlobalConstants()->GetHandledTimeZoneString();
421         JSHandle<JSTaggedValue> timeZoneValue(factory->NewFromASCII(zone));
422         JSObject::SetProperty(thread, options, timeZoneKey, timeZoneValue);
423         JSObject::SetProperty(thread, options, hourCycleKey, hourCycleValue);
424         return options;
425     }
426 
ArrayUndefinedGcCommon(JSThread * thread,TriggerGCType type)427     static void ArrayUndefinedGcCommon(JSThread *thread, TriggerGCType type)
428     {
429         EcmaVM *ecmaVM = thread->GetEcmaVM();
430         JSHandle<TaggedArray> array = ecmaVM->GetFactory()->NewTaggedArray(2);  // 2: len
431         EXPECT_TRUE(*array != nullptr);
432         JSHandle<JSObject> newObj1(thread, EcmaContainerCommon::JSObjectTestCreate(thread));
433         array->Set(thread, 0, newObj1.GetTaggedValue());
434 
435         JSObject *newObj2 = EcmaContainerCommon::JSObjectTestCreate(thread);
436         JSTaggedValue value(newObj2);
437         value.CreateWeakRef();
438         array->Set(thread, 1, value);
439         EXPECT_EQ(newObj1.GetTaggedValue(), array->Get(thread, 0));
440         EXPECT_EQ(value, array->Get(thread, 1));
441         ecmaVM->CollectGarbage(type);
442         EXPECT_EQ(newObj1.GetTaggedValue(), array->Get(thread, 0));
443         EXPECT_EQ(JSTaggedValue::Undefined(), array->Get(thread, 1));  // 1 : index
444     }
445 
ArrayKeepGcCommon(JSThread * thread,TriggerGCType type)446     static void ArrayKeepGcCommon(JSThread *thread, TriggerGCType type)
447     {
448         EcmaVM *ecmaVM = thread->GetEcmaVM();
449         JSHandle<TaggedArray> array = ecmaVM->GetFactory()->NewTaggedArray(2);  // 2: len
450         EXPECT_TRUE(*array != nullptr);
451         JSHandle<JSObject> newObj1(thread, EcmaContainerCommon::JSObjectTestCreate(thread));
452         array->Set(thread, 0, newObj1.GetTaggedValue());
453 
454         JSHandle<JSObject> newObj2(thread, EcmaContainerCommon::JSObjectTestCreate(thread));
455         JSTaggedValue value(newObj2.GetTaggedValue());
456         value.CreateWeakRef();
457         array->Set(thread, 1, value);
458         EXPECT_EQ(newObj1.GetTaggedValue(), array->Get(thread, 0));
459         EXPECT_EQ(value, array->Get(thread, 1));
460         ecmaVM->CollectGarbage(type);
461         EXPECT_EQ(newObj1.GetTaggedValue(), array->Get(thread, 0));
462         EXPECT_EQ(true, array->Get(thread, 1).IsWeak());
463         value = newObj2.GetTaggedValue();
464         value.CreateWeakRef();
465         EXPECT_EQ(value, array->Get(thread, 1));
466     }
467 };
468 };  // namespace panda::test
469 
470 #endif
471