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/ecma_test_common.h"
22
23using namespace panda::ecmascript;
24
25namespace panda::test {
26class WeakRefOldGCTest : public BaseTestWithScope<false> {
27};
28
29static JSObject *JSObjectTestCreate(JSThread *thread)
30{
31    [[maybe_unused]] ecmascript::EcmaHandleScope scope(thread);
32    EcmaVM *ecmaVM = thread->GetEcmaVM();
33    auto globalEnv = ecmaVM->GetGlobalEnv();
34    JSFunction *jsFunc = globalEnv->GetObjectFunction().GetObject<JSFunction>();
35    JSHandle<JSTaggedValue> jsFunc1(thread, jsFunc);
36    JSHandle<JSObject> newObj =
37        ecmaVM->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(jsFunc1), jsFunc1);
38    return *newObj;
39}
40
41static TaggedArray *ArrayTestCreate(JSThread *thread)
42{
43    [[maybe_unused]] ecmascript::EcmaHandleScope scope(thread);
44    // 2 : test case
45    JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(2);
46    return *array;
47}
48
49HWTEST_F_L0(WeakRefOldGCTest, ArrayNonMovable)
50{
51    auto vm = thread->GetEcmaVM();
52    auto array = vm->GetFactory()->NewTaggedArray(2, JSTaggedValue::Undefined(), true);
53    JSHandle<JSObject> newObj1(thread, JSObjectTestCreate(thread));
54    array->Set(thread, 0, newObj1.GetTaggedValue());
55
56    JSObject *newObj2 = JSObjectTestCreate(thread);
57    JSTaggedValue value(newObj2);
58    value.CreateWeakRef();
59    array->Set(thread, 1, value);
60    EXPECT_EQ(newObj1.GetTaggedValue(), array->Get(0));
61    EXPECT_EQ(value, array->Get(1));
62    vm->CollectGarbage(TriggerGCType::OLD_GC);
63    EXPECT_EQ(newObj1.GetTaggedValue(), array->Get(0));
64    EXPECT_EQ(JSTaggedValue::Undefined(), array->Get(1));
65}
66
67HWTEST_F_L0(WeakRefOldGCTest, ArrayUndefined)
68{
69    EcmaTestCommon::ArrayUndefinedGcCommon(thread, TriggerGCType::OLD_GC);
70}
71
72HWTEST_F_L0(WeakRefOldGCTest, ArrayKeep)
73{
74    EcmaTestCommon::ArrayKeepGcCommon(thread, TriggerGCType::OLD_GC);
75}
76
77HWTEST_F_L0(WeakRefOldGCTest, ObjectUndefined)
78{
79    JSHandle<JSObject> newObj1(thread, JSObjectTestCreate(thread));
80    JSTaggedValue array(ArrayTestCreate(thread));
81    array.CreateWeakRef();
82    newObj1->SetElements(thread, array);
83    EXPECT_EQ(newObj1->GetElements(), array);
84    thread->GetEcmaVM()->CollectGarbage(TriggerGCType::OLD_GC);
85    EXPECT_EQ(newObj1->GetElements(), JSTaggedValue::Undefined());
86}
87
88HWTEST_F_L0(WeakRefOldGCTest, ObjectKeep)
89{
90    JSHandle<JSObject> newObj1(thread, JSObjectTestCreate(thread));
91    JSHandle<TaggedArray> array(thread, ArrayTestCreate(thread));
92    JSTaggedValue value = array.GetTaggedValue();
93    value.CreateWeakRef();
94    newObj1->SetElements(thread, value);
95    EXPECT_EQ(newObj1->GetElements(), value);
96    thread->GetEcmaVM()->CollectGarbage(TriggerGCType::OLD_GC);
97    value = array.GetTaggedValue();
98    value.CreateWeakRef();
99    EXPECT_EQ(newObj1->GetElements(), value);
100}
101}  // namespace panda::test
102