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<TaggedArray> keyArray = factory->NewTaggedArray(infoLength);
121 JSHandle<LayoutInfo> layoutInfoHandle = factory->CreateLayoutInfo(infoLength);
122 EXPECT_TRUE(*layoutInfoHandle != nullptr);
123 std::vector<JSTaggedValue> keyVector;
124 // Add key to layout info
125 for (int i = 0; i < infoLength; i++) {
126 JSHandle<JSTaggedValue> elements(thread, JSTaggedValue(i));
127 JSHandle<JSTaggedValue> elementsKey(JSTaggedValue::ToString(thread, elements));
128 defaultAttr.SetOffset(i);
129 if (enumKeys) {
130 if (i != 3) { // 3: index
131 defaultAttr.SetEnumerable(false);
132 } else {
133 defaultAttr.SetEnumerable(true);
134 }
135 }
136 layoutInfoHandle->AddKey(thread, i, elementsKey.GetTaggedValue(), defaultAttr);
137 }
138 if (enumKeys) {
139 uint32_t keys = 0;
140 layoutInfoHandle->GetAllEnumKeys(thread, infoLength, 0, keyArray, &keys); // 0: offset
141 EXPECT_EQ(keyArray->Get(0), key3.GetTaggedValue());
142 EXPECT_EQ(keys, 1U);
143 } else {
144 layoutInfoHandle->GetAllKeys(thread, infoLength, 0, *keyArray); // 0: offset
145 layoutInfoHandle->GetAllKeysForSerialization(infoLength, keyVector);
146 EXPECT_EQ(keyArray->GetLength(), keyVector.size());
147
148 for (int i = 0;i < infoLength; i++) {
149 bool result = JSTaggedValue::SameValue(keyArray->Get(i), keyVector[i]);
150 EXPECT_TRUE(result);
151 }
152 }
153 }
154
HWTEST_F_L0(LayoutInfoTest,GetAllKeys)155 HWTEST_F_L0(LayoutInfoTest, GetAllKeys)
156 {
157 GetAllKeysCommon(thread);
158 }
159
HWTEST_F_L0(LayoutInfoTest,GetAllEnumKeys)160 HWTEST_F_L0(LayoutInfoTest, GetAllEnumKeys)
161 {
162 GetAllKeysCommon(thread, true);
163 }
164 } // namespace panda::ecmascript
165