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.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 testing::Test {
24 public:
SetUpTestCase()25 static void SetUpTestCase()
26 {
27 GTEST_LOG_(INFO) << "SetUpTestCase";
28 }
29
TearDownTestCase()30 static void TearDownTestCase()
31 {
32 GTEST_LOG_(INFO) << "TearDownCase";
33 }
34
SetUp()35 void SetUp() override
36 {
37 TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
38 }
39
TearDown()40 void TearDown() override
41 {
42 TestHelper::DestroyEcmaVMWithScope(instance, scope);
43 }
44
45 EcmaVM *instance {nullptr};
46 EcmaHandleScope *scope {nullptr};
47 JSThread *thread {nullptr};
48 };
49
HWTEST_F_L0(LayoutInfoTest,SetNumberOfElements)50 HWTEST_F_L0(LayoutInfoTest, SetNumberOfElements)
51 {
52 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
53 int32_t infoLength = 2;
54 JSHandle<LayoutInfo> layoutInfoHandle = factory->CreateLayoutInfo(infoLength);
55 EXPECT_TRUE(*layoutInfoHandle != nullptr);
56
57 layoutInfoHandle->SetNumberOfElements(thread, 100);
58 EXPECT_EQ(layoutInfoHandle->NumberOfElements(), 100);
59 }
60
HWTEST_F_L0(LayoutInfoTest,SetPropertyInit)61 HWTEST_F_L0(LayoutInfoTest, SetPropertyInit)
62 {
63 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
64 int32_t infoLength = 3;
65 PropertyAttributes defaultAttr = PropertyAttributes::Default();
66 defaultAttr.SetNormalAttr(infoLength);
67 JSHandle<JSTaggedValue> key(factory->NewFromASCII("key"));
68 JSHandle<LayoutInfo> layoutInfoHandle = factory->CreateLayoutInfo(infoLength);
69 EXPECT_TRUE(*layoutInfoHandle != nullptr);
70
71 layoutInfoHandle->SetPropertyInit(thread, 0, key.GetTaggedValue(), defaultAttr);
72 EXPECT_EQ(layoutInfoHandle->GetKey(0), key.GetTaggedValue());
73 EXPECT_EQ(layoutInfoHandle->GetAttr(0).GetNormalAttr(), static_cast<uint32_t>(infoLength));
74 }
75
HWTEST_F_L0(LayoutInfoTest,SetSortedIndex)76 HWTEST_F_L0(LayoutInfoTest, SetSortedIndex)
77 {
78 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
79 int32_t infoLength = 5;
80 PropertyAttributes defaultAttr = PropertyAttributes::Default();
81 defaultAttr.SetNormalAttr(infoLength);
82 JSHandle<JSTaggedValue> key1(factory->NewFromASCII("hello"));
83 JSHandle<JSTaggedValue> key2(factory->NewFromASCII("world"));
84 JSHandle<LayoutInfo> layoutInfoHandle = factory->CreateLayoutInfo(infoLength);
85 EXPECT_TRUE(*layoutInfoHandle != nullptr);
86
87 layoutInfoHandle->SetPropertyInit(thread, 0, key1.GetTaggedValue(), defaultAttr);
88 layoutInfoHandle->SetPropertyInit(thread, 1, key2.GetTaggedValue(), defaultAttr);
89 layoutInfoHandle->SetSortedIndex(thread, 0, infoLength - 4);
90 EXPECT_EQ(layoutInfoHandle->GetSortedIndex(0), 1U);
91 EXPECT_EQ(layoutInfoHandle->GetSortedKey(0), key2.GetTaggedValue());
92 }
93
HWTEST_F_L0(LayoutInfoTest,FindElementWithCache)94 HWTEST_F_L0(LayoutInfoTest, FindElementWithCache)
95 {
96 int infoLength = 5;
97 int newPropertiesLength = 11;
98 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
99 PropertyAttributes defaultAttr = PropertyAttributes::Default();
100 JSHandle<JSTaggedValue> key1(factory->NewFromASCII("1"));
101 JSHandle<JSTaggedValue> key4(factory->NewFromASCII("4"));
102 JSHandle<JSTaggedValue> key5(factory->NewFromASCII("5"));
103 JSHandle<JSTaggedValue> key10(factory->NewFromASCII("10"));
104 JSHandle<JSTaggedValue> key11(factory->NewFromASCII("11"));
105 JSHandle<LayoutInfo> layoutInfoHandle = factory->CreateLayoutInfo(infoLength);
106 EXPECT_TRUE(*layoutInfoHandle != nullptr);
107 for (int i = 0; i < infoLength; i++) {
108 JSHandle<JSTaggedValue> elements(thread, JSTaggedValue(i));
109 JSHandle<JSTaggedValue> elementsKey(JSTaggedValue::ToString(thread, elements));
110 defaultAttr.SetOffset(i);
111 layoutInfoHandle->AddKey(thread, i, elementsKey.GetTaggedValue(), defaultAttr);
112 }
113 int propertiesNumber = layoutInfoHandle->NumberOfElements();
114 int result = 0;
115 result = layoutInfoHandle->FindElementWithCache(thread, nullptr, key1.GetTaggedValue(), propertiesNumber);
116 EXPECT_EQ(result, 1); // 1: Index corresponding to key1
117 result = layoutInfoHandle->FindElementWithCache(thread, nullptr, key5.GetTaggedValue(), propertiesNumber);
118 EXPECT_EQ(result, -1); // -1: not find
119 // extend layoutInfo
120 JSHandle<LayoutInfo> newLayoutInfo = factory->ExtendLayoutInfo(layoutInfoHandle, newPropertiesLength);
121 for (int i = 5; i < newPropertiesLength; i++) {
122 JSHandle<JSTaggedValue> elements(thread, JSTaggedValue(i));
123 JSHandle<JSTaggedValue> elementsKey(JSTaggedValue::ToString(thread, elements));
124 defaultAttr.SetOffset(i);
125 newLayoutInfo->AddKey(thread, i, elementsKey.GetTaggedValue(), defaultAttr);
126 }
127 result = newLayoutInfo->FindElementWithCache(thread, nullptr, key4.GetTaggedValue(), newPropertiesLength);
128 EXPECT_EQ(result, 4); // 4: Index corresponding to key4
129 result = newLayoutInfo->FindElementWithCache(thread, nullptr, key10.GetTaggedValue(), newPropertiesLength);
130 EXPECT_EQ(result, 10); // 10: Index corresponding to key10
131 result = newLayoutInfo->FindElementWithCache(thread, nullptr, key5.GetTaggedValue(), newPropertiesLength);
132 EXPECT_EQ(result, 5); // 5: Index corresponding to key5
133 result = newLayoutInfo->FindElementWithCache(thread, nullptr, key11.GetTaggedValue(), newPropertiesLength);
134 EXPECT_EQ(result, -1); // -1: not find
135 }
136
HWTEST_F_L0(LayoutInfoTest,GetAllKeys)137 HWTEST_F_L0(LayoutInfoTest, GetAllKeys)
138 {
139 int infoLength = 5;
140 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
141 PropertyAttributes defaultAttr = PropertyAttributes::Default();
142 JSHandle<JSTaggedValue> key3(factory->NewFromASCII("3"));
143
144 JSHandle<JSObject> objectHandle = factory->NewEmptyJSObject();
145 JSHandle<TaggedArray> keyArray = factory->NewTaggedArray(infoLength);
146 JSHandle<LayoutInfo> layoutInfoHandle = factory->CreateLayoutInfo(infoLength);
147 EXPECT_TRUE(*layoutInfoHandle != nullptr);
148 std::vector<JSTaggedValue> keyVector;
149 // Add key to layout info
150 for (int i = 0; i < infoLength; i++) {
151 JSHandle<JSTaggedValue> elements(thread, JSTaggedValue(i));
152 JSHandle<JSTaggedValue> elementsKey(JSTaggedValue::ToString(thread, elements));
153 defaultAttr.SetOffset(i);
154 layoutInfoHandle->AddKey(thread, i, elementsKey.GetTaggedValue(), defaultAttr);
155 }
156 layoutInfoHandle->GetAllKeys(thread, infoLength, 0, *keyArray, objectHandle); // 0: offset
157 layoutInfoHandle->GetAllKeys(infoLength, keyVector, objectHandle);
158 EXPECT_EQ(keyArray->GetLength(), keyVector.size());
159
160 for (int i = 0;i < infoLength; i++) {
161 bool result = JSTaggedValue::SameValue(keyArray->Get(i), keyVector[i]);
162 EXPECT_TRUE(result);
163 }
164 }
165
HWTEST_F_L0(LayoutInfoTest,GetAllEnumKeys)166 HWTEST_F_L0(LayoutInfoTest, GetAllEnumKeys)
167 {
168 int infoLength = 5;
169 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
170 PropertyAttributes defaultAttr = PropertyAttributes::Default();
171 JSHandle<JSTaggedValue> key3(factory->NewFromASCII("3"));
172
173 JSHandle<JSObject> objectHandle = factory->NewEmptyJSObject();
174 JSHandle<TaggedArray> keyArray = factory->NewTaggedArray(infoLength);
175 JSHandle<LayoutInfo> layoutInfoHandle = factory->CreateLayoutInfo(infoLength);
176 EXPECT_TRUE(*layoutInfoHandle != nullptr);
177 std::vector<JSTaggedValue> keyVector;
178 // Add key to layout info
179 for (int i = 0; i < infoLength; i++) {
180 JSHandle<JSTaggedValue> elements(thread, JSTaggedValue(i));
181 JSHandle<JSTaggedValue> elementsKey(JSTaggedValue::ToString(thread, elements));
182 defaultAttr.SetOffset(i);
183 if (i != 3) {
184 defaultAttr.SetEnumerable(false);
185 }
186 else {
187 defaultAttr.SetEnumerable(true);
188 }
189 layoutInfoHandle->AddKey(thread, i, elementsKey.GetTaggedValue(), defaultAttr);
190 }
191 uint32_t keys = 0;
192 layoutInfoHandle->GetAllEnumKeys(thread, infoLength, 0, *keyArray, &keys, objectHandle); // 0: offset
193 EXPECT_EQ(keyArray->Get(0), key3.GetTaggedValue());
194 EXPECT_EQ(keys, 1U);
195 }
196 } // namespace panda::ecmascript