1 /*
2 * Copyright (c) 2021 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/ecma_vm.h"
17 #include "ecmascript/global_env.h"
18 #include "ecmascript/js_handle.h"
19 #include "ecmascript/js_object-inl.h"
20 #include "ecmascript/js_tagged_value.h"
21 #include "ecmascript/linked_hash_table.h"
22 #include "ecmascript/linked_hash_table.h"
23 #include "ecmascript/object_factory.h"
24 #include "ecmascript/tagged_hash_table.h"
25 #include "ecmascript/tests/test_helper.h"
26
27 using namespace panda;
28
29 using namespace panda::ecmascript;
30
31 namespace panda::test {
32 class LinkedHashTableTest : public testing::Test {
33 public:
SetUpTestCase()34 static void SetUpTestCase()
35 {
36 GTEST_LOG_(INFO) << "SetUpTestCase";
37 }
38
TearDownTestCase()39 static void TearDownTestCase()
40 {
41 GTEST_LOG_(INFO) << "TearDownCase";
42 }
43
SetUp()44 void SetUp() override
45 {
46 TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
47 }
48
TearDown()49 void TearDown() override
50 {
51 TestHelper::DestroyEcmaVMWithScope(instance, scope);
52 }
53
54 EcmaVM *instance {nullptr};
55 EcmaHandleScope *scope {nullptr};
56 JSThread *thread {nullptr};
57
GetGlobalEnv()58 JSHandle<GlobalEnv> GetGlobalEnv()
59 {
60 EcmaVM *ecma = thread->GetEcmaVM();
61 return ecma->GetGlobalEnv();
62 }
63 };
64
HWTEST_F_L0(LinkedHashTableTest,MapCreate)65 HWTEST_F_L0(LinkedHashTableTest, MapCreate)
66 {
67 int numOfElement = 64;
68 JSHandle<LinkedHashMap> dict = LinkedHashMap::Create(thread, numOfElement);
69 EXPECT_TRUE(*dict != nullptr);
70 }
71
HWTEST_F_L0(LinkedHashTableTest,SetCreate)72 HWTEST_F_L0(LinkedHashTableTest, SetCreate)
73 {
74 int numOfElement = 64;
75 JSHandle<LinkedHashSet> set = LinkedHashSet::Create(thread, numOfElement);
76 EXPECT_TRUE(*set != nullptr);
77 }
78
HWTEST_F_L0(LinkedHashTableTest,addKeyAndValue)79 HWTEST_F_L0(LinkedHashTableTest, addKeyAndValue)
80 {
81 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
82 // mock object needed in test
83 int numOfElement = 64;
84 JSHandle<LinkedHashMap> dictHandle = LinkedHashMap::Create(thread, numOfElement);
85 EXPECT_TRUE(*dictHandle != nullptr);
86 JSHandle<JSTaggedValue> objFun = GetGlobalEnv()->GetObjectFunction();
87
88 char keyArray[] = "hello";
89 JSHandle<EcmaString> stringKey1 = factory->NewFromASCII(keyArray);
90 JSHandle<JSTaggedValue> key1(stringKey1);
91 JSHandle<JSTaggedValue> value1(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
92
93 char key2Array[] = "hello2";
94 JSHandle<EcmaString> stringKey2 = factory->NewFromASCII(key2Array);
95 JSHandle<JSTaggedValue> key2(stringKey2);
96 JSHandle<JSTaggedValue> value2(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
97
98 // test set()
99 dictHandle = LinkedHashMap::Set(thread, dictHandle, key1, value1);
100 EXPECT_EQ(dictHandle->NumberOfElements(), 1);
101
102 // test find()
103 int entry1 = dictHandle->FindElement(key1.GetTaggedValue());
104 EXPECT_EQ(key1.GetTaggedValue(), dictHandle->GetKey(entry1));
105 EXPECT_EQ(value1.GetTaggedValue(), dictHandle->GetValue(entry1));
106
107 dictHandle = LinkedHashMap::Set(thread, dictHandle, key2, value2);
108 EXPECT_EQ(dictHandle->NumberOfElements(), 2);
109 // test remove()
110 dictHandle = LinkedHashMap::Delete(thread, dictHandle, key1);
111 EXPECT_EQ(-1, dictHandle->FindElement(key1.GetTaggedValue()));
112 EXPECT_EQ(dictHandle->NumberOfElements(), 1);
113
114 JSHandle<JSTaggedValue> undefinedKey(thread, JSTaggedValue::Undefined());
115 dictHandle = LinkedHashMap::Set(thread, dictHandle, undefinedKey, value1);
116 int entry2 = dictHandle->FindElement(undefinedKey.GetTaggedValue());
117 EXPECT_EQ(value1.GetTaggedValue(), dictHandle->GetValue(entry2));
118 }
119
HWTEST_F_L0(LinkedHashTableTest,SetaddKeyAndValue)120 HWTEST_F_L0(LinkedHashTableTest, SetaddKeyAndValue)
121 {
122 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
123 // mock object needed in test
124 int numOfElement = 64;
125 JSHandle<LinkedHashSet> setHandle = LinkedHashSet::Create(thread, numOfElement);
126 EXPECT_TRUE(*setHandle != nullptr);
127 JSHandle<JSTaggedValue> objFun = GetGlobalEnv()->GetObjectFunction();
128
129 char keyArray[] = "hello";
130 JSHandle<EcmaString> stringKey1 = factory->NewFromASCII(keyArray);
131 JSHandle<JSTaggedValue> key1(stringKey1);
132 JSHandle<JSTaggedValue> value1(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
133
134 char key2Array[] = "hello2";
135 JSHandle<EcmaString> stringKey2 = factory->NewFromASCII(key2Array);
136 JSHandle<JSTaggedValue> key2(stringKey2);
137 JSHandle<JSTaggedValue> value2(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
138
139 // test set()
140 setHandle = LinkedHashSet::Add(thread, setHandle, key1);
141 EXPECT_EQ(setHandle->NumberOfElements(), 1);
142
143 // test has()
144 EXPECT_TRUE(setHandle->Has(key1.GetTaggedValue()));
145
146 setHandle = LinkedHashSet::Add(thread, setHandle, key2);
147 EXPECT_EQ(setHandle->NumberOfElements(), 2);
148 // test remove()
149 setHandle = LinkedHashSet::Delete(thread, setHandle, key1);
150 EXPECT_EQ(-1, setHandle->FindElement(key1.GetTaggedValue()));
151 EXPECT_EQ(setHandle->NumberOfElements(), 1);
152
153 JSHandle<JSTaggedValue> undefinedKey(thread, JSTaggedValue::Undefined());
154 setHandle = LinkedHashSet::Add(thread, setHandle, undefinedKey);
155 EXPECT_TRUE(setHandle->Has(undefinedKey.GetTaggedValue()));
156 }
157
HWTEST_F_L0(LinkedHashTableTest,GrowCapacity)158 HWTEST_F_L0(LinkedHashTableTest, GrowCapacity)
159 {
160 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
161 int numOfElement = 8;
162 JSHandle<LinkedHashMap> dictHandle = LinkedHashMap::Create(thread, numOfElement);
163 EXPECT_TRUE(*dictHandle != nullptr);
164 JSHandle<JSFunction> objFun(GetGlobalEnv()->GetObjectFunction());
165 char keyArray[7] = "hello";
166 for (int i = 0; i < 33; i++) {
167 keyArray[5] = '1' + static_cast<uint32_t>(i);
168 keyArray[6] = 0;
169 JSHandle<JSTaggedValue> key(factory->NewFromASCII(keyArray));
170 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
171
172 // test insert()
173 dictHandle = LinkedHashMap::Set(thread, dictHandle, key, value);
174 EXPECT_EQ(i, dictHandle->FindElement(key.GetTaggedValue()));
175 }
176
177 // test order
178 for (int i = 0; i < 33; i++) {
179 keyArray[5] = '1' + static_cast<uint32_t>(i);
180 keyArray[6] = 0;
181 JSHandle<EcmaString> stringKey = factory->NewFromASCII(keyArray);
182 // test insert()
183 EXPECT_EQ(i, dictHandle->FindElement(stringKey.GetTaggedValue()));
184 }
185 EXPECT_EQ(dictHandle->NumberOfElements(), 33);
186 EXPECT_EQ(dictHandle->Capacity(), 64);
187 }
188
HWTEST_F_L0(LinkedHashTableTest,SetGrowCapacity)189 HWTEST_F_L0(LinkedHashTableTest, SetGrowCapacity)
190 {
191 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
192 int numOfElement = 8;
193 JSHandle<LinkedHashSet> setHandle = LinkedHashSet::Create(thread, numOfElement);
194 EXPECT_TRUE(*setHandle != nullptr);
195 JSHandle<JSFunction> objFun(GetGlobalEnv()->GetObjectFunction());
196 // create key and values
197 char keyArray[7] = "hello";
198 for (int i = 0; i < 33; i++) {
199 keyArray[5] = '1' + static_cast<uint32_t>(i);
200 keyArray[6] = 0;
201 JSHandle<EcmaString> stringKey = factory->NewFromASCII(keyArray);
202 JSHandle<JSTaggedValue> key(stringKey);
203
204 // test insert()
205 setHandle = LinkedHashSet::Add(thread, setHandle, key);
206 EXPECT_EQ(i, setHandle->FindElement(key.GetTaggedValue()));
207 }
208
209 // test order
210 for (int i = 0; i < 33; i++) {
211 keyArray[5] = '1' + static_cast<uint32_t>(i);
212 keyArray[6] = 0;
213 JSHandle<EcmaString> stringKey = factory->NewFromASCII(keyArray);
214 // test insert()
215 EXPECT_EQ(i, setHandle->FindElement(stringKey.GetTaggedValue()));
216 }
217 EXPECT_EQ(setHandle->NumberOfElements(), 33);
218 EXPECT_EQ(setHandle->Capacity(), 64);
219 }
220
HWTEST_F_L0(LinkedHashTableTest,ShrinkCapacity)221 HWTEST_F_L0(LinkedHashTableTest, ShrinkCapacity)
222 {
223 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
224 int numOfElement = 64;
225 JSHandle<LinkedHashMap> dictHandle = LinkedHashMap::Create(thread, numOfElement);
226 EXPECT_TRUE(*dictHandle != nullptr);
227 JSHandle<JSFunction> objFun(GetGlobalEnv()->GetObjectFunction());
228 char keyArray[7] = "hello";
229 for (int i = 0; i < 10; i++) {
230 keyArray[5] = '1' + static_cast<uint32_t>(i);
231 keyArray[6] = 0;
232 JSHandle<JSTaggedValue> key(factory->NewFromASCII(keyArray));
233 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
234
235 // test insert()
236 dictHandle = LinkedHashMap::Set(thread, dictHandle, key, value);
237 }
238 keyArray[5] = '1' + 9;
239 JSHandle<JSTaggedValue> key(factory->NewFromASCII(keyArray));
240 dictHandle = LinkedHashMap::Delete(thread, dictHandle, key);
241 // test order
242 for (int i = 0; i < 9; i++) {
243 keyArray[5] = '1' + static_cast<uint32_t>(i);
244 keyArray[6] = 0;
245 JSHandle<EcmaString> stringKey = factory->NewFromASCII(keyArray);
246 // test insert()
247 EXPECT_EQ(i, dictHandle->FindElement(stringKey.GetTaggedValue()));
248 }
249 EXPECT_EQ(dictHandle->NumberOfElements(), 9);
250 EXPECT_EQ(dictHandle->Capacity(), 16);
251 }
252
HWTEST_F_L0(LinkedHashTableTest,SetShrinkCapacity)253 HWTEST_F_L0(LinkedHashTableTest, SetShrinkCapacity)
254 {
255 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
256 int numOfElement = 64;
257 JSHandle<LinkedHashSet> setHandle = LinkedHashSet::Create(thread, numOfElement);
258 EXPECT_TRUE(*setHandle != nullptr);
259 JSHandle<JSFunction> objFun(GetGlobalEnv()->GetObjectFunction());
260 // create key and values
261 char keyArray[7] = "hello";
262 for (int i = 0; i < 10; i++) {
263 keyArray[5] = '1' + static_cast<uint32_t>(i);
264 keyArray[6] = 0;
265 JSHandle<JSTaggedValue> key(factory->NewFromASCII(keyArray));
266
267 // test insert()
268 setHandle = LinkedHashSet::Add(thread, setHandle, key);
269 }
270 keyArray[5] = '1' + 9;
271 JSHandle<JSTaggedValue> keyHandle(factory->NewFromASCII(keyArray));
272 setHandle = LinkedHashSet::Delete(thread, setHandle, keyHandle);
273 // test order
274 for (int i = 0; i < 9; i++) {
275 keyArray[5] = '1' + static_cast<uint32_t>(i);
276 keyArray[6] = 0;
277 JSHandle<EcmaString> stringKey = factory->NewFromASCII(keyArray);
278 // test insert()
279 EXPECT_EQ(i, setHandle->FindElement(stringKey.GetTaggedValue()));
280 }
281 EXPECT_EQ(setHandle->NumberOfElements(), 9);
282 EXPECT_EQ(setHandle->Capacity(), 16);
283 }
284 } // namespace panda::test
285