• 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_set_iterator.h"
17 #include "ecmascript/global_env.h"
18 #include "ecmascript/js_array.h"
19 #include "ecmascript/js_set.h"
20 #include "ecmascript/linked_hash_table.h"
21 #include "ecmascript/tests/ecma_test_common.h"
22 
23 using namespace panda;
24 using namespace panda::ecmascript;
25 
26 namespace panda::test {
27 class JSSetIteratorTest : public BaseTestWithScope<false> {
28 };
29 
CreateJSSet(JSThread * thread)30 static JSSet *CreateJSSet(JSThread *thread)
31 {
32     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
33     JSHandle<JSTaggedValue> constructor = thread->GetEcmaVM()->GetGlobalEnv()->GetBuiltinsSetFunction();
34     JSHandle<JSSet> set =
35         JSHandle<JSSet>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
36     JSHandle<LinkedHashSet> hashSet = LinkedHashSet::Create(thread);
37     set->SetLinkedSet(thread, hashSet);
38     return JSSet::Cast(set.GetTaggedValue().GetTaggedObject());
39 }
40 
41 /**
42  * @tc.name: CreateSetIterator
43  * @tc.desc: Call "CreateSetIterator" function create SetIterator,Check whether the the attribute setting of SetIterator
44  *           through "GetNextIndex" and "GetIterationKind" function is within expectations.
45  * @tc.type: FUNC
46  * @tc.require:
47  */
HWTEST_F_L0(JSSetIteratorTest,CreateSetIterator)48 HWTEST_F_L0(JSSetIteratorTest, CreateSetIterator)
49 {
50     JSHandle<JSSet> jsSet(thread, CreateJSSet(thread));
51     EXPECT_TRUE(*jsSet != nullptr);
52 
53     JSHandle<JSTaggedValue> setIteratorValue1 =
54         JSSetIterator::CreateSetIterator(thread, JSHandle<JSTaggedValue>(jsSet), IterationKind::KEY);
55 
56     EXPECT_EQ(setIteratorValue1->IsJSSetIterator(), true);
57     JSHandle<JSSetIterator> setIterator1(setIteratorValue1);
58     EXPECT_EQ(JSTaggedValue::SameValue(thread, setIterator1->GetIteratedSet(thread), jsSet->GetLinkedSet(thread)),
59               true);
60     EXPECT_EQ(setIterator1->GetNextIndex(), 0U);
61     EXPECT_EQ(setIterator1->GetIterationKind(), IterationKind::KEY);
62 
63     JSHandle<JSTaggedValue> setIteratorValue2 =
64         JSSetIterator::CreateSetIterator(thread, JSHandle<JSTaggedValue>(jsSet), IterationKind::VALUE);
65 
66     EXPECT_EQ(setIteratorValue2->IsJSSetIterator(), true);
67     JSHandle<JSSetIterator> setIterator2(setIteratorValue2);
68     EXPECT_EQ(JSTaggedValue::SameValue(thread, setIterator2->GetIteratedSet(thread), jsSet->GetLinkedSet(thread)),
69               true);
70     EXPECT_EQ(setIterator2->GetNextIndex(), 0U);
71     EXPECT_EQ(setIterator2->GetIterationKind(), IterationKind::VALUE);
72 }
73 
74 /**
75  * @tc.name: Update
76  * @tc.desc: Call "NewJSSetIterator" function create SetIterator with emty IteratedSet,create other JSSet and add key
77  *           to it,the old JSSet call "Rehash" function set new JSSet to the next table, then SetIterator call "Update"
78  *           function upadate IteratedSet,check whether the IteratedSet is within expectations.
79  * @tc.type: FUNC
80  * @tc.require:
81  */
HWTEST_F_L0(JSSetIteratorTest,Update)82 HWTEST_F_L0(JSSetIteratorTest, Update)
83 {
84     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
85     JSHandle<JSSet> jsSet1(thread, CreateJSSet(thread));
86     JSHandle<JSSet> jsSet2(thread, CreateJSSet(thread));
87 
88     JSHandle<JSTaggedValue> keyHandle1(factory->NewFromASCII("key1"));
89     JSHandle<JSTaggedValue> keyHandle2(factory->NewFromASCII("key2"));
90     JSHandle<JSTaggedValue> keyHandle3(factory->NewFromASCII("key3"));
91     // add key to jsSet2
92     JSSet::Add(thread, jsSet2, keyHandle1);
93     JSSet::Add(thread, jsSet2, keyHandle2);
94     JSSet::Add(thread, jsSet2, keyHandle3);
95 
96     JSHandle<LinkedHashSet> setHandle1(thread, LinkedHashSet::Cast(jsSet1->GetLinkedSet(thread).GetTaggedObject()));
97     JSHandle<LinkedHashSet> setHandle2(thread, LinkedHashSet::Cast(jsSet2->GetLinkedSet(thread).GetTaggedObject()));
98     setHandle1->Rehash(thread, *setHandle2);
99     // create SetIterator with jsSet1
100     JSHandle<JSSetIterator> setIterator = factory->NewJSSetIterator(jsSet1, IterationKind::KEY);
101     // update SetIterator
102     setIterator->Update(thread);
103     LinkedHashSet *resultSet = LinkedHashSet::Cast(setIterator->GetIteratedSet(thread).GetTaggedObject());
104     EXPECT_TRUE(resultSet->Has(thread, keyHandle1.GetTaggedValue()));
105     EXPECT_TRUE(resultSet->Has(thread, keyHandle2.GetTaggedValue()));
106     EXPECT_TRUE(resultSet->Has(thread, keyHandle3.GetTaggedValue()));
107 }
108 
NextCommon(JSThread * thread,JSHandle<JSSetIterator> & setIterator,IterationKind kind=IterationKind::KEY)109 EcmaRuntimeCallInfo* NextCommon(JSThread *thread, JSHandle<JSSetIterator>& setIterator,
110     IterationKind kind = IterationKind::KEY)
111 {
112     JSHandle<JSSet> jsSet(thread, CreateJSSet(thread));
113     EXPECT_TRUE(*jsSet != nullptr);
114 
115     for (int i = 0; i < 3; i++) {  // 3 : 3 default numberOfElements
116         JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
117         JSSet::Add(thread, jsSet, key);
118     }
119     // set IterationKind(key or value)
120     JSHandle<JSTaggedValue> setIteratorValue =
121         JSSetIterator::CreateSetIterator(thread, JSHandle<JSTaggedValue>(jsSet), kind);
122     setIterator = JSHandle<JSSetIterator>(setIteratorValue);
123     std::vector<JSTaggedValue> args{JSTaggedValue::Undefined()};
124     auto ecmaRuntimeCallInfo =
125         TestHelper::CreateEcmaRuntimeCallInfo(thread, args, 6, setIteratorValue.GetTaggedValue());
126     return ecmaRuntimeCallInfo;
127 }
128 /**
129  * @tc.name: Next
130  * @tc.desc: get the next value in setiterator,Check whether the return value obtained by the function is
131  *           the next value in the array element.
132  * @tc.type: FUNC
133  * @tc.require:
134  */
HWTEST_F_L0(JSSetIteratorTest,KEY_Next)135 HWTEST_F_L0(JSSetIteratorTest, KEY_Next)
136 {
137     JSHandle<JSSetIterator> setIterator;
138     auto ecmaRuntimeCallInfo = NextCommon(thread, setIterator);
139     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
140 
141     for (int i = 0; i <= 3; i++) { // 3 : 3 default numberOfElements
142         JSTaggedValue result = JSSetIterator::Next(ecmaRuntimeCallInfo);
143         JSHandle<JSTaggedValue> resultObj(thread, result);
144         if (i < 3) {
145             EXPECT_EQ(setIterator->GetNextIndex(), static_cast<uint32_t>(i + 1));
146             EXPECT_EQ(i, JSIterator::IteratorValue(thread, resultObj)->GetInt());
147         }
148         else {
149             EXPECT_EQ(JSIterator::IteratorValue(thread, resultObj).GetTaggedValue(), JSTaggedValue::Undefined());
150         }
151     }
152     TestHelper::TearDownFrame(thread, prev);
153 }
154 
HWTEST_F_L0(JSSetIteratorTest,KEY_AND_VALUE_Next)155 HWTEST_F_L0(JSSetIteratorTest, KEY_AND_VALUE_Next)
156 {
157     JSHandle<JSTaggedValue> index0(thread, JSTaggedValue(0));
158     JSHandle<JSTaggedValue> index1(thread, JSTaggedValue(1));
159     JSHandle<JSSetIterator> setIterator;
160     auto ecmaRuntimeCallInfo = NextCommon(thread, setIterator, IterationKind::KEY_AND_VALUE);
161     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
162 
163     for (int i = 0; i <= 3; i++) { // 3 : 3 default numberOfElements
164         JSTaggedValue result = JSSetIterator::Next(ecmaRuntimeCallInfo);
165         JSHandle<JSTaggedValue> resultObj(thread, result);
166         if (i < 3) {
167             JSHandle<JSArray> arrayList(thread, JSIterator::IteratorValue(thread, resultObj).GetTaggedValue());
168             EXPECT_EQ(setIterator->GetNextIndex(), static_cast<uint32_t>(i+1));
169             EXPECT_EQ(JSArray::GetProperty(thread, JSHandle<JSTaggedValue>(arrayList), index0).GetValue()->GetInt(), i);
170             EXPECT_EQ(JSArray::GetProperty(thread, JSHandle<JSTaggedValue>(arrayList), index1).GetValue()->GetInt(), i);
171         }
172         else {
173             EXPECT_EQ(JSIterator::IteratorValue(thread, resultObj).GetTaggedValue(), JSTaggedValue::Undefined());
174         }
175     }
176     TestHelper::TearDownFrame(thread, prev);
177 }
178 }  // namespace panda::test
179