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/layout_info-inl.h"
17 #include "ecmascript/property_attributes.h"
18 #include "ecmascript/tests/test_helper.h"
19
20 using namespace panda::ecmascript;
21
22 namespace panda::test {
23 class LayoutInfoTest : public BaseTestWithScope<false> {
24 };
25
HWTEST_F_L0(LayoutInfoTest,SetNumberOfElements)26 HWTEST_F_L0(LayoutInfoTest, SetNumberOfElements)
27 {
28 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
29 int32_t infoLength = 2; // 2: len
30 JSHandle<LayoutInfo> layoutInfoHandle = factory->CreateLayoutInfo(infoLength);
31 EXPECT_TRUE(*layoutInfoHandle != nullptr);
32
33 layoutInfoHandle->SetNumberOfElements(thread, 100);
34 EXPECT_EQ(layoutInfoHandle->NumberOfElements(), 100);
35 }
36
HWTEST_F_L0(LayoutInfoTest,SetPropertyInit)37 HWTEST_F_L0(LayoutInfoTest, SetPropertyInit)
38 {
39 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
40 int32_t infoLength = 3;
41 PropertyAttributes defaultAttr = PropertyAttributes::Default();
42 defaultAttr.SetNormalAttr(infoLength);
43 JSHandle<JSTaggedValue> key(factory->NewFromASCII("key"));
44 JSHandle<LayoutInfo> layoutInfoHandle = factory->CreateLayoutInfo(infoLength);
45 EXPECT_TRUE(*layoutInfoHandle != nullptr);
46
47 layoutInfoHandle->SetPropertyInit(thread, 0, key.GetTaggedValue(), defaultAttr);
48 EXPECT_EQ(layoutInfoHandle->GetKey(0), key.GetTaggedValue());
49 EXPECT_EQ(layoutInfoHandle->GetAttr(0).GetNormalAttr(), static_cast<uint32_t>(infoLength));
50 }
51
HWTEST_F_L0(LayoutInfoTest,SetSortedIndex)52 HWTEST_F_L0(LayoutInfoTest, SetSortedIndex)
53 {
54 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
55 int32_t infoLength = 5;
56 PropertyAttributes defaultAttr = PropertyAttributes::Default();
57 defaultAttr.SetNormalAttr(infoLength);
58 JSHandle<JSTaggedValue> key1(factory->NewFromASCII("hello"));
59 JSHandle<JSTaggedValue> key2(factory->NewFromASCII("world"));
60 JSHandle<LayoutInfo> layoutInfoHandle = factory->CreateLayoutInfo(infoLength);
61 EXPECT_TRUE(*layoutInfoHandle != nullptr);
62
63 layoutInfoHandle->SetPropertyInit(thread, 0, key1.GetTaggedValue(), defaultAttr);
64 layoutInfoHandle->SetPropertyInit(thread, 1, key2.GetTaggedValue(), defaultAttr);
65 layoutInfoHandle->SetSortedIndex(thread, 0, infoLength - 4);
66 EXPECT_EQ(layoutInfoHandle->GetSortedIndex(0), 1U);
67 EXPECT_EQ(layoutInfoHandle->GetSortedKey(0), key2.GetTaggedValue());
68 }
69
HWTEST_F_L0(LayoutInfoTest,FindElementWithCache)70 HWTEST_F_L0(LayoutInfoTest, FindElementWithCache)
71 {
72 int infoLength = 5;
73 int newPropertiesLength = 11;
74 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
75 PropertyAttributes defaultAttr = PropertyAttributes::Default();
76 JSHandle<JSTaggedValue> key1(factory->NewFromASCII("1"));
77 JSHandle<JSTaggedValue> key4(factory->NewFromASCII("4"));
78 JSHandle<JSTaggedValue> key5(factory->NewFromASCII("5"));
79 JSHandle<JSTaggedValue> key10(factory->NewFromASCII("10"));
80 JSHandle<JSTaggedValue> key11(factory->NewFromASCII("11"));
81 JSHandle<LayoutInfo> layoutInfoHandle = factory->CreateLayoutInfo(infoLength);
82 EXPECT_TRUE(*layoutInfoHandle != nullptr);
83 for (int i = 0; i < infoLength; i++) {
84 JSHandle<JSTaggedValue> elements(thread, JSTaggedValue(i));
85 JSHandle<JSTaggedValue> elementsKey(JSTaggedValue::ToString(thread, elements));
86 defaultAttr.SetOffset(i);
87 layoutInfoHandle->AddKey(thread, i, elementsKey.GetTaggedValue(), defaultAttr);
88 }
89 int propertiesNumber = layoutInfoHandle->NumberOfElements();
90 int result = 0;
91 result = layoutInfoHandle->FindElementWithCache(thread, nullptr, key1.GetTaggedValue(), propertiesNumber);
92 EXPECT_EQ(result, 1); // 1: Index corresponding to key1
93 result = layoutInfoHandle->FindElementWithCache(thread, nullptr, key5.GetTaggedValue(), propertiesNumber);
94 EXPECT_EQ(result, -1); // -1: not find
95 // extend layoutInfo
96 JSHandle<LayoutInfo> newLayoutInfo = factory->ExtendLayoutInfo(layoutInfoHandle, newPropertiesLength);
97 for (int i = 5; i < newPropertiesLength; i++) {
98 JSHandle<JSTaggedValue> elements(thread, JSTaggedValue(i));
99 JSHandle<JSTaggedValue> elementsKey(JSTaggedValue::ToString(thread, elements));
100 defaultAttr.SetOffset(i);
101 newLayoutInfo->AddKey(thread, i, elementsKey.GetTaggedValue(), defaultAttr);
102 }
103 result = newLayoutInfo->FindElementWithCache(thread, nullptr, key4.GetTaggedValue(), newPropertiesLength);
104 EXPECT_EQ(result, 4); // 4: Index corresponding to key4
105 result = newLayoutInfo->FindElementWithCache(thread, nullptr, key10.GetTaggedValue(), newPropertiesLength);
106 EXPECT_EQ(result, 10); // 10: Index corresponding to key10
107 result = newLayoutInfo->FindElementWithCache(thread, nullptr, key5.GetTaggedValue(), newPropertiesLength);
108 EXPECT_EQ(result, 5); // 5: Index corresponding to key5
109 result = newLayoutInfo->FindElementWithCache(thread, nullptr, key11.GetTaggedValue(), newPropertiesLength);
110 EXPECT_EQ(result, -1); // -1: not find
111 }
112
GetAllKeysCommon(JSThread * thread,bool enumKeys=false)113 void GetAllKeysCommon(JSThread *thread, bool enumKeys = false)
114 {
115 int infoLength = 5;
116 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
117 PropertyAttributes defaultAttr = PropertyAttributes::Default();
118 JSHandle<JSTaggedValue> key3(factory->NewFromASCII("3"));
119
120 JSHandle<JSObject> objectHandle = factory->NewEmptyJSObject();
121 JSHandle<TaggedArray> keyArray = factory->NewTaggedArray(infoLength);
122 JSHandle<LayoutInfo> layoutInfoHandle = factory->CreateLayoutInfo(infoLength);
123 EXPECT_TRUE(*layoutInfoHandle != nullptr);
124 std::vector<JSTaggedValue> keyVector;
125 // Add key to layout info
126 for (int i = 0; i < infoLength; i++) {
127 JSHandle<JSTaggedValue> elements(thread, JSTaggedValue(i));
128 JSHandle<JSTaggedValue> elementsKey(JSTaggedValue::ToString(thread, elements));
129 defaultAttr.SetOffset(i);
130 if (enumKeys) {
131 if (i != 3) { // 3: index
132 defaultAttr.SetEnumerable(false);
133 } else {
134 defaultAttr.SetEnumerable(true);
135 }
136 }
137 layoutInfoHandle->AddKey(thread, i, elementsKey.GetTaggedValue(), defaultAttr);
138 }
139 if (enumKeys) {
140 uint32_t keys = 0;
141 layoutInfoHandle->GetAllEnumKeys(thread, infoLength, 0, keyArray, &keys, objectHandle); // 0: offset
142 EXPECT_EQ(keyArray->Get(0), key3.GetTaggedValue());
143 EXPECT_EQ(keys, 1U);
144 } else {
145 layoutInfoHandle->GetAllKeys(thread, infoLength, 0, *keyArray, objectHandle); // 0: offset
146 layoutInfoHandle->GetAllKeysForSerialization(infoLength, keyVector);
147 EXPECT_EQ(keyArray->GetLength(), keyVector.size());
148
149 for (int i = 0;i < infoLength; i++) {
150 bool result = JSTaggedValue::SameValue(keyArray->Get(i), keyVector[i]);
151 EXPECT_TRUE(result);
152 }
153 }
154 }
155
HWTEST_F_L0(LayoutInfoTest,GetAllKeys)156 HWTEST_F_L0(LayoutInfoTest, GetAllKeys)
157 {
158 GetAllKeysCommon(thread);
159 }
160
HWTEST_F_L0(LayoutInfoTest,GetAllEnumKeys)161 HWTEST_F_L0(LayoutInfoTest, GetAllEnumKeys)
162 {
163 GetAllKeysCommon(thread, true);
164 }
165 } // namespace panda::ecmascript
166