1 /*
2 * Copyright (c) 2024 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/ecma_string.h"
17 #include "ecmascript/ecma_vm.h"
18 #include "ecmascript/global_env.h"
19 #include "ecmascript/shared_objects/js_shared_array.h"
20 #include "ecmascript/js_tagged_value.h"
21 #include "ecmascript/object_factory.h"
22 #include "ecmascript/tests/test_helper.h"
23
24 using namespace panda;
25
26 using namespace panda::ecmascript;
27
28 namespace panda::test {
29 class JSSharedArrayTest : public BaseTestWithScope<false> {
30 };
31
HWTEST_F_L0(JSSharedArrayTest,SetCapacityTest001)32 HWTEST_F_L0(JSSharedArrayTest, SetCapacityTest001)
33 {
34 JSHandle<JSTaggedValue> lengthKeyHandle = thread->GlobalConstants()->GetHandledLengthString();
35 JSSharedArray *arr = JSSharedArray::Cast(JSSharedArray::ArrayCreate(thread, JSTaggedNumber(0))
36 .GetTaggedValue()
37 .GetTaggedObject());
38 EXPECT_TRUE(arr != nullptr);
39 JSHandle<JSTaggedValue> obj(thread, arr);
40 EXPECT_EQ(JSSharedArray::GetProperty(thread, obj, lengthKeyHandle, SCheckMode::SKIP).GetValue()->GetInt(), 0);
41
42 auto ecmaVM = thread->GetEcmaVM();
43 ObjectFactory *factory = ecmaVM->GetFactory();
44 JSHandle<TaggedArray> values(factory->NewTaggedArray(5));
45 for (int i = 0; i < 5; i++)
46 {
47 values->Set(thread, i, JSTaggedValue(i + 1));
48 }
49 JSHandle<TaggedArray> result(JSSharedArray::SetCapacity(thread, values, 10U));
50 JSHandle<JSSharedArray> sharedArray(JSSharedArray::CreateArrayFromList(thread, result));
51 EXPECT_EQ(sharedArray->GetArrayLength(), 10U);
52 }
53
HWTEST_F_L0(JSSharedArrayTest,SetCapacityTest002)54 HWTEST_F_L0(JSSharedArrayTest, SetCapacityTest002)
55 {
56 JSSharedArray *sharedArray = JSSharedArray::Cast(JSSharedArray::ArrayCreate(thread, JSTaggedNumber(5))
57 .GetTaggedValue()
58 .GetTaggedObject());
59 EXPECT_TRUE(sharedArray != nullptr);
60 JSHandle<JSObject> obj(thread, sharedArray);
61 JSSharedArray::SetCapacity(thread, obj, 5U, 10U);
62 EXPECT_EQ(sharedArray->GetArrayLength(), 10U);
63 }
64
HWTEST_F_L0(JSSharedArrayTest,SetCapacityTest003)65 HWTEST_F_L0(JSSharedArrayTest, SetCapacityTest003)
66 {
67 JSSharedArray *sharedArray = JSSharedArray::Cast(JSSharedArray::ArrayCreate(thread, JSTaggedNumber(5))
68 .GetTaggedValue()
69 .GetTaggedObject());
70 EXPECT_TRUE(sharedArray != nullptr);
71 JSHandle<JSObject> obj(thread, sharedArray);
72 JSSharedArray::SetCapacity(thread, obj, 10U, 5U);
73 EXPECT_EQ(sharedArray->GetArrayLength(), 5U);
74 }
75
HWTEST_F_L0(JSSharedArrayTest,PropertyKeyToArrayIndex)76 HWTEST_F_L0(JSSharedArrayTest, PropertyKeyToArrayIndex)
77 {
78 auto ecmaVM = thread->GetEcmaVM();
79 ObjectFactory *factory = ecmaVM->GetFactory();
80 JSHandle<TaggedArray> values(factory->NewTaggedArray(5));
81 for (int i = 0; i < 5; i++)
82 {
83 values->Set(thread, i, JSTaggedValue(i + 1));
84 }
85 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(5));
86 JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(-1));
87 uint32_t output = 5;
88 ASSERT_TRUE(JSSharedArray::PropertyKeyToArrayIndex(thread, key, &output));
89 ASSERT_FALSE(JSSharedArray::PropertyKeyToArrayIndex(thread, key1, &output));
90 }
91
HWTEST_F_L0(JSSharedArrayTest,ArraySetLength)92 HWTEST_F_L0(JSSharedArrayTest, ArraySetLength)
93 {
94 JSHandle<JSTaggedValue> lengthKeyHandle = thread->GlobalConstants()->GetHandledLengthString();
95 JSSharedArray *arr = JSSharedArray::Cast(JSSharedArray::ArrayCreate(thread, JSTaggedNumber(1))
96 .GetTaggedValue()
97 .GetTaggedObject());
98 EXPECT_TRUE(arr != nullptr);
99 JSHandle<JSObject> obj(thread, arr);
100 PropertyDescriptor desc1(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(0)), true, true, true);
101 ASSERT_FALSE(JSSharedArray::ArraySetLength(thread, obj, desc1));
102 EXPECT_EQ(JSSharedArray::GetProperty(thread, JSHandle<JSTaggedValue>(obj), lengthKeyHandle, SCheckMode::SKIP)
103 .GetValue()
104 ->GetInt(),
105 1);
106
107 std::vector<int> vals{1, 2, 3, 4, 5};
108 std::vector<JSHandle<JSTaggedValue>> keys;
109 for (size_t i = 0; i < vals.size(); i++)
110 {
111 keys.push_back(JSHandle<JSTaggedValue>(thread, JSTaggedValue(static_cast<int>(i))));
112 PropertyDescriptor desc0(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(vals[i])), true, true, true);
113 EXPECT_TRUE(desc0.IsWritable());
114 JSSharedArray::DefineOwnProperty(thread, obj, keys[i], desc0);
115 }
116 PropertyDescriptor desc2(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(6)), true, true, true);
117 EXPECT_TRUE(desc1.IsWritable());
118 ASSERT_FALSE(JSSharedArray::ArraySetLength(thread, obj, desc2));
119 }
120
HWTEST_F_L0(JSSharedArrayTest,ArraySetLengthTest001)121 HWTEST_F_L0(JSSharedArrayTest, ArraySetLengthTest001)
122 {
123 JSSharedArray *arr = JSSharedArray::Cast(JSSharedArray::ArrayCreate(thread, JSTaggedNumber(1))
124 .GetTaggedValue()
125 .GetTaggedObject());
126 EXPECT_TRUE(arr != nullptr);
127 JSHandle<JSObject> obj(thread, arr);
128 PropertyDescriptor desc(thread);
129 ASSERT_TRUE(JSSharedArray::ArraySetLength(thread, obj, desc));
130 }
131
HWTEST_F_L0(JSSharedArrayTest,ArraySetLengthTest002)132 HWTEST_F_L0(JSSharedArrayTest, ArraySetLengthTest002)
133 {
134 JSSharedArray *arr = JSSharedArray::Cast(JSSharedArray::ArrayCreate(thread, JSTaggedNumber(2))
135 .GetTaggedValue()
136 .GetTaggedObject());
137 EXPECT_TRUE(arr != nullptr);
138 JSHandle<JSObject> obj(thread, arr);
139 PropertyDescriptor desc(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(6)));
140 ASSERT_TRUE(JSSharedArray::ArraySetLength(thread, obj, desc));
141 }
142
HWTEST_F_L0(JSSharedArrayTest,ArraySetLengthTest003)143 HWTEST_F_L0(JSSharedArrayTest, ArraySetLengthTest003)
144 {
145 JSSharedArray *arr = JSSharedArray::Cast(JSSharedArray::ArrayCreate(thread, JSTaggedNumber(1))
146 .GetTaggedValue()
147 .GetTaggedObject());
148 EXPECT_TRUE(arr != nullptr);
149 JSHandle<JSObject> obj(thread, arr);
150 PropertyDescriptor desc1(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(0)), false, true, false);
151
152 ASSERT_FALSE(JSSharedArray::ArraySetLength(thread, obj, desc1));
153 PropertyDescriptor desc2(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(0)), false, true, true);
154
155 ASSERT_FALSE(JSSharedArray::ArraySetLength(thread, obj, desc2));
156 }
157
HWTEST_F_L0(JSSharedArrayTest,ArraySetLengthTest004)158 HWTEST_F_L0(JSSharedArrayTest, ArraySetLengthTest004)
159 {
160 JSSharedArray *arr = JSSharedArray::Cast(JSSharedArray::ArrayCreate(thread, JSTaggedNumber(2))
161 .GetTaggedValue()
162 .GetTaggedObject());
163 EXPECT_TRUE(arr != nullptr);
164 JSHandle<JSObject> obj(thread, arr);
165 PropertyDescriptor desc(thread);
166 JSSharedArray::DefineOwnProperty(thread, obj,
167 JSHandle<JSTaggedValue>(thread, JSTaggedValue(static_cast<int>(0))), desc);
168 PropertyDescriptor desc1(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)), true, false, false);
169 ASSERT_TRUE(JSSharedArray::ArraySetLength(thread, obj, desc1));
170 }
171
HWTEST_F_L0(JSSharedArrayTest,ArrayCreateTest001)172 HWTEST_F_L0(JSSharedArrayTest, ArrayCreateTest001)
173 {
174 double len = (double)std::numeric_limits<uint32_t>::max() + 1000;
175 JSHandle<JSTaggedValue> result = JSSharedArray::ArrayCreate(thread, JSTaggedNumber(len));
176 EXPECT_EQ(result->GetRawData(), JSTaggedValue::Exception().GetRawData());
177 }
178
HWTEST_F_L0(JSSharedArrayTest,ArrayCreateTest002)179 HWTEST_F_L0(JSSharedArrayTest, ArrayCreateTest002)
180 {
181 JSHandle<JSTaggedValue> result = JSSharedArray::ArrayCreate( \
182 thread, JSTaggedNumber(10), ArrayMode::LITERAL);
183 JSSharedArray *arr = JSSharedArray::Cast(result.GetTaggedValue().GetTaggedObject());
184 EXPECT_EQ(arr->GetArrayLength(), 10);
185 }
186
HWTEST_F_L0(JSSharedArrayTest,LengthSetterTest001)187 HWTEST_F_L0(JSSharedArrayTest, LengthSetterTest001)
188 {
189 JSHandle<JSObject> self;
190 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(static_cast<int32_t>(-64)));
191 bool result = JSSharedArray::LengthSetter(thread, self, value, true);
192 EXPECT_EQ(result, false);
193 }
194
HWTEST_F_L0(JSSharedArrayTest,LengthSetterTest003)195 HWTEST_F_L0(JSSharedArrayTest, LengthSetterTest003)
196 {
197 JSSharedArray *arr = JSSharedArray::Cast(JSSharedArray::ArrayCreate(thread, JSTaggedNumber(15))
198 .GetTaggedValue()
199 .GetTaggedObject());
200 EXPECT_TRUE(arr != nullptr);
201 JSHandle<JSObject> self(thread, arr);
202 auto *hclass = self->GetJSHClass();
203 LayoutInfo *layoutInfo = LayoutInfo::Cast(hclass->GetLayout(thread).GetTaggedObject());
204 PropertyAttributes attr(layoutInfo->GetAttr(thread, JSArray::LENGTH_INLINE_PROPERTY_INDEX));
205 attr.SetWritable(false);
206 layoutInfo->SetNormalAttr(thread, 0, attr);
207 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(10));
208 bool result = JSSharedArray::LengthSetter(thread, self, value, true);
209 EXPECT_EQ(result, false);
210 }
211
HWTEST_F_L0(JSSharedArrayTest,ArraySpeciesCreateTest001)212 HWTEST_F_L0(JSSharedArrayTest, ArraySpeciesCreateTest001)
213 {
214 JSArray *arr = JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetObject<JSArray>();
215 EXPECT_TRUE(arr != nullptr);
216 JSHandle<JSObject> obj(thread, arr);
217 JSSharedArray::ArraySpeciesCreate(thread, obj, JSTaggedNumber(10));
218 }
219
HWTEST_F_L0(JSSharedArrayTest,LengthSetterTest004)220 HWTEST_F_L0(JSSharedArrayTest, LengthSetterTest004)
221 {
222 JSSharedArray *arr = JSSharedArray::Cast(JSSharedArray::ArrayCreate(thread, JSTaggedNumber(15))
223 .GetTaggedValue()
224 .GetTaggedObject());
225 EXPECT_TRUE(arr != nullptr);
226 JSHandle<JSObject> self(thread, arr);
227 auto *hclass = self->GetJSHClass();
228 LayoutInfo *layoutInfo = LayoutInfo::Cast(hclass->GetLayout(thread).GetTaggedObject());
229 PropertyAttributes attr(layoutInfo->GetAttr(thread, JSArray::LENGTH_INLINE_PROPERTY_INDEX));
230 attr.SetWritable(false);
231 layoutInfo->SetNormalAttr(thread, 0, attr);
232 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(10));
233 bool result = JSSharedArray::LengthSetter(thread, self, value, false);
234 EXPECT_EQ(result, false);
235 }
236
HWTEST_F_L0(JSSharedArrayTest,ArraySetLengthTest005)237 HWTEST_F_L0(JSSharedArrayTest, ArraySetLengthTest005)
238 {
239 JSSharedArray *arr = JSSharedArray::Cast(JSSharedArray::ArrayCreate(thread, JSTaggedNumber(2))
240 .GetTaggedValue()
241 .GetTaggedObject());
242 EXPECT_TRUE(arr != nullptr);
243 JSHandle<JSObject> obj(thread, arr);
244 PropertyDescriptor desc(thread);
245 JSSharedArray::DefineOwnProperty(thread, obj,
246 JSHandle<JSTaggedValue>(thread, JSTaggedValue(static_cast<int>(0))), desc);
247 PropertyDescriptor desc1(thread, JSHandle<JSTaggedValue>(thread,
248 JSTaggedValue(std::numeric_limits<uint64_t>::max())), true, false, false);
249 ASSERT_FALSE(JSSharedArray::ArraySetLength(thread, obj, desc1));
250 }
251
HWTEST_F_L0(JSSharedArrayTest,LengthSetterTest002)252 HWTEST_F_L0(JSSharedArrayTest, LengthSetterTest002)
253 {
254 JSSharedArray *arr = JSSharedArray::Cast(JSSharedArray::ArrayCreate(thread, JSTaggedNumber(0))
255 .GetTaggedValue()
256 .GetTaggedObject());
257 EXPECT_TRUE(arr != nullptr);
258 JSHandle<JSObject> self(thread, arr);
259 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(static_cast<int32_t>(0)));
260 bool result = JSSharedArray::LengthSetter(thread, self, value, false);
261 EXPECT_EQ(result, true);
262 }
263
HWTEST_F_L0(JSSharedArrayTest,CheckAndCopyArray)264 HWTEST_F_L0(JSSharedArrayTest, CheckAndCopyArray)
265 {
266 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
267 JSHandle<JSSharedArray> jsArray = factory->NewJSSArray();
268 JSHandle<TaggedArray> prop(thread, jsArray->GetProperties(thread));
269 JSHClass* hclass = JSHandle<TaggedObject>(prop)->GetClass();
270 hclass->SetObjectType(JSType::COW_TAGGED_ARRAY);
271 ASSERT_EQ(hclass->GetObjectType(), JSType::COW_TAGGED_ARRAY);
272 JSSharedArray::CheckAndCopyArray(thread, jsArray);
273 }
274 } // namespace panda::test