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 "builtin_test_util.h"
17 #include "ecmascript/builtins/builtins_atomics.h"
18
19 #include "ecmascript/builtins/builtins_array.h"
20 #include "ecmascript/builtins/builtins_typedarray.h"
21 #include "ecmascript/builtins/builtins_sharedarraybuffer.h"
22 #include "ecmascript/js_arraybuffer.h"
23 #include "ecmascript/base/atomic_helper.h"
24 #include "ecmascript/js_tagged_value.h"
25 #include "ecmascript/ecma_vm.h"
26 #include "ecmascript/global_env.h"
27 #include "ecmascript/js_array.h"
28 #include "ecmascript/js_handle.h"
29 #include "ecmascript/js_thread.h"
30 #include "ecmascript/js_typed_array.h"
31 #include "ecmascript/tests/test_helper.h"
32
33 using namespace panda::ecmascript;
34 using namespace panda::ecmascript::builtins;
35
36 namespace panda::test {
37 using TypedArray = ecmascript::builtins::BuiltinsTypedArray;
38 class BuiltinsAtomicsTest : public BaseTestWithScope<false> {
39 };
40
CreateTypedArray(JSThread *thread, const JSHandle<TaggedArray> &array, DataViewType type)41 JSTypedArray *CreateTypedArray(JSThread *thread, const JSHandle<TaggedArray> &array, DataViewType type)
42 {
43 auto vm = thread->GetEcmaVM();
44 auto env = vm->GetGlobalEnv();
45 JSHandle<JSTaggedValue> jsarray(JSArray::CreateArrayFromList(thread, array));
46 JSHandle<JSObject> globalObject(thread, env->GetGlobalObject());
47 JSHandle<JSFunction> arrayFunc;
48 JSTaggedValue result = JSTaggedValue::Hole();
49 switch (type) {
50 case DataViewType::BIGINT64: {
51 arrayFunc = JSHandle<JSFunction>(env->GetBigInt64ArrayFunction());
52 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*arrayFunc), 6);
53 ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue(*arrayFunc));
54 ecmaRuntimeCallInfo1->SetThis(JSTaggedValue(*globalObject));
55 ecmaRuntimeCallInfo1->SetCallArg(0, jsarray.GetTaggedValue());
56
57 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
58 result = TypedArray::BigInt64ArrayConstructor(ecmaRuntimeCallInfo1);
59 TestHelper::TearDownFrame(thread, prev);
60 break;
61 }
62 case DataViewType::BIGUINT64: {
63 arrayFunc = JSHandle<JSFunction>(env->GetBigUint64ArrayFunction());
64 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*arrayFunc), 6);
65 ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue(*arrayFunc));
66 ecmaRuntimeCallInfo1->SetThis(JSTaggedValue(*globalObject));
67 ecmaRuntimeCallInfo1->SetCallArg(0, jsarray.GetTaggedValue());
68
69 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
70 result = TypedArray::BigUint64ArrayConstructor(ecmaRuntimeCallInfo1);
71 TestHelper::TearDownFrame(thread, prev);
72 break;
73 }
74 case DataViewType::INT16: {
75 arrayFunc = JSHandle<JSFunction>(env->GetInt16ArrayFunction());
76 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*arrayFunc), 6);
77 ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue(*arrayFunc));
78 ecmaRuntimeCallInfo1->SetThis(JSTaggedValue(*globalObject));
79 ecmaRuntimeCallInfo1->SetCallArg(0, jsarray.GetTaggedValue());
80
81 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
82 result = TypedArray::Int16ArrayConstructor(ecmaRuntimeCallInfo1);
83 TestHelper::TearDownFrame(thread, prev);
84 break;
85 }
86 case DataViewType::INT32: {
87 arrayFunc = JSHandle<JSFunction>(env->GetInt32ArrayFunction());
88 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*arrayFunc), 6);
89 ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue(*arrayFunc));
90 ecmaRuntimeCallInfo1->SetThis(JSTaggedValue(*globalObject));
91 ecmaRuntimeCallInfo1->SetCallArg(0, jsarray.GetTaggedValue());
92
93 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
94 result = TypedArray::Int32ArrayConstructor(ecmaRuntimeCallInfo1);
95 TestHelper::TearDownFrame(thread, prev);
96 break;
97 }
98 case DataViewType::INT8: {
99 arrayFunc = JSHandle<JSFunction>(env->GetInt8ArrayFunction());
100 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*arrayFunc), 6);
101 ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue(*arrayFunc));
102 ecmaRuntimeCallInfo1->SetThis(JSTaggedValue(*globalObject));
103 ecmaRuntimeCallInfo1->SetCallArg(0, jsarray.GetTaggedValue());
104
105 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
106 result = TypedArray::Int8ArrayConstructor(ecmaRuntimeCallInfo1);
107 TestHelper::TearDownFrame(thread, prev);
108 break;
109 }
110 case DataViewType::UINT16: {
111 arrayFunc = JSHandle<JSFunction>(env->GetUint16ArrayFunction());
112 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*arrayFunc), 6);
113 ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue(*arrayFunc));
114 ecmaRuntimeCallInfo1->SetThis(JSTaggedValue(*globalObject));
115 ecmaRuntimeCallInfo1->SetCallArg(0, jsarray.GetTaggedValue());
116
117 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
118 result = TypedArray::Uint16ArrayConstructor(ecmaRuntimeCallInfo1);
119 TestHelper::TearDownFrame(thread, prev);
120 break;
121 }
122 case DataViewType::UINT32: {
123 arrayFunc = JSHandle<JSFunction>(env->GetUint32ArrayFunction());
124 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*arrayFunc), 6);
125 ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue(*arrayFunc));
126 ecmaRuntimeCallInfo1->SetThis(JSTaggedValue(*globalObject));
127 ecmaRuntimeCallInfo1->SetCallArg(0, jsarray.GetTaggedValue());
128
129 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
130 result = TypedArray::Uint32ArrayConstructor(ecmaRuntimeCallInfo1);
131 TestHelper::TearDownFrame(thread, prev);
132 break;
133 }
134 case DataViewType::UINT8: {
135 arrayFunc = JSHandle<JSFunction>(env->GetUint8ArrayFunction());
136 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*arrayFunc), 6);
137 ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue(*arrayFunc));
138 ecmaRuntimeCallInfo1->SetThis(JSTaggedValue(*globalObject));
139 ecmaRuntimeCallInfo1->SetCallArg(0, jsarray.GetTaggedValue());
140
141 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
142 result = TypedArray::Uint8ArrayConstructor(ecmaRuntimeCallInfo1);
143 TestHelper::TearDownFrame(thread, prev);
144 break;
145 }
146 default: {
147 JSHandle<JSTaggedValue> undefined(thread, JSTaggedValue::Undefined());
148 arrayFunc = JSHandle<JSFunction>(undefined);
149 break;
150 }
151 }
152 EXPECT_TRUE(result.IsECMAObject());
153 JSTypedArray *arr = JSTypedArray::Cast(reinterpret_cast<TaggedObject *>(result.GetRawData()));
154 return arr;
155 }
156
CreateInt32TypedArray(JSThread *thread, const JSHandle<JSArrayBuffer> &arrBuf)157 JSTypedArray *CreateInt32TypedArray(JSThread *thread, const JSHandle<JSArrayBuffer> &arrBuf)
158 {
159 auto ecmaVM = thread->GetEcmaVM();
160 JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
161
162 JSHandle<JSFunction> int32_array(env->GetInt32ArrayFunction());
163 JSHandle<JSObject> globalObject(thread, env->GetGlobalObject());
164 // 6 : test case
165 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*int32_array), 6);
166 ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue(*int32_array));
167 ecmaRuntimeCallInfo1->SetThis(JSTaggedValue(*globalObject));
168 ecmaRuntimeCallInfo1->SetCallArg(0, arrBuf.GetTaggedValue());
169
170 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
171 JSTaggedValue result = TypedArray::Int32ArrayConstructor(ecmaRuntimeCallInfo1);
172 TestHelper::TearDownFrame(thread, prev);
173
174 EXPECT_TRUE(result.IsECMAObject());
175 JSTypedArray *int32arr = JSTypedArray::Cast(reinterpret_cast<TaggedObject *>(result.GetRawData()));
176 return int32arr;
177 }
178
179 enum class AlgorithmType {
180 ALGORITHM_AND,
181 ALGORITHM_ADD,
182 ALGORITHM_SUB,
183 ALGORITHM_OR,
184 ALGORITHM_XOR,
185 ALGORITHM_LOAD,
186 ALGORITHM_STORE,
187 ALGORITHM_WAIT,
188 ALGORITHM_NOTIFY,
189 ALGORITHM_EXCHANGE,
190 ALGORITHM_COMP_EXCHANGE,
191 };
192
AtomicsAlgorithm(JSThread *thread, JSHandle<JSTaggedValue>& obj, std::vector<int32_t>& vals, uint32_t argLen = 8, AlgorithmType type = AlgorithmType::ALGORITHM_LOAD)193 static JSTaggedValue AtomicsAlgorithm(JSThread *thread, JSHandle<JSTaggedValue>& obj, std::vector<int32_t>& vals,
194 uint32_t argLen = 8, AlgorithmType type = AlgorithmType::ALGORITHM_LOAD)
195 {
196 auto ecmaRuntimeCallInfos = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), argLen);
197 ecmaRuntimeCallInfos->SetFunction(JSTaggedValue::Undefined());
198 ecmaRuntimeCallInfos->SetThis(JSTaggedValue::Undefined());
199 ecmaRuntimeCallInfos->SetCallArg(0, obj.GetTaggedValue());
200 for (size_t i = 0; i < vals.size(); i++) {
201 ecmaRuntimeCallInfos->SetCallArg(i+1, JSTaggedValue(vals[i]));
202 }
203 auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfos);
204 JSTaggedValue result;
205 switch (type) {
206 case AlgorithmType::ALGORITHM_AND:
207 result = BuiltinsAtomics::And(ecmaRuntimeCallInfos);
208 break;
209 case AlgorithmType::ALGORITHM_ADD:
210 result = BuiltinsAtomics::Add(ecmaRuntimeCallInfos);
211 break;
212 case AlgorithmType::ALGORITHM_SUB:
213 result = BuiltinsAtomics::Sub(ecmaRuntimeCallInfos);
214 break;
215 case AlgorithmType::ALGORITHM_LOAD:
216 result = BuiltinsAtomics::Load(ecmaRuntimeCallInfos);
217 break;
218 case AlgorithmType::ALGORITHM_STORE:
219 result = BuiltinsAtomics::Store(ecmaRuntimeCallInfos);
220 break;
221 case AlgorithmType::ALGORITHM_COMP_EXCHANGE:
222 result = BuiltinsAtomics::CompareExchange(ecmaRuntimeCallInfos);
223 break;
224 case AlgorithmType::ALGORITHM_EXCHANGE:
225 result = BuiltinsAtomics::Exchange(ecmaRuntimeCallInfos);
226 break;
227 case AlgorithmType::ALGORITHM_OR:
228 result = BuiltinsAtomics::Or(ecmaRuntimeCallInfos);
229 break;
230 case AlgorithmType::ALGORITHM_XOR:
231 result = BuiltinsAtomics::Xor(ecmaRuntimeCallInfos);
232 break;
233 case AlgorithmType::ALGORITHM_WAIT:
234 result = BuiltinsAtomics::Wait(ecmaRuntimeCallInfos);
235 break;
236 case AlgorithmType::ALGORITHM_NOTIFY:
237 result = BuiltinsAtomics::Notify(ecmaRuntimeCallInfos);
238 break;
239 default:
240 break;
241 }
242 TestHelper::TearDownFrame(thread, prev);
243 return result;
244 }
245
CreateArrayList(JSThread *thread, std::vector<int32_t> vals, size_t maxLen)246 static JSHandle<TaggedArray> CreateArrayList(JSThread *thread, std::vector<int32_t> vals, size_t maxLen)
247 {
248 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
249 JSHandle<TaggedArray> array(factory->NewTaggedArray(maxLen));
250 for (size_t i = 0; i < vals.size(); i++) {
251 array->Set(thread, i, JSTaggedValue(vals[i]));
252 }
253 return array;
254 }
255
HWTEST_F_L0(BuiltinsAtomicsTest, Add_1)256 HWTEST_F_L0(BuiltinsAtomicsTest, Add_1)
257 {
258 ASSERT_NE(thread, nullptr);
259 std::vector<int32_t> arrVals{7, 8, 9};
260 auto array = CreateArrayList(thread, arrVals, 3);
261
262 JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array, DataViewType::UINT8));
263 std::vector<int32_t> vals{0, 5};
264 auto result = AtomicsAlgorithm(thread, obj, vals, 10, AlgorithmType::ALGORITHM_ADD);
265 ASSERT_EQ(result.GetInt(), 7);
266 }
267
AddCommon(JSThread *thread, DataViewType type, JSHandle<JSTaggedValue>& obj)268 static JSTaggedValue AddCommon(JSThread *thread, DataViewType type, JSHandle<JSTaggedValue>& obj)
269 {
270 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
271 JSHandle<TaggedArray> array(factory->NewTaggedArray(10)); // 10: array len
272
273 obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array, type));
274 std::vector<int32_t> vals{0, 2};
275 auto result = AtomicsAlgorithm(thread, obj, vals, 10, AlgorithmType::ALGORITHM_ADD);
276 return result;
277 }
278
HWTEST_F_L0(BuiltinsAtomicsTest, Add_2)279 HWTEST_F_L0(BuiltinsAtomicsTest, Add_2)
280 {
281 ASSERT_NE(thread, nullptr);
282 JSHandle<JSTaggedValue> obj;
283 auto result = AddCommon(thread, DataViewType::INT8, obj);
284 ASSERT_EQ(result.GetInt(), 0);
285 }
286
HWTEST_F_L0(BuiltinsAtomicsTest, Add_3)287 HWTEST_F_L0(BuiltinsAtomicsTest, Add_3)
288 {
289 ASSERT_NE(thread, nullptr);
290 JSHandle<JSTaggedValue> obj;
291 auto result = AddCommon(thread, DataViewType::UINT16, obj);
292 ASSERT_EQ(result.GetInt(), 0);
293 std::vector<int32_t> vals{0, 2};
294 result = AtomicsAlgorithm(thread, obj, vals, 10, AlgorithmType::ALGORITHM_ADD);
295 ASSERT_EQ(result.GetInt(), 2);
296 }
297
HWTEST_F_L0(BuiltinsAtomicsTest, SubAndAdd_1)298 HWTEST_F_L0(BuiltinsAtomicsTest, SubAndAdd_1)
299 {
300 ASSERT_NE(thread, nullptr);
301 std::vector<int32_t> arrVals{5, 0, 0};
302 auto array = CreateArrayList(thread, arrVals, arrVals.size());
303
304 JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array, DataViewType::INT16));
305 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10);
306 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
307 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
308 ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
309 ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(0)));
310 ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast<int32_t>(2)));
311
312 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
313 BuiltinsAtomics::Sub(ecmaRuntimeCallInfo);
314 JSTaggedValue addResult = BuiltinsAtomics::Add(ecmaRuntimeCallInfo);
315 TestHelper::TearDownFrame(thread, prev);
316 ASSERT_EQ(addResult.GetInt(), 3);
317 }
318
HWTEST_F_L0(BuiltinsAtomicsTest, And_1)319 HWTEST_F_L0(BuiltinsAtomicsTest, And_1)
320 {
321 ASSERT_NE(thread, nullptr);
322 std::vector<int32_t> arrVals{7, 0, 0};
323 auto array = CreateArrayList(thread, arrVals, 10);
324
325 JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array, DataViewType::INT32));
326 std::vector<int32_t> vals{0, 2};
327 auto result = AtomicsAlgorithm(thread, obj, vals, 10, AlgorithmType::ALGORITHM_AND);
328 ASSERT_EQ(result.GetInt(), 7);
329 }
330
HWTEST_F_L0(BuiltinsAtomicsTest, And_2)331 HWTEST_F_L0(BuiltinsAtomicsTest, And_2)
332 {
333 ASSERT_NE(thread, nullptr);
334 std::vector<int32_t> arrVals{7, 0, 0};
335 auto array = CreateArrayList(thread, arrVals, 10);
336
337 JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array,
338 DataViewType::UINT32));
339 std::vector<int32_t> vals{0, 2};
340 auto result = AtomicsAlgorithm(thread, obj, vals, 10, AlgorithmType::ALGORITHM_AND);
341 ASSERT_EQ(result.GetInt(), 7);
342
343 std::vector<int32_t> storeVals{0};
344 result = AtomicsAlgorithm(thread, obj, storeVals, 8, AlgorithmType::ALGORITHM_LOAD);
345 ASSERT_EQ(result.GetInt(), 2);
346 }
347
HWTEST_F_L0(BuiltinsAtomicsTest, CompareExchange_1)348 HWTEST_F_L0(BuiltinsAtomicsTest, CompareExchange_1)
349 {
350 ASSERT_NE(thread, nullptr);
351 std::vector<int32_t> arrVals{5, 0, 0};
352 auto array = CreateArrayList(thread, arrVals, arrVals.size());
353
354 JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array, DataViewType::UINT8));
355 std::vector<int32_t> vals{0, 5, 2};
356 auto result = AtomicsAlgorithm(thread, obj, vals, 12, AlgorithmType::ALGORITHM_COMP_EXCHANGE);
357 ASSERT_EQ(result.GetInt(), 5);
358 }
359
HWTEST_F_L0(BuiltinsAtomicsTest, CompareExchange_2)360 HWTEST_F_L0(BuiltinsAtomicsTest, CompareExchange_2)
361 {
362 ASSERT_NE(thread, nullptr);
363 std::vector<int32_t> arrVals{5, 0, 0};
364 auto array = CreateArrayList(thread, arrVals, arrVals.size());
365
366 JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array, DataViewType::INT8));
367 std::vector<int32_t> vals{0, 5, 2};
368 auto result = AtomicsAlgorithm(thread, obj, vals, 12, AlgorithmType::ALGORITHM_COMP_EXCHANGE);
369 ASSERT_EQ(result.GetInt(), 5);
370
371 std::vector<int32_t> loadVals{0};
372 result = AtomicsAlgorithm(thread, obj, loadVals, 8, AlgorithmType::ALGORITHM_LOAD);
373 ASSERT_EQ(result.GetInt(), 2);
374 }
375
HWTEST_F_L0(BuiltinsAtomicsTest, TypedArrayCover)376 HWTEST_F_L0(BuiltinsAtomicsTest, TypedArrayCover)
377 {
378 ASSERT_NE(thread, nullptr);
379 std::vector<int32_t> arrVals{2, 0, 0};
380 auto array = CreateArrayList(thread, arrVals, arrVals.size());
381 // UINT16
382 JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array,
383 DataViewType::UINT16));
384 std::vector<int32_t> vals{0, 2, 2};
385 auto result = AtomicsAlgorithm(thread, obj, vals, 12, AlgorithmType::ALGORITHM_COMP_EXCHANGE);
386 ASSERT_EQ(result.GetInt(), 2);
387 // INT16
388 obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array, DataViewType::INT16));
389 result = AtomicsAlgorithm(thread, obj, vals, 12, AlgorithmType::ALGORITHM_COMP_EXCHANGE);
390 ASSERT_EQ(result.GetInt(), 2);
391 // UINT32
392 obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array, DataViewType::UINT32));
393 result = AtomicsAlgorithm(thread, obj, vals, 12, AlgorithmType::ALGORITHM_COMP_EXCHANGE);
394 ASSERT_EQ(result.GetInt(), 2);
395 // INT32
396 obj = JSHandle<JSTaggedValue>(thread, CreateTypedArray(thread, array, DataViewType::INT32));
397 result = AtomicsAlgorithm(thread, obj, vals, 12, AlgorithmType::ALGORITHM_COMP_EXCHANGE);
398 ASSERT_EQ(result.GetInt(), 2);
399
400 // Detached Buffer
401 JSTaggedValue tagged = BuiltTestUtil::CreateBuiltinsSharedArrayBuffer(thread, 0);
402 JSHandle<JSArrayBuffer> arrBuf(thread, JSArrayBuffer::Cast(reinterpret_cast<TaggedObject *>(tagged.GetRawData())));
403 obj = JSHandle<JSTaggedValue>(thread, CreateInt32TypedArray(thread, arrBuf));
404 arrBuf->SetArrayBufferData(thread, JSTaggedValue::Null());
405 result = AtomicsAlgorithm(thread, obj, vals, 12, AlgorithmType::ALGORITHM_COMP_EXCHANGE);
406 EXPECT_TRUE(thread->HasPendingException());
407 EXPECT_EQ(result, JSTaggedValue::Exception());
408 thread->ClearException();
409 }
410
HWTEST_F_L0(BuiltinsAtomicsTest, Exchange_1)411 HWTEST_F_L0(BuiltinsAtomicsTest, Exchange_1)
412 {
413 ASSERT_NE(thread, nullptr);
414 std::vector<int32_t> arrVals{3, 0, 0};
415 auto array = CreateArrayList(thread, arrVals, arrVals.size());
416
417 JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, BuiltTestUtil::CreateTypedArray(thread, array));
418 std::vector<int32_t> vals{0, 6};
419 auto result = AtomicsAlgorithm(thread, obj, vals, 10, AlgorithmType::ALGORITHM_EXCHANGE);
420 ASSERT_EQ(result.GetInt(), 3);
421 }
422
HWTEST_F_L0(BuiltinsAtomicsTest, Exchange_2)423 HWTEST_F_L0(BuiltinsAtomicsTest, Exchange_2)
424 {
425 ASSERT_NE(thread, nullptr);
426 std::vector<int32_t> arrVals{3, 0, 0};
427 auto array = CreateArrayList(thread, arrVals, arrVals.size());
428
429 JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, BuiltTestUtil::CreateTypedArray(thread, array));
430 std::vector<int32_t> vals{0, 6};
431 auto result = AtomicsAlgorithm(thread, obj, vals, 10, AlgorithmType::ALGORITHM_EXCHANGE);
432 ASSERT_EQ(result.GetInt(), 3);
433
434 std::vector<int32_t> loadVals{0};
435 result = AtomicsAlgorithm(thread, obj, loadVals, 8, AlgorithmType::ALGORITHM_LOAD);
436 ASSERT_EQ(result.GetInt(), 6);
437 }
438
HWTEST_F_L0(BuiltinsAtomicsTest, Or_1)439 HWTEST_F_L0(BuiltinsAtomicsTest, Or_1)
440 {
441 ASSERT_NE(thread, nullptr);
442 std::vector<int32_t> arrVals{5, 0, 0};
443 auto array = CreateArrayList(thread, arrVals, arrVals.size());
444
445 JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, BuiltTestUtil::CreateTypedArray(thread, array));
446 std::vector<int32_t> vals{0, 2};
447 auto result = AtomicsAlgorithm(thread, obj, vals, 10, AlgorithmType::ALGORITHM_OR);
448 ASSERT_EQ(result.GetInt(), 5);
449 }
450
HWTEST_F_L0(BuiltinsAtomicsTest, Or_2)451 HWTEST_F_L0(BuiltinsAtomicsTest, Or_2)
452 {
453 ASSERT_NE(thread, nullptr);
454 std::vector<int32_t> arrVals{5, 0, 0};
455 auto array = CreateArrayList(thread, arrVals, arrVals.size());
456
457 JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, BuiltTestUtil::CreateTypedArray(thread, array));
458 std::vector<int32_t> vals{0, 2};
459 auto result = AtomicsAlgorithm(thread, obj, vals, 12, AlgorithmType::ALGORITHM_OR);
460 ASSERT_EQ(result.GetInt(), 5);
461
462 std::vector<int32_t> loadVals{0};
463 result = AtomicsAlgorithm(thread, obj, loadVals, 8, AlgorithmType::ALGORITHM_LOAD);
464 ASSERT_EQ(result.GetInt(), 7);
465 }
466
HWTEST_F_L0(BuiltinsAtomicsTest, Sub_1)467 HWTEST_F_L0(BuiltinsAtomicsTest, Sub_1)
468 {
469 ASSERT_NE(thread, nullptr);
470 std::vector<int32_t> arrVals{5, 0, 0};
471 auto array = CreateArrayList(thread, arrVals, arrVals.size());
472
473 JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, BuiltTestUtil::CreateTypedArray(thread, array));
474 std::vector<int32_t> vals{0, 2};
475 auto result = AtomicsAlgorithm(thread, obj, vals, 10, AlgorithmType::ALGORITHM_SUB);
476 ASSERT_EQ(result.GetInt(), 5);
477 }
478
HWTEST_F_L0(BuiltinsAtomicsTest, Sub_2)479 HWTEST_F_L0(BuiltinsAtomicsTest, Sub_2)
480 {
481 ASSERT_NE(thread, nullptr);
482 std::vector<int32_t> arrVals{0, 5, 0};
483 auto array = CreateArrayList(thread, arrVals, arrVals.size());
484
485 JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, BuiltTestUtil::CreateTypedArray(thread, array));
486 std::vector<int32_t> vals{1, 2};
487 auto result = AtomicsAlgorithm(thread, obj, vals, 10, AlgorithmType::ALGORITHM_SUB);
488 ASSERT_EQ(result.GetInt(), 5);
489
490 std::vector<int32_t> loadVals{1};
491 result = AtomicsAlgorithm(thread, obj, loadVals, 8, AlgorithmType::ALGORITHM_LOAD);
492 ASSERT_EQ(result.GetInt(), 3);
493 }
494
HWTEST_F_L0(BuiltinsAtomicsTest, Xor_1)495 HWTEST_F_L0(BuiltinsAtomicsTest, Xor_1)
496 {
497 ASSERT_NE(thread, nullptr);
498 std::vector<int32_t> arrVals{5, 7, 0};
499 auto array = CreateArrayList(thread, arrVals, arrVals.size());
500
501 JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, BuiltTestUtil::CreateTypedArray(thread, array));
502 std::vector<int32_t> vals{1, 2};
503 auto result = AtomicsAlgorithm(thread, obj, vals, 10, AlgorithmType::ALGORITHM_XOR);
504 ASSERT_EQ(result.GetInt(), 7);
505 }
506
HWTEST_F_L0(BuiltinsAtomicsTest, Xor_2)507 HWTEST_F_L0(BuiltinsAtomicsTest, Xor_2)
508 {
509 ASSERT_NE(thread, nullptr);
510 std::vector<int32_t> arrVals{5, 7, 0};
511 auto array = CreateArrayList(thread, arrVals, arrVals.size());
512
513 JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, BuiltTestUtil::CreateTypedArray(thread, array));
514 std::vector<int32_t> vals{1, 2};
515 auto result = AtomicsAlgorithm(thread, obj, vals, 10, AlgorithmType::ALGORITHM_XOR);
516 ASSERT_EQ(result.GetInt(), 7);
517
518 std::vector<int32_t> loadVals{1};
519 result = AtomicsAlgorithm(thread, obj, loadVals, 8, AlgorithmType::ALGORITHM_LOAD);
520 ASSERT_EQ(result.GetInt(), 5);
521 }
522
HWTEST_F_L0(BuiltinsAtomicsTest, IsLockFree_1)523 HWTEST_F_L0(BuiltinsAtomicsTest, IsLockFree_1)
524 {
525 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
526 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
527 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
528 ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int32_t>(1)));
529
530 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
531 JSTaggedValue result = BuiltinsAtomics::IsLockFree(ecmaRuntimeCallInfo);
532 TestHelper::TearDownFrame(thread, prev);
533 ASSERT_TRUE(result.ToBoolean());
534 }
535
HWTEST_F_L0(BuiltinsAtomicsTest, IsLockFree_2)536 HWTEST_F_L0(BuiltinsAtomicsTest, IsLockFree_2)
537 {
538 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
539 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
540 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
541 ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int32_t>(2)));
542
543 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
544 JSTaggedValue result = BuiltinsAtomics::IsLockFree(ecmaRuntimeCallInfo);
545 TestHelper::TearDownFrame(thread, prev);
546 ASSERT_TRUE(result.ToBoolean());
547 }
548
HWTEST_F_L0(BuiltinsAtomicsTest, IsLockFree_3)549 HWTEST_F_L0(BuiltinsAtomicsTest, IsLockFree_3)
550 {
551 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
552 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
553 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
554 ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int32_t>(4)));
555
556 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
557 JSTaggedValue result = BuiltinsAtomics::IsLockFree(ecmaRuntimeCallInfo);
558 TestHelper::TearDownFrame(thread, prev);
559 ASSERT_TRUE(result.ToBoolean());
560 }
561
HWTEST_F_L0(BuiltinsAtomicsTest, IsLockFree_4)562 HWTEST_F_L0(BuiltinsAtomicsTest, IsLockFree_4)
563 {
564 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
565 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
566 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
567 ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int32_t>(-3)));
568
569 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
570 JSTaggedValue result = BuiltinsAtomics::IsLockFree(ecmaRuntimeCallInfo);
571 TestHelper::TearDownFrame(thread, prev);
572 ASSERT_FALSE(result.ToBoolean());
573 }
574
HWTEST_F_L0(BuiltinsAtomicsTest, IsLockFree_5)575 HWTEST_F_L0(BuiltinsAtomicsTest, IsLockFree_5)
576 {
577 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
578 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
579 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
580 ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int32_t>(8)));
581
582 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
583 JSTaggedValue result = BuiltinsAtomics::IsLockFree(ecmaRuntimeCallInfo);
584 TestHelper::TearDownFrame(thread, prev);
585 ASSERT_TRUE(result.ToBoolean());
586 }
587
HWTEST_F_L0(BuiltinsAtomicsTest, Store_1)588 HWTEST_F_L0(BuiltinsAtomicsTest, Store_1)
589 {
590 ASSERT_NE(thread, nullptr);
591 std::vector<int32_t> arrVals{5, 6, 7};
592 auto array = CreateArrayList(thread, arrVals, arrVals.size());
593
594 JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, BuiltTestUtil::CreateTypedArray(thread, array));
595 std::vector<int32_t> vals{0, 2};
596 auto result = AtomicsAlgorithm(thread, obj, vals, 10, AlgorithmType::ALGORITHM_STORE);
597 ASSERT_EQ(result.GetDouble(), 2);
598 }
599
HWTEST_F_L0(BuiltinsAtomicsTest, Store_2)600 HWTEST_F_L0(BuiltinsAtomicsTest, Store_2)
601 {
602 ASSERT_NE(thread, nullptr);
603 std::vector<int32_t> arrVals{5, 6, 7};
604 auto array = CreateArrayList(thread, arrVals, arrVals.size());
605
606 JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, BuiltTestUtil::CreateTypedArray(thread, array));
607 std::vector<int32_t> vals{0, 2};
608 auto result = AtomicsAlgorithm(thread, obj, vals, 10, AlgorithmType::ALGORITHM_STORE);
609 ASSERT_EQ(result.GetDouble(), 2);
610
611 std::vector<int32_t> addVals{0};
612 result = AtomicsAlgorithm(thread, obj, addVals, 8, AlgorithmType::ALGORITHM_ADD);
613 ASSERT_EQ(result.GetInt(), 2);
614 }
615
HWTEST_F_L0(BuiltinsAtomicsTest, Wait)616 HWTEST_F_L0(BuiltinsAtomicsTest, Wait)
617 {
618 ASSERT_NE(thread, nullptr);
619 JSTaggedValue tagged = BuiltTestUtil::CreateBuiltinsSharedArrayBuffer(thread, 4);
620 JSHandle<JSArrayBuffer> arrBuf(thread, JSArrayBuffer::Cast(reinterpret_cast<TaggedObject *>(tagged.GetRawData())));
621 JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateInt32TypedArray(thread, arrBuf));
622
623 // Not Equal
624 std::vector<int32_t> vals{0, 2, 2};
625 auto result = AtomicsAlgorithm(thread, obj, vals, 12, AlgorithmType::ALGORITHM_WAIT); // 12 : arg max len
626 ASSERT_EQ(result, thread->GlobalConstants()->GetNotEqualString());
627
628 // timeout
629 vals[1] = 0;
630 vals[2] = 100;
631 result = AtomicsAlgorithm(thread, obj, vals, 12, AlgorithmType::ALGORITHM_WAIT); // 12 : arg max len
632 ASSERT_EQ(result, thread->GlobalConstants()->GetTimeoutString());
633 }
634
HWTEST_F_L0(BuiltinsAtomicsTest, Notify)635 HWTEST_F_L0(BuiltinsAtomicsTest, Notify)
636 {
637 ASSERT_NE(thread, nullptr);
638 JSTaggedValue tagged = BuiltTestUtil::CreateBuiltinsSharedArrayBuffer(thread, 4);
639 JSHandle<JSArrayBuffer> arrBuf(thread, JSArrayBuffer::Cast(reinterpret_cast<TaggedObject *>(tagged.GetRawData())));
640 JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateInt32TypedArray(thread, arrBuf));
641
642 std::vector<int32_t> vals{0, 2};
643 auto result = AtomicsAlgorithm(thread, obj, vals, 10, AlgorithmType::ALGORITHM_NOTIFY);
644 ASSERT_EQ(result, JSTaggedValue(0));
645 }
646 }
647