• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(i);
118         EXPECT_EQ(gvalue, key.GetTaggedValue());
119     }
120     EXPECT_EQ(array->GetKeyAt(-1), JSTaggedValue::Undefined());
121     EXPECT_EQ(array->GetKeyAt(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(lkey);
156     EXPECT_TRUE(result);
157     EXPECT_FALSE(array->Has(lkey * 2));
158 
159     // test get
160     myValue = std::string("myvalue3");
161     value.Update(factory->NewFromStdString(myValue).GetTaggedValue());
162     EXPECT_TRUE(JSTaggedValue::Equal(thread, JSHandle<JSTaggedValue>(thread, array->Get(key.GetTaggedValue())), value));
163 }
164 
HWTEST_F_L0(JSAPIPlainArrayTest,PA_GetIndexOfKeyAndGeIndexOfValueAndIsEmptyAndRemoveRangeFrom)165 HWTEST_F_L0(JSAPIPlainArrayTest, PA_GetIndexOfKeyAndGeIndexOfValueAndIsEmptyAndRemoveRangeFrom)
166 {
167     constexpr uint32_t NODE_NUMBERS = 8; // 8 means the value
168     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
169     auto array = GetIndexOfKeyAndGeIndexOfValueGetArray(value, NODE_NUMBERS);
170     value.Update(JSTaggedValue(103)); // 103 means the value
171     int32_t lvalue = 103;
172     JSTaggedValue value2 = array->GetIndexOfKey(lvalue);
173     EXPECT_EQ(value2.GetNumber(), 3); // 3 means the value
174     EXPECT_EQ(array->GetIndexOfKey(lvalue * 2), JSTaggedValue(-1));
175 
176     std::string myValue = "myvalue2";
177     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
178     value.Update(factory->NewFromStdString(myValue).GetTaggedValue());
179     JSTaggedValue value3 = array->GetIndexOfValue(value.GetTaggedValue());
180     EXPECT_EQ(value3.GetNumber(), 2); // 2 means the value
181     EXPECT_EQ(array->GetIndexOfValue(JSTaggedValue(0)), JSTaggedValue(-1));
182 
183     value.Update(JSTaggedValue(1));
184     int32_t batchSize = 3; // 3 means the value
185     lvalue = 1;
186     value3 = array->RemoveRangeFrom(thread, lvalue, batchSize);
187     EXPECT_EQ(value3.GetNumber(), 3); // 3 means the value
188     EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS - 3));
189 
190     // test RemoveRangeFrom exception
191     array->RemoveRangeFrom(thread, lvalue, -1);
192 }
193 
HWTEST_F_L0(JSAPIPlainArrayTest,PA_RemvoeAnrRemvoeAtAndSetValueAtAndGetValueAt)194 HWTEST_F_L0(JSAPIPlainArrayTest, PA_RemvoeAnrRemvoeAtAndSetValueAtAndGetValueAt)
195 {
196     constexpr uint32_t NODE_NUMBERS = 8; // 8 means the value
197     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
198     auto array = GetIndexOfKeyAndGeIndexOfValueGetArray(value, NODE_NUMBERS);
199     // test Remove
200     std::string myValue = "myvalue2";
201     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
202     value.Update(factory->NewFromStdString(myValue).GetTaggedValue());
203     JSTaggedValue taggedValue =
204         array->Remove(thread, JSTaggedValue(102)); // 102 means the value
205     EXPECT_TRUE(JSTaggedValue::Equal(thread, value, JSHandle<JSTaggedValue>(thread, taggedValue)));
206     EXPECT_EQ(array->Remove(thread, JSTaggedValue(-1)), JSTaggedValue::Undefined());
207     EXPECT_EQ(array->Remove(thread, JSTaggedValue(100 + NODE_NUMBERS)), JSTaggedValue::Undefined());
208 
209     // test RemoveAt
210     myValue = "myvalue4";
211     value.Update(factory->NewFromStdString(myValue).GetTaggedValue());
212     taggedValue =
213         array->RemoveAt(thread, JSTaggedValue(3)); // 3 means the value
214     EXPECT_TRUE(JSTaggedValue::Equal(thread, value, JSHandle<JSTaggedValue>(thread, taggedValue)));
215     EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS - 2));
216     EXPECT_EQ(array->RemoveAt(thread, JSTaggedValue(-1)), JSTaggedValue::Undefined());
217     EXPECT_EQ(array->RemoveAt(thread, JSTaggedValue(NODE_NUMBERS)), JSTaggedValue::Undefined());
218 
219     // test SetValueAt
220     myValue = "myvalue14";
221     value.Update(factory->NewFromStdString(myValue).GetTaggedValue());
222     array->SetValueAt(thread, JSTaggedValue(3), value.GetTaggedValue()); // 3 means the value
223     int32_t lvalue = 3; // 3 means the value
224     taggedValue = array->GetValueAt(thread, lvalue);
225     EXPECT_TRUE(JSTaggedValue::Equal(thread, value, JSHandle<JSTaggedValue>(thread, taggedValue)));
226 }
227 
HWTEST_F_L0(JSAPIPlainArrayTest,PA_GetOwnProperty)228 HWTEST_F_L0(JSAPIPlainArrayTest, PA_GetOwnProperty)
229 {
230     constexpr uint32_t DEFAULT_LENGTH = 8;
231     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
232     JSHandle<JSAPIPlainArray> toor(thread, CreatePlainArray());
233     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
234     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
235 
236     std::string plainArrayvalue("plainArrayvalue");
237     for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
238         uint32_t ikey = 100 + i;
239         std::string ivalue = plainArrayvalue + std::to_string(i);
240         key.Update(JSTaggedValue(ikey));
241         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
242         JSAPIPlainArray::Add(thread, toor, key, value);
243     }
244     // test GetOwnProperty
245     int testInt = 100 + 1;
246     JSHandle<JSTaggedValue> plainArrayKey1(thread, JSTaggedValue(testInt));
247     EXPECT_TRUE(JSAPIPlainArray::GetOwnProperty(thread, toor, plainArrayKey1));
248     testInt = 100 + 20;
249     JSHandle<JSTaggedValue> plainArrayKey2(thread, JSTaggedValue(testInt));
250     EXPECT_FALSE(JSAPIPlainArray::GetOwnProperty(thread, toor, plainArrayKey2));
251 }
252 
HWTEST_F_L0(JSAPIPlainArrayTest,PA_ToString)253 HWTEST_F_L0(JSAPIPlainArrayTest, PA_ToString)
254 {
255     constexpr uint32_t NODE_NUMBERS = 3; // 3 means the value
256     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
257     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
258     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
259 
260     // test JSAPIPlainArray
261     JSHandle<JSAPIPlainArray> array(thread, CreatePlainArray());
262     JSTaggedValue result1 = JSAPIPlainArray::ToString(thread, array);
263     JSHandle<EcmaString> resultHandle1(thread, result1);
264     JSHandle<EcmaString> det = thread->GetEcmaVM()->GetFactory()->NewFromASCII("");
265     ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle1, det), 0);
266     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
267         uint32_t ikey = i;
268         std::string ivalue = std::to_string(i);
269         key.Update(JSTaggedValue(ikey));
270         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
271         JSAPIPlainArray::Add(thread, array, key, value);
272     }
273     JSHandle<EcmaString> str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0:0,1:1,2:2");
274     JSTaggedValue result = JSAPIPlainArray::ToString(thread, array);
275     JSHandle<EcmaString> resultHandle(thread, result);
276 
277     ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, str), 0);
278 }
279 
280 /**
281  * @tc.name: GetProperty
282  * @tc.desc:
283  * @tc.type: FUNC
284  * @tc.require:
285  */
HWTEST_F_L0(JSAPIPlainArrayTest,GetProperty)286 HWTEST_F_L0(JSAPIPlainArrayTest, GetProperty)
287 {
288     uint32_t elementsNums = 8;
289     auto plainArray = PropertyCommon(elementsNums);
290     for (uint32_t i = 0; i < elementsNums; i++) {
291         JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
292         OperationResult getPropertyRes = JSAPIPlainArray::GetProperty(thread, plainArray, key);
293         EXPECT_EQ(getPropertyRes.GetValue().GetTaggedValue(), JSTaggedValue(i));
294     }
295 }
296 
297 /**
298  * @tc.name: SetProperty
299  * @tc.desc:
300  * @tc.type: FUNC
301  * @tc.require:
302  */
HWTEST_F_L0(JSAPIPlainArrayTest,SetProperty)303 HWTEST_F_L0(JSAPIPlainArrayTest, SetProperty)
304 {
305     uint32_t elementsNums = 8;
306     auto plainArray = PropertyCommon(elementsNums);
307     for (uint32_t i = 0; i < elementsNums; i++) {
308         JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
309         JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i * 2)); // 2 : It means double
310         bool setPropertyRes = JSAPIPlainArray::SetProperty(thread, plainArray, key, value);
311         EXPECT_EQ(setPropertyRes, true);
312     }
313     JSHandle<JSTaggedValue> key(thread, JSTaggedValue(-1));
314     JSHandle<JSTaggedValue> value(thread, JSTaggedValue(-1));
315     EXPECT_FALSE(JSAPIPlainArray::SetProperty(thread, plainArray, key, value));
316     JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(elementsNums));
317     EXPECT_FALSE(JSAPIPlainArray::SetProperty(thread, plainArray, key1, value));
318     JSHandle<JSTaggedValue> key2(thread, JSTaggedValue(int64_t(-9007199254740992))); // Out-of-Bounds test
319     EXPECT_FALSE(JSAPIPlainArray::SetProperty(thread, plainArray, key1, value));
320 }
321 }  // namespace panda::test
322