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