• 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/test_helper.h"
29 
30 using namespace panda;
31 
32 using namespace panda::ecmascript;
33 
34 namespace panda::test {
35 class JSAPIPlainArrayTest : public testing::Test {
36 public:
SetUpTestCase()37     static void SetUpTestCase()
38     {
39         GTEST_LOG_(INFO) << "SetUpTestCase";
40     }
41 
TearDownTestCase()42     static void TearDownTestCase()
43     {
44         GTEST_LOG_(INFO) << "TearDownCase";
45     }
46 
SetUp()47     void SetUp() override
48     {
49         TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
50     }
51 
TearDown()52     void TearDown() override
53     {
54         TestHelper::DestroyEcmaVMWithScope(instance, scope);
55     }
56 
57     EcmaVM *instance {nullptr};
58     ecmascript::EcmaHandleScope *scope {nullptr};
59     JSThread *thread {nullptr};
60 
61 protected:
CreatePlainArray()62     JSAPIPlainArray *CreatePlainArray()
63     {
64         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
65         JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
66 
67         JSHandle<JSTaggedValue> globalObject = env->GetJSGlobalObject();
68         JSHandle<JSTaggedValue> key(factory->NewFromASCII("ArkPrivate"));
69         JSHandle<JSTaggedValue> value =
70             JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(globalObject), key).GetValue();
71 
72         auto objCallInfo =
73             TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); // 6 means the value
74         objCallInfo->SetFunction(JSTaggedValue::Undefined());
75         objCallInfo->SetThis(value.GetTaggedValue());
76         objCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int>(containers::ContainerTag::PlainArray)));
77 
78         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
79         JSTaggedValue result = containers::ContainersPrivate::Load(objCallInfo);
80         TestHelper::TearDownFrame(thread, prev);
81 
82         JSHandle<JSTaggedValue> constructor(thread, result);
83         JSHandle<JSAPIPlainArray> plainArray(
84             factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
85         JSHandle<JSTaggedValue> keyArray = JSHandle<JSTaggedValue>(factory->NewTaggedArray(8)); // 8 means the value
86         JSHandle<JSTaggedValue> valueArray = JSHandle<JSTaggedValue>(factory->NewTaggedArray(8)); // 8 means the value
87         plainArray->SetKeys(thread, keyArray);
88         plainArray->SetValues(thread, valueArray);
89         return *plainArray;
90     }
91 };
92 
HWTEST_F_L0(JSAPIPlainArrayTest,PlainArrayCreate)93 HWTEST_F_L0(JSAPIPlainArrayTest, PlainArrayCreate)
94 {
95     JSAPIPlainArray *plainArray = CreatePlainArray();
96     EXPECT_TRUE(plainArray != nullptr);
97 }
98 
HWTEST_F_L0(JSAPIPlainArrayTest,PA_AddAndGetKeyAtAndClear)99 HWTEST_F_L0(JSAPIPlainArrayTest, PA_AddAndGetKeyAtAndClear)
100 {
101     constexpr uint32_t NODE_NUMBERS = 8; // 8 means the value
102     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
103     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
104     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
105 
106     // test JSAPIPlainArray
107     JSHandle<JSAPIPlainArray> array(thread, CreatePlainArray());
108     std::string myValue("myvalue");
109     for (uint32_t i = 0; i < NODE_NUMBERS; i = i + 2) {
110         uint32_t ikey = 100 + i;
111         std::string ivalue = myValue + std::to_string(i);
112 
113         key.Update(JSTaggedValue(ikey));
114         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
115 
116         JSAPIPlainArray::Add(thread, array, key, value);
117     }
118     for (uint32_t i = 1; i < NODE_NUMBERS; i = i + 2) {
119         uint32_t ikey = 100 + i;
120         std::string ivalue = myValue + std::to_string(i);
121 
122         key.Update(JSTaggedValue(ikey));
123         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
124 
125         JSAPIPlainArray::Add(thread, array, key, value);
126     }
127     EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS));
128 
129     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
130         uint32_t ikey = 100 + i;
131         std::string ivalue = myValue + std::to_string(i);
132         key.Update(JSTaggedValue(ikey));
133         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
134 
135         // test getKeyAt
136         JSTaggedValue gvalue = array->GetKeyAt(i);
137         EXPECT_EQ(gvalue, key.GetTaggedValue());
138     }
139     EXPECT_EQ(array->GetKeyAt(-1), JSTaggedValue::Undefined());
140     EXPECT_EQ(array->GetKeyAt(NODE_NUMBERS), JSTaggedValue::Undefined());
141     // test clear
142     array->Clear(thread);
143     EXPECT_EQ(array->GetSize(), 0); // 0 means the value
144 }
145 
HWTEST_F_L0(JSAPIPlainArrayTest,PA_CloneAndHasAndGet)146 HWTEST_F_L0(JSAPIPlainArrayTest, PA_CloneAndHasAndGet)
147 {
148     constexpr uint32_t NODE_NUMBERS = 8; // 8 means the value
149     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
150     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
151     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
152 
153     // test JSAPIPlainArray
154     JSHandle<JSAPIPlainArray> array(thread, CreatePlainArray());
155     std::string myValue("myvalue");
156     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
157         uint32_t ikey = 100 + i;
158         std::string ivalue = myValue + std::to_string(i);
159         key.Update(JSTaggedValue(ikey));
160         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
161         JSAPIPlainArray::Add(thread, array, key, value);
162     }
163     EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS));
164 
165     // test clone
166     JSHandle<JSAPIPlainArray> newArray(thread, CreatePlainArray());
167     EXPECT_EQ(newArray->GetSize(), 0); // 0 means the value
168     newArray = JSAPIPlainArray::Clone(thread, array);
169     EXPECT_EQ(newArray->GetSize(), static_cast<int>(NODE_NUMBERS));
170 
171     // test has
172     key.Update(JSTaggedValue(103)); // 103 means the value
173     int32_t lkey = 103;
174     bool result = array->Has(lkey);
175     EXPECT_TRUE(result);
176     EXPECT_FALSE(array->Has(lkey * 2));
177 
178     // test get
179     myValue = std::string("myvalue3");
180     value.Update(factory->NewFromStdString(myValue).GetTaggedValue());
181     EXPECT_TRUE(JSTaggedValue::Equal(thread, JSHandle<JSTaggedValue>(thread, array->Get(key.GetTaggedValue())), value));
182 }
183 
HWTEST_F_L0(JSAPIPlainArrayTest,PA_GetIndexOfKeyAndGeIndexOfValueAndIsEmptyAndRemoveRangeFrom)184 HWTEST_F_L0(JSAPIPlainArrayTest, PA_GetIndexOfKeyAndGeIndexOfValueAndIsEmptyAndRemoveRangeFrom)
185 {
186     constexpr uint32_t NODE_NUMBERS = 8; // 8 means the value
187     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
188     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
189     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
190 
191     JSHandle<JSAPIPlainArray> array(thread, CreatePlainArray());
192     EXPECT_TRUE(array->IsEmpty());
193     std::string myValue("myvalue");
194     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
195         uint32_t ikey = 100 + i;
196         std::string ivalue = myValue + std::to_string(i);
197         key.Update(JSTaggedValue(ikey));
198         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
199         JSAPIPlainArray::Add(thread, array, key, value);
200     }
201     EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS));
202     EXPECT_FALSE(array->IsEmpty());
203 
204     value.Update(JSTaggedValue(103)); // 103 means the value
205     int32_t lvalue = 103;
206     JSTaggedValue value2 = array->GetIndexOfKey(lvalue);
207     EXPECT_EQ(value2.GetNumber(), 3); // 3 means the value
208     EXPECT_EQ(array->GetIndexOfKey(lvalue * 2), JSTaggedValue(-1));
209 
210     myValue = "myvalue2";
211     value.Update(factory->NewFromStdString(myValue).GetTaggedValue());
212     JSTaggedValue value3 = array->GetIndexOfValue(value.GetTaggedValue());
213     EXPECT_EQ(value3.GetNumber(), 2); // 2 means the value
214     EXPECT_EQ(array->GetIndexOfValue(JSTaggedValue(0)), JSTaggedValue(-1));
215 
216     value.Update(JSTaggedValue(1));
217     int32_t batchSize = 3; // 3 means the value
218     lvalue = 1;
219     value3 = array->RemoveRangeFrom(thread, lvalue, batchSize);
220     EXPECT_EQ(value3.GetNumber(), 3); // 3 means the value
221     EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS - 3));
222 
223     // test RemoveRangeFrom exception
224     array->RemoveRangeFrom(thread, lvalue, -1);
225 }
226 
HWTEST_F_L0(JSAPIPlainArrayTest,PA_RemvoeAnrRemvoeAtAndSetValueAtAndGetValueAt)227 HWTEST_F_L0(JSAPIPlainArrayTest, PA_RemvoeAnrRemvoeAtAndSetValueAtAndGetValueAt)
228 {
229     constexpr uint32_t NODE_NUMBERS = 8; // 8 means the value
230     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
231     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
232     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
233 
234     JSHandle<JSAPIPlainArray> array(thread, CreatePlainArray());
235     EXPECT_TRUE(array->IsEmpty());
236     std::string myValue("myvalue");
237     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
238         uint32_t ikey = 100 + i;
239         std::string ivalue = myValue + std::to_string(i);
240         key.Update(JSTaggedValue(ikey));
241         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
242         JSAPIPlainArray::Add(thread, array, key, value);
243     }
244     EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS));
245     EXPECT_FALSE(array->IsEmpty());
246 
247     // test Remove
248     myValue = "myvalue2";
249     value.Update(factory->NewFromStdString(myValue).GetTaggedValue());
250     JSTaggedValue taggedValue =
251         array->Remove(thread, JSTaggedValue(102)); // 102 means the value
252     EXPECT_TRUE(JSTaggedValue::Equal(thread, value, JSHandle<JSTaggedValue>(thread, taggedValue)));
253     EXPECT_EQ(array->Remove(thread, JSTaggedValue(-1)), JSTaggedValue::Undefined());
254     EXPECT_EQ(array->Remove(thread, JSTaggedValue(100 + NODE_NUMBERS)), JSTaggedValue::Undefined());
255 
256     // test RemoveAt
257     myValue = "myvalue4";
258     value.Update(factory->NewFromStdString(myValue).GetTaggedValue());
259     taggedValue =
260         array->RemoveAt(thread, JSTaggedValue(3)); // 3 means the value
261     EXPECT_TRUE(JSTaggedValue::Equal(thread, value, JSHandle<JSTaggedValue>(thread, taggedValue)));
262     EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS - 2));
263     EXPECT_EQ(array->RemoveAt(thread, JSTaggedValue(-1)), JSTaggedValue::Undefined());
264     EXPECT_EQ(array->RemoveAt(thread, JSTaggedValue(NODE_NUMBERS)), JSTaggedValue::Undefined());
265 
266     // test SetValueAt
267     myValue = "myvalue14";
268     value.Update(factory->NewFromStdString(myValue).GetTaggedValue());
269     array->SetValueAt(thread, JSTaggedValue(3), value.GetTaggedValue()); // 3 means the value
270     int32_t lvalue = 3; // 3 means the value
271     taggedValue = array->GetValueAt(thread, lvalue);
272     EXPECT_TRUE(JSTaggedValue::Equal(thread, value, JSHandle<JSTaggedValue>(thread, taggedValue)));
273 }
274 
HWTEST_F_L0(JSAPIPlainArrayTest,PA_GetOwnProperty)275 HWTEST_F_L0(JSAPIPlainArrayTest, PA_GetOwnProperty)
276 {
277     constexpr uint32_t DEFAULT_LENGTH = 8;
278     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
279     JSHandle<JSAPIPlainArray> toor(thread, CreatePlainArray());
280     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
281     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
282 
283     std::string plainArrayvalue("plainArrayvalue");
284     for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
285         uint32_t ikey = 100 + i;
286         std::string ivalue = plainArrayvalue + std::to_string(i);
287         key.Update(JSTaggedValue(ikey));
288         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
289         JSAPIPlainArray::Add(thread, toor, key, value);
290     }
291     // test GetOwnProperty
292     int testInt = 100 + 1;
293     JSHandle<JSTaggedValue> plainArrayKey1(thread, JSTaggedValue(testInt));
294     EXPECT_TRUE(JSAPIPlainArray::GetOwnProperty(thread, toor, plainArrayKey1));
295     testInt = 100 + 20;
296     JSHandle<JSTaggedValue> plainArrayKey2(thread, JSTaggedValue(testInt));
297     EXPECT_FALSE(JSAPIPlainArray::GetOwnProperty(thread, toor, plainArrayKey2));
298 }
299 
HWTEST_F_L0(JSAPIPlainArrayTest,PA_ToString)300 HWTEST_F_L0(JSAPIPlainArrayTest, PA_ToString)
301 {
302     constexpr uint32_t NODE_NUMBERS = 3; // 3 means the value
303     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
304     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
305     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
306 
307     // test JSAPIPlainArray
308     JSHandle<JSAPIPlainArray> array(thread, CreatePlainArray());
309     JSTaggedValue result1 = JSAPIPlainArray::ToString(thread, array);
310     JSHandle<EcmaString> resultHandle1(thread, result1);
311     JSHandle<EcmaString> det = thread->GetEcmaVM()->GetFactory()->NewFromASCII("");
312     ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle1, det), 0);
313     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
314         uint32_t ikey = i;
315         std::string ivalue = std::to_string(i);
316         key.Update(JSTaggedValue(ikey));
317         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
318         JSAPIPlainArray::Add(thread, array, key, value);
319     }
320     JSHandle<EcmaString> str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0:0,1:1,2:2");
321     JSTaggedValue result = JSAPIPlainArray::ToString(thread, array);
322     JSHandle<EcmaString> resultHandle(thread, result);
323 
324     ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, str), 0);
325 }
326 
327 /**
328  * @tc.name: GetProperty
329  * @tc.desc:
330  * @tc.type: FUNC
331  * @tc.require:
332  */
HWTEST_F_L0(JSAPIPlainArrayTest,GetProperty)333 HWTEST_F_L0(JSAPIPlainArrayTest, GetProperty)
334 {
335     JSHandle<JSAPIPlainArray> plainArray(thread, CreatePlainArray());
336     uint32_t elementsNums = 8;
337     for (uint32_t i = 0; i < elementsNums; i++) {
338         JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
339         JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
340         JSAPIPlainArray::Add(thread, plainArray, key, value);
341     }
342     for (uint32_t i = 0; i < elementsNums; i++) {
343         JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
344         OperationResult getPropertyRes = JSAPIPlainArray::GetProperty(thread, plainArray, key);
345         EXPECT_EQ(getPropertyRes.GetValue().GetTaggedValue(), JSTaggedValue(i));
346     }
347 }
348 
349 /**
350  * @tc.name: SetProperty
351  * @tc.desc:
352  * @tc.type: FUNC
353  * @tc.require:
354  */
HWTEST_F_L0(JSAPIPlainArrayTest,SetProperty)355 HWTEST_F_L0(JSAPIPlainArrayTest, SetProperty)
356 {
357     JSHandle<JSAPIPlainArray> plainArray(thread, CreatePlainArray());
358     uint32_t elementsNums = 8;
359     for (uint32_t i = 0; i < elementsNums; i++) {
360         JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
361         JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
362         JSAPIPlainArray::Add(thread, plainArray, key, value);
363     }
364     for (uint32_t i = 0; i < elementsNums; i++) {
365         JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
366         JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i * 2)); // 2 : It means double
367         bool setPropertyRes = JSAPIPlainArray::SetProperty(thread, plainArray, key, value);
368         EXPECT_EQ(setPropertyRes, true);
369     }
370     JSHandle<JSTaggedValue> key(thread, JSTaggedValue(-1));
371     JSHandle<JSTaggedValue> value(thread, JSTaggedValue(-1));
372     EXPECT_FALSE(JSAPIPlainArray::SetProperty(thread, plainArray, key, value));
373     JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(elementsNums));
374     EXPECT_FALSE(JSAPIPlainArray::SetProperty(thread, plainArray, key1, value));
375 }
376 }  // namespace panda::test
377