• 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/containers/containers_private.h"
17 #include "ecmascript/ecma_string.h"
18 #include "ecmascript/ecma_vm.h"
19 #include "ecmascript/global_env.h"
20 #include "ecmascript/js_function.h"
21 #include "ecmascript/js_handle.h"
22 #include "ecmascript/js_iterator.h"
23 #include "ecmascript/js_api/js_api_hashmap.h"
24 #include "ecmascript/js_api/js_api_hashmap_iterator.h"
25 #include "ecmascript/js_object-inl.h"
26 #include "ecmascript/js_tagged_value.h"
27 #include "ecmascript/object_factory.h"
28 #include "ecmascript/tests/ecma_test_common.h"
29 
30 using namespace panda;
31 using namespace panda::ecmascript;
32 
33 namespace panda::test {
34 class JSAPIHashMapTest : public BaseTestWithScope<false> {
35 protected:
CreateHashMap()36     JSAPIHashMap *CreateHashMap()
37     {
38         return EcmaContainerCommon::CreateHashMap(thread);
39     }
40 
Update(JSHandle<JSAPIHashMap> & hashMap,JSMutableHandle<JSTaggedValue> & key,JSMutableHandle<JSTaggedValue> & value,std::pair<std::string,std::string> myKeyVal,uint32_t numbers)41     void Update(JSHandle<JSAPIHashMap>& hashMap, JSMutableHandle<JSTaggedValue>& key,
42         JSMutableHandle<JSTaggedValue>& value, std::pair<std::string, std::string> myKeyVal, uint32_t numbers)
43     {
44         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
45         for (uint32_t i = 0; i < numbers; i++) {
46             std::string iKey = myKeyVal.first + std::to_string(i);
47             std::string iValue = myKeyVal.second + std::to_string(i);
48             key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
49             value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
50             JSAPIHashMap::Set(thread, hashMap, key, value);
51         }
52     }
53 };
54 
HWTEST_F_L0(JSAPIHashMapTest,HashMapCreate)55 HWTEST_F_L0(JSAPIHashMapTest, HashMapCreate)
56 {
57     JSAPIHashMap *map = CreateHashMap();
58     EXPECT_TRUE(map != nullptr);
59 }
60 
HWTEST_F_L0(JSAPIHashMapTest,HashMapSetAndGet)61 HWTEST_F_L0(JSAPIHashMapTest, HashMapSetAndGet)
62 {
63     constexpr uint32_t NODE_NUMBERS = 8;
64     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
65     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
66     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
67 
68     // test JSAPIHashMap
69     JSHandle<JSAPIHashMap> hashMap(thread, CreateHashMap());
70 
71     // test IsEmpty
72     EXPECT_EQ(hashMap->IsEmpty(), JSTaggedValue::True());
73 
74     // test Set exception
75     key.Update(JSTaggedValue::Undefined());
76     JSAPIHashMap::Set(thread, hashMap, key, value);
77     EXPECT_EXCEPTION();
78 
79     std::string myKey("mykey");
80     std::string myValue("myvalue");
81     auto pair = std::make_pair(myKey, myValue);
82     Update(hashMap, key, value, pair, NODE_NUMBERS);
83     EXPECT_EQ(hashMap->GetSize(), NODE_NUMBERS);
84 
85     // test isEmpty
86     EXPECT_EQ(hashMap->IsEmpty(), JSTaggedValue::False());
87 
88     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
89         std::string iKey = myKey + std::to_string(i);
90         std::string iValue = myValue + std::to_string(i);
91         key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
92         value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
93 
94         // test get
95         JSTaggedValue gValue = hashMap->Get(thread, key.GetTaggedValue());
96         EXPECT_EQ(gValue, value.GetTaggedValue());
97     }
98 }
99 
HWTEST_F_L0(JSAPIHashMapTest,HashMapRemoveAndHas)100 HWTEST_F_L0(JSAPIHashMapTest, HashMapRemoveAndHas)
101 {
102     constexpr uint32_t NODE_NUMBERS = 8;
103     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
104     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
105     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
106 
107     // test JSAPIHashMap
108     JSHandle<JSAPIHashMap> hashMap(thread, CreateHashMap());
109 
110     // test Remove Hole
111     JSTaggedValue undefined = JSAPIHashMap::Remove(thread, hashMap, JSTaggedValue::Hole());
112     EXPECT_EQ(undefined, JSTaggedValue::Undefined());
113 
114     // test Remove empty hashmap
115     JSTaggedValue undefined1 = JSAPIHashMap::Remove(thread, hashMap, JSTaggedValue(0));
116     EXPECT_EQ(undefined1, JSTaggedValue::Undefined());
117 
118     std::string myKey("mykey");
119     std::string myValue("myvalue");
120     auto pair = std::make_pair(myKey, myValue);
121     Update(hashMap, key, value, pair, NODE_NUMBERS);
122     EXPECT_EQ(hashMap->GetSize(), NODE_NUMBERS);
123 
124     // test Remove non-existent
125     JSTaggedValue undefined2 = JSAPIHashMap::Remove(thread, hashMap, JSTaggedValue(0));
126     EXPECT_EQ(undefined2, JSTaggedValue::Undefined());
127 
128     for (uint32_t i = 0; i < NODE_NUMBERS / 2; i++) {
129         std::string iKey = myKey + std::to_string(i);
130         key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
131         [[maybe_unused]] JSTaggedValue rValue = JSAPIHashMap::Remove(thread, hashMap, key.GetTaggedValue());
132     }
133     EXPECT_EQ(hashMap->GetSize(), NODE_NUMBERS / 2);
134 
135     for (uint32_t i = 0; i < NODE_NUMBERS / 2; i++) {
136         std::string iKey = myKey + std::to_string(i);
137         std::string iValue = myValue + std::to_string(i);
138         key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
139         value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
140 
141         // test has
142         JSTaggedValue hasKey = hashMap->HasKey(thread, key.GetTaggedValue());
143         EXPECT_EQ(hasKey, JSTaggedValue::False());
144         JSTaggedValue hasValue = JSAPIHashMap::HasValue(thread, hashMap, value);
145         EXPECT_EQ(hasValue, JSTaggedValue::False());
146     }
147 
148     for (uint32_t i = NODE_NUMBERS / 2; i < NODE_NUMBERS; i++) {
149         std::string iKey = myKey + std::to_string(i);
150         std::string iValue = myValue + std::to_string(i);
151         key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
152         value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
153 
154         // test has
155         JSTaggedValue hasKey = hashMap->HasKey(thread, key.GetTaggedValue());
156         EXPECT_EQ(hasKey, JSTaggedValue::True());
157         JSTaggedValue hasValue = JSAPIHashMap::HasValue(thread, hashMap, value);
158         EXPECT_EQ(hasValue, JSTaggedValue::True());
159     }
160 }
161 
HWTEST_F_L0(JSAPIHashMapTest,HashMapReplaceAndClear)162 HWTEST_F_L0(JSAPIHashMapTest, HashMapReplaceAndClear)
163 {
164     constexpr uint32_t NODE_NUMBERS = 8;
165     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
166     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
167     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
168     // test TaggedHashMap
169     JSHandle<JSAPIHashMap> hashMap(thread, CreateHashMap());
170     std::string myKey("mykey");
171     std::string myValue("myvalue");
172     auto pair = std::make_pair(myKey, myValue);
173     Update(hashMap, key, value, pair, NODE_NUMBERS);
174     EXPECT_EQ(hashMap->GetSize(), NODE_NUMBERS);
175     for (uint32_t i = 0; i < NODE_NUMBERS / 2; i++) {
176         std::string iKey = myKey + std::to_string(i);
177         std::string iValue = myValue + std::to_string(i + 1);
178         key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
179         value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
180         // test replace
181         bool success = hashMap->Replace(thread, key.GetTaggedValue(), value.GetTaggedValue());
182         EXPECT_EQ(success, true);
183     }
184     for (uint32_t i = 0; i < NODE_NUMBERS / 2; i++) {
185         std::string iKey = myKey + std::to_string(i);
186         std::string iValue = myValue + std::to_string(i + 1);
187         key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
188         value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
189         // test get
190         JSTaggedValue gValue = hashMap->Get(thread, key.GetTaggedValue());
191         EXPECT_EQ(gValue, value.GetTaggedValue());
192     }
193     for (uint32_t i = NODE_NUMBERS / 2; i < NODE_NUMBERS; i++) {
194         std::string iKey = myKey + std::to_string(i);
195         std::string iValue = myValue + std::to_string(i);
196         key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
197         value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
198         // test get
199         JSTaggedValue gValue = hashMap->Get(thread, key.GetTaggedValue());
200         EXPECT_EQ(gValue, value.GetTaggedValue());
201     }
202     for (uint32_t i = 0; i < NODE_NUMBERS / 2; i++) {
203         std::string iKey = myKey + std::to_string(i);
204         key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
205         [[maybe_unused]] JSTaggedValue rValue = JSAPIHashMap::Remove(thread, hashMap, key.GetTaggedValue());
206     }
207     hashMap->Clear(thread);
208     EXPECT_EQ(hashMap->GetSize(), (uint32_t)0);
209     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
210         std::string iKey = myKey + std::to_string(i);
211         std::string iValue = myValue + std::to_string(i);
212         key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
213         value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
214         // test get
215         JSTaggedValue gValue = hashMap->Get(thread, key.GetTaggedValue());
216         EXPECT_EQ(gValue, JSTaggedValue::Undefined());
217         // test has
218         JSTaggedValue hasKey = hashMap->HasKey(thread, key.GetTaggedValue());
219         EXPECT_EQ(hasKey, JSTaggedValue::False());
220         JSTaggedValue hasValue = JSAPIHashMap::HasValue(thread, hashMap, value);
221         EXPECT_EQ(hasValue, JSTaggedValue::False());
222     }
223 }
224 
HWTEST_F_L0(JSAPIHashMapTest,JSAPIHashMapIterator)225 HWTEST_F_L0(JSAPIHashMapTest, JSAPIHashMapIterator)
226 {
227     constexpr uint32_t NODE_NUMBERS = 8;
228     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
229     JSHandle<JSAPIHashMap> hashMap(thread, CreateHashMap());
230     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
231     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
232     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
233         key.Update(JSTaggedValue(i));
234         value.Update(JSTaggedValue(i));
235         JSAPIHashMap::Set(thread, hashMap, key, value);
236     }
237     // test key or value
238     JSHandle<JSTaggedValue> keyIter(factory->NewJSAPIHashMapIterator(hashMap, IterationKind::KEY));
239     JSHandle<JSTaggedValue> valueIter(factory->NewJSAPIHashMapIterator(hashMap, IterationKind::VALUE));
240     JSMutableHandle<JSTaggedValue> keyIterResult(thread, JSTaggedValue::Undefined());
241     JSMutableHandle<JSTaggedValue> valueIterResult(thread, JSTaggedValue::Undefined());
242     for (uint32_t i = 0; i < NODE_NUMBERS / 2; i++) {
243         keyIterResult.Update(JSIterator::IteratorStep(thread, keyIter).GetTaggedValue());
244         valueIterResult.Update(JSIterator::IteratorStep(thread, valueIter).GetTaggedValue());
245         JSHandle<JSTaggedValue> tmpIterKey = JSIterator::IteratorValue(thread, keyIterResult);
246         JSTaggedValue iterKeyFlag = hashMap->HasKey(thread, tmpIterKey.GetTaggedValue());
247         EXPECT_EQ(JSTaggedValue::True(), iterKeyFlag);
248         JSHandle<JSTaggedValue> tmpIterValue = JSIterator::IteratorValue(thread, valueIterResult);
249         JSTaggedValue iterValueFlag = JSAPIHashMap::HasValue(thread, hashMap, tmpIterValue);
250         EXPECT_EQ(JSTaggedValue::True(), iterValueFlag);
251     }
252     // test key and value
253     JSHandle<JSTaggedValue> indexKey(thread, JSTaggedValue(0));
254     JSHandle<JSTaggedValue> elementKey(thread, JSTaggedValue(1));
255     JSHandle<JSTaggedValue> iter(factory->NewJSAPIHashMapIterator(hashMap, IterationKind::KEY_AND_VALUE));
256     JSMutableHandle<JSTaggedValue> iterResult(thread, JSTaggedValue::Undefined());
257     JSMutableHandle<JSTaggedValue> result(thread, JSTaggedValue::Undefined());
258     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
259         iterResult.Update(JSIterator::IteratorStep(thread, iter).GetTaggedValue());
260         result.Update(JSIterator::IteratorValue(thread, iterResult).GetTaggedValue());
261         JSHandle<JSTaggedValue> tmpKey = JSObject::GetProperty(thread, result, indexKey).GetValue();
262         JSTaggedValue iterKeyFlag = hashMap->HasKey(thread, tmpKey.GetTaggedValue());
263         EXPECT_EQ(JSTaggedValue::True(), iterKeyFlag);
264         JSHandle<JSTaggedValue> tmpValue = JSObject::GetProperty(thread, result, elementKey).GetValue();
265         JSTaggedValue iterValueFlag = JSAPIHashMap::HasValue(thread, hashMap, tmpValue);
266         EXPECT_EQ(JSTaggedValue::True(), iterValueFlag);
267     }
268     // test delete
269     key.Update(JSTaggedValue(NODE_NUMBERS / 2));
270     JSTaggedValue rValue = JSAPIHashMap::Remove(thread, hashMap, key.GetTaggedValue());
271     EXPECT_EQ(rValue, JSTaggedValue(NODE_NUMBERS / 2));
272     for (uint32_t i = NODE_NUMBERS / 2 + 1; i < NODE_NUMBERS; i++) {
273         keyIterResult.Update(JSIterator::IteratorStep(thread, keyIter).GetTaggedValue());
274         valueIterResult.Update(JSIterator::IteratorStep(thread, valueIter).GetTaggedValue());
275         JSHandle<JSTaggedValue> tmpIterKey = JSIterator::IteratorValue(thread, keyIterResult);
276         JSTaggedValue iterKeyFlag = hashMap->HasKey(thread, tmpIterKey.GetTaggedValue());
277         EXPECT_EQ(JSTaggedValue::True(), iterKeyFlag);
278         JSHandle<JSTaggedValue> tmpIterValue = JSIterator::IteratorValue(thread, valueIterResult);
279         JSTaggedValue iterValueFlag = JSAPIHashMap::HasValue(thread, hashMap, tmpIterValue);
280         EXPECT_EQ(JSTaggedValue::True(), iterValueFlag);
281     }
282     // test set
283     key.Update(JSTaggedValue(NODE_NUMBERS));
284     JSAPIHashMap::Set(thread, hashMap, key, key);
285     keyIterResult.Update(JSIterator::IteratorStep(thread, keyIter).GetTaggedValue());
286     JSHandle<JSTaggedValue> tmpIterKey = JSIterator::IteratorValue(thread, keyIterResult);
287     JSTaggedValue iterKeyFlag = hashMap->HasKey(thread, tmpIterKey.GetTaggedValue());
288     EXPECT_EQ(JSTaggedValue::True(), iterKeyFlag);
289     EXPECT_EQ(hashMap->GetSize(), NODE_NUMBERS);
290     keyIterResult.Update(JSIterator::IteratorStep(thread, keyIter).GetTaggedValue());
291     EXPECT_EQ(JSTaggedValue::False(), keyIterResult.GetTaggedValue());
292 }
293 
HWTEST_F_L0(JSAPIHashMapTest,JSAPIHashMapIteratorRBTreeTest)294 HWTEST_F_L0(JSAPIHashMapTest, JSAPIHashMapIteratorRBTreeTest)
295 {
296     constexpr uint32_t NODE_NUMBERS = 11;
297     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
298     JSHandle<JSAPIHashMap> hashMap(thread, CreateHashMap());
299     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
300     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
301     JSHandle<JSTaggedValue> valueStr = thread->GlobalConstants()->GetHandledValueString();
302     std::vector<int> hashCollisionVector = {1013, 1015, 1021, 1023, 1045, 1047, 1053, 1055, 1077, 1079, 1085};
303 
304     JSHandle<TaggedHashArray> hashArray(thread, hashMap->GetTable(thread));
305     hashArray = TaggedHashArray::Resize(thread, hashArray, NODE_NUMBERS);
306     hashMap->SetTable(thread, hashArray);
307 
308     for (size_t i = 0; i < hashCollisionVector.size(); i++) {
309         key.Update(JSTaggedValue(hashCollisionVector[i]));
310         value.Update(JSTaggedValue(hashCollisionVector[i]));
311         JSAPIHashMap::Set(thread, hashMap, key, value);
312     }
313 
314     JSHandle<JSAPIHashMapIterator> hashmapIterator = factory->NewJSAPIHashMapIterator(hashMap, IterationKind::VALUE);
315     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
316         auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
317         ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
318         ecmaRuntimeCallInfo->SetThis(hashmapIterator.GetTaggedValue());
319 
320         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
321         JSTaggedValue result = JSAPIHashMapIterator::Next(ecmaRuntimeCallInfo);
322         TestHelper::TearDownFrame(thread, prev);
323 
324         JSHandle<JSObject> resultObj(thread, result);
325         if (i <= NODE_NUMBERS - 1U) {
326             EXPECT_TRUE(JSObject::GetProperty(thread, resultObj, valueStr).GetValue()->IsInt());
327         }
328     }
329 }
330 
HWTEST_F_L0(JSAPIHashMapTest,JSAPIHashMapIteratorDiffNodeTest)331 HWTEST_F_L0(JSAPIHashMapTest, JSAPIHashMapIteratorDiffNodeTest)
332 {
333     constexpr uint32_t NODE_NUMBERS = 1 << 4;
334     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
335     JSHandle<JSAPIHashMap> hashMap(thread, CreateHashMap());
336     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
337     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
338     JSHandle<TaggedHashArray> hashArray(thread, hashMap->GetTable(thread));
339     hashArray = TaggedHashArray::Resize(thread, hashArray, NODE_NUMBERS);
340     hashMap->SetTable(thread, hashArray);
341     std::vector<int> treeNumsVector = {1224, 1285, 1463, 4307, 5135, 5903, 6603, 6780, 8416, 9401, 9740};
342 
343     int32_t totalNums = 0;
344     // create RBTree Node
345     for (size_t i = 0; i < treeNumsVector.size(); i++) {
346         key.Update(JSTaggedValue(treeNumsVector[i]));
347         value.Update(JSTaggedValue(treeNumsVector[i]));
348         if (!TaggedHashArray::SetVal(thread, hashArray, 0, key, value).IsUndefined()) {
349             totalNums++;
350         }
351     }
352 
353     // create LinkList Node
354     std::vector<int> linkListVector = {1224, 1285, 1463, 4307};
355     for (uint32_t hash = 1; hash < NODE_NUMBERS; hash++) {
356         for (size_t i = 0; i < linkListVector.size(); i++) {
357             key.Update(JSTaggedValue(linkListVector[i]));
358             value.Update(JSTaggedValue(linkListVector[i]));
359             if (!TaggedHashArray::SetVal(thread, hashArray, hash, key, value).IsUndefined()) {
360                 totalNums++;
361             }
362         }
363     }
364 
365     JSHandle<JSAPIHashMapIterator> hashmapIterator = factory->NewJSAPIHashMapIterator(hashMap, IterationKind::VALUE);
366     int32_t count = 0;
367     while (!hashmapIterator->GetIteratedHashMap(thread).IsUndefined()) {
368         auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
369         ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
370         ecmaRuntimeCallInfo->SetThis(hashmapIterator.GetTaggedValue());
371 
372         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
373         JSAPIHashMapIterator::Next(ecmaRuntimeCallInfo);
374         TestHelper::TearDownFrame(thread, prev);
375         count++;
376     }
377     EXPECT_EQ(count - 1, totalNums);
378 }
379 
HWTEST_F_L0(JSAPIHashMapTest,JSAPIHashMapIteratorDiffNodeRandomlyTest)380 HWTEST_F_L0(JSAPIHashMapTest, JSAPIHashMapIteratorDiffNodeRandomlyTest)
381 {
382     constexpr uint32_t NODE_NUMBERS = 1 << 4;
383     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
384     JSHandle<JSAPIHashMap> hashMap(thread, CreateHashMap());
385     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
386     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
387     JSHandle<TaggedHashArray> hashArray(thread, hashMap->GetTable(thread));
388     hashArray = TaggedHashArray::Resize(thread, hashArray, NODE_NUMBERS);
389     hashMap->SetTable(thread, hashArray);
390     std::vector<int> treeNumsVector = {1224, 1285, 1463, 4307, 5135, 5903, 6603, 6780, 8416, 9401, 9740};
391     std::random_device rd;
392     std::mt19937 g(rd());
393     std::vector<int>p;
394     for (uint32_t i = 1; i <= NODE_NUMBERS; i++) {
395         p.push_back(i);
396     }
397     std::shuffle(p.begin(), p.end(), g);
398     int32_t totalNums = 0;
399     for (uint32_t index = 0; index < p.size(); index++) {
400         if (!(g() % 3)) {
401             // create RBTree Node
402             for (size_t i = 0; i < treeNumsVector.size(); i++) {
403                 key.Update(JSTaggedValue(treeNumsVector[i]));
404                 value.Update(JSTaggedValue(treeNumsVector[i]));
405                 totalNums += (TaggedHashArray::SetVal(thread, hashArray, p[index], key, value).IsUndefined() ? 0 : 1);
406             }
407             continue;
408         }
409         // create LinkList Node
410         std::vector<int> linkListVector = {1224, 1285, 1463, 4307};
411         for (size_t i = 0; i < linkListVector.size(); i++) {
412             key.Update(JSTaggedValue(linkListVector[i]));
413             value.Update(JSTaggedValue(linkListVector[i]));
414             totalNums += (TaggedHashArray::SetVal(thread, hashArray, p[index], key, value).IsUndefined() ? 0 : 1);
415         }
416     }
417     JSHandle<JSAPIHashMapIterator> hashmapIterator = factory->NewJSAPIHashMapIterator(hashMap, IterationKind::VALUE);
418     int32_t count = 0;
419     while (!hashmapIterator->GetIteratedHashMap(thread).IsUndefined()) {
420         auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
421         ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
422         ecmaRuntimeCallInfo->SetThis(hashmapIterator.GetTaggedValue());
423 
424         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
425         JSAPIHashMapIterator::Next(ecmaRuntimeCallInfo);
426         TestHelper::TearDownFrame(thread, prev);
427         count++;
428     }
429     EXPECT_EQ(count - 1, totalNums);
430 }
431 
HWTEST_F_L0(JSAPIHashMapTest,JSAPIHashMapRBTreeHasValueReplaceGet)432 HWTEST_F_L0(JSAPIHashMapTest, JSAPIHashMapRBTreeHasValueReplaceGet)
433 {
434     std::vector<int> hashCollisionVector = {1224, 1285, 1463, 4307, 5135, 5903, 6780, 8416, 9401, 9740, 6603};
435     uint32_t NODE_NUMBERS = static_cast<uint32_t>(hashCollisionVector.size());
436     JSHandle<JSAPIHashMap> hashMap(thread, CreateHashMap());
437     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
438     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
439 
440     for (uint32_t i = 0; i < NODE_NUMBERS - 1; i++) {
441         key.Update(JSTaggedValue(hashCollisionVector[i]));
442         value.Update(JSTaggedValue(hashCollisionVector[i]));
443         JSAPIHashMap::Set(thread, hashMap, key, value);
444     }
445 
446     // test RBTree HasValue
447     for (uint32_t i = 0; i < NODE_NUMBERS - 1; i++) {
448         value.Update(JSTaggedValue(hashCollisionVector[i]));
449         JSTaggedValue hasValue = JSAPIHashMap::HasValue(thread, hashMap, value);
450         EXPECT_EQ(hasValue, JSTaggedValue::True());
451     }
452     value.Update(JSTaggedValue(hashCollisionVector[NODE_NUMBERS - 1]));
453     JSTaggedValue hasValue = JSAPIHashMap::HasValue(thread, hashMap, value);
454     EXPECT_EQ(hasValue, JSTaggedValue::False());
455 
456     // test RBTree Replace and Get
457     for (uint32_t i = 0; i < NODE_NUMBERS - 1; i++) {
458         bool replaceResult = hashMap->Replace(
459             thread, JSTaggedValue(hashCollisionVector[i]), JSTaggedValue(hashCollisionVector[i] * 2));
460         EXPECT_EQ(replaceResult, true);
461     }
462     for (uint32_t i = 0; i < NODE_NUMBERS - 1; i++) {
463         JSTaggedValue replaceResult = hashMap->Get(
464             thread, JSTaggedValue(hashCollisionVector[i]));
465         EXPECT_EQ(replaceResult, JSTaggedValue(hashCollisionVector[i] * 2));
466     }
467 }
468 
HWTEST_F_L0(JSAPIHashMapTest,JSAPIHashMapRBTreeSetAllRemove)469 HWTEST_F_L0(JSAPIHashMapTest, JSAPIHashMapRBTreeSetAllRemove)
470 {
471     std::vector<int> hashCollisionVector = {1224, 1285, 1463, 4307, 5135, 5903, 6780, 8416, 9401, 9740, 6603};
472     uint32_t NODE_NUMBERS = static_cast<uint32_t>(hashCollisionVector.size());
473     uint32_t REMOVE_NUMBERS = 4;
474     JSHandle<JSAPIHashMap> dstHashMap(thread, CreateHashMap());
475     JSHandle<JSAPIHashMap> srcHashMap(thread, CreateHashMap());
476     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
477     JSMutableHandle<JSTaggedValue> dstValue(thread, JSTaggedValue::Undefined());
478     JSMutableHandle<JSTaggedValue> srcValue(thread, JSTaggedValue::Undefined());
479 
480     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
481         key.Update(JSTaggedValue(hashCollisionVector[i]));
482         dstValue.Update(JSTaggedValue(hashCollisionVector[i]));
483         srcValue.Update(JSTaggedValue(hashCollisionVector[i] * 2));
484         JSAPIHashMap::Set(thread, dstHashMap, key, dstValue);
485         JSAPIHashMap::Set(thread, srcHashMap, key, srcValue);
486     }
487 
488     // test SetAll and Get
489     JSAPIHashMap::SetAll(thread, dstHashMap, srcHashMap);
490     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
491         JSTaggedValue replaceResult = dstHashMap->Get(
492             thread, JSTaggedValue(hashCollisionVector[i]));
493         EXPECT_EQ(replaceResult, JSTaggedValue(hashCollisionVector[i] * 2));
494     }
495 
496     // test Remove RBTree
497     for (uint32_t i = 0; i < REMOVE_NUMBERS; i++) {
498         key.Update(JSTaggedValue(hashCollisionVector[i]));
499         JSAPIHashMap::Remove(thread, dstHashMap, key.GetTaggedValue());
500     }
501     EXPECT_EQ(dstHashMap->GetSize(), NODE_NUMBERS - REMOVE_NUMBERS);
502 
503     for (uint32_t i = 0; i < REMOVE_NUMBERS; i++) {
504         JSTaggedValue getResult = dstHashMap->Get(thread, JSTaggedValue(hashCollisionVector[i]));
505         EXPECT_EQ(getResult, JSTaggedValue::Undefined());
506     }
507 
508     for (uint32_t i = REMOVE_NUMBERS; i < NODE_NUMBERS; i++) {
509         JSTaggedValue getResult = dstHashMap->Get(thread, JSTaggedValue(hashCollisionVector[i]));
510         EXPECT_EQ(getResult, JSTaggedValue(hashCollisionVector[i] * 2));
511     }
512 }
513 }  // namespace panda::test
514