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