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_plain_array.h"
17 #include "ecmascript/containers/containers_private.h"
18 #include "ecmascript/ecma_string.h"
19 #include "ecmascript/ecma_vm.h"
20 #include "ecmascript/global_env.h"
21 #include "ecmascript/js_api/js_api_plain_array_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
30 using namespace panda;
31
32 using namespace panda::ecmascript;
33
34 namespace panda::test {
35 class JSAPIPlainArrayTest : public BaseTestWithScope<false> {
36 protected:
CreatePlainArray()37 JSAPIPlainArray *CreatePlainArray()
38 {
39 return EcmaContainerCommon::CreatePlainArray(thread);
40 }
GetIndexOfKeyAndGeIndexOfValueGetArray(JSMutableHandle<JSTaggedValue> & value,uint32_t numbers)41 JSHandle<JSAPIPlainArray> GetIndexOfKeyAndGeIndexOfValueGetArray(JSMutableHandle<JSTaggedValue>& value,
42 uint32_t numbers)
43 {
44 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
45 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
46
47 JSHandle<JSAPIPlainArray> array(thread, CreatePlainArray());
48 EXPECT_TRUE(array->IsEmpty());
49 std::string myValue("myvalue");
50 for (uint32_t i = 0; i < numbers; i++) {
51 uint32_t ikey = 100 + i;
52 std::string ivalue = myValue + std::to_string(i);
53 key.Update(JSTaggedValue(ikey));
54 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
55 JSAPIPlainArray::Add(thread, array, key, value);
56 }
57 EXPECT_EQ(array->GetSize(), static_cast<int>(numbers));
58 EXPECT_FALSE(array->IsEmpty());
59 return array;
60 }
61
PropertyCommon(uint32_t elementsNums)62 JSHandle<JSAPIPlainArray> PropertyCommon(uint32_t elementsNums)
63 {
64 JSHandle<JSAPIPlainArray> plainArray(thread, CreatePlainArray());
65 for (uint32_t i = 0; i < elementsNums; i++) {
66 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
67 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
68 JSAPIPlainArray::Add(thread, plainArray, key, value);
69 }
70 return plainArray;
71 }
72 };
73
HWTEST_F_L0(JSAPIPlainArrayTest,PlainArrayCreate)74 HWTEST_F_L0(JSAPIPlainArrayTest, PlainArrayCreate)
75 {
76 JSAPIPlainArray *plainArray = CreatePlainArray();
77 EXPECT_TRUE(plainArray != nullptr);
78 }
79
HWTEST_F_L0(JSAPIPlainArrayTest,PA_AddAndGetKeyAtAndClear)80 HWTEST_F_L0(JSAPIPlainArrayTest, PA_AddAndGetKeyAtAndClear)
81 {
82 constexpr uint32_t NODE_NUMBERS = 8; // 8 means the value
83 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
84 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
85 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
86
87 // test JSAPIPlainArray
88 JSHandle<JSAPIPlainArray> array(thread, CreatePlainArray());
89 std::string myValue("myvalue");
90 for (uint32_t i = 0; i < NODE_NUMBERS; i = i + 2) {
91 uint32_t ikey = 100 + i;
92 std::string ivalue = myValue + std::to_string(i);
93
94 key.Update(JSTaggedValue(ikey));
95 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
96
97 JSAPIPlainArray::Add(thread, array, key, value);
98 }
99 for (uint32_t i = 1; i < NODE_NUMBERS; i = i + 2) {
100 uint32_t ikey = 100 + i;
101 std::string ivalue = myValue + std::to_string(i);
102
103 key.Update(JSTaggedValue(ikey));
104 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
105
106 JSAPIPlainArray::Add(thread, array, key, value);
107 }
108 EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS));
109
110 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
111 uint32_t ikey = 100 + i;
112 std::string ivalue = myValue + std::to_string(i);
113 key.Update(JSTaggedValue(ikey));
114 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
115
116 // test getKeyAt
117 JSTaggedValue gvalue = array->GetKeyAt(thread, i);
118 EXPECT_EQ(gvalue, key.GetTaggedValue());
119 }
120 EXPECT_EQ(array->GetKeyAt(thread, -1), JSTaggedValue::Undefined());
121 EXPECT_EQ(array->GetKeyAt(thread, NODE_NUMBERS), JSTaggedValue::Undefined());
122 // test clear
123 array->Clear(thread);
124 EXPECT_EQ(array->GetSize(), 0); // 0 means the value
125 }
126
HWTEST_F_L0(JSAPIPlainArrayTest,PA_CloneAndHasAndGet)127 HWTEST_F_L0(JSAPIPlainArrayTest, PA_CloneAndHasAndGet)
128 {
129 constexpr uint32_t NODE_NUMBERS = 8; // 8 means the value
130 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
131 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
132 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
133
134 // test JSAPIPlainArray
135 JSHandle<JSAPIPlainArray> array(thread, CreatePlainArray());
136 std::string myValue("myvalue");
137 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
138 uint32_t ikey = 100 + i;
139 std::string ivalue = myValue + std::to_string(i);
140 key.Update(JSTaggedValue(ikey));
141 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
142 JSAPIPlainArray::Add(thread, array, key, value);
143 }
144 EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS));
145
146 // test clone
147 JSHandle<JSAPIPlainArray> newArray(thread, CreatePlainArray());
148 EXPECT_EQ(newArray->GetSize(), 0); // 0 means the value
149 newArray = JSAPIPlainArray::Clone(thread, array);
150 EXPECT_EQ(newArray->GetSize(), static_cast<int>(NODE_NUMBERS));
151
152 // test has
153 key.Update(JSTaggedValue(103)); // 103 means the value
154 int32_t lkey = 103;
155 bool result = array->Has(thread, lkey);
156 EXPECT_TRUE(result);
157 EXPECT_FALSE(array->Has(thread, lkey * 2));
158
159 // test get
160 myValue = std::string("myvalue3");
161 value.Update(factory->NewFromStdString(myValue).GetTaggedValue());
162 EXPECT_TRUE(
163 JSTaggedValue::Equal(thread, JSHandle<JSTaggedValue>(thread, array->Get(thread, key.GetTaggedValue())), value));
164 }
165
HWTEST_F_L0(JSAPIPlainArrayTest,PA_GetIndexOfKeyAndGeIndexOfValueAndIsEmptyAndRemoveRangeFrom)166 HWTEST_F_L0(JSAPIPlainArrayTest, PA_GetIndexOfKeyAndGeIndexOfValueAndIsEmptyAndRemoveRangeFrom)
167 {
168 constexpr uint32_t NODE_NUMBERS = 8; // 8 means the value
169 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
170 auto array = GetIndexOfKeyAndGeIndexOfValueGetArray(value, NODE_NUMBERS);
171 value.Update(JSTaggedValue(103)); // 103 means the value
172 int32_t lvalue = 103;
173 JSTaggedValue value2 = array->GetIndexOfKey(thread, lvalue);
174 EXPECT_EQ(value2.GetNumber(), 3); // 3 means the value
175 EXPECT_EQ(array->GetIndexOfKey(thread, lvalue * 2), JSTaggedValue(-1));
176
177 std::string myValue = "myvalue2";
178 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
179 value.Update(factory->NewFromStdString(myValue).GetTaggedValue());
180 JSTaggedValue value3 = array->GetIndexOfValue(thread, value.GetTaggedValue());
181 EXPECT_EQ(value3.GetNumber(), 2); // 2 means the value
182 EXPECT_EQ(array->GetIndexOfValue(thread, JSTaggedValue(0)), JSTaggedValue(-1));
183
184 value.Update(JSTaggedValue(1));
185 int32_t batchSize = 3; // 3 means the value
186 lvalue = 1;
187 value3 = array->RemoveRangeFrom(thread, lvalue, batchSize);
188 EXPECT_EQ(value3.GetNumber(), 3); // 3 means the value
189 EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS - 3));
190
191 // test RemoveRangeFrom exception
192 array->RemoveRangeFrom(thread, lvalue, -1);
193 }
194
HWTEST_F_L0(JSAPIPlainArrayTest,PA_RemvoeAnrRemvoeAtAndSetValueAtAndGetValueAt)195 HWTEST_F_L0(JSAPIPlainArrayTest, PA_RemvoeAnrRemvoeAtAndSetValueAtAndGetValueAt)
196 {
197 constexpr uint32_t NODE_NUMBERS = 8; // 8 means the value
198 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
199 auto array = GetIndexOfKeyAndGeIndexOfValueGetArray(value, NODE_NUMBERS);
200 // test Remove
201 std::string myValue = "myvalue2";
202 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
203 value.Update(factory->NewFromStdString(myValue).GetTaggedValue());
204 JSTaggedValue taggedValue =
205 array->Remove(thread, JSTaggedValue(102)); // 102 means the value
206 EXPECT_TRUE(JSTaggedValue::Equal(thread, value, JSHandle<JSTaggedValue>(thread, taggedValue)));
207 EXPECT_EQ(array->Remove(thread, JSTaggedValue(-1)), JSTaggedValue::Undefined());
208 EXPECT_EQ(array->Remove(thread, JSTaggedValue(100 + NODE_NUMBERS)), JSTaggedValue::Undefined());
209
210 // test RemoveAt
211 myValue = "myvalue4";
212 value.Update(factory->NewFromStdString(myValue).GetTaggedValue());
213 taggedValue =
214 array->RemoveAt(thread, JSTaggedValue(3)); // 3 means the value
215 EXPECT_TRUE(JSTaggedValue::Equal(thread, value, JSHandle<JSTaggedValue>(thread, taggedValue)));
216 EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS - 2));
217 EXPECT_EQ(array->RemoveAt(thread, JSTaggedValue(-1)), JSTaggedValue::Undefined());
218 EXPECT_EQ(array->RemoveAt(thread, JSTaggedValue(NODE_NUMBERS)), JSTaggedValue::Undefined());
219
220 // test SetValueAt
221 myValue = "myvalue14";
222 value.Update(factory->NewFromStdString(myValue).GetTaggedValue());
223 array->SetValueAt(thread, JSTaggedValue(3), value.GetTaggedValue()); // 3 means the value
224 int32_t lvalue = 3; // 3 means the value
225 taggedValue = array->GetValueAt(thread, lvalue);
226 EXPECT_TRUE(JSTaggedValue::Equal(thread, value, JSHandle<JSTaggedValue>(thread, taggedValue)));
227 }
228
HWTEST_F_L0(JSAPIPlainArrayTest,PA_GetOwnProperty)229 HWTEST_F_L0(JSAPIPlainArrayTest, PA_GetOwnProperty)
230 {
231 constexpr uint32_t DEFAULT_LENGTH = 8;
232 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
233 JSHandle<JSAPIPlainArray> toor(thread, CreatePlainArray());
234 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
235 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
236
237 std::string plainArrayvalue("plainArrayvalue");
238 for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
239 uint32_t ikey = 100 + i;
240 std::string ivalue = plainArrayvalue + std::to_string(i);
241 key.Update(JSTaggedValue(ikey));
242 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
243 JSAPIPlainArray::Add(thread, toor, key, value);
244 }
245 // test GetOwnProperty
246 int testInt = 100 + 1;
247 JSHandle<JSTaggedValue> plainArrayKey1(thread, JSTaggedValue(testInt));
248 EXPECT_TRUE(JSAPIPlainArray::GetOwnProperty(thread, toor, plainArrayKey1));
249 testInt = 100 + 20;
250 JSHandle<JSTaggedValue> plainArrayKey2(thread, JSTaggedValue(testInt));
251 EXPECT_FALSE(JSAPIPlainArray::GetOwnProperty(thread, toor, plainArrayKey2));
252 }
253
HWTEST_F_L0(JSAPIPlainArrayTest,PA_ToString)254 HWTEST_F_L0(JSAPIPlainArrayTest, PA_ToString)
255 {
256 constexpr uint32_t NODE_NUMBERS = 3; // 3 means the value
257 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
258 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
259 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
260
261 // test JSAPIPlainArray
262 JSHandle<JSAPIPlainArray> array(thread, CreatePlainArray());
263 JSTaggedValue result1 = JSAPIPlainArray::ToString(thread, array);
264 JSHandle<EcmaString> resultHandle1(thread, result1);
265 JSHandle<EcmaString> det = thread->GetEcmaVM()->GetFactory()->NewFromASCII("");
266 ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle1, det), 0);
267 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
268 uint32_t ikey = i;
269 std::string ivalue = std::to_string(i);
270 key.Update(JSTaggedValue(ikey));
271 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
272 JSAPIPlainArray::Add(thread, array, key, value);
273 }
274 JSHandle<EcmaString> str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0:0,1:1,2:2");
275 JSTaggedValue result = JSAPIPlainArray::ToString(thread, array);
276 JSHandle<EcmaString> resultHandle(thread, result);
277
278 ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, str), 0);
279 }
280
281 /**
282 * @tc.name: GetProperty
283 * @tc.desc:
284 * @tc.type: FUNC
285 * @tc.require:
286 */
HWTEST_F_L0(JSAPIPlainArrayTest,GetProperty)287 HWTEST_F_L0(JSAPIPlainArrayTest, GetProperty)
288 {
289 uint32_t elementsNums = 8;
290 auto plainArray = PropertyCommon(elementsNums);
291 for (uint32_t i = 0; i < elementsNums; i++) {
292 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
293 OperationResult getPropertyRes = JSAPIPlainArray::GetProperty(thread, plainArray, key);
294 EXPECT_EQ(getPropertyRes.GetValue().GetTaggedValue(), JSTaggedValue(i));
295 }
296 }
297
298 /**
299 * @tc.name: SetProperty
300 * @tc.desc:
301 * @tc.type: FUNC
302 * @tc.require:
303 */
HWTEST_F_L0(JSAPIPlainArrayTest,SetProperty)304 HWTEST_F_L0(JSAPIPlainArrayTest, SetProperty)
305 {
306 uint32_t elementsNums = 8;
307 auto plainArray = PropertyCommon(elementsNums);
308 for (uint32_t i = 0; i < elementsNums; i++) {
309 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
310 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i * 2)); // 2 : It means double
311 bool setPropertyRes = JSAPIPlainArray::SetProperty(thread, plainArray, key, value);
312 EXPECT_EQ(setPropertyRes, true);
313 }
314 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(-1));
315 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(-1));
316 EXPECT_FALSE(JSAPIPlainArray::SetProperty(thread, plainArray, key, value));
317 JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(elementsNums));
318 EXPECT_FALSE(JSAPIPlainArray::SetProperty(thread, plainArray, key1, value));
319 JSHandle<JSTaggedValue> key2(thread, JSTaggedValue(int64_t(-9007199254740992))); // Out-of-Bounds test
320 EXPECT_FALSE(JSAPIPlainArray::SetProperty(thread, plainArray, key1, value));
321 }
322 } // namespace panda::test
323