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