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/containers/containers_treeset.h"
18 #include "ecmascript/ecma_runtime_call_info.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_handle.h"
23 #include "ecmascript/js_tagged_value-inl.h"
24 #include "ecmascript/js_thread.h"
25 #include "ecmascript/object_factory.h"
26 #include "ecmascript/tests/test_helper.h"
27 #include "ecmascript/containers/tests/containers_test_helper.h"
28
29 using namespace panda::ecmascript;
30 using namespace panda::ecmascript::containers;
31
32 namespace panda::test {
33 class ContainersTreeSetTest : public testing::Test {
34 public:
SetUpTestCase()35 static void SetUpTestCase()
36 {
37 GTEST_LOG_(INFO) << "SetUpTestCase";
38 }
39
TearDownTestCase()40 static void TearDownTestCase()
41 {
42 GTEST_LOG_(INFO) << "TearDownCase";
43 }
44
SetUp()45 void SetUp() override
46 {
47 TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
48 }
49
TearDown()50 void TearDown() override
51 {
52 TestHelper::DestroyEcmaVMWithScope(instance, scope);
53 }
54
55 EcmaVM *instance {nullptr};
56 EcmaHandleScope *scope {nullptr};
57 JSThread *thread {nullptr};
58
59 class TestClass : public base::BuiltinsBase {
60 public:
TestForEachFunc(EcmaRuntimeCallInfo * argv)61 static JSTaggedValue TestForEachFunc(EcmaRuntimeCallInfo *argv)
62 {
63 JSThread *thread = argv->GetThread();
64 JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
65 JSHandle<JSTaggedValue> key = GetCallArg(argv, 1);
66 JSHandle<JSAPITreeSet> set(GetCallArg(argv, 2)); // 2 means the second arg
67 EXPECT_EQ(key.GetTaggedValue(), value.GetTaggedValue());
68 JSAPITreeSet::Delete(thread, set, key);
69
70 JSHandle<JSAPITreeSet> jsTreeSet(GetThis(argv));
71 JSAPITreeSet::Add(thread, jsTreeSet, key);
72 return JSTaggedValue::Undefined();
73 }
74
TestCompareFunction(EcmaRuntimeCallInfo * argv)75 static JSTaggedValue TestCompareFunction(EcmaRuntimeCallInfo *argv)
76 {
77 JSThread *thread = argv->GetThread();
78 JSHandle<JSTaggedValue> valueX = GetCallArg(argv, 0);
79 JSHandle<JSTaggedValue> valueY = GetCallArg(argv, 1);
80
81 if (valueX->IsString() && valueY->IsString()) {
82 auto xHandle = JSHandle<EcmaString>(valueX);
83 auto yHandle = JSHandle<EcmaString>(valueY);
84 int result = EcmaStringAccessor::Compare(thread->GetEcmaVM(), xHandle, yHandle);
85 if (result < 0) {
86 return JSTaggedValue(1);
87 }
88 if (result == 0) {
89 return JSTaggedValue(0);
90 }
91 return JSTaggedValue(-1);
92 }
93
94 if (valueX->IsNumber() && valueY->IsString()) {
95 return JSTaggedValue(1);
96 }
97 if (valueX->IsString() && valueY->IsNumber()) {
98 return JSTaggedValue(-1);
99 }
100
101 ComparisonResult res = ComparisonResult::UNDEFINED;
102 if (valueX->IsNumber() && valueY->IsNumber()) {
103 res = JSTaggedValue::StrictNumberCompare(valueY->GetNumber(), valueX->GetNumber());
104 } else {
105 res = JSTaggedValue::Compare(thread, valueY, valueX);
106 }
107 return res == ComparisonResult::GREAT ?
108 JSTaggedValue(1) : (res == ComparisonResult::LESS ? JSTaggedValue(-1) : JSTaggedValue(0));
109 }
110 };
111
112 protected:
InitializeTreeSetConstructor()113 JSTaggedValue InitializeTreeSetConstructor()
114 {
115 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
116 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
117
118 JSHandle<JSTaggedValue> globalObject = env->GetJSGlobalObject();
119 JSHandle<JSTaggedValue> key(factory->NewFromASCII("ArkPrivate"));
120 JSHandle<JSTaggedValue> value =
121 JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(globalObject), key).GetValue();
122
123 auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
124 objCallInfo->SetFunction(JSTaggedValue::Undefined());
125 objCallInfo->SetThis(value.GetTaggedValue());
126 objCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int>(ContainerTag::TreeSet)));
127 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
128 JSTaggedValue result = ContainersPrivate::Load(objCallInfo);
129 TestHelper::TearDownFrame(thread, prev);
130
131 return result;
132 }
133
CreateJSAPITreeSet(JSTaggedValue compare=JSTaggedValue::Undefined ())134 JSHandle<JSAPITreeSet> CreateJSAPITreeSet(JSTaggedValue compare = JSTaggedValue::Undefined())
135 {
136 JSHandle<JSTaggedValue> compareHandle(thread, compare);
137 JSHandle<JSFunction> newTarget(thread, InitializeTreeSetConstructor());
138 auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
139 objCallInfo->SetFunction(newTarget.GetTaggedValue());
140 objCallInfo->SetNewTarget(newTarget.GetTaggedValue());
141 objCallInfo->SetThis(JSTaggedValue::Undefined());
142 objCallInfo->SetCallArg(0, compareHandle.GetTaggedValue());
143
144 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
145 JSTaggedValue result = ContainersTreeSet::TreeSetConstructor(objCallInfo);
146 TestHelper::TearDownFrame(thread, prev);
147 JSHandle<JSAPITreeSet> set(thread, result);
148 return set;
149 }
150 };
151
152 // new TreeSet()
HWTEST_F_L0(ContainersTreeSetTest,TreeSetConstructor)153 HWTEST_F_L0(ContainersTreeSetTest, TreeSetConstructor)
154 {
155 // Initialize twice and return directly the second time
156 InitializeTreeSetConstructor();
157 JSHandle<JSFunction> newTarget(thread, InitializeTreeSetConstructor());
158
159 auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
160 objCallInfo->SetFunction(newTarget.GetTaggedValue());
161 objCallInfo->SetNewTarget(newTarget.GetTaggedValue());
162 objCallInfo->SetThis(JSTaggedValue::Undefined());
163
164 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
165 JSTaggedValue result = ContainersTreeSet::TreeSetConstructor(objCallInfo);
166 TestHelper::TearDownFrame(thread, prev);
167
168 ASSERT_TRUE(result.IsJSAPITreeSet());
169 JSHandle<JSAPITreeSet> setHandle(thread, result);
170 JSTaggedValue resultProto = JSTaggedValue::GetPrototype(thread, JSHandle<JSTaggedValue>(setHandle));
171 JSTaggedValue funcProto = newTarget->GetFunctionPrototype();
172 ASSERT_EQ(resultProto, funcProto);
173 int size = setHandle->GetSize();
174 ASSERT_EQ(size, 0);
175
176 // test TreeSetConstructor exception
177 objCallInfo->SetCallArg(0, JSTaggedValue(0));
178 CONTAINERS_API_EXCEPTION_TEST(ContainersTreeSet, TreeSetConstructor, objCallInfo);
179 objCallInfo->SetNewTarget(JSTaggedValue::Undefined());
180 CONTAINERS_API_EXCEPTION_TEST(ContainersTreeSet, TreeSetConstructor, objCallInfo);
181 }
182
183 // treeset.add(value), treeset.has(value)
HWTEST_F_L0(ContainersTreeSetTest,AddAndHas)184 HWTEST_F_L0(ContainersTreeSetTest, AddAndHas)
185 {
186 constexpr int NODE_NUMBERS = 8;
187 JSHandle<JSAPITreeSet> tset = CreateJSAPITreeSet();
188 for (int i = 0; i < NODE_NUMBERS; i++) {
189 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
190 callInfo->SetFunction(JSTaggedValue::Undefined());
191 callInfo->SetThis(tset.GetTaggedValue());
192 callInfo->SetCallArg(0, JSTaggedValue(i));
193
194 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
195 JSTaggedValue result = ContainersTreeSet::Add(callInfo);
196 TestHelper::TearDownFrame(thread, prev);
197 EXPECT_TRUE(result.IsTrue());
198 EXPECT_EQ(tset->GetSize(), i + 1);
199 }
200 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS);
201
202 // test add string
203 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
204 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
205 std::string myKey("mykey");
206 for (int i = 0; i < NODE_NUMBERS; i++) {
207 std::string ikey = myKey + std::to_string(i);
208 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
209
210 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
211 callInfo->SetFunction(JSTaggedValue::Undefined());
212 callInfo->SetThis(tset.GetTaggedValue());
213 callInfo->SetCallArg(0, key.GetTaggedValue());
214
215 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
216 JSTaggedValue result = ContainersTreeSet::Add(callInfo);
217 TestHelper::TearDownFrame(thread, prev);
218 EXPECT_TRUE(result.IsTrue());
219 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS + i + 1);
220 }
221 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS * 2);
222
223 for (int i = 0; i < NODE_NUMBERS; i++) {
224 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
225 callInfo->SetFunction(JSTaggedValue::Undefined());
226 callInfo->SetThis(tset.GetTaggedValue());
227 callInfo->SetCallArg(0, JSTaggedValue(i));
228
229 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
230 JSTaggedValue result = ContainersTreeSet::Has(callInfo);
231 TestHelper::TearDownFrame(thread, prev);
232 EXPECT_TRUE(result.IsTrue());
233 }
234 for (int i = 0; i < NODE_NUMBERS; i++) {
235 std::string ikey = myKey + std::to_string(i);
236 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
237
238 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
239 callInfo->SetFunction(JSTaggedValue::Undefined());
240 callInfo->SetThis(tset.GetTaggedValue());
241 callInfo->SetCallArg(0, key.GetTaggedValue());
242
243 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
244 JSTaggedValue result = ContainersTreeSet::Has(callInfo);
245 TestHelper::TearDownFrame(thread, prev);
246 EXPECT_TRUE(result.IsTrue());
247 }
248 }
249
250 // treeset.remove(key)
HWTEST_F_L0(ContainersTreeSetTest,Remove)251 HWTEST_F_L0(ContainersTreeSetTest, Remove)
252 {
253 constexpr int NODE_NUMBERS = 64;
254 constexpr int REMOVE_SIZE = 48;
255 JSHandle<JSAPITreeSet> tset = CreateJSAPITreeSet();
256 for (int i = 0; i < NODE_NUMBERS; i++) {
257 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
258 callInfo->SetFunction(JSTaggedValue::Undefined());
259 callInfo->SetThis(tset.GetTaggedValue());
260 callInfo->SetCallArg(0, JSTaggedValue(i));
261
262 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
263 JSTaggedValue result = ContainersTreeSet::Add(callInfo);
264 TestHelper::TearDownFrame(thread, prev);
265 EXPECT_TRUE(result.IsTrue());
266 EXPECT_EQ(tset->GetSize(), i + 1);
267 }
268
269 for (int i = 0; i < REMOVE_SIZE; i++) {
270 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
271 callInfo->SetFunction(JSTaggedValue::Undefined());
272 callInfo->SetThis(tset.GetTaggedValue());
273 callInfo->SetCallArg(0, JSTaggedValue(i));
274
275 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
276 JSTaggedValue rvalue = ContainersTreeSet::Remove(callInfo);
277 TestHelper::TearDownFrame(thread, prev);
278 EXPECT_TRUE(rvalue.IsTrue());
279 }
280 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS - REMOVE_SIZE);
281
282 for (int i = 0; i < NODE_NUMBERS; i++) {
283 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
284 callInfo->SetFunction(JSTaggedValue::Undefined());
285 callInfo->SetThis(tset.GetTaggedValue());
286 callInfo->SetCallArg(0, JSTaggedValue(i));
287
288 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
289 JSTaggedValue result = ContainersTreeSet::Has(callInfo);
290 TestHelper::TearDownFrame(thread, prev);
291 if (i < REMOVE_SIZE) {
292 EXPECT_TRUE(result.IsFalse());
293 } else {
294 EXPECT_TRUE(result.IsTrue());
295 }
296 }
297
298 // test add string
299 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
300 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
301 std::string myKey("mykey");
302 for (int i = 0; i < NODE_NUMBERS; i++) {
303 std::string ikey = myKey + std::to_string(i);
304 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
305
306 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
307 callInfo->SetFunction(JSTaggedValue::Undefined());
308 callInfo->SetThis(tset.GetTaggedValue());
309 callInfo->SetCallArg(0, key.GetTaggedValue());
310
311 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
312 JSTaggedValue result = ContainersTreeSet::Add(callInfo);
313 TestHelper::TearDownFrame(thread, prev);
314 EXPECT_TRUE(result.IsTrue());
315 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS - REMOVE_SIZE + i + 1);
316 }
317 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS * 2 - REMOVE_SIZE);
318
319 for (int i = 0; i < REMOVE_SIZE; i++) {
320 std::string ikey = myKey + std::to_string(i);
321 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
322
323 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
324 callInfo->SetFunction(JSTaggedValue::Undefined());
325 callInfo->SetThis(tset.GetTaggedValue());
326 callInfo->SetCallArg(0, key.GetTaggedValue());
327
328 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
329 JSTaggedValue rvalue = ContainersTreeSet::Remove(callInfo);
330 TestHelper::TearDownFrame(thread, prev);
331 EXPECT_TRUE(rvalue.IsTrue());
332 }
333 EXPECT_EQ(tset->GetSize(), (NODE_NUMBERS - REMOVE_SIZE) * 2);
334 for (int i = 0; i < NODE_NUMBERS; i++) {
335 std::string ikey = myKey + std::to_string(i);
336 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
337
338 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
339 callInfo->SetFunction(JSTaggedValue::Undefined());
340 callInfo->SetThis(tset.GetTaggedValue());
341 callInfo->SetCallArg(0, key.GetTaggedValue());
342
343 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
344 JSTaggedValue result = ContainersTreeSet::Has(callInfo);
345 TestHelper::TearDownFrame(thread, prev);
346 if (i < REMOVE_SIZE) {
347 EXPECT_TRUE(result.IsFalse());
348 } else {
349 EXPECT_TRUE(result.IsTrue());
350 }
351 }
352 }
353
354 // treeset.getFirstValue(), treeset.getLastValue()
HWTEST_F_L0(ContainersTreeSetTest,GetFirstValueAndGetLastValue)355 HWTEST_F_L0(ContainersTreeSetTest, GetFirstValueAndGetLastValue)
356 {
357 constexpr int NODE_NUMBERS = 8;
358 JSHandle<JSAPITreeSet> tset = CreateJSAPITreeSet();
359 for (int i = 0; i < NODE_NUMBERS; i++) {
360 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
361 callInfo->SetFunction(JSTaggedValue::Undefined());
362 callInfo->SetThis(tset.GetTaggedValue());
363 callInfo->SetCallArg(0, JSTaggedValue(i));
364
365 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
366 JSTaggedValue result = ContainersTreeSet::Add(callInfo);
367 TestHelper::TearDownFrame(thread, prev);
368 EXPECT_TRUE(result.IsTrue());
369 EXPECT_EQ(tset->GetSize(), i + 1);
370 }
371 // test getFirstValue
372 {
373 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
374 callInfo->SetFunction(JSTaggedValue::Undefined());
375 callInfo->SetThis(tset.GetTaggedValue());
376
377 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
378 JSTaggedValue result = ContainersTreeSet::GetFirstValue(callInfo);
379 TestHelper::TearDownFrame(thread, prev);
380 EXPECT_EQ(result, JSTaggedValue(0));
381 }
382 // test getLastValue
383 {
384 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
385 callInfo->SetFunction(JSTaggedValue::Undefined());
386 callInfo->SetThis(tset.GetTaggedValue());
387
388 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
389 JSTaggedValue result = ContainersTreeSet::GetLastValue(callInfo);
390 TestHelper::TearDownFrame(thread, prev);
391 EXPECT_EQ(result, JSTaggedValue(NODE_NUMBERS - 1));
392 }
393
394 // test add string
395 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
396 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
397 std::string myKey("mykey");
398 for (int i = 0; i < NODE_NUMBERS; i++) {
399 std::string ikey = myKey + std::to_string(i);
400 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
401
402 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
403 callInfo->SetFunction(JSTaggedValue::Undefined());
404 callInfo->SetThis(tset.GetTaggedValue());
405 callInfo->SetCallArg(0, key.GetTaggedValue());
406
407 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
408 JSTaggedValue result = ContainersTreeSet::Add(callInfo);
409 TestHelper::TearDownFrame(thread, prev);
410 EXPECT_TRUE(result.IsTrue());
411 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS + i + 1);
412 }
413 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS * 2);
414
415 // test getFirstValue
416 {
417 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
418 callInfo->SetFunction(JSTaggedValue::Undefined());
419 callInfo->SetThis(tset.GetTaggedValue());
420
421 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
422 JSTaggedValue result = ContainersTreeSet::GetFirstValue(callInfo);
423 TestHelper::TearDownFrame(thread, prev);
424 EXPECT_EQ(result, JSTaggedValue(0));
425 }
426 // test getLastValue
427 {
428 std::string ikey = myKey + std::to_string(NODE_NUMBERS - 1);
429 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
430
431 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
432 callInfo->SetFunction(JSTaggedValue::Undefined());
433 callInfo->SetThis(tset.GetTaggedValue());
434
435 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
436 JSTaggedValue result = ContainersTreeSet::GetLastValue(callInfo);
437 TestHelper::TearDownFrame(thread, prev);
438 EXPECT_EQ(result, key.GetTaggedValue());
439 }
440 }
441
442 // treeset.clear()
HWTEST_F_L0(ContainersTreeSetTest,Clear)443 HWTEST_F_L0(ContainersTreeSetTest, Clear)
444 {
445 constexpr int NODE_NUMBERS = 8;
446 JSHandle<JSAPITreeSet> tset = CreateJSAPITreeSet();
447 for (int i = 0; i < NODE_NUMBERS; i++) {
448 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
449 callInfo->SetFunction(JSTaggedValue::Undefined());
450 callInfo->SetThis(tset.GetTaggedValue());
451 callInfo->SetCallArg(0, JSTaggedValue(i));
452
453 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
454 JSTaggedValue result = ContainersTreeSet::Add(callInfo);
455 TestHelper::TearDownFrame(thread, prev);
456 EXPECT_TRUE(result.IsTrue());
457 EXPECT_EQ(tset->GetSize(), i + 1);
458 }
459 // test clear
460 {
461 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
462 callInfo->SetFunction(JSTaggedValue::Undefined());
463 callInfo->SetThis(tset.GetTaggedValue());
464
465 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
466 ContainersTreeSet::Clear(callInfo);
467 TestHelper::TearDownFrame(thread, prev);
468 EXPECT_EQ(tset->GetSize(), 0);
469 }
470 for (int i = 0; i < NODE_NUMBERS; i++) {
471 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
472 callInfo->SetFunction(JSTaggedValue::Undefined());
473 callInfo->SetThis(tset.GetTaggedValue());
474 callInfo->SetCallArg(0, JSTaggedValue(i));
475
476 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
477 JSTaggedValue result = ContainersTreeSet::Has(callInfo);
478 TestHelper::TearDownFrame(thread, prev);
479 EXPECT_TRUE(result.IsFalse());
480 }
481
482 // test add string
483 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
484 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
485 std::string myKey("mykey");
486 for (int i = 0; i < NODE_NUMBERS; i++) {
487 std::string ikey = myKey + std::to_string(i);
488 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
489
490 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
491 callInfo->SetFunction(JSTaggedValue::Undefined());
492 callInfo->SetThis(tset.GetTaggedValue());
493 callInfo->SetCallArg(0, key.GetTaggedValue());
494
495 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
496 JSTaggedValue result = ContainersTreeSet::Add(callInfo);
497 TestHelper::TearDownFrame(thread, prev);
498 EXPECT_TRUE(result.IsTrue());
499 EXPECT_EQ(tset->GetSize(), i + 1);
500 }
501 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS);
502 // test clear
503 {
504 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
505 callInfo->SetFunction(JSTaggedValue::Undefined());
506 callInfo->SetThis(tset.GetTaggedValue());
507
508 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
509 ContainersTreeSet::Clear(callInfo);
510 TestHelper::TearDownFrame(thread, prev);
511 EXPECT_EQ(tset->GetSize(), 0);
512 }
513 for (int i = 0; i < NODE_NUMBERS; i++) {
514 std::string ikey = myKey + std::to_string(i);
515 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
516
517 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
518 callInfo->SetFunction(JSTaggedValue::Undefined());
519 callInfo->SetThis(tset.GetTaggedValue());
520 callInfo->SetCallArg(0, key.GetTaggedValue());
521
522 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
523 JSTaggedValue result = ContainersTreeSet::Has(callInfo);
524 TestHelper::TearDownFrame(thread, prev);
525 EXPECT_TRUE(result.IsFalse());
526 }
527 }
528
529 // treeset.getLowerValue(value), treeset.getHigherValue(value)
HWTEST_F_L0(ContainersTreeSetTest,GetLowerValueAndGetHigherValue)530 HWTEST_F_L0(ContainersTreeSetTest, GetLowerValueAndGetHigherValue)
531 {
532 constexpr int NODE_NUMBERS = 8;
533 JSHandle<JSAPITreeSet> tset = CreateJSAPITreeSet();
534 for (int i = 0; i < NODE_NUMBERS; i++) {
535 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
536 callInfo->SetFunction(JSTaggedValue::Undefined());
537 callInfo->SetThis(tset.GetTaggedValue());
538 callInfo->SetCallArg(0, JSTaggedValue(i));
539
540 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
541 JSTaggedValue result = ContainersTreeSet::Add(callInfo);
542 TestHelper::TearDownFrame(thread, prev);
543 EXPECT_TRUE(result.IsTrue());
544 EXPECT_EQ(tset->GetSize(), i + 1);
545 }
546
547 // test getLowerValue
548 for (int i = 0; i <= NODE_NUMBERS; i++) {
549 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
550 callInfo->SetFunction(JSTaggedValue::Undefined());
551 callInfo->SetThis(tset.GetTaggedValue());
552 callInfo->SetCallArg(0, JSTaggedValue(i));
553 if (i == NODE_NUMBERS) {
554 callInfo->SetCallArg(0, JSTaggedValue::Undefined());
555 }
556
557 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
558 JSTaggedValue result = ContainersTreeSet::GetLowerValue(callInfo);
559 TestHelper::TearDownFrame(thread, prev);
560 if (i == 0) {
561 EXPECT_EQ(result, JSTaggedValue::Undefined());
562 } else if (i == NODE_NUMBERS) {
563 EXPECT_TRUE(thread->HasPendingException());
564 EXPECT_EQ(result, JSTaggedValue::Exception());
565 thread->ClearException();
566 } else {
567 EXPECT_EQ(result, JSTaggedValue(i - 1));
568 }
569 }
570 // test getHigherValue
571 for (int i = 0; i <= NODE_NUMBERS; i++) {
572 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
573 callInfo->SetFunction(JSTaggedValue::Undefined());
574 callInfo->SetThis(tset.GetTaggedValue());
575 callInfo->SetCallArg(0, JSTaggedValue(i));
576
577 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
578 JSTaggedValue result = ContainersTreeSet::GetHigherValue(callInfo);
579 TestHelper::TearDownFrame(thread, prev);
580 if (i >= NODE_NUMBERS - 1) {
581 EXPECT_EQ(result, JSTaggedValue::Undefined());
582 } else {
583 EXPECT_EQ(result, JSTaggedValue(i + 1));
584 }
585 }
586
587 // test add string
588 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
589 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
590 std::string myKey("mykey");
591 for (int i = 0; i < NODE_NUMBERS; i++) {
592 std::string ikey = myKey + std::to_string(i);
593 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
594
595 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
596 callInfo->SetFunction(JSTaggedValue::Undefined());
597 callInfo->SetThis(tset.GetTaggedValue());
598 callInfo->SetCallArg(0, key.GetTaggedValue());
599
600 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
601 JSTaggedValue result = ContainersTreeSet::Add(callInfo);
602 TestHelper::TearDownFrame(thread, prev);
603 EXPECT_TRUE(result.IsTrue());
604 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS + i + 1);
605 }
606 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS * 2);
607
608 // test getLowerValue
609 // using to compare the result of GetLowerValue
610 JSMutableHandle<JSTaggedValue> resultKey(thread, JSTaggedValue::Undefined());
611 for (int i = 0; i <= NODE_NUMBERS; i++) {
612 std::string ikey = myKey + std::to_string(i);
613 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
614 std::string rkey = myKey + std::to_string(i - 1);
615 resultKey.Update(factory->NewFromStdString(rkey).GetTaggedValue());
616
617 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
618 callInfo->SetFunction(JSTaggedValue::Undefined());
619 callInfo->SetThis(tset.GetTaggedValue());
620 callInfo->SetCallArg(0, key.GetTaggedValue());
621
622 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
623 JSTaggedValue result = ContainersTreeSet::GetLowerValue(callInfo);
624 TestHelper::TearDownFrame(thread, prev);
625 if (i == 0) {
626 EXPECT_EQ(result, JSTaggedValue(NODE_NUMBERS - 1));
627 } else {
628 EXPECT_EQ(result, resultKey.GetTaggedValue());
629 }
630 }
631 // test getHigherValue
632 for (int i = 0; i < NODE_NUMBERS; i++) {
633 std::string ikey = myKey + std::to_string(i);
634 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
635 std::string rkey = myKey + std::to_string(i + 1);
636 resultKey.Update(factory->NewFromStdString(rkey).GetTaggedValue());
637
638 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
639 callInfo->SetFunction(JSTaggedValue::Undefined());
640 callInfo->SetThis(tset.GetTaggedValue());
641 callInfo->SetCallArg(0, key.GetTaggedValue());
642
643 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
644 JSTaggedValue result = ContainersTreeSet::GetHigherValue(callInfo);
645 TestHelper::TearDownFrame(thread, prev);
646 if (i == NODE_NUMBERS - 1) {
647 EXPECT_EQ(result, JSTaggedValue::Undefined());
648 } else {
649 EXPECT_TRUE(JSTaggedValue::SameValue(result, resultKey.GetTaggedValue()));
650 }
651 }
652 }
653
654 // treeset.popFirst(), treeset.popLast()
HWTEST_F_L0(ContainersTreeSetTest,PopFirstAndPopLast)655 HWTEST_F_L0(ContainersTreeSetTest, PopFirstAndPopLast)
656 {
657 constexpr int NODE_NUMBERS = 8;
658 JSHandle<JSAPITreeSet> tset = CreateJSAPITreeSet();
659 for (int i = 0; i < NODE_NUMBERS; i++) {
660 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
661 callInfo->SetFunction(JSTaggedValue::Undefined());
662 callInfo->SetThis(tset.GetTaggedValue());
663 callInfo->SetCallArg(0, JSTaggedValue(i));
664
665 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
666 JSTaggedValue result = ContainersTreeSet::Add(callInfo);
667 TestHelper::TearDownFrame(thread, prev);
668 EXPECT_TRUE(result.IsTrue());
669 EXPECT_EQ(tset->GetSize(), i + 1);
670 }
671
672 // test popFirst
673 {
674 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
675 callInfo->SetFunction(JSTaggedValue::Undefined());
676 callInfo->SetThis(tset.GetTaggedValue());
677
678 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
679 JSTaggedValue result = ContainersTreeSet::PopFirst(callInfo);
680 TestHelper::TearDownFrame(thread, prev);
681 EXPECT_EQ(result, JSTaggedValue(0));
682 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS - 1);
683 }
684 // test popLast
685 {
686 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
687 callInfo->SetFunction(JSTaggedValue::Undefined());
688 callInfo->SetThis(tset.GetTaggedValue());
689
690 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
691 JSTaggedValue result = ContainersTreeSet::PopLast(callInfo);
692 TestHelper::TearDownFrame(thread, prev);
693 EXPECT_EQ(result, JSTaggedValue(NODE_NUMBERS - 1));
694 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS - 2); // 2 means two elements
695 }
696
697 // test add string
698 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
699 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
700 std::string myKey("mykey");
701 for (int i = 0; i < NODE_NUMBERS; i++) {
702 std::string ikey = myKey + std::to_string(i);
703 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
704
705 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
706 callInfo->SetFunction(JSTaggedValue::Undefined());
707 callInfo->SetThis(tset.GetTaggedValue());
708 callInfo->SetCallArg(0, key.GetTaggedValue());
709
710 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
711 JSTaggedValue result = ContainersTreeSet::Add(callInfo);
712 TestHelper::TearDownFrame(thread, prev);
713 EXPECT_TRUE(result.IsTrue());
714 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS + i - 1);
715 }
716 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS * 2 - 2);
717
718 // test popFirst
719 {
720 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
721 callInfo->SetFunction(JSTaggedValue::Undefined());
722 callInfo->SetThis(tset.GetTaggedValue());
723
724 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
725 JSTaggedValue result = ContainersTreeSet::PopFirst(callInfo);
726 TestHelper::TearDownFrame(thread, prev);
727 EXPECT_EQ(result, JSTaggedValue(1));
728 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS * 2 - 3); // 3 means three elements
729 }
730 // test popLast
731 {
732 std::string ikey = myKey + std::to_string(NODE_NUMBERS - 1);
733 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
734
735 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
736 callInfo->SetFunction(JSTaggedValue::Undefined());
737 callInfo->SetThis(tset.GetTaggedValue());
738
739 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
740 JSTaggedValue result = ContainersTreeSet::PopLast(callInfo);
741 TestHelper::TearDownFrame(thread, prev);
742 EXPECT_EQ(result, key.GetTaggedValue());
743 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS * 2 - 4); // 4 means four elements
744 }
745 }
746
747 // testset.isEmpty()
HWTEST_F_L0(ContainersTreeSetTest,IsEmpty)748 HWTEST_F_L0(ContainersTreeSetTest, IsEmpty)
749 {
750 constexpr int NODE_NUMBERS = 8;
751 JSHandle<JSAPITreeSet> tset = CreateJSAPITreeSet();
752 // test isEmpty
753 {
754 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
755 callInfo->SetFunction(JSTaggedValue::Undefined());
756 callInfo->SetThis(tset.GetTaggedValue());
757
758 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
759 JSTaggedValue result = ContainersTreeSet::IsEmpty(callInfo);
760 TestHelper::TearDownFrame(thread, prev);
761 EXPECT_TRUE(result.IsTrue());
762 EXPECT_EQ(tset->GetSize(), 0);
763 }
764
765 // add elements
766 for (int i = 0; i < NODE_NUMBERS; i++) {
767 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
768 callInfo->SetFunction(JSTaggedValue::Undefined());
769 callInfo->SetThis(tset.GetTaggedValue());
770 callInfo->SetCallArg(0, JSTaggedValue(i));
771
772 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
773 JSTaggedValue result = ContainersTreeSet::Add(callInfo);
774 TestHelper::TearDownFrame(thread, prev);
775 EXPECT_TRUE(result.IsTrue());
776 EXPECT_EQ(tset->GetSize(), i + 1);
777 }
778 // test isEmpty
779 {
780 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
781 callInfo->SetFunction(JSTaggedValue::Undefined());
782 callInfo->SetThis(tset.GetTaggedValue());
783
784 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
785 JSTaggedValue result = ContainersTreeSet::IsEmpty(callInfo);
786 TestHelper::TearDownFrame(thread, prev);
787 EXPECT_TRUE(result.IsFalse());
788 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS);
789 }
790 }
791
792 // treeset.values(), treeset.entries()
HWTEST_F_L0(ContainersTreeSetTest,KeysAndValuesAndEntries)793 HWTEST_F_L0(ContainersTreeSetTest, KeysAndValuesAndEntries)
794 {
795 constexpr int NODE_NUMBERS = 8;
796 JSHandle<JSAPITreeSet> tset = CreateJSAPITreeSet();
797 for (int i = 0; i < NODE_NUMBERS; i++) {
798 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
799 callInfo->SetFunction(JSTaggedValue::Undefined());
800 callInfo->SetThis(tset.GetTaggedValue());
801 callInfo->SetCallArg(0, JSTaggedValue(i));
802
803 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
804 JSTaggedValue result = ContainersTreeSet::Add(callInfo);
805 TestHelper::TearDownFrame(thread, prev);
806 EXPECT_TRUE(result.IsTrue());
807 EXPECT_EQ(tset->GetSize(), i + 1);
808 }
809
810 // test values
811 auto callInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
812 callInfo1->SetFunction(JSTaggedValue::Undefined());
813 callInfo1->SetThis(tset.GetTaggedValue());
814 [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, callInfo1);
815 JSHandle<JSTaggedValue> iterValues(thread, ContainersTreeSet::Values(callInfo1));
816 TestHelper::TearDownFrame(thread, prev1);
817 EXPECT_TRUE(iterValues->IsJSAPITreeSetIterator());
818 {
819 JSMutableHandle<JSTaggedValue> result(thread, JSTaggedValue::Undefined());
820 for (int i = 0; i < NODE_NUMBERS; i++) {
821 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
822 callInfo->SetFunction(JSTaggedValue::Undefined());
823 callInfo->SetThis(iterValues.GetTaggedValue());
824
825 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
826 result.Update(JSAPITreeSetIterator::Next(callInfo));
827 TestHelper::TearDownFrame(thread, prev);
828 EXPECT_EQ(i, JSIterator::IteratorValue(thread, result)->GetInt());
829 }
830 }
831 // test add string
832 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
833 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
834 std::string myKey("mykey");
835 for (int i = 0; i < NODE_NUMBERS; i++) {
836 std::string ikey = myKey + std::to_string(i);
837 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
838
839 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
840 callInfo->SetFunction(JSTaggedValue::Undefined());
841 callInfo->SetThis(tset.GetTaggedValue());
842 callInfo->SetCallArg(0, key.GetTaggedValue());
843
844 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
845 JSTaggedValue result = ContainersTreeSet::Add(callInfo);
846 TestHelper::TearDownFrame(thread, prev);
847 EXPECT_TRUE(result.IsTrue());
848 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS + i + 1);
849 }
850 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS * 2);
851 {
852 JSMutableHandle<JSTaggedValue> result(thread, JSTaggedValue::Undefined());
853 for (int i = 0; i < NODE_NUMBERS; i++) {
854 std::string ikey = myKey + std::to_string(i);
855 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
856
857 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
858 callInfo->SetFunction(JSTaggedValue::Undefined());
859 callInfo->SetThis(iterValues.GetTaggedValue());
860
861 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
862 result.Update(JSAPITreeSetIterator::Next(callInfo));
863 TestHelper::TearDownFrame(thread, prev);
864 JSHandle<JSTaggedValue> itRes = JSIterator::IteratorValue(thread, result);
865 EXPECT_TRUE(JSTaggedValue::SameValue(key, itRes));
866 }
867 }
868 // test entries
869 {
870 auto callInfo2 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
871 callInfo2->SetFunction(JSTaggedValue::Undefined());
872 callInfo2->SetThis(tset.GetTaggedValue());
873 [[maybe_unused]] auto prev2 = TestHelper::SetupFrame(thread, callInfo2);
874 JSHandle<JSTaggedValue> iter(thread, ContainersTreeSet::Entries(callInfo2));
875 TestHelper::TearDownFrame(thread, prev2);
876 EXPECT_TRUE(iter->IsJSAPITreeSetIterator());
877
878 JSHandle<JSTaggedValue> first(thread, JSTaggedValue(0));
879 JSHandle<JSTaggedValue> second(thread, JSTaggedValue(1));
880 JSMutableHandle<JSTaggedValue> result(thread, JSTaggedValue::Undefined());
881 JSMutableHandle<JSTaggedValue> entries(thread, JSTaggedValue::Undefined());
882 for (int i = 0; i < NODE_NUMBERS; i++) {
883 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
884 callInfo->SetFunction(JSTaggedValue::Undefined());
885 callInfo->SetThis(iter.GetTaggedValue());
886
887 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
888 result.Update(JSAPITreeSetIterator::Next(callInfo));
889 TestHelper::TearDownFrame(thread, prev);
890 entries.Update(JSIterator::IteratorValue(thread, result).GetTaggedValue());
891 EXPECT_EQ(i, JSObject::GetProperty(thread, entries, first).GetValue()->GetInt());
892 EXPECT_EQ(i, JSObject::GetProperty(thread, entries, second).GetValue()->GetInt());
893 }
894 for (int i = 0; i < NODE_NUMBERS; i++) {
895 std::string ikey = myKey + std::to_string(i);
896 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
897
898 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
899 callInfo->SetFunction(JSTaggedValue::Undefined());
900 callInfo->SetThis(iter.GetTaggedValue());
901
902 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
903 result.Update(JSAPITreeSetIterator::Next(callInfo));
904 TestHelper::TearDownFrame(thread, prev);
905 entries.Update(JSIterator::IteratorValue(thread, result).GetTaggedValue());
906 EXPECT_TRUE(JSTaggedValue::SameValue(key, JSObject::GetProperty(thread, entries, first).GetValue()));
907 EXPECT_TRUE(JSTaggedValue::SameValue(key, JSObject::GetProperty(thread, entries, second).GetValue()));
908 }
909 }
910 }
911
912 // treeset.ForEach(callbackfn, this)
HWTEST_F_L0(ContainersTreeSetTest,ForEach)913 HWTEST_F_L0(ContainersTreeSetTest, ForEach)
914 {
915 constexpr int NODE_NUMBERS = 8;
916 JSHandle<JSAPITreeSet> tset = CreateJSAPITreeSet();
917 for (int i = 0; i < NODE_NUMBERS; i++) {
918 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
919 callInfo->SetFunction(JSTaggedValue::Undefined());
920 callInfo->SetThis(tset.GetTaggedValue());
921 callInfo->SetCallArg(0, JSTaggedValue(i));
922
923 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
924 JSTaggedValue result = ContainersTreeSet::Add(callInfo);
925 TestHelper::TearDownFrame(thread, prev);
926 EXPECT_TRUE(result.IsTrue());
927 EXPECT_EQ(tset->GetSize(), i + 1);
928 }
929
930 // test foreach function with TestForEachFunc;
931 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
932 JSHandle<JSAPITreeSet> dset = CreateJSAPITreeSet();
933 {
934 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
935 JSHandle<JSFunction> func = factory->NewJSFunction(env, reinterpret_cast<void *>(TestClass::TestForEachFunc));
936 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
937 callInfo->SetFunction(JSTaggedValue::Undefined());
938 callInfo->SetThis(tset.GetTaggedValue());
939 callInfo->SetCallArg(0, func.GetTaggedValue());
940 callInfo->SetCallArg(1, dset.GetTaggedValue());
941
942 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
943 ContainersTreeSet::ForEach(callInfo);
944 TestHelper::TearDownFrame(thread, prev);
945 }
946
947 EXPECT_EQ(dset->GetSize(), NODE_NUMBERS / 2);
948 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS / 2);
949 for (int i = 0; i < NODE_NUMBERS; i += 2) {
950 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
951 callInfo->SetFunction(JSTaggedValue::Undefined());
952 callInfo->SetThis(dset.GetTaggedValue());
953 callInfo->SetCallArg(0, JSTaggedValue(i));
954
955 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
956 JSTaggedValue result = ContainersTreeSet::Has(callInfo);
957 TestHelper::TearDownFrame(thread, prev);
958 EXPECT_TRUE(result.IsTrue());
959 }
960
961 // test add string
962 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
963 std::string myKey("mykey");
964 for (int i = 0; i < NODE_NUMBERS; i++) {
965 std::string ikey = myKey + std::to_string(i);
966 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
967
968 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
969 callInfo->SetFunction(JSTaggedValue::Undefined());
970 callInfo->SetThis(tset.GetTaggedValue());
971 callInfo->SetCallArg(0, key.GetTaggedValue());
972
973 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
974 JSTaggedValue result = ContainersTreeSet::Add(callInfo);
975 TestHelper::TearDownFrame(thread, prev);
976 EXPECT_TRUE(result.IsTrue());
977 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS / 2 + i + 1);
978 }
979 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS / 2 + NODE_NUMBERS);
980 {
981 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
982 JSHandle<JSFunction> func = factory->NewJSFunction(env, reinterpret_cast<void *>(TestClass::TestForEachFunc));
983 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
984 callInfo->SetFunction(JSTaggedValue::Undefined());
985 callInfo->SetThis(tset.GetTaggedValue());
986 callInfo->SetCallArg(0, func.GetTaggedValue());
987 callInfo->SetCallArg(1, dset.GetTaggedValue());
988
989 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
990 ContainersTreeSet::ForEach(callInfo);
991 TestHelper::TearDownFrame(thread, prev);
992 }
993 EXPECT_EQ(dset->GetSize(), NODE_NUMBERS + 2);
994 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS - 2);
995 for (int i = 0; i < NODE_NUMBERS; i += 2) {
996 std::string ikey = myKey + std::to_string(i);
997 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
998
999 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
1000 callInfo->SetFunction(JSTaggedValue::Undefined());
1001 callInfo->SetThis(dset.GetTaggedValue());
1002 callInfo->SetCallArg(0, key.GetTaggedValue());
1003
1004 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
1005 JSTaggedValue result = ContainersTreeSet::Has(callInfo);
1006 TestHelper::TearDownFrame(thread, prev);
1007 EXPECT_TRUE(result.IsTrue());
1008 }
1009 }
1010
HWTEST_F_L0(ContainersTreeSetTest,CustomCompareFunctionTest)1011 HWTEST_F_L0(ContainersTreeSetTest, CustomCompareFunctionTest)
1012 {
1013 constexpr int NODE_NUMBERS = 8;
1014 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1015 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1016 JSHandle<JSFunction> func = factory->NewJSFunction(env, reinterpret_cast<void *>(TestClass::TestCompareFunction));
1017 JSHandle<JSAPITreeSet> tset = CreateJSAPITreeSet(func.GetTaggedValue());
1018 for (int i = 0; i < NODE_NUMBERS; i++) {
1019 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
1020 callInfo->SetFunction(JSTaggedValue::Undefined());
1021 callInfo->SetThis(tset.GetTaggedValue());
1022 callInfo->SetCallArg(0, JSTaggedValue(i));
1023
1024 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
1025 JSTaggedValue result = ContainersTreeSet::Add(callInfo);
1026 TestHelper::TearDownFrame(thread, prev);
1027 EXPECT_TRUE(result.IsTrue());
1028 EXPECT_EQ(tset->GetSize(), i + 1);
1029 }
1030 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS);
1031
1032 // test add string
1033 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
1034 std::string myKey("mykey");
1035 for (int i = 0; i < NODE_NUMBERS; i++) {
1036 std::string ikey = myKey + std::to_string(i);
1037 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
1038
1039 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
1040 callInfo->SetFunction(JSTaggedValue::Undefined());
1041 callInfo->SetThis(tset.GetTaggedValue());
1042 callInfo->SetCallArg(0, key.GetTaggedValue());
1043
1044 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
1045 JSTaggedValue result = ContainersTreeSet::Add(callInfo);
1046 TestHelper::TearDownFrame(thread, prev);
1047 EXPECT_TRUE(result.IsTrue());
1048 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS + i + 1);
1049 }
1050 EXPECT_EQ(tset->GetSize(), NODE_NUMBERS * 2);
1051
1052 // test sort
1053 auto callInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
1054 callInfo1->SetFunction(JSTaggedValue::Undefined());
1055 callInfo1->SetThis(tset.GetTaggedValue());
1056 [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, callInfo1);
1057 JSHandle<JSTaggedValue> iterValues(thread, ContainersTreeSet::Values(callInfo1));
1058 TestHelper::TearDownFrame(thread, prev1);
1059 EXPECT_TRUE(iterValues->IsJSAPITreeSetIterator());
1060 JSMutableHandle<JSTaggedValue> result(thread, JSTaggedValue::Undefined());
1061 for (int i = 0; i < NODE_NUMBERS; i++) {
1062 std::string ikey = myKey + std::to_string(NODE_NUMBERS - 1 - i);
1063 key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
1064
1065 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
1066 callInfo->SetFunction(JSTaggedValue::Undefined());
1067 callInfo->SetThis(iterValues.GetTaggedValue());
1068
1069 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
1070 result.Update(JSAPITreeSetIterator::Next(callInfo));
1071 TestHelper::TearDownFrame(thread, prev);
1072 JSHandle<JSTaggedValue> itRes = JSIterator::IteratorValue(thread, result);
1073 EXPECT_TRUE(JSTaggedValue::SameValue(key, itRes));
1074 }
1075 for (int i = 0; i < NODE_NUMBERS; i++) {
1076 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
1077 callInfo->SetFunction(JSTaggedValue::Undefined());
1078 callInfo->SetThis(iterValues.GetTaggedValue());
1079
1080 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
1081 result.Update(JSAPITreeSetIterator::Next(callInfo));
1082 TestHelper::TearDownFrame(thread, prev);
1083 EXPECT_EQ((NODE_NUMBERS - 1 - i), JSIterator::IteratorValue(thread, result)->GetInt());
1084 }
1085 }
1086
HWTEST_F_L0(ContainersTreeSetTest,ProxyOfGetLength)1087 HWTEST_F_L0(ContainersTreeSetTest, ProxyOfGetLength)
1088 {
1089 constexpr uint32_t NODE_NUMBERS = 8;
1090 JSHandle<JSAPITreeSet> treeSet = CreateJSAPITreeSet();
1091 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
1092 callInfo->SetFunction(JSTaggedValue::Undefined());
1093 JSHandle<JSProxy> proxy = CreateJSProxyHandle(thread);
1094 proxy->SetTarget(thread, treeSet.GetTaggedValue());
1095 callInfo->SetThis(proxy.GetTaggedValue());
1096
1097 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
1098 callInfo->SetCallArg(0, JSTaggedValue(i));
1099 callInfo->SetCallArg(1, JSTaggedValue(i + 1));
1100 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
1101 ContainersTreeSet::Add(callInfo);
1102 TestHelper::TearDownFrame(thread, prev);
1103
1104 [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, callInfo);
1105 JSTaggedValue retult = ContainersTreeSet::GetLength(callInfo);
1106 TestHelper::TearDownFrame(thread, prev1);
1107 EXPECT_EQ(retult, JSTaggedValue(i + 1));
1108 }
1109 }
1110
HWTEST_F_L0(ContainersTreeSetTest,ExceptionReturn1)1111 HWTEST_F_L0(ContainersTreeSetTest, ExceptionReturn1)
1112 {
1113 CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersTreeSet, GetHigherValue);
1114 CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersTreeSet, Add);
1115 CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersTreeSet, Remove);
1116 CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersTreeSet, Has);
1117 CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersTreeSet, GetFirstValue);
1118 CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersTreeSet, GetLastValue);
1119 CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersTreeSet, Clear);
1120 CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersTreeSet, GetLowerValue);
1121
1122 JSHandle<JSAPITreeSet> treeSet = CreateJSAPITreeSet();
1123 {
1124 auto callInfo = NewEmptyCallInfo(thread);
1125 callInfo->SetThis(treeSet.GetTaggedValue());
1126 CONTAINERS_API_EXCEPTION_TEST(ContainersTreeSet, GetHigherValue, callInfo);
1127 }
1128 }
1129
HWTEST_F_L0(ContainersTreeSetTest,ExceptionReturn2)1130 HWTEST_F_L0(ContainersTreeSetTest, ExceptionReturn2)
1131 {
1132 CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersTreeSet, PopFirst);
1133 CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersTreeSet, PopLast);
1134 CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersTreeSet, IsEmpty);
1135 CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersTreeSet, ForEach);
1136 CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersTreeSet, GetLength);
1137 }
1138 } // namespace panda::test
1139