• 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/template_map.h"
17 #include "ecmascript/tagged_hash_table.h"
18 #include "ecmascript/tests/test_helper.h"
19 
20 using namespace panda;
21 using namespace panda::ecmascript;
22 
23 namespace panda::test {
24 class TemplateMapTest : public BaseTestWithScope<false> {
25 };
26 
27 /*
28  * @tc.name: CreateTemplateMap
29  * @tc.desc: Create a TemplateMap through calling Create function with numberOfElements. Check whether the value
30  *           returned through the TemplateMap's calling Get/GetKey/GetValue function is within expectations.Check
31  *           whether the value returned through the TaggedArray's(transformed from the TemplateMap) calling GetLength
32  *           function is within expectations.
33  * expectations.
34  * @tc.type: FUNC
35  * @tc.require:
36  */
HWTEST_F_L0(TemplateMapTest,CreateTemplateMap)37 HWTEST_F_L0(TemplateMapTest, CreateTemplateMap)
38 {
39     int numElementsTempMap = 128;
40     uint32_t tagArrExpectLength = TemplateMap::HashTable::TABLE_HEADER_SIZE +
41         numElementsTempMap * TemplateMap::ENTRY_SIZE;
42 
43     JSHandle<TemplateMap> templateMap = TemplateMap::Create(thread, numElementsTempMap);
44     JSHandle<TaggedArray> handleTagArr(templateMap);
45 
46     EXPECT_EQ(handleTagArr->GetLength(), tagArrExpectLength);
47     EXPECT_EQ(templateMap->EntriesCount(), 0);
48     EXPECT_EQ(templateMap->HoleEntriesCount(), 0);
49     EXPECT_EQ(templateMap->Size(), numElementsTempMap);
50     for (int32_t i = 0; i < numElementsTempMap; i++) {
51         EXPECT_EQ(templateMap->GetKey(i), JSTaggedValue::Undefined());
52         EXPECT_EQ(templateMap->GetValue(i), JSTaggedValue::Undefined());
53     }
54 }
55 
56 /*
57  * @tc.name: Insert
58  * @tc.desc: Create a TemplateMap, call Insert function with the TemplateMap, a key(JSArray) and a value. Check whether
59  *           the value(entry) returned through the TemplateMap's calling FindEntry function with the key(JSArray) is
60  *           within expectations. Check whether the value returned through the TemplateMap's calling GetKey/GetValue
61  *           function with the value(entry) is within expectations.
62  * @tc.type: FUNC
63  * @tc.require:
64  */
HWTEST_F_L0(TemplateMapTest,Insert)65 HWTEST_F_L0(TemplateMapTest, Insert)
66 {
67     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
68     JSHandle<TemplateMap> templateMap = TemplateMap::Create(thread);
69 
70     JSHandle<JSTaggedValue> tempMapKey(JSArray::ArrayCreate(thread, JSTaggedNumber(0)));
71     JSHandle<JSTaggedValue> tempMapKey1(JSArray::ArrayCreate(thread, JSTaggedNumber(1)));
72     JSHandle<JSTaggedValue> templateArrVal(factory->NewFromASCII("key"));
73     JSHandle<JSTaggedValue> templateArrVal1(factory->NewFromASCII("key1"));
74 
75     TemplateMap::Insert(thread, templateMap, tempMapKey, templateArrVal);
76     int keyEntry = templateMap->FindEntry(tempMapKey.GetTaggedValue());
77     EXPECT_EQ(templateMap->GetKey(keyEntry), tempMapKey.GetTaggedValue());
78     EXPECT_EQ(templateMap->GetValue(keyEntry), templateArrVal.GetTaggedValue());
79 
80     TemplateMap::Insert(thread, templateMap, tempMapKey, templateArrVal1);
81     int keyEntry1 = templateMap->FindEntry(tempMapKey.GetTaggedValue());
82     EXPECT_EQ(keyEntry, keyEntry1);
83     EXPECT_EQ(templateMap->GetKey(keyEntry1), tempMapKey.GetTaggedValue());
84     EXPECT_EQ(templateMap->GetValue(keyEntry1), templateArrVal1.GetTaggedValue());
85 
86     TemplateMap::Insert(thread, templateMap, tempMapKey1, templateArrVal1);
87     int keyEntry2 = templateMap->FindEntry(tempMapKey1.GetTaggedValue());
88     EXPECT_NE(keyEntry1, keyEntry2);
89     EXPECT_EQ(templateMap->GetKey(keyEntry2), tempMapKey1.GetTaggedValue());
90     EXPECT_EQ(templateMap->GetValue(keyEntry2), templateArrVal1.GetTaggedValue());
91     EXPECT_EQ(templateMap->GetValue(keyEntry), templateArrVal1.GetTaggedValue());
92 }
93 
94 /*
95  * @tc.name: IncreaseEntries
96  * @tc.desc: Create a TemplateMap, let it call IncreaseEntries function, check whether the value returned through
97  *           calling EntriesCount function is within expectations.
98  * @tc.type: FUNC
99  * @tc.require:
100  */
101 
HWTEST_F_L0(TemplateMapTest,IncreaseEntries)102 HWTEST_F_L0(TemplateMapTest, IncreaseEntries)
103 {
104     int entriesCount = 8;
105     JSHandle<TemplateMap> templateMap = TemplateMap::Create(thread);
106     for (int32_t i = 0; i < entriesCount; i++) {
107         templateMap->IncreaseEntries(thread);
108     }
109     EXPECT_EQ(templateMap->EntriesCount(), entriesCount);
110 }
111 
112 /*
113  * @tc.name: IncreaseHoleEntriesCount
114  * @tc.desc: Create a TemplateMap, let it call IncreaseEntries function and IncreaseHoleEntriesCount function, check
115  *           whether the value returned through calling EntriesCount function and the value returned through calling
116  *           HoleEntriesCount function are within expectations.
117  * @tc.type: FUNC
118  * @tc.require:
119  */
HWTEST_F_L0(TemplateMapTest,IncreaseHoleEntriesCount)120 HWTEST_F_L0(TemplateMapTest, IncreaseHoleEntriesCount)
121 {
122     int entriesCount = 8;
123     int holeEntriesCount = 3;
124     JSHandle<TemplateMap> templateMap = TemplateMap::Create(thread);
125     for (int32_t i = 0; i < entriesCount; i++) {
126         templateMap->IncreaseEntries(thread);
127     }
128     templateMap->IncreaseHoleEntriesCount(thread, holeEntriesCount);
129 
130     EXPECT_EQ(templateMap->EntriesCount(), entriesCount - holeEntriesCount);
131     EXPECT_EQ(templateMap->HoleEntriesCount(), holeEntriesCount);
132 }
133 
134 /*
135  * @tc.name: ComputeHashTableSize
136  * @tc.desc: Check whether the value returned through a TemplateMap's calling ComputeHashTableSize function is within
137  *           expectations.
138  * expectations.
139  * @tc.type: FUNC
140  * @tc.require:
141  */
HWTEST_F_L0(TemplateMapTest,ComputeHashTableSize)142 HWTEST_F_L0(TemplateMapTest, ComputeHashTableSize)
143 {
144     JSHandle<TemplateMap> templateMap = TemplateMap::Create(thread);
145 
146     uint32_t atLeastSize = 85;
147     uint32_t atLeastSize1 = atLeastSize + 1;
148     // 128: eighty-five is close to the seventh power of two
149     EXPECT_EQ(templateMap->ComputeHashTableSize(atLeastSize), 128);
150     // 256: eighty-six is close to the  eighth power of two
151     EXPECT_EQ(templateMap->ComputeHashTableSize(atLeastSize1), 256);
152     uint32_t atLeastSize2 = 172;
153     // 512: one hundred and seventy-two is close to the ninth power of two
154     EXPECT_EQ(templateMap->ComputeHashTableSize(atLeastSize2), 512);
155 }
156 
157 /*
158  * @tc.name: IsNeedGrowHashTable
159  * @tc.desc: Create a source TemplateMap, change it through calling IncreaseEntries/IncreaseHoleEntriesCount function.
160  *           Check whether the bool returned through the source TemplateMap's calling IsNeedGrowHashTable function is
161  *           within expectations.
162  * expectations.
163  * @tc.type: FUNC
164  * @tc.require:
165  */
HWTEST_F_L0(TemplateMapTest,IsNeedGrowHashTable)166 HWTEST_F_L0(TemplateMapTest, IsNeedGrowHashTable)
167 {
168     // Test for the TemplateMap of which the size is 128
169     int intNumElementsTempMap = 128;
170     JSHandle<TemplateMap> templateMap = TemplateMap::Create(thread, intNumElementsTempMap);
171     int atLeastSize = 85;
172     int entriesCount = 22;
173     int addEntriesCount = atLeastSize - entriesCount;
174     for (int32_t i = 0; i < entriesCount; i++) {
175         templateMap->IncreaseEntries(thread);
176     }
177     EXPECT_FALSE(templateMap->IsNeedGrowHashTable(addEntriesCount));
178     EXPECT_TRUE(templateMap->IsNeedGrowHashTable(addEntriesCount + 1));
179     // Test for the TemplateMap of which the size is 256
180     intNumElementsTempMap = 256;
181     JSHandle<TemplateMap> templateMap1 = TemplateMap::Create(thread, intNumElementsTempMap);
182     atLeastSize = 170;
183     entriesCount = 33;
184     addEntriesCount = atLeastSize - entriesCount;
185     for (int32_t i = 0; i < entriesCount; i++) {
186         templateMap1->IncreaseEntries(thread);
187     }
188     EXPECT_FALSE(templateMap1->IsNeedGrowHashTable(addEntriesCount));
189     EXPECT_FALSE(templateMap1->IsNeedGrowHashTable(addEntriesCount + 1));
190     EXPECT_TRUE(templateMap1->IsNeedGrowHashTable(addEntriesCount + 2));
191 }
192 
193 /*
194  * @tc.name: GrowHashTable
195  * @tc.desc: Create a source TemplateMap, change it through calling IncreaseEntries function. Check whether the value
196  *           returned through the TemplateMap's(returned through calling GrowHashTable function) calling Size function
197  *           is within expectations.
198  * expectations.
199  * @tc.type: FUNC
200  * @tc.require:
201  */
HWTEST_F_L0(TemplateMapTest,GrowHashTable)202 HWTEST_F_L0(TemplateMapTest, GrowHashTable)
203 {
204     // Test for the TemplateMap of which the size is 128
205     int intNumElementsTempMap = 128;
206     JSHandle<TemplateMap> templateMap = TemplateMap::Create(thread, intNumElementsTempMap);
207     int atLeastSize = 85;
208     int entriesCount = 55;
209     int addEntriesCount = atLeastSize - entriesCount;
210     for (int32_t i = 0; i < entriesCount; i++) {
211         templateMap->IncreaseEntries(thread);
212     }
213     JSHandle<TemplateMap> templateMap1 = TemplateMap::GrowHashTable(thread, templateMap, addEntriesCount);
214     EXPECT_EQ(templateMap1->Size(), intNumElementsTempMap);
215 
216     JSHandle<TemplateMap> templateMap2 = TemplateMap::GrowHashTable(thread, templateMap, addEntriesCount + 1);
217     EXPECT_EQ(templateMap2->Size(), intNumElementsTempMap << 1);
218     // Test for the TemplateMap of which the size is 256
219     intNumElementsTempMap = 256;
220     JSHandle<TemplateMap> templateMap3 = TemplateMap::Create(thread, intNumElementsTempMap);
221     atLeastSize = 170;
222     entriesCount = 66;
223     addEntriesCount = atLeastSize - entriesCount;
224     for (int32_t i = 0; i < entriesCount; i++) {
225         templateMap3->IncreaseEntries(thread);
226     }
227     JSHandle<TemplateMap> templateMap4 = TemplateMap::GrowHashTable(thread, templateMap3, addEntriesCount);
228     EXPECT_EQ(templateMap4->Size(), intNumElementsTempMap);
229 
230     JSHandle<TemplateMap> templateMap5 = TemplateMap::GrowHashTable(thread, templateMap3, addEntriesCount + 1);
231     EXPECT_EQ(templateMap5->Size(), intNumElementsTempMap);
232     // 2: means needing to grow
233     JSHandle<TemplateMap> templateMap6 = TemplateMap::GrowHashTable(thread, templateMap3, addEntriesCount + 2);
234     // 2: means twice as much
235     EXPECT_EQ(templateMap6->Size(), intNumElementsTempMap << 2);
236 }
237 
238 /*
239  * @tc.name: RecalculateTableSize
240  * @tc.desc: Check whether the value returned through calling RecalculateTableSize function is within expectations.
241  * @tc.type: FUNC
242  * @tc.require:
243  */
HWTEST_F_L0(TemplateMapTest,RecalculateTableSize)244 HWTEST_F_L0(TemplateMapTest, RecalculateTableSize)
245 {
246     int currentSize = 128, atLeastSize = 33;
247     EXPECT_EQ(TemplateMap::RecalculateTableSize(currentSize, atLeastSize), currentSize);
248     // 2: means half
249     EXPECT_EQ(TemplateMap::RecalculateTableSize(currentSize, atLeastSize - 1), currentSize / 2);
250     // 4: shift left by two digits
251     currentSize = TemplateMap::MIN_SIZE * 4;
252     for (int i = currentSize; i >= 0; i--) {
253         EXPECT_EQ(TemplateMap::RecalculateTableSize(currentSize, i), currentSize);
254     }
255 }
256 
257 /*
258  * @tc.name: GetAllKeys
259  * @tc.desc: Create a source TemplateMap, change the source TemplateMap through calling Insert function some times.
260  *           Create a target TaggedArray, change the target TaggedArray through the changed source TemplateMap's calling
261  *           GetAllKeys function with the offset at which the copying of the elements start and the target TaggedArray
262  *           Check whether the target TaggedArray is within expectations.
263  * @tc.type: FUNC
264  * @tc.require:
265  */
HWTEST_F_L0(TemplateMapTest,GetAllKeys)266 HWTEST_F_L0(TemplateMapTest, GetAllKeys)
267 {
268     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
269     int numElements = 32;
270     JSHandle<TemplateMap> templateMap = TemplateMap::Create(thread);
271     // insert key and value
272     for (int i = 0; i < numElements; i++) {
273         JSHandle<JSTaggedValue> tempMapKey(JSArray::ArrayCreate(thread, JSTaggedNumber(i)));
274         JSHandle<JSTaggedValue> tempMapValue(thread, JSTaggedValue(i));
275         templateMap = TemplateMap::Insert(thread, templateMap, tempMapKey, tempMapValue);
276     }
277 
278     JSHandle<TaggedArray> storeKeyArray = factory->NewTaggedArray(55);  // 55 : means the length of array
279     templateMap->GetAllKeys(thread, 5, *storeKeyArray);  // 5: means the index of array
280     for (int32_t i = 0; i < numElements; i++) {
281         EXPECT_NE(templateMap->GetKey(i), JSTaggedValue::Undefined());
282         // 5: get value from subscript five
283         EXPECT_EQ(templateMap->GetKey(i), storeKeyArray->Get(i + 5));
284     }
285 }
286 
287 /*
288  * @tc.name: GetAllKeysIntoVector
289  * @tc.desc: Create a source TemplateMap, change the source TemplateMap through calling Insert function some times.
290  *           Create a target std::vector<JSTaggedValue>,change the target std::vector<JSTaggedValue> through the changed
291  *           source TemplateMap's calling GetAllKeysIntoVector function with the target std::vector<JSTaggedValue>.Check
292  *           whether the target std::vector<JSTaggedValue> is within expectations.
293  * @tc.type: FUNC
294  * @tc.require:
295  */
HWTEST_F_L0(TemplateMapTest,GetAllKeysIntoVector)296 HWTEST_F_L0(TemplateMapTest, GetAllKeysIntoVector)
297 {
298     int numElements = 33;
299     JSHandle<TemplateMap> templateMap = TemplateMap::Create(thread);
300     // insert key and value
301     for (int i = 0; i < numElements; i++) {
302         JSHandle<JSTaggedValue> tempMapKey(JSArray::ArrayCreate(thread, JSTaggedNumber(i)));
303         JSHandle<JSTaggedValue> tempMapValue(thread, JSTaggedValue(i));
304         templateMap = TemplateMap::Insert(thread, templateMap, tempMapKey, tempMapValue);
305     }
306     std::vector<JSTaggedValue> storeKeyVector = {};
307     templateMap->GetAllKeysIntoVector(storeKeyVector);
308     for (int32_t i = 0; i < numElements; i++) {
309         EXPECT_NE(templateMap->GetKey(i), JSTaggedValue::Undefined());
310         EXPECT_EQ(templateMap->GetKey(i), storeKeyVector[i]);
311     }
312 }
313 
314 /*
315  * @tc.name: FindInsertIndex
316  * @tc.desc: Create a source TemplateMap, change the source TemplateMap through calling Insert function some times.
317  *           Get the next InsertIndex through the changed source TemplateMap's calling FindInsertIndex function with the
318  *           hash of the Key which exists in the changed TemplateMap. Check whether the JSTaggedValue returned through
319  *           the changed source TemplateMap's calling GetKey function with the next InsertIndex is Undefined.
320  * @tc.type: FUNC
321  * @tc.require:
322  */
HWTEST_F_L0(TemplateMapTest,FindInsertIndex)323 HWTEST_F_L0(TemplateMapTest, FindInsertIndex)
324 {
325     int numElements = 33;
326     JSHandle<TemplateMap> templateMap = TemplateMap::Create(thread);
327     // insert key and value
328     for (int i = 0; i < numElements; i++) {
329         JSHandle<JSTaggedValue> tempMapKey(JSArray::ArrayCreate(thread, JSTaggedNumber(i)));
330         JSHandle<JSTaggedValue> tempMapValue(thread, JSTaggedValue(i));
331         templateMap = TemplateMap::Insert(thread, templateMap, tempMapKey, tempMapValue);
332     }
333 
334     for (int i = 0; i < numElements; i++) {
335         JSHandle<JSTaggedValue> tempMapKey(JSArray::ArrayCreate(thread, JSTaggedNumber(i)));
336         uint32_t hashValue = static_cast<uint32_t>(TemplateMap::Hash(tempMapKey.GetTaggedValue()));
337         EXPECT_EQ(JSTaggedValue::Undefined(), templateMap->GetKey(
338             templateMap->FindInsertIndex(hashValue)));
339     }
340 }
341 }  // namespace panda::test
342