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