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_sharedarraybuffer.h"
18
19#include "ecmascript/ecma_runtime_call_info.h"
20#include "ecmascript/ecma_vm.h"
21#include "ecmascript/global_env.h"
22#include "ecmascript/js_arraybuffer.h"
23#include "ecmascript/js_handle.h"
24#include "ecmascript/js_tagged_value.h"
25#include "ecmascript/tests/test_helper.h"
26#include "ecmascript/builtins/builtins_arraybuffer.h"
27
28using namespace panda::ecmascript;
29using namespace panda::ecmascript::builtins;
30using BuiltinsArrayBuffer = builtins::BuiltinsArrayBuffer;
31
32namespace panda::test {
33class BuiltinsSharedArrayBufferTest : public BaseTestWithScope<false> {
34};
35
36JSArrayBuffer *CreateJSArrayBuffer(JSThread *thread)
37{
38    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
39    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
40    JSHandle<JSTaggedValue> target = env->GetArrayBufferFunction();
41    JSHandle<JSArrayBuffer> jsArrayBuffer =
42        JSHandle<JSArrayBuffer>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(target), target));
43    return *jsArrayBuffer;
44}
45
46// new ArrayBuffer(20)
47HWTEST_F_L0(BuiltinsSharedArrayBufferTest, Constructor1)
48{
49    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
50    JSHandle<JSFunction> sharedArrayBuffer(thread, env->GetSharedArrayBufferFunction().GetTaggedValue());
51    JSHandle<JSObject> globalObject(thread, env->GetGlobalObject());
52    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, sharedArrayBuffer.GetTaggedValue(), 6);
53    ecmaRuntimeCallInfo->SetFunction(sharedArrayBuffer.GetTaggedValue());
54    ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue());
55    ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int32_t>(20)));
56
57    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
58    JSTaggedValue result = BuiltinsSharedArrayBuffer::SharedArrayBufferConstructor(ecmaRuntimeCallInfo);
59    ASSERT_TRUE(result.IsECMAObject());
60}
61
62// (new ArrayBuffer(18)).byteLength
63HWTEST_F_L0(BuiltinsSharedArrayBufferTest, byteLength1)
64{
65    JSTaggedValue tagged = BuiltTestUtil::CreateBuiltinsSharedArrayBuffer(thread, 18);
66    JSHandle<JSArrayBuffer> arrBuf(thread, JSArrayBuffer::Cast(reinterpret_cast<TaggedObject *>(tagged.GetRawData())));
67    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
68    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
69    ecmaRuntimeCallInfo->SetThis(arrBuf.GetTaggedValue());
70
71    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
72    JSTaggedValue result = BuiltinsSharedArrayBuffer::GetByteLength(ecmaRuntimeCallInfo);
73    ASSERT_EQ(result.GetRawData(), JSTaggedValue(18).GetRawData());
74}
75
76// (new ArrayBuffer(10)).slice(1, 5).bytelength
77HWTEST_F_L0(BuiltinsSharedArrayBufferTest, slice1)
78{
79    JSTaggedValue tagged = BuiltTestUtil::CreateBuiltinsSharedArrayBuffer(thread, 10);
80    JSHandle<JSArrayBuffer> arrBuf(thread, JSArrayBuffer::Cast(reinterpret_cast<TaggedObject *>(tagged.GetRawData())));
81    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
82    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
83    ecmaRuntimeCallInfo->SetThis(arrBuf.GetTaggedValue());
84    ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int32_t>(1)));
85    ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(5)));
86
87    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
88    JSTaggedValue result1 = BuiltinsSharedArrayBuffer::Slice(ecmaRuntimeCallInfo);
89    TestHelper::TearDownFrame(thread, prev);
90    JSHandle<JSArrayBuffer> arrBuf1(thread,
91                                    JSArrayBuffer::Cast(reinterpret_cast<TaggedObject *>(result1.GetRawData())));
92    auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
93    ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined());
94    ecmaRuntimeCallInfo1->SetThis(arrBuf1.GetTaggedValue());
95    prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
96    JSTaggedValue result2 = BuiltinsSharedArrayBuffer::GetByteLength(ecmaRuntimeCallInfo1);
97    TestHelper::TearDownFrame(thread, prev);
98    ASSERT_EQ(result2.GetRawData(), JSTaggedValue(4).GetRawData());
99
100    // IsShared false
101    JSTaggedValue tagged1 = BuiltTestUtil::CreateBuiltinsSharedArrayBuffer(thread, 10);
102    JSHandle<JSArrayBuffer> arrBuf2(thread, JSArrayBuffer::Cast(
103                                    reinterpret_cast<TaggedObject *>(tagged1.GetRawData())));
104    arrBuf2->SetShared(false);
105    auto ecmaRuntimeCallInfo2 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
106    ecmaRuntimeCallInfo2->SetFunction(JSTaggedValue::Undefined());
107    ecmaRuntimeCallInfo2->SetThis(arrBuf2.GetTaggedValue());
108    ecmaRuntimeCallInfo2->SetCallArg(0, JSTaggedValue(static_cast<int32_t>(1)));
109    ecmaRuntimeCallInfo2->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(5)));
110
111    prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo2);
112    JSTaggedValue result3 = BuiltinsSharedArrayBuffer::Slice(ecmaRuntimeCallInfo2);
113    TestHelper::TearDownFrame(thread, prev);
114    EXPECT_TRUE(thread->HasPendingException());
115    EXPECT_EQ(result3, JSTaggedValue::Exception());
116    thread->ClearException();
117}
118
119HWTEST_F_L0(BuiltinsSharedArrayBufferTest, IsSharedArrayBuffer)
120{
121    JSTaggedValue tagged = BuiltTestUtil::CreateBuiltinsSharedArrayBuffer(thread, 10);
122    JSHandle<JSArrayBuffer> arrBuf(thread,
123                                   JSArrayBuffer::Cast(reinterpret_cast<TaggedObject *>(tagged.GetRawData())));
124    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
125    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
126    ecmaRuntimeCallInfo->SetThis(arrBuf.GetTaggedValue());
127    ecmaRuntimeCallInfo->SetCallArg(0, arrBuf.GetTaggedValue()); // JSTaggedValue(static_cast<int32_t>(1))
128
129    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
130    JSTaggedValue result = BuiltinsSharedArrayBuffer::IsSharedArrayBuffer(ecmaRuntimeCallInfo);
131    TestHelper::TearDownFrame(thread, prev);
132    ASSERT_EQ(result, JSTaggedValue::True());
133    // Is Not ECMAObject
134    ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
135    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
136    ecmaRuntimeCallInfo->SetThis(arrBuf.GetTaggedValue());
137    ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue::Undefined());
138
139    prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
140    result = BuiltinsSharedArrayBuffer::IsSharedArrayBuffer(ecmaRuntimeCallInfo);
141    TestHelper::TearDownFrame(thread, prev);
142    ASSERT_EQ(result, JSTaggedValue::False());
143    // Is Not sharedbuffer
144    JSHandle<JSArrayBuffer> jsArrayBuffer(thread, CreateJSArrayBuffer(thread));
145    ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
146    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
147    ecmaRuntimeCallInfo->SetThis(arrBuf.GetTaggedValue());
148    ecmaRuntimeCallInfo->SetCallArg(0, jsArrayBuffer.GetTaggedValue());
149
150    prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
151    result = BuiltinsSharedArrayBuffer::IsSharedArrayBuffer(ecmaRuntimeCallInfo);
152    TestHelper::TearDownFrame(thread, prev);
153    ASSERT_EQ(result, JSTaggedValue::False());
154
155    // sharedbuffer IsNull
156    JSTaggedValue tagged1 = BuiltTestUtil::CreateBuiltinsSharedArrayBuffer(thread, 0);
157    JSHandle<JSArrayBuffer> arrBuf1(thread,
158                                    JSArrayBuffer::Cast(reinterpret_cast<TaggedObject *>(tagged1.GetRawData())));
159    arrBuf1->SetArrayBufferData(thread, JSTaggedValue::Null());
160    ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
161    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
162    ecmaRuntimeCallInfo->SetThis(arrBuf.GetTaggedValue());
163    ecmaRuntimeCallInfo->SetCallArg(0, arrBuf1.GetTaggedValue());
164
165    prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
166    result = BuiltinsSharedArrayBuffer::IsSharedArrayBuffer(ecmaRuntimeCallInfo);
167    TestHelper::TearDownFrame(thread, prev);
168    ASSERT_EQ(result, JSTaggedValue::False());
169
170    //  ArrayBuffer is not shared
171    JSTaggedValue tagged2 = BuiltTestUtil::CreateBuiltinsSharedArrayBuffer(thread, 0);
172    JSHandle<JSArrayBuffer> arrBuf2(thread,
173                                    JSArrayBuffer::Cast(reinterpret_cast<TaggedObject *>(tagged2.GetRawData())));
174    arrBuf2->SetShared(false);
175    ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
176    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
177    ecmaRuntimeCallInfo->SetThis(arrBuf.GetTaggedValue());
178    ecmaRuntimeCallInfo->SetCallArg(0, arrBuf2.GetTaggedValue());
179
180    prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
181    JSTaggedValue result1 = BuiltinsSharedArrayBuffer::IsSharedArrayBuffer(ecmaRuntimeCallInfo);
182    TestHelper::TearDownFrame(thread, prev);
183    ASSERT_EQ(result1, JSTaggedValue::False());
184}
185
186HWTEST_F_L0(BuiltinsSharedArrayBufferTest, IsShared)
187{
188    // is not SharedBuffer
189    JSHandle<JSArrayBuffer> jsArrayBuffer(thread, CreateJSArrayBuffer(thread));
190    bool result = BuiltinsSharedArrayBuffer::IsShared(jsArrayBuffer.GetTaggedValue());
191    ASSERT_EQ(result, false);
192    // no BufferData
193    JSTaggedValue tagged1 = BuiltTestUtil::CreateBuiltinsSharedArrayBuffer(thread, 0);
194    JSHandle<JSArrayBuffer> arrBuf1(thread,
195                                    JSArrayBuffer::Cast(reinterpret_cast<TaggedObject *>(tagged1.GetRawData())));
196    arrBuf1->SetArrayBufferData(thread, JSTaggedValue::Null());
197    bool result1 = BuiltinsSharedArrayBuffer::IsShared(arrBuf1.GetTaggedValue());
198    ASSERT_EQ(result1, false);
199}
200}  // namespace panda::test
201