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