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 #include "gtest/gtest.h"
16
17 #define protected public
18 #define private public
19
20 #include "test/mock/core/pipeline/mock_pipeline_context.h"
21
22 #include "core/common/multi_thread_build_manager.h"
23 #include "core/components_ng/base/frame_node.h"
24 #include "core/components_ng/base/ui_node.h"
25 #include "core/components_ng/pattern/pattern.h"
26 #include "frameworks/core/pipeline/base/element_register_multi_thread.h"
27
28 using namespace testing;
29 using namespace testing::ext;
30
31 namespace OHOS::Ace::NG {
32 class ThreadSafeNodeTestNg : public testing::Test {
33 public:
34 static void SetUpTestSuite();
35 static void TearDownTestSuite();
36 };
37
SetUpTestSuite()38 void ThreadSafeNodeTestNg::SetUpTestSuite()
39 {
40 MockPipelineContext::SetUp();
41 }
42
TearDownTestSuite()43 void ThreadSafeNodeTestNg::TearDownTestSuite()
44 {
45 MockPipelineContext::TearDown();
46 }
47
48 /**
49 * @tc.name: ThreadSafeNodeTestNg001
50 * @tc.desc: Test AddUINodeMultiThread Repeated
51 * @tc.type: FUNC
52 */
53 HWTEST_F(ThreadSafeNodeTestNg, ThreadSafeNodeTestNg001, TestSize.Level1)
54 {
55 /**
56 * @tc.steps: step1. create thread safe uinode
57 */
58 MultiThreadBuildManager::SetIsThreadSafeNodeScope(true);
59 auto frameNode = AceType::MakeRefPtr<FrameNode>("main", 1, AceType::MakeRefPtr<Pattern>(), true);
60 MultiThreadBuildManager::SetIsThreadSafeNodeScope(false);
61
62 /**
63 * @tc.steps: step2. thread safe uinode add to ElementRegister
64 * @tc.expected: add success
65 */
66 EXPECT_EQ(ElementRegisterMultiThread::GetInstance()->AddUINodeMultiThread(frameNode), true);
67
68 /**
69 * @tc.steps: step3. thread safe uinode add to ElementRegister again
70 * @tc.expected: add failed
71 */
72 EXPECT_EQ(ElementRegisterMultiThread::GetInstance()->AddUINodeMultiThread(frameNode), false);
73 }
74
75 /**
76 * @tc.name: ThreadSafeNodeTestNg002
77 * @tc.desc: Test GetThreadSafeNodeById
78 * @tc.type: FUNC
79 */
80 HWTEST_F(ThreadSafeNodeTestNg, ThreadSafeNodeTestNg002, TestSize.Level1)
81 {
82 /**
83 * @tc.steps: step1. create thread safe uinode
84 */
85 MultiThreadBuildManager::SetIsThreadSafeNodeScope(true);
86 auto frameNode =
87 FrameNode::CreateFrameNode("main", 1, AceType::MakeRefPtr<Pattern>(), true);
88 MultiThreadBuildManager::SetIsThreadSafeNodeScope(false);
89 EXPECT_EQ(ElementRegisterMultiThread::GetInstance()->AddUINodeMultiThread(frameNode), true);
90
91 /**
92 * @tc.steps: step2. get the thread safe node which id is 1 from ElementRegister
93 * @tc.expected: get success
94 */
95 EXPECT_EQ(ElementRegisterMultiThread::GetInstance()->GetThreadSafeNodeById(1), true);
96
97 /**
98 * @tc.steps: step3. get the thread safe node which id is ElementRegister::UndefinedElementId from ElementRegister
99 * @tc.expected: get failed
100 */
101 EXPECT_EQ(
102 ElementRegisterMultiThread::GetInstance()->GetThreadSafeNodeById(ElementRegister::UndefinedElementId), false);
103 }
104
105 /**
106 * @tc.name: ThreadSafeNodeTestNg003
107 * @tc.desc: Test RemoveThreadSafeNode
108 * @tc.type: FUNC
109 */
110 HWTEST_F(ThreadSafeNodeTestNg, ThreadSafeNodeTestNg003, TestSize.Level1)
111 {
112 /**
113 * @tc.steps: step1. create thread safe uinode
114 */
115 MultiThreadBuildManager::SetIsThreadSafeNodeScope(true);
116 auto frameNode =
117 FrameNode::CreateFrameNode("main", 1, AceType::MakeRefPtr<Pattern>(), true);
118 MultiThreadBuildManager::SetIsThreadSafeNodeScope(false);
119 EXPECT_EQ(ElementRegisterMultiThread::GetInstance()->AddUINodeMultiThread(frameNode), true);
120
121 /**
122 * @tc.steps: step2. remove the thread safe node which id is 1 from ElementRegister
123 * @tc.expected: remove success
124 */
125 EXPECT_EQ(ElementRegisterMultiThread::GetInstance()->RemoveThreadSafeNode(1), true);
126
127 /**
128 * @tc.steps: step3. remove the thread safe node which
129 * id is ElementRegister::UndefinedElementId from ElementRegister
130 * @tc.expected: remove failed
131 */
132 EXPECT_EQ(
133 ElementRegisterMultiThread::GetInstance()->RemoveThreadSafeNode(ElementRegister::UndefinedElementId), false);
134 }
135
136 /**
137 * @tc.name: ThreadSafeNodeTestNg004
138 * @tc.desc: Test thread safe node RebuildRenderContextTree.
139 * @tc.type: FUNC
140 */
141 HWTEST_F(ThreadSafeNodeTestNg, ThreadSafeNodeTestNg004, TestSize.Level1)
142 {
143 /**
144 * @tc.steps: step1. create thread safe uinode
145 */
146 MultiThreadBuildManager::SetIsThreadSafeNodeScope(true);
147 auto frameNode =
148 FrameNode::CreateFrameNode("main", 1, AceType::MakeRefPtr<Pattern>(), true);
149 MultiThreadBuildManager::SetIsThreadSafeNodeScope(false);
150
151 /**
152 * @tc.steps: step2. thread safe uinode RebuildRenderContextTree
153 * @tc.expected: rebuild success
154 */
155 int32_t taskSize = frameNode->afterAttachMainTreeTasks_.size();
156 frameNode->RebuildRenderContextTree();
157 EXPECT_EQ(frameNode->afterAttachMainTreeTasks_.size(), taskSize + 1);
158 }
159
160 /**
161 * @tc.name: ThreadSafeNodeTestNg005
162 * @tc.desc: Test thread safe node MarkNeedRender.
163 * @tc.type: FUNC
164 */
165 HWTEST_F(ThreadSafeNodeTestNg, ThreadSafeNodeTestNg005, TestSize.Level1)
166 {
167 /**
168 * @tc.steps: step1. create thread safe uinode
169 */
170 auto context = MockPipelineContext::GetCurrent();
171 MultiThreadBuildManager::SetIsThreadSafeNodeScope(true);
172 auto frameNode =
173 FrameNode::CreateFrameNode("main", 1, AceType::MakeRefPtr<Pattern>(), true);
174 MultiThreadBuildManager::SetIsThreadSafeNodeScope(false);
175 frameNode->context_ = AceType::RawPtr(context);
176 frameNode->isRenderDirtyMarked_ = false;
177 frameNode->isLayoutDirtyMarked_ = false;
178
179 /**
180 * @tc.steps: step2. thread safe uinode MarkNeedRender
181 * @tc.expected: mark success
182 */
183 int32_t taskSize = frameNode->afterAttachMainTreeTasks_.size();
184 frameNode->MarkNeedRender(true);
185 EXPECT_EQ(frameNode->afterAttachMainTreeTasks_.size(), taskSize + 1);
186
187 /**
188 * @tc.steps: step3. create not thread safe uinode
189 */
190 auto frameNode2 =
191 FrameNode::CreateFrameNode("main", 1, AceType::MakeRefPtr<Pattern>(), true);
192 frameNode2->context_ = AceType::RawPtr(context);
193 frameNode2->isRenderDirtyMarked_ = false;
194 frameNode2->isLayoutDirtyMarked_ = false;
195
196 /**
197 * @tc.steps: step4. not thread safe uinode MarkNeedRender
198 * @tc.expected: mark success
199 */
200 taskSize = frameNode2->afterAttachMainTreeTasks_.size();
201 frameNode2->MarkNeedRender(true);
202 EXPECT_EQ(frameNode2 ->afterAttachMainTreeTasks_.size(), taskSize);
203 }
204
205 /**
206 * @tc.name: ThreadSafeNodeTestNg006
207 * @tc.desc: Test thread safe uinode create.
208 * @tc.type: FUNC
209 */
210 HWTEST_F(ThreadSafeNodeTestNg, ThreadSafeNodeTestNg006, TestSize.Level1)
211 {
212 /**
213 * @tc.steps: step1. create thread safe uinode
214 * @tc.expected: create success
215 */
216 MultiThreadBuildManager::SetIsThreadSafeNodeScope(true);
217 auto frameNode =
218 FrameNode::CreateFrameNode("main", 1, AceType::MakeRefPtr<Pattern>(), true);
219 MultiThreadBuildManager::SetIsThreadSafeNodeScope(false);
220 EXPECT_EQ(frameNode->isThreadSafeNode_, true);
221 EXPECT_EQ(frameNode->isFree_, true);
222 }
223
224 /**
225 * @tc.name: ThreadSafeNodeTestNg007
226 * @tc.desc: Test thread safe uinode release
227 * @tc.type: FUNC
228 */
229 HWTEST_F(ThreadSafeNodeTestNg, ThreadSafeNodeTestNg007, TestSize.Level1)
230 {
231 bool isUIThread = MultiThreadBuildManager::isUIThread_;
232 {
233 /**
234 * @tc.steps: step1. create thread safe uinode
235 */
236 MultiThreadBuildManager::SetIsThreadSafeNodeScope(true);
237 auto frameNode =
238 FrameNode::CreateFrameNode("main", 1, AceType::MakeRefPtr<Pattern>(), true);
239 MultiThreadBuildManager::SetIsThreadSafeNodeScope(false);
240 /**
241 * @tc.steps: step2. release thread safe uinode not on ui thread
242 * @tc.expected: release success
243 */
244 MultiThreadBuildManager::isUIThread_ = false;
245 EXPECT_EQ(frameNode->isThreadSafeNode_, true);
246 EXPECT_EQ(frameNode->isFree_, true);
247 }
248 {
249 /**
250 * @tc.steps: step3. create thread safe uinode
251 */
252 MultiThreadBuildManager::SetIsThreadSafeNodeScope(true);
253 auto frameNode =
254 FrameNode::CreateFrameNode("main", 1, AceType::MakeRefPtr<Pattern>(), true);
255 MultiThreadBuildManager::SetIsThreadSafeNodeScope(false);
256 /**
257 * @tc.steps: step2. release thread safe uinode on ui thread
258 * @tc.expected: release success
259 */
260 MultiThreadBuildManager::isUIThread_ = true;
261 EXPECT_EQ(frameNode->isThreadSafeNode_, true);
262 EXPECT_EQ(frameNode->isFree_, true);
263 }
264 MultiThreadBuildManager::isUIThread_ = isUIThread;
265 }
266
267 /**
268 * @tc.name: ThreadSafeNodeTestNg0088
269 * @tc.desc: Test uinode release
270 * @tc.type: FUNC
271 */
272 HWTEST_F(ThreadSafeNodeTestNg, ThreadSafeNodeTestNg008, TestSize.Level1)
273 {
274 bool isUIThread = MultiThreadBuildManager::isUIThread_;
275 {
276 /**
277 * @tc.steps: step1. create not thread safe uinode
278 */
279 auto frameNode =
280 FrameNode::CreateFrameNode("main", 1, AceType::MakeRefPtr<Pattern>(), true);
281 /**
282 * @tc.steps: step2. release not thread safe uinode not on ui thread
283 * @tc.expected: release success
284 */
285 MultiThreadBuildManager::isUIThread_ = false;
286 EXPECT_EQ(frameNode->isThreadSafeNode_, false);
287 EXPECT_EQ(frameNode->isFree_, false);
288 }
289 {
290 /**
291 * @tc.steps: step3. create not thread safe uinode
292 */
293 auto frameNode =
294 FrameNode::CreateFrameNode("main", 1, AceType::MakeRefPtr<Pattern>(), true);
295 /**
296 * @tc.steps: step4. release not thread safe uinode on ui thread
297 * @tc.expected: release success
298 */
299 MultiThreadBuildManager::isUIThread_ = true;
300 EXPECT_EQ(frameNode->isThreadSafeNode_, false);
301 EXPECT_EQ(frameNode->isFree_, false);
302 }
303 MultiThreadBuildManager::isUIThread_ = isUIThread;
304 }
305
306 /**
307 * @tc.name: ThreadSafeNodeTestNg009
308 * @tc.desc: Test thread safe uinode AttachToMainTree.
309 * @tc.type: FUNC
310 */
311 HWTEST_F(ThreadSafeNodeTestNg, ThreadSafeNodeTestNg009, TestSize.Level1)
312 {
313 /**
314 * @tc.steps: step1. create thread safe uinode
315 */
316 MultiThreadBuildManager::SetIsThreadSafeNodeScope(true);
317 auto frameNode =
318 FrameNode::CreateFrameNode("main", 1, AceType::MakeRefPtr<Pattern>(), true);
319 MultiThreadBuildManager::SetIsThreadSafeNodeScope(false);
320
321 /**
322 * @tc.steps: step2. thread safe uinode AttachToMainTree and DetachFromMainTree
323 * @tc.expected: attach and detach success
324 */
325 PipelineContext* pipeline = frameNode->GetContextWithCheck();
326 frameNode->AttachToMainTree(false, pipeline);
327 EXPECT_EQ(frameNode->isFree_, false);
328 frameNode->DetachFromMainTree(false, false);
329 EXPECT_EQ(frameNode->isFree_, true);
330 }
331
332 /**
333 * @tc.name: ThreadSafeNodeTestNg010
334 * @tc.desc: Test thread safe uinode DetachFromMainTree.
335 * @tc.type: FUNC
336 */
337 HWTEST_F(ThreadSafeNodeTestNg, ThreadSafeNodeTestNg010, TestSize.Level1)
338 {
339 /**
340 * @tc.steps: step1. create thread safe uinode
341 */
342 MultiThreadBuildManager::SetIsThreadSafeNodeScope(true);
343 auto frameNode =
344 FrameNode::CreateFrameNode("main", 1, AceType::MakeRefPtr<Pattern>(), true);
345 MultiThreadBuildManager::SetIsThreadSafeNodeScope(false);
346
347 /**
348 * @tc.steps: step2. thread safe uinode AttachToMainTree and DetachFromMainTree
349 * @tc.expected: attach and detach success
350 */
351 PipelineContext* pipeline = frameNode->GetContextWithCheck();
352 frameNode->AttachToMainTree(false, pipeline);
353 EXPECT_EQ(frameNode->isFree_, false);
354 frameNode->DetachFromMainTree(false, true);
355 EXPECT_EQ(frameNode->isFree_, true);
356 }
357
358 /**
359 * @tc.name: ThreadSafeNodeTestNg011
360 * @tc.desc: Test thread safe uinode tree DetachFromMainTree.
361 * @tc.type: FUNC
362 */
363 HWTEST_F(ThreadSafeNodeTestNg, ThreadSafeNodeTestNg011, TestSize.Level1)
364 {
365 /**
366 * @tc.steps: step1. create thread safe uinode tree
367 */
368 MultiThreadBuildManager::SetIsThreadSafeNodeScope(true);
369 auto frameNode =
370 FrameNode::CreateFrameNode("main", 1, AceType::MakeRefPtr<Pattern>(), true);
371 auto child =
372 FrameNode::CreateFrameNode("main", 2, AceType::MakeRefPtr<Pattern>(), true);
373 frameNode->AddChild(child);
374 MultiThreadBuildManager::SetIsThreadSafeNodeScope(false);
375
376 /**
377 * @tc.steps: step2. thread safe uinode tree AttachToMainTree and DetachFromMainTree
378 * @tc.expected: attach and detach success
379 */
380 PipelineContext* pipeline = frameNode->GetContextWithCheck();
381 frameNode->AttachToMainTree(false, pipeline);
382 EXPECT_EQ(frameNode->isFree_, false);
383 frameNode->DetachFromMainTree(false, true);
384 EXPECT_EQ(frameNode->isFree_, true);
385 }
386
387 /**
388 * @tc.name: ThreadSafeNodeTestNg012
389 * @tc.desc: Test not thread safe ui node tree DetachFromMainTree.
390 * @tc.type: FUNC
391 */
392 HWTEST_F(ThreadSafeNodeTestNg, ThreadSafeNodeTestNg012, TestSize.Level1)
393 {
394 /**
395 * @tc.steps: step1. create thread safe uinode
396 */
397 MultiThreadBuildManager::SetIsThreadSafeNodeScope(true);
398 auto frameNode =
399 FrameNode::CreateFrameNode("main", 1, AceType::MakeRefPtr<Pattern>(), true);
400 MultiThreadBuildManager::SetIsThreadSafeNodeScope(false);
401 /**
402 * @tc.steps: step2. create not thread safe uinode tree
403 */
404 auto child =
405 FrameNode::CreateFrameNode("main", 2, AceType::MakeRefPtr<Pattern>(), true);
406 frameNode->AddChild(child);
407 /**
408 * @tc.steps: step3. not thread safe uinode tree AttachToMainTree and DetachFromMainTree
409 * @tc.expected: attach and detach success
410 */
411 PipelineContext* pipeline = frameNode->GetContextWithCheck();
412 frameNode->AttachToMainTree(false, pipeline);
413 EXPECT_EQ(frameNode->isFree_, false);
414 frameNode->DetachFromMainTree(false, true);
415 EXPECT_EQ(frameNode->isFree_, true);
416 }
417
418 /**
419 * @tc.name: ThreadSafeNodeTestNg013
420 * @tc.desc: Test thread safe node MarkModifyDone.
421 * @tc.type: FUNC
422 */
423 HWTEST_F(ThreadSafeNodeTestNg, ThreadSafeNodeTestNg013, TestSize.Level1)
424 {
425 /**
426 * @tc.steps: step1. create thread safe uinode
427 */
428 MultiThreadBuildManager::SetIsThreadSafeNodeScope(true);
429 auto frameNode =
430 FrameNode::CreateFrameNode("main", 1, AceType::MakeRefPtr<Pattern>(), true);
431 MultiThreadBuildManager::SetIsThreadSafeNodeScope(false);
432 /**
433 * @tc.steps: step2. thread safe uinode MarkModifyDone
434 * @tc.expected: MarkModifyDone success
435 */
436 int32_t taskSize = frameNode->afterAttachMainTreeTasks_.size();
437 frameNode->MarkModifyDone();
438 EXPECT_EQ(frameNode->afterAttachMainTreeTasks_.size(), taskSize + 1);
439 }
440
441 /**
442 * @tc.name: ThreadSafeNodeTestNg014
443 * @tc.desc: Test thread safe node MarkDirtyNode.
444 * @tc.type: FUNC
445 */
446 HWTEST_F(ThreadSafeNodeTestNg, ThreadSafeNodeTestNg014, TestSize.Level1)
447 {
448 /**
449 * @tc.steps: step1. create thread safe uinode
450 */
451 MultiThreadBuildManager::SetIsThreadSafeNodeScope(true);
452 auto frameNode =
453 FrameNode::CreateFrameNode("main", 1, AceType::MakeRefPtr<Pattern>(), true);
454 MultiThreadBuildManager::SetIsThreadSafeNodeScope(false);
455 /**
456 * @tc.steps: step2. thread safe uinode MarkDirtyNode
457 * @tc.expected: MarkDirtyNode success
458 */
459 int32_t taskSize = frameNode->afterAttachMainTreeTasks_.size();
460 frameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
461 EXPECT_EQ(frameNode->afterAttachMainTreeTasks_.size(), taskSize + 1);
462 }
463
464 /**
465 * @tc.name: ThreadSafeNodeTestNg015
466 * @tc.desc: Test thread safe node CheckThreadSafeNodeTree.
467 * @tc.type: FUNC
468 */
469 HWTEST_F(ThreadSafeNodeTestNg, ThreadSafeNodeTestNg015, TestSize.Level1)
470 {
471 /**
472 * @tc.steps: step1. create thread safe uinode
473 */
474 MultiThreadBuildManager::SetIsThreadSafeNodeScope(true);
475 auto frameNode =
476 FrameNode::CreateFrameNode("main", 1, AceType::MakeRefPtr<Pattern>(), true);
477 MultiThreadBuildManager::SetIsThreadSafeNodeScope(false);
478 /**
479 * @tc.steps: step2. thread safe uinode CheckThreadSafeNodeTree
480 * @tc.expected: CheckThreadSafeNodeTree success
481 */
482 EXPECT_EQ(frameNode->CheckThreadSafeNodeTree(true), true);
483 EXPECT_EQ(frameNode->CheckThreadSafeNodeTree(false), true);
484 }
485
486 /**
487 * @tc.name: ThreadSafeNodeTestNg016
488 * @tc.desc: Test thread unsafe node CheckThreadSafeNodeTree.
489 * @tc.type: FUNC
490 */
491 HWTEST_F(ThreadSafeNodeTestNg, ThreadSafeNodeTestNg016, TestSize.Level1)
492 {
493 /**
494 * @tc.steps: step1. create thread unsafe uinode
495 */
496 auto frameNode =
497 FrameNode::CreateFrameNode("main", 1, AceType::MakeRefPtr<Pattern>(), true);
498 /**
499 * @tc.steps: step2. thread unsafe uinode CheckThreadSafeNodeTree
500 * @tc.expected: CheckThreadSafeNodeTree success
501 */
502 EXPECT_EQ(frameNode->CheckThreadSafeNodeTree(true), false);
503 EXPECT_EQ(frameNode->CheckThreadSafeNodeTree(false), false);
504 }
505 } // namespace OHOS::Ace::NG