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/js_api/js_api_lightweightset.h"
17
18#include "ecmascript/containers/containers_lightweightset.h"
19#include "ecmascript/containers/containers_private.h"
20#include "ecmascript/ecma_runtime_call_info.h"
21#include "ecmascript/global_env.h"
22
23#include "ecmascript/js_api/js_api_lightweightset_iterator.h"
24#include "ecmascript/js_handle.h"
25#include "ecmascript/js_tagged_value-inl.h"
26#include "ecmascript/js_thread.h"
27#include "ecmascript/object_factory.h"
28#include "ecmascript/tests/test_helper.h"
29#include "ecmascript/containers/tests/containers_test_helper.h"
30
31using namespace panda::ecmascript;
32using namespace panda::ecmascript::containers;
33
34namespace panda::test {
35class ContainersLightWeightSetTest : public testing::Test {
36public:
37    static void SetUpTestCase()
38    {
39        GTEST_LOG_(INFO) << "SetUpTestCase";
40    }
41
42    static void TearDownTestCase()
43    {
44        GTEST_LOG_(INFO) << "TearDownCase";
45    }
46
47    void SetUp() override
48    {
49        TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
50    }
51
52    void TearDown() override
53    {
54        TestHelper::DestroyEcmaVMWithScope(instance, scope);
55    }
56
57    EcmaVM *instance {nullptr};
58    EcmaHandleScope *scope {nullptr};
59    JSThread *thread {nullptr};
60
61    class TestClass : public base::BuiltinsBase {
62    public:
63        static JSTaggedValue TestForEachFunc(EcmaRuntimeCallInfo *argv)
64        {
65            JSThread *thread = argv->GetThread();
66            JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);    // 0 means the first argument vector
67            JSHandle<JSAPILightWeightSet> jSAPILightWeightSet(GetThis(argv));
68            JSAPILightWeightSet::Add(thread, jSAPILightWeightSet, value);
69            return JSTaggedValue::Undefined();
70        }
71    };
72protected:
73    JSTaggedValue InitializeLightWeightSetConstructor()
74    {
75        ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
76        JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
77        JSHandle<JSTaggedValue> globalObject = env->GetJSGlobalObject();
78        JSHandle<JSTaggedValue> key(factory->NewFromASCII("ArkPrivate"));
79        JSHandle<JSTaggedValue> value =
80            JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(globalObject), key).GetValue();
81        auto objCallInfo =
82            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); // 6 means the value
83        objCallInfo->SetFunction(JSTaggedValue::Undefined());
84        objCallInfo->SetThis(value.GetTaggedValue());
85        objCallInfo->SetCallArg(
86            0, JSTaggedValue(static_cast<int>(ContainerTag::LightWeightSet))); // 0 means the argument
87        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
88        JSTaggedValue result = ContainersPrivate::Load(objCallInfo);
89        TestHelper::TearDownFrame(thread, prev);
90
91        return result;
92    }
93
94    JSHandle<JSAPILightWeightSet> CreateJSAPILightWeightSet()
95    {
96        JSHandle<JSFunction> newTarget(thread, InitializeLightWeightSetConstructor());
97        auto objCallInfo =
98            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); // 4 means the value
99        objCallInfo->SetFunction(newTarget.GetTaggedValue());
100        objCallInfo->SetNewTarget(newTarget.GetTaggedValue());
101        objCallInfo->SetThis(JSTaggedValue::Undefined());
102
103        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
104        JSTaggedValue result = ContainersLightWeightSet::LightWeightSetConstructor(objCallInfo);
105        TestHelper::TearDownFrame(thread, prev);
106        JSHandle<JSAPILightWeightSet> map(thread, result);
107        return map;
108    }
109};
110
111HWTEST_F_L0(ContainersLightWeightSetTest, LightWeightSetConstructor)
112{
113    InitializeLightWeightSetConstructor();
114    JSHandle<JSFunction> newTarget(thread, InitializeLightWeightSetConstructor());
115    auto objCallInfo =
116        TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);   // 4 means the value
117    objCallInfo->SetFunction(newTarget.GetTaggedValue());
118    objCallInfo->SetNewTarget(newTarget.GetTaggedValue());
119    objCallInfo->SetThis(JSTaggedValue::Undefined());
120
121    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
122    JSTaggedValue result = ContainersLightWeightSet::LightWeightSetConstructor(objCallInfo);
123    TestHelper::TearDownFrame(thread, prev);
124
125    ASSERT_TRUE(result.IsJSAPILightWeightSet());
126    JSHandle<JSAPILightWeightSet> mapHandle(thread, result);
127    JSTaggedValue resultProto = JSObject::GetPrototype(JSHandle<JSObject>::Cast(mapHandle));
128    JSTaggedValue funcProto = newTarget->GetFunctionPrototype();
129    ASSERT_EQ(resultProto, funcProto);
130    int length = mapHandle->GetLength();
131    ASSERT_EQ(length, 0);   // 0 means the value
132
133    // test LightWeightSetConstructor exception
134    objCallInfo->SetNewTarget(JSTaggedValue::Undefined());
135    CONTAINERS_API_EXCEPTION_TEST(ContainersLightWeightSet, LightWeightSetConstructor, objCallInfo);
136}
137
138HWTEST_F_L0(ContainersLightWeightSetTest, AddAndGetValueAt)
139{
140    constexpr uint32_t NODE_NUMBERS = 8;    // 8 means the value
141    JSHandle<JSAPILightWeightSet> lightWeightSet = CreateJSAPILightWeightSet();
142    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
143        auto callInfo =
144            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);   // 6 means the value
145        callInfo->SetFunction(JSTaggedValue::Undefined());
146        callInfo->SetThis(lightWeightSet.GetTaggedValue());
147        callInfo->SetCallArg(0, JSTaggedValue(i + 1));
148
149        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
150        JSTaggedValue result = ContainersLightWeightSet::Add(callInfo);
151        EXPECT_TRUE(JSTaggedValue::Equal(thread, JSHandle<JSTaggedValue>(thread, result),
152                    JSHandle<JSTaggedValue>(thread, JSTaggedValue::True())));
153        TestHelper::TearDownFrame(thread, prev);
154        int length = lightWeightSet->GetLength();
155        EXPECT_EQ(length, static_cast<int>(i + 1));
156    }
157
158    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
159    JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
160    std::string myValue("myvalue");
161    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
162        std::string ivalue = myValue + std::to_string(i);
163        value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
164        auto callInfo =
165            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); // 6 means the value
166        callInfo->SetFunction(JSTaggedValue::Undefined());
167        callInfo->SetThis(lightWeightSet.GetTaggedValue());
168        callInfo->SetCallArg(0, value.GetTaggedValue());
169        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
170        JSTaggedValue result = ContainersLightWeightSet::Add(callInfo);
171        TestHelper::TearDownFrame(thread, prev);
172        int length = lightWeightSet->GetLength();
173        EXPECT_TRUE(JSTaggedValue::Equal(thread, JSHandle<JSTaggedValue>(thread, result),
174                                         JSHandle<JSTaggedValue>(thread, JSTaggedValue::True())));
175        EXPECT_EQ(length, static_cast<int>(NODE_NUMBERS + 1 + i));
176    }
177}
178
179HWTEST_F_L0(ContainersLightWeightSetTest, AddAll)
180{
181    constexpr uint32_t NODE_NUMBERS = 8;    // 8 means the value
182    JSHandle<JSAPILightWeightSet> lightWeightSet = CreateJSAPILightWeightSet();
183    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
184        auto callInfo =
185            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);   // 6 means the value
186        callInfo->SetFunction(JSTaggedValue::Undefined());
187        callInfo->SetThis(lightWeightSet.GetTaggedValue());
188        callInfo->SetCallArg(0, JSTaggedValue(i + 1));
189
190        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
191        JSTaggedValue result = ContainersLightWeightSet::Add(callInfo);
192        EXPECT_TRUE(JSTaggedValue::Equal(thread, JSHandle<JSTaggedValue>(thread, result),
193                                         JSHandle<JSTaggedValue>(thread, JSTaggedValue::True())));
194        TestHelper::TearDownFrame(thread, prev);
195        int length = lightWeightSet->GetLength();
196        EXPECT_EQ(length, static_cast<int>(i + 1));
197    }
198
199    JSHandle<JSAPILightWeightSet> lws = CreateJSAPILightWeightSet();
200    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
201        auto callInfo =
202            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);   // 6 means the value
203        callInfo->SetFunction(JSTaggedValue::Undefined());
204        callInfo->SetThis(lws.GetTaggedValue());
205        callInfo->SetCallArg(0, JSTaggedValue(i + 1 + 10));
206
207        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
208        JSTaggedValue result = ContainersLightWeightSet::Add(callInfo);
209        EXPECT_TRUE(JSTaggedValue::Equal(thread, JSHandle<JSTaggedValue>(thread, result),
210                    JSHandle<JSTaggedValue>(thread, JSTaggedValue::True())));
211        TestHelper::TearDownFrame(thread, prev);
212        int length = lws->GetLength();
213        EXPECT_EQ(length, static_cast<int>(i + 1));
214    }
215    // test AddAll
216    {
217        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
218        callInfo->SetFunction(JSTaggedValue::Undefined());
219        callInfo->SetThis(lightWeightSet.GetTaggedValue());
220        callInfo->SetCallArg(0, lws.GetTaggedValue());
221
222        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
223        JSTaggedValue result = ContainersLightWeightSet::AddAll(callInfo);
224        TestHelper::TearDownFrame(thread, prev);
225        int length = lightWeightSet->GetLength();
226        EXPECT_EQ(length, static_cast<int>(NODE_NUMBERS * 2));
227        EXPECT_TRUE(JSTaggedValue::Equal(thread, JSHandle<JSTaggedValue>(thread, result),
228                    JSHandle<JSTaggedValue>(thread, JSTaggedValue::True())));
229    }
230}
231
232HWTEST_F_L0(ContainersLightWeightSetTest, HasAllAndHas)
233{
234    constexpr uint32_t NODE_NUMBERS = 8;    // 8 means the value
235    JSHandle<JSAPILightWeightSet> lightWeightSet = CreateJSAPILightWeightSet();
236    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
237        auto callInfo =
238            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);   // 6 means the value
239        callInfo->SetFunction(JSTaggedValue::Undefined());
240        callInfo->SetThis(lightWeightSet.GetTaggedValue());
241        callInfo->SetCallArg(0, JSTaggedValue(i + 1));
242
243        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
244        JSTaggedValue result = ContainersLightWeightSet::Add(callInfo);
245        EXPECT_TRUE(JSTaggedValue::Equal(thread, JSHandle<JSTaggedValue>(thread, result),
246                                         JSHandle<JSTaggedValue>(thread, JSTaggedValue::True())));
247        TestHelper::TearDownFrame(thread, prev);
248        int length = lightWeightSet->GetLength();
249        EXPECT_EQ(length, static_cast<int>(i + 1));
250    }
251
252    JSHandle<JSAPILightWeightSet> lws = CreateJSAPILightWeightSet();
253    for (uint32_t i = 3; i < NODE_NUMBERS - 2; i++) {
254        auto callInfo =
255            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);   // 6 means the value
256        callInfo->SetFunction(JSTaggedValue::Undefined());
257        callInfo->SetThis(lws.GetTaggedValue());
258        callInfo->SetCallArg(0, JSTaggedValue(i + 1));
259
260        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
261        JSTaggedValue result = ContainersLightWeightSet::Add(callInfo);
262        EXPECT_TRUE(JSTaggedValue::Equal(thread, JSHandle<JSTaggedValue>(thread, result),
263                                         JSHandle<JSTaggedValue>(thread, JSTaggedValue::True())));
264        TestHelper::TearDownFrame(thread, prev);
265    }
266    // test HasAll true
267    {
268        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
269        callInfo->SetFunction(JSTaggedValue::Undefined());
270        callInfo->SetThis(lightWeightSet.GetTaggedValue());
271        callInfo->SetCallArg(0, lws.GetTaggedValue());
272
273        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
274        JSTaggedValue result = ContainersLightWeightSet::HasAll(callInfo);
275        TestHelper::TearDownFrame(thread, prev);
276        EXPECT_TRUE(JSTaggedValue::Equal(thread, JSHandle<JSTaggedValue>(thread, result),
277                    JSHandle<JSTaggedValue>(thread, JSTaggedValue::True())));
278    }
279    // test HasAll fales
280    JSHandle<JSAPILightWeightSet> lwsFalse = CreateJSAPILightWeightSet();
281    for (uint32_t i = 1; i < NODE_NUMBERS - 2; i++) {
282        auto callInfo =
283            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);   // 6 means the value
284        callInfo->SetFunction(JSTaggedValue::Undefined());
285        callInfo->SetThis(lwsFalse.GetTaggedValue());
286
287        if (i == 2) {
288            callInfo->SetCallArg(0, JSTaggedValue(i + 1 + 10));
289            [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
290            JSTaggedValue result = ContainersLightWeightSet::Add(callInfo);
291            EXPECT_TRUE(JSTaggedValue::Equal(thread, JSHandle<JSTaggedValue>(thread, result),
292                        JSHandle<JSTaggedValue>(thread, JSTaggedValue::True())));
293        } else {
294            callInfo->SetCallArg(0, JSTaggedValue(i + 1));
295            [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
296            JSTaggedValue result = ContainersLightWeightSet::Add(callInfo);
297            EXPECT_TRUE(JSTaggedValue::Equal(thread, JSHandle<JSTaggedValue>(thread, result),
298                        JSHandle<JSTaggedValue>(thread, JSTaggedValue::True())));
299        }
300    }
301    {
302        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
303        callInfo->SetFunction(JSTaggedValue::Undefined());
304        callInfo->SetThis(lightWeightSet.GetTaggedValue());
305        callInfo->SetCallArg(0, lwsFalse.GetTaggedValue());
306
307        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
308        JSTaggedValue result = ContainersLightWeightSet::HasAll(callInfo);
309        TestHelper::TearDownFrame(thread, prev);
310        EXPECT_TRUE(JSTaggedValue::Equal(thread, JSHandle<JSTaggedValue>(thread, result),
311                                         JSHandle<JSTaggedValue>(thread, JSTaggedValue::False())));
312    }
313    // test Has Value
314    {
315        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
316        callInfo->SetFunction(JSTaggedValue::Undefined());
317        callInfo->SetThis(lightWeightSet.GetTaggedValue());
318        callInfo->SetCallArg(0, JSTaggedValue(3));
319
320        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
321        JSTaggedValue result = ContainersLightWeightSet::Has(callInfo);
322        TestHelper::TearDownFrame(thread, prev);
323        EXPECT_TRUE(JSTaggedValue::Equal(thread, JSHandle<JSTaggedValue>(thread, result),
324                                         JSHandle<JSTaggedValue>(thread, JSTaggedValue::True())));
325    }
326}
327
328HWTEST_F_L0(ContainersLightWeightSetTest, Equal)
329{
330    constexpr uint32_t NODE_NUMBERS = 8;    // 8 means the value
331    JSHandle<JSAPILightWeightSet> lightWeightSet = CreateJSAPILightWeightSet();
332    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
333    JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
334    std::string myValue("myvalue");
335    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
336        std::string ivalue = myValue + std::to_string(i);
337        value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
338        auto callInfo =
339            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); // 6 means the value
340        callInfo->SetFunction(JSTaggedValue::Undefined());
341        callInfo->SetThis(lightWeightSet.GetTaggedValue());
342        callInfo->SetCallArg(0, value.GetTaggedValue());
343        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
344        JSTaggedValue result = ContainersLightWeightSet::Add(callInfo);
345        TestHelper::TearDownFrame(thread, prev);
346        int length = lightWeightSet->GetLength();
347        EXPECT_TRUE(JSTaggedValue::Equal(thread, JSHandle<JSTaggedValue>(thread, result),
348                    JSHandle<JSTaggedValue>(thread, JSTaggedValue::True())));
349        EXPECT_EQ(length, static_cast<int>(1 + i));
350    }
351
352    JSHandle<JSAPILightWeightSet> lws = CreateJSAPILightWeightSet();
353    JSMutableHandle<JSTaggedValue> value1(thread, JSTaggedValue::Undefined());
354    myValue = "myvalue";
355    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
356        std::string ivalue = myValue + std::to_string(i);
357        value1.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
358        auto callInfo =
359            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); // 6 means the value
360        callInfo->SetFunction(JSTaggedValue::Undefined());
361        callInfo->SetThis(lws.GetTaggedValue());
362        callInfo->SetCallArg(0, value1.GetTaggedValue());
363        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
364        JSTaggedValue result = ContainersLightWeightSet::Add(callInfo);
365        TestHelper::TearDownFrame(thread, prev);
366        int length = lws->GetLength();
367        EXPECT_TRUE(JSTaggedValue::Equal(thread, JSHandle<JSTaggedValue>(thread, result),
368                                         JSHandle<JSTaggedValue>(thread, JSTaggedValue::True())));
369        EXPECT_EQ(length, static_cast<int>(1 + i));
370    }
371    // test equal
372    {
373        auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
374        callInfo->SetFunction(JSTaggedValue::Undefined());
375        callInfo->SetThis(lightWeightSet.GetTaggedValue());
376        callInfo->SetCallArg(0, lws.GetTaggedValue());
377
378        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
379        JSTaggedValue result = ContainersLightWeightSet::HasAll(callInfo);
380        TestHelper::TearDownFrame(thread, prev);
381        EXPECT_TRUE(JSTaggedValue::Equal(thread, JSHandle<JSTaggedValue>(thread, result),
382                                         JSHandle<JSTaggedValue>(thread, JSTaggedValue::True())));
383    }
384}
385
386HWTEST_F_L0(ContainersLightWeightSetTest, HasAndValuesAndEntries)
387{
388    constexpr uint32_t NODE_NUMBERS = 8;    // 8 means the value
389    JSHandle<JSAPILightWeightSet> lightWeightSet = CreateJSAPILightWeightSet();
390    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
391        auto callInfo =
392            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);   // 4 means the value
393        callInfo->SetFunction(JSTaggedValue::Undefined());
394        callInfo->SetThis(lightWeightSet.GetTaggedValue());
395        callInfo->SetCallArg(0, JSTaggedValue(i));
396
397        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
398        JSTaggedValue result = ContainersLightWeightSet::Add(callInfo);
399        TestHelper::TearDownFrame(thread, prev);
400        int length = lightWeightSet->GetLength();
401        EXPECT_TRUE(JSTaggedValue::Equal(thread, JSHandle<JSTaggedValue>(thread, result),
402                    JSHandle<JSTaggedValue>(thread, JSTaggedValue::True())));
403        EXPECT_EQ(length, static_cast<int>(i + 1));
404    }
405
406    JSMutableHandle<JSTaggedValue> result(thread, JSTaggedValue::Undefined());
407    // test values
408    auto callInfo =
409        TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);   // 4 means the value
410    callInfo->SetFunction(JSTaggedValue::Undefined());
411    callInfo->SetThis(lightWeightSet.GetTaggedValue());
412    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
413    JSHandle<JSTaggedValue> iterValues(thread, ContainersLightWeightSet::Values(callInfo));
414    TestHelper::TearDownFrame(thread, prev);
415    EXPECT_TRUE(iterValues->IsJSAPILightWeightSetIterator());
416
417    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
418        callInfo =
419            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);   // 4 means the value
420        callInfo->SetFunction(JSTaggedValue::Undefined());
421        callInfo->SetThis(iterValues.GetTaggedValue());
422
423        prev = TestHelper::SetupFrame(thread, callInfo);
424        result.Update(JSAPILightWeightSetIterator::Next(callInfo));
425        TestHelper::TearDownFrame(thread, prev);
426        JSHandle<JSTaggedValue> ValueHandle = JSIterator::IteratorValue(thread, result);
427
428        callInfo =
429            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);   // 6 means the value
430        callInfo->SetFunction(JSTaggedValue::Undefined());
431        callInfo->SetThis(lightWeightSet.GetTaggedValue());
432        callInfo->SetCallArg(0, ValueHandle.GetTaggedValue());
433
434        prev = TestHelper::SetupFrame(thread, callInfo);
435        JSTaggedValue valueResult = ContainersLightWeightSet::Has(callInfo);
436        TestHelper::TearDownFrame(thread, prev);
437        EXPECT_EQ(valueResult, JSTaggedValue::True());
438    }
439    // test entries
440    callInfo =
441        TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);   // 4 means the value
442    callInfo->SetFunction(JSTaggedValue::Undefined());
443    callInfo->SetThis(lightWeightSet.GetTaggedValue());
444    prev = TestHelper::SetupFrame(thread, callInfo);
445    JSHandle<JSTaggedValue> iter(thread, ContainersLightWeightSet::Entries(callInfo));
446    TestHelper::TearDownFrame(thread, prev);
447    EXPECT_TRUE(iter->IsJSAPILightWeightSetIterator());
448
449    JSHandle<JSTaggedValue> first(thread, JSTaggedValue(0));    // 0 means the value
450    JSHandle<JSTaggedValue> second(thread, JSTaggedValue(1));   // 1 means the value
451    JSMutableHandle<JSTaggedValue> entries(thread, JSTaggedValue::Undefined());
452    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
453        callInfo =
454            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);   // 4 means the value
455        callInfo->SetFunction(JSTaggedValue::Undefined());
456        callInfo->SetThis(iter.GetTaggedValue());
457
458        prev = TestHelper::SetupFrame(thread, callInfo);
459        result.Update(JSAPILightWeightSetIterator::Next(callInfo));
460        TestHelper::TearDownFrame(thread, prev);
461        entries.Update(JSIterator::IteratorValue(thread, result).GetTaggedValue());
462
463        int entriesKey = JSObject::GetProperty(thread, entries, first).GetValue()->GetInt();
464        callInfo =
465            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);   // 6 means the value
466        callInfo->SetFunction(JSTaggedValue::Undefined());
467        callInfo->SetThis(lightWeightSet.GetTaggedValue());
468        callInfo->SetCallArg(0, JSTaggedValue(entriesKey));
469        prev = TestHelper::SetupFrame(thread, callInfo);
470        JSTaggedValue keyResult = ContainersLightWeightSet::HasHash(callInfo);
471        TestHelper::TearDownFrame(thread, prev);
472        EXPECT_EQ(keyResult, JSTaggedValue::True());
473
474        int entriesValue = JSObject::GetProperty(thread, entries, second).GetValue()->GetInt();
475        callInfo =
476            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);   // 6 means the value
477        callInfo->SetFunction(JSTaggedValue::Undefined());
478        callInfo->SetThis(lightWeightSet.GetTaggedValue());
479        callInfo->SetCallArg(0, JSTaggedValue(entriesValue));
480        prev = TestHelper::SetupFrame(thread, callInfo);
481        JSTaggedValue valueResult = ContainersLightWeightSet::Has(callInfo);
482        TestHelper::TearDownFrame(thread, prev);
483        EXPECT_EQ(valueResult, JSTaggedValue::True());
484    }
485}
486
487HWTEST_F_L0(ContainersLightWeightSetTest, ForEach)
488{
489    constexpr uint32_t NODE_NUMBERS = 8;    // 8 means the value
490    JSHandle<JSAPILightWeightSet> lightWeightSet = CreateJSAPILightWeightSet();
491    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
492        auto callInfo =
493            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);   // 8 means the value
494        callInfo->SetFunction(JSTaggedValue::Undefined());
495        callInfo->SetThis(lightWeightSet.GetTaggedValue());
496        callInfo->SetCallArg(0, JSTaggedValue(i));
497
498        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
499        JSTaggedValue result = ContainersLightWeightSet::Add(callInfo);
500        TestHelper::TearDownFrame(thread, prev);
501        int len = lightWeightSet->GetLength();
502        EXPECT_EQ(result, JSTaggedValue::True());
503        EXPECT_EQ(len, static_cast<int>(i + 1));
504    }
505    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
506    JSHandle<JSAPILightWeightSet> newLightWeightSet = CreateJSAPILightWeightSet();
507    {
508        JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
509        JSHandle<JSFunction> func = factory->NewJSFunction(env, reinterpret_cast<void *>(TestClass::TestForEachFunc));
510        auto callInfo =
511            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);   // 8 means the value
512        callInfo->SetFunction(JSTaggedValue::Undefined());
513        callInfo->SetThis(lightWeightSet.GetTaggedValue());
514        callInfo->SetCallArg(0, func.GetTaggedValue());
515        callInfo->SetCallArg(1, newLightWeightSet.GetTaggedValue());
516
517        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
518        ContainersLightWeightSet::ForEach(callInfo);
519        TestHelper::TearDownFrame(thread, prev);
520    }
521
522    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
523        auto callInfo =
524            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);   // 6 means the value
525        callInfo->SetFunction(JSTaggedValue::Undefined());
526        callInfo->SetThis(lightWeightSet.GetTaggedValue());
527        callInfo->SetCallArg(0, JSTaggedValue(i));
528
529        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
530        JSTaggedValue result = ContainersLightWeightSet::GetValueAt(callInfo);
531        TestHelper::TearDownFrame(thread, prev);
532
533        callInfo =
534            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);   // 6 means the value
535        callInfo->SetFunction(JSTaggedValue::Undefined());
536        callInfo->SetThis(lightWeightSet.GetTaggedValue());
537        callInfo->SetCallArg(0, result);
538
539        prev = TestHelper::SetupFrame(thread, callInfo);
540        JSTaggedValue valueResult = ContainersLightWeightSet::Has(callInfo);
541        TestHelper::TearDownFrame(thread, prev);
542        EXPECT_EQ(valueResult, JSTaggedValue::True());
543    }
544}
545
546HWTEST_F_L0(ContainersLightWeightSetTest, ProxyOfGetSizeAndHasHash)
547{
548    constexpr uint32_t NODE_NUMBERS = 8;
549    JSHandle<JSAPILightWeightSet> lightWeightSet = CreateJSAPILightWeightSet();
550    auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
551    callInfo->SetFunction(JSTaggedValue::Undefined());
552    JSHandle<JSProxy> proxy = CreateJSProxyHandle(thread);
553    proxy->SetTarget(thread, lightWeightSet.GetTaggedValue());
554    callInfo->SetThis(proxy.GetTaggedValue());
555
556    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
557        callInfo->SetCallArg(0, JSTaggedValue(i));
558        callInfo->SetCallArg(1, JSTaggedValue(i + 1));
559        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
560        ContainersLightWeightSet::Add(callInfo);
561        TestHelper::TearDownFrame(thread, prev);
562
563        [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, callInfo);
564        JSTaggedValue retult = ContainersLightWeightSet::GetSize(callInfo);
565        TestHelper::TearDownFrame(thread, prev1);
566        EXPECT_EQ(retult, JSTaggedValue(i + 1));
567
568        [[maybe_unused]] auto prev2 = TestHelper::SetupFrame(thread, callInfo);
569        EXPECT_EQ(ContainersLightWeightSet::HasHash(callInfo), JSTaggedValue::True());
570        TestHelper::TearDownFrame(thread, prev2);
571    }
572    callInfo->SetCallArg(0, JSTaggedValue(NODE_NUMBERS));
573    [[maybe_unused]] auto prev2 = TestHelper::SetupFrame(thread, callInfo);
574    EXPECT_EQ(ContainersLightWeightSet::HasHash(callInfo), JSTaggedValue::False());
575    TestHelper::TearDownFrame(thread, prev2);
576}
577
578HWTEST_F_L0(ContainersLightWeightSetTest, ExceptionReturn1)
579{
580    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersLightWeightSet, AddAll);
581    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersLightWeightSet, GetValueAt);
582    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersLightWeightSet, HasAll);
583    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersLightWeightSet, IncreaseCapacityTo);
584    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersLightWeightSet, Add);
585    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersLightWeightSet, IsEmpty);
586    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersLightWeightSet, Has);
587    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersLightWeightSet, HasHash);
588    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersLightWeightSet, Equal);
589    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersLightWeightSet, GetIteratorObj);
590
591    JSHandle<JSAPILightWeightSet> lightWeightSet = CreateJSAPILightWeightSet();
592    {
593        auto callInfo = NewEmptyCallInfo(thread);
594        callInfo->SetThis(lightWeightSet.GetTaggedValue());
595        CONTAINERS_API_EXCEPTION_TEST(ContainersLightWeightSet, AddAll, callInfo);
596    }
597    {
598        auto callInfo = NewEmptyCallInfo(thread);
599        callInfo->SetThis(lightWeightSet.GetTaggedValue());
600        CONTAINERS_API_EXCEPTION_TEST(ContainersLightWeightSet, GetValueAt, callInfo);
601    }
602    {
603        auto callInfo = NewEmptyCallInfo(thread);
604        callInfo->SetThis(lightWeightSet.GetTaggedValue());
605        CONTAINERS_API_EXCEPTION_TEST(ContainersLightWeightSet, HasAll, callInfo);
606    }
607    {
608        auto callInfo = NewEmptyCallInfo(thread);
609        callInfo->SetThis(lightWeightSet.GetTaggedValue());
610        CONTAINERS_API_EXCEPTION_TEST(ContainersLightWeightSet, IncreaseCapacityTo, callInfo);
611    }
612}
613
614HWTEST_F_L0(ContainersLightWeightSetTest, ExceptionReturn2)
615{
616    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersLightWeightSet, RemoveAt);
617    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersLightWeightSet, Values);
618    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersLightWeightSet, Entries);
619    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersLightWeightSet, ForEach);
620    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersLightWeightSet, GetIndexOf);
621    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersLightWeightSet, Remove);
622    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersLightWeightSet, Clear);
623    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersLightWeightSet, ToString);
624    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersLightWeightSet, ToArray);
625    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersLightWeightSet, GetSize);
626
627    JSHandle<JSAPILightWeightSet> lightWeightSet = CreateJSAPILightWeightSet();
628    {
629        auto callInfo = NewEmptyCallInfo(thread);
630        callInfo->SetThis(lightWeightSet.GetTaggedValue());
631        CONTAINERS_API_EXCEPTION_TEST(ContainersLightWeightSet, RemoveAt, callInfo);
632    }
633}
634}  // namespace panda::test
635