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/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/js_api_tree_set.h"
21 #include "ecmascript/js_api/js_api_tree_set_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.h"
29 #include "ecmascript/tests/ecma_test_common.h"
30
31 using namespace panda;
32
33 using namespace panda::ecmascript;
34
35 namespace panda::test {
36 class JSAPITreeSetTest : public BaseTestWithScope<false> {
37 protected:
CreateTreeSet()38 JSAPITreeSet *CreateTreeSet()
39 {
40 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
41 auto result = TestCommon::CreateContainerTaggedValue(thread, containers::ContainerTag::TreeSet);
42 JSHandle<JSTaggedValue> constructor(thread, result);
43 JSHandle<JSAPITreeSet> set(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
44 JSTaggedValue internal = TaggedTreeSet::Create(thread);
45 set->SetTreeSet(thread, internal);
46 return *set;
47 }
48
TestCommon(JSMutableHandle<JSTaggedValue> & key,std::string & myKey,uint32_t nums)49 JSHandle<JSAPITreeSet> TestCommon(JSMutableHandle<JSTaggedValue>& key, std::string& myKey, uint32_t nums)
50 {
51 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
52 // test JSAPITreeSet
53 JSHandle<JSAPITreeSet> tset(thread, CreateTreeSet());
54 for (int i = 0; i < nums; i++) {
55 std::string ikey = myKey + std::to_string(i);
56 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
57 JSAPITreeSet::Add(thread, tset, key);
58 }
59 EXPECT_EQ(tset->GetSize(), nums);
60 return tset;
61 }
62 };
63
HWTEST_F_L0(JSAPITreeSetTest,TreeSetCreate)64 HWTEST_F_L0(JSAPITreeSetTest, TreeSetCreate)
65 {
66 JSAPITreeSet *set = CreateTreeSet();
67 EXPECT_TRUE(set != nullptr);
68 }
69
HWTEST_F_L0(JSAPITreeSetTest,TreeSetAddAndHas)70 HWTEST_F_L0(JSAPITreeSetTest, TreeSetAddAndHas)
71 {
72 constexpr int NODE_NUMBERS = 8;
73 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
74 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
75
76 // test JSAPITreeSet
77 std::string myKey("mykey");
78 auto tset = TestCommon(key, myKey, NODE_NUMBERS);
79
80 // test Add exception
81 key.Update(JSTaggedValue::Hole());
82 JSAPITreeSet::Add(thread, tset, key);
83 EXPECT_EXCEPTION();
84
85 for (int i = 0; i < NODE_NUMBERS; i++) {
86 std::string ikey = myKey + std::to_string(i);
87 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
88
89 // test has
90 bool has = JSAPITreeSet::Has(thread, tset, key);
91 EXPECT_EQ(has, true);
92 }
93 }
94
HWTEST_F_L0(JSAPITreeSetTest,TreeSetDeleteAndHas)95 HWTEST_F_L0(JSAPITreeSetTest, TreeSetDeleteAndHas)
96 {
97 constexpr int NODE_NUMBERS = 64;
98 constexpr int REMOVE_SIZE = 48;
99 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
100 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
101
102 // test JSAPITreeSet
103 std::string myKey("mykey");
104 auto tset = TestCommon(key, myKey, NODE_NUMBERS);
105
106 // test delete
107 {
108 std::string ikey = myKey + std::to_string(NODE_NUMBERS);
109 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
110 bool success = JSAPITreeSet::Delete(thread, tset, key);
111 EXPECT_EQ(success, false);
112 }
113
114 for (int i = 0; i < REMOVE_SIZE; i++) {
115 std::string ikey = myKey + std::to_string(i);
116 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
117 bool success = JSAPITreeSet::Delete(thread, tset, key);
118 EXPECT_EQ(success, true);
119 }
120 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS - REMOVE_SIZE);
121
122 for (int i = 0; i < REMOVE_SIZE; i++) {
123 std::string ikey = myKey + std::to_string(i);
124 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
125
126 // test has
127 bool has = JSAPITreeSet::Has(thread, tset, key);
128 EXPECT_EQ(has, false);
129 }
130
131 for (int i = REMOVE_SIZE; i < NODE_NUMBERS; i++) {
132 std::string ikey = myKey + std::to_string(i);
133 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
134
135 // test has
136 bool has = JSAPITreeSet::Has(thread, tset, key);
137 EXPECT_EQ(has, true);
138 }
139 }
140
HWTEST_F_L0(JSAPITreeSetTest,TreeSetClear)141 HWTEST_F_L0(JSAPITreeSetTest, TreeSetClear)
142 {
143 constexpr int NODE_NUMBERS = 8;
144 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
145 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
146
147 // test TaggedTreeSet
148 std::string myKey("mykey");
149 auto tset = TestCommon(key, myKey, NODE_NUMBERS);
150
151 JSAPITreeSet::Clear(thread, tset);
152 EXPECT_EQ(tset->GetSize(), 0);
153 for (int i = 0; i < NODE_NUMBERS; i++) {
154 std::string ikey = myKey + std::to_string(i);
155 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
156
157 // test has
158 bool has = JSAPITreeSet::Has(thread, tset, key);
159 EXPECT_EQ(has, false);
160 }
161 }
162
HWTEST_F_L0(JSAPITreeSetTest,TreeSetPop)163 HWTEST_F_L0(JSAPITreeSetTest, TreeSetPop)
164 {
165 constexpr int NODE_NUMBERS = 8;
166 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
167 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
168
169 // test TaggedTreeSet
170 JSHandle<JSAPITreeSet> tset(thread, CreateTreeSet());
171
172 // test popFirst and popLast of empty treeset
173 JSTaggedValue fvalue1 = JSAPITreeSet::PopFirst(thread, tset);
174 EXPECT_EQ(fvalue1, JSTaggedValue::Undefined());
175 JSTaggedValue lvalue1 = JSAPITreeSet::PopFirst(thread, tset);
176 EXPECT_EQ(lvalue1, JSTaggedValue::Undefined());
177
178 std::string myKey("mykey");
179 for (int i = 0; i < NODE_NUMBERS; i++) {
180 std::string ikey = myKey + std::to_string(i);
181 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
182 JSAPITreeSet::Add(thread, tset, key);
183 }
184 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS);
185
186 // test popFirst
187 std::string fkey = myKey + std::to_string(0);
188 key.Update(factory->NewFromStdString(fkey).GetTaggedValue());
189 JSTaggedValue fvalue = JSAPITreeSet::PopFirst(thread, tset);
190 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS - 1);
191 EXPECT_EQ(fvalue, key.GetTaggedValue());
192 bool has = JSAPITreeSet::Has(thread, tset, key);
193 EXPECT_EQ(has, false);
194
195 // test popLast
196 std::string lkey = myKey + std::to_string(NODE_NUMBERS - 1);
197 key.Update(factory->NewFromStdString(lkey).GetTaggedValue());
198 JSTaggedValue lvalue = JSAPITreeSet::PopLast(thread, tset);
199 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS - 2);
200 EXPECT_EQ(lvalue, key.GetTaggedValue());
201 has = JSAPITreeSet::Has(thread, tset, key);
202 EXPECT_EQ(has, false);
203 }
204
HWTEST_F_L0(JSAPITreeSetTest,JSAPITreeSetIterator)205 HWTEST_F_L0(JSAPITreeSetTest, JSAPITreeSetIterator)
206 {
207 constexpr int NODE_NUMBERS = 8;
208 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
209 JSHandle<JSAPITreeSet> tset(thread, CreateTreeSet());
210
211 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
212 for (int i = 0; i < NODE_NUMBERS; i++) {
213 key.Update(JSTaggedValue(i));
214 JSAPITreeSet::Add(thread, tset, key);
215 }
216
217 // test key or value
218 JSHandle<JSTaggedValue> keyIter(factory->NewJSAPITreeSetIterator(tset, IterationKind::KEY));
219 JSHandle<JSTaggedValue> valueIter(factory->NewJSAPITreeSetIterator(tset, IterationKind::VALUE));
220 JSMutableHandle<JSTaggedValue> keyIterResult(thread, JSTaggedValue::Undefined());
221 JSMutableHandle<JSTaggedValue> valueIterResult(thread, JSTaggedValue::Undefined());
222 for (int i = 0; i < NODE_NUMBERS / 2; i++) {
223 keyIterResult.Update(JSIterator::IteratorStep(thread, keyIter).GetTaggedValue());
224 valueIterResult.Update(JSIterator::IteratorStep(thread, valueIter).GetTaggedValue());
225 EXPECT_EQ(i, JSIterator::IteratorValue(thread, keyIterResult)->GetInt());
226 EXPECT_EQ(i, JSIterator::IteratorValue(thread, valueIterResult)->GetInt());
227 }
228
229 // test key and value
230 JSHandle<JSTaggedValue> indexKey(thread, JSTaggedValue(0));
231 JSHandle<JSTaggedValue> elementKey(thread, JSTaggedValue(1));
232 JSHandle<JSTaggedValue> iter(factory->NewJSAPITreeSetIterator(tset, IterationKind::KEY_AND_VALUE));
233 JSMutableHandle<JSTaggedValue> iterResult(thread, JSTaggedValue::Undefined());
234 JSMutableHandle<JSTaggedValue> result(thread, JSTaggedValue::Undefined());
235 for (int i = 0; i < NODE_NUMBERS; i++) {
236 iterResult.Update(JSIterator::IteratorStep(thread, iter).GetTaggedValue());
237 result.Update(JSIterator::IteratorValue(thread, iterResult).GetTaggedValue());
238 EXPECT_EQ(i, JSObject::GetProperty(thread, result, indexKey).GetValue()->GetInt());
239 EXPECT_EQ(i, JSObject::GetProperty(thread, result, elementKey).GetValue()->GetInt());
240 }
241
242 // test delete
243 key.Update(JSTaggedValue(NODE_NUMBERS / 2));
244 bool success = JSAPITreeSet::Delete(thread, tset, key);
245 EXPECT_EQ(success, true);
246 for (int i = NODE_NUMBERS / 2 + 1; i < NODE_NUMBERS; i++) {
247 keyIterResult.Update(JSIterator::IteratorStep(thread, keyIter).GetTaggedValue());
248 valueIterResult.Update(JSIterator::IteratorStep(thread, valueIter).GetTaggedValue());
249 EXPECT_EQ(i, JSIterator::IteratorValue(thread, keyIterResult)->GetInt());
250 EXPECT_EQ(i, JSIterator::IteratorValue(thread, valueIterResult)->GetInt());
251 }
252
253 // test set
254 key.Update(JSTaggedValue(NODE_NUMBERS));
255 JSAPITreeSet::Add(thread, tset, key);
256 keyIterResult.Update(JSIterator::IteratorStep(thread, keyIter).GetTaggedValue());
257 EXPECT_EQ(NODE_NUMBERS, JSIterator::IteratorValue(thread, keyIterResult)->GetInt());
258
259 // test end
260 keyIterResult.Update(JSIterator::IteratorStep(thread, keyIter).GetTaggedValue());
261 EXPECT_EQ(JSTaggedValue::False(), keyIterResult.GetTaggedValue());
262 }
263
HWTEST_F_L0(JSAPITreeSetTest,TreeSetGetKey)264 HWTEST_F_L0(JSAPITreeSetTest, TreeSetGetKey)
265 {
266 constexpr int NODE_NUMBERS = 8;
267 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
268
269 // init treeset
270 JSHandle<JSAPITreeSet> tset(thread, CreateTreeSet());
271 for (int i = 0; i < NODE_NUMBERS; i++) {
272 key.Update(JSTaggedValue(i));
273 JSAPITreeSet::Add(thread, tset, key);
274 }
275 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS);
276
277 // test GetKey
278 for (int i = 0; i < NODE_NUMBERS; i++) {
279 EXPECT_EQ(tset->GetKey(i), JSTaggedValue(i));
280 }
281 EXPECT_EQ(tset->GetKey(-1), JSTaggedValue::Undefined());
282 }
283 } // namespace panda::test
284