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/ecma_vm.h"
17 #include "ecmascript/global_env.h"
18 #include "ecmascript/js_handle.h"
19 #include "ecmascript/object_factory.h"
20 #include "ecmascript/tagged_array-inl.h"
21 #include "ecmascript/tests/test_helper.h"
22
23 using namespace panda::ecmascript;
24
25 namespace panda::test {
26 class WeakRefOldGCTest : public testing::Test {
27 public:
SetUpTestCase()28 static void SetUpTestCase()
29 {
30 GTEST_LOG_(INFO) << "SetUpTestCase";
31 }
32
TearDownTestCase()33 static void TearDownTestCase()
34 {
35 GTEST_LOG_(INFO) << "TearDownCase";
36 }
37
SetUp()38 void SetUp() override
39 {
40 TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
41 }
42
TearDown()43 void TearDown() override
44 {
45 TestHelper::DestroyEcmaVMWithScope(instance, scope);
46 }
47
48 EcmaVM *instance {nullptr};
49 EcmaHandleScope *scope {nullptr};
50 JSThread *thread {nullptr};
51 };
52
JSObjectTestCreate(JSThread * thread)53 static JSObject *JSObjectTestCreate(JSThread *thread)
54 {
55 [[maybe_unused]] ecmascript::EcmaHandleScope scope(thread);
56 EcmaVM *ecmaVM = thread->GetEcmaVM();
57 auto globalEnv = ecmaVM->GetGlobalEnv();
58 JSFunction *jsFunc = globalEnv->GetObjectFunction().GetObject<JSFunction>();
59 JSHandle<JSTaggedValue> jsFunc1(thread, jsFunc);
60 JSHandle<JSObject> newObj =
61 ecmaVM->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(jsFunc1), jsFunc1);
62 return *newObj;
63 }
64
ArrayTestCreate(JSThread * thread)65 static TaggedArray *ArrayTestCreate(JSThread *thread)
66 {
67 [[maybe_unused]] ecmascript::EcmaHandleScope scope(thread);
68 // 2 : test case
69 JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(2);
70 return *array;
71 }
72
HWTEST_F_L0(WeakRefOldGCTest,ArrayNonMovable)73 HWTEST_F_L0(WeakRefOldGCTest, ArrayNonMovable)
74 {
75 auto vm = thread->GetEcmaVM();
76 auto array = vm->GetFactory()->NewTaggedArray(2, JSTaggedValue::Undefined(), true);
77 JSHandle<JSObject> newObj1(thread, JSObjectTestCreate(thread));
78 array->Set(thread, 0, newObj1.GetTaggedValue());
79
80 JSObject *newObj2 = JSObjectTestCreate(thread);
81 JSTaggedValue value(newObj2);
82 value.CreateWeakRef();
83 array->Set(thread, 1, value);
84 EXPECT_EQ(newObj1.GetTaggedValue(), array->Get(0));
85 EXPECT_EQ(value, array->Get(1));
86 vm->CollectGarbage(TriggerGCType::OLD_GC);
87 EXPECT_EQ(newObj1.GetTaggedValue(), array->Get(0));
88 EXPECT_EQ(JSTaggedValue::Undefined(), array->Get(1));
89 }
90
HWTEST_F_L0(WeakRefOldGCTest,ArrayUndefined)91 HWTEST_F_L0(WeakRefOldGCTest, ArrayUndefined)
92 {
93 EcmaVM *ecmaVM = thread->GetEcmaVM();
94 JSHandle<TaggedArray> array = ecmaVM->GetFactory()->NewTaggedArray(2);
95 EXPECT_TRUE(*array != nullptr);
96 JSHandle<JSObject> newObj1(thread, JSObjectTestCreate(thread));
97 array->Set(thread, 0, newObj1.GetTaggedValue());
98
99 JSObject *newObj2 = JSObjectTestCreate(thread);
100 JSTaggedValue value(newObj2);
101 value.CreateWeakRef();
102 array->Set(thread, 1, value);
103 EXPECT_EQ(newObj1.GetTaggedValue(), array->Get(0));
104 EXPECT_EQ(value, array->Get(1));
105 ecmaVM->CollectGarbage(TriggerGCType::OLD_GC);
106 EXPECT_EQ(newObj1.GetTaggedValue(), array->Get(0));
107 EXPECT_EQ(JSTaggedValue::Undefined(), array->Get(1));
108 }
109
HWTEST_F_L0(WeakRefOldGCTest,ArrayKeep)110 HWTEST_F_L0(WeakRefOldGCTest, ArrayKeep)
111 {
112 EcmaVM *ecmaVM = thread->GetEcmaVM();
113 JSHandle<TaggedArray> array = ecmaVM->GetFactory()->NewTaggedArray(2);
114 EXPECT_TRUE(*array != nullptr);
115 JSHandle<JSObject> newObj1(thread, JSObjectTestCreate(thread));
116 array->Set(thread, 0, newObj1.GetTaggedValue());
117
118 JSHandle<JSObject> newObj2(thread, JSObjectTestCreate(thread));
119 JSTaggedValue value(newObj2.GetTaggedValue());
120 value.CreateWeakRef();
121 array->Set(thread, 1, value);
122 EXPECT_EQ(newObj1.GetTaggedValue(), array->Get(0));
123 EXPECT_EQ(value, array->Get(1));
124 ecmaVM->CollectGarbage(TriggerGCType::OLD_GC);
125 EXPECT_EQ(newObj1.GetTaggedValue(), array->Get(0));
126 EXPECT_EQ(true, array->Get(1).IsWeak());
127 value = newObj2.GetTaggedValue();
128 value.CreateWeakRef();
129 EXPECT_EQ(value, array->Get(1));
130 }
131
HWTEST_F_L0(WeakRefOldGCTest,ObjectUndefined)132 HWTEST_F_L0(WeakRefOldGCTest, ObjectUndefined)
133 {
134 JSHandle<JSObject> newObj1(thread, JSObjectTestCreate(thread));
135 JSTaggedValue array(ArrayTestCreate(thread));
136 array.CreateWeakRef();
137 newObj1->SetElements(thread, array);
138 EXPECT_EQ(newObj1->GetElements(), array);
139 thread->GetEcmaVM()->CollectGarbage(TriggerGCType::OLD_GC);
140 EXPECT_EQ(newObj1->GetElements(), JSTaggedValue::Undefined());
141 }
142
HWTEST_F_L0(WeakRefOldGCTest,ObjectKeep)143 HWTEST_F_L0(WeakRefOldGCTest, ObjectKeep)
144 {
145 JSHandle<JSObject> newObj1(thread, JSObjectTestCreate(thread));
146 JSHandle<TaggedArray> array(thread, ArrayTestCreate(thread));
147 JSTaggedValue value = array.GetTaggedValue();
148 value.CreateWeakRef();
149 newObj1->SetElements(thread, value);
150 EXPECT_EQ(newObj1->GetElements(), value);
151 thread->GetEcmaVM()->CollectGarbage(TriggerGCType::OLD_GC);
152 value = array.GetTaggedValue();
153 value.CreateWeakRef();
154 EXPECT_EQ(newObj1->GetElements(), value);
155 }
156 } // namespace panda::test
157