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 "ecmascript/weak_vector.h"
17#include "ecmascript/global_env.h"
18#include "ecmascript/tests/test_helper.h"
19
20using namespace panda;
21using namespace panda::ecmascript;
22
23namespace panda::test {
24class WeakVectorTest : public BaseTestWithScope<false> {
25};
26
27/**
28 * @tc.name: Create
29 * @tc.desc: Check whether the returned value through "Create" function is within expectations by "GetEnd"
30 *           function and "Empty" function. convert to tagedarray, and check whether the length attribute
31 *           meets the expectation.
32 * @tc.type: FUNC
33 * @tc.require:
34 */
35HWTEST_F_L0(WeakVectorTest, Create)
36{
37    uint32_t weakVectorCapacity = 100;
38    JSHandle<WeakVector> weakVector = WeakVector::Create(thread, weakVectorCapacity);
39    EXPECT_TRUE(*weakVector != nullptr);
40    JSHandle<TaggedArray> weakVectArr(weakVector);
41    EXPECT_EQ(weakVector->GetEnd(), 0U);
42    EXPECT_TRUE(weakVector->Empty());
43    EXPECT_EQ(weakVectArr->GetLength(), weakVectorCapacity + 1);
44}
45
46/**
47 * @tc.name: SetAndGet
48 * @tc.desc: Check whether each value in the vector container is the same as the value of set by "set" function.
49 * @tc.type: FUNC
50 * @tc.require:
51 */
52HWTEST_F_L0(WeakVectorTest, SetAndGet)
53{
54    uint32_t weakVectorCapacity = 100;
55    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
56    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
57    JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
58    JSHandle<WeakVector> weakVector = WeakVector::Create(thread, weakVectorCapacity);
59
60    JSHandle<JSObject> weakObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
61    JSHandle<JSTaggedValue> weakObjclassVal(thread, weakObj->GetJSHClass());
62    JSTaggedValue weakValue = JSTaggedValue(weakObjclassVal.GetTaggedValue().CreateAndGetWeakRef());
63    // set weak value
64    for (uint32_t i = 0; i < weakVectorCapacity; i++) {
65        weakVector->Set(thread, i, weakValue);
66        EXPECT_EQ(weakVector->Get(i), weakValue);
67    }
68}
69
70/**
71 * @tc.name: Grow
72 * @tc.desc: Create a weak vector with a certain length through the "Create" function, and then expand the weak vector
73 *           with the "Grow" function to increase its length.
74 * @tc.type: FUNC
75 * @tc.require:
76 */
77HWTEST_F_L0(WeakVectorTest, Grow)
78{
79    thread->GetEcmaVM()->SetEnableForceGC(false); // turn off gc
80    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
81    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
82    JSHandle<JSTaggedValue> objFun = env->GetStringFunction();
83
84    JSHandle<JSObject> weakObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
85    JSHandle<JSTaggedValue> weakObjclassVal(thread, weakObj->GetJSHClass());
86    JSTaggedValue weakValue = JSTaggedValue(weakObjclassVal.GetTaggedValue().CreateAndGetWeakRef());
87    // test growing vector with null value
88    uint32_t oldWeakVectorCapacity = 0;
89    uint32_t newWeakVectorCapacity = 100;
90    JSHandle<WeakVector> oldWeakVector = WeakVector::Create(thread, oldWeakVectorCapacity);
91    JSHandle<WeakVector> newWeakVector = oldWeakVector->Grow(thread, oldWeakVector, newWeakVectorCapacity);
92    EXPECT_EQ(newWeakVector->GetCapacity(), newWeakVectorCapacity);
93    EXPECT_TRUE(newWeakVector->Empty());
94    // test growing vector with no null value
95    oldWeakVectorCapacity = 100;
96    newWeakVectorCapacity = 200;
97    for (uint32_t i = 0; i < oldWeakVectorCapacity; i++) {
98        newWeakVector->Set(thread, i, weakValue);
99    }
100    newWeakVector = newWeakVector->Grow(thread, newWeakVector, newWeakVectorCapacity);
101    EXPECT_EQ(newWeakVector->GetCapacity(), newWeakVectorCapacity);
102    for (uint32_t i = 0; i < oldWeakVectorCapacity; i++) {
103        EXPECT_EQ(newWeakVector->Get(i), weakValue);
104    }
105    EXPECT_EQ(newWeakVector->GetEnd(), 0U);
106    thread->GetEcmaVM()->SetEnableForceGC(true);  // turn on gc
107}
108
109/**
110 * @tc.name: PushBack
111 * @tc.desc: Change the value in the weak vector through "pushback" function,and compare whether the original value of
112 *           the weak vector and the pushback value are the same in the pushback position.
113 * @tc.type: FUNC
114 * @tc.require:
115 */
116HWTEST_F_L0(WeakVectorTest, PushBack)
117{
118    uint32_t weakVectorCapacity = 100;
119    uint32_t pushWeakVectorCapacity = weakVectorCapacity >> 2;  // 2: means half value
120    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
121    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
122    JSHandle<JSTaggedValue> objFun = env->GetPromiseFunction();
123    JSHandle<WeakVector> weakVector = WeakVector::Create(thread, weakVectorCapacity);
124
125    JSHandle<JSObject> weakObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
126    JSHandle<JSTaggedValue> weakObjclassVal(thread, weakObj->GetJSHClass());
127    JSTaggedValue weakValue = JSTaggedValue(weakObjclassVal.GetTaggedValue().CreateAndGetWeakRef());
128    // fill the value into the vector
129    for (uint32_t i = 0; i < weakVectorCapacity; i++) {
130        weakVector->Set(thread, i, weakValue);
131    }
132    // push the value into the vector and reset end
133    for (uint32_t i = 0; i < pushWeakVectorCapacity; i++) {
134        weakVector->PushBack(thread, JSTaggedValue::Hole());
135    }
136    EXPECT_EQ(weakVector->GetEnd(), pushWeakVectorCapacity);
137
138    for (uint32_t i = 0; i < pushWeakVectorCapacity; i++) {
139        EXPECT_TRUE(weakVector->Get(i).IsHole());
140    }
141    for (uint32_t i = pushWeakVectorCapacity; i < weakVectorCapacity; i++) {
142        EXPECT_EQ(weakVector->Get(i), weakValue);
143    }
144}
145
146/**
147 * @tc.name: Delete
148 * @tc.desc: Check whether the value in the vector container is hole when deleted, and whether the container
149 *           is not empty when all are deleted by "delete" function.
150 * @tc.type: FUNC
151 * @tc.require:
152 */
153HWTEST_F_L0(WeakVectorTest, Delete)
154{
155    uint32_t weakVectorCapacity = 100;
156    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
157    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
158    JSHandle<JSTaggedValue> objFun = env->GetPromiseFunction();
159    JSHandle<WeakVector> weakVector = WeakVector::Create(thread, weakVectorCapacity);
160
161    JSHandle<JSObject> weakObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
162    JSHandle<JSTaggedValue> weakObjclassVal(thread, weakObj->GetJSHClass());
163    JSTaggedValue weakValue = JSTaggedValue(weakObjclassVal.GetTaggedValue().CreateAndGetWeakRef());
164
165    for (uint32_t i = 0; i < weakVectorCapacity; i++) {
166        weakVector->PushBack(thread, weakValue);
167    }
168    EXPECT_TRUE(weakVector->Full());
169    EXPECT_FALSE(weakVector->Delete(thread, weakVectorCapacity));
170
171    for (uint32_t i = 0; i < weakVectorCapacity; i++) {
172        EXPECT_TRUE(weakVector->Delete(thread, i));
173        EXPECT_TRUE(weakVector->Get(i).IsHole());
174    }
175    EXPECT_FALSE(weakVector->Empty());
176    EXPECT_EQ(weakVector->GetCapacity(), weakVectorCapacity);
177}
178}  // namespace panda::test