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
33using namespace panda::ecmascript;
34using namespace panda::ecmascript::builtins;
35
36namespace panda::test {
37using TypedArray = ecmascript::builtins::BuiltinsTypedArray;
38class BuiltinsAtomicsTest : public BaseTestWithScope<false> {
39};
40
41JSTypedArray *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
157JSTypedArray *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
179enum 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
193static 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
246static 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
256HWTEST_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
268static 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
279HWTEST_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
287HWTEST_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
298HWTEST_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
319HWTEST_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
331HWTEST_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
348HWTEST_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
360HWTEST_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
376HWTEST_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
411HWTEST_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
423HWTEST_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
439HWTEST_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
451HWTEST_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
467HWTEST_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
479HWTEST_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
495HWTEST_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
507HWTEST_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
523HWTEST_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
536HWTEST_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
549HWTEST_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
562HWTEST_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
575HWTEST_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
588HWTEST_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
600HWTEST_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
616HWTEST_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
635HWTEST_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