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