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/ark_collector/ark_collector.h"
17 #include "common_components/heap/verification.cpp"
18 #include "common_components/heap/heap_manager.h"
19 #include "common_components/tests/test_helper.h"
20 #include "common_interfaces/objects/base_object_operator.h"
21
22 using namespace common;
23 namespace common::test {
24 class TestBaseObjectOperator : public common::BaseObjectOperatorInterfaces {
25 public:
IsValidObject(const BaseObject * object) const26 bool IsValidObject([[maybe_unused]] const BaseObject *object) const override { return enbaleValidObject_; }
ForEachRefField(const BaseObject * object,const common::RefFieldVisitor & visitor) const27 void ForEachRefField(const BaseObject *object, const common::RefFieldVisitor &visitor) const override {}
GetSize(const BaseObject * object) const28 size_t GetSize(const BaseObject *object) const override{ return size_; }
GetForwardingPointer(const BaseObject * object) const29 BaseObject *GetForwardingPointer(const BaseObject *object) const override { return nullptr; }
SetForwardingPointerAfterExclusive(BaseObject * object,BaseObject * fwdPtr)30 void SetForwardingPointerAfterExclusive(BaseObject *object, BaseObject *fwdPtr) override {}
SetValidObject(bool value)31 void SetValidObject(bool value) { enbaleValidObject_ = value; }
SetSize(size_t size)32 void SetSize(size_t size) { size_ = size; }
33 private:
34 bool enbaleValidObject_ = false;
35 size_t size_ = 0;
36 };
37 class VerificationTest : public common::test::BaseTestWithScope {
38 protected:
SetUpTestCase()39 static void SetUpTestCase()
40 {
41 BaseRuntime::GetInstance()->Init();
42 }
43
TearDownTestCase()44 static void TearDownTestCase()
45 {
46 BaseRuntime::GetInstance()->Fini();
47 }
48
SetUp()49 void SetUp() override
50 {
51 MutatorManager::Instance().CreateRuntimeMutator(ThreadType::GC_THREAD);
52 }
53
TearDown()54 void TearDown() override
55 {
56 MutatorManager::Instance().DestroyRuntimeMutator(ThreadType::GC_THREAD);
57 }
58 };
59
HWTEST_F_L0(VerificationTest,GetObjectInfoTest)60 HWTEST_F_L0(VerificationTest, GetObjectInfoTest)
61 {
62 BaseObject* obj = nullptr;
63 std::string result = GetObjectInfo(obj);
64
65 EXPECT_NE(result.find("address: 0x0"), std::string::npos);
66 EXPECT_NE(result.find("Skip: nullptr"), std::string::npos);
67 EXPECT_NE(result.find("Skip: Object is not in heap range"), std::string::npos);
68 }
69
HWTEST_F_L0(VerificationTest,GetObjectInfoTest2)70 HWTEST_F_L0(VerificationTest, GetObjectInfoTest2)
71 {
72 BaseObject obj;
73 std::string result = GetObjectInfo(&obj);
74 EXPECT_NE(result.find("address: 0x"), std::string::npos);
75 EXPECT_NE(result.find("Skip: Object is not in heap range"), std::string::npos);
76 }
77
HWTEST_F_L0(VerificationTest,GetRefInfoTest)78 HWTEST_F_L0(VerificationTest, GetRefInfoTest)
79 {
80 BaseObject oldObj;
81 RefField<false> oldField(&oldObj);
82 MAddress oldAddress = oldField.GetFieldValue();
83 std::string result = GetRefInfo(oldField);
84 EXPECT_NE(result.find("address: 0x"), std::string::npos);
85 EXPECT_NE(result.find("Skip: Object is not in heap range"), std::string::npos);
86 }
87
HWTEST_F_L0(VerificationTest,VerifyRefImplTest2)88 HWTEST_F_L0(VerificationTest, VerifyRefImplTest2)
89 {
90 RegionSpace& theAllocator = reinterpret_cast<RegionSpace&>(Heap::GetHeap().GetAllocator());
91 uintptr_t addr = theAllocator.AllocOldRegion();
92 ASSERT_NE(addr, 0U);
93 BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
94 RegionDesc* region = RegionDesc::GetRegionDescAt(reinterpret_cast<uintptr_t>(obj));
95 ASSERT_NE(region, nullptr);
96 region->SetRegionType(RegionDesc::RegionType::FROM_REGION);
97 RefField<false> field(obj);
98
99 auto refObj = field.GetTargetObject();
100
101 AfterForwardVisitor visitor;
102 visitor.VerifyRefImpl(obj, field);
103 ASSERT_FALSE(RegionSpace::IsMarkedObject(refObj));
104 ASSERT_FALSE(RegionSpace::IsResurrectedObject(refObj));
105 }
106
HWTEST_F_L0(VerificationTest,VerifyRefImplTest3)107 HWTEST_F_L0(VerificationTest, VerifyRefImplTest3)
108 {
109 RegionSpace& theAllocator = reinterpret_cast<RegionSpace&>(Heap::GetHeap().GetAllocator());
110 uintptr_t addr = theAllocator.AllocOldRegion();
111 ASSERT_NE(addr, 0U);
112 BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
113 RegionDesc* region = RegionDesc::GetRegionDescAt(reinterpret_cast<uintptr_t>(obj));
114 ASSERT_NE(region, nullptr);
115 region->SetRegionType(RegionDesc::RegionType::FULL_PINNED_REGION);
116 RefField<false> field(obj);
117
118 auto refObj = field.GetTargetObject();
119
120 ReadBarrierSetter visitor;
121 visitor.VerifyRefImpl(nullptr, field);
122 visitor.VerifyRefImpl(obj, field);
123 EXPECT_EQ(RegionDesc::RegionType::FULL_PINNED_REGION,
124 RegionDesc::GetRegionDescAt(reinterpret_cast<MAddress>(field.GetTargetObject()))->GetRegionType());
125
126 region->SetRegionType(RegionDesc::RegionType::RECENT_PINNED_REGION);
127 visitor.VerifyRefImpl(obj, field);
128 EXPECT_EQ(RegionDesc::RegionType::RECENT_PINNED_REGION,
129 RegionDesc::GetRegionDescAt(reinterpret_cast<MAddress>(field.GetTargetObject()))->GetRegionType());
130
131 region->SetRegionType(RegionDesc::RegionType::FIXED_PINNED_REGION);
132 visitor.VerifyRefImpl(obj, field);
133 EXPECT_EQ(RegionDesc::RegionType::FIXED_PINNED_REGION,
134 RegionDesc::GetRegionDescAt(reinterpret_cast<MAddress>(field.GetTargetObject()))->GetRegionType());
135
136 region->SetRegionType(RegionDesc::RegionType::FULL_FIXED_PINNED_REGION);
137 visitor.VerifyRefImpl(obj, field);
138 EXPECT_EQ(RegionDesc::RegionType::FULL_FIXED_PINNED_REGION,
139 RegionDesc::GetRegionDescAt(reinterpret_cast<MAddress>(field.GetTargetObject()))->GetRegionType());
140
141 region->SetRegionType(RegionDesc::RegionType::READ_ONLY_REGION);
142 auto oldRefValue = field.GetFieldValue();
143 visitor.VerifyRefImpl(obj, field);
144 auto newRefValue = field.GetFieldValue();
145 EXPECT_NE(oldRefValue, newRefValue);
146 }
147
GetArkCollector()148 std::unique_ptr<ArkCollector> GetArkCollector()
149 {
150 CollectorResources &resources = Heap::GetHeap().GetCollectorResources();
151 Allocator &allocator = Heap::GetHeap().GetAllocator();
152
153 return std::make_unique<ArkCollector>(allocator, resources);
154 }
155
HWTEST_F_L0(VerificationTest,VerifyAfterMarkTest1)156 HWTEST_F_L0(VerificationTest, VerifyAfterMarkTest1)
157 {
158 Heap::GetHeap().SetGCPhase(GCPhase::GC_PHASE_POST_MARK);
159 std::unique_ptr<ArkCollector> arkCollector = GetArkCollector();
160 ASSERT_TRUE(arkCollector != nullptr);
161 WVerify verify;
162 verify.VerifyAfterMark(*arkCollector);
163 ASSERT_FALSE(MutatorManager::Instance().WorldStopped());
164 }
165
HWTEST_F_L0(VerificationTest,VerifyAfterForwardTest1)166 HWTEST_F_L0(VerificationTest, VerifyAfterForwardTest1)
167 {
168 Heap::GetHeap().SetGCPhase(GCPhase::GC_PHASE_COPY);
169 std::unique_ptr<ArkCollector> arkCollector = GetArkCollector();
170 ASSERT_TRUE(arkCollector != nullptr);
171 WVerify verify;
172 verify.VerifyAfterForward(*arkCollector);
173 ASSERT_FALSE(MutatorManager::Instance().WorldStopped());
174 }
175
HWTEST_F_L0(VerificationTest,VerifyAfterFixTest1)176 HWTEST_F_L0(VerificationTest, VerifyAfterFixTest1)
177 {
178 Heap::GetHeap().SetGCPhase(GCPhase::GC_PHASE_FIX);
179 std::unique_ptr<ArkCollector> arkCollector = GetArkCollector();
180 ASSERT_TRUE(arkCollector != nullptr);
181 WVerify verify;
182 verify.VerifyAfterFix(*arkCollector);
183 ASSERT_FALSE(MutatorManager::Instance().WorldStopped());
184 }
185
HWTEST_F_L0(VerificationTest,EnableReadBarrierDFXTest1)186 HWTEST_F_L0(VerificationTest, EnableReadBarrierDFXTest1)
187 {
188 std::unique_ptr<ArkCollector> arkCollector = GetArkCollector();
189 ASSERT_TRUE(arkCollector != nullptr);
190 WVerify verify;
191 verify.EnableReadBarrierDFX(*arkCollector);
192 ASSERT_FALSE(MutatorManager::Instance().WorldStopped());
193 }
194
HWTEST_F_L0(VerificationTest,DisableReadBarrierDFXTest1)195 HWTEST_F_L0(VerificationTest, DisableReadBarrierDFXTest1)
196 {
197 std::unique_ptr<ArkCollector> arkCollector = GetArkCollector();
198 ASSERT_TRUE(arkCollector != nullptr);
199 WVerify verify;
200 verify.DisableReadBarrierDFX(*arkCollector);
201 ASSERT_FALSE(MutatorManager::Instance().WorldStopped());
202 }
203
HWTEST_F_L0(VerificationTest,GetObjectInfoTest3)204 HWTEST_F_L0(VerificationTest, GetObjectInfoTest3)
205 {
206 HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::PINNED_OBJECT, true);
207 BaseObject *obj = reinterpret_cast<BaseObject *>(addr);
208 std::string result = GetObjectInfo(obj);
209 EXPECT_NE(result.find("address: 0x"), std::string::npos);
210 EXPECT_NE(result.find("Type: 0x"), std::string::npos);
211 EXPECT_NE(result.find("Base: 0x"), std::string::npos);
212 EXPECT_NE(result.find("Start: 0x"), std::string::npos);
213 EXPECT_NE(result.find("End: 0x"), std::string::npos);
214 EXPECT_NE(result.find("AllocPtr: 0x"), std::string::npos);
215 EXPECT_NE(result.find("MarkingLine: 0x"), std::string::npos);
216 EXPECT_NE(result.find("CopyLine: 0x"), std::string::npos);
217 }
218
HWTEST_F_L0(VerificationTest,GetRefInfoTest2)219 HWTEST_F_L0(VerificationTest, GetRefInfoTest2)
220 {
221 RefField<false> field(nullptr);
222 uintptr_t taggedValue = 0x04;
223 field.SetFieldValue(static_cast<MAddress>(taggedValue));
224 std::string result = GetRefInfo(field);
225 EXPECT_NE(result.find("> Raw memory:"), std::string::npos);
226 EXPECT_NE(result.find("Skip: primitive"), std::string::npos);
227 }
228
HWTEST_F_L0(VerificationTest,VerifyRefImplTest)229 HWTEST_F_L0(VerificationTest, VerifyRefImplTest)
230 {
231 HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::PINNED_OBJECT, true);
232 BaseObject *obj = reinterpret_cast<BaseObject *>(addr);
233 RefField<false> oldField(obj);
234 TestBaseObjectOperator operatorImpl;
235 BaseObject::RegisterDynamic(&operatorImpl);
236 operatorImpl.SetValidObject(true);
237 Heap::GetHeap().SetGCReason(GCReason::GC_REASON_YOUNG);
238 operatorImpl.SetSize(BaseObject::BaseObjectSize());
239 AfterMarkVisitor visitor;
240 visitor.VerifyRefImpl(nullptr, oldField);
241 ASSERT_TRUE(Heap::GetHeap().GetGCReason() == GCReason::GC_REASON_YOUNG);
242 ASSERT_TRUE(Heap::IsTaggedObject(oldField.GetFieldValue()));
243
244 AfterMarkVisitor<false> visitor1;
245 visitor1.VerifyRefImpl(nullptr, oldField);
246 ASSERT_TRUE(Heap::IsTaggedObject(oldField.GetFieldValue()));
247 }
248
HWTEST_F_L0(VerificationTest,VerifyRefImplTest1)249 HWTEST_F_L0(VerificationTest, VerifyRefImplTest1)
250 {
251 HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::PINNED_OBJECT, true);
252 BaseObject *obj = reinterpret_cast<BaseObject *>(addr);
253 RefField<false> oldField(obj);
254 TestBaseObjectOperator operatorImpl;
255 BaseObject::RegisterDynamic(&operatorImpl);
256 operatorImpl.SetValidObject(true);
257 Heap::GetHeap().SetGCReason(GCReason::GC_REASON_YOUNG);
258 operatorImpl.SetSize(BaseObject::BaseObjectSize());
259 AfterMarkVisitor visitor;
260 visitor.VerifyRefImpl(obj, oldField);
261 ASSERT_TRUE(Heap::GetHeap().GetGCReason() == GCReason::GC_REASON_YOUNG);
262 ASSERT_TRUE(Heap::IsTaggedObject(oldField.GetFieldValue()));
263 }
264
265 static BaseObject* testObj = nullptr;
CustomVisitRoot(const RefFieldVisitor & visitorFunc)266 static void CustomVisitRoot(const RefFieldVisitor& visitorFunc)
267 {
268 RefField<> field(testObj);
269 visitorFunc(field);
270 }
HWTEST_F_L0(VerificationTest,IterateRemarked_VerifyAllRefs)271 HWTEST_F_L0(VerificationTest, IterateRemarked_VerifyAllRefs)
272 {
273 RegionSpace regionSpace;
274 VerifyIterator verify(regionSpace);
275 AfterForwardVisitor visitor;
276 std::unordered_set<BaseObject*> markSet;
277 HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::PINNED_OBJECT, true);
278 testObj = reinterpret_cast<BaseObject*>(addr);
279 markSet.insert(testObj);
280
281 verify.IterateRemarked<CustomVisitRoot>(visitor, markSet, true);
282 verify.IterateRemarked<CustomVisitRoot>(visitor, markSet, false);
283 EXPECT_EQ(markSet.size(), 1);
284 EXPECT_TRUE(markSet.find(testObj) != markSet.end());
285 }
286 } // namespace common::test
287