1 /*
2  * Copyright (c) 2022 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 <cstddef>
17 
18 #include "gtest/gtest.h"
19 
20 #include "core/components_ng/base/view_stack_processor.h"
21 #include "core/components_ng/pattern/pattern.h"
22 #include "core/components_ng/syntax/if_else_model_ng.h"
23 #include "core/components_v2/inspector/inspector_constants.h"
24 
25 #define private public
26 #include "core/components_ng/syntax/if_else_node.h"
27 #include "test/mock/core/pipeline/mock_pipeline_context.h"
28 
29 using namespace testing;
30 using namespace testing::ext;
31 
32 namespace OHOS::Ace::NG {
33 namespace {
34 constexpr int32_t IF_ELSE_BRANCH_ID = 1;
35 constexpr int32_t IF_ELSE_BRANCH_ID_2 = 2;
36 constexpr int32_t IF_ELSE_CHILDREN_COUNT = 1;
37 constexpr int32_t IF_ELSE_CHILDREN_COUNT_2 = 0;
38 constexpr int32_t IF_ELSE_NODE_ID = 1;
39 std::list<int32_t> removedElmtIds;
40 constexpr bool IS_ATOMIC_NODE = false;
41 } // namespace
42 
43 class IfElseSyntaxTestNg : public testing::Test {
44 public:
45     static void SetUpTestSuite();
46     static void TearDownTestSuite();
47     void SetUp() override;
48     void TearDown() override;
49 };
50 
SetUpTestSuite()51 void IfElseSyntaxTestNg::SetUpTestSuite()
52 {
53     GTEST_LOG_(INFO) << "IfElseSyntaxTestNg SetUpTestCase";
54 }
55 
TearDownTestSuite()56 void IfElseSyntaxTestNg::TearDownTestSuite()
57 {
58     GTEST_LOG_(INFO) << "IfElseSyntaxTestNg TearDownTestCase";
59 }
60 
SetUp()61 void IfElseSyntaxTestNg::SetUp()
62 {
63     MockPipelineContext::SetUp();
64 }
65 
TearDown()66 void IfElseSyntaxTestNg::TearDown()
67 {
68     MockPipelineContext::TearDown();
69 }
70 
71 /**
72  * @tc.name: IfElseSyntaxCreateTest001
73  * @tc.desc: Create IfElse.
74  * @tc.type: FUNC
75  */
76 HWTEST_F(IfElseSyntaxTestNg, IfElseSyntaxTest001, TestSize.Level1)
77 {
78     IfElseModelNG ifElse;
79     ifElse.Create();
80     auto ifElseNodeNode = AceType::DynamicCast<IfElseNode>(ViewStackProcessor::GetInstance()->Finish());
81     EXPECT_TRUE(ifElseNodeNode != nullptr && ifElseNodeNode->GetTag() == V2::JS_IF_ELSE_ETS_TAG);
82 }
83 
84 /**
85  * @tc.name: IfElseSyntaxPopTest002
86  * @tc.desc: Create IfElse and pop it.
87  * @tc.type: FUNC
88  */
89 HWTEST_F(IfElseSyntaxTestNg, IfElseSyntaxTest002, TestSize.Level1)
90 {
91     IfElseModelNG ifElse;
92     ifElse.Create();
93     ifElse.Pop();
94     // ViewStackProcessor will not pop when it's size equals 1.
95     EXPECT_FALSE(ViewStackProcessor::GetInstance()->GetMainElementNode() == nullptr);
96 }
97 
98 /**
99  * @tc.name: IfElseSyntaxBranchIDTest003
100  * @tc.desc: Create IfElse and set/get branchId.
101  * @tc.type: FUNC
102  */
103 HWTEST_F(IfElseSyntaxTestNg, IfElseSyntaxBranchIDTest003, TestSize.Level1)
104 {
105     IfElseModelNG ifElse;
106     ifElse.Create();
107     ifElse.SetBranchId(IF_ELSE_BRANCH_ID, removedElmtIds);
108 
109     EXPECT_EQ(ifElse.GetBranchId(), IF_ELSE_BRANCH_ID);
110     auto ifElseNodeNode = AceType::DynamicCast<IfElseNode>(ViewStackProcessor::GetInstance()->Finish());
111     EXPECT_TRUE(ifElseNodeNode != nullptr && ifElseNodeNode->GetTag() == V2::JS_IF_ELSE_ETS_TAG);
112     EXPECT_EQ(ifElseNodeNode->GetBranchId(), IF_ELSE_BRANCH_ID);
113 
114     /**
115     // corresponding ets code:
116     //     if () {
117     //       Blank()
118     //     }
119     */
120     auto childFrameNode = FrameNode::CreateFrameNode(V2::BLANK_ETS_TAG, 1, AceType::MakeRefPtr<Pattern>());
121     ifElseNodeNode->AddChild(childFrameNode);
122     EXPECT_EQ(ifElseNodeNode->GetChildren().size(), IF_ELSE_CHILDREN_COUNT);
123     // ifElse node will clean its children when its branch id has changed.
124     ifElseNodeNode->SetBranchId(IF_ELSE_BRANCH_ID_2, removedElmtIds);
125     ifElseNodeNode->FlushUpdateAndMarkDirty();
126     EXPECT_EQ(ifElseNodeNode->GetChildren().size(), IF_ELSE_CHILDREN_COUNT_2);
127 
128     /**
129      * @tc.steps: step1. Set branch id which is same as before.
130      * @tc.expected: OnDirtyLayoutWrapperSwap return the true only when the canvas images all have been initialized.
131      */
132     ifElseNodeNode->SetBranchId(IF_ELSE_BRANCH_ID, removedElmtIds);
133     ifElseNodeNode->FlushUpdateAndMarkDirty();
134     EXPECT_FALSE(ifElseNodeNode->branchIdChanged_);
135 }
136 
137 /**
138  * @tc.name: IfElseSyntaxTest004
139  * @tc.desc: Create IfElse and invoke IsAtomicNode.
140  * @tc.type: FUNC
141  */
142 HWTEST_F(IfElseSyntaxTestNg, IfElseSyntaxTest004, TestSize.Level1)
143 {
144     IfElseModelNG ifElse;
145     ifElse.Create();
146     ifElse.SetBranchId(IF_ELSE_BRANCH_ID, removedElmtIds);
147 
148     auto ifElseNodeNode = AceType::DynamicCast<IfElseNode>(ViewStackProcessor::GetInstance()->Finish());
149     EXPECT_TRUE(ifElseNodeNode != nullptr && ifElseNodeNode->GetTag() == V2::JS_IF_ELSE_ETS_TAG);
150     EXPECT_EQ(ifElseNodeNode->IsAtomicNode(), IS_ATOMIC_NODE);
151 }
152 
153 /**
154  * @tc.name: IfElseSyntaxBranchIDTest005
155  * @tc.desc: Create IfElse and set/get branchId in abnormal condition.
156  * @tc.type: FUNC
157  */
158 HWTEST_F(IfElseSyntaxTestNg, IfElseSyntaxBranchIDTest005, TestSize.Level1)
159 {
160     IfElseModelNG ifElse;
161     ifElse.Create();
162     ifElse.SetBranchId(IF_ELSE_BRANCH_ID, removedElmtIds);
163 
164     EXPECT_EQ(ifElse.GetBranchId(), IF_ELSE_BRANCH_ID);
165     auto ifElseNodeNode = AceType::DynamicCast<IfElseNode>(ViewStackProcessor::GetInstance()->Finish());
166     EXPECT_TRUE(ifElseNodeNode != nullptr && ifElseNodeNode->GetTag() == V2::JS_IF_ELSE_ETS_TAG);
167     EXPECT_EQ(ifElseNodeNode->GetBranchId(), IF_ELSE_BRANCH_ID);
168 
169     /**
170     // corresponding ets code:
171     //     if () {
172     //       Blank()
173     //     }
174     */
175     auto childFrameNode = FrameNode::CreateFrameNode(V2::BLANK_ETS_TAG, 1, AceType::MakeRefPtr<Pattern>());
176     ifElseNodeNode->AddChild(childFrameNode);
177     EXPECT_EQ(ifElseNodeNode->GetChildren().size(), IF_ELSE_CHILDREN_COUNT);
178     // ifElse node will clean its children when its branch id has changed.
179     ifElseNodeNode->SetBranchId(IF_ELSE_BRANCH_ID_2, removedElmtIds);
180     ifElseNodeNode->FlushUpdateAndMarkDirty();
181     EXPECT_EQ(ifElseNodeNode->GetChildren().size(), IF_ELSE_CHILDREN_COUNT_2);
182 
183     /**
184      * @tc.steps: step1. Set branch id which is same as before.
185      * @tc.expected: OnDirtyLayoutWrapperSwap return the true only when the canvas images all have been initialized.
186      */
187     ifElseNodeNode->SetBranchId(IF_ELSE_BRANCH_ID_2, removedElmtIds);
188     ifElseNodeNode->FlushUpdateAndMarkDirty();
189     EXPECT_FALSE(ifElseNodeNode->branchIdChanged_);
190 }
191 
192 /**
193  * @tc.name: IfElseSyntaxCreateTest006
194  * @tc.desc: Create IfElse with same id.
195  * @tc.type: FUNC
196  */
197 HWTEST_F(IfElseSyntaxTestNg, IfElseSyntaxTest006, TestSize.Level1)
198 {
199     auto ifElseNode = IfElseNode::GetOrCreateIfElseNode(IF_ELSE_NODE_ID);
200     auto anotherIfElseNode = IfElseNode::GetOrCreateIfElseNode(IF_ELSE_NODE_ID);
201     EXPECT_TRUE(ifElseNode == anotherIfElseNode);
202 }
203 
204 /**
205  * @tc.name: IfElseSyntaxCreateTest007
206  * @tc.desc: Test TryRetake function.
207  * @tc.type: FUNC
208  */
209 HWTEST_F(IfElseSyntaxTestNg, IfElseSyntaxTest007, TestSize.Level1)
210 {
211     /**
212      * @tc.steps: step1. Add a node whose id is "node1" to the disappearingChildren of ifElseNode.
213      */
214     auto ifElseNode = IfElseNode::GetOrCreateIfElseNode(IF_ELSE_NODE_ID);
215     ASSERT_NE(ifElseNode, nullptr);
216     auto frameNode = FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG, -1, AceType::MakeRefPtr<Pattern>());
217     ASSERT_NE(frameNode, nullptr);
218     ASSERT_NE(frameNode->GetLayoutProperty(), nullptr);
219     frameNode->UpdateInspectorId("node1");
220     auto frameNode2 = FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG, -1, AceType::MakeRefPtr<Pattern>());
221     ASSERT_NE(frameNode2, nullptr);
222     ASSERT_NE(frameNode2->GetLayoutProperty(), nullptr);
223     frameNode2->UpdateInspectorId("node2");
224     ifElseNode->branchId_ = 0;
225     ifElseNode->AddDisappearingChild(frameNode, -1, 0);
226     ifElseNode->branchId_ = 1;
227     ifElseNode->AddDisappearingChild(frameNode2, -1, 1);
228 
229     /**
230      * @tc.steps: step2. IfElse is branch 0 again. Try to reuse "node1".
231      * @tc.expected: node1 can be reused, return value is true.
232      */
233     ifElseNode->branchId_ = 0;
234     bool result1 = ifElseNode->TryRetake("node1");
235     EXPECT_TRUE(result1);
236     EXPECT_TRUE(ifElseNode->GetChildren().size() == 1 && ifElseNode->GetChildAtIndex(0) == frameNode);
237 
238     /**
239      * @tc.steps: step3. Try to reuse "node10".
240      * @tc.expected: node10 is not in disappearingChildren so it can't be reused, return value is false.
241      */
242     bool result2 = ifElseNode->TryRetake("node10");
243     EXPECT_FALSE(result2);
244 
245     /**
246      * @tc.steps: step4. Try to reuse "node2".
247      * @tc.expected: node2 branch is not same with branchId of ifElse, return value is false.
248      */
249     bool result3 = ifElseNode->TryRetake("node2");
250     EXPECT_FALSE(result3);
251 }
252 } // namespace OHOS::Ace::NG
253