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/containers/containers_hashmap.h"
18#include "ecmascript/ecma_runtime_call_info.h"
19#include "ecmascript/global_env.h"
20#include "ecmascript/js_handle.h"
21#include "ecmascript/js_tagged_value-inl.h"
22#include "ecmascript/js_thread.h"
23#include "ecmascript/js_api/js_api_hashmap.h"
24#include "ecmascript/js_api/js_api_hashmap_iterator.h"
25#include "ecmascript/object_factory.h"
26#include "ecmascript/tests/test_helper.h"
27#include "ecmascript/containers/tests/containers_test_helper.h"
28
29using namespace panda::ecmascript;
30using namespace panda::ecmascript::containers;
31
32namespace panda::test {
33class ContainersHashMapTest : public testing::Test {
34public:
35    static void SetUpTestCase()
36    {
37        GTEST_LOG_(INFO) << "SetUpTestCase";
38    }
39
40    static void TearDownTestCase()
41    {
42        GTEST_LOG_(INFO) << "TearDownCase";
43    }
44
45    void SetUp() override
46    {
47        TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
48    }
49
50    void TearDown() override
51    {
52        TestHelper::DestroyEcmaVMWithScope(instance, scope);
53    }
54
55    EcmaVM *instance {nullptr};
56    EcmaHandleScope *scope {nullptr};
57    JSThread *thread {nullptr};
58
59    class TestClass : public base::BuiltinsBase {
60    public:
61        static JSTaggedValue TestForEachFunc(EcmaRuntimeCallInfo *argv)
62        {
63            JSThread *thread = argv->GetThread();
64            JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
65            JSHandle<JSTaggedValue> key = GetCallArg(argv, 1);
66            JSHandle<JSTaggedValue> map = GetCallArg(argv, 2); // 2 means the secode arg
67            if (!map->IsUndefined()) {
68                if (value->IsNumber()) {
69                    JSHandle<JSTaggedValue> newValue(thread, JSTaggedValue(value->GetInt() * 2)); // 2 means mul by 2
70                    JSAPIHashMap::Set(thread, JSHandle<JSAPIHashMap>::Cast(map), key, newValue);
71                }
72            }
73            JSHandle<JSAPIHashMap> jsHashMap(GetThis(argv));
74            JSAPIHashMap::Set(thread, jsHashMap, key, value);
75            return JSTaggedValue::Undefined();
76        }
77    };
78protected:
79    JSTaggedValue InitializeHashMapConstructor()
80    {
81        ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
82        JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
83
84        JSHandle<JSTaggedValue> globalObject = env->GetJSGlobalObject();
85        JSHandle<JSTaggedValue> key(factory->NewFromASCII("ArkPrivate"));
86        JSHandle<JSTaggedValue> value =
87            JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(globalObject), key).GetValue();
88
89        auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
90        objCallInfo->SetFunction(JSTaggedValue::Undefined());
91        objCallInfo->SetThis(value.GetTaggedValue());
92        objCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int>(ContainerTag::HashMap)));
93        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
94        JSTaggedValue result = ContainersPrivate::Load(objCallInfo);
95        TestHelper::TearDownFrame(thread, prev);
96
97        return result;
98    }
99
100    JSHandle<JSAPIHashMap> CreateJSAPIHashMap()
101    {
102        JSHandle<JSFunction> newTarget(thread, InitializeHashMapConstructor());
103        auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
104        objCallInfo->SetFunction(newTarget.GetTaggedValue());
105        objCallInfo->SetNewTarget(newTarget.GetTaggedValue());
106        objCallInfo->SetThis(JSTaggedValue::Undefined());
107
108        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
109        JSTaggedValue result = ContainersHashMap::HashMapConstructor(objCallInfo);
110        TestHelper::TearDownFrame(thread, prev);
111        JSHandle<JSAPIHashMap> map(thread, result);
112        return map;
113    }
114};
115
116// new HashMap()
117HWTEST_F_L0(ContainersHashMapTest, HashMapConstructor)
118{
119    InitializeHashMapConstructor();
120    JSHandle<JSFunction> newTarget(thread, InitializeHashMapConstructor());
121
122    auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
123    objCallInfo->SetFunction(newTarget.GetTaggedValue());
124    objCallInfo->SetNewTarget(newTarget.GetTaggedValue());
125    objCallInfo->SetThis(JSTaggedValue::Undefined());
126
127    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
128    JSTaggedValue result = ContainersHashMap::HashMapConstructor(objCallInfo);
129    TestHelper::TearDownFrame(thread, prev);
130
131    ASSERT_TRUE(result.IsJSAPIHashMap());
132    JSHandle<JSAPIHashMap> mapHandle(thread, result);
133    JSTaggedValue resultProto = JSTaggedValue::GetPrototype(thread, JSHandle<JSTaggedValue>(mapHandle));
134    JSTaggedValue funcProto = newTarget->GetFunctionPrototype();
135    ASSERT_EQ(resultProto, funcProto);
136    int size = mapHandle->GetSize();
137    ASSERT_EQ(size, 0);
138
139    // test HashMapConstructor exception
140    objCallInfo->SetNewTarget(JSTaggedValue::Undefined());
141    CONTAINERS_API_EXCEPTION_TEST(ContainersHashMap, HashMapConstructor, objCallInfo);
142}
143
144// hashmap.set(key, value), hashmap.get(key)
145HWTEST_F_L0(ContainersHashMapTest, SetAndGet)
146{
147    constexpr uint32_t NODE_NUMBERS = 8;
148    JSHandle<JSAPIHashMap> tMap = CreateJSAPIHashMap();
149    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
150        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
151        callInfo->SetFunction(JSTaggedValue::Undefined());
152        callInfo->SetThis(tMap.GetTaggedValue());
153        callInfo->SetCallArg(0, JSTaggedValue(i));
154        callInfo->SetCallArg(1, JSTaggedValue(i));
155
156        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
157        JSTaggedValue result = ContainersHashMap::Set(callInfo);
158        TestHelper::TearDownFrame(thread, prev);
159        EXPECT_TRUE(result.IsJSAPIHashMap());
160        EXPECT_EQ(JSAPIHashMap::Cast(result.GetTaggedObject())->GetSize(), i + 1);
161    }
162
163    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
164        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
165        callInfo->SetFunction(JSTaggedValue::Undefined());
166        callInfo->SetThis(tMap.GetTaggedValue());
167        callInfo->SetCallArg(0, JSTaggedValue(i));
168
169        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
170        JSTaggedValue result = ContainersHashMap::Get(callInfo);
171        TestHelper::TearDownFrame(thread, prev);
172        EXPECT_EQ(result, JSTaggedValue(i));
173    }
174}
175
176// hashmap.hasKey(key), hashmap.hasValue(value)
177HWTEST_F_L0(ContainersHashMapTest, HasKeyAndHasValue)
178{
179    constexpr uint32_t NODE_NUMBERS = 8;
180    JSHandle<JSAPIHashMap> tMap = CreateJSAPIHashMap();
181    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
182        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
183        callInfo->SetFunction(JSTaggedValue::Undefined());
184        callInfo->SetThis(tMap.GetTaggedValue());
185        callInfo->SetCallArg(0, JSTaggedValue(i));
186        callInfo->SetCallArg(1, JSTaggedValue(i));
187
188        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
189        JSTaggedValue result = ContainersHashMap::Set(callInfo);
190        TestHelper::TearDownFrame(thread, prev);
191        EXPECT_TRUE(result.IsJSAPIHashMap());
192        EXPECT_EQ(JSAPIHashMap::Cast(result.GetTaggedObject())->GetSize(), i + 1);
193    }
194
195    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
196        // test hasKey
197        {
198            auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
199            callInfo->SetFunction(JSTaggedValue::Undefined());
200            callInfo->SetThis(tMap.GetTaggedValue());
201            callInfo->SetCallArg(0, JSTaggedValue(i));
202
203            [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
204            JSTaggedValue result = ContainersHashMap::HasKey(callInfo);
205            TestHelper::TearDownFrame(thread, prev);
206            EXPECT_EQ(result, JSTaggedValue::True());
207        }
208        // test hasValue
209        {
210            auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
211            callInfo->SetFunction(JSTaggedValue::Undefined());
212            callInfo->SetThis(tMap.GetTaggedValue());
213            callInfo->SetCallArg(0, JSTaggedValue(i));
214
215            [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
216            JSTaggedValue result = ContainersHashMap::HasValue(callInfo);
217            TestHelper::TearDownFrame(thread, prev);
218            EXPECT_EQ(result, JSTaggedValue::True());
219        }
220    }
221
222    // test add string
223    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
224    JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
225    JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
226    std::string myKey("mykey");
227    std::string myValue("myvalue");
228    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
229        std::string iKey = myKey + std::to_string(i);
230        std::string iValue = myValue + std::to_string(i);
231        key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
232        value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
233
234        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
235        callInfo->SetFunction(JSTaggedValue::Undefined());
236        callInfo->SetThis(tMap.GetTaggedValue());
237        callInfo->SetCallArg(0, key.GetTaggedValue());
238        callInfo->SetCallArg(1, value.GetTaggedValue());
239        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
240        JSTaggedValue result = ContainersHashMap::Set(callInfo);
241        TestHelper::TearDownFrame(thread, prev);
242        EXPECT_TRUE(result.IsJSAPIHashMap());
243        EXPECT_EQ(JSAPIHashMap::Cast(result.GetTaggedObject())->GetSize(), NODE_NUMBERS + i + 1);
244    }
245
246    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
247        // test hasKey
248        {
249            std::string iKey = myKey + std::to_string(i);
250            key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
251            auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
252            callInfo->SetFunction(JSTaggedValue::Undefined());
253            callInfo->SetThis(tMap.GetTaggedValue());
254            callInfo->SetCallArg(0, key.GetTaggedValue());
255
256            [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
257            JSTaggedValue result = ContainersHashMap::HasKey(callInfo);
258            TestHelper::TearDownFrame(thread, prev);
259            EXPECT_EQ(result, JSTaggedValue::True());
260        }
261        // test hasValue
262        {
263            std::string iValue = myValue + std::to_string(i);
264            value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
265            auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
266            callInfo->SetFunction(JSTaggedValue::Undefined());
267            callInfo->SetThis(tMap.GetTaggedValue());
268            callInfo->SetCallArg(0, value.GetTaggedValue());
269
270            [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
271            JSTaggedValue result = ContainersHashMap::HasValue(callInfo);
272            TestHelper::TearDownFrame(thread, prev);
273            EXPECT_EQ(result, JSTaggedValue::True());
274        }
275    }
276}
277
278// hashmap.keys(), hashmap.values(), hashmap.entries()
279HWTEST_F_L0(ContainersHashMapTest, KeysAndValuesAndEntries)
280{
281    constexpr uint32_t NODE_NUMBERS = 8;
282    JSHandle<JSAPIHashMap> tMap = CreateJSAPIHashMap();
283    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
284        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
285        callInfo->SetFunction(JSTaggedValue::Undefined());
286        callInfo->SetThis(tMap.GetTaggedValue());
287        callInfo->SetCallArg(0, JSTaggedValue(i));
288        callInfo->SetCallArg(1, JSTaggedValue(i));
289
290        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
291        JSTaggedValue result2 = ContainersHashMap::Set(callInfo);
292        TestHelper::TearDownFrame(thread, prev);
293        EXPECT_TRUE(result2.IsJSAPIHashMap());
294        EXPECT_EQ(JSAPIHashMap::Cast(result2.GetTaggedObject())->GetSize(), i + 1);
295    }
296
297    // test keys
298    auto callInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
299    callInfo1->SetFunction(JSTaggedValue::Undefined());
300    callInfo1->SetThis(tMap.GetTaggedValue());
301    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo1);
302    JSHandle<JSTaggedValue> iterKeys(thread, ContainersHashMap::Keys(callInfo1));
303    TestHelper::TearDownFrame(thread, prev);
304    EXPECT_TRUE(iterKeys->IsJSAPIHashMapIterator());
305
306    JSMutableHandle<JSTaggedValue> result(thread, JSTaggedValue::Undefined());
307    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
308        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
309        callInfo->SetFunction(JSTaggedValue::Undefined());
310        callInfo->SetThis(iterKeys.GetTaggedValue());
311
312        [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, callInfo);
313        result.Update(JSAPIHashMapIterator::Next(callInfo));
314        TestHelper::TearDownFrame(thread, prev1);
315        JSHandle<JSTaggedValue> iterKey = JSIterator::IteratorValue(thread, result);
316        JSTaggedValue keyFlag = tMap->HasKey(thread, iterKey.GetTaggedValue());
317        EXPECT_EQ(JSTaggedValue::True(), keyFlag);
318    }
319
320    // test values
321    callInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
322    callInfo1->SetFunction(JSTaggedValue::Undefined());
323    callInfo1->SetThis(tMap.GetTaggedValue());
324    prev = TestHelper::SetupFrame(thread, callInfo1);
325    JSHandle<JSTaggedValue> iterValues(thread, ContainersHashMap::Values(callInfo1));
326    TestHelper::TearDownFrame(thread, prev);
327    EXPECT_TRUE(iterValues->IsJSAPIHashMapIterator());
328
329    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
330        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
331        callInfo->SetFunction(JSTaggedValue::Undefined());
332        callInfo->SetThis(iterValues.GetTaggedValue());
333
334        [[maybe_unused]] auto prev2 = TestHelper::SetupFrame(thread, callInfo);
335        result.Update(JSAPIHashMapIterator::Next(callInfo));
336        TestHelper::TearDownFrame(thread, prev2);
337        JSHandle<JSTaggedValue> iterValue = JSIterator::IteratorValue(thread, result);
338        JSTaggedValue valueFlag = JSAPIHashMap::HasValue(thread, tMap, iterValue);
339        EXPECT_EQ(JSTaggedValue::True(), valueFlag);
340    }
341
342    // test add string
343    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
344    JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
345    JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
346    std::string myKey("mykey");
347    std::string myValue("myvalue");
348    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
349        std::string iKey = myKey + std::to_string(i);
350        std::string iValue = myValue + std::to_string(i);
351        key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
352        value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
353
354        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
355        callInfo->SetFunction(JSTaggedValue::Undefined());
356        callInfo->SetThis(tMap.GetTaggedValue());
357        callInfo->SetCallArg(0, key.GetTaggedValue());
358        callInfo->SetCallArg(1, value.GetTaggedValue());
359        [[maybe_unused]] auto prev3 = TestHelper::SetupFrame(thread, callInfo);
360        JSTaggedValue result1 = ContainersHashMap::Set(callInfo);
361        TestHelper::TearDownFrame(thread, prev3);
362        EXPECT_TRUE(result1.IsJSAPIHashMap());
363        EXPECT_EQ(JSAPIHashMap::Cast(result1.GetTaggedObject())->GetSize(), NODE_NUMBERS + i + 1);
364    }
365    EXPECT_EQ(tMap->GetSize(), NODE_NUMBERS * 2);
366    // test keys after add
367    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
368        std::string iKey = myKey + std::to_string(i);
369        key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
370        JSTaggedValue keyFlag = tMap->HasKey(thread, key.GetTaggedValue());
371        EXPECT_EQ(JSTaggedValue::True(), keyFlag);
372    }
373    // test values after add
374    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
375        std::string iValue = myValue + std::to_string(i);
376        value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
377        JSTaggedValue valueFlag = JSAPIHashMap::HasValue(thread, tMap, value);
378        EXPECT_EQ(JSTaggedValue::True(), valueFlag);
379    }
380
381    // test entries
382    {
383        auto callInfo2 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
384        callInfo2->SetFunction(JSTaggedValue::Undefined());
385        callInfo2->SetThis(tMap.GetTaggedValue());
386        [[maybe_unused]] auto prev6 = TestHelper::SetupFrame(thread, callInfo2);
387        JSHandle<JSTaggedValue> iter(thread, ContainersHashMap::Entries(callInfo2));
388        TestHelper::TearDownFrame(thread, prev6);
389        EXPECT_TRUE(iter->IsJSAPIHashMapIterator());
390
391        JSHandle<JSTaggedValue> first(thread, JSTaggedValue(0));
392        JSHandle<JSTaggedValue> second(thread, JSTaggedValue(1));
393        JSMutableHandle<JSTaggedValue> result3(thread, JSTaggedValue::Undefined());
394        JSMutableHandle<JSTaggedValue> entries(thread, JSTaggedValue::Undefined());
395        for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
396            auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
397            callInfo->SetFunction(JSTaggedValue::Undefined());
398            callInfo->SetThis(iter.GetTaggedValue());
399
400            [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, callInfo);
401            result3.Update(JSAPIHashMapIterator::Next(callInfo));
402            TestHelper::TearDownFrame(thread, prev1);
403            entries.Update(JSIterator::IteratorValue(thread, result3).GetTaggedValue());
404            JSHandle<JSTaggedValue> iterKey = JSObject::GetProperty(thread, entries, first).GetValue();
405            JSTaggedValue keyFlag = tMap->HasKey(thread, iterKey.GetTaggedValue());
406            EXPECT_EQ(JSTaggedValue::True(), keyFlag);
407            JSHandle<JSTaggedValue> iterValue = JSObject::GetProperty(thread, entries, second).GetValue();
408            JSTaggedValue valueFlag = JSAPIHashMap::HasValue(thread, tMap, iterValue);
409            EXPECT_EQ(JSTaggedValue::True(), valueFlag);
410        }
411
412        for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
413            std::string iKey = myKey + std::to_string(i);
414            std::string iValue = myValue + std::to_string(i);
415            key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
416            value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
417            JSTaggedValue keyFlag = tMap->HasKey(thread, key.GetTaggedValue());
418            EXPECT_EQ(JSTaggedValue::True(), keyFlag);
419            JSTaggedValue valueFlag = JSAPIHashMap::HasValue(thread, tMap, value);
420            EXPECT_EQ(JSTaggedValue::True(), valueFlag);
421        }
422    }
423}
424
425// hashmap.remove(key)
426HWTEST_F_L0(ContainersHashMapTest, Remove)
427{
428    constexpr uint32_t NODE_NUMBERS = 8;
429    JSHandle<JSAPIHashMap> tMap = CreateJSAPIHashMap();
430    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
431        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
432        callInfo->SetFunction(JSTaggedValue::Undefined());
433        callInfo->SetThis(tMap.GetTaggedValue());
434        callInfo->SetCallArg(0, JSTaggedValue(i));
435        callInfo->SetCallArg(1, JSTaggedValue(i));
436
437        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
438        JSTaggedValue result = ContainersHashMap::Set(callInfo);
439        TestHelper::TearDownFrame(thread, prev);
440        EXPECT_TRUE(result.IsJSAPIHashMap());
441        EXPECT_EQ(JSAPIHashMap::Cast(result.GetTaggedObject())->GetSize(), i + 1);
442    }
443
444    {
445        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
446        callInfo->SetFunction(JSTaggedValue::Undefined());
447        callInfo->SetThis(tMap.GetTaggedValue());
448        callInfo->SetCallArg(0, JSTaggedValue(NODE_NUMBERS / 2));
449
450        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
451        JSTaggedValue rValue = ContainersHashMap::Remove(callInfo);
452        TestHelper::TearDownFrame(thread, prev);
453        EXPECT_EQ(rValue, JSTaggedValue(NODE_NUMBERS / 2));
454        EXPECT_EQ(tMap->GetSize(), NODE_NUMBERS - 1);
455    }
456
457    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
458        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
459        callInfo->SetFunction(JSTaggedValue::Undefined());
460        callInfo->SetThis(tMap.GetTaggedValue());
461        callInfo->SetCallArg(0, JSTaggedValue(i));
462
463        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
464        JSTaggedValue result = ContainersHashMap::Get(callInfo);
465        TestHelper::TearDownFrame(thread, prev);
466        if (i == (NODE_NUMBERS / 2)) {
467            EXPECT_EQ(result, JSTaggedValue::Undefined());
468        } else {
469            EXPECT_EQ(result, JSTaggedValue(i));
470        }
471    }
472
473    // test add string
474    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
475    JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
476    JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
477    std::string myKey("mykey");
478    std::string myValue("myvalue");
479    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
480        std::string iKey = myKey + std::to_string(i);
481        std::string iValue = myValue + std::to_string(i);
482        key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
483        value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
484
485        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
486        callInfo->SetFunction(JSTaggedValue::Undefined());
487        callInfo->SetThis(tMap.GetTaggedValue());
488        callInfo->SetCallArg(0, key.GetTaggedValue());
489        callInfo->SetCallArg(1, value.GetTaggedValue());
490        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
491        JSTaggedValue result = ContainersHashMap::Set(callInfo);
492        TestHelper::TearDownFrame(thread, prev);
493        EXPECT_TRUE(result.IsJSAPIHashMap());
494        EXPECT_EQ(JSAPIHashMap::Cast(result.GetTaggedObject())->GetSize(), NODE_NUMBERS + i);
495    }
496
497    {
498        std::string iKey = myKey + std::to_string(NODE_NUMBERS / 2);
499        key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
500        std::string iValue = myValue + std::to_string(NODE_NUMBERS / 2);
501        value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
502        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
503        callInfo->SetFunction(JSTaggedValue::Undefined());
504        callInfo->SetThis(tMap.GetTaggedValue());
505        callInfo->SetCallArg(0, key.GetTaggedValue());
506
507        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
508        JSTaggedValue rValue = ContainersHashMap::Remove(callInfo);
509        TestHelper::TearDownFrame(thread, prev);
510        EXPECT_TRUE(JSTaggedValue::SameValue(rValue, value.GetTaggedValue()));
511        EXPECT_EQ(tMap->GetSize(), NODE_NUMBERS * 2 - 2);
512    }
513}
514
515// hashmap.setAll(map)
516HWTEST_F_L0(ContainersHashMapTest, SetAll)
517{
518    constexpr uint32_t NODE_NUMBERS = 8;
519    JSHandle<JSAPIHashMap> sMap = CreateJSAPIHashMap();
520    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
521        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
522        callInfo->SetFunction(JSTaggedValue::Undefined());
523        callInfo->SetThis(sMap.GetTaggedValue());
524        callInfo->SetCallArg(0, JSTaggedValue(i));
525        callInfo->SetCallArg(1, JSTaggedValue(i));
526
527        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
528        JSTaggedValue result = ContainersHashMap::Set(callInfo);
529        TestHelper::TearDownFrame(thread, prev);
530        EXPECT_TRUE(result.IsJSAPIHashMap());
531        EXPECT_EQ(JSAPIHashMap::Cast(result.GetTaggedObject())->GetSize(), i + 1);
532    }
533
534    JSHandle<JSAPIHashMap> dMap = CreateJSAPIHashMap();
535    {
536        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
537        callInfo->SetFunction(JSTaggedValue::Undefined());
538        callInfo->SetThis(dMap.GetTaggedValue());
539        callInfo->SetCallArg(0, sMap.GetTaggedValue());
540
541        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
542        ContainersHashMap::SetAll(callInfo);
543        TestHelper::TearDownFrame(thread, prev);
544        EXPECT_EQ(dMap->GetSize(), NODE_NUMBERS);
545    }
546    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
547        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
548        callInfo->SetFunction(JSTaggedValue::Undefined());
549        callInfo->SetThis(dMap.GetTaggedValue());
550        callInfo->SetCallArg(0, JSTaggedValue(i));
551
552        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
553        JSTaggedValue result = ContainersHashMap::Get(callInfo);
554        TestHelper::TearDownFrame(thread, prev);
555        EXPECT_EQ(result, JSTaggedValue(i));
556    }
557
558    // test add string
559    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
560    JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
561    JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
562    std::string myKey("mykey");
563    std::string myValue("myvalue");
564    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
565        std::string iKey = myKey + std::to_string(i);
566        std::string iValue = myValue + std::to_string(i);
567        key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
568        value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
569
570        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
571        callInfo->SetFunction(JSTaggedValue::Undefined());
572        callInfo->SetThis(sMap.GetTaggedValue());
573        callInfo->SetCallArg(0, key.GetTaggedValue());
574        callInfo->SetCallArg(1, value.GetTaggedValue());
575        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
576        JSTaggedValue result = ContainersHashMap::Set(callInfo);
577        TestHelper::TearDownFrame(thread, prev);
578        EXPECT_TRUE(result.IsJSAPIHashMap());
579        EXPECT_EQ(JSAPIHashMap::Cast(result.GetTaggedObject())->GetSize(), NODE_NUMBERS + i + 1);
580    }
581    {
582        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
583        callInfo->SetFunction(JSTaggedValue::Undefined());
584        callInfo->SetThis(dMap.GetTaggedValue());
585        callInfo->SetCallArg(0, sMap.GetTaggedValue());
586
587        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
588        ContainersHashMap::SetAll(callInfo);
589        TestHelper::TearDownFrame(thread, prev);
590        EXPECT_EQ(dMap->GetSize(), NODE_NUMBERS * 2);
591    }
592    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
593        std::string iKey = myKey + std::to_string(i);
594        key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
595        std::string iValue = myValue + std::to_string(i);
596        value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
597        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
598        callInfo->SetFunction(JSTaggedValue::Undefined());
599        callInfo->SetThis(dMap.GetTaggedValue());
600        callInfo->SetCallArg(0, key.GetTaggedValue());
601
602        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
603        JSTaggedValue result = ContainersHashMap::Get(callInfo);
604        TestHelper::TearDownFrame(thread, prev);
605        EXPECT_TRUE(JSTaggedValue::SameValue(result, value.GetTaggedValue()));
606    }
607    EXPECT_EQ(dMap->GetSize(), 2 * NODE_NUMBERS);
608}
609
610// hashmap.clear()
611HWTEST_F_L0(ContainersHashMapTest, Clear)
612{
613    constexpr uint32_t NODE_NUMBERS = 8;
614    JSHandle<JSAPIHashMap> tMap = CreateJSAPIHashMap();
615    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
616        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
617        callInfo->SetFunction(JSTaggedValue::Undefined());
618        callInfo->SetThis(tMap.GetTaggedValue());
619        callInfo->SetCallArg(0, JSTaggedValue(i));
620        callInfo->SetCallArg(1, JSTaggedValue(i));
621
622        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
623        JSTaggedValue result = ContainersHashMap::Set(callInfo);
624        TestHelper::TearDownFrame(thread, prev);
625        EXPECT_TRUE(result.IsJSAPIHashMap());
626        EXPECT_EQ(JSAPIHashMap::Cast(result.GetTaggedObject())->GetSize(), i + 1);
627    }
628
629    // test clear
630    {
631        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
632        callInfo->SetFunction(JSTaggedValue::Undefined());
633        callInfo->SetThis(tMap.GetTaggedValue());
634
635        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
636        ContainersHashMap::Clear(callInfo);
637        TestHelper::TearDownFrame(thread, prev);
638        EXPECT_EQ(tMap->GetSize(), (uint32_t)0);
639    }
640    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
641        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
642        callInfo->SetFunction(JSTaggedValue::Undefined());
643        callInfo->SetThis(tMap.GetTaggedValue());
644        callInfo->SetCallArg(0, JSTaggedValue(i));
645
646        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
647        JSTaggedValue result = ContainersHashMap::Get(callInfo);
648        TestHelper::TearDownFrame(thread, prev);
649        EXPECT_EQ(result, JSTaggedValue::Undefined());
650    }
651
652    // test add string
653    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
654    JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
655    JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
656    std::string myKey("mykey");
657    std::string myValue("myvalue");
658    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
659        std::string iKey = myKey + std::to_string(i);
660        std::string iValue = myValue + std::to_string(i);
661        key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
662        value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
663
664        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
665        callInfo->SetFunction(JSTaggedValue::Undefined());
666        callInfo->SetThis(tMap.GetTaggedValue());
667        callInfo->SetCallArg(0, key.GetTaggedValue());
668        callInfo->SetCallArg(1, value.GetTaggedValue());
669        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
670        JSTaggedValue result = ContainersHashMap::Set(callInfo);
671        TestHelper::TearDownFrame(thread, prev);
672        EXPECT_TRUE(result.IsJSAPIHashMap());
673        EXPECT_EQ(JSAPIHashMap::Cast(result.GetTaggedObject())->GetSize(), i + 1);
674    }
675
676    // test clear
677    {
678        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
679        callInfo->SetFunction(JSTaggedValue::Undefined());
680        callInfo->SetThis(tMap.GetTaggedValue());
681
682        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
683        ContainersHashMap::Clear(callInfo);
684        TestHelper::TearDownFrame(thread, prev);
685        EXPECT_EQ(tMap->GetSize(), (uint32_t)0);
686    }
687    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
688        std::string iKey = myKey + std::to_string(i);
689        key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
690        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
691        callInfo->SetFunction(JSTaggedValue::Undefined());
692        callInfo->SetThis(tMap.GetTaggedValue());
693        callInfo->SetCallArg(0, key.GetTaggedValue());
694
695        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
696        JSTaggedValue result = ContainersHashMap::Get(callInfo);
697        TestHelper::TearDownFrame(thread, prev);
698        EXPECT_EQ(result, JSTaggedValue::Undefined());
699    }
700}
701
702// hashmap.replace(key, value)
703HWTEST_F_L0(ContainersHashMapTest, Replace)
704{
705    constexpr uint32_t NODE_NUMBERS = 8;
706    JSHandle<JSAPIHashMap> tMap = CreateJSAPIHashMap();
707    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
708        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
709        callInfo->SetFunction(JSTaggedValue::Undefined());
710        callInfo->SetThis(tMap.GetTaggedValue());
711        callInfo->SetCallArg(0, JSTaggedValue(i));
712        callInfo->SetCallArg(1, JSTaggedValue(i));
713
714        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
715        JSTaggedValue result = ContainersHashMap::Set(callInfo);
716        TestHelper::TearDownFrame(thread, prev);
717        EXPECT_TRUE(result.IsJSAPIHashMap());
718        EXPECT_EQ(JSAPIHashMap::Cast(result.GetTaggedObject())->GetSize(), i + 1);
719    }
720
721    {
722        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
723        callInfo->SetFunction(JSTaggedValue::Undefined());
724        callInfo->SetThis(tMap.GetTaggedValue());
725        callInfo->SetCallArg(0, JSTaggedValue(NODE_NUMBERS / 2));
726        callInfo->SetCallArg(1, JSTaggedValue(NODE_NUMBERS));
727
728        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
729        JSTaggedValue result = ContainersHashMap::Replace(callInfo);
730        TestHelper::TearDownFrame(thread, prev);
731        EXPECT_EQ(result, JSTaggedValue::True());
732        EXPECT_EQ(tMap->GetSize(), NODE_NUMBERS);
733    }
734    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
735        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
736        callInfo->SetFunction(JSTaggedValue::Undefined());
737        callInfo->SetThis(tMap.GetTaggedValue());
738        callInfo->SetCallArg(0, JSTaggedValue(i));
739
740        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
741        JSTaggedValue result = ContainersHashMap::Get(callInfo);
742        TestHelper::TearDownFrame(thread, prev);
743        if (i == (NODE_NUMBERS / 2)) {
744            EXPECT_EQ(result, JSTaggedValue(NODE_NUMBERS));
745        } else {
746            EXPECT_EQ(result, JSTaggedValue(i));
747        }
748    }
749
750    // test add string
751    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
752    JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
753    JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
754    std::string myKey("mykey");
755    std::string myValue("myvalue");
756    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
757        std::string iKey = myKey + std::to_string(i);
758        std::string iValue = myValue + std::to_string(i);
759        key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
760        value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
761
762        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
763        callInfo->SetFunction(JSTaggedValue::Undefined());
764        callInfo->SetThis(tMap.GetTaggedValue());
765        callInfo->SetCallArg(0, key.GetTaggedValue());
766        callInfo->SetCallArg(1, value.GetTaggedValue());
767        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
768        JSTaggedValue result = ContainersHashMap::Set(callInfo);
769        TestHelper::TearDownFrame(thread, prev);
770        EXPECT_TRUE(result.IsJSAPIHashMap());
771        EXPECT_EQ(JSAPIHashMap::Cast(result.GetTaggedObject())->GetSize(), NODE_NUMBERS + i + 1);
772    }
773
774    {
775        std::string iKey = myKey + std::to_string(NODE_NUMBERS / 2);
776        std::string iValue = myValue + std::to_string(NODE_NUMBERS);
777        key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
778        value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
779        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
780        callInfo->SetFunction(JSTaggedValue::Undefined());
781        callInfo->SetThis(tMap.GetTaggedValue());
782        callInfo->SetCallArg(0, key.GetTaggedValue());
783        callInfo->SetCallArg(1, value.GetTaggedValue());
784
785        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
786        JSTaggedValue result = ContainersHashMap::Replace(callInfo);
787        TestHelper::TearDownFrame(thread, prev);
788        EXPECT_EQ(result, JSTaggedValue::True());
789        EXPECT_EQ(tMap->GetSize(), NODE_NUMBERS * 2);
790    }
791    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
792        std::string iKey = myKey + std::to_string(i);
793        key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
794        std::string iValue;
795        if (i == (NODE_NUMBERS / 2)) {
796            iValue = myValue + std::to_string(NODE_NUMBERS);
797        } else {
798            iValue = myValue + std::to_string(i);
799        }
800        value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
801        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
802        callInfo->SetFunction(JSTaggedValue::Undefined());
803        callInfo->SetThis(tMap.GetTaggedValue());
804        callInfo->SetCallArg(0, key.GetTaggedValue());
805
806        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
807        JSTaggedValue result = ContainersHashMap::Get(callInfo);
808        TestHelper::TearDownFrame(thread, prev);
809        EXPECT_TRUE(JSTaggedValue::SameValue(result, value.GetTaggedValue()));
810    }
811}
812
813// hashmap.ForEach(callbackfn, this)
814HWTEST_F_L0(ContainersHashMapTest, ForEach)
815{
816    constexpr uint32_t NODE_NUMBERS = 8;
817    JSHandle<JSAPIHashMap> tMap = CreateJSAPIHashMap();
818    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
819        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
820        callInfo->SetFunction(JSTaggedValue::Undefined());
821        callInfo->SetThis(tMap.GetTaggedValue());
822        callInfo->SetCallArg(0, JSTaggedValue(i));
823        callInfo->SetCallArg(1, JSTaggedValue(i));
824
825        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
826        JSTaggedValue result = ContainersHashMap::Set(callInfo);
827        TestHelper::TearDownFrame(thread, prev);
828        EXPECT_TRUE(result.IsJSAPIHashMap());
829        EXPECT_EQ(JSAPIHashMap::Cast(result.GetTaggedObject())->GetSize(), i + 1);
830    }
831    // test foreach function with TestForEachFunc;
832    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
833    JSHandle<JSAPIHashMap> dMap = CreateJSAPIHashMap();
834    {
835        JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
836        JSHandle<JSFunction> func = factory->NewJSFunction(env, reinterpret_cast<void *>(TestClass::TestForEachFunc));
837        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
838        callInfo->SetFunction(JSTaggedValue::Undefined());
839        callInfo->SetThis(tMap.GetTaggedValue());
840        callInfo->SetCallArg(0, func.GetTaggedValue());
841        callInfo->SetCallArg(1, dMap.GetTaggedValue());
842
843        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
844        ContainersHashMap::ForEach(callInfo);
845        TestHelper::TearDownFrame(thread, prev);
846    }
847    EXPECT_EQ(dMap->GetSize(), NODE_NUMBERS);
848    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
849        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
850        callInfo->SetFunction(JSTaggedValue::Undefined());
851        callInfo->SetThis(tMap.GetTaggedValue());
852        callInfo->SetCallArg(0, JSTaggedValue(i));
853
854        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
855        JSTaggedValue result = ContainersHashMap::Get(callInfo);
856        TestHelper::TearDownFrame(thread, prev);
857        EXPECT_EQ(result, JSTaggedValue(i * 2));
858    }
859
860    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
861        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
862        callInfo->SetFunction(JSTaggedValue::Undefined());
863        callInfo->SetThis(dMap.GetTaggedValue());
864        callInfo->SetCallArg(0, JSTaggedValue(i));
865
866        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
867        JSTaggedValue result = ContainersHashMap::Get(callInfo);
868        TestHelper::TearDownFrame(thread, prev);
869        EXPECT_EQ(result, JSTaggedValue(i));
870    }
871
872    // test add string
873    JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
874    JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
875    std::string myKey("mykey");
876    std::string myValue("myvalue");
877    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
878        std::string iKey = myKey + std::to_string(i);
879        std::string iValue = myValue + std::to_string(i);
880        key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
881        value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
882
883        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
884        callInfo->SetFunction(JSTaggedValue::Undefined());
885        callInfo->SetThis(tMap.GetTaggedValue());
886        callInfo->SetCallArg(0, key.GetTaggedValue());
887        callInfo->SetCallArg(1, value.GetTaggedValue());
888        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
889        JSTaggedValue result = ContainersHashMap::Set(callInfo);
890        TestHelper::TearDownFrame(thread, prev);
891        EXPECT_TRUE(result.IsJSAPIHashMap());
892        EXPECT_EQ(JSAPIHashMap::Cast(result.GetTaggedObject())->GetSize(), NODE_NUMBERS + i + 1);
893    }
894    EXPECT_EQ(tMap->GetSize(), NODE_NUMBERS * 2);
895    EXPECT_EQ(dMap->GetSize(), NODE_NUMBERS);
896
897    // test foreach function with TestForEachFunc;
898    {
899        JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
900        JSHandle<JSFunction> func = factory->NewJSFunction(env, reinterpret_cast<void *>(TestClass::TestForEachFunc));
901        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
902        callInfo->SetFunction(JSTaggedValue::Undefined());
903        callInfo->SetThis(tMap.GetTaggedValue());
904        callInfo->SetCallArg(0, func.GetTaggedValue());
905        callInfo->SetCallArg(1, dMap.GetTaggedValue());
906        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
907        ContainersHashMap::ForEach(callInfo);
908        TestHelper::TearDownFrame(thread, prev);
909    }
910
911    EXPECT_EQ(dMap->GetSize(), NODE_NUMBERS * 2);
912    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
913        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
914        callInfo->SetFunction(JSTaggedValue::Undefined());
915        callInfo->SetThis(tMap.GetTaggedValue());
916        callInfo->SetCallArg(0, JSTaggedValue(i));
917
918        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
919        JSTaggedValue result = ContainersHashMap::Get(callInfo);
920        TestHelper::TearDownFrame(thread, prev);
921        EXPECT_EQ(result, JSTaggedValue(i * 4)); // 4 means 4 times
922    }
923
924    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
925        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
926        callInfo->SetFunction(JSTaggedValue::Undefined());
927        callInfo->SetThis(dMap.GetTaggedValue());
928        callInfo->SetCallArg(0, JSTaggedValue(i));
929
930        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
931        JSTaggedValue result = ContainersHashMap::Get(callInfo);
932        TestHelper::TearDownFrame(thread, prev);
933        EXPECT_EQ(result, JSTaggedValue(i * 2));
934    }
935
936    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
937        std::string iKey = myKey + std::to_string(i);
938        std::string iValue = myValue + std::to_string(i);
939        key.Update(factory->NewFromStdString(iKey).GetTaggedValue());
940        value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
941
942        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
943        callInfo->SetFunction(JSTaggedValue::Undefined());
944        callInfo->SetThis(dMap.GetTaggedValue());
945        callInfo->SetCallArg(0, key.GetTaggedValue());
946
947        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
948        JSTaggedValue result = ContainersHashMap::Get(callInfo);
949        TestHelper::TearDownFrame(thread, prev);
950        EXPECT_EQ(result, value.GetTaggedValue());
951    }
952}
953
954HWTEST_F_L0(ContainersHashMapTest, ProxyOfGetLength)
955{
956    constexpr uint32_t NODE_NUMBERS = 8;
957    JSHandle<JSAPIHashMap> treeMap = CreateJSAPIHashMap();
958    auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
959    callInfo->SetFunction(JSTaggedValue::Undefined());
960    JSHandle<JSProxy> proxy = CreateJSProxyHandle(thread);
961    proxy->SetTarget(thread, treeMap.GetTaggedValue());
962    callInfo->SetThis(proxy.GetTaggedValue());
963
964    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
965        callInfo->SetCallArg(0, JSTaggedValue(i));
966        callInfo->SetCallArg(1, JSTaggedValue(i + 1));
967        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
968        ContainersHashMap::Set(callInfo);
969        TestHelper::TearDownFrame(thread, prev);
970
971        [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, callInfo);
972        JSTaggedValue retult = ContainersHashMap::GetLength(callInfo);
973        TestHelper::TearDownFrame(thread, prev1);
974        EXPECT_EQ(retult, JSTaggedValue(i + 1));
975    }
976}
977
978HWTEST_F_L0(ContainersHashMapTest, ExceptionReturn)
979{
980    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersHashMap, SetAll);
981    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersHashMap, Keys);
982    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersHashMap, Values);
983    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersHashMap, Entries);
984    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersHashMap, ForEach);
985    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersHashMap, Set);
986    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersHashMap, Get);
987    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersHashMap, Remove);
988    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersHashMap, HasKey);
989    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersHashMap, HasValue);
990    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersHashMap, Replace);
991    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersHashMap, Clear);
992    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersHashMap, GetLength);
993
994    JSHandle<JSAPIHashMap> treeMap = CreateJSAPIHashMap();
995    {
996        auto callInfo = NewEmptyCallInfo(thread);
997        callInfo->SetThis(treeMap.GetTaggedValue());
998        CONTAINERS_API_EXCEPTION_TEST(ContainersHashMap, SetAll, callInfo);
999    }
1000}
1001} // namespace panda::test
1002