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 "gtest/gtest.h"
17 #include "ui/base/ace_type.h"
18
19 #include "core/pipeline/base/element_register.h"
20 #define protected public
21 #define private public
22
23 #include "test/mock/core/pipeline/mock_pipeline_context.h"
24
25 #include "core/components_ng/base/node_render_status_monitor.h"
26
27 #undef private
28 #undef protected
29
30 namespace OHOS::Ace::NG {
31
32 class NodeRenderStatusMonitorTestNg : public testing::Test {
33 public:
34 static void SetUpTestSuite();
35 static void TearDownTestSuite();
36 void SetUp();
TearDown()37 void TearDown() {};
38
39 protected:
40 RefPtr<NodeRenderStatusMonitor> monitor_;
41 };
42
SetUpTestSuite()43 void NodeRenderStatusMonitorTestNg::SetUpTestSuite()
44 {
45 MockPipelineContext::SetUp();
46 }
47
TearDownTestSuite()48 void NodeRenderStatusMonitorTestNg::TearDownTestSuite()
49 {
50 MockPipelineContext::TearDown();
51 }
52
SetUp()53 void NodeRenderStatusMonitorTestNg::SetUp()
54 {
55 auto context = PipelineContext::GetCurrentContext();
56 CHECK_NULL_VOID(context);
57 monitor_ = context->GetNodeRenderStatusMonitor();
58 }
59
60 /**
61 * @tc.name: NodeRenderStatusMonitorTestNg001
62 * @tc.desc: Test RegisterNodeRenderStatusListener UnRegisterNodeRenderStatusListener
63 * @tc.type: FUNC
64 */
65 HWTEST_F(NodeRenderStatusMonitorTestNg, NodeRenderStatusMonitorTestNg001, testing::ext::TestSize.Level1)
66 {
67 ASSERT_NE(monitor_, nullptr);
68 auto frameNodeOne = FrameNode::CreateFrameNode(
69 V2::BUTTON_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<Pattern>(), false);
70 ASSERT_NE(frameNodeOne, nullptr);
__anon47eae03c0102(FrameNode* frameNode, NodeRenderState state, RenderMonitorReason reason) 71 auto func = [](FrameNode* frameNode, NodeRenderState state, RenderMonitorReason reason) {};
72 auto frameNodeOnePtr = AceType::RawPtr(frameNodeOne);
73 auto resultOne = monitor_->RegisterNodeRenderStatusListener(frameNodeOnePtr, func, MonitorSourceType::OBSERVER);
74 auto resultOneId = resultOne.id;
75 EXPECT_NE(resultOne.id, MONITOR_INVALID_ID);
76 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 1);
77
78 resultOne = monitor_->RegisterNodeRenderStatusListener(frameNodeOnePtr, func, MonitorSourceType::OBSERVER);
79 EXPECT_EQ(resultOne.id, MONITOR_INVALID_ID);
80 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 1);
81
82 resultOne = monitor_->RegisterNodeRenderStatusListener(nullptr, func, MonitorSourceType::OBSERVER);
83 EXPECT_EQ(resultOne.id, MONITOR_INVALID_ID);
84 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 1);
85
86 auto frameNodeTwo = FrameNode::CreateFrameNode(
87 V2::BUTTON_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<Pattern>(), false);
88 ASSERT_NE(frameNodeTwo, nullptr);
89 auto frameNodeTwoPtr = AceType::RawPtr(frameNodeTwo);
90 auto resultTwo = monitor_->RegisterNodeRenderStatusListener(frameNodeTwoPtr, nullptr, MonitorSourceType::OBSERVER);
91 EXPECT_EQ(resultTwo.id, MONITOR_INVALID_ID);
92 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 1);
93
94 resultTwo = monitor_->RegisterNodeRenderStatusListener(frameNodeTwoPtr, func, MonitorSourceType::OBSERVER);
95 EXPECT_NE(resultTwo.id, MONITOR_INVALID_ID);
96 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 2);
97 monitor_->UnRegisterNodeRenderStatusListener(frameNodeOnePtr, resultOneId);
98 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 1);
99 monitor_->UnRegisterNodeRenderStatusListener(frameNodeOnePtr, resultOneId);
100 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 1);
101 monitor_->UnRegisterNodeRenderStatusListener(frameNodeTwoPtr, resultTwo.id);
102 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 0);
103 }
104
105 /**
106 * @tc.name: NodeRenderStatusMonitorTestNg002
107 * @tc.desc: Test WalkThroughAncestorForStateListener
108 * @tc.type: FUNC
109 */
110 HWTEST_F(NodeRenderStatusMonitorTestNg, NodeRenderStatusMonitorTestNg002, testing::ext::TestSize.Level1)
111 {
112 ASSERT_NE(monitor_, nullptr);
113 auto rootNode = FrameNode::CreateFrameNode(
114 V2::ROOT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<Pattern>(), true);
115 ASSERT_NE(rootNode, nullptr);
116 rootNode->layoutProperty_->UpdateVisibility(OHOS::Ace::VisibleType::VISIBLE);
117 rootNode->SetActive(true);
118 auto childNodeOne = FrameNode::CreateFrameNode(
119 V2::BUTTON_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<Pattern>(), false);
120 ASSERT_NE(childNodeOne, nullptr);
121 childNodeOne->layoutProperty_->UpdateVisibility(OHOS::Ace::VisibleType::VISIBLE);
122 childNodeOne->SetActive(true);
123 childNodeOne->AttachToMainTree(true);
124 childNodeOne->MountToParent(rootNode);
125 rootNode->AttachToMainTree(true);
126 int32_t listenerCount = 0;
127 auto func = [&listenerCount](
__anon47eae03c0202( FrameNode* frameNode, NodeRenderState state, RenderMonitorReason reason) 128 FrameNode* frameNode, NodeRenderState state, RenderMonitorReason reason) { listenerCount++; };
129 auto childNodeOnePtr = AceType::RawPtr(childNodeOne);
130 auto result = monitor_->RegisterNodeRenderStatusListener(childNodeOnePtr, func, MonitorSourceType::OBSERVER);
131 EXPECT_EQ(result.state, NodeRenderState::ABOUT_TO_RENDER_IN);
132
133 childNodeOne->layoutProperty_->UpdateVisibility(OHOS::Ace::VisibleType::INVISIBLE);
134 auto state = monitor_->GetNodeCurrentRenderState(childNodeOnePtr);
135 EXPECT_EQ(state, NodeRenderState::ABOUT_TO_RENDER_OUT);
136 monitor_->WalkThroughAncestorForStateListener();
137 EXPECT_EQ(listenerCount, 1);
138
139 auto childNodeTwo = FrameNode::CreateFrameNode(
140 V2::BUTTON_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<Pattern>(), false);
141 ASSERT_NE(childNodeTwo, nullptr);
142 childNodeTwo->layoutProperty_->UpdateVisibility(OHOS::Ace::VisibleType::VISIBLE);
143 childNodeTwo->SetActive(true);
144 childNodeTwo->AttachToMainTree(true);
145 childNodeTwo->MountToParent(childNodeOne);
146 auto childNodeTwoPtr = AceType::RawPtr(childNodeTwo);
147 state = monitor_->GetNodeCurrentRenderState(childNodeTwoPtr);
148 EXPECT_EQ(state, NodeRenderState::ABOUT_TO_RENDER_OUT);
149 childNodeOne->layoutProperty_->UpdateVisibility(OHOS::Ace::VisibleType::VISIBLE);
150 state = monitor_->GetNodeCurrentRenderState(childNodeTwoPtr);
151 EXPECT_EQ(state, NodeRenderState::ABOUT_TO_RENDER_IN);
152 monitor_->UnRegisterNodeRenderStatusListener(childNodeOnePtr, result.id);
153 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 0);
154 }
155
156 /**
157 * @tc.name: NodeRenderStatusMonitorTestNg003
158 * @tc.desc: Test GetNodeCurrentRenderState
159 * @tc.type: FUNC
160 */
161 HWTEST_F(NodeRenderStatusMonitorTestNg, NodeRenderStatusMonitorTestNg003, testing::ext::TestSize.Level1)
162 {
163 ASSERT_NE(monitor_, nullptr);
164 auto rootNode = FrameNode::CreateFrameNode(
165 V2::ROOT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<Pattern>(), true);
166 ASSERT_NE(rootNode, nullptr);
167 rootNode->layoutProperty_->UpdateVisibility(OHOS::Ace::VisibleType::VISIBLE);
168 rootNode->SetActive(true);
__anon47eae03c0302(FrameNode* frameNode, NodeRenderState state, RenderMonitorReason reason) 169 auto func = [](FrameNode* frameNode, NodeRenderState state, RenderMonitorReason reason) {};
170 auto childNodeOne = FrameNode::CreateFrameNode(
171 V2::BUTTON_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<Pattern>(), false);
172 ASSERT_NE(childNodeOne, nullptr);
173 childNodeOne->layoutProperty_->UpdateVisibility(OHOS::Ace::VisibleType::VISIBLE);
174 childNodeOne->SetActive(true);
175 rootNode->AddChild(childNodeOne);
176 auto childNodeOnePtr = AceType::RawPtr(childNodeOne);
177 rootNode->AttachToMainTree(true);
178 auto result = monitor_->RegisterNodeRenderStatusListener(childNodeOnePtr, func, MonitorSourceType::OBSERVER);
179 auto state = monitor_->GetNodeCurrentRenderState(childNodeOnePtr);
180 EXPECT_EQ(state, NodeRenderState::ABOUT_TO_RENDER_IN);
181
182 childNodeOne->layoutProperty_->UpdateVisibility(OHOS::Ace::VisibleType::INVISIBLE);
183 state = monitor_->GetNodeCurrentRenderState(childNodeOnePtr);
184 EXPECT_EQ(state, NodeRenderState::ABOUT_TO_RENDER_OUT);
185
186 childNodeOne->layoutProperty_->UpdateVisibility(OHOS::Ace::VisibleType::VISIBLE);
187 childNodeOne->SetActive(false);
188 state = monitor_->GetNodeCurrentRenderState(childNodeOnePtr);
189 EXPECT_EQ(state, NodeRenderState::ABOUT_TO_RENDER_OUT);
190
191 childNodeOne->SetActive(true);
192 childNodeOne->onMainTree_ = false;
193 state = monitor_->GetNodeCurrentRenderState(childNodeOnePtr);
194 EXPECT_EQ(state, NodeRenderState::ABOUT_TO_RENDER_OUT);
195
196 monitor_->UnRegisterNodeRenderStatusListener(childNodeOnePtr, result.id);
197 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 0);
198 }
199
200 /**
201 * @tc.name: NodeRenderStatusMonitorTestNg004
202 * @tc.desc: Test NotifyFrameNodeRelease
203 * @tc.type: FUNC
204 */
205 HWTEST_F(NodeRenderStatusMonitorTestNg, NodeRenderStatusMonitorTestNg004, testing::ext::TestSize.Level1)
206 {
207 ASSERT_NE(monitor_, nullptr);
__anon47eae03c0402(FrameNode* frameNode, NodeRenderState state, RenderMonitorReason reason) 208 auto func = [](FrameNode* frameNode, NodeRenderState state, RenderMonitorReason reason) {};
209 auto childNodeOne = FrameNode::CreateFrameNode(
210 V2::BUTTON_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<Pattern>(), false);
211 ASSERT_NE(childNodeOne, nullptr);
212 monitor_->RegisterNodeRenderStatusListener(AceType::RawPtr(childNodeOne), func, MonitorSourceType::OBSERVER);
213 auto childNodeTwo = FrameNode::CreateFrameNode(
214 V2::BUTTON_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<Pattern>(), false);
215 ASSERT_NE(childNodeTwo, nullptr);
216 monitor_->RegisterNodeRenderStatusListener(AceType::RawPtr(childNodeTwo), func, MonitorSourceType::OBSERVER);
217 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 2);
218 childNodeOne.Reset();
219 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 1);
220 childNodeTwo.Reset();
221 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 0);
222 }
223
224 /**
225 * @tc.name: NodeRenderStatusMonitorTestNg005
226 * @tc.desc: Test IsRegisterNodeRenderStateChangeCallbackExceedLimit
227 * @tc.type: FUNC
228 */
229 HWTEST_F(NodeRenderStatusMonitorTestNg, NodeRenderStatusMonitorTestNg005, testing::ext::TestSize.Level1)
230 {
231 ASSERT_NE(monitor_, nullptr);
232 std::vector<RefPtr<FrameNode>> frameNodes;
__anon47eae03c0502(FrameNode* frameNode, NodeRenderState state, RenderMonitorReason reason) 233 auto func = [](FrameNode* frameNode, NodeRenderState state, RenderMonitorReason reason) {};
234 for (int i = 0; i < 63; i++) {
235 auto child = FrameNode::CreateFrameNode(
236 V2::BUTTON_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<Pattern>(), false);
237 ASSERT_NE(child, nullptr);
238 frameNodes.emplace_back(child);
239 monitor_->RegisterNodeRenderStatusListener(AceType::RawPtr(child), func, MonitorSourceType::OBSERVER);
240 }
241 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 63);
242 bool isLimit = monitor_->IsRegisterNodeRenderStateChangeCallbackExceedLimit();
243 EXPECT_EQ(isLimit, false);
244
245 auto child = FrameNode::CreateFrameNode(
246 V2::BUTTON_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<Pattern>(), false);
247 ASSERT_NE(child, nullptr);
248 auto result = monitor_->RegisterNodeRenderStatusListener(AceType::RawPtr(child), func, MonitorSourceType::OBSERVER);
249 EXPECT_NE(result.id, MONITOR_INVALID_ID);
250 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 64);
251 isLimit = monitor_->IsRegisterNodeRenderStateChangeCallbackExceedLimit();
252 EXPECT_EQ(isLimit, true);
253
254 auto childTwo = FrameNode::CreateFrameNode(
255 V2::BUTTON_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<Pattern>(), false);
256 ASSERT_NE(childTwo, nullptr);
257 result = monitor_->RegisterNodeRenderStatusListener(AceType::RawPtr(childTwo), func, MonitorSourceType::OBSERVER);
258 EXPECT_EQ(result.id, MONITOR_INVALID_ID);
259 isLimit = monitor_->IsRegisterNodeRenderStateChangeCallbackExceedLimit();
260 EXPECT_EQ(isLimit, true);
261 }
262
263 /**
264 * @tc.name: NodeRenderStatusMonitorTestNg006
265 * @tc.desc: Test RegisterNodeRenderStatusListener
266 * @tc.type: FUNC
267 */
268 HWTEST_F(NodeRenderStatusMonitorTestNg, NodeRenderStatusMonitorTestNg006, testing::ext::TestSize.Level1)
269 {
270 ASSERT_NE(monitor_, nullptr);
271 std::vector<RefPtr<FrameNode>> frameNodes;
__anon47eae03c0602(FrameNode* frameNode, NodeRenderState state, RenderMonitorReason reason) 272 auto func = [](FrameNode* frameNode, NodeRenderState state, RenderMonitorReason reason) {};
273 auto child = FrameNode::CreateFrameNode(
274 V2::BUTTON_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<Pattern>(), false);
275 ASSERT_NE(child, nullptr);
276 frameNodes.emplace_back(child);
277 monitor_->RegisterNodeRenderStatusListener(AceType::RawPtr(child), func, MonitorSourceType::OBSERVER);
278 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 1);
279 monitor_->RegisterNodeRenderStatusListener(AceType::RawPtr(child), func, MonitorSourceType::OBSERVER);
280 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 1);
281 monitor_->RegisterNodeRenderStatusListener(AceType::RawPtr(child), func, static_cast<MonitorSourceType>(2));
282 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 1);
283 }
284
285 /**
286 * @tc.name: NodeRenderStatusMonitorTestNg007
287 * @tc.desc: Test UnRegisterNodeRenderStatusListener
288 * @tc.type: FUNC
289 */
290 HWTEST_F(NodeRenderStatusMonitorTestNg, NodeRenderStatusMonitorTestNg007, testing::ext::TestSize.Level1)
291 {
292 ASSERT_NE(monitor_, nullptr);
293 std::vector<RefPtr<FrameNode>> frameNodes;
__anon47eae03c0702(FrameNode* frameNode, NodeRenderState state, RenderMonitorReason reason) 294 auto func = [](FrameNode* frameNode, NodeRenderState state, RenderMonitorReason reason) {};
295 auto child = FrameNode::CreateFrameNode(
296 V2::BUTTON_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<Pattern>(), false);
297 ASSERT_NE(child, nullptr);
298 frameNodes.emplace_back(child);
299 monitor_->UnRegisterNodeRenderStatusListener(AceType::RawPtr(child), 0);
300 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 0);
301 MonitorRegisterResult testResult =
302 monitor_->RegisterNodeRenderStatusListener(AceType::RawPtr(child), func, MonitorSourceType::OBSERVER);
303 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 1);
304 monitor_->UnRegisterNodeRenderStatusListener(AceType::RawPtr(child), testResult.id);
305 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 0);
306 }
307
308 /**
309 * @tc.name: NodeRenderStatusMonitorTestNg008
310 * @tc.desc: Test NotifyFrameNodeRelease
311 * @tc.type: FUNC
312 */
313 HWTEST_F(NodeRenderStatusMonitorTestNg, NodeRenderStatusMonitorTestNg008, testing::ext::TestSize.Level1)
314 {
315 ASSERT_NE(monitor_, nullptr);
316 std::vector<RefPtr<FrameNode>> frameNodes;
__anon47eae03c0802(FrameNode* frameNode, NodeRenderState state, RenderMonitorReason reason) 317 auto func = [](FrameNode* frameNode, NodeRenderState state, RenderMonitorReason reason) {};
318 auto child = FrameNode::CreateFrameNode(
319 V2::BUTTON_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<Pattern>(), false);
320 ASSERT_NE(child, nullptr);
321 frameNodes.emplace_back(child);
322 monitor_->NotifyFrameNodeRelease(AceType::RawPtr(child));
323 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 0);
324 monitor_->RegisterNodeRenderStatusListener(AceType::RawPtr(child), func, MonitorSourceType::OBSERVER);
325 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 1);
326 monitor_->NotifyFrameNodeRelease(AceType::RawPtr(child));
327 EXPECT_EQ(monitor_->nodeRenderStatusListeners_.size(), 0);
328 }
329
330 /**
331 * @tc.name: NodeRenderStatusMonitorTestNg009
332 * @tc.desc: Test IsNodeRenderOut
333 * @tc.type: FUNC
334 */
335 HWTEST_F(NodeRenderStatusMonitorTestNg, NodeRenderStatusMonitorTestNg009, testing::ext::TestSize.Level1)
336 {
337 ASSERT_NE(monitor_, nullptr);
338 std::vector<RefPtr<FrameNode>> frameNodes;
339 auto child = FrameNode::CreateFrameNode(
340 V2::BUTTON_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<Pattern>(), false);
341 ASSERT_NE(child, nullptr);
342 frameNodes.emplace_back(child);
343 child->layoutProperty_->propVisibility_ = VisibleType::VISIBLE;
344 child->isActive_ = true;
345 child->onMainTree_ = true;
346 EXPECT_FALSE(monitor_->IsNodeRenderOut(AceType::RawPtr(child)));
347 child->onMainTree_ = false;
348 EXPECT_TRUE(monitor_->IsNodeRenderOut(AceType::RawPtr(child)));
349 child->isActive_ = false;
350 EXPECT_TRUE(monitor_->IsNodeRenderOut(AceType::RawPtr(child)));
351 child->layoutProperty_->propVisibility_ = VisibleType::INVISIBLE;
352 EXPECT_TRUE(monitor_->IsNodeRenderOut(AceType::RawPtr(child)));
353 }
354
355 /**
356 * @tc.name: CheckSourceTypeChangeTest
357 * @tc.desc: Test Check input source switching
358 * @tc.type: FUNC
359 */
360 HWTEST_F(NodeRenderStatusMonitorTestNg, CheckSourceTypeChangeTest, testing::ext::TestSize.Level1)
361 {
362 auto context = PipelineContext::GetCurrentContext();
363 CHECK_NULL_VOID(context);
364 context->lastSourceType_ = SourceType::MOUSE;
365 EXPECT_FALSE(context->CheckSourceTypeChange(SourceType::MOUSE));
366
367 EXPECT_TRUE(context->CheckSourceTypeChange(SourceType::TOUCH));
368
369 EXPECT_TRUE(context->CheckSourceTypeChange(SourceType::MOUSE));
370 context->lastSourceType_ = SourceType::NONE;
371 }
372 } // namespace OHOS::Ace::NG