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