• 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/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