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