1 /*
2 * Copyright (c) 2023 iSoftStone Information Technology (Group) 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 <memory>
17 #include <optional>
18
19 #include "gtest/gtest.h"
20
21 #define protected public
22 #define private public
23 #include "test/mock/core/pipeline/mock_pipeline_context.h"
24
25 #include "base/geometry/dimension.h"
26 #include "base/geometry/ng/offset_t.h"
27 #include "base/geometry/ng/size_t.h"
28 #include "base/memory/ace_type.h"
29 #include "base/utils/utils.h"
30 #include "core/components/common/layout/grid_layout_info.h"
31 #include "core/components/common/properties/alignment.h"
32 #include "core/components_ng/layout/layout_algorithm.h"
33 #include "core/components_ng/layout/layout_wrapper_node.h"
34 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
35 #include "core/components_ng/property/grid_property.h"
36 #include "core/components_ng/property/property.h"
37 #include "core/components_ng/syntax/lazy_for_each_model.h"
38 #include "core/components_ng/syntax/lazy_layout_wrapper_builder.h"
39 #undef private
40 #undef protected
41
42 using namespace testing;
43 using namespace testing::ext;
44
45 namespace OHOS::Ace::NG {
46 namespace {
47 constexpr int32_t NODE_ID_0 = 0;
48 constexpr int32_t NODE_ID_1 = 1;
49 constexpr int32_t NODE_ID_2 = 2;
50 constexpr int32_t NODE_ID_3 = 3;
51 const std::string ROW_FRAME_NODE = "rowFrameNode";
52 // const std::string FIRST_FRAME_NODE = "TabContent";
53 const std::string FIRST_CHILD_FRAME_NODE = "firstChildFrameNode";
54 const std::string SECOND_CHILD_FRAME_NODE = "secondChildFrameNode";
55 const std::string THIRD_CHILD_FRAME_NODE = "thirdChildFrameNode";
56 const int32_t INDEX = 1;
57
CreateNodeAndWrapper(const std::string & tag,int32_t nodeId)58 std::pair<RefPtr<FrameNode>, RefPtr<LayoutWrapperNode>> CreateNodeAndWrapper(const std::string& tag, int32_t nodeId)
59 {
60 auto node = FrameNode::CreateFrameNode(tag, nodeId, AceType::MakeRefPtr<Pattern>());
61 RefPtr<GeometryNode> geometryNode = AceType::MakeRefPtr<GeometryNode>();
62 RefPtr<LayoutWrapperNode> layoutWrapper =
63 AceType::MakeRefPtr<LayoutWrapperNode>(node, geometryNode, node->GetLayoutProperty());
64
65 return std::make_pair(node, layoutWrapper);
66 }
67
CreateWrapperBuilder()68 RefPtr<LazyLayoutWrapperBuilder> CreateWrapperBuilder()
69 {
70 RefPtr<LazyForEachActuator> actuator = AceType::MakeRefPtr<LazyForEachActuator>();
71 auto builder = AceType::DynamicCast<LazyForEachBuilder>(actuator);
72 RefPtr<LazyForEachNode> host = AceType::MakeRefPtr<LazyForEachNode>(INDEX, builder);
73 RefPtr<LazyLayoutWrapperBuilder> wrapperBuilder = AceType::MakeRefPtr<LazyLayoutWrapperBuilder>(builder, host);
74 return wrapperBuilder;
75 }
76 } // namespace
77
78 class LayoutWrapperNodeTestNg : public testing::Test {
79 public:
80 static void SetUpTestSuite();
81 static void TearDownTestSuite();
82 };
83
SetUpTestSuite()84 void LayoutWrapperNodeTestNg::SetUpTestSuite()
85 {
86 MockPipelineContext::SetUp();
87 }
88
TearDownTestSuite()89 void LayoutWrapperNodeTestNg::TearDownTestSuite()
90 {
91 MockPipelineContext::TearDown();
92 }
93
94 /**
95 * @tc.name: LayoutWrapperNodeTestNg001
96 * @tc.desc: Test Update.
97 * @tc.type: FUNC
98 */
99 HWTEST_F(LayoutWrapperNodeTestNg, LayoutWrapperNodeTestNg001, TestSize.Level1)
100 {
101 auto [node, wrapper] = CreateNodeAndWrapper(ROW_FRAME_NODE, NODE_ID_0);
102 auto [newNode, newWrapper] = CreateNodeAndWrapper(FIRST_CHILD_FRAME_NODE, NODE_ID_1);
103 wrapper->Update(newNode, newWrapper->GetGeometryNode(), newNode->GetLayoutProperty());
104 EXPECT_EQ(wrapper->GetHostNode()->GetTag(), FIRST_CHILD_FRAME_NODE);
105 }
106
107 /**
108 * @tc.name: LayoutWrapperNodeTestNg002
109 * @tc.desc: Test AppendChild.
110 * @tc.type: FUNC
111 */
112 HWTEST_F(LayoutWrapperNodeTestNg, LayoutWrapperNodeTestNg002, TestSize.Level1)
113 {
114 auto [node, wrapper] = CreateNodeAndWrapper(ROW_FRAME_NODE, NODE_ID_0);
115 auto [child, childWrapper] = CreateNodeAndWrapper(FIRST_CHILD_FRAME_NODE, NODE_ID_1);
116
117 wrapper->AppendChild(childWrapper, true);
118 EXPECT_EQ(wrapper->overlayChild_->GetHostNode()->GetTag(), FIRST_CHILD_FRAME_NODE);
119 }
120
121 /**
122 * @tc.name: LayoutWrapperNodeTestNg003
123 * @tc.desc: Test GetAllChildrenWithBuild.
124 * @tc.type: FUNC
125 */
126 HWTEST_F(LayoutWrapperNodeTestNg, LayoutWrapperNodeTestNg003, TestSize.Level1)
127 {
128 auto [node, wrapper] = CreateNodeAndWrapper(ROW_FRAME_NODE, NODE_ID_0);
129 auto [child, childWrapper] = CreateNodeAndWrapper(FIRST_CHILD_FRAME_NODE, NODE_ID_1);
130 auto [child2, childWrapper2] = CreateNodeAndWrapper(SECOND_CHILD_FRAME_NODE, NODE_ID_2);
131 auto [child3, childWrapper3] = CreateNodeAndWrapper(THIRD_CHILD_FRAME_NODE, NODE_ID_3);
132
133 wrapper->AppendChild(childWrapper, false);
134 wrapper->AppendChild(childWrapper2, false);
135 wrapper->AppendChild(childWrapper3, true);
136 wrapper->GetAllChildrenWithBuild(true);
137
138 EXPECT_TRUE(wrapper->overlayChild_->IsActive());
139 }
140
141 /**
142 * @tc.name: LayoutWrapperNodeTestNg004
143 * @tc.desc: Test Layout.
144 * @tc.type: FUNC
145 */
146 HWTEST_F(LayoutWrapperNodeTestNg, LayoutWrapperNodeTestNg004, TestSize.Level1)
147 {
148 auto [node, wrapper] = CreateNodeAndWrapper(ROW_FRAME_NODE, NODE_ID_0);
149
150 auto layoutAlgorithmT = AceType::MakeRefPtr<LayoutAlgorithm>();
151 auto layoutAlgorithm = AceType::MakeRefPtr<LayoutAlgorithmWrapper>(layoutAlgorithmT, false, false);
152 wrapper->SetLayoutAlgorithm(layoutAlgorithm);
153
154 wrapper->Layout();
155 EXPECT_TRUE(wrapper->layoutProperty_->GetLayoutConstraint());
156
157 LayoutConstraintF layoutConstraint;
158 layoutConstraint.parentIdealSize = OptionalSizeF(768, 1024);
159 wrapper->layoutProperty_->UpdateLayoutConstraint(layoutConstraint);
160 EXPECT_EQ(wrapper->layoutProperty_->layoutConstraint_->parentIdealSize, OptionalSizeF(768, 1024));
161 }
162
163 /**
164 * @tc.name: LayoutWrapperNodeTestNg005
165 * @tc.desc: Test SetLongPredictTask.
166 * @tc.type: FUNC
167 */
168 HWTEST_F(LayoutWrapperNodeTestNg, LayoutWrapperNodeTestNg005, TestSize.Level1)
169 {
170 auto [node, wrapper] = CreateNodeAndWrapper(ROW_FRAME_NODE, NODE_ID_0);
171 wrapper->layoutWrapperBuilder_ = CreateWrapperBuilder();
172 EXPECT_TRUE(wrapper->layoutWrapperBuilder_);
173
174 wrapper->SetLongPredictTask();
175 EXPECT_TRUE(wrapper->layoutWrapperBuilder_->useLongPredictTask_);
176 }
177
178 /**
179 * @tc.name: LayoutWrapperNodeTestNg006
180 * @tc.desc: Test SwapDirtyLayoutWrapperOnMainThread.
181 * @tc.type: FUNC
182 */
183 HWTEST_F(LayoutWrapperNodeTestNg, LayoutWrapperNodeTestNg006, TestSize.Level1)
184 {
185 auto [child, childWrapper] = CreateNodeAndWrapper(FIRST_CHILD_FRAME_NODE, NODE_ID_1);
186 childWrapper->isActive_ = true;
187 childWrapper->layoutProperty_->gridProperty_ = std::make_unique<GridProperty>();
188 childWrapper->layoutProperty_->UpdateGridProperty(DEFAULT_GRID_SPAN, DEFAULT_GRID_OFFSET, GridSizeType::UNDEFINED);
189
190 auto [node, wrapper] = CreateNodeAndWrapper(ROW_FRAME_NODE, NODE_ID_0);
191 wrapper->AppendChild(childWrapper, true);
192 wrapper->isActive_ = true;
193 wrapper->SwapDirtyLayoutWrapperOnMainThread();
194 EXPECT_EQ(child->layoutProperty_->gridProperty_->GetOffset(), Dimension(0.0, DimensionUnit::PX));
195 }
196
197 /**
198 * @tc.name: LayoutWrapperNodeTestNg007
199 * @tc.desc: Test LayoutOverlay.
200 * @tc.type: FUNC
201 */
202 HWTEST_F(LayoutWrapperNodeTestNg, LayoutWrapperNodeTestNg007, TestSize.Level1)
203 {
204 auto [node, wrapper] = CreateNodeAndWrapper(ROW_FRAME_NODE, NODE_ID_0);
205 auto frameSize = SizeF(100, 200);
206 wrapper->geometryNode_->SetFrameSize(frameSize);
207
208 auto [child, childWrapper] = CreateNodeAndWrapper(FIRST_CHILD_FRAME_NODE, NODE_ID_1);
209 auto frameSizeChild = SizeF(50, 100);
210 childWrapper->geometryNode_->SetFrameSize(frameSizeChild);
211 childWrapper->layoutProperty_->overlayOffsetX_ = Dimension::FromString("1px");
212 childWrapper->layoutProperty_->overlayOffsetY_ = Dimension::FromString("1px");
213
214 wrapper->AppendChild(childWrapper, true);
215 wrapper->LayoutOverlay();
216 EXPECT_EQ(childWrapper->GetGeometryNode()->GetFrameRect().GetOffset(), OffsetF(1, 1));
217 }
218
219 /**
220 * @tc.name: LayoutWrapperNodeTestNg008
221 * @tc.desc: Test SwapDirtyLayoutWrapperOnMainThread child is an empty branch .
222 * @tc.type: FUNC
223 */
224 HWTEST_F(LayoutWrapperNodeTestNg, LayoutWrapperNodeTestNg008, TestSize.Level1)
225 {
226 /**
227 * @tc.steps: step1. Create frameNode.
228 */
229 RefPtr<FrameNode> frameNode = FrameNode::CreateFrameNode(ROW_FRAME_NODE, NODE_ID_0, AceType::MakeRefPtr<Pattern>());
230
231 /**
232 * @tc.steps: step2. Create geometryNode.
233 */
234 RefPtr<GeometryNode> geometryNode = AceType::MakeRefPtr<GeometryNode>();
235
236 /**
237 * @tc.steps: step3. Create layoutWrapper.
238 */
239 RefPtr<LayoutWrapperNode> layoutWrapper =
240 AceType::MakeRefPtr<LayoutWrapperNode>(frameNode, geometryNode, frameNode->GetLayoutProperty());
241
242 /**
243 * @tc.steps: step4. Call SwapDirtyLayoutWrapperOnMainThread.
244 * @tc.expected: child is an null.
245 */
246 layoutWrapper->AppendChild(nullptr, true);
247 layoutWrapper->isActive_ = true;
248 layoutWrapper->SwapDirtyLayoutWrapperOnMainThread();
249 RefPtr<LayoutWrapperNode> child = layoutWrapper->children_.front();
250 EXPECT_EQ(child, nullptr);
251 }
252
253 /**
254 * @tc.name: LayoutWrapperNodeTestNg009
255 * @tc.desc: Test SwapDirtyLayoutWrapperOnMainThreadForChild child is an empty branch .
256 * @tc.type: FUNC
257 */
258 HWTEST_F(LayoutWrapperNodeTestNg, LayoutWrapperNodeTestNg009, TestSize.Level1)
259 {
260 /**
261 * @tc.steps: step1. Create frameNode.
262 */
263 RefPtr<FrameNode> frameNode = FrameNode::CreateFrameNode(ROW_FRAME_NODE, NODE_ID_0, AceType::MakeRefPtr<Pattern>());
264
265 /**
266 * @tc.steps: step2. Create geometryNode.
267 */
268 RefPtr<GeometryNode> geometryNode = AceType::MakeRefPtr<GeometryNode>();
269
270 /**
271 * @tc.steps: step3. Create layoutWrapper.
272 */
273 RefPtr<LayoutWrapperNode> layoutWrapper =
274 AceType::MakeRefPtr<LayoutWrapperNode>(frameNode, geometryNode, frameNode->GetLayoutProperty());
275
276 /**
277 * @tc.steps: step4. Call SwapDirtyLayoutWrapperOnMainThreadForChild.
278 * @tc.expected: child is an null.
279 */
280 RefPtr<LayoutWrapperNode> child = nullptr;
281 layoutWrapper->SwapDirtyLayoutWrapperOnMainThreadForChild(child);
282 EXPECT_EQ(child, nullptr);
283 }
284
285 /**
286 * @tc.name: LayoutWrapperNodeTestNg010
287 * @tc.desc: Test SwapDirtyLayoutWrapperOnMainThreadForChild geometryTransition is not empty branch .
288 * @tc.type: FUNC
289 */
290 HWTEST_F(LayoutWrapperNodeTestNg, LayoutWrapperNodeTestNg010, TestSize.Level1)
291 {
292 /**
293 * @tc.steps: step1. Create frameNode.
294 */
295 RefPtr<FrameNode> frameNode = FrameNode::CreateFrameNode(ROW_FRAME_NODE, NODE_ID_0, AceType::MakeRefPtr<Pattern>());
296
297 /**
298 * @tc.steps: step2. Create geometryNode.
299 */
300 RefPtr<GeometryNode> geometryNode = AceType::MakeRefPtr<GeometryNode>();
301
302 /**
303 * @tc.steps: step3. Create GeometryTransition.
304 */
305 RefPtr<GeometryTransition> geometryTransition = AceType::MakeRefPtr<GeometryTransition>("test", true, true);
306 geometryTransition->state_ = GeometryTransition::State::ACTIVE;
307 geometryTransition->inNode_ = frameNode;
308 geometryTransition->outNode_ = frameNode;
309 geometryTransition->hasInAnim_ = true;
310
311 /**
312 * @tc.steps: step4. Create layoutWrapper.
313 */
314 RefPtr<LayoutWrapperNode> childWrapper =
315 AceType::MakeRefPtr<LayoutWrapperNode>(frameNode, geometryNode, frameNode->GetLayoutProperty());
316 childWrapper->layoutProperty_->geometryTransition_ = geometryTransition;
317 childWrapper->isActive_ = true;
318 childWrapper->layoutProperty_->UpdateGridProperty(DEFAULT_GRID_SPAN, DEFAULT_GRID_OFFSET, GridSizeType::UNDEFINED);
319
320 RefPtr<LayoutWrapperNode> wrapper =
321 AceType::MakeRefPtr<LayoutWrapperNode>(frameNode, geometryNode, frameNode->GetLayoutProperty());
322 wrapper->AppendChild(childWrapper, true);
323 wrapper->isActive_ = true;
324 wrapper->SwapDirtyLayoutWrapperOnMainThreadForChild(childWrapper);
325 }
326
327 /**
328 * @tc.name: LayoutWrapperNodeTestNg011
329 * @tc.desc: Test GetAllChildrenWithBuild .
330 * @tc.type: FUNC
331 */
332 HWTEST_F(LayoutWrapperNodeTestNg, LayoutWrapperNodeTestNg011, TestSize.Level1)
333 {
334 /**
335 * @tc.steps: step1. Create frameNode.
336 */
337 RefPtr<FrameNode> frameNode = FrameNode::CreateFrameNode(ROW_FRAME_NODE, NODE_ID_0, AceType::MakeRefPtr<Pattern>());
338
339 /**
340 * @tc.steps: step2. Create geometryNode.
341 */
342 RefPtr<GeometryNode> geometryNode = AceType::MakeRefPtr<GeometryNode>();
343
344 /**
345 * @tc.steps: step3. Create layoutWrapper.
346 */
347 RefPtr<LayoutWrapperNode> layoutWrapper =
348 AceType::MakeRefPtr<LayoutWrapperNode>(frameNode, geometryNode, frameNode->GetLayoutProperty());
349
350 /**
351 * @tc.steps: step4. Add Children.
352 * @tc.expected: Children add successful.
353 */
354 RefPtr<LayoutWrapperNode> layoutWrapper1 =
355 AceType::MakeRefPtr<LayoutWrapperNode>(frameNode, geometryNode, frameNode->GetLayoutProperty());
356 layoutWrapper->AppendChild(layoutWrapper1, false);
357 EXPECT_EQ(layoutWrapper->children_.size(), 1);
358
359 RefPtr<LayoutWrapperNode> layoutWrapper2 =
360 AceType::MakeRefPtr<LayoutWrapperNode>(frameNode, geometryNode, frameNode->GetLayoutProperty());
361 layoutWrapper->AppendChild(layoutWrapper2, false);
362 EXPECT_EQ(layoutWrapper->children_.size(), 2);
363
364 /**
365 * @tc.steps: step5. set overlayChild_.
366 * @tc.expected: overlayChild_ is not null.
367 */
368 RefPtr<LayoutWrapperNode> layoutWrapper3 =
369 AceType::MakeRefPtr<LayoutWrapperNode>(frameNode, geometryNode, frameNode->GetLayoutProperty());
370 layoutWrapper->AppendChild(layoutWrapper3, true);
371 EXPECT_EQ(layoutWrapper->children_.size(), 2);
372 EXPECT_TRUE(layoutWrapper->overlayChild_);
373
374 /**
375 * @tc.steps: step6. GetAllChildrenWithBuild.
376 * @tc.expected: cachedList_ is same with children.
377 */
378 layoutWrapper->overlayChild_->isActive_ = true;
379 layoutWrapper->GetAllChildrenWithBuild();
380 EXPECT_EQ(layoutWrapper->cachedList_.size(), layoutWrapper->children_.size());
381 }
382
383 /**
384 * @tc.name: LayoutWrapperNodeTestNg012
385 * @tc.desc: Test Measure .
386 * @tc.type: FUNC
387 */
388 HWTEST_F(LayoutWrapperNodeTestNg, LayoutWrapperNodeTestNg012, TestSize.Level1)
389 {
390 /**
391 * @tc.steps: step1. Create frameNode.
392 */
393 RefPtr<FrameNode> frameNode = FrameNode::CreateFrameNode(ROW_FRAME_NODE, NODE_ID_0, AceType::MakeRefPtr<Pattern>());
394 frameNode->layoutPriority_ = 1;
395
396 /**
397 * @tc.steps: step2. Create geometryNode.
398 */
399 RefPtr<GeometryNode> geometryNode = AceType::MakeRefPtr<GeometryNode>();
400
401 /**
402 * @tc.steps: step3. Create layoutWrapper.
403 */
404 RefPtr<LayoutWrapperNode> layoutWrapper =
405 AceType::MakeRefPtr<LayoutWrapperNode>(frameNode, geometryNode, frameNode->GetLayoutProperty());
406
407 /**
408 * @tc.steps: step4. Create LayoutAlgorithmWrapper.
409 * @tc.expected: layoutAlgorithm is not null.
410 */
411 auto layoutAlgorithmT = AceType::MakeRefPtr<LayoutAlgorithm>();
412 auto layoutAlgorithm = AceType::MakeRefPtr<LayoutAlgorithmWrapper>(layoutAlgorithmT, false, false);
413 layoutWrapper->layoutAlgorithm_ = layoutAlgorithm;
414 layoutAlgorithm->skipMeasure_ = false;
415
416 /**
417 * @tc.steps: step5. Create GeometryTransition.
418 */
419 RefPtr<FrameNode> frameNode1 =
420 FrameNode::CreateFrameNode(ROW_FRAME_NODE, NODE_ID_1, AceType::MakeRefPtr<Pattern>());
421 RefPtr<GeometryTransition> geometryTransition = AceType::MakeRefPtr<GeometryTransition>("test", true, true);
422 geometryTransition->state_ = GeometryTransition::State::ACTIVE;
423 geometryTransition->inNode_ = frameNode;
424 geometryTransition->outNode_ = frameNode1;
425 geometryTransition->hasInAnim_ = true;
426 layoutWrapper->layoutProperty_->geometryTransition_ = geometryTransition;
427
428 /**
429 * @tc.steps: step6. Create LayoutConstraintF and Call Measure.
430 * @tc.expected: IsRunning and IsNodeInAndActive is true.
431 */
432 layoutWrapper->SetRootMeasureNode();
433 EXPECT_TRUE(layoutWrapper->IsRootMeasureNode());
434 LayoutConstraintF parentLayoutConstraint;
435 layoutWrapper->Measure(parentLayoutConstraint);
436 EXPECT_TRUE(geometryTransition->IsRunning(layoutWrapper->GetHostNode()));
437 EXPECT_TRUE(geometryTransition->IsNodeInAndActive(layoutWrapper->GetHostNode()));
438
439 /**
440 * @tc.steps: step7. set overlayChild_.
441 * @tc.expected: IsRunning and IsNodeInAndActive is true.
442 */
443 RefPtr<LayoutWrapperNode> layoutWrapper1 =
444 AceType::MakeRefPtr<LayoutWrapperNode>(frameNode, geometryNode, frameNode->GetLayoutProperty());
445 layoutWrapper->overlayChild_ = layoutWrapper1;
446 layoutWrapper->Measure(parentLayoutConstraint);
447 EXPECT_TRUE(geometryTransition->IsRunning(layoutWrapper->GetHostNode()));
448 EXPECT_TRUE(geometryTransition->IsNodeInAndActive(layoutWrapper->GetHostNode()));
449 }
450 } // namespace OHOS::Ace::NG
451