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/heap_manager.h"
17 #include "common_components/mutator/mutator.h"
18 #include "common_components/mutator/mutator_manager.h"
19 #include "common_components/tests/test_helper.h"
20 #include "common_interfaces/base_runtime.h"
21 #include "common_interfaces/objects/base_object.h"
22
23 using namespace common;
24
25 namespace common::test {
26 class TestMutator : public Mutator {
27 public:
28 using Mutator::VisitRawObjects;
29 };
30 class MutatorTest : public BaseTestWithScope {
31 protected:
SetUpTestCase()32 static void SetUpTestCase()
33 {
34 BaseRuntime::GetInstance()->Init();
35 }
TearDownTestCase()36 static void TearDownTestCase() {}
37 };
38
HWTEST_F_L0(MutatorTest,GetThreadLocalData_Test1)39 HWTEST_F_L0(MutatorTest, GetThreadLocalData_Test1)
40 {
41 ThreadLocalData *ret = GetThreadLocalData();
42 ASSERT_TRUE(ret != nullptr);
43 }
44
HWTEST_F_L0(MutatorTest,TransitionGCPhase_Test1)45 HWTEST_F_L0(MutatorTest, TransitionGCPhase_Test1)
46 {
47 MutatorBase mutatorBase;
48 mutatorBase.Init();
49 bool ret = mutatorBase.TransitionGCPhase(false);
50 EXPECT_TRUE(ret == true);
51
52 MutatorBase::SuspensionType flag = MutatorBase::SuspensionType::SUSPENSION_FOR_GC_PHASE;
53 mutatorBase.SetSuspensionFlag(flag);
54
55 ret = mutatorBase.TransitionGCPhase(false);
56 EXPECT_TRUE(ret == true);
57
58 ret = mutatorBase.TransitionGCPhase(true);
59 EXPECT_TRUE(ret == true);
60 ret = mutatorBase.TransitionGCPhase(false);
61 EXPECT_TRUE(ret == true);
62 }
63
HWTEST_F_L0(MutatorTest,HandleSuspensionRequest_Test0)64 HWTEST_F_L0(MutatorTest, HandleSuspensionRequest_Test0)
65 {
66 MutatorBase mutatorBase;
67 mutatorBase.Init();
68
69 MutatorBase::SuspensionType flag = MutatorBase::SuspensionType::SUSPENSION_FOR_STW;
70 mutatorBase.SetSuspensionFlag(flag);
71
72 mutatorBase.HandleSuspensionRequest();
73 EXPECT_TRUE(mutatorBase.InSaferegion() == false);
74
75 flag = MutatorBase::SuspensionType::SUSPENSION_FOR_GC_PHASE;
76 mutatorBase.SetSuspensionFlag(flag);
77 mutatorBase.HandleSuspensionRequest();
78 EXPECT_TRUE(mutatorBase.InSaferegion() == false);
79 }
80
HWTEST_F_L0(MutatorTest,SuspendForStw_Test0)81 HWTEST_F_L0(MutatorTest, SuspendForStw_Test0)
82 {
83 MutatorBase mutatorBase;
84 mutatorBase.Init();
85
86 mutatorBase.SuspendForStw();
87 EXPECT_TRUE(mutatorBase.InSaferegion() == false);
88 }
89
HWTEST_F_L0(MutatorTest,VisitRawObjects_Nullptr_NoCall)90 HWTEST_F_L0(MutatorTest, VisitRawObjects_Nullptr_NoCall)
91 {
92 TestMutator mutator;
93 mutator.Init();
94 mutator.PushRawObject(nullptr);
95
96 bool called = false;
97 RootVisitor func = [&called](const ObjectRef& obj) {
98 called = true;
99 };
100 mutator.VisitRawObjects(func);
101 EXPECT_FALSE(called);
102 }
103
HWTEST_F_L0(MutatorTest,VisitRawObjects_NonNull_Call)104 HWTEST_F_L0(MutatorTest, VisitRawObjects_NonNull_Call)
105 {
106 TestMutator mutator;
107 mutator.Init();
108 BaseObject mockObj;
109 mutator.PushRawObject(&mockObj);
110
111 bool called = false;
112 RootVisitor func = [&called, &mockObj](const ObjectRef& obj) {
113 called = true;
114 EXPECT_EQ(obj.object, &mockObj);
115 };
116
117 mutator.VisitRawObjects(func);
118 EXPECT_TRUE(called);
119 }
120
HWTEST_F_L0(MutatorTest,HandleSuspensionRequest_Test1)121 HWTEST_F_L0(MutatorTest, HandleSuspensionRequest_Test1)
122 {
123 MutatorBase mutatorBase;
124 mutatorBase.Init();
125 MutatorBase::SuspensionType flag = MutatorBase::SuspensionType::SUSPENSION_FOR_STW;
126 mutatorBase.SetSuspensionFlag(flag);
127 flag = MutatorBase::SuspensionType::SUSPENSION_FOR_GC_PHASE;
128 mutatorBase.SetSuspensionFlag(flag);
129 mutatorBase.HandleSuspensionRequest();
130 EXPECT_FALSE(mutatorBase.InSaferegion());
131 EXPECT_TRUE(mutatorBase.FinishedTransition());
132 }
133
HWTEST_F_L0(MutatorTest,HandleSuspensionRequest_Test2)134 HWTEST_F_L0(MutatorTest, HandleSuspensionRequest_Test2)
135 {
136 MutatorBase mutatorBase;
137 mutatorBase.Init();
138 MutatorBase::SuspensionType flag = MutatorBase::SuspensionType::SUSPENSION_FOR_CPU_PROFILE;
139 mutatorBase.SetSuspensionFlag(flag);
140 mutatorBase.SetCpuProfileState(MutatorBase::CpuProfileState::FINISH_CPUPROFILE);
141 std::thread t([&]() {
142 std::this_thread::sleep_for(std::chrono::nanoseconds(1));
143 mutatorBase.ClearSuspensionFlag(MutatorBase::SUSPENSION_FOR_CPU_PROFILE);
144 });
145 mutatorBase.HandleSuspensionRequest();
146 t.join();
147 EXPECT_FALSE(mutatorBase.InSaferegion());
148 EXPECT_TRUE(mutatorBase.FinishedCpuProfile());
149 }
150
HWTEST_F_L0(MutatorTest,HandleSuspensionRequest_Test3)151 HWTEST_F_L0(MutatorTest, HandleSuspensionRequest_Test3)
152 {
153 MutatorBase mutatorBase;
154 mutatorBase.Init();
155 mutatorBase.SetSuspensionFlag(MutatorBase::SUSPENSION_FOR_STW);
156 mutatorBase.SetSuspensionFlag(MutatorBase::SUSPENSION_FOR_CPU_PROFILE);
157 mutatorBase.SetCpuProfileState(MutatorBase::CpuProfileState::FINISH_CPUPROFILE);
158 std::thread t([&]() {
159 std::this_thread::sleep_for(std::chrono::nanoseconds(1));
160 mutatorBase.ClearSuspensionFlag(MutatorBase::SUSPENSION_FOR_CPU_PROFILE);
161 });
162 mutatorBase.HandleSuspensionRequest();
163 t.join();
164 EXPECT_FALSE(mutatorBase.InSaferegion());
165 EXPECT_TRUE(mutatorBase.FinishedCpuProfile());
166 }
167
HWTEST_F_L0(MutatorTest,HandleGCPhase_SatbNodeNotNull)168 HWTEST_F_L0(MutatorTest, HandleGCPhase_SatbNodeNotNull)
169 {
170 Mutator* mutator = MutatorManager::Instance().CreateRuntimeMutator(ThreadType::ARK_PROCESSOR);
171 HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true);
172 BaseObject *mockObj = reinterpret_cast<BaseObject*>(addr);
173 new (mockObj) BaseObject();
174 mutator->RememberObjectInSatbBuffer(mockObj);
175 EXPECT_NE(mutator->GetSatbBufferNode(), nullptr);
176 MutatorBase* base = static_cast<MutatorBase*>(mutator->GetMutatorBasePtr());
177 base->TransitionToGCPhaseExclusive(GCPhase::GC_PHASE_REMARK_SATB);
178 EXPECT_EQ(mutator->GetSatbBufferNode(), nullptr);
179 MutatorManager::Instance().DestroyRuntimeMutator(ThreadType::ARK_PROCESSOR);
180 }
181
HWTEST_F_L0(MutatorTest,HandleSuspensionRequest_LeaveSaferegion1)182 HWTEST_F_L0(MutatorTest, HandleSuspensionRequest_LeaveSaferegion1)
183 {
184 MutatorBase mutatorBase;
185 mutatorBase.Init();
186 mutatorBase.IncObserver();
187 std::thread t([&]() {
188 std::this_thread::sleep_for(std::chrono::nanoseconds(1));
189 mutatorBase.DecObserver();
190 });
191 mutatorBase.HandleSuspensionRequest();
192 t.join();
193 EXPECT_FALSE(mutatorBase.InSaferegion());
194 }
195
HWTEST_F_L0(MutatorTest,HandleSuspensionRequest_LeaveSaferegion2)196 HWTEST_F_L0(MutatorTest, HandleSuspensionRequest_LeaveSaferegion2)
197 {
198 MutatorBase mutatorBase;
199 mutatorBase.Init();
200 MutatorBase::SuspensionType flag = MutatorBase::SuspensionType::SUSPENSION_FOR_CPU_PROFILE;
201 mutatorBase.SetSuspensionFlag(flag);
202 mutatorBase.SetCpuProfileState(MutatorBase::CpuProfileState::FINISH_CPUPROFILE);
203 mutatorBase.IncObserver();
204 std::thread t([&]() {
205 std::this_thread::sleep_for(std::chrono::nanoseconds(1));
206 mutatorBase.ClearSuspensionFlag(MutatorBase::SUSPENSION_FOR_CPU_PROFILE);
207 mutatorBase.DecObserver();
208 });
209 mutatorBase.HandleSuspensionRequest();
210 t.join();
211 EXPECT_FALSE(mutatorBase.InSaferegion());
212 }
213
HWTEST_F_L0(MutatorTest,HandleSuspensionRequest_Test4)214 HWTEST_F_L0(MutatorTest, HandleSuspensionRequest_Test4)
215 {
216 MutatorBase mutatorBase;
217 mutatorBase.Init();
218 mutatorBase.SetSuspensionFlag(MutatorBase::SUSPENSION_FOR_STW);
219 EXPECT_NO_FATAL_FAILURE(mutatorBase.HandleSuspensionRequest());
220 }
221
HWTEST_F_L0(MutatorTest,HandleSuspensionRequest_Test5)222 HWTEST_F_L0(MutatorTest, HandleSuspensionRequest_Test5)
223 {
224 MutatorBase mutatorBase;
225 mutatorBase.Init();
226 mutatorBase.SetSuspensionFlag(MutatorBase::SUSPENSION_FOR_GC_PHASE);
227 EXPECT_NO_FATAL_FAILURE(mutatorBase.HandleSuspensionRequest());
228 }
229
HWTEST_F_L0(MutatorTest,TransitionToGCPhaseExclusive_TestEnum)230 HWTEST_F_L0(MutatorTest, TransitionToGCPhaseExclusive_TestEnum)
231 {
232 MutatorBase mutatorBase;
233 mutatorBase.Init();
234
235 GCPhase phase = GCPhase::GC_PHASE_ENUM;
236 EXPECT_NO_FATAL_FAILURE(mutatorBase.TransitionToGCPhaseExclusive(phase));
237 }
238
HWTEST_F_L0(MutatorTest,TransitionToGCPhaseExclusive_TestPrecopy)239 HWTEST_F_L0(MutatorTest, TransitionToGCPhaseExclusive_TestPrecopy)
240 {
241 MutatorBase mutatorBase;
242 mutatorBase.Init();
243
244 GCPhase phase = GCPhase::GC_PHASE_PRECOPY;
245 EXPECT_NO_FATAL_FAILURE(mutatorBase.TransitionToGCPhaseExclusive(phase));
246 }
247
HWTEST_F_L0(MutatorTest,TransitionToGCPhaseExclusive_TestIdle)248 HWTEST_F_L0(MutatorTest, TransitionToGCPhaseExclusive_TestIdle)
249 {
250 MutatorBase mutatorBase;
251 mutatorBase.Init();
252
253 GCPhase phase = GCPhase::GC_PHASE_IDLE;
254 EXPECT_NO_FATAL_FAILURE(mutatorBase.TransitionToGCPhaseExclusive(phase));
255 }
256 } // namespace common::test
257