• 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_tree_map_iterator.h"
17 #include "ecmascript/containers/containers_private.h"
18 #include "ecmascript/global_env.h"
19 #include "ecmascript/js_api/js_api_tree_map.h"
20 #include "ecmascript/js_iterator.h"
21 #include "ecmascript/tagged_tree.h"
22 #include "ecmascript/tests/test_helper.h"
23 
24 using namespace panda;
25 using namespace panda::ecmascript;
26 
27 namespace panda::test {
28 class JSAPITreeMapIteratorTest : public testing::Test {
29 public:
SetUpTestCase()30     static void SetUpTestCase()
31     {
32         GTEST_LOG_(INFO) << "SetUpTestCase";
33     }
34 
TearDownTestCase()35     static void TearDownTestCase()
36     {
37         GTEST_LOG_(INFO) << "TearDownCase";
38     }
39 
SetUp()40     void SetUp() override
41     {
42         TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
43     }
44 
TearDown()45     void TearDown() override
46     {
47         TestHelper::DestroyEcmaVMWithScope(instance, scope);
48     }
49 
50     EcmaVM *instance {nullptr};
51     ecmascript::EcmaHandleScope *scope {nullptr};
52     JSThread *thread {nullptr};
53 
54 protected:
CreateTreeMap()55     JSHandle<JSAPITreeMap> CreateTreeMap()
56     {
57         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
58         JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
59 
60         JSHandle<JSTaggedValue> globalObject = env->GetJSGlobalObject();
61         JSHandle<JSTaggedValue> key(factory->NewFromASCII("ArkPrivate"));
62         JSHandle<JSTaggedValue> value =
63             JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(globalObject), key).GetValue();
64 
65         auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
66         ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
67         ecmaRuntimeCallInfo->SetThis(value.GetTaggedValue());
68         ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int>(containers::ContainerTag::TreeMap)));
69 
70         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
71         JSTaggedValue result = containers::ContainersPrivate::Load(ecmaRuntimeCallInfo);
72         TestHelper::TearDownFrame(thread, prev);
73 
74         JSHandle<JSTaggedValue> constructor(thread, result);
75         JSHandle<JSAPITreeMap> jsTreeMap(
76             factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
77         JSTaggedValue internal = TaggedTreeMap::Create(thread);
78         jsTreeMap->SetTreeMap(thread, internal);
79         return jsTreeMap;
80     }
81 };
82 
83 /**
84  * @tc.name: SetIterationKind
85  * @tc.desc: Call the "SetIterationKind" function, check whether the result returned through "GetIterationKind"
86  *           function from the JSAPITreeMapIterator is within expectations.
87  * @tc.type: FUNC
88  * @tc.require:
89  */
HWTEST_F_L0(JSAPITreeMapIteratorTest,SetIterationKind)90 HWTEST_F_L0(JSAPITreeMapIteratorTest, SetIterationKind)
91 {
92     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
93     JSHandle<JSAPITreeMap> jsTreeMap = CreateTreeMap();
94     EXPECT_TRUE(*jsTreeMap != nullptr);
95     JSHandle<JSAPITreeMapIterator> treeMapIterator =
96         factory->NewJSAPITreeMapIterator(jsTreeMap, IterationKind::KEY);
97     EXPECT_EQ(treeMapIterator->GetIterationKind(), IterationKind::KEY);
98     treeMapIterator->SetIterationKind(IterationKind::VALUE);
99     EXPECT_EQ(treeMapIterator->GetIterationKind(), IterationKind::VALUE);
100     treeMapIterator->SetIterationKind(IterationKind::KEY_AND_VALUE);
101     EXPECT_EQ(treeMapIterator->GetIterationKind(), IterationKind::KEY_AND_VALUE);
102 }
103 
104 /**
105  * @tc.name: SetIteratedMap
106  * @tc.desc: Call the "SetIteratedMap" function, check whether the result returned through "GetIteratedMap"
107  *           function from the JSAPITreeMapIterator is within expectations.
108  * @tc.type: FUNC
109  * @tc.require:
110  */
HWTEST_F_L0(JSAPITreeMapIteratorTest,SetIteratedMap)111 HWTEST_F_L0(JSAPITreeMapIteratorTest, SetIteratedMap)
112 {
113     constexpr uint32_t DEFAULT_LENGTH = 8;
114     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
115     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
116     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
117     JSHandle<JSAPITreeMap> jsTreeMap = CreateTreeMap();
118     EXPECT_TRUE(*jsTreeMap != nullptr);
119     JSHandle<JSAPITreeMapIterator> treeMapIterator =
120         factory->NewJSAPITreeMapIterator(jsTreeMap, IterationKind::VALUE);
121 
122     std::string mapKey("mapkey");
123     std::string mapValue("mapvalue");
124     for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
125         std::string ikey = mapKey + std::to_string(i);
126         std::string ivalue = mapValue + std::to_string(i + 2U);
127         key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
128         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
129         JSAPITreeMap::Set(thread, jsTreeMap, key, value);
130     }
131     treeMapIterator->SetIteratedMap(thread, jsTreeMap.GetTaggedValue());
132     JSHandle<JSAPITreeMap> treeMapTo(thread, JSAPITreeMap::Cast(treeMapIterator->GetIteratedMap().GetTaggedObject()));
133     EXPECT_EQ(treeMapTo->GetSize(), static_cast<int>(DEFAULT_LENGTH));
134     for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
135         std::string ikey = mapKey + std::to_string(i);
136         std::string ivalue = mapValue + std::to_string(i + 2U);
137         key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
138         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
139         JSTaggedValue result = JSAPITreeMap::Get(thread, treeMapTo, key);
140         EXPECT_EQ(result, value.GetTaggedValue());
141     }
142 }
143 
144 /**
145  * @tc.name: SetNextIndex
146  * @tc.desc: Call the "SetNextIndex" function, check whether the result returned through "GetNextIndex"
147  *           function from the JSAPITreeMapIterator is within expectations.
148  * @tc.type: FUNC
149  * @tc.require:
150  */
HWTEST_F_L0(JSAPITreeMapIteratorTest,SetNextIndex)151 HWTEST_F_L0(JSAPITreeMapIteratorTest, SetNextIndex)
152 {
153     constexpr uint32_t DEFAULT_LENGTH = 8;
154     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
155     JSHandle<JSAPITreeMap> jsTreeMap = CreateTreeMap();
156     EXPECT_TRUE(*jsTreeMap != nullptr);
157     JSHandle<JSAPITreeMapIterator> treeMapIterator =
158         factory->NewJSAPITreeMapIterator(jsTreeMap, IterationKind::KEY_AND_VALUE);
159     EXPECT_EQ(treeMapIterator->GetNextIndex(), 0U);
160 
161     for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
162         treeMapIterator->SetNextIndex(i);
163         EXPECT_EQ(treeMapIterator->GetNextIndex(), i);
164     }
165 }
166 
167 /**
168  * @tc.name: CreateTreeMapIterator
169  * @tc.desc: Create TreeMap iterator, check whether the result returned through "IsJSAPITreeMapIterator"
170  *           function from the JSAPITreeMapIterator is within expectations.
171  * @tc.type: FUNC
172  * @tc.require:
173  */
HWTEST_F_L0(JSAPITreeMapIteratorTest,CreateTreeMapIterator)174 HWTEST_F_L0(JSAPITreeMapIteratorTest, CreateTreeMapIterator)
175 {
176     JSHandle<JSAPITreeMap> jsTreeMap = CreateTreeMap();
177     EXPECT_TRUE(*jsTreeMap != nullptr);
178     JSHandle<JSTaggedValue> treeMapVal(jsTreeMap);
179     // Create Iterator with KEY
180     JSHandle<JSTaggedValue> treeMapIterator =
181         JSAPITreeMapIterator::CreateTreeMapIterator(thread, treeMapVal, IterationKind::KEY);
182     EXPECT_TRUE(*treeMapIterator != nullptr);
183     EXPECT_TRUE(treeMapIterator->IsJSAPITreeMapIterator());
184     // Create Iterator with VALUE
185     treeMapIterator = JSAPITreeMapIterator::CreateTreeMapIterator(thread, treeMapVal, IterationKind::VALUE);
186     EXPECT_TRUE(*treeMapIterator != nullptr);
187     EXPECT_TRUE(treeMapIterator->IsJSAPITreeMapIterator());
188     // Create Iterator with KEY_AND_VALUE
189     treeMapIterator = JSAPITreeMapIterator::CreateTreeMapIterator(thread, treeMapVal, IterationKind::KEY_AND_VALUE);
190     EXPECT_TRUE(*treeMapIterator != nullptr);
191     EXPECT_TRUE(treeMapIterator->IsJSAPITreeMapIterator());
192 }
193 
194 /**
195  * @tc.name: Next
196  * @tc.desc: Create an iterator of JSAPITreeMap,and then loop through the elements(key,value and keyAndvalue) of the
197  *           iterator to check whether the elements through "Next" function are consistent.
198  * @tc.type: FUNC
199  * @tc.require:
200  */
HWTEST_F_L0(JSAPITreeMapIteratorTest,KEY_Next)201 HWTEST_F_L0(JSAPITreeMapIteratorTest, KEY_Next)
202 {
203     constexpr uint32_t DEFAULT_LENGTH = 8;
204     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
205     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
206     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
207     JSHandle<JSTaggedValue> valueStr = thread->GlobalConstants()->GetHandledValueString();
208     JSHandle<JSAPITreeMap> jsTreeMap = CreateTreeMap();
209     std::string mapKey("mapkey");
210     std::string mapValue("mapvalue");
211     for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
212         std::string ikey = mapKey + std::to_string(i);
213         std::string ivalue = mapValue + std::to_string(i);
214         key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
215         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
216         JSAPITreeMap::Set(thread, jsTreeMap, key, value);
217     }
218     // Create Iterator with KEY
219     JSHandle<JSAPITreeMapIterator> treeMapKeyIterator =
220         factory->NewJSAPITreeMapIterator(jsTreeMap, IterationKind::KEY);
221     // traversal iterator
222     for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
223         auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
224         ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
225         ecmaRuntimeCallInfo->SetThis(treeMapKeyIterator.GetTaggedValue());
226 
227         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
228         JSTaggedValue result = JSAPITreeMapIterator::Next(ecmaRuntimeCallInfo);
229         TestHelper::TearDownFrame(thread, prev);
230 
231         JSHandle<JSObject> resultObj(thread, result);
232         std::string resultKey = mapKey + std::to_string(i);
233         key.Update(factory->NewFromStdString(resultKey).GetTaggedValue());
234         EXPECT_EQ(JSTaggedValue::SameValue(
235             JSObject::GetProperty(thread, resultObj, valueStr).GetValue(), key), true);
236         EXPECT_EQ(treeMapKeyIterator->GetNextIndex(), (i + 1U));
237     }
238 }
239 
HWTEST_F_L0(JSAPITreeMapIteratorTest,VALUE_Next)240 HWTEST_F_L0(JSAPITreeMapIteratorTest, VALUE_Next)
241 {
242     constexpr uint32_t DEFAULT_LENGTH = 8;
243     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
244     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
245     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
246     JSHandle<JSTaggedValue> valueStr = thread->GlobalConstants()->GetHandledValueString();
247     JSHandle<JSAPITreeMap> jsTreeMap = CreateTreeMap();
248     std::string mapKey("mapkey");
249     std::string mapValue("mapvalue");
250     for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
251         std::string ikey = mapKey + std::to_string(i);
252         std::string ivalue = mapValue + std::to_string(i + 1U);
253         key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
254         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
255         JSAPITreeMap::Set(thread, jsTreeMap, key, value);
256     }
257     // Create Iterator with VALUE
258     JSHandle<JSAPITreeMapIterator> treeMapKeyIterator =
259         factory->NewJSAPITreeMapIterator(jsTreeMap, IterationKind::VALUE);
260     // traversal iterator
261     for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
262         auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
263         ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
264         ecmaRuntimeCallInfo->SetThis(treeMapKeyIterator.GetTaggedValue());
265 
266         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
267         JSTaggedValue result = JSAPITreeMapIterator::Next(ecmaRuntimeCallInfo);
268         TestHelper::TearDownFrame(thread, prev);
269 
270         JSHandle<JSObject> resultObj(thread, result);
271         std::string resultKey = mapValue + std::to_string(i + 1U);
272         value.Update(factory->NewFromStdString(resultKey).GetTaggedValue());
273         EXPECT_EQ(JSTaggedValue::SameValue(
274             JSObject::GetProperty(thread, resultObj, valueStr).GetValue(), value), true);
275         EXPECT_EQ(treeMapKeyIterator->GetNextIndex(), (i + 1U));
276     }
277 }
278 
HWTEST_F_L0(JSAPITreeMapIteratorTest,KEY_AND_VALUE_Next)279 HWTEST_F_L0(JSAPITreeMapIteratorTest, KEY_AND_VALUE_Next)
280 {
281     constexpr uint32_t DEFAULT_LENGTH = 8;
282     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
283     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
284     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
285     JSHandle<JSTaggedValue> valueStr = thread->GlobalConstants()->GetHandledValueString();
286     JSHandle<JSAPITreeMap> jsTreeMap = CreateTreeMap();
287     std::string mapKey("mapkey");
288     std::string mapValue("mapvalue");
289     for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
290         std::string ikey = mapKey + std::to_string(i + 1U);
291         std::string ivalue = mapValue + std::to_string(i + 2U);
292         key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
293         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
294         JSAPITreeMap::Set(thread, jsTreeMap, key, value);
295     }
296     // Create Iterator with KEY_AND_VALUE
297     JSHandle<JSAPITreeMapIterator> treeMapKeyIterator =
298         factory->NewJSAPITreeMapIterator(jsTreeMap, IterationKind::KEY_AND_VALUE);
299     // traversal iterator
300     for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
301         auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
302         ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
303         ecmaRuntimeCallInfo->SetThis(treeMapKeyIterator.GetTaggedValue());
304 
305         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
306         JSTaggedValue result = JSAPITreeMapIterator::Next(ecmaRuntimeCallInfo);
307         TestHelper::TearDownFrame(thread, prev);
308 
309         JSHandle<JSObject> resultObj(thread, result);
310         std::string resultKeyAndValue = mapKey + std::to_string(i + 1U);
311         value.Update(factory->NewFromStdString(resultKeyAndValue).GetTaggedValue());
312 
313         JSHandle<JSTaggedValue> keyValueArr(JSObject::GetProperty(thread, resultObj, valueStr).GetValue());
314         for (int index = 0; index < 2; index++) {
315             JSHandle<JSTaggedValue> indexValue(thread, JSTaggedValue(index));
316             EXPECT_EQ(JSTaggedValue::SameValue(
317                 JSObject::GetProperty(thread, keyValueArr, indexValue).GetValue(), value), true);
318             resultKeyAndValue = mapValue + std::to_string(i + 2U);
319             value.Update(factory->NewFromStdString(resultKeyAndValue).GetTaggedValue());
320         }
321         EXPECT_EQ(treeMapKeyIterator->GetNextIndex(), (i + 1U));
322     }
323 }
324 
325 /**
326  * @tc.name: Next and CreateTreeMapIterator
327  * @tc.desc: test special return of Next and CreateTreeMapIterator,
328  *           including throw exception and return undefined
329  * @tc.type: FUNC
330  * @tc.require:
331  */
HWTEST_F_L0(JSAPITreeMapIteratorTest,SpecailReturnOfNextCreateTreeMapIterator)332 HWTEST_F_L0(JSAPITreeMapIteratorTest, SpecailReturnOfNextCreateTreeMapIterator)
333 {
334     JSHandle<JSAPITreeMap> jsTreeMap = CreateTreeMap();
335     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
336     JSHandle<JSAPITreeMapIterator> treeMapIterator = factory->NewJSAPITreeMapIterator(
337         jsTreeMap, IterationKind::KEY_AND_VALUE);
338     treeMapIterator->SetIteratedMap(thread, JSTaggedValue::Undefined());
339 
340     // test Next exception
341     {
342         auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
343         ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
344         ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
345 
346         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
347         JSTaggedValue result = JSAPITreeMapIterator::Next(ecmaRuntimeCallInfo);
348         TestHelper::TearDownFrame(thread, prev);
349         EXPECT_EQ(result, JSTaggedValue::Exception());
350         EXPECT_EXCEPTION();
351     }
352 
353     // test Next return undefined
354     {
355         auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
356         ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
357         ecmaRuntimeCallInfo->SetThis(treeMapIterator.GetTaggedValue());
358 
359         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
360         JSTaggedValue result = JSAPITreeMapIterator::Next(ecmaRuntimeCallInfo);
361         TestHelper::TearDownFrame(thread, prev);
362         EXPECT_EQ(result, thread->GlobalConstants()->GetUndefinedIterResult());
363     }
364 
365     // test CreateTreeMapIterator exception
366     {
367         JSHandle<JSTaggedValue> undefined(thread, JSTaggedValue::Undefined());
368         JSHandle<JSTaggedValue> result =
369             JSAPITreeMapIterator::CreateTreeMapIterator(thread, undefined, IterationKind::KEY_AND_VALUE);
370         EXPECT_EQ(result.GetTaggedValue(), JSTaggedValue::Exception());
371         EXPECT_EXCEPTION();
372     }
373 }
374 }  // namespace panda::ecmascript
375