1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "ecmascript/containers/containers_private.h"
17#include "ecmascript/ecma_string.h"
18#include "ecmascript/ecma_vm.h"
19#include "ecmascript/global_env.h"
20#include "ecmascript/js_api/js_api_deque.h"
21#include "ecmascript/js_api/js_api_deque_iterator.h"
22#include "ecmascript/js_function.h"
23#include "ecmascript/js_handle.h"
24#include "ecmascript/js_iterator.h"
25#include "ecmascript/js_object-inl.h"
26#include "ecmascript/js_tagged_value.h"
27#include "ecmascript/object_factory.h"
28#include "ecmascript/tests/ecma_test_common.h"
29
30using namespace panda;
31using namespace panda::ecmascript;
32using namespace panda::ecmascript::containers;
33
34namespace panda::test {
35class JSAPIDequeTest : public BaseTestWithScope<false> {
36protected:
37    JSAPIDeque *CreateDeque()
38    {
39        return EcmaContainerCommon::CreateJSApiDeque(thread);
40    }
41};
42
43HWTEST_F_L0(JSAPIDequeTest, dequeCreate)
44{
45    JSAPIDeque *deque = CreateDeque();
46    EXPECT_TRUE(deque != nullptr);
47}
48
49HWTEST_F_L0(JSAPIDequeTest, InsertFrontAndGetFront)
50{
51    constexpr uint32_t NODE_NUMBERS = 9;
52    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
53    JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
54
55    JSHandle<JSAPIDeque> toor(thread, CreateDeque());
56
57    // test GetFront of empty deque
58    EXPECT_EQ(toor->GetFront(), JSTaggedValue::Undefined());
59
60    std::string myValue("myvalue");
61    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
62        std::string ivalue = myValue + std::to_string(i);
63        value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
64        JSAPIDeque::InsertFront(thread, toor, value);
65        EXPECT_EQ(toor->GetFront(), value.GetTaggedValue());
66    }
67
68    toor->Dump();
69}
70
71HWTEST_F_L0(JSAPIDequeTest, InsertEndAndGetTail)
72{
73    constexpr uint32_t NODE_NUMBERS = 9;
74    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
75    JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
76
77    JSHandle<JSAPIDeque> toor(thread, CreateDeque());
78
79    // test GetTail of empty deque
80    EXPECT_EQ(toor->GetTail(), JSTaggedValue::Undefined());
81
82    std::string myValue("myvalue");
83    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
84        std::string ivalue = myValue + std::to_string(i);
85        value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
86        JSAPIDeque::InsertEnd(thread, toor, value);
87        EXPECT_EQ(toor->GetTail(), value.GetTaggedValue());
88    }
89
90    toor->Dump();
91}
92
93HWTEST_F_L0(JSAPIDequeTest, PopFirst)
94{
95    constexpr uint32_t NODE_NUMBERS = 9;
96    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
97    JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
98
99    JSHandle<JSAPIDeque> toor(thread, CreateDeque());
100
101    // test PopFirst of empty deque
102    EXPECT_EQ(toor->PopFirst(), JSTaggedValue::Undefined());
103
104    std::string myValue("myvalue");
105    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
106        std::string ivalue = myValue + std::to_string(i);
107        value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
108        JSAPIDeque::InsertFront(thread, toor, value);
109        EXPECT_EQ(toor->PopFirst(), value.GetTaggedValue());
110    }
111
112    toor->Dump();
113}
114
115HWTEST_F_L0(JSAPIDequeTest, PopLast)
116{
117    constexpr uint32_t NODE_NUMBERS = 9;
118    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
119    JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
120
121    JSHandle<JSAPIDeque> toor(thread, CreateDeque());
122
123    // test PopLast of empty deque
124    EXPECT_EQ(toor->PopLast(), JSTaggedValue::Undefined());
125
126    std::string myValue("myvalue");
127    for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
128        std::string ivalue = myValue + std::to_string(i);
129        value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
130        JSAPIDeque::InsertEnd(thread, toor, value);
131        EXPECT_EQ(toor->PopLast(), value.GetTaggedValue());
132    }
133
134    toor->Dump();
135}
136
137HWTEST_F_L0(JSAPIDequeTest, GetOwnProperty)
138{
139    constexpr uint32_t DEFAULT_LENGTH = 8;
140    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
141    JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
142    JSHandle<JSAPIDeque> toor(thread, CreateDeque());
143
144    std::string dequeValue("dequevalue");
145    for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
146        std::string ivalue = dequeValue + std::to_string(i);
147        value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
148        JSAPIDeque::InsertFront(thread, toor, value);
149        JSAPIDeque::InsertEnd(thread, toor, value);
150    }
151    // test GetOwnProperty
152    int testInt = 1;
153    JSHandle<JSTaggedValue> dequeKey1(thread, JSTaggedValue(testInt));
154    EXPECT_TRUE(JSAPIDeque::GetOwnProperty(thread, toor, dequeKey1));
155    testInt = 20;
156    JSHandle<JSTaggedValue> dequeKey2(thread, JSTaggedValue(testInt));
157    EXPECT_FALSE(JSAPIDeque::GetOwnProperty(thread, toor, dequeKey2));
158    EXPECT_EXCEPTION();
159
160    // test GetOwnProperty exception
161    JSHandle<JSTaggedValue> undefined(thread, JSTaggedValue::Undefined());
162    EXPECT_FALSE(JSAPIDeque::GetOwnProperty(thread, toor, undefined));
163    EXPECT_EXCEPTION();
164}
165
166/**
167 * @tc.name: GetProperty
168 * @tc.desc:
169 * @tc.type: FUNC
170 * @tc.require:
171 */
172HWTEST_F_L0(JSAPIDequeTest, GetProperty)
173{
174    JSHandle<JSAPIDeque> toor(thread, CreateDeque());
175    uint32_t elementsNums = 8;
176    for (uint32_t i = 0; i < elementsNums; i++) {
177        JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
178        JSAPIDeque::InsertEnd(thread, toor, value);
179    }
180    for (uint32_t i = 0; i < elementsNums; i++) {
181        JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
182        OperationResult getPropertyRes = JSAPIDeque::GetProperty(thread, toor, key);
183        EXPECT_EQ(getPropertyRes.GetValue().GetTaggedValue(), JSTaggedValue(i));
184    }
185}
186
187/**
188 * @tc.name: SetProperty
189 * @tc.desc:
190 * @tc.type: FUNC
191 * @tc.require:
192 */
193HWTEST_F_L0(JSAPIDequeTest, SetProperty)
194{
195    JSHandle<JSAPIDeque> toor(thread, CreateDeque());
196    uint32_t elementsNums = 8;
197    for (uint32_t i = 0; i < elementsNums; i++) {
198        JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
199        JSAPIDeque::InsertFront(thread, toor, value);
200        JSAPIDeque::InsertEnd(thread, toor, value);
201    }
202    for (uint32_t i = 0; i < elementsNums; i++) {
203        JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
204        JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i * 2)); // 2 : It means double
205        bool setPropertyRes = JSAPIDeque::SetProperty(thread, toor, key, value);
206        EXPECT_EQ(setPropertyRes, true);
207    }
208    JSHandle<JSTaggedValue> key(thread, JSTaggedValue(-1));
209    JSHandle<JSTaggedValue> value(thread, JSTaggedValue(-1));
210    EXPECT_FALSE(JSAPIDeque::SetProperty(thread, toor, key, value));
211    JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(elementsNums * 2));
212    EXPECT_FALSE(JSAPIDeque::SetProperty(thread, toor, key1, value));
213}
214
215/**
216 * @tc.name: OwnKeys
217 * @tc.desc:
218 * @tc.type: FUNC
219 * @tc.require:
220 */
221HWTEST_F_L0(JSAPIDequeTest, OwnKeys)
222{
223    JSHandle<JSAPIDeque> toor(thread, CreateDeque());
224    uint32_t elementsNums = 8;
225    for (uint32_t i = 0; i < elementsNums; i++) {
226        JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
227        JSAPIDeque::InsertEnd(thread, toor, value);
228    }
229
230    // test OwnKeys
231    JSHandle<TaggedArray> keyArray = JSAPIDeque::OwnKeys(thread, toor);
232    EXPECT_TRUE(keyArray->GetClass()->IsTaggedArray());
233    EXPECT_TRUE(keyArray->GetLength() == elementsNums);
234    for (uint32_t i = 0; i < elementsNums; i++) {
235        ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))),
236            EcmaString::Cast(keyArray->Get(i).GetTaggedObject())));
237    }
238}
239}  // namespace panda::test
240