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 #include "gtest/gtest.h"
16 
17 #define protected public
18 #define private public
19 
20 #include "test/mock/base/mock_task_executor.h"
21 #include "test/mock/core/common/mock_container.h"
22 #include "test/mock/core/pipeline/mock_pipeline_context.h"
23 
24 #include "core/components_ng/base/group_node.h"
25 #include "core/components_ng/base/view_stack_processor.h"
26 #include "core/components_ng/pattern/pattern.h"
27 #include "core/components_ng/pattern/root/root_pattern.h"
28 
29 using namespace testing;
30 using namespace testing::ext;
31 
32 namespace OHOS::Ace::NG {
33 namespace {
34 constexpr char TAG_ROOT[] = "root";
35 constexpr char TAG_CHILD[] = "child";
36 const auto MOCK_PATTERN_ROOT = AceType::MakeRefPtr<Pattern>();
37 const auto MOCK_PATTERN_CHILD = AceType::MakeRefPtr<Pattern>();
38 const auto PATTERN_ROOT = AceType::MakeRefPtr<Pattern>();
39 const auto FRAME_NODE_ROOT = FrameNode::CreateFrameNode(TAG_ROOT, 1, MOCK_PATTERN_ROOT, true);
40 const auto FRAME_NODE_CHILD = FrameNode::CreateFrameNode(TAG_CHILD, 2, MOCK_PATTERN_ROOT, false);
41 }; // namespace
42 
43 class ViewStackProcessorTestNg : public testing::Test {
44 public:
SetUpTestSuite()45     static void SetUpTestSuite()
46     {
47         MockPipelineContext::SetUp();
48         MockContainer::SetUp();
49         MockContainer::Current()->taskExecutor_ = AceType::MakeRefPtr<MockTaskExecutor>();
50         MockContainer::Current()->pipelineContext_ = MockPipelineContext::GetCurrentContext();
51         MockContainer::Current()->pipelineContext_->taskExecutor_ = MockContainer::Current()->taskExecutor_;
52     }
TearDownTestSuite()53     static void TearDownTestSuite()
54     {
55         MockPipelineContext::TearDown();
56         MockContainer::TearDown();
57     }
58 };
59 
60 /**
61  * @tc.name: ViewStackProcessorTestNg001
62  * @tc.desc: Test the operation of view stack processor
63  * @tc.type: FUNC
64  */
65 HWTEST_F(ViewStackProcessorTestNg, ViewStackProcessorTestNg001, TestSize.Level1)
66 {
67     /**
68      * @tc.steps: step1. push isCustomView = false
69      * @tc.expected: removeSilently_ is false
70      */
71     bool customViews[2] = { true, false };
72     for (int i = 0; i < 2; ++i) {
73         ViewStackProcessor::GetInstance()->Push(FRAME_NODE_ROOT, customViews[i]);
74         auto node = ViewStackProcessor::GetInstance()->Finish();
75         EXPECT_FALSE(node->removeSilently_);
76     }
77 }
78 
79 /**
80  * @tc.name: ViewStackProcessorTestNg002
81  * @tc.desc: Test the operation of view stack processor
82  * @tc.type: FUNC
83  */
84 HWTEST_F(ViewStackProcessorTestNg, ViewStackProcessorTestNg002, TestSize.Level1)
85 {
86     /**
87      * @tc.steps: step1. push childFrameNode
88      * @tc.expected: mainFrameNode's tag is child
89      */
90     ViewStackProcessor::GetInstance()->Push(FRAME_NODE_CHILD);
91     ViewStackProcessor::GetInstance()->Push(FRAME_NODE_ROOT);
92     ViewStackProcessor::GetInstance()->ImplicitPopBeforeContinue();
93     auto topFrameNodeOne = ViewStackProcessor::GetInstance()->GetMainElementNode();
94     EXPECT_EQ(strcmp(topFrameNodeOne->GetTag().c_str(), TAG_CHILD), 0);
95     /**
96      * @tc.steps: step2. ImplicitPopBeforeContinue
97      * @tc.expected: mainFrameNode's tag is child
98      */
99     ViewStackProcessor::GetInstance()->ImplicitPopBeforeContinue();
100     auto topFrameNodeTwo = ViewStackProcessor::GetInstance()->Finish();
101     EXPECT_EQ(strcmp(topFrameNodeTwo->GetTag().c_str(), TAG_CHILD), 0);
102 }
103 
104 /**
105  * @tc.name: ViewStackProcessorTestNg003
106  * @tc.desc: Test the operation of view stack processor
107  * @tc.type: FUNC
108  */
109 HWTEST_F(ViewStackProcessorTestNg, ViewStackProcessorTestNg003, TestSize.Level1)
110 {
111     /**
112      * @tc.steps: step1. ImplicitPopBeforeContinue
113      * @tc.expected: frameNode's isMeasureBoundary_ is false
114      */
115     ViewStackProcessor::GetInstance()->Push(FRAME_NODE_ROOT);
116     ViewStackProcessor::GetInstance()->FlushImplicitAnimation();
117     FRAME_NODE_ROOT->onMainTree_ = true;
118     ViewStackProcessor::GetInstance()->FlushImplicitAnimation();
119     ViewStackProcessor::GetInstance()->FlushRerenderTask();
120     ViewStackProcessor::GetInstance()->Push(FRAME_NODE_ROOT);
121     ViewStackProcessor::GetInstance()->FlushRerenderTask();
122     ViewStackProcessor::GetInstance()->FlushRerenderTask();
123     EXPECT_FALSE(FRAME_NODE_ROOT->isMeasureBoundary_);
124 }
125 
126 /**
127  * @tc.name: ViewStackProcessorTestNg004
128  * @tc.desc: Test the operation of view stack processor
129  * @tc.type: FUNC
130  */
131 HWTEST_F(ViewStackProcessorTestNg, ViewStackProcessorTestNg004, TestSize.Level1)
132 {
133     /**
134      * @tc.steps: step1. push key one and two
135      * @tc.expected: GetKey is "one_two"
136      */
137     const std::string keyOne("one");
138     const std::string keyTwo("two");
139     ViewStackProcessor::GetInstance()->PushKey(keyOne);
140     ViewStackProcessor::GetInstance()->PushKey(keyTwo);
141     EXPECT_EQ(strcmp(ViewStackProcessor::GetInstance()->GetKey().c_str(), "one_two"), 0);
142     /**
143      * @tc.steps: step2. pop key one and two
144      * @tc.expected: GetKey is ""
145      */
146     ViewStackProcessor::GetInstance()->PopKey();
147     ViewStackProcessor::GetInstance()->PopKey();
148     EXPECT_EQ(strcmp(ViewStackProcessor::GetInstance()->GetKey().c_str(), ""), 0);
149     ViewStackProcessor::GetInstance()->ProcessViewId("three");
150     EXPECT_EQ(strcmp(ViewStackProcessor::GetInstance()->GetKey().c_str(), ""), 0);
151     /**
152      * @tc.steps: step3. push a empty key and do pop key
153      * @tc.expected: GetKey is ""
154      */
155     ViewStackProcessor::GetInstance()->PushKey("");
156     ViewStackProcessor::GetInstance()->PopKey();
157     EXPECT_EQ(strcmp(ViewStackProcessor::GetInstance()->GetKey().c_str(), ""), 0);
158     /**
159      * @tc.steps: step4. create ScopedViewStackProcessor
160      * @tc.expected: not nullptr
161      */
162     auto scoped = std::make_shared<ScopedViewStackProcessor>();
163     EXPECT_NE(scoped->instance_, nullptr);
164     scoped = nullptr;
165 }
166 
167 /**
168  * @tc.name: ViewStackProcessorTestNg005
169  * @tc.desc: Test the SetVisualState and GetVisualState in view stack processor
170  * @tc.type: FUNC
171  */
172 HWTEST_F(ViewStackProcessorTestNg, ViewStackProcessorTestNg005, TestSize.Level1)
173 {
174     /**
175      * @tc.steps: step1. get instance and set different states and show result
176      * @tc.expected: GetVisualState value meeting expectations.
177      */
178     auto instance = ViewStackProcessor::GetInstance();
179     instance->SetVisualState(VisualState::DISABLED);
180     EXPECT_EQ(instance->GetVisualState(), 4);
181     instance->SetVisualState(VisualState::FOCUSED);
182     EXPECT_EQ(instance->GetVisualState(), 2);
183     instance->SetVisualState(VisualState::PRESSED);
184     EXPECT_EQ(instance->GetVisualState(), 1);
185     instance->SetVisualState(VisualState::NORMAL);
186     EXPECT_EQ(instance->GetVisualState(), 0);
187     instance->SetVisualState(VisualState::HOVER);
188     EXPECT_EQ(instance->GetVisualState(), 0);
189     /**
190      * @tc.steps: step2. clear visual state
191      * @tc.expected: IsCurrentVisualStateProcess meeting expectations.
192      */
193     EXPECT_FALSE(instance->IsCurrentVisualStateProcess());
194     instance->ClearVisualState();
195     EXPECT_TRUE(instance->IsCurrentVisualStateProcess());
196 }
197 
198 /**
199  * @tc.name: ViewStackProcessorTestNg006
200  * @tc.desc: Test the Push and PopContainer in view stack processor
201  * @tc.type: FUNC
202  */
203 HWTEST_F(ViewStackProcessorTestNg, ViewStackProcessorTestNg006, TestSize.Level1)
204 {
205     /**
206      * @tc.steps: step1. Get instance and try PopContainer
207      * @tc.expected: actually nothing happened because elementsStack no value.
208      */
209     auto instance = ViewStackProcessor::GetInstance();
210     instance->PopContainer();
211     EXPECT_EQ(instance->elementsStack_.size(), 0);
212     /**
213      * @tc.steps: step2. Create some node
214      */
215     auto pipe = MockPipelineContext::GetCurrent();
216     const auto root = FrameNode::CreateFrameNode(TAG_CHILD, 0, AceType::MakeRefPtr<RootPattern>(), true);
217     const auto child = FrameNode::CreateFrameNode(TAG_CHILD, 3, AceType::MakeRefPtr<RootPattern>(), true);
218     const auto child2 = FrameNode::CreateFrameNode(TAG_CHILD, 4, AceType::MakeRefPtr<Pattern>(), true);
219     root->context_ = AceType::RawPtr(pipe);
220     child->context_ = AceType::RawPtr(pipe);
221     child2->context_ = AceType::RawPtr(pipe);
222     /**
223      * @tc.steps: step3. Push root into container
224      * @tc.expected: Pop failed elementsStack_ size still 1.
225      */
226     instance->Push(root);
227     instance->PopContainer();
228     EXPECT_EQ(instance->elementsStack_.size(), 1);
229     /**
230      * @tc.steps: step4. pop root and put FRAME_NODE_ROOT into container
231      * @tc.expected: Pop failed elementsStack_ size still 1.
232      */
233     FRAME_NODE_ROOT->context_ = AceType::RawPtr(pipe);
234     instance->elementsStack_.pop();
235     instance->Push(FRAME_NODE_ROOT);
236     instance->PopContainer();
237     EXPECT_EQ(instance->elementsStack_.size(), 1);
238     /**
239      * @tc.steps: step5. push child2 and child into instance
240      * @tc.expected: Pop success elementsStack_ size residue 1.
241      */
242     instance->Push(child2);
243     instance->Push(child);
244     instance->ImplicitPopBeforeContinue();
245     EXPECT_EQ(instance->elementsStack_.size(), 2);
246     instance->PopContainer();
247     EXPECT_EQ(instance->elementsStack_.size(), 1);
248     /**
249      * @tc.steps: step6. push child2 again
250      * @tc.expected: Pop success elementsStack_ size residue 1.
251      */
252     instance->Push(child2);
253     instance->PopContainer();
254     EXPECT_EQ(instance->elementsStack_.size(), 1);
255 }
256 } // namespace OHOS::Ace::NG
257