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