• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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/containers/containers_private.h"
17 #include "ecmascript/ecma_string.h"
18 #include "ecmascript/ecma_vm.h"
19 #include "ecmascript/global_env.h"
20 #include "ecmascript/js_api_tree_map.h"
21 #include "ecmascript/js_api_tree_map_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/tagged_tree-inl.h"
29 #include "ecmascript/tests/test_helper.h"
30 
31 using namespace panda;
32 
33 using namespace panda::ecmascript;
34 
35 namespace panda::test {
36 class JSAPITreeMapTest : public testing::Test {
37 public:
SetUpTestCase()38     static void SetUpTestCase()
39     {
40         GTEST_LOG_(INFO) << "SetUpTestCase";
41     }
42 
TearDownTestCase()43     static void TearDownTestCase()
44     {
45         GTEST_LOG_(INFO) << "TearDownCase";
46     }
47 
SetUp()48     void SetUp() override
49     {
50         TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
51     }
52 
TearDown()53     void TearDown() override
54     {
55         TestHelper::DestroyEcmaVMWithScope(instance, scope);
56     }
57 
58     PandaVM *instance {nullptr};
59     ecmascript::EcmaHandleScope *scope {nullptr};
60     JSThread *thread {nullptr};
61 
62 protected:
CreateTreeMap()63     JSAPITreeMap *CreateTreeMap()
64     {
65         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
66         JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
67 
68         JSHandle<JSTaggedValue> globalObject = env->GetJSGlobalObject();
69         JSHandle<JSTaggedValue> key(factory->NewFromCanBeCompressString("ArkPrivate"));
70         JSHandle<JSTaggedValue> value =
71             JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(globalObject), key).GetValue();
72 
73         auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
74         objCallInfo->SetFunction(JSTaggedValue::Undefined());
75         objCallInfo->SetThis(value.GetTaggedValue());
76         objCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int>(containers::ContainerTag::TreeMap)));
77 
78         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo.get());
79         JSTaggedValue result = containers::ContainersPrivate::Load(objCallInfo.get());
80         TestHelper::TearDownFrame(thread, prev);
81 
82         JSHandle<JSTaggedValue> constructor(thread, result);
83         JSHandle<JSAPITreeMap> map(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
84         JSTaggedValue internal = TaggedTreeMap::Create(thread);
85         map->SetTreeMap(thread, internal);
86         return *map;
87     }
88 };
89 
HWTEST_F_L0(JSAPITreeMapTest,TreeMapCreate)90 HWTEST_F_L0(JSAPITreeMapTest, TreeMapCreate)
91 {
92     JSAPITreeMap *map = CreateTreeMap();
93     EXPECT_TRUE(map != nullptr);
94 }
95 
HWTEST_F_L0(JSAPITreeMapTest,TreeMapSetAndGet)96 HWTEST_F_L0(JSAPITreeMapTest, TreeMapSetAndGet)
97 {
98     constexpr uint32_t NODE_NUMBERS = 8;
99     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
100     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
101     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
102 
103     // test JSAPITreeMap
104     JSHandle<JSAPITreeMap> tmap(thread, CreateTreeMap());
105     std::string myKey("mykey");
106     std::string myValue("myvalue");
107     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
108         std::string ikey = myKey + std::to_string(i);
109         std::string ivalue = myValue + std::to_string(i);
110         key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
111         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
112         JSAPITreeMap::Set(thread, tmap, key, value);
113     }
114     EXPECT_EQ(tmap->GetSize(), NODE_NUMBERS);
115 
116     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
117         std::string ikey = myKey + std::to_string(i);
118         std::string ivalue = myValue + std::to_string(i);
119         key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
120         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
121 
122         // test get
123         JSTaggedValue gvalue = JSAPITreeMap::Get(thread, tmap, key);
124         EXPECT_EQ(gvalue, value.GetTaggedValue());
125     }
126 }
127 
HWTEST_F_L0(JSAPITreeMapTest,TreeMapDeleteAndHas)128 HWTEST_F_L0(JSAPITreeMapTest, TreeMapDeleteAndHas)
129 {
130     constexpr uint32_t NODE_NUMBERS = 64;
131     constexpr uint32_t REMOVE_SIZE = 48;
132     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
133     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
134     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
135 
136     // test JSAPITreeMap
137     JSHandle<JSAPITreeMap> tmap(thread, CreateTreeMap());
138     std::string myKey("mykey");
139     std::string myValue("myvalue");
140     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
141         std::string ikey = myKey + std::to_string(i);
142         std::string ivalue = myValue + std::to_string(i);
143         key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
144         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
145         JSAPITreeMap::Set(thread, tmap, key, value);
146     }
147     EXPECT_EQ(tmap->GetSize(), NODE_NUMBERS);
148 
149     for (uint32_t i = 0; i < REMOVE_SIZE; i++) {
150         std::string ikey = myKey + std::to_string(i);
151         key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
152         [[maybe_unused]] JSTaggedValue dvalue = JSAPITreeMap::Delete(thread, tmap, key);
153     }
154     EXPECT_EQ(tmap->GetSize(), NODE_NUMBERS - REMOVE_SIZE);
155 
156     for (uint32_t i = 0; i < REMOVE_SIZE; i++) {
157         std::string ikey = myKey + std::to_string(i);
158         std::string ivalue = myValue + std::to_string(i);
159         key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
160         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
161 
162         // test has
163         bool hasKey = JSAPITreeMap::HasKey(thread, tmap, key);
164         EXPECT_EQ(hasKey, false);
165         bool hasValue = tmap->HasValue(thread, value);
166         EXPECT_EQ(hasValue, false);
167     }
168 
169     for (uint32_t i = REMOVE_SIZE; i < NODE_NUMBERS; i++) {
170         std::string ikey = myKey + std::to_string(i);
171         std::string ivalue = myValue + std::to_string(i);
172         key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
173         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
174 
175         // test has
176         bool hasKey = JSAPITreeMap::HasKey(thread, tmap, key);
177         EXPECT_EQ(hasKey, true);
178         bool hasValue = tmap->HasValue(thread, value);
179         EXPECT_EQ(hasValue, true);
180     }
181 }
182 
HWTEST_F_L0(JSAPITreeMapTest,TreeMapReplaceAndClear)183 HWTEST_F_L0(JSAPITreeMapTest, TreeMapReplaceAndClear)
184 {
185     constexpr uint32_t NODE_NUMBERS = 8;
186     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
187     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
188     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
189 
190     // test TaggedTreeMap
191     JSHandle<JSAPITreeMap> tmap(thread, CreateTreeMap());
192     std::string myKey("mykey");
193     std::string myValue("myvalue");
194     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
195         std::string ikey = myKey + std::to_string(i);
196         std::string ivalue = myValue + std::to_string(i);
197         key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
198         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
199         JSAPITreeMap::Set(thread, tmap, key, value);
200     }
201     EXPECT_EQ(tmap->GetSize(), NODE_NUMBERS);
202 
203     for (uint32_t i = 0; i < NODE_NUMBERS / 2; i++) {
204         std::string ikey = myKey + std::to_string(i);
205         std::string ivalue = myValue + std::to_string(i + 1);
206         key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
207         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
208 
209         // test replace
210         bool success = JSAPITreeMap::Replace(thread, tmap, key, value);
211         EXPECT_EQ(success, true);
212     }
213 
214     for (uint32_t i = 0; i < NODE_NUMBERS / 2; i++) {
215         std::string ikey = myKey + std::to_string(i);
216         std::string ivalue = myValue + std::to_string(i + 1);
217         key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
218         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
219 
220         // test get
221         JSTaggedValue gvalue = JSAPITreeMap::Get(thread, tmap, key);
222         EXPECT_EQ(gvalue, value.GetTaggedValue());
223     }
224 
225     for (uint32_t i = NODE_NUMBERS / 2; i < NODE_NUMBERS; i++) {
226         std::string ikey = myKey + std::to_string(i);
227         std::string ivalue = myValue + std::to_string(i);
228         key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
229         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
230 
231         // test get
232         JSTaggedValue gvalue = JSAPITreeMap::Get(thread, tmap, key);
233         EXPECT_EQ(gvalue, value.GetTaggedValue());
234     }
235 
236     for (uint32_t i = 0; i < NODE_NUMBERS / 2; i++) {
237         std::string ikey = myKey + std::to_string(i);
238         key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
239         [[maybe_unused]] JSTaggedValue dvalue = JSAPITreeMap::Delete(thread, tmap, key);
240     }
241 
242     JSAPITreeMap::Clear(thread, tmap);
243     EXPECT_EQ(tmap->GetSize(), 0);
244     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
245         std::string ikey = myKey + std::to_string(i);
246         std::string ivalue = myValue + std::to_string(i);
247         key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
248         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
249 
250         // test get
251         JSTaggedValue gvalue = JSAPITreeMap::Get(thread, tmap, key);
252         EXPECT_EQ(gvalue, JSTaggedValue::Undefined());
253 
254         // test has
255         bool hasKey = JSAPITreeMap::HasKey(thread, tmap, key);
256         EXPECT_EQ(hasKey, false);
257         bool hasValue = tmap->HasValue(thread, value);
258         EXPECT_EQ(hasValue, false);
259     }
260 }
261 
HWTEST_F_L0(JSAPITreeMapTest,JSAPITreeMapIterator)262 HWTEST_F_L0(JSAPITreeMapTest, JSAPITreeMapIterator)
263 {
264     constexpr uint32_t NODE_NUMBERS = 8;
265     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
266     JSHandle<JSAPITreeMap> tmap(thread, CreateTreeMap());
267 
268     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
269     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
270     for (int i = 0; i < NODE_NUMBERS; i++) {
271         key.Update(JSTaggedValue(i));
272         value.Update(JSTaggedValue(i + 1));
273         JSAPITreeMap::Set(thread, tmap, key, value);
274     }
275 
276     // test key or value
277     JSHandle<JSTaggedValue> keyIter(factory->NewJSAPITreeMapIterator(tmap, IterationKind::KEY));
278     JSHandle<JSTaggedValue> valueIter(factory->NewJSAPITreeMapIterator(tmap, IterationKind::VALUE));
279     JSMutableHandle<JSTaggedValue> keyIterResult(thread, JSTaggedValue::Undefined());
280     JSMutableHandle<JSTaggedValue> valueIterResult(thread, JSTaggedValue::Undefined());
281     for (int i = 0; i < NODE_NUMBERS / 2; i++) {
282         keyIterResult.Update(JSIterator::IteratorStep(thread, keyIter).GetTaggedValue());
283         valueIterResult.Update(JSIterator::IteratorStep(thread, valueIter).GetTaggedValue());
284         EXPECT_EQ(i, JSIterator::IteratorValue(thread, keyIterResult)->GetInt());
285         EXPECT_EQ(i + 1, JSIterator::IteratorValue(thread, valueIterResult)->GetInt());
286     }
287 
288     // test key and value
289     JSHandle<JSTaggedValue> indexKey(thread, JSTaggedValue(0));
290     JSHandle<JSTaggedValue> elementKey(thread, JSTaggedValue(1));
291     JSHandle<JSTaggedValue> iter(factory->NewJSAPITreeMapIterator(tmap, IterationKind::KEY_AND_VALUE));
292     JSMutableHandle<JSTaggedValue> iterResult(thread, JSTaggedValue::Undefined());
293     JSMutableHandle<JSTaggedValue> result(thread, JSTaggedValue::Undefined());
294     for (int i = 0; i < NODE_NUMBERS; i++) {
295         iterResult.Update(JSIterator::IteratorStep(thread, iter).GetTaggedValue());
296         result.Update(JSIterator::IteratorValue(thread, iterResult).GetTaggedValue());
297         EXPECT_EQ(i, JSObject::GetProperty(thread, result, indexKey).GetValue()->GetInt());
298         EXPECT_EQ(i + 1, JSObject::GetProperty(thread, result, elementKey).GetValue()->GetInt());
299     }
300 
301     // test delete
302     key.Update(JSTaggedValue(NODE_NUMBERS / 2));
303     JSTaggedValue dvalue = JSAPITreeMap::Delete(thread, tmap, key);
304     EXPECT_EQ(dvalue, JSTaggedValue(NODE_NUMBERS / 2 + 1));
305     for (int i = NODE_NUMBERS / 2 + 1; i < NODE_NUMBERS; i++) {
306         keyIterResult.Update(JSIterator::IteratorStep(thread, keyIter).GetTaggedValue());
307         valueIterResult.Update(JSIterator::IteratorStep(thread, valueIter).GetTaggedValue());
308         EXPECT_EQ(i, JSIterator::IteratorValue(thread, keyIterResult)->GetInt());
309         EXPECT_EQ(i + 1, JSIterator::IteratorValue(thread, valueIterResult)->GetInt());
310     }
311 
312     // test set
313     key.Update(JSTaggedValue(NODE_NUMBERS));
314     JSAPITreeMap::Set(thread, tmap, key, key);
315     keyIterResult.Update(JSIterator::IteratorStep(thread, keyIter).GetTaggedValue());
316     EXPECT_EQ(NODE_NUMBERS, JSIterator::IteratorValue(thread, keyIterResult)->GetInt());
317 
318     // test end
319     keyIterResult.Update(JSIterator::IteratorStep(thread, keyIter).GetTaggedValue());
320     EXPECT_EQ(JSTaggedValue::False(), keyIterResult.GetTaggedValue());
321 }
322 }  // namespace panda::test
323