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