• 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/tagged_dictionary.h"
17 #include "ecmascript/ecma_string_table.h"
18 #include "ecmascript/global_env.h"
19 #include "ecmascript/tests/test_helper.h"
20 
21 using namespace panda;
22 using namespace panda::ecmascript;
23 
24 namespace panda::test {
25 class TaggedDictionaryTest : public testing::Test {
26 public:
SetUpTestCase()27     static void SetUpTestCase()
28     {
29         GTEST_LOG_(INFO) << "SetUpTestCase";
30     }
31 
TearDownTestCase()32     static void TearDownTestCase()
33     {
34         GTEST_LOG_(INFO) << "TearDownCase";
35     }
36 
SetUp()37     void SetUp() override
38     {
39         TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
40     }
41 
TearDown()42     void TearDown() override
43     {
44         TestHelper::DestroyEcmaVMWithScope(instance, scope);
45     }
46 
47     EcmaVM *instance {nullptr};
48     EcmaHandleScope *scope {nullptr};
49     JSThread *thread {nullptr};
50 };
51 
GetGlobalEnv(JSThread * thread)52 static JSHandle<GlobalEnv> GetGlobalEnv(JSThread *thread)
53 {
54     EcmaVM *ecma = thread->GetEcmaVM();
55     return ecma->GetGlobalEnv();
56 }
57 
58 /**
59  * @tc.name: CreateNameDictionary
60  * @tc.desc: Call "NameDictionary::Create" function Create a name dictionary.then, check whether the dictionary
61  *           is created successfully.
62  * @tc.type: FUNC
63  * @tc.require:
64  */
HWTEST_F_L0(TaggedDictionaryTest,CreateNameDictionary)65 HWTEST_F_L0(TaggedDictionaryTest, CreateNameDictionary)
66 {
67     int numOfElement = 64;
68     JSHandle<NameDictionary> nameDict = NameDictionary::Create(thread, numOfElement);
69     EXPECT_TRUE(*nameDict != nullptr);
70 }
71 
72 /**
73  * @tc.name: NameDictionary_addKeyAndValue
74  * @tc.desc: Create a name dictionary, set a key value pair to the dictionary.The key is a string type, call the
75  *           "PutIfAbsent" function to add the key and value to the dictionary then,check whether the key is found in
76  *           the dictionary.
77  * @tc.type: FUNC
78  * @tc.require:
79  */
HWTEST_F_L0(TaggedDictionaryTest,NameDictionary_addKeyAndValue)80 HWTEST_F_L0(TaggedDictionaryTest, NameDictionary_addKeyAndValue)
81 {
82     // mock object needed in test
83     int numOfElement = 64;
84     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
85     JSHandle<NameDictionary> dictJShandle(NameDictionary::Create(thread, numOfElement));
86     EXPECT_TRUE(*dictJShandle != nullptr);
87     JSMutableHandle<NameDictionary> dictHandle(thread, dictJShandle);
88     JSHandle<JSTaggedValue> objFun = GetGlobalEnv(thread)->GetObjectFunction();
89 
90     // create key and values
91     char keyArray[] = "hello";
92     JSHandle<EcmaString> stringKey1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII(keyArray);
93     JSHandle<JSTaggedValue> key1(stringKey1);
94     JSHandle<JSTaggedValue> value1(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
95     PropertyAttributes metaData1;
96 
97     char key2Array[] = "hello2";
98     JSHandle<EcmaString> stringKey2 = thread->GetEcmaVM()->GetFactory()->NewFromASCII(key2Array);
99     JSHandle<JSTaggedValue> key2(stringKey2);
100     JSHandle<JSTaggedValue> value2(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
101     PropertyAttributes metaData2;
102 
103     // test insert()
104     JSHandle<NameDictionary> dict(NameDictionary::PutIfAbsent(thread, dictHandle, key1, value1, metaData1));
105     dictHandle.Update(dict.GetTaggedValue());
106     EXPECT_EQ(dict->EntriesCount(), 1);
107 
108     // test find() and lookup()
109     int entry1 = dict->FindEntry(key1.GetTaggedValue());
110     EXPECT_EQ(key1.GetTaggedValue(), JSTaggedValue(dict->GetKey(entry1).GetRawData()));
111     EXPECT_EQ(value1.GetTaggedValue(), JSTaggedValue(dict->GetValue(entry1).GetRawData()));
112 
113     JSHandle<NameDictionary> dict2(NameDictionary::PutIfAbsent(thread, dictHandle, key2, value2, metaData2));
114     EXPECT_EQ(dict2->EntriesCount(), 2);
115     // test remove()
116     dict = NameDictionary::Remove(thread, dictHandle, entry1);
117     EXPECT_EQ(-1, dict->FindEntry(key1.GetTaggedValue()));
118     EXPECT_EQ(dict->EntriesCount(), 1);
119 }
120 
121 /**
122  * @tc.name: NameDictionary_GrowCapacity
123  * @tc.desc: Create a name dictionary, set a key value pair to the dictionary.The key is a string type, call the
124  *           "PutIfAbsent" function to glow the capacity of the dictionary,then check whether the key number and size
125  *           of the dictionary have become bigger.
126  * @tc.type: FUNC
127  * @tc.require:
128  */
HWTEST_F_L0(TaggedDictionaryTest,NameDictionary_GrowCapacity)129 HWTEST_F_L0(TaggedDictionaryTest, NameDictionary_GrowCapacity)
130 {
131     int numOfElement = 8;
132     JSHandle<NameDictionary> dictHandle(NameDictionary::Create(thread, numOfElement));
133     EXPECT_TRUE(*dictHandle != nullptr);
134     // create key and values
135     char keyArray[7] = "hello";
136     for (int i = 0; i < 9; i++) {
137         JSHandle<NameDictionary> tempHandle = dictHandle;
138         keyArray[5] = '1' + static_cast<uint32_t>(i);
139         keyArray[6] = 0;
140         JSHandle<EcmaString> stringKey = thread->GetEcmaVM()->GetFactory()->NewFromASCII(keyArray);
141         JSHandle<JSTaggedValue> key(stringKey);
142         JSHandle<JSTaggedValue> keyHandle(key);
143         JSHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue(i));
144         PropertyAttributes metaData;
145         // test insert()
146         dictHandle = NameDictionary::PutIfAbsent(thread, tempHandle, keyHandle, valueHandle, metaData);
147     }
148     EXPECT_EQ(dictHandle->EntriesCount(), 9);
149     EXPECT_EQ(dictHandle->Size(), 16);
150 }
151 
152 /**
153  * @tc.name: NameDictionary_ShrinkCapacity
154  * @tc.desc: Create a name dictionary, set a key value pair to the dictionary.The key is a string type, call the
155  *           "Remove" function to shrink the capacity of the dictionary,then check whether the key number and size of
156  *           the dictionary have become smaller.
157  * @tc.type: FUNC
158  * @tc.require:
159  */
HWTEST_F_L0(TaggedDictionaryTest,NameDictionary_ShrinkCapacity)160 HWTEST_F_L0(TaggedDictionaryTest, NameDictionary_ShrinkCapacity)
161 {
162     int numOfElement = 64;
163     JSMutableHandle<NameDictionary> dictHandle(thread, NameDictionary::Create(thread, numOfElement));
164     EXPECT_TRUE(*dictHandle != nullptr);
165     // create key and values
166     uint8_t keyArray[7] = "hello";
167 
168     auto stringTable = thread->GetEcmaVM()->GetEcmaStringTable();
169     for (int i = 0; i < 10; i++) {
170         keyArray[5] = '0' + static_cast<uint32_t>(i);
171         keyArray[6] = 0;
172         JSHandle<JSTaggedValue> key(thread, stringTable->GetOrInternString(keyArray, utf::Mutf8Size(keyArray), true));
173         JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
174         PropertyAttributes metaData;
175         // test insert()
176         JSHandle<NameDictionary> newDict = NameDictionary::PutIfAbsent(thread, dictHandle, key, value, metaData);
177         dictHandle.Update(newDict.GetTaggedValue());
178     }
179 
180     keyArray[5] = '2';
181     keyArray[6] = 0;
182     JSHandle<JSTaggedValue> arrayHandle(thread,
183                                         stringTable->GetOrInternString(keyArray, utf::Mutf8Size(keyArray), true));
184     int entry = dictHandle->FindEntry(arrayHandle.GetTaggedValue());
185     EXPECT_NE(entry, -1);
186 
187     JSHandle<NameDictionary> newDict1 = NameDictionary::Remove(thread, dictHandle, entry);
188     dictHandle.Update(newDict1.GetTaggedValue());
189     EXPECT_EQ(dictHandle->EntriesCount(), 9);
190     EXPECT_EQ(dictHandle->Size(), 16);
191 }
192 
193 /**
194  * @tc.name: CreateNumberDictionary
195  * @tc.desc: Call "NumberDictionary::Create" function Create a number dictionary.then, check whether the dictionary
196  *           is created successfully.
197  * @tc.type: FUNC
198  * @tc.require:
199  */
HWTEST_F_L0(TaggedDictionaryTest,CreateNumberDictionary)200 HWTEST_F_L0(TaggedDictionaryTest, CreateNumberDictionary)
201 {
202     int numOfElement = 64;
203     JSHandle<NumberDictionary> numberDict = NumberDictionary::Create(thread, numOfElement);
204     EXPECT_TRUE(*numberDict != nullptr);
205 }
206 
207 /**
208  * @tc.name: NumberDictionary_addKeyAndValue
209  * @tc.desc: Create a number dictionary, set a key value pair to the dictionary.The key is a numeric type, call the
210  *           "PutIfAbsent" function to add the key and value to the dictionary then,check whether the key is found in
211  *           the dictionary.
212  * @tc.type: FUNC
213  * @tc.require:
214  */
HWTEST_F_L0(TaggedDictionaryTest,NumberDictionary_addKeyAndValue)215 HWTEST_F_L0(TaggedDictionaryTest, NumberDictionary_addKeyAndValue)
216 {
217     int numOfElement = 64;
218     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
219     JSHandle<NumberDictionary> dictJShandle = NumberDictionary::Create(thread, numOfElement);
220     EXPECT_TRUE(*dictJShandle != nullptr);
221     JSMutableHandle<NumberDictionary> dictHandle(thread, dictJShandle);
222     JSHandle<JSTaggedValue> objFun = GetGlobalEnv(thread)->GetObjectFunction();
223 
224     // create key and values
225     JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(1));
226     JSHandle<JSTaggedValue> value1(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
227     PropertyAttributes metaData1;
228 
229     JSHandle<JSTaggedValue> key2(thread, JSTaggedValue(2)); // 2: number key
230     JSHandle<JSTaggedValue> value2(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
231     PropertyAttributes metaData2;
232 
233     // add key and values
234     JSHandle<NumberDictionary> dict = NumberDictionary::PutIfAbsent(thread, dictHandle, key1, value1, metaData1);
235     dictHandle.Update(dict.GetTaggedValue());
236     EXPECT_EQ(dict->EntriesCount(), 1);
237 
238     // test find() and lookup()
239     int entry1 = dict->FindEntry(key1.GetTaggedValue());
240     EXPECT_EQ(key1.GetTaggedValue(), JSTaggedValue(dict->GetKey(entry1).GetRawData()));
241     EXPECT_EQ(value1.GetTaggedValue(), JSTaggedValue(dict->GetValue(entry1).GetRawData()));
242 
243     JSHandle<NumberDictionary> dict2 = NumberDictionary::PutIfAbsent(thread, dictHandle, key2, value2, metaData2);
244     EXPECT_EQ(dict2->EntriesCount(), 2);
245     // test remove()
246     dict = NumberDictionary::Remove(thread, dictHandle, entry1);
247     EXPECT_EQ(-1, dict->FindEntry(key1.GetTaggedValue()));
248     EXPECT_EQ(dict->EntriesCount(), 1);
249 }
250 
251 /**
252  * @tc.name: NumberDictionary_GetAllKey
253  * @tc.desc: Create a number dictionary, set a key value pair to the dictionary.The key is a numeric type, call the
254  *           "GetAllKeys" function to get the key of the dictionary to the taggedarray,then check whether the length
255  *           of the array is equal to the number of keys, and whether the array value is equal to the key value.
256  * @tc.type: FUNC
257  * @tc.require:
258  */
HWTEST_F_L0(TaggedDictionaryTest,NumberDictionary_GetAllKey)259 HWTEST_F_L0(TaggedDictionaryTest, NumberDictionary_GetAllKey)
260 {
261     int numOfElement = 64;
262     int keyNumbers = 10;
263     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
264     JSHandle<NumberDictionary> dictHandle = NumberDictionary::Create(thread, numOfElement);
265     EXPECT_TRUE(*dictHandle != nullptr);
266     JSHandle<TaggedArray> storeKeyArray = factory->NewTaggedArray(keyNumbers);
267     // create key and values
268     for (int i = keyNumbers - 2; i >= 0 ; i--) {
269         JSHandle<NumberDictionary> tempHandle = dictHandle;
270         JSHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue(i));
271         JSHandle<JSTaggedValue> valueHandle(JSTaggedValue::ToString(thread, keyHandle));
272         PropertyAttributes metaData;
273         dictHandle = NumberDictionary::PutIfAbsent(thread, tempHandle, keyHandle, valueHandle, metaData);
274     }
275     // get key
276     NumberDictionary::GetAllKeys(thread, dictHandle, 1, storeKeyArray); // 1: store to the second position of the array
277     for (int i = 1; i < keyNumbers; i++) {
278         JSHandle<JSTaggedValue> numberKey(thread, JSTaggedValue(i-1));
279         JSHandle<EcmaString> stringKey(JSTaggedValue::ToString(thread, numberKey));
280         EXPECT_EQ(storeKeyArray->Get(i), stringKey.GetTaggedValue());
281     }
282     EXPECT_TRUE(storeKeyArray->Get(0).IsHole());
283 }
284 
285 /**
286  * @tc.name: NumberDictionary_GrowCapacity
287  * @tc.desc: Create a number dictionary, set a key value pair to the dictionary.The key is a numeric type, call the
288  *           "PutIfAbsent" function to glow the capacity of the dictionary,then check whether the key number and size
289  *           of the dictionary have become bigger.
290  * @tc.type: FUNC
291  * @tc.require:
292  */
HWTEST_F_L0(TaggedDictionaryTest,NumberDictionary_GrowCapacity)293 HWTEST_F_L0(TaggedDictionaryTest, NumberDictionary_GrowCapacity)
294 {
295     int numOfElement = 8;
296     JSHandle<NumberDictionary> dictHandle = NumberDictionary::Create(thread, numOfElement);
297     EXPECT_TRUE(*dictHandle != nullptr);
298     // create key and values
299     for (int i = 0; i < 9; i++) {
300         JSHandle<NumberDictionary> tempHandle = dictHandle;
301         JSHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue(i));
302         JSHandle<JSTaggedValue> valueHandle(JSTaggedValue::ToString(thread, keyHandle));
303         PropertyAttributes metaData;
304         // test insert()
305         dictHandle = NumberDictionary::PutIfAbsent(thread, tempHandle, keyHandle, valueHandle, metaData);
306     }
307     EXPECT_EQ(dictHandle->EntriesCount(), 9);
308     EXPECT_EQ(dictHandle->Size(), 16);
309 }
310 
311 /**
312  * @tc.name: NumberDictionary_ShrinkCapacity
313  * @tc.desc: Create a number dictionary, set a key value pair to the dictionary.The key is a numeric type, call the
314  *           "Remove" function to shrink the capacity of the dictionary,then check whether the key number and size of
315  *           the dictionary have become smaller.
316  * @tc.type: FUNC
317  * @tc.require:
318  */
HWTEST_F_L0(TaggedDictionaryTest,NumberDictionary_ShrinkCapacity)319 HWTEST_F_L0(TaggedDictionaryTest, NumberDictionary_ShrinkCapacity)
320 {
321     int numOfElement = 64;
322     JSMutableHandle<NumberDictionary> dictHandle(thread, NumberDictionary::Create(thread, numOfElement));
323     EXPECT_TRUE(*dictHandle != nullptr);
324     // create key and values
325     for (int i = 0; i < 10; i++) {
326         JSHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue(i));
327         JSHandle<JSTaggedValue> valueHandle(JSTaggedValue::ToString(thread, keyHandle));
328         PropertyAttributes metaData;
329         JSHandle<NumberDictionary> newDict =
330             NumberDictionary::PutIfAbsent(thread, dictHandle, keyHandle, valueHandle, metaData);
331         dictHandle.Update(newDict.GetTaggedValue());
332     }
333 
334     JSHandle<JSTaggedValue> arrayHandle(thread, JSTaggedValue(9));
335     int entry = dictHandle->FindEntry(arrayHandle.GetTaggedValue());
336     EXPECT_NE(entry, -1);
337 
338     JSHandle<NumberDictionary> newDict1 = NumberDictionary::Remove(thread, dictHandle, entry);
339     dictHandle.Update(newDict1.GetTaggedValue());
340     EXPECT_EQ(dictHandle->EntriesCount(), 9);
341     EXPECT_EQ(dictHandle->Size(), 16);
342 }
343 
344 /**
345  * @tc.name: NumberDictionary_IsMatch
346  * @tc.desc: Call the "IsMatch" function to determine whether the key in the dictionary is equal to the defined key.
347  *           If it is equal, return true, otherwise return false.
348  * @tc.type: FUNC
349  * @tc.require:
350  */
HWTEST_F_L0(TaggedDictionaryTest,NumberDictionary_IsMatch)351 HWTEST_F_L0(TaggedDictionaryTest, NumberDictionary_IsMatch)
352 {
353     JSTaggedValue numberKey1(0);
354     JSTaggedValue numberKey2(1);
355     bool result = false;
356     // key must be integer
357     result = NumberDictionary::IsMatch(numberKey1, numberKey2);
358     EXPECT_TRUE(!result);
359 
360     result = NumberDictionary::IsMatch(numberKey1, numberKey1);
361     EXPECT_TRUE(result);
362 }
363 }  // namespace panda::test
364