1 /*
2 * Copyright (c) 2025 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 "common_components/heap/collector/finalizer_processor.h"
17 #include "common_components/heap/collector/collector_proxy.h"
18 #include "common_components/heap/heap_manager.h"
19 #include "common_components/tests/test_helper.h"
20
21 using namespace common;
22
23 namespace common::test {
24 const uint32_t TWO_SECONDS = 2;
25 const uint32_t HUNDRED_MILLISECONDS = 100;
26 constexpr uint64_t TAG_BOOLEAN = 0x04ULL;
27
28 class FinalizerProcessorTest : public common::test::BaseTestWithScope {
29 protected:
SetUpTestCase()30 static void SetUpTestCase()
31 {
32 BaseRuntime::GetInstance()->Init();
33 }
34
TearDownTestCase()35 static void TearDownTestCase() {}
36
SetUp()37 void SetUp() override
38 {
39 MutatorManager::Instance().CreateRuntimeMutator(ThreadType::ARK_PROCESSOR);
40 }
41
TearDown()42 void TearDown() override
43 {
44 MutatorManager::Instance().DestroyRuntimeMutator(ThreadType::ARK_PROCESSOR);
45 }
46 };
47
HWTEST_F_L0(FinalizerProcessorTest,RegisterFinalizer_TEST1)48 HWTEST_F_L0(FinalizerProcessorTest, RegisterFinalizer_TEST1)
49 {
50 FinalizerProcessor finalizerProcessor;
51 HeapAddress addr = common::HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
52 BaseObject *obj = reinterpret_cast<BaseObject*>(addr | TAG_BOOLEAN);
53 new (obj) BaseObject(); // Construct BaseObject
54 finalizerProcessor.RegisterFinalizer(obj);
55 bool flag = common::RegionSpace::IsMarkedObject(obj);
56 EXPECT_FALSE(flag);
57 }
58
HWTEST_F_L0(FinalizerProcessorTest,EnqueueFinalizables_TEST1)59 HWTEST_F_L0(FinalizerProcessorTest, EnqueueFinalizables_TEST1)
60 {
61 FinalizerProcessor finalizerProcessor;
62 HeapAddress addr = common::HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
63 BaseObject *obj = reinterpret_cast<BaseObject*>(addr | TAG_BOOLEAN);
64 new (obj) BaseObject(); // Construct BaseObject
65 finalizerProcessor.RegisterFinalizer(obj);
66 std::function<bool(BaseObject*)> finalizable = [](BaseObject* obj) {
67 return !common::RegionSpace::IsMarkedObject(obj);
68 };
69 finalizerProcessor.EnqueueFinalizables(finalizable, 1);
70 bool flag = finalizable(obj);
71 EXPECT_TRUE(flag);
72 }
73
HWTEST_F_L0(FinalizerProcessorTest,EnqueueFinalizables_TEST2)74 HWTEST_F_L0(FinalizerProcessorTest, EnqueueFinalizables_TEST2)
75 {
76 FinalizerProcessor finalizerProcessor;
77 HeapAddress addr = common::HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
78 BaseObject *obj = reinterpret_cast<BaseObject*>(addr | TAG_BOOLEAN);
79 new (obj) BaseObject();
80 finalizerProcessor.RegisterFinalizer(obj);
81 RootVisitor visitor = [](ObjectRef&) {
82 return;
83 };
84 std::function<bool(BaseObject*)> finalizable = [this](BaseObject* obj) {
85 return common::RegionSpace::IsMarkedObject(obj);
86 };
87 auto before = finalizerProcessor.VisitFinalizers(visitor);
88 finalizerProcessor.EnqueueFinalizables(finalizable, 1);
89 auto after = finalizerProcessor.VisitFinalizers(visitor);
90 bool flag = finalizable(obj);
91 EXPECT_FALSE(flag);
92 EXPECT_EQ(before, after);
93 }
94
HWTEST_F_L0(FinalizerProcessorTest,EnqueueFinalizables_TEST3)95 HWTEST_F_L0(FinalizerProcessorTest, EnqueueFinalizables_TEST3)
96 {
97 FinalizerProcessor finalizerProcessor;
98 RootVisitor visitor = [](ObjectRef&) {
99 return;
100 };
101 std::function<bool(BaseObject*)> finalizable = [this](BaseObject* obj) {
102 return common::RegionSpace::IsMarkedObject(obj);
103 };
104 auto num1 = finalizerProcessor.VisitFinalizers(visitor);
105 finalizerProcessor.EnqueueFinalizables(finalizable, 0);
106 EXPECT_EQ(num1, 0);
107 auto num2 = finalizerProcessor.VisitFinalizers(visitor);
108 finalizerProcessor.EnqueueFinalizables(finalizable, 1);
109 EXPECT_EQ(num2, 0);
110 HeapAddress addr = common::HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
111 BaseObject *obj = reinterpret_cast<BaseObject*>(addr | TAG_BOOLEAN);
112 new (obj) BaseObject();
113 finalizerProcessor.RegisterFinalizer(obj);
114 auto num3 = finalizerProcessor.VisitFinalizers(visitor);
115 finalizerProcessor.EnqueueFinalizables(finalizable, 0);
116 bool flag = finalizable(obj);
117 EXPECT_NE(num3, 0);
118 EXPECT_FALSE(flag);
119 }
120
HWTEST_F_L0(FinalizerProcessorTest,Run_TEST1)121 HWTEST_F_L0(FinalizerProcessorTest, Run_TEST1)
122 {
123 FinalizerProcessor finalizerProcessor;
124 HeapAddress addr = common::HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
125 BaseObject *obj = reinterpret_cast<BaseObject*>(addr | TAG_BOOLEAN);
126 new (obj) BaseObject();
127 AllocationBuffer* buffer = new (std::nothrow) AllocationBuffer();
128 RegionDesc* region = RegionDesc::GetRegionDescAt(addr);
129 buffer->SetPreparedRegion(region);
130 Heap::GetHeap().GetAllocator().AddHungryBuffer(*buffer);
131 finalizerProcessor.RegisterFinalizer(obj);
132 finalizerProcessor.Start();
133 std::thread notifier([&]() {
134 std::this_thread::sleep_for(std::chrono::milliseconds(HUNDRED_MILLISECONDS));
135 finalizerProcessor.NotifyToFeedAllocBuffers();
136 std::this_thread::sleep_for(std::chrono::milliseconds(HUNDRED_MILLISECONDS));
137 finalizerProcessor.NotifyToReclaimGarbage();
138 });
139 notifier.join();
140 std::this_thread::sleep_for(std::chrono::seconds(TWO_SECONDS));
141 finalizerProcessor.Stop();
142 EXPECT_NE(buffer->GetPreparedRegion(), nullptr);
143 delete buffer;
144 }
145 } // namespace common::test
146