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_plainarray.h"
17#include "ecmascript/containers/containers_private.h"
18#include "ecmascript/ecma_runtime_call_info.h"
19#include "ecmascript/global_env.h"
20#include "ecmascript/js_api/js_api_plain_array_iterator.h"
21#include "ecmascript/js_api/js_api_plain_array.h"
22#include "ecmascript/js_handle.h"
23#include "ecmascript/js_tagged_value-inl.h"
24#include "ecmascript/js_thread.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 ContainersPlainArrayTest : 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> key = GetCallArg(argv, 0);  // 0 means the value
65            JSHandle<JSTaggedValue> value = GetCallArg(argv, 1); // 1 means the value
66            JSHandle<JSAPIPlainArray> plainArray(GetCallArg(argv, 2)); // 2 means the value
67            if (key->IsNumber()) {
68                JSHandle<JSTaggedValue> newValue(thread, JSTaggedValue(value->GetInt() * 2)); // 2 means the value
69                JSAPIPlainArray::Add(thread, plainArray, key, newValue);
70            }
71
72            return JSTaggedValue::True();
73        }
74    };
75protected:
76    JSTaggedValue InitializePlainArrayConstructor()
77    {
78        ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
79        JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
80
81        JSHandle<JSTaggedValue> globalObject = env->GetJSGlobalObject();
82        JSHandle<JSTaggedValue> key(factory->NewFromASCII("ArkPrivate"));
83        JSHandle<JSTaggedValue> value =
84            JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(globalObject), key).GetValue();
85
86        auto objCallInfo =
87            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);   // 6 means the value
88        objCallInfo->SetFunction(JSTaggedValue::Undefined());
89        objCallInfo->SetThis(value.GetTaggedValue());
90        objCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int>(ContainerTag::PlainArray)));
91        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
92        JSTaggedValue result = ContainersPrivate::Load(objCallInfo);
93        TestHelper::TearDownFrame(thread, prev);
94
95        return result;
96    }
97
98    JSHandle<JSAPIPlainArray> CreateJSAPIPlainArray()
99    {
100        JSHandle<JSFunction> newTarget(thread, InitializePlainArrayConstructor());
101        auto objCallInfo =
102            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);   // 4 means the value
103        objCallInfo->SetFunction(newTarget.GetTaggedValue());
104        objCallInfo->SetNewTarget(newTarget.GetTaggedValue());
105        objCallInfo->SetThis(JSTaggedValue::Undefined());
106
107        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
108        JSTaggedValue result = ContainersPlainArray::PlainArrayConstructor(objCallInfo);
109        TestHelper::TearDownFrame(thread, prev);
110        JSHandle<JSAPIPlainArray> plain(thread, result);
111        return plain;
112    }
113
114    JSTaggedValue PlainArrayAdd(JSHandle<JSAPIPlainArray> plainArray, JSTaggedValue index, JSTaggedValue value)
115    {
116        auto callInfo =
117            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); // 4 means the value
118        callInfo->SetFunction(JSTaggedValue::Undefined());
119        callInfo->SetThis(plainArray.GetTaggedValue());
120        callInfo->SetCallArg(0, index);
121        callInfo->SetCallArg(1, value);
122
123        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
124        JSTaggedValue result = ContainersPlainArray::Add(callInfo);
125        TestHelper::TearDownFrame(thread, prev);
126        return result;
127    }
128
129    JSTaggedValue PlainArrayRemoveRangeFrom(JSHandle<JSAPIPlainArray> plainArray, JSTaggedValue index,
130                                            JSTaggedValue size)
131    {
132        auto callInfo =
133            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); // 8 means the value
134        callInfo->SetFunction(JSTaggedValue::Undefined());
135        callInfo->SetThis(plainArray.GetTaggedValue());
136        callInfo->SetCallArg(0, index);
137        callInfo->SetCallArg(1, size);
138
139        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
140        JSTaggedValue result = ContainersPlainArray::RemoveRangeFrom(callInfo);
141        TestHelper::TearDownFrame(thread, prev);
142        return result;
143    }
144};
145
146HWTEST_F_L0(ContainersPlainArrayTest, PlainArrayConstructor)
147{
148    InitializePlainArrayConstructor();
149    JSHandle<JSFunction> newTarget(thread, InitializePlainArrayConstructor());
150    auto objCallInfo =
151        TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);    // 4 means the value
152    objCallInfo->SetFunction(newTarget.GetTaggedValue());
153    objCallInfo->SetNewTarget(newTarget.GetTaggedValue());
154    objCallInfo->SetThis(JSTaggedValue::Undefined());
155
156    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
157    JSTaggedValue result = ContainersPlainArray::PlainArrayConstructor(objCallInfo);
158    TestHelper::TearDownFrame(thread, prev);
159
160    ASSERT_TRUE(result.IsJSAPIPlainArray());
161    JSHandle<JSAPIPlainArray> arrayHandle(thread, result);
162    JSTaggedValue resultProto = JSObject::GetPrototype(JSHandle<JSObject>::Cast(arrayHandle));
163    JSTaggedValue funcProto = newTarget->GetFunctionPrototype();
164    ASSERT_EQ(resultProto, funcProto);
165    int size = arrayHandle->GetSize();
166    ASSERT_EQ(size, 0);
167
168    // test PlainArrayConstructor exception
169    objCallInfo->SetNewTarget(JSTaggedValue::Undefined());
170    CONTAINERS_API_EXCEPTION_TEST(ContainersPlainArray, PlainArrayConstructor, objCallInfo);
171}
172
173HWTEST_F_L0(ContainersPlainArrayTest, AddAndHas)
174{
175    constexpr uint32_t NODE_NUMBERS = 8;    // 8 means the value
176
177    JSHandle<JSAPIPlainArray> tArray1 = CreateJSAPIPlainArray();
178    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
179        auto callInfo =
180            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);   // 8 means the value
181        callInfo->SetFunction(JSTaggedValue::Undefined());
182        callInfo->SetThis(tArray1.GetTaggedValue());
183        callInfo->SetCallArg(0, JSTaggedValue(i));
184        callInfo->SetCallArg(1, JSTaggedValue(i + 1));
185
186        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
187        JSTaggedValue result = ContainersPlainArray::Add(callInfo);
188        TestHelper::TearDownFrame(thread, prev);
189        EXPECT_TRUE(result.IsUndefined());
190        EXPECT_EQ(tArray1->GetSize(), static_cast<int>(i + 1));
191    }
192    EXPECT_EQ(tArray1->GetSize(), static_cast<int>(NODE_NUMBERS));
193    // test has
194    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
195        auto callInfo =
196            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);   // 8 means the value
197        callInfo->SetFunction(JSTaggedValue::Undefined());
198        callInfo->SetThis(tArray1.GetTaggedValue());
199        callInfo->SetCallArg(0, JSTaggedValue(i));
200
201        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
202        JSTaggedValue result = ContainersPlainArray::Has(callInfo);
203        TestHelper::TearDownFrame(thread, prev);
204        EXPECT_TRUE(result.IsTrue());
205    }
206    EXPECT_EQ(tArray1->GetSize(), static_cast<int>(NODE_NUMBERS));
207    // test add string
208    JSHandle<JSAPIPlainArray> tArray = CreateJSAPIPlainArray();
209    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
210    JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
211    JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
212    std::string myValue("myvalue");
213    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
214        std::string ivalue = myValue + std::to_string(i);
215        key.Update(JSTaggedValue(i));
216        value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
217
218        auto callInfo =
219            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);   // 8 means the value
220        callInfo->SetFunction(JSTaggedValue::Undefined());
221        callInfo->SetThis(tArray.GetTaggedValue());
222        callInfo->SetCallArg(0, key.GetTaggedValue());
223        callInfo->SetCallArg(1, value.GetTaggedValue());
224
225        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
226        JSTaggedValue result = ContainersPlainArray::Add(callInfo);
227        TestHelper::TearDownFrame(thread, prev);
228        EXPECT_TRUE(result.IsUndefined());
229    }
230    EXPECT_EQ(tArray->GetSize(), static_cast<int>(NODE_NUMBERS));
231    // test get
232    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
233        std::string ivalue = myValue + std::to_string(i);
234        key.Update(JSTaggedValue(i));
235        value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
236
237        auto callInfo =
238            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);   // 8 means the value
239        callInfo->SetFunction(JSTaggedValue::Undefined());
240        callInfo->SetThis(tArray.GetTaggedValue());
241        callInfo->SetCallArg(0, key.GetTaggedValue());
242
243        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
244        JSTaggedValue result = ContainersPlainArray::Get(callInfo);
245        TestHelper::TearDownFrame(thread, prev);
246        EXPECT_TRUE(JSTaggedValue::Equal(thread, JSHandle<JSTaggedValue>(thread, result), value));
247    }
248}
249
250HWTEST_F_L0(ContainersPlainArrayTest, Iterator)
251{
252    constexpr uint32_t NODE_NUMBERS = 8;
253    JSHandle<JSAPIPlainArray> array = CreateJSAPIPlainArray();
254    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
255        auto callInfo =
256            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);   // 8 means the value
257        callInfo->SetFunction(JSTaggedValue::Undefined());
258        callInfo->SetThis(array.GetTaggedValue());
259        callInfo->SetCallArg(0, JSTaggedValue(i));
260        callInfo->SetCallArg(1, JSTaggedValue(i + 1));
261
262        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
263        JSTaggedValue result = ContainersPlainArray::Add(callInfo);
264        TestHelper::TearDownFrame(thread, prev);
265        EXPECT_TRUE(result.IsUndefined());
266        EXPECT_EQ(array->GetSize(), static_cast<int>(i + 1));
267    }
268    // test iterator
269    {
270        auto callInf = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
271        callInf->SetFunction(JSTaggedValue::Undefined());
272        callInf->SetThis(array.GetTaggedValue());
273        [[maybe_unused]] auto pre = TestHelper::SetupFrame(thread, callInf);
274        JSHandle<JSTaggedValue> iter(thread, ContainersPlainArray::GetIteratorObj(callInf));
275        TestHelper::TearDownFrame(thread, pre);
276        EXPECT_TRUE(iter->IsJSAPIPlainArrayIterator());
277
278        JSHandle<JSTaggedValue> first(thread, JSTaggedValue(0));
279        JSHandle<JSTaggedValue> second(thread, JSTaggedValue(1));
280        JSMutableHandle<JSTaggedValue> result(thread, JSTaggedValue::Undefined());
281        JSMutableHandle<JSTaggedValue> entries(thread, JSTaggedValue::Undefined());
282        for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
283            auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
284            callInfo->SetFunction(JSTaggedValue::Undefined());
285            callInfo->SetThis(iter.GetTaggedValue());
286
287            [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
288            result.Update(JSAPIPlainArrayIterator::Next(callInfo));
289            TestHelper::TearDownFrame(thread, prev);
290            entries.Update(JSIterator::IteratorValue(thread, result).GetTaggedValue());
291            EXPECT_EQ(static_cast<int>(i), JSObject::GetProperty(thread, entries, first).GetValue()->GetInt());
292            EXPECT_EQ(static_cast<int>(i + 1), JSObject::GetProperty(thread, entries, second).GetValue()->GetInt());
293        }
294    }
295    // test add string
296    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
297    JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
298    std::string myValue("myvalue");
299    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
300        std::string iValue = myValue + std::to_string(i);
301        value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
302        auto callInfo =
303            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);   // 8 means the value
304        callInfo->SetFunction(JSTaggedValue::Undefined());
305        callInfo->SetThis(array.GetTaggedValue());
306        callInfo->SetCallArg(0, JSTaggedValue(100 + i));
307        callInfo->SetCallArg(1, value.GetTaggedValue());
308
309        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
310        JSTaggedValue result = ContainersPlainArray::Add(callInfo);
311        TestHelper::TearDownFrame(thread, prev);
312        EXPECT_TRUE(result.IsUndefined());
313        EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS + i + 1));
314    }
315    EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS * 2));
316}
317
318HWTEST_F_L0(ContainersPlainArrayTest, GetIndexOfKeyAndGetIndexOfValue)
319{
320    constexpr uint32_t NODE_NUMBERS = 8;
321    JSHandle<JSAPIPlainArray> pArray = CreateJSAPIPlainArray();
322    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
323        auto callInfo =
324            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); // 4 means the value
325        callInfo->SetFunction(JSTaggedValue::Undefined());
326        callInfo->SetThis(pArray.GetTaggedValue());
327        callInfo->SetCallArg(0, JSTaggedValue(i));
328        callInfo->SetCallArg(1, JSTaggedValue(i + 1));
329
330        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
331        JSTaggedValue result = ContainersPlainArray::Add(callInfo);
332        TestHelper::TearDownFrame(thread, prev);
333        EXPECT_TRUE(result.IsUndefined());
334        EXPECT_EQ(pArray->GetSize(), static_cast<int>(i + 1));
335    }
336    // test GetIndexOfKey
337    {
338        auto callInfo =
339            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); // 6 means the value
340        callInfo->SetFunction(JSTaggedValue::Undefined());
341        callInfo->SetThis(pArray.GetTaggedValue());
342        callInfo->SetCallArg(0, JSTaggedValue(2));
343
344        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
345        JSTaggedValue result = ContainersPlainArray::GetIndexOfKey(callInfo);
346        TestHelper::TearDownFrame(thread, prev);
347        EXPECT_EQ(result, JSTaggedValue(2));
348    }
349    // test GetIndexOfValue
350    {
351        auto callInfo =
352            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); // 6 means the value
353        callInfo->SetFunction(JSTaggedValue::Undefined());
354        callInfo->SetThis(pArray.GetTaggedValue());
355        callInfo->SetCallArg(0, JSTaggedValue(4));
356
357        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
358        JSTaggedValue result = ContainersPlainArray::GetIndexOfValue(callInfo);
359        TestHelper::TearDownFrame(thread, prev);
360        EXPECT_EQ(result, JSTaggedValue(3));
361    }
362    // test add string
363    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
364    JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
365    std::string myValue("myvalue");
366    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
367        std::string iValue = myValue + std::to_string(i);
368        value.Update(factory->NewFromStdString(iValue).GetTaggedValue());
369        auto callInfo =
370            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); // 8 means the value
371        callInfo->SetFunction(JSTaggedValue::Undefined());
372        callInfo->SetThis(pArray.GetTaggedValue());
373        callInfo->SetCallArg(0, JSTaggedValue(100 + i));
374        callInfo->SetCallArg(1, value.GetTaggedValue());
375
376        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
377        JSTaggedValue result = ContainersPlainArray::Add(callInfo);
378        TestHelper::TearDownFrame(thread, prev);
379        EXPECT_TRUE(result.IsUndefined());
380        EXPECT_EQ(pArray->GetSize(), static_cast<int>(NODE_NUMBERS + i + 1));
381    }
382    EXPECT_EQ(pArray->GetSize(), static_cast<int>(NODE_NUMBERS * 2));
383    // test GetIndexOfKey
384    {
385        auto callInfo =
386            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); // 6 means the value
387        callInfo->SetFunction(JSTaggedValue::Undefined());
388        callInfo->SetThis(pArray.GetTaggedValue());
389        callInfo->SetCallArg(0, JSTaggedValue(102));
390
391        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
392        JSTaggedValue result = ContainersPlainArray::GetIndexOfKey(callInfo);
393        TestHelper::TearDownFrame(thread, prev);
394        EXPECT_EQ(result, JSTaggedValue(10));
395    }
396    // test GetIndexOfValue
397    {
398        std::string tValue("myvalue3");
399        value.Update(factory->NewFromStdString(tValue).GetTaggedValue());
400        auto callInfo =
401            TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); // 6 means the value
402        callInfo->SetFunction(JSTaggedValue::Undefined());
403        callInfo->SetThis(pArray.GetTaggedValue());
404        callInfo->SetCallArg(0, value.GetTaggedValue());
405
406        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
407        JSTaggedValue result = ContainersPlainArray::GetIndexOfValue(callInfo);
408        TestHelper::TearDownFrame(thread, prev);
409        EXPECT_EQ(result, JSTaggedValue(11));
410    }
411}
412
413HWTEST_F_L0(ContainersPlainArrayTest, RemoveRangeFrom)
414{
415    constexpr uint32_t NODE_NUMBERS = 8;
416    JSHandle<JSAPIPlainArray> pArray = CreateJSAPIPlainArray();
417    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
418        JSTaggedValue result = PlainArrayAdd(pArray, JSTaggedValue(i), JSTaggedValue(i + 1));
419        EXPECT_TRUE(result.IsUndefined());
420        EXPECT_EQ(pArray->GetSize(), static_cast<int>(i + 1));
421    }
422
423    // remove success
424    {
425        JSTaggedValue result = PlainArrayRemoveRangeFrom(pArray, JSTaggedValue(2), JSTaggedValue(2));
426        EXPECT_EQ(result, JSTaggedValue(2));
427        EXPECT_EQ(pArray->GetSize(), static_cast<int>(NODE_NUMBERS - 2));
428        for (uint32_t i = 0; i < NODE_NUMBERS - 2; i++) {
429            if (i < 2) {
430                EXPECT_EQ(pArray->Get(JSTaggedValue(i)), JSTaggedValue(i + 1));
431            } else {
432                EXPECT_EQ(pArray->Get(JSTaggedValue(i + 2)), JSTaggedValue(i + 3));
433            }
434        }
435    }
436
437    // input index type error
438    {
439        JSTaggedValue result = PlainArrayRemoveRangeFrom(pArray, JSTaggedValue::Undefined(), JSTaggedValue(2));
440        EXPECT_TRUE(thread->HasPendingException());
441        EXPECT_EQ(result, JSTaggedValue::Exception());
442        thread->ClearException();
443    }
444
445    // input size type error
446    {
447        JSTaggedValue result = PlainArrayRemoveRangeFrom(pArray, JSTaggedValue(2), JSTaggedValue::Undefined());
448        EXPECT_TRUE(thread->HasPendingException());
449        EXPECT_EQ(result, JSTaggedValue::Exception());
450        thread->ClearException();
451    }
452
453    // input index out of range
454    {
455        JSTaggedValue result = PlainArrayRemoveRangeFrom(pArray, JSTaggedValue(NODE_NUMBERS + 1), JSTaggedValue(2));
456        EXPECT_TRUE(thread->HasPendingException());
457        EXPECT_EQ(result, JSTaggedValue::Exception());
458        thread->ClearException();
459    }
460}
461
462HWTEST_F_L0(ContainersPlainArrayTest, ProxyOfGetSize)
463{
464    constexpr uint32_t NODE_NUMBERS = 8;
465    JSHandle<JSAPIPlainArray> proxyArrayList = CreateJSAPIPlainArray();
466    auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
467    callInfo->SetFunction(JSTaggedValue::Undefined());
468    JSHandle<JSProxy> proxy = CreateJSProxyHandle(thread);
469    proxy->SetTarget(thread, proxyArrayList.GetTaggedValue());
470    callInfo->SetThis(proxy.GetTaggedValue());
471
472    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
473        callInfo->SetCallArg(0, JSTaggedValue(i));
474        callInfo->SetCallArg(1, JSTaggedValue(i + 1));
475        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
476        ContainersPlainArray::Add(callInfo);
477        TestHelper::TearDownFrame(thread, prev);
478
479        [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, callInfo);
480        JSTaggedValue retult = ContainersPlainArray::GetSize(callInfo);
481        TestHelper::TearDownFrame(thread, prev1);
482        EXPECT_EQ(retult, JSTaggedValue(i + 1));
483    }
484}
485
486HWTEST_F_L0(ContainersPlainArrayTest, ExceptionReturn1)
487{
488    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersPlainArray, Add);
489    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersPlainArray, Has);
490    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersPlainArray, Get);
491    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersPlainArray, GetIndexOfKey);
492    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersPlainArray, Clear);
493    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersPlainArray, Clone);
494    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersPlainArray, GetIteratorObj);
495    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersPlainArray, ForEach);
496    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersPlainArray, ToString);
497    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersPlainArray, GetIndexOfValue);
498
499    JSHandle<JSAPIPlainArray> plianArray = CreateJSAPIPlainArray();
500    {
501        auto callInfo = NewEmptyCallInfo(thread);
502        callInfo->SetThis(plianArray.GetTaggedValue());
503        CONTAINERS_API_EXCEPTION_TEST(ContainersPlainArray, Add, callInfo);
504    }
505    {
506        auto callInfo = NewEmptyCallInfo(thread);
507        callInfo->SetThis(plianArray.GetTaggedValue());
508        CONTAINERS_API_EXCEPTION_TEST(ContainersPlainArray, Has, callInfo);
509    }
510    {
511        auto callInfo = NewEmptyCallInfo(thread);
512        callInfo->SetThis(plianArray.GetTaggedValue());
513        CONTAINERS_API_EXCEPTION_TEST(ContainersPlainArray, Get, callInfo);
514    }
515    {
516        auto callInfo = NewEmptyCallInfo(thread);
517        callInfo->SetThis(plianArray.GetTaggedValue());
518        CONTAINERS_API_EXCEPTION_TEST(ContainersPlainArray, GetIndexOfKey, callInfo);
519    }
520}
521
522HWTEST_F_L0(ContainersPlainArrayTest, ExceptionReturn2)
523{
524    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersPlainArray, GetKeyAt);
525    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersPlainArray, Remove);
526    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersPlainArray, RemoveAt);
527    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersPlainArray, SetValueAt);
528    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersPlainArray, GetValueAt);
529    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersPlainArray, IsEmpty);
530    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersPlainArray, RemoveRangeFrom);
531    CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersPlainArray, GetSize);
532
533    JSHandle<JSAPIPlainArray> plianArray = CreateJSAPIPlainArray();
534    {
535        auto callInfo = NewEmptyCallInfo(thread);
536        callInfo->SetThis(plianArray.GetTaggedValue());
537        CONTAINERS_API_EXCEPTION_TEST(ContainersPlainArray, GetKeyAt, callInfo);
538    }
539    {
540        auto callInfo = NewEmptyCallInfo(thread);
541        callInfo->SetThis(plianArray.GetTaggedValue());
542        CONTAINERS_API_EXCEPTION_TEST(ContainersPlainArray, Remove, callInfo);
543    }
544    {
545        auto callInfo = NewEmptyCallInfo(thread);
546        callInfo->SetThis(plianArray.GetTaggedValue());
547        CONTAINERS_API_EXCEPTION_TEST(ContainersPlainArray, RemoveAt, callInfo);
548    }
549    {
550        auto callInfo = NewEmptyCallInfo(thread);
551        callInfo->SetThis(plianArray.GetTaggedValue());
552        CONTAINERS_API_EXCEPTION_TEST(ContainersPlainArray, SetValueAt, callInfo);
553    }
554    {
555        auto callInfo = NewEmptyCallInfo(thread);
556        callInfo->SetThis(plianArray.GetTaggedValue());
557        CONTAINERS_API_EXCEPTION_TEST(ContainersPlainArray, GetValueAt, callInfo);
558    }
559}
560}
561