• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/js_api/js_api_tree_set_iterator.h"
17 #include "ecmascript/containers/containers_private.h"
18 #include "ecmascript/global_env.h"
19 #include "ecmascript/js_api/js_api_tree_set.h"
20 #include "ecmascript/js_iterator.h"
21 #include "ecmascript/tagged_tree.h"
22 #include "ecmascript/tests/test_helper.h"
23 
24 using namespace panda;
25 using namespace panda::ecmascript;
26 
27 namespace panda::test {
28 class JSAPITreeSetIteratorTest : public testing::Test {
29 public:
SetUpTestCase()30     static void SetUpTestCase()
31     {
32         GTEST_LOG_(INFO) << "SetUpTestCase";
33     }
34 
TearDownTestCase()35     static void TearDownTestCase()
36     {
37         GTEST_LOG_(INFO) << "TearDownCase";
38     }
39 
SetUp()40     void SetUp() override
41     {
42         TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
43     }
44 
TearDown()45     void TearDown() override
46     {
47         TestHelper::DestroyEcmaVMWithScope(instance, scope);
48     }
49 
50     EcmaVM *instance {nullptr};
51     ecmascript::EcmaHandleScope *scope {nullptr};
52     JSThread *thread {nullptr};
53 
54 protected:
CreateTreeSet()55     JSHandle<JSAPITreeSet> CreateTreeSet()
56     {
57         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
58         JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
59 
60         JSHandle<JSTaggedValue> globalObject = env->GetJSGlobalObject();
61         JSHandle<JSTaggedValue> key(factory->NewFromASCII("ArkPrivate"));
62         JSHandle<JSTaggedValue> value =
63             JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(globalObject), key).GetValue();
64 
65         auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
66         objCallInfo->SetFunction(JSTaggedValue::Undefined());
67         objCallInfo->SetThis(value.GetTaggedValue());
68         objCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int>(containers::ContainerTag::TreeSet)));
69 
70         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
71         JSTaggedValue result = containers::ContainersPrivate::Load(objCallInfo);
72         TestHelper::TearDownFrame(thread, prev);
73 
74         JSHandle<JSTaggedValue> constructor(thread, result);
75         JSHandle<JSAPITreeSet> jsSet(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
76         JSTaggedValue internal = TaggedTreeSet::Create(thread);
77         jsSet->SetTreeSet(thread, internal);
78         return jsSet;
79     }
80 };
81 
82 /**
83  * @tc.name: SetIterationKind
84  * @tc.desc: Call the "SetIterationKind" function, check whether the result returned through "GetIterationKind"
85  *           function from the JSAPITreeSetIterator is within expectations.
86  * @tc.type: FUNC
87  * @tc.require:
88  */
HWTEST_F_L0(JSAPITreeSetIteratorTest,SetIterationKind)89 HWTEST_F_L0(JSAPITreeSetIteratorTest, SetIterationKind)
90 {
91     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
92     JSHandle<JSAPITreeSet> jsTreeSet = CreateTreeSet();
93     EXPECT_TRUE(*jsTreeSet != nullptr);
94     JSHandle<JSAPITreeSetIterator> treeSetIterator =
95         factory->NewJSAPITreeSetIterator(jsTreeSet, IterationKind::KEY);
96     EXPECT_EQ(treeSetIterator->GetIterationKind(), IterationKind::KEY);
97     treeSetIterator->SetIterationKind(IterationKind::VALUE);
98     EXPECT_EQ(treeSetIterator->GetIterationKind(), IterationKind::VALUE);
99     treeSetIterator->SetIterationKind(IterationKind::KEY_AND_VALUE);
100     EXPECT_EQ(treeSetIterator->GetIterationKind(), IterationKind::KEY_AND_VALUE);
101 }
102 
103 /**
104  * @tc.name: SetIteratedSet
105  * @tc.desc: Call the "SetIteratedSet" function, check whether the result returned through "GetIteratedSet"
106  *           function from the JSAPITreeSetIterator is within expectations.
107  * @tc.type: FUNC
108  * @tc.require:
109  */
HWTEST_F_L0(JSAPITreeSetIteratorTest,SetIteratedSet)110 HWTEST_F_L0(JSAPITreeSetIteratorTest, SetIteratedSet)
111 {
112     constexpr uint32_t DEFAULT_LENGTH = 8;
113     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
114     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
115     JSHandle<JSAPITreeSet> jsTreeSet = CreateTreeSet();
116     EXPECT_TRUE(*jsTreeSet != nullptr);
117     JSHandle<JSAPITreeSetIterator> treeSetIterator =
118         factory->NewJSAPITreeSetIterator(jsTreeSet, IterationKind::VALUE);
119 
120     std::string setKey("setkey");
121     for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
122         std::string ikey = setKey + std::to_string(i);
123         key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
124         JSAPITreeSet::Add(thread, jsTreeSet, key);
125     }
126     treeSetIterator->SetIteratedSet(thread, jsTreeSet.GetTaggedValue());
127     JSHandle<JSAPITreeSet> treeSetTo(thread, JSAPITreeSet::Cast(treeSetIterator->GetIteratedSet().GetTaggedObject()));
128     EXPECT_EQ(treeSetTo->GetSize(), static_cast<int>(DEFAULT_LENGTH));
129     for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
130         std::string ikey = setKey + std::to_string(i);
131         key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
132         EXPECT_TRUE(JSAPITreeSet::Has(thread, jsTreeSet, key));
133     }
134 }
135 
136 /**
137  * @tc.name: SetNextIndex
138  * @tc.desc: Call the "SetNextIndex" function, check whether the result returned through "GetNextIndex"
139  *           function from the JSAPITreeSetIterator is within expectations.
140  * @tc.type: FUNC
141  * @tc.require:
142  */
HWTEST_F_L0(JSAPITreeSetIteratorTest,SetNextIndex)143 HWTEST_F_L0(JSAPITreeSetIteratorTest, SetNextIndex)
144 {
145     constexpr uint32_t DEFAULT_LENGTH = 8;
146     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
147     JSHandle<JSAPITreeSet> jsTreeSet = CreateTreeSet();
148     EXPECT_TRUE(*jsTreeSet != nullptr);
149     JSHandle<JSAPITreeSetIterator> treeSetIterator =
150         factory->NewJSAPITreeSetIterator(jsTreeSet, IterationKind::KEY_AND_VALUE);
151     EXPECT_EQ(treeSetIterator->GetNextIndex(), 0U);
152 
153     for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
154         treeSetIterator->SetNextIndex(i);
155         EXPECT_EQ(treeSetIterator->GetNextIndex(), i);
156     }
157 }
158 
159 /**
160  * @tc.name: CreateTreeSetIterator
161  * @tc.desc: Create TreeSet iterator, check whether the result returned through "IsJSAPITreeSetIterator"
162  *           function from the JSAPITreeSetIterator is within expectations.
163  * @tc.type: FUNC
164  * @tc.require:
165  */
HWTEST_F_L0(JSAPITreeSetIteratorTest,CreateTreeSetIterator)166 HWTEST_F_L0(JSAPITreeSetIteratorTest, CreateTreeSetIterator)
167 {
168     JSHandle<JSAPITreeSet> jsTreeSet = CreateTreeSet();
169     EXPECT_TRUE(*jsTreeSet != nullptr);
170     JSHandle<JSTaggedValue> treeSetVal(jsTreeSet);
171     // Create Iterator with KEY
172     JSHandle<JSTaggedValue> treeSetIterator =
173         JSAPITreeSetIterator::CreateTreeSetIterator(thread, treeSetVal, IterationKind::KEY);
174     EXPECT_TRUE(*treeSetIterator != nullptr);
175     EXPECT_TRUE(treeSetIterator->IsJSAPITreeSetIterator());
176     // Create Iterator with VALUE
177     treeSetIterator = JSAPITreeSetIterator::CreateTreeSetIterator(thread, treeSetVal, IterationKind::VALUE);
178     EXPECT_TRUE(*treeSetIterator != nullptr);
179     EXPECT_TRUE(treeSetIterator->IsJSAPITreeSetIterator());
180     // Create Iterator with KEY_AND_VALUE
181     treeSetIterator = JSAPITreeSetIterator::CreateTreeSetIterator(thread, treeSetVal, IterationKind::KEY_AND_VALUE);
182     EXPECT_TRUE(*treeSetIterator != nullptr);
183     EXPECT_TRUE(treeSetIterator->IsJSAPITreeSetIterator());
184 }
185 
186 /**
187  * @tc.name: Next
188  * @tc.desc: Create an iterator of JSAPITreeSet,and then loop through the elements(key and keyAndvalue) of the
189  *           iterator to check whether the elements through "Next" function are consistent.
190  * @tc.type: FUNC
191  * @tc.require:
192  */
HWTEST_F_L0(JSAPITreeSetIteratorTest,KEY_Next)193 HWTEST_F_L0(JSAPITreeSetIteratorTest, KEY_Next)
194 {
195     constexpr uint32_t DEFAULT_LENGTH = 8;
196     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
197     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
198     JSHandle<JSTaggedValue> valueStr = thread->GlobalConstants()->GetHandledValueString();
199     JSHandle<JSAPITreeSet> jsTreeSet = CreateTreeSet();
200     std::string setKey("setkey");
201     for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
202         std::string ikey = setKey + std::to_string(i);
203         key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
204         JSAPITreeSet::Add(thread, jsTreeSet, key);
205     }
206     // Create Iterator with KEY or VALUE
207     JSHandle<JSAPITreeSetIterator> treeSetIterator =
208         factory->NewJSAPITreeSetIterator(jsTreeSet, IterationKind::KEY);
209     // traversal iterator
210     for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
211         auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
212         ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
213         ecmaRuntimeCallInfo->SetThis(treeSetIterator.GetTaggedValue());
214 
215         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
216         JSTaggedValue result = JSAPITreeSetIterator::Next(ecmaRuntimeCallInfo);
217         TestHelper::TearDownFrame(thread, prev);
218 
219         JSHandle<JSObject> resultObj(thread, result);
220         std::string resultKey = setKey + std::to_string(i);
221         key.Update(factory->NewFromStdString(resultKey).GetTaggedValue());
222         EXPECT_EQ(JSTaggedValue::SameValue(
223             JSObject::GetProperty(thread, resultObj, valueStr).GetValue(), key), true);
224         EXPECT_EQ(treeSetIterator->GetNextIndex(), (i + 1U));
225     }
226 }
227 
228 /**
229  * @tc.name: Next
230  * @tc.desc: test special return of Next, including throw exception and return undefined
231  * @tc.type: FUNC
232  * @tc.require:
233  */
HWTEST_F_L0(JSAPITreeSetIteratorTest,SpecialReturnOfNext)234 HWTEST_F_L0(JSAPITreeSetIteratorTest, SpecialReturnOfNext)
235 {
236     JSHandle<JSAPITreeSet> jsTreeSet = CreateTreeSet();
237     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
238     JSHandle<JSAPITreeSetIterator> treeSetIterator = factory->NewJSAPITreeSetIterator(jsTreeSet, IterationKind::KEY);
239     treeSetIterator->SetIteratedSet(thread, JSTaggedValue::Undefined());
240 
241     // test Next exception
242     {
243         auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
244         ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
245         ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
246 
247         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
248         JSTaggedValue result = JSAPITreeSetIterator::Next(ecmaRuntimeCallInfo);
249         TestHelper::TearDownFrame(thread, prev);
250         EXPECT_EQ(result, JSTaggedValue::Exception());
251         EXPECT_EXCEPTION();
252     }
253 
254     // test Next return undefined
255     {
256         auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
257         ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
258         ecmaRuntimeCallInfo->SetThis(treeSetIterator.GetTaggedValue());
259 
260         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
261         JSTaggedValue result = JSAPITreeSetIterator::Next(ecmaRuntimeCallInfo);
262         TestHelper::TearDownFrame(thread, prev);
263         EXPECT_EQ(result, thread->GlobalConstants()->GetUndefinedIterResult());
264     }
265 }
266 
HWTEST_F_L0(JSAPITreeSetIteratorTest,KEY_AND_VALUE_Next)267 HWTEST_F_L0(JSAPITreeSetIteratorTest, KEY_AND_VALUE_Next)
268 {
269     constexpr uint32_t DEFAULT_LENGTH = 8;
270     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
271     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
272     JSHandle<JSTaggedValue> valueStr = thread->GlobalConstants()->GetHandledValueString();
273     JSHandle<JSAPITreeSet> jsTreeSet = CreateTreeSet();
274     std::string setKey("setkey");
275     for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
276         std::string ikey = setKey + std::to_string(i + 1U);
277         key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
278         JSAPITreeSet::Add(thread, jsTreeSet, key);
279     }
280     // Create Iterator with KEY_AND_VALUE
281     JSHandle<JSAPITreeSetIterator> treeSetIterator =
282         factory->NewJSAPITreeSetIterator(jsTreeSet, IterationKind::KEY_AND_VALUE);
283     // traversal iterator
284     for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
285         auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
286         ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
287         ecmaRuntimeCallInfo->SetThis(treeSetIterator.GetTaggedValue());
288 
289         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
290         JSTaggedValue result = JSAPITreeSetIterator::Next(ecmaRuntimeCallInfo);
291         TestHelper::TearDownFrame(thread, prev);
292 
293         JSHandle<JSObject> resultObj(thread, result);
294         std::string resultKeyAndValue = setKey + std::to_string(i + 1U);
295         key.Update(factory->NewFromStdString(resultKeyAndValue).GetTaggedValue());
296 
297         JSHandle<JSTaggedValue> keyValueArr(JSObject::GetProperty(thread, resultObj, valueStr).GetValue());
298         for (int index = 0; index < 2; index++) {
299             JSHandle<JSTaggedValue> indexValue(thread, JSTaggedValue(index));
300             EXPECT_EQ(JSTaggedValue::SameValue(
301                 JSObject::GetProperty(thread, keyValueArr, indexValue).GetValue(), key), true);
302         }
303         EXPECT_EQ(treeSetIterator->GetNextIndex(), (i + 1U));
304     }
305 }
306 }  // namespace panda::ecmascript
307