1/*
2 * Copyright (c) 2021 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 "ecmascript/ic/proto_change_details.h"
17#include "ecmascript/global_env.h"
18#include "ecmascript/tagged_array.h"
19#include "ecmascript/tests/test_helper.h"
20#include "ecmascript/weak_vector.h"
21
22using namespace panda::ecmascript;
23
24namespace panda::test {
25class ProtoChangeDetailsTest : public testing::Test {
26public:
27    static void SetUpTestCase()
28    {
29        GTEST_LOG_(INFO) << "SetUpTestCase";
30    }
31
32    static void TearDownTestCase()
33    {
34        GTEST_LOG_(INFO) << "TearDownCase";
35    }
36
37    void SetUp() override
38    {
39        TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
40    }
41
42    void TearDown() override
43    {
44        TestHelper::DestroyEcmaVMWithScope(instance, scope);
45    }
46
47    EcmaVM *instance {nullptr};
48    EcmaHandleScope *scope {nullptr};
49    JSThread *thread {nullptr};
50};
51
52/**
53 * @tc.name: SetBitField
54 * @tc.desc: Check whether the result returned through "GetBitField" function is within expectations.
55 * @tc.type: FUNC
56 * @tc.require:
57 */
58HWTEST_F_L0(ProtoChangeDetailsTest, SetBitField)
59{
60    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
61    JSHandle<ProtoChangeMarker> handleProtoChangeMarker = factory->NewProtoChangeMarker();
62
63    handleProtoChangeMarker->SetBitField(true);
64    EXPECT_TRUE(handleProtoChangeMarker->GetBitField());
65
66    handleProtoChangeMarker->SetBitField(false);
67    EXPECT_FALSE(handleProtoChangeMarker->GetBitField());
68}
69
70/**
71 * @tc.name: SetHasChanged
72 * @tc.desc: Check whether the result returned through "GetHasChanged" function is within expectations.
73 * @tc.type: FUNC
74 * @tc.require:
75 */
76HWTEST_F_L0(ProtoChangeDetailsTest, SetHasChanged)
77{
78    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
79    JSHandle<ProtoChangeMarker> handleProtoChangeMarker = factory->NewProtoChangeMarker();
80
81    handleProtoChangeMarker->SetHasChanged(true);
82    EXPECT_TRUE(handleProtoChangeMarker->GetHasChanged());
83
84    handleProtoChangeMarker->SetHasChanged(false);
85    EXPECT_FALSE(handleProtoChangeMarker->GetHasChanged());
86}
87
88/**
89 * @tc.name: SetChangeListener
90 * @tc.desc: Check whether the result returned through "GetChangeListener" function is within expectations.
91 * @tc.type: FUNC
92 * @tc.require:
93 */
94HWTEST_F_L0(ProtoChangeDetailsTest, SetChangeListener)
95{
96    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
97    JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue(1));
98
99    uint32_t weakVectorCapacity = 100;
100    JSHandle<WeakVector> weakVector = WeakVector::Create(thread, weakVectorCapacity);
101    JSHandle<ChangeListener> handleChangeListener = JSHandle<ChangeListener>::Cast(weakVector);
102    JSHandle<ProtoChangeDetails> handleChangeDetails = factory->NewProtoChangeDetails();
103
104    handleChangeDetails->SetChangeListener(thread, handleValue.GetTaggedValue());
105    EXPECT_EQ(handleChangeDetails->GetChangeListener().GetInt(), 1);
106    handleChangeDetails->SetChangeListener(thread, handleChangeListener.GetTaggedValue());
107    EXPECT_EQ(handleChangeDetails->GetChangeListener(), handleChangeListener.GetTaggedValue());
108}
109
110/**
111 * @tc.name: SetRegisterIndex
112 * @tc.desc: Check whether the result returned through "GetRegisterIndex" function is within expectations.
113 * @tc.type: FUNC
114 * @tc.require:
115 */
116HWTEST_F_L0(ProtoChangeDetailsTest, SetRegisterIndex)
117{
118    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
119    JSHandle<ProtoChangeDetails> handleChangeDetails = factory->NewProtoChangeDetails();
120
121    handleChangeDetails->SetRegisterIndex(static_cast<uint32_t>(1));
122    EXPECT_EQ(handleChangeDetails->GetRegisterIndex(), 1U);
123}
124
125/**
126 * @tc.name: Add_001
127 * @tc.desc: Create a weakvector object with a length of ten,Call the "pushback" function to set the value of the
128 *           vector.the vector is not fully set,convert the weakvector object into a ChangeListener object.In this case,
129 *           call the "add" function to add a jshclass object. The added jshclass object will create and get weakref and
130 *           return the location of the added object.
131 * @tc.type: FUNC
132 * @tc.require:
133 */
134HWTEST_F_L0(ProtoChangeDetailsTest, Add_001)
135{
136    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
137    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
138    JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
139    JSHandle<JSObject> handleObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
140    JSHandle<JSTaggedValue> objClassVal(thread, handleObj->GetJSHClass());
141    uint32_t weakVectorCapacity = 10;
142    uint32_t index = 2;
143    JSHandle<WeakVector> weakVector = WeakVector::Create(thread, weakVectorCapacity);
144    for (int i = 0; i < 9; i++) {
145        weakVector->PushBack(thread, JSTaggedValue(i));
146    } // weakVector is not full
147    JSHandle<ChangeListener> handleChangeListenerArr = JSHandle<ChangeListener>::Cast(weakVector);
148    JSHandle<ChangeListener> resultListenerArray =
149        ChangeListener::Add(thread, handleChangeListenerArr, JSHandle<JSHClass>(objClassVal), &index);
150    EXPECT_EQ(index, 9U);
151    JSTaggedValue weakRefValue(objClassVal.GetTaggedValue());
152    weakRefValue.CreateWeakRef();
153    EXPECT_EQ(resultListenerArray->Get(index).GetTaggedObject(), weakRefValue.GetTaggedWeakRef());
154}
155
156/**
157 * @tc.name: Add_002
158 * @tc.desc: Create a weakvector object with a length of ten,Call the "pushback" function to set the value of the
159 *           vector the vector is fully set but exist hole,convert the weakvector object into a ChangeListener object
160 *           in this case call the "add" function to add a jshclass object. The added jshclass object will create and
161 *           get weakref and return the location of the added object.
162 * @tc.type: FUNC
163 * @tc.require:
164 */
165HWTEST_F_L0(ProtoChangeDetailsTest, Add_002)
166{
167    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
168    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
169    JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
170    JSHandle<JSObject> handleObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
171    JSHandle<JSTaggedValue> objClassVal(thread, handleObj->GetJSHClass());
172    uint32_t weakVectorCapacity = 10;
173    uint32_t index = 2;
174    JSHandle<WeakVector> weakVector = WeakVector::Create(thread, weakVectorCapacity);
175    for (int i = 0; i < 10; i++) {
176        weakVector->PushBack(thread, JSTaggedValue(i));
177    }
178    JSHandle<ChangeListener> handleChangeListenerArr = JSHandle<ChangeListener>::Cast(weakVector);
179    // weakVector exist hole
180    weakVector->Delete(thread, 1); // delete in one
181    JSHandle<ChangeListener> resultListenerArray =
182    ChangeListener::Add(thread, handleChangeListenerArr, JSHandle<JSHClass>(objClassVal), &index);
183    EXPECT_EQ(index, 1U);
184    JSTaggedValue weakRefValue(objClassVal.GetTaggedValue());
185    weakRefValue.CreateWeakRef();
186    EXPECT_EQ(resultListenerArray->Get(index).GetTaggedObject(), weakRefValue.GetTaggedWeakRef());
187}
188
189/**
190 * @tc.name: Add_003
191 * @tc.desc: Create a weakvector object with a length of ten,Call the "pushback" function to set the value of the
192 *           vector the vector is fully set and not exist hole,convert the weakvector object into a ChangeListener
193 *           object.in this case call the "add" function increase the length to add the jshclass object. The added
194 *           jshclass object will create and get weakref and return the location of the added object.
195 * @tc.type: FUNC
196 * @tc.require:
197 */
198HWTEST_F_L0(ProtoChangeDetailsTest, Add_003)
199{
200    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
201    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
202    JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
203    JSHandle<JSObject> handleObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
204    JSHandle<JSTaggedValue> objClassVal(thread, handleObj->GetJSHClass());
205    uint32_t weakVectorCapacity = 10;
206    uint32_t index = 2;
207    JSHandle<WeakVector> weakVector = WeakVector::Create(thread, weakVectorCapacity);
208    for (int i = 0; i < 10; i++) {
209        weakVector->PushBack(thread, JSTaggedValue(i));
210    }
211    JSHandle<ChangeListener> handleChangeListenerArr = JSHandle<ChangeListener>::Cast(weakVector);
212    // weakVector is full and no hole exists.
213    JSHandle<ChangeListener> resultListenerArray =
214    ChangeListener::Add(thread, handleChangeListenerArr, JSHandle<JSHClass>(objClassVal), &index);
215    EXPECT_EQ(index, 10U);
216    JSTaggedValue weakRefValue(objClassVal.GetTaggedValue());
217    weakRefValue.CreateWeakRef();
218    EXPECT_EQ(resultListenerArray->Get(index).GetTaggedObject(), weakRefValue.GetTaggedWeakRef());
219}
220
221/**
222 * @tc.name: CheckHole
223 * @tc.desc: Create a weakvector object with a length of ten,Call the "pushback" function to set the value of the
224 *           vector the vector is fully set,convert the weakvector object into a ChangeListener object.ChangeListener
225 *           object call the "CheckHole" function to check whether there is a hole. If there is, return the location
226 *           of the hole If not, return the maximum value.
227 * @tc.type: FUNC
228 * @tc.require:
229 */
230HWTEST_F_L0(ProtoChangeDetailsTest, CheckHole)
231{
232    uint32_t weakVectorCapacity = 10;
233    JSHandle<WeakVector> weakVector = WeakVector::Create(thread, weakVectorCapacity);
234    for (int i = 0; i < 10; i++) {
235        weakVector->PushBack(thread, JSTaggedValue(i)); // Set Value and End
236    }
237    JSHandle<ChangeListener> handleChangeListenerArr = JSHandle<ChangeListener>::Cast(weakVector);
238    EXPECT_EQ(ChangeListener::CheckHole(handleChangeListenerArr), TaggedArray::MAX_ARRAY_INDEX);
239    weakVector->Delete(thread, 1);
240    EXPECT_EQ(ChangeListener::CheckHole(handleChangeListenerArr), 1U);
241}
242
243/**
244 * @tc.name: Get
245 * @tc.desc: Create a weakvector object with a length of three,Call the "pushback" function to set the value of the
246 *           vector the vector is fully set,convert the weakvector object into a ChangeListener object.check whether
247 *           the return value of calling "Get" function is the same as the value set by calling the "Set" function.
248 * @tc.type: FUNC
249 * @tc.require:
250 */
251HWTEST_F_L0(ProtoChangeDetailsTest, Get)
252{
253    uint32_t weakVectorCapacity = 3;
254    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
255    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
256    JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
257    JSHandle<JSTaggedValue> handleObj(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
258    JSHandle<WeakVector> weakVector = WeakVector::Create(thread, weakVectorCapacity);
259    // create weakref
260    JSTaggedValue objValue(handleObj.GetTaggedValue());
261    objValue.CreateWeakRef();
262    // set value for vector
263    weakVector->Set(thread, 0, JSTaggedValue(0));
264    weakVector->Set(thread, 1, objValue);
265    weakVector->Set(thread, 2, JSTaggedValue::Undefined());
266    JSHandle<ChangeListener> handleChangeListenerArr = JSHandle<ChangeListener>::Cast(weakVector);
267    EXPECT_TRUE(*handleChangeListenerArr != nullptr);
268    EXPECT_EQ(handleChangeListenerArr->Get(0).GetInt(), 0);
269    // the value is the weakRef of objValue
270    EXPECT_EQ(handleChangeListenerArr->Get(1).GetTaggedObject(), objValue.GetTaggedWeakRef());
271    EXPECT_TRUE(handleChangeListenerArr->Get(2).IsUndefined());
272}
273} // namespace panda::test
274