• 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/global_dictionary-inl.h"
17 #include "ecmascript/symbol_table.h"
18 #include "ecmascript/property_attributes.h"
19 #include "ecmascript/tests/test_helper.h"
20 
21 using namespace panda::ecmascript;
22 
23 namespace panda::test {
24 class GlobalDictionaryTest : public BaseTestWithScope<false> {
25 };
26 
27 /**
28  * @tc.name: IsMatch
29  * @tc.desc: Check whether two JSTaggedValue is equal through calling IsMatch function is within expectations.
30  * @tc.type: FUNC
31  * @tc.require:
32  */
HWTEST_F_L0(GlobalDictionaryTest,IsMatch)33 HWTEST_F_L0(GlobalDictionaryTest, IsMatch)
34 {
35     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
36 
37     JSHandle<EcmaString> globalKey = factory->NewFromASCII("key");
38     JSTaggedValue globalOtherKey = globalKey.GetTaggedValue();
39 
40     EXPECT_EQ(GlobalDictionary::IsMatch(thread, globalKey.GetTaggedValue(), globalOtherKey), true);
41     EXPECT_EQ(GlobalDictionary::IsMatch(thread, globalKey.GetTaggedValue(), JSTaggedValue::Undefined()), false);
42 }
43 
44 /**
45  * @tc.name: Hash
46  * @tc.desc: Check whether the hash size through calling Hash function is within expectations.
47  * @tc.type: FUNC
48  * @tc.require:
49  */
HWTEST_F_L0(GlobalDictionaryTest,Hash)50 HWTEST_F_L0(GlobalDictionaryTest, Hash)
51 {
52     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
53 
54     // test obj is string(uint8_t)
55     uint8_t utf8ArrayName[4] = {0, 2, 5}; // The last element is "\0"
56     uint32_t utf8ArrayNameLen = sizeof(utf8ArrayName) - 1;
57     JSHandle<EcmaString> nameStringUtf8Obj = factory->NewFromUtf8(utf8ArrayName, utf8ArrayNameLen);
58     // 67 = (0 << 5 - 0 + 2) << 5 - 2 + 5
59     EXPECT_EQ(GlobalDictionary::Hash(thread, nameStringUtf8Obj.GetTaggedValue()), 67);
60     // test obj is string(uint16_t)
61     uint16_t utf16ArrayName[] = {0x1, 0x2, 0x1};
62     uint32_t utf16ArrayNameLen = sizeof(utf16ArrayName) / sizeof(utf16ArrayName[0]);
63     JSHandle<EcmaString> nameStringUtf16Obj = factory->NewFromUtf16(utf16ArrayName, utf16ArrayNameLen);
64     // 1024 = (1 << 5 - 0 + 1) << 5 - 1 + 1
65     EXPECT_EQ(GlobalDictionary::Hash(thread, nameStringUtf16Obj.GetTaggedValue()), 1024);
66 }
67 
68 /**
69  * @tc.name: GetBoxAndValue
70  * @tc.desc: Check whether the Box and Value through calling SetEntry function is within expectations.
71  * @tc.type: FUNC
72  * @tc.require:
73  */
HWTEST_F_L0(GlobalDictionaryTest,GetBoxAndValue)74 HWTEST_F_L0(GlobalDictionaryTest, GetBoxAndValue)
75 {
76     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
77 
78     JSHandle<JSTaggedValue> globalKey(factory->NewFromASCII("key"));
79     JSHandle<JSTaggedValue> globalKey1(factory->NewFromASCII("value"));
80     JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue(123));
81     JSHandle<JSTaggedValue> handleValue1(thread, JSTaggedValue(100));
82     JSHandle<JSTaggedValue> propertyBox(factory->NewPropertyBox(handleValue));
83     JSHandle<JSTaggedValue> propertyBox1(factory->NewPropertyBox(handleValue1));
84     PropertyAttributes attribute(1);
85     // create GlobalDictionary
86     JSHandle<GlobalDictionary> handleDict = GlobalDictionary::Create(thread, 4);
87     EXPECT_TRUE(*handleDict != nullptr);
88     handleDict->SetEntry(thread, 0, globalKey.GetTaggedValue(), propertyBox.GetTaggedValue(), attribute);
89     // put value and cerate new dictionary
90     JSHandle<GlobalDictionary> newDict =
91         handleDict->PutIfAbsent(thread, handleDict, globalKey1, propertyBox1, attribute);
92 
93     EXPECT_TRUE(handleDict->GetBox(thread, 0) != nullptr);
94     EXPECT_EQ(handleDict->GetValue(thread, 0).GetInt(), 123);
95 
96     EXPECT_TRUE(newDict->GetBox(thread, 0) != nullptr);
97     EXPECT_EQ(newDict->GetValue(thread, 0).GetInt(), 123);
98     EXPECT_TRUE(newDict->GetBox(thread, 1) != nullptr);
99     EXPECT_EQ(newDict->GetValue(thread, 1).GetInt(), 100);
100 }
101 
102 /**
103  * @tc.name: GetAttributes
104  * @tc.desc: Check whether the Attributes Get through calling SetAttributes function is within expectations.
105  * @tc.type: FUNC
106  * @tc.require:
107  */
HWTEST_F_L0(GlobalDictionaryTest,GetAttributes)108 HWTEST_F_L0(GlobalDictionaryTest, GetAttributes)
109 {
110     // create GlobalDictionary
111     int numberofElements = 4;
112     JSHandle<GlobalDictionary> handleDict = GlobalDictionary::Create(thread, numberofElements);
113     EXPECT_TRUE(*handleDict != nullptr);
114     // set attributes call SetAttributes function
115     for (int i = 0; i < numberofElements; i++) {
116         handleDict->SetAttributes(thread, i, PropertyAttributes(i));
117         EXPECT_EQ(handleDict->GetAttributes(thread, i).GetPropertyMetaData(), i);
118     }
119 }
120 
121 /**
122  * @tc.name: ClearEntry
123  * @tc.desc: Create dictionary and set entry calling SetEntry function,Check whether Attributes is
124  *           the same as Attributes after calling the ClearEntry function.
125  * @tc.type: FUNC
126  * @tc.require:
127  */
HWTEST_F_L0(GlobalDictionaryTest,ClearEntry)128 HWTEST_F_L0(GlobalDictionaryTest, ClearEntry)
129 {
130     // create GlobalDictionary
131     int numberofElements = 16;
132     JSHandle<GlobalDictionary> handleDict = GlobalDictionary::Create(thread, numberofElements);
133     EXPECT_TRUE(*handleDict != nullptr);
134     // set entry
135     for (int i = 0; i < numberofElements; i++) {
136         JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue(i));
137         JSHandle<JSTaggedValue> handleValueKey(JSTaggedValue::ToString(thread, handleValue));
138         handleDict->SetEntry(thread, i, handleValueKey.GetTaggedValue(),
139                                         handleValue.GetTaggedValue(), PropertyAttributes(i));
140     }
141     // check attributes in three
142     EXPECT_EQ(handleDict->GetAttributes(thread, 3).GetPropertyMetaData(), 3);
143     handleDict->ClearEntry(thread, 3);
144     EXPECT_EQ(handleDict->GetAttributes(thread, 3).GetPropertyMetaData(), 0);
145 }
146 
147 /**
148  * @tc.name: UpdateValueAndAttributes
149  * @tc.desc: Update value and Attributes through calling UpdateValueAndAttributes function.
150  * @tc.type: FUNC
151  * @tc.require:
152  */
HWTEST_F_L0(GlobalDictionaryTest,UpdateValueAndAttributes)153 HWTEST_F_L0(GlobalDictionaryTest, UpdateValueAndAttributes)
154 {
155     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
156     // create GlobalDictionary
157     int numberofElements = 16;
158     JSHandle<GlobalDictionary> handleDict = GlobalDictionary::Create(thread, numberofElements);
159     EXPECT_TRUE(*handleDict != nullptr);
160     // set entry
161     for (int i = 0; i < numberofElements; i++) {
162         JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue(i));
163         JSHandle<JSTaggedValue> propertyBox(factory->NewPropertyBox(handleValue));
164         JSHandle<JSTaggedValue> handleValueKey(JSTaggedValue::ToString(thread, handleValue));
165         handleDict->SetEntry(thread, i, handleValueKey.GetTaggedValue(),
166                                         propertyBox.GetTaggedValue(), PropertyAttributes(i));
167     }
168     // check attributes in five
169     EXPECT_EQ(handleDict->GetAttributes(thread, 5).GetPropertyMetaData(), 5);
170     EXPECT_EQ(handleDict->GetValue(thread, 5).GetInt(), 5);
171     // Update value and attributes
172     for (int i = 0; i < numberofElements; i++) {
173         JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue(static_cast<int>(i + 1)));
174         JSHandle<JSTaggedValue> propertyBox(factory->NewPropertyBox(handleValue));
175         handleDict->UpdateValueAndAttributes(thread, i, propertyBox.GetTaggedValue(),
176                                              PropertyAttributes(static_cast<int>(i + 1)));
177     }
178     // check attributes in five
179     EXPECT_EQ(handleDict->GetAttributes(thread, 5).GetPropertyMetaData(), 6);
180     EXPECT_EQ(handleDict->GetValue(thread, 5).GetInt(), 6);
181 }
182 
183 /**
184  * @tc.name: GetAllKeys
185  * @tc.desc: Get all Attributes from dictionary and store it in the TaggedArray.
186  * @tc.type: FUNC
187  * @tc.require:
188  */
HWTEST_F_L0(GlobalDictionaryTest,GetAllKeys)189 HWTEST_F_L0(GlobalDictionaryTest, GetAllKeys)
190 {
191     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
192     // create GlobalDictionary
193     int numberofElements = 16;
194     std::vector<CString> nameKey = {"a", "b", "c", "d", "e", "f",
195                                     "g", "h", "i", "j", "k", "l", "m", "n", "o", "p"};
196     JSHandle<GlobalDictionary> handleDict = GlobalDictionary::Create(thread, numberofElements);
197     EXPECT_TRUE(*handleDict != nullptr);
198     JSMutableHandle<GlobalDictionary> dictHandle(thread, handleDict);
199     for (int i = 0; i < numberofElements; i++) {
200         JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue(i));
201         JSHandle<JSTaggedValue> handleNameKey(factory->NewFromASCII(nameKey[i]));
202         PropertyAttributes metaData;
203         // insert value
204         JSHandle<GlobalDictionary> dict(GlobalDictionary::PutIfAbsent(thread, dictHandle,
205                                                                       handleNameKey, handleValue, metaData));
206         dictHandle.Update(dict.GetTaggedValue());
207     }
208     uint32_t offset = 7;
209     // keyArray capacity must be enough for dictionary
210     int arraySize = numberofElements + static_cast<int>(offset);
211     JSHandle<TaggedArray> keyArray = factory->NewTaggedArray(arraySize);
212     dictHandle->GetAllKeys(thread, offset, *keyArray);
213     // Skip the first seven positions
214     for (uint32_t i = 0; i < offset; i++) {
215         EXPECT_TRUE(keyArray->Get(thread, i).IsHole());
216     }
217     // check key name
218     JSHandle<EcmaString> resultFirstKey(thread, keyArray->Get(thread, offset));
219     JSHandle<EcmaString> resultLastKey(thread, keyArray->Get(thread, arraySize - 1));
220     EXPECT_EQ(nameKey[0], EcmaStringAccessor(resultFirstKey).ToCString(thread).c_str());
221     EXPECT_EQ(nameKey[15], EcmaStringAccessor(resultLastKey).ToCString(thread).c_str());
222 }
223 
224 /**
225  * @tc.name: GetEnumAllKeys
226  * @tc.desc: Get all Enumerable Attributes from dictionary and store it in the TaggedArray.
227  * @tc.type: FUNC
228  * @tc.require:
229  */
HWTEST_F_L0(GlobalDictionaryTest,GetEnumAllKeys)230 HWTEST_F_L0(GlobalDictionaryTest, GetEnumAllKeys)
231 {
232     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
233     // create GlobalDictionary
234     int numberofElements = 16;
235     std::vector<CString> nameKey = {"a", "b", "c", "d", "e", "f",
236                                     "g", "h", "i", "j", "k", "l", "m", "n", "o", "q"};
237     JSHandle<GlobalDictionary> handleDict = GlobalDictionary::Create(thread, numberofElements);
238     EXPECT_TRUE(*handleDict != nullptr);
239     JSMutableHandle<GlobalDictionary> dictHandle(thread, handleDict);
240     bool enumerable;
241     for (int i = 0; i < numberofElements; i++) {
242         JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue(i));
243         JSHandle<JSTaggedValue> handleNameKey(factory->NewFromASCII(nameKey[i]));
244         PropertyAttributes metaData;
245         enumerable = true;
246         if (!(i % 2)) {
247             enumerable = false;
248         }
249         metaData.SetEnumerable(enumerable);
250         // insert value
251         JSHandle<GlobalDictionary> dict(GlobalDictionary::PutIfAbsent(thread, dictHandle,
252                                                                       handleNameKey, handleValue, metaData));
253         dictHandle.Update(dict.GetTaggedValue());
254     }
255     uint32_t offset = 7;
256     uint32_t keys = 0;
257     // keyArray capacity must be enough for dictionary
258     uint32_t arraySize = static_cast<uint32_t>(numberofElements) + offset;
259     JSHandle<TaggedArray> keyArray = factory->NewTaggedArray(arraySize);
260     dictHandle->GetEnumAllKeys(thread, offset, *keyArray, &keys);
261     EXPECT_EQ(keys, 8U);
262     JSHandle<EcmaString> resultFirstKey(thread, keyArray->Get(thread, offset));
263     JSHandle<EcmaString> resultLastKey(thread, keyArray->Get(thread, offset + keys - 1U));
264     EXPECT_EQ(nameKey[1], EcmaStringAccessor(resultFirstKey).ToCString(thread).c_str());
265     EXPECT_EQ(nameKey[15], EcmaStringAccessor(resultLastKey).ToCString(thread).c_str());
266 }
267 
268 /**
269  * @tc.name: CompKey
270  * @tc.desc: The second element in the two structures is compared.If it is less than,return true.
271  * @tc.type: FUNC
272  * @tc.require:
273  */
HWTEST_F_L0(GlobalDictionaryTest,CompKey)274 HWTEST_F_L0(GlobalDictionaryTest, CompKey)
275 {
276     std::pair<JSTaggedValue, uint32_t> a(JSTaggedValue(1), 1);
277     std::pair<JSTaggedValue, uint32_t> b(JSTaggedValue(2), 2);
278     std::pair<JSTaggedValue, uint32_t> c(JSTaggedValue(0), 0);
279     EXPECT_TRUE(GlobalDictionary::CompKey(a, b));
280     EXPECT_TRUE(!GlobalDictionary::CompKey(a, c));
281 }
282 
283 /**
284  * @tc.name: InvalidatePropertyBox
285  * @tc.desc: Invalidate value which is Configurable in a dictionary.
286  * @tc.type: FUNC
287  * @tc.require:
288  */
HWTEST_F_L0(GlobalDictionaryTest,InvalidatePropertyBox)289 HWTEST_F_L0(GlobalDictionaryTest, InvalidatePropertyBox)
290 {
291     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
292     // create GlobalDictionary
293     int numberofElements = 16;
294     std::vector<CString> nameKey = {"a", "b", "s", "t", "e", "f",
295                                     "g", "h", "i", "j", "k", "l", "m", "n", "o", "p"};
296     JSHandle<GlobalDictionary> handleDict = GlobalDictionary::Create(thread, numberofElements);
297     EXPECT_TRUE(*handleDict != nullptr);
298     int invalidatedSet = 3;
299     int invalidatedPosition = 12;
300     for (int i = 0; i < numberofElements; i++) {
301         JSHandle<JSTaggedValue> handleKey(factory->NewFromASCII(nameKey[i]));
302         JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue(i));
303         JSHandle<JSTaggedValue> propertyBox(factory->NewPropertyBox(handleValue));
304         PropertyAttributes metaData;
305         if (i == invalidatedSet) {
306             metaData.SetDictionaryOrder(invalidatedPosition);
307         }
308         else if (i == invalidatedPosition) {
309             metaData.SetConfigurable(true);
310         }
311         handleDict->SetEntry(thread, i, handleKey.GetTaggedValue(),
312                                         propertyBox.GetTaggedValue(), metaData);
313     }
314     // calling InvalidatePropertyBox function to Invalidate the PropertyBox
315     PropertyAttributes newAttr(10);
316     GlobalDictionary::InvalidatePropertyBox(thread, handleDict, invalidatedPosition);
317     EXPECT_EQ(handleDict->GetAttributes(thread, invalidatedPosition).GetBoxType(), PropertyBoxType::MUTABLE);
318     EXPECT_EQ(handleDict->GetAttributes(thread, invalidatedSet).GetDictionaryOrder(), invalidatedPosition);
319     EXPECT_EQ(handleDict->GetValue(thread, invalidatedPosition).GetInt(), invalidatedPosition);
320 }
321 }  // namespace panda::test
322