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 16 #include "gtest/gtest.h" 17 18 #define private public 19 #define protected public 20 #include "interfaces/inner_api/ace_kit/src/view/ui_context_impl.h" 21 #include "test/mock/core/common/mock_frontend.h" 22 #include "test/mock/core/pipeline/mock_pipeline_context.h" 23 24 #include "core/common/builder_util.h" 25 #include "core/components_ng/base/frame_node.h" 26 #include "core/components_ng/pattern/pattern.h" 27 28 using namespace testing; 29 using namespace testing::ext; 30 31 namespace OHOS::Ace { 32 namespace { 33 const std::string TEST_NODE_TAG = "TestNode"; 34 static int32_t UNIQUED_ID_OF_TEST_NODE = 0; 35 } // namespace 36 // namespace 37 class BuilderUtilsTest : public testing::Test { 38 public: SetUpTestCase()39 static void SetUpTestCase() {} TearDownTestCase()40 static void TearDownTestCase() {} SetUp()41 void SetUp() {} TearDown()42 void TearDown() {} 43 }; 44 45 /** 46 * @tc.name: BuilderUtilsTest001 47 * @tc.desc: Test Func of IsBuilderRootNode and IsBuilderContainer. 48 * @tc.type: FUNC 49 */ 50 HWTEST_F(BuilderUtilsTest, BuilderUtilsTest001, TestSize.Level1) 51 { 52 /** 53 * @tc.steps: step1. Create an UINode. 54 * @tc.expected: step1. The return value is not null. 55 */ 56 auto firstNode = NG::FrameNode::GetOrCreateFrameNode( __anonefe3979e0202() 57 TEST_NODE_TAG, UNIQUED_ID_OF_TEST_NODE++, []() { return AceType::MakeRefPtr<NG::Pattern>(); }); 58 EXPECT_NE(firstNode, nullptr); 59 auto contentSlot = NG::FrameNode::GetOrCreateFrameNode( __anonefe3979e0302() 60 V2::JS_NODE_SLOT_ETS_TAG, UNIQUED_ID_OF_TEST_NODE++, []() { return AceType::MakeRefPtr<NG::Pattern>(); }); 61 EXPECT_NE(contentSlot, nullptr); 62 auto nodeContainer = NG::FrameNode::GetOrCreateFrameNode( __anonefe3979e0402() 63 V2::NODE_CONTAINER_ETS_TAG, UNIQUED_ID_OF_TEST_NODE++, []() { return AceType::MakeRefPtr<NG::Pattern>(); }); 64 EXPECT_NE(nodeContainer, nullptr); 65 /** 66 * @tc.steps: step2. Call IsBuilderRootNode and send nullptr. 67 * @tc.expected: step2. The return value as false. 68 */ 69 EXPECT_FALSE(BuilderUtils::IsBuilderRootNode(nullptr)); 70 /** 71 * @tc.steps: step3. Call IsBuilderRootNode and send firstNode. 72 * @tc.expected: step3. The return value as false. 73 */ 74 EXPECT_FALSE(BuilderUtils::IsBuilderRootNode(firstNode)); 75 /** 76 * @tc.steps: step4. SetJsBuilderNodeId to firstNode and Call IsBuilderRootNode again. 77 * @tc.expected: step4. The return value as true. 78 */ 79 firstNode->SetJsBuilderNodeId(firstNode->GetId()); 80 EXPECT_TRUE(BuilderUtils::IsBuilderRootNode(firstNode)); 81 82 /** 83 * @tc.steps: step4. IsBuilderContainer to firstNode. 84 * @tc.expected: step4. The return value as false. 85 */ 86 EXPECT_FALSE(BuilderUtils::IsBuilderContainer(firstNode)); 87 EXPECT_TRUE(BuilderUtils::IsBuilderContainer(contentSlot) && BuilderUtils::IsBuilderContainer(nodeContainer)); 88 } 89 90 /** 91 * @tc.name: BuilderUtilsTest002 92 * @tc.desc: Test GetBuilderNodes. 93 * @tc.type: FUNC 94 */ 95 HWTEST_F(BuilderUtilsTest, BuilderUtilsTest002, TestSize.Level1) 96 { 97 /** 98 * @tc.steps: step1. Create some UINode. And Set Second Node as BuilderRootNode; 99 * @tc.expected: step1. The return value is not null. 100 */ 101 auto firstNode = NG::FrameNode::GetOrCreateFrameNode( __anonefe3979e0502() 102 TEST_NODE_TAG, UNIQUED_ID_OF_TEST_NODE++, []() { return AceType::MakeRefPtr<NG::Pattern>(); }); 103 EXPECT_NE(firstNode, nullptr); 104 auto secondedNode = NG::FrameNode::GetOrCreateFrameNode( __anonefe3979e0602() 105 TEST_NODE_TAG, UNIQUED_ID_OF_TEST_NODE++, []() { return AceType::MakeRefPtr<NG::Pattern>(); }); 106 EXPECT_NE(secondedNode, nullptr); 107 auto thirdNode = NG::FrameNode::GetOrCreateFrameNode( __anonefe3979e0702() 108 TEST_NODE_TAG, UNIQUED_ID_OF_TEST_NODE++, []() { return AceType::MakeRefPtr<NG::Pattern>(); }); 109 EXPECT_NE(thirdNode, nullptr); 110 auto forthNode = NG::FrameNode::GetOrCreateFrameNode( __anonefe3979e0802() 111 TEST_NODE_TAG, UNIQUED_ID_OF_TEST_NODE++, []() { return AceType::MakeRefPtr<NG::Pattern>(); }); 112 EXPECT_NE(forthNode, nullptr); 113 auto fifthNode = NG::FrameNode::GetOrCreateFrameNode( __anonefe3979e0902() 114 TEST_NODE_TAG, UNIQUED_ID_OF_TEST_NODE++, []() { return AceType::MakeRefPtr<NG::Pattern>(); }); 115 EXPECT_NE(fifthNode, nullptr); 116 117 /** 118 * @tc.steps: step2. Make a tree by the previous Node. 119 *├─ firstNode 120 *│ ├─ secondedNode (true) 121 *│ │ └─ thirdNode (true) 122 *│ ├─ forthNode (true) 123 *| └─ fifthNode 124 */ 125 firstNode->AddChild(secondedNode); 126 secondedNode->AddChild(thirdNode); 127 firstNode->AddChild(forthNode); 128 firstNode->AddChild(fifthNode); 129 secondedNode->SetJsBuilderNodeId(firstNode->GetId()); 130 thirdNode->SetJsBuilderNodeId(secondedNode->GetId()); 131 forthNode->SetJsBuilderNodeId(firstNode->GetId()); 132 133 /** 134 * @tc.steps: step3. Call GetBuilderNodes. 135 * @tc.expected: step3. Get the true count of those node. 136 */ 137 std::list<RefPtr<NG::UINode>> nodes; 138 BuilderUtils::GetBuilderNodes(nullptr, nodes); 139 EXPECT_TRUE(nodes.empty()); 140 BuilderUtils::GetBuilderNodes(firstNode, nodes); 141 EXPECT_EQ(nodes.size(), 2); 142 nodes.clear(); 143 BuilderUtils::GetBuilderNodes(secondedNode, nodes); 144 EXPECT_EQ(nodes.size(), 1); 145 nodes.clear(); 146 BuilderUtils::GetBuilderNodes(thirdNode, nodes); 147 EXPECT_EQ(nodes.size(), 1); 148 nodes.clear(); 149 BuilderUtils::GetBuilderNodes(forthNode, nodes); 150 EXPECT_EQ(nodes.size(), 1); 151 nodes.clear(); 152 BuilderUtils::GetBuilderNodes(fifthNode, nodes); 153 EXPECT_TRUE(nodes.empty()); 154 155 /** 156 * @tc.steps: step4. Call GetBuilderNodes when contains CNode. 157 * @tc.expected: step4. Get the true count of those node. 158 */ 159 nodes.clear(); 160 secondedNode->SetJsBuilderNodeId(-1); 161 secondedNode->setIsCNode(true); 162 BuilderUtils::GetBuilderNodes(firstNode, nodes); 163 EXPECT_EQ(nodes.size(), 1); 164 } 165 166 /** 167 * @tc.name: BuilderUtilsTest003 168 * @tc.desc: Test ClearChildInBuilderContainer. 169 * @tc.type: FUNC 170 */ 171 HWTEST_F(BuilderUtilsTest, BuilderUtilsTest003, TestSize.Level1) 172 { 173 /** 174 * @tc.steps: step1. Create some UINode. And Set Second Node as BuilderRootNode; 175 * @tc.expected: step1. The return value is not null. 176 */ 177 auto firstNode = NG::FrameNode::GetOrCreateFrameNode( __anonefe3979e0a02() 178 V2::JS_NODE_SLOT_ETS_TAG, UNIQUED_ID_OF_TEST_NODE++, []() { return AceType::MakeRefPtr<NG::Pattern>(); }); 179 EXPECT_NE(firstNode, nullptr); 180 auto secondedNode = NG::FrameNode::GetOrCreateFrameNode( __anonefe3979e0b02() 181 TEST_NODE_TAG, UNIQUED_ID_OF_TEST_NODE++, []() { return AceType::MakeRefPtr<NG::Pattern>(); }); 182 EXPECT_NE(secondedNode, nullptr); 183 auto thirdNode = NG::FrameNode::GetOrCreateFrameNode( __anonefe3979e0c02() 184 TEST_NODE_TAG, UNIQUED_ID_OF_TEST_NODE++, []() { return AceType::MakeRefPtr<NG::Pattern>(); }); 185 EXPECT_NE(thirdNode, nullptr); 186 auto forthNode = NG::FrameNode::GetOrCreateFrameNode( __anonefe3979e0d02() 187 TEST_NODE_TAG, UNIQUED_ID_OF_TEST_NODE++, []() { return AceType::MakeRefPtr<NG::Pattern>(); }); 188 EXPECT_NE(forthNode, nullptr); 189 auto fifthNode = NG::FrameNode::GetOrCreateFrameNode( __anonefe3979e0e02() 190 TEST_NODE_TAG, UNIQUED_ID_OF_TEST_NODE++, []() { return AceType::MakeRefPtr<NG::Pattern>(); }); 191 EXPECT_NE(fifthNode, nullptr); 192 193 /** 194 * @tc.steps: step2. Make a tree by the previous Node. 195 *├─ firstNode 196 *│ ├─ secondedNode (true) 197 *│ │ └─ thirdNode (true) 198 *│ ├─ forthNode (true) 199 *| └─ fifthNode 200 */ 201 firstNode->AddChild(secondedNode); 202 secondedNode->AddChild(thirdNode); 203 firstNode->AddChild(forthNode); 204 firstNode->AddChild(fifthNode); 205 secondedNode->SetJsBuilderNodeId(firstNode->GetId()); 206 thirdNode->SetJsBuilderNodeId(secondedNode->GetId()); 207 forthNode->SetJsBuilderNodeId(firstNode->GetId()); 208 209 auto context = AceType::MakeRefPtr<NG::MockPipelineContext>(); 210 EXPECT_NE(context, nullptr); 211 firstNode->context_ = AceType::RawPtr(context); 212 secondedNode->context_ = AceType::RawPtr(context); 213 thirdNode->context_ = AceType::RawPtr(context); 214 forthNode->context_ = AceType::RawPtr(context); 215 fifthNode->context_ = AceType::RawPtr(context); 216 auto frontend = AceType::MakeRefPtr<MockFrontend>(); 217 context->weakFrontend_ = AceType::WeakClaim(AceType::RawPtr(frontend)); 218 219 /** 220 * @tc.steps: step3. Call ClearChildInBuilderContainer. 221 * @tc.expected: step3. Call BuilderNodeFunc with "__deleteBuilderNode__". 222 */ 223 std::list<RefPtr<NG::UINode>> nodes; 224 BuilderUtils::ClearChildInBuilderContainer(UNIQUED_ID_OF_TEST_NODE, nodes); 225 BuilderUtils::GetBuilderNodes(firstNode, nodes); 226 EXPECT_EQ(nodes.size(), 2); 227 EXPECT_CALL(*frontend, BuilderNodeFunc("__deleteBuilderNode__", _)).Times(1); 228 BuilderUtils::ClearChildInBuilderContainer(firstNode->GetId(), nodes); 229 230 /** 231 * @tc.steps: step4. Call AddBuilderToParent. 232 * @tc.expected: step4. Call BuilderNodeFunc with "__deleteBuilderNode__". 233 */ 234 EXPECT_CALL(*frontend, BuilderNodeFunc("__addBuilderNodeToBuilder__", _)).Times(1); 235 BuilderUtils::AddBuilderToParent(secondedNode, thirdNode); 236 EXPECT_CALL(*frontend, BuilderNodeFunc("__addBuilderNode__", _)).Times(1); 237 BuilderUtils::AddBuilderToParent(firstNode, secondedNode); 238 239 /** 240 * @tc.steps: step4. Call AddBuilderToParent. 241 * @tc.expected: step4. Call BuilderNodeFunc with "__deleteBuilderNode__". 242 */ 243 EXPECT_CALL(*frontend, BuilderNodeFunc("__deleteBuilderNodeFromBuilder__", _)).Times(1); 244 BuilderUtils::RemoveBuilderFromParent(secondedNode, thirdNode); 245 EXPECT_CALL(*frontend, BuilderNodeFunc("__deleteBuilderNode__", _)).Times(1); 246 BuilderUtils::RemoveBuilderFromParent(firstNode, secondedNode); 247 248 /** 249 * @tc.steps: step5. Call AddBuilderToParent or RemoveBuilderFromParent with C Node. 250 */ 251 secondedNode->setIsCNode(true); 252 EXPECT_CALL(*frontend, BuilderNodeFunc("__addBuilderNode__", _)).Times(0); 253 EXPECT_CALL(*frontend, BuilderNodeFunc("__addBuilderNodeToBuilder__", _)).Times(0); 254 BuilderUtils::AddBuilderToParent(secondedNode, thirdNode); 255 BuilderUtils::AddBuilderToParent(nullptr, thirdNode); 256 BuilderUtils::AddBuilderToParent(nullptr, nullptr); 257 BuilderUtils::AddBuilderToParent(secondedNode, nullptr); 258 259 EXPECT_CALL(*frontend, BuilderNodeFunc("__deleteBuilderNodeFromBuilder__", _)).Times(0); 260 EXPECT_CALL(*frontend, BuilderNodeFunc("__deleteBuilderNode__", _)).Times(0); 261 BuilderUtils::RemoveBuilderFromParent(secondedNode, thirdNode); 262 BuilderUtils::RemoveBuilderFromParent(nullptr, thirdNode); 263 BuilderUtils::RemoveBuilderFromParent(nullptr, nullptr); 264 BuilderUtils::RemoveBuilderFromParent(secondedNode, nullptr); 265 } 266 267 /** 268 * @tc.name: BuilderUtilsTest004 269 * @tc.desc: Test when the Tree does not contains valid parent. 270 * @tc.type: FUNC 271 */ 272 HWTEST_F(BuilderUtilsTest, BuilderUtilsTest004, TestSize.Level1) 273 { 274 /** 275 * @tc.steps: step1. Create some UINode. And Set Second Node as BuilderRootNode; 276 * @tc.expected: step1. The return value is not null. 277 */ 278 auto firstNode = NG::FrameNode::GetOrCreateFrameNode( __anonefe3979e0f02() 279 TEST_NODE_TAG, UNIQUED_ID_OF_TEST_NODE++, []() { return AceType::MakeRefPtr<NG::Pattern>(); }); 280 EXPECT_NE(firstNode, nullptr); 281 auto secondedNode = NG::FrameNode::GetOrCreateFrameNode( __anonefe3979e1002() 282 TEST_NODE_TAG, UNIQUED_ID_OF_TEST_NODE++, []() { return AceType::MakeRefPtr<NG::Pattern>(); }); 283 EXPECT_NE(secondedNode, nullptr); 284 auto thirdNode = NG::FrameNode::GetOrCreateFrameNode( __anonefe3979e1102() 285 TEST_NODE_TAG, UNIQUED_ID_OF_TEST_NODE++, []() { return AceType::MakeRefPtr<NG::Pattern>(); }); 286 /** 287 * @tc.steps: step2. Make a tree by the previous Node. 288 *├─ firstNode 289 *│ ├─ secondedNode 290 *│ │ └─ thirdNode (true) 291 */ 292 firstNode->AddChild(secondedNode); 293 secondedNode->AddChild(thirdNode); 294 thirdNode->SetJsBuilderNodeId(secondedNode->GetId()); 295 296 auto context = AceType::MakeRefPtr<NG::MockPipelineContext>(); 297 EXPECT_NE(context, nullptr); 298 firstNode->context_ = AceType::RawPtr(context); 299 secondedNode->context_ = AceType::RawPtr(context); 300 thirdNode->context_ = AceType::RawPtr(context); 301 auto frontend = AceType::MakeRefPtr<MockFrontend>(); 302 context->weakFrontend_ = AceType::WeakClaim(AceType::RawPtr(frontend)); 303 304 /** 305 * @tc.steps: step3. Call AddBuilderToParent or RemoveBuilderFromParent without valid parent. 306 */ 307 EXPECT_CALL(*frontend, BuilderNodeFunc("__addBuilderNode__", _)).Times(0); 308 EXPECT_CALL(*frontend, BuilderNodeFunc("__addBuilderNodeToBuilder__", _)).Times(0); 309 BuilderUtils::AddBuilderToParent(secondedNode, thirdNode); 310 BuilderUtils::AddBuilderToParent(nullptr, thirdNode); 311 BuilderUtils::AddBuilderToParent(nullptr, nullptr); 312 BuilderUtils::AddBuilderToParent(secondedNode, nullptr); 313 314 EXPECT_CALL(*frontend, BuilderNodeFunc("__deleteBuilderNodeFromBuilder__", _)).Times(0); 315 EXPECT_CALL(*frontend, BuilderNodeFunc("__deleteBuilderNode__", _)).Times(0); 316 BuilderUtils::RemoveBuilderFromParent(secondedNode, thirdNode); 317 BuilderUtils::RemoveBuilderFromParent(nullptr, thirdNode); 318 BuilderUtils::RemoveBuilderFromParent(nullptr, nullptr); 319 BuilderUtils::RemoveBuilderFromParent(secondedNode, nullptr); 320 } 321 } // namespace OHOS::Ace 322