1 /*
2 * Copyright (c) 2024 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 <optional>
17 #include <utility>
18
19 #include "gtest/gtest.h"
20
21 #include "base/memory/ace_type.h"
22 #include "base/memory/referenced.h"
23
24 #define private public
25 #define protected public
26 #include "test/mock/core/pipeline/mock_pipeline_context.h"
27
28 #include "core/components_ng/base/view_stack_processor.h"
29 #include "core/components_ng/syntax/repeat_virtual_scroll_caches.h"
30 #include "core/components_ng/syntax/repeat_virtual_scroll_node.h"
31 #include "core/components_ng/pattern/list/list_item_event_hub.h"
32 #include "core/components_ng/pattern/list/list_item_layout_property.h"
33 #include "core/components_ng/pattern/list/list_item_pattern.h"
34 #include "core/components_ng/pattern/list/list_pattern.h"
35 #include "core/components_ng/pattern/scrollable/scrollable_item.h"
36 #include "core/components_ng/pattern/scrollable/scrollable_item_pool.h"
37 #include "core/components_v2/inspector/inspector_constants.h"
38 #undef private
39 #undef protected
40
41 using namespace testing;
42 using namespace testing::ext;
43
44 namespace OHOS::Ace::NG {
45 class RepeatNodeCacheSyntaxTest : public testing::Test {
46 public:
47
SetUp()48 void SetUp() override
49 {
50 MockPipelineContext::SetUp();
51 }
52
TearDown()53 void TearDown() override
54 {
55 MockPipelineContext::TearDown();
56 }
57
CreateNode(const std::string & tag,int32_t elmtId)58 RefPtr<FrameNode> CreateNode(const std::string& tag, int32_t elmtId)
59 {
60 auto pattern = AceType::MakeRefPtr<Pattern>();
61 auto frameNode = AceType::MakeRefPtr<FrameNode>(tag, elmtId, pattern);
62 pattern->AttachToFrameNode(frameNode);
63 ViewStackProcessor::GetInstance()->Push(frameNode);
64 return frameNode;
65 }
66
67 // create ListItemNode with 2 Text Node inside
CreateListItemNode(int32_t elmtId)68 RefPtr<FrameNode> CreateListItemNode(int32_t elmtId)
69 {
70 auto tag = "TEXT_ETS_TAG";
71
72 auto* stack = ViewStackProcessor::GetInstance();
73 auto liFrameNode = FrameNode::GetOrCreateFrameNode(V2::LIST_ITEM_ETS_TAG, elmtId,
74 []() { return AceType::MakeRefPtr<ListItemPattern>(nullptr, V2::ListItemStyle::NONE); });
75
76 auto textNode = CreateNode(V2::TEXT_ETS_TAG, 100*elmtId);
77
78 auto pattern = AceType::MakeRefPtr<Pattern>();
79 const uint32_t uniqNumMultiplier1 = 200;
80 auto textFrameNode = AceType::MakeRefPtr<FrameNode>(tag, uniqNumMultiplier1*elmtId, pattern);
81 pattern->AttachToFrameNode(textFrameNode);
82 liFrameNode->AddChild(textFrameNode);
83
84 pattern = AceType::MakeRefPtr<Pattern>();
85 const uint32_t uniqNumMultiplier2 = 100;
86 textFrameNode = AceType::MakeRefPtr<FrameNode>(tag, uniqNumMultiplier2*elmtId, pattern);
87 pattern->AttachToFrameNode(textFrameNode);
88 liFrameNode->AddChild(textFrameNode);
89 stack->Push(liFrameNode);
90 return liFrameNode;
91 }
92
__anona03fc19a0202(uint32_t forIndex) 93 const std::function<void(uint32_t)> onCreateNode = [this](uint32_t forIndex) {
94 CreateListItemNode(forIndex);
95 };
96 };
97 /**
98 * Function needed by RepeatVirtualScrollCaches constructor
99 */
__anona03fc19a0302(uint32_t forIndex) 100 auto g_onCreateNode = [](uint32_t forIndex) {
101 };
102
103 /**
104 * Function needed by RepeatVirtualScrollCaches constructor
105 */
__anona03fc19a0402(const std::string& fromKey, uint32_t forIndex) 106 auto g_onUpdateNode = [](const std::string& fromKey, uint32_t forIndex) {
107 };
108
109 /**
110 * Function needed by RepeatVirtualScrollCaches constructor
111 */
__anona03fc19a0502(uint32_t from, uint32_t to) 112 auto g_onGetKeys4Range = [](uint32_t from, uint32_t to) -> std::list<std::string> {
113 std::list<std::string> keys;
114 for (uint32_t i = from; i <= to; ++i) {
115 keys.push_back("Key" + std::to_string(i));
116 }
117 return keys;
118 };
119
120 /**
121 * Function needed by RepeatVirtualScrollCaches constructor is special test case
122 */
__anona03fc19a0602(uint32_t from, uint32_t to) 123 auto g_onGetKeys4RangeMaxTo5 = [](uint32_t from, uint32_t to) -> std::list<std::string> {
124 std::list<std::string> keys;
125 for (uint32_t i = from; i <= to && i<=5; ++i) {
126 keys.push_back("Key" + std::to_string(i));
127 }
128 return keys;
129 };
130
131 /**
132 * Function needed by RepeatVirtualScrollCaches constructor
133 */
__anona03fc19a0702(uint32_t from, uint32_t to) 134 auto g_onGetTypes4Range = [](uint32_t from, uint32_t to) -> std::list<std::string> {
135 std::list<std::string> types;
136 for (uint32_t i = from; i <= to; ++i) {
137 types.push_back("Type" + std::to_string(i));
138 }
139
140 return types;
141 };
142 /**
143 * Function needed by RepeatVirtualScrollNode constructor
144 */
__anona03fc19a0802(int32_t from, int32_t to) 145 auto g_onSetActiveRange = [](int32_t from, int32_t to) {
146 };
147
148 /**
149 * Map needed by RepeatVirtualScrollCaches constructor
150 */
151 const std::map<std::string, std::pair<bool, uint32_t>> cacheCountL24ttype = {
152 {"element1", { true, 1 }},
153 {"element2", { true, 2 } },
154 {"element3", { true, 3 }},
155 {"element4", { true, 4 }},
156 {"element5", { true, 5 }}
157 };
158
159 /**
160 * Map needed by RepeatVirtualScrollNode constructor
161 */
162 const std::map<std::string, std::pair<bool, uint32_t>> templateCachedCountMap = {
163 // { template, { cachedCountSpecified, cacheCount } }
164 {"elmt1", { true, 1} },
165 {"elmt2", { true, 2} }
166 };
167
168 /**
169 * @tc.name: RepeatNodeCacheTest001
170 * @tc.desc: Test GetKey4Index without fetch.
171 * @tc.type: FUNC
172 */
173 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest001, TestSize.Level1)
174 {
175 RepeatVirtualScrollCaches caches(cacheCountL24ttype,
176 g_onCreateNode,
177 g_onUpdateNode,
178 g_onGetKeys4Range,
179 g_onGetTypes4Range);
180
181 /**
182 * @tc.steps: step1. Try to get key for index 2.
183 * @tc.expected: Because second parameter is false
184 * FetchMoreKeysTTypes will not be called and std::nullopt is returned
185 */
186 std::optional<std::string> key = caches.GetKey4Index(2, false);
187 EXPECT_EQ(key, std::nullopt);
188 }
189
190 /**
191 * @tc.name: RepeatNodeCacheTest002
192 * @tc.desc: Test GetKey4Index with fetch.
193 * @tc.type: FUNC
194 */
195 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest002, TestSize.Level1)
196 {
197 RepeatVirtualScrollCaches caches(cacheCountL24ttype,
198 g_onCreateNode,
199 g_onUpdateNode,
200 g_onGetKeys4Range,
201 g_onGetTypes4Range);
202
203 /**
204 * @tc.steps: step1. Try to get key for index 2.
205 * @tc.expected: Because second parameter is true FetchMoreKeysTTypes will be called and Key2 string is returned
206 */
207 std::optional<std::string> key = caches.GetKey4Index(2, true);
208
209 /**
210 * @tc.steps: step2. Try to create node for index 2.
211 * @tc.expected: Because viewStack->Finish() will eventually return nullptr node will also be nullptr
212 */
213 RefPtr<UINode> node = caches.CreateNewNode(2);
214 EXPECT_EQ(node, nullptr);
215 EXPECT_EQ(key, "Key2");
216 }
217
218 /**
219 * @tc.name: RepeatNodeCacheTest003
220 * @tc.desc: Test UpdateFromL2
221 * @tc.type: FUNC
222 */
223 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest003, TestSize.Level1)
224 {
225 RepeatVirtualScrollCaches caches(cacheCountL24ttype,
226 g_onCreateNode,
227 g_onUpdateNode,
228 g_onGetKeys4Range,
229 g_onGetTypes4Range);
230
231 /**
232 * @tc.steps: step1. Try to get UINode from index 2
233 * @tc.expected: Because there are no items in L2 nullptr is expected
234 */
235 RefPtr<UINode> node = caches.UpdateFromL2(2);
236 EXPECT_EQ(node, nullptr);
237 }
238
239 /**
240 * @tc.name: RepeatNodeCacheTest004
241 * @tc.desc: Test GetDistanceFromRange
242 * @tc.type: FUNC
243 */
244 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest004, TestSize.Level1)
245 {
246 RepeatVirtualScrollCaches caches(cacheCountL24ttype,
247 g_onCreateNode,
248 g_onUpdateNode,
249 g_onGetKeys4Range,
250 g_onGetTypes4Range);
251
252 /**
253 * @tc.steps: step1. Get distance from active range of index 2
254 * @tc.expected: Because active range index is 0 it expected that number 2 is returned.
255 */
256 int32_t dist = caches.GetDistanceFromRange(2);
257 EXPECT_EQ(dist, 2);
258 }
259
260 /**
261 * @tc.name: RepeatNodeCacheTest005
262 * @tc.desc: Test creation of GetOrCreateRepeatNode
263 * @tc.type: FUNC
264 */
265 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest005, TestSize.Level1)
266 {
267 auto* stack = ViewStackProcessor::GetInstance();
268 auto nodeId = stack->ClaimNodeId();
269 /**
270 * @tc.steps: step1. Create node object
271 * @tc.expected: Object is not nullptr.
272 */
273 auto repeatNode = RepeatVirtualScrollNode::GetOrCreateRepeatNode(
274 nodeId,
275 1,
276 templateCachedCountMap,
277 g_onCreateNode,
278 g_onUpdateNode,
279 g_onGetKeys4Range,
280 g_onGetTypes4Range,
281 g_onSetActiveRange);
282
283 EXPECT_NE(repeatNode, nullptr);
284 }
285
286 /**
287 * @tc.name: RepeatNodeCacheTest006
288 * @tc.desc: Test FrameCount
289 * @tc.type: FUNC
290 */
291 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest006, TestSize.Level1)
292 {
293 auto repeatNode = RepeatVirtualScrollNode::GetOrCreateRepeatNode(
294 1,
295 1,
296 templateCachedCountMap,
297 g_onCreateNode,
298 g_onUpdateNode,
299 g_onGetKeys4Range,
300 g_onGetTypes4Range,
301 g_onSetActiveRange);
302
303 /**
304 * @tc.steps: step2. Update total count to 2
305 * @tc.expected: Object internal frame count is increased to 2
306 */
307 repeatNode->UpdateTotalCount(2);
308
309 /**
310 * @tc.steps: step3. Get frame count
311 * @tc.expected: Object internal frame count should be 2
312 */
313 uint32_t frameCount = repeatNode->FrameCount();
314 EXPECT_EQ(frameCount, 2);
315 }
316
317 /**
318 * @tc.name: RepeatNodeCacheTest007
319 * @tc.desc: Test GetChildren
320 * @tc.type: FUNC
321 */
322 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest007, TestSize.Level1)
323 {
324 auto repeatNode = RepeatVirtualScrollNode::GetOrCreateRepeatNode(
325 1,
326 1,
327 templateCachedCountMap,
328 g_onCreateNode,
329 g_onUpdateNode,
330 g_onGetKeys4Range,
331 g_onGetTypes4Range,
332 g_onSetActiveRange);
333
334 /**
335 * @tc.steps: step2. Get children count
336 * @tc.expected: Returns number of children. Should be 0
337 */
338 std::list<RefPtr<UINode>> nodes = repeatNode->GetChildren();
339 EXPECT_EQ(nodes.size(), 0);
340 }
341
342 /**
343 * @tc.name: RepeatNodeCacheTest008
344 * @tc.desc: Test Multiple functions when onCreate lambda really creates node.
345 * @tc.type: FUNC
346 */
347 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest008, TestSize.Level1)
348 {
349 RepeatVirtualScrollCaches caches(cacheCountL24ttype, onCreateNode,
350 g_onUpdateNode, g_onGetKeys4Range,
351 g_onGetTypes4Range);
352
353 std::optional<std::string> key1 = caches.GetKey4Index(1, true);
354 EXPECT_EQ(key1, "Key1");
355 std::optional<std::string> key2 = caches.GetKey4Index(2, true);
356 EXPECT_EQ(key2, "Key2");
357 std::optional<std::string> key3 = caches.GetKey4Index(3, true);
358 EXPECT_EQ(key3, "Key3");
359
360 RefPtr<UINode> node1 = caches.CreateNewNode(1);
361 EXPECT_NE(node1, nullptr);
362 RefPtr<UINode> node2 = caches.CreateNewNode(2);
363 EXPECT_NE(node2, nullptr);
364 RefPtr<UINode> node3 = caches.CreateNewNode(3);
365 EXPECT_NE(node3, nullptr);
366
367 auto repeatNode = RepeatVirtualScrollNode::GetOrCreateRepeatNode(
368 1, 3, templateCachedCountMap, onCreateNode,
369 g_onUpdateNode, g_onGetKeys4Range,
370 g_onGetTypes4Range, g_onSetActiveRange);
371
372 repeatNode->caches_ = caches;
373 /**
374 * @tc.steps: step1. Add keys to cache
375 * @tc.expected: Items in cache size should be 3
376 */
377 repeatNode->caches_.FetchMoreKeysTTypes(1, 3);
378 repeatNode->caches_.AddKeyToL1("Key1");
379 repeatNode->caches_.AddKeyToL1("Key2");
380 repeatNode->caches_.AddKeyToL1("Key3");
381 EXPECT_EQ(repeatNode->caches_.activeNodeKeysInL1_.size(), 3);
382
383 /**
384 * @tc.steps: step2. Dump information
385 * @tc.expected: Dumping output string should have ListItem(3) substring
386 */
387 std::string l1Dump = repeatNode->caches_.DumpL1();
388 const std::string expectedSubStringL1And4TType = "ListItem";
389 EXPECT_NE(l1Dump.find(expectedSubStringL1And4TType), std::string::npos);
390 std::string dmp4KeyType = repeatNode->caches_.DumpUINode4Key4TType();
391 EXPECT_NE(dmp4KeyType.find(expectedSubStringL1And4TType), std::string::npos);
392
393 /**
394 * @tc.steps: step3. Find unused keys
395 * @tc.expected: Number of unused keys should be 0
396 */
397 std::set<std::pair<bool, std::string>> keys;
398 caches.FindUnusedKeys(keys);
399 EXPECT_EQ(keys.size(), 0);
400
401 caches.UINodeHasBeenUpdated("Type1", "Key1", "Key2");
402 repeatNode->DoSetActiveChildRange(1, 3, 1, 2);
403 repeatNode->caches_.index4Key_.clear();
404 repeatNode->DropFromL1("Key1");
405 repeatNode->caches_.GetL1KeyToUpdate("Key1");
406 repeatNode->caches_.InvalidateKeyAndTTypeCaches();
407 repeatNode->UpdateRenderState(true);
408 repeatNode->UpdateRenderState(false);
409 repeatNode->RecycleItems(0, 100);
410
411 /**
412 * @tc.steps: step4. Get GetFrameNode
413 * @tc.expected: Returns valid frame node
414 */
415 auto frameNode = repeatNode->GetFrameNode(1);
416 EXPECT_NE(frameNode, nullptr);
417 }
418
419 /**
420 * @tc.name: RepeatNodeCacheTest009
421 * @tc.desc: Test FrameCount
422 * @tc.type: FUNC
423 */
424 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest009, TestSize.Level1)
425 {
426 const uint32_t totalCount = 10;
427 const uint32_t updatedCount = 5;
428 /**
429 * @tc.steps: step1. Create node object with totalCount = 10
430 * @tc.expected: Object is not nullptr.
431 */
432 auto repeatNode = RepeatVirtualScrollNode::GetOrCreateRepeatNode(
433 1,
434 totalCount,
435 templateCachedCountMap,
436 g_onCreateNode,
437 g_onUpdateNode,
438 g_onGetKeys4Range,
439 g_onGetTypes4Range,
440 g_onSetActiveRange);
441
442 /**
443 * @tc.steps: step2. Ask frame count
444 * @tc.expected: Should be totalCount
445 */
446 uint32_t frameCount = repeatNode->FrameCount();
447 EXPECT_EQ(frameCount, totalCount);
448
449 /**
450 * @tc.steps: step3. Update total count to the new value
451 * @tc.expected: Should be updatedCount
452 */
453 repeatNode->UpdateTotalCount(updatedCount);
454 frameCount = repeatNode->FrameCount();
455 EXPECT_EQ(frameCount, updatedCount);
456 }
457
458 /**
459 * @tc.name: RepeatNodeCacheTest010
460 * @tc.desc: Test GetL1KeyToUpdate
461 * @tc.type: FUNC
462 */
463 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest010, TestSize.Level1)
464 {
465 RepeatVirtualScrollCaches caches(cacheCountL24ttype,
466 g_onCreateNode,
467 g_onUpdateNode,
468 g_onGetKeys4Range,
469 g_onGetTypes4Range);
470
471 caches.FetchMoreKeysTTypes(1, 3);
472 /**
473 * @tc.steps: step1. Try to get L1 key to update
474 * @tc.expected: Because there are no L1 key for Type1
475 * std::nullopt is returned
476 */
477 std::optional<std::string> key = caches.GetL1KeyToUpdate("Type1");
478 EXPECT_EQ(key, std::nullopt);
479 }
480
481 /**
482 * @tc.name: RepeatNodeCacheTest011
483 * @tc.desc: Test UiNodeHasBeenUpdated
484 * @tc.type: FUNC
485 */
486 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest011, TestSize.Level1)
487 {
488 RepeatVirtualScrollCaches caches(cacheCountL24ttype,
489 g_onCreateNode,
490 g_onUpdateNode,
491 g_onGetKeys4Range,
492 g_onGetTypes4Range);
493
494 /**
495 * @tc.steps: step1. Try to get UI node by calling UINodeHasBeenUpdated
496 * @tc.expected: Because there are no nodes nullptr is returned
497 */
498 RefPtr<UINode> node = caches.UINodeHasBeenUpdated("Type1", "Key0", "Key1");
499 EXPECT_EQ(node, nullptr);
500 }
501
502 /**
503 * @tc.name: RepeatNodeCacheTest012
504 * @tc.desc: Test FindUnusedKeys
505 * @tc.type: FUNC
506 */
507 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest012, TestSize.Level1)
508 {
509 RepeatVirtualScrollCaches caches(cacheCountL24ttype,
510 g_onCreateNode,
511 g_onUpdateNode,
512 g_onGetKeys4Range,
513 g_onGetTypes4Range);
514
515 /**
516 * @tc.steps: step1. Try to get set of unused keys
517 * @tc.expected: Because there are no keys 0 is returned
518 */
519 std::set<std::pair<bool, std::string>> keys;
520 caches.FindUnusedKeys(keys);
521 EXPECT_EQ(keys.size(), 0);
522 }
523
524 /**
525 * @tc.name: RepeatNodeCacheTest013
526 * @tc.desc: Test DumpL1
527 * @tc.type: FUNC
528 */
529 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest013, TestSize.Level1)
530 {
531 RepeatVirtualScrollCaches caches(cacheCountL24ttype,
532 g_onCreateNode,
533 g_onUpdateNode,
534 g_onGetKeys4Range,
535 g_onGetTypes4Range);
536
537 /**
538 * @tc.steps: step1. Try to call DumpL1
539 * @tc.expected: Because there are no items. Its expected that there is
540 * total number=0 substring in return value
541 */
542 std::string l1Dump = caches.DumpL1();
543 const std::string expectedSubString = "total number=0";
544 EXPECT_NE(l1Dump.find(expectedSubString), std::string::npos);
545 }
546
547 /**
548 * @tc.name: RepeatNodeCacheTest014
549 * @tc.desc: Test DumpL2
550 * @tc.type: FUNC
551 */
552 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest014, TestSize.Level1)
553 {
554 RepeatVirtualScrollCaches caches(cacheCountL24ttype,
555 g_onCreateNode,
556 g_onUpdateNode,
557 g_onGetKeys4Range,
558 g_onGetTypes4Range);
559
560 /**
561 * @tc.steps: step1. Try to call DumpL2
562 * @tc.expected: Because there are no items. Its expected that there is size=0 substring in return value
563 */
564 std::string l2Dump = caches.DumpL2();
565 const std::string expectedSubString = "size=0";
566 EXPECT_NE(l2Dump.find(expectedSubString), std::string::npos);
567 }
568
569 /**
570 * @tc.name: RepeatNodeCacheTest015
571 * @tc.desc: Test DumpKey4Index
572 * @tc.type: FUNC
573 */
574 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest015, TestSize.Level1)
575 {
576 RepeatVirtualScrollCaches caches(cacheCountL24ttype,
577 g_onCreateNode,
578 g_onUpdateNode,
579 g_onGetKeys4Range,
580 g_onGetTypes4Range);
581
582 /**
583 * @tc.steps: step1. Try to call DumpKey4Index
584 * @tc.expected: Because there are no items. Its expected that there is size=0 substring in return value
585 */
586 std::string key4IndexDump = caches.DumpKey4Index();
587 const std::string expectedSubString = "size=0";
588 EXPECT_NE(key4IndexDump.find(expectedSubString), std::string::npos);
589 }
590
591 /**
592 * @tc.name: RepeatNodeCacheTest016
593 * @tc.desc: Test DumpTType4Index
594 * @tc.type: FUNC
595 */
596 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest016, TestSize.Level1)
597 {
598 RepeatVirtualScrollCaches caches(cacheCountL24ttype,
599 g_onCreateNode,
600 g_onUpdateNode,
601 g_onGetKeys4Range,
602 g_onGetTypes4Range);
603
604 /**
605 * @tc.steps: step1. Try to call DumpTType4Index
606 * @tc.expected: Because there are no items. Its expected that there is size=0 substring in return value
607 */
608 std::string tTypeIndex = caches.DumpTType4Index();
609 const std::string expectedSubString = "size=0";
610 EXPECT_NE(tTypeIndex.find(expectedSubString), std::string::npos);
611 }
612
613 /**
614 * @tc.name: RepeatNodeCacheTest017
615 * @tc.desc: Test DumpUINode4Key
616 * @tc.type: FUNC
617 */
618 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest017, TestSize.Level1)
619 {
620 RepeatVirtualScrollCaches caches(cacheCountL24ttype,
621 g_onCreateNode,
622 g_onUpdateNode,
623 g_onGetKeys4Range,
624 g_onGetTypes4Range);
625
626 /**
627 * @tc.steps: step1. Try to call DumpUINode4Key
628 * @tc.expected: Because there are no items. Its expected that there is size=0 substring in return value
629 */
630 std::string uiNode4Key = caches.DumpUINode4Key();
631 const std::string expectedSubString = "size=0";
632 EXPECT_NE(uiNode4Key.find(expectedSubString), std::string::npos);
633 }
634
635 /**
636 * @tc.name: RepeatNodeCacheTest018
637 * @tc.desc: Test DumpUINode4Key4TType
638 * @tc.type: FUNC
639 */
640 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest018, TestSize.Level1)
641 {
642 RepeatVirtualScrollCaches caches(cacheCountL24ttype,
643 g_onCreateNode,
644 g_onUpdateNode,
645 g_onGetKeys4Range,
646 g_onGetTypes4Range);
647
648
649 /**
650 * @tc.steps: step1. Try to call DumpUINode4Key4TType
651 * @tc.expected: Because there are no items. Its expected that there is size=0 substring in return value
652 */
653 std::string uiNode4Key4TType = caches.DumpUINode4Key4TType();
654 const std::string expectedSubString = "size=0";
655 EXPECT_NE(uiNode4Key4TType.find(expectedSubString), std::string::npos);
656 }
657
658 /**
659 * @tc.name: RepeatNodeCacheTest019
660 * @tc.desc: Test DumpUINodeWithKey
661 * @tc.type: FUNC
662 */
663 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest019, TestSize.Level1)
664 {
665 RepeatVirtualScrollCaches caches(cacheCountL24ttype,
666 g_onCreateNode,
667 g_onUpdateNode,
668 g_onGetKeys4Range,
669 g_onGetTypes4Range);
670
671 /**
672 * @tc.steps: step1. Try to call DumpUINodeWithKey
673 * @tc.expected: Because there are no items. Its expected that there is "no UINode" substring in return value
674 */
675 std::string uiNodeWithKey = caches.DumpUINodeWithKey("Key1");
676 const std::string expectedSubString = "no UINode";
677 EXPECT_NE(uiNodeWithKey.find(expectedSubString), std::string::npos);
678 }
679
680 /**
681 * @tc.name: RepeatNodeCacheTest020
682 * @tc.desc: Test DumpUINode
683 * @tc.type: FUNC
684 */
685 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest020, TestSize.Level1)
686 {
687 RepeatVirtualScrollCaches caches(cacheCountL24ttype,
688 g_onCreateNode,
689 g_onUpdateNode,
690 g_onGetKeys4Range,
691 g_onGetTypes4Range);
692
693 /**
694 * @tc.steps: step1. Try to call DumpUINode
695 * @tc.expected: Because input argument is nullptr its expected that there is nullptr in return value
696 */
697 std::string uiNode = caches.DumpUINode(nullptr);
698 const std::string expectedSubString = "nullptr";
699 EXPECT_NE(uiNode.find(expectedSubString), std::string::npos);
700 }
701
702 /**
703 * @tc.name: RepeatNodeCacheTest021
704 * @tc.desc: Test OnConfigurationUpdate function
705 * @tc.type: FUNC
706 */
707 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest021, TestSize.Level1)
708 {
709 auto repeatNode = RepeatVirtualScrollNode::GetOrCreateRepeatNode(
710 1,
711 1,
712 templateCachedCountMap,
713 g_onCreateNode,
714 g_onUpdateNode,
715 g_onGetKeys4Range,
716 g_onGetTypes4Range,
717 g_onSetActiveRange);
718
719 ConfigurationChange cfgChange;
720 cfgChange.colorModeUpdate = true;
721 /**
722 * @tc.steps: step1. Try to call GetOrCreateRepeatNode.
723 * @tc.expected: Instead of creating current node is returned,
724 */
725 auto repeatNode2 = RepeatVirtualScrollNode::GetOrCreateRepeatNode(
726 1,
727 1,
728 templateCachedCountMap,
729 g_onCreateNode,
730 g_onUpdateNode,
731 g_onGetKeys4Range,
732 g_onGetTypes4Range,
733 g_onSetActiveRange);
734
735 EXPECT_EQ(repeatNode, repeatNode2);
736 /**
737 * @tc.steps: step3. Try to call OnConfigurationChange.
738 * @tc.expected: No code crash happens
739 */
740 repeatNode->OnConfigurationUpdate(cfgChange);
741 }
742
743 /**
744 * @tc.name: RepeatNodeCacheTest022
745 * @tc.desc: Test FetchMoreKeysTTypes with invalid values.
746 * @tc.type: FUNC
747 */
748 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest022, TestSize.Level1)
749 {
750 RepeatVirtualScrollCaches caches(cacheCountL24ttype,
751 g_onCreateNode,
752 g_onUpdateNode,
753 g_onGetKeys4Range,
754 g_onGetTypes4Range);
755
756 /**
757 * @tc.steps: step1. Try to call FetchMoreKeysTTypes so that "from" is bigger than "to"
758 * @tc.expected: False is expected to be returned
759 */
760 bool status = caches.FetchMoreKeysTTypes(2, 1);
761 EXPECT_EQ(status, false);
762 }
763
764 /**
765 * @tc.name: RepeatNodeCacheTest023
766 * @tc.desc: Test FetchMoreKeysTTypes with special MaxTo5 lambda.
767 * @tc.type: FUNC
768 */
769 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest023, TestSize.Level1)
770 {
771 /**
772 * @tc.steps: step1. Create caches object with Keys function that limits keys to 5 (for unit testing)
773 * @tc.expected: Object is created correctly
774 */
775 RepeatVirtualScrollCaches caches(cacheCountL24ttype,
776 g_onCreateNode,
777 g_onUpdateNode,
778 g_onGetKeys4RangeMaxTo5,
779 g_onGetTypes4Range);
780
781 /**
782 * @tc.steps: step2. Try to call FetchMoreKeysTTypes so that internally "keys"
783 * *are smaller than "types" due to g_onGetKeys4RangeMaxTo5
784 * @tc.expected: False is expected to be returned
785 */
786 bool status = caches.FetchMoreKeysTTypes(1, 10);
787 EXPECT_EQ(status, false);
788 }
789
790 /**
791 * @tc.name: RepeatNodeCacheTest024
792 * @tc.desc: Test GetKey4Index with fetch and creating new node.
793 * @tc.type: FUNC
794 */
795 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest024, TestSize.Level1)
796 {
797 RepeatVirtualScrollCaches caches(cacheCountL24ttype,
798 onCreateNode,
799 g_onUpdateNode,
800 g_onGetKeys4Range,
801 g_onGetTypes4Range);
802
803 /**
804 * @tc.steps: step1. Try to get key for index 2.
805 * @tc.expected: Because second parameter is true FetchMoreKeysTTypes will be internally
806 * called and Key2 string is returned
807 */
808 std::optional<std::string> key = caches.GetKey4Index(2, true);
809 EXPECT_EQ(key, "Key2");
810 /**
811 * @tc.steps: step2. Try to create node for index 2.
812 * @tc.expected: Because onCreateNode lambda used that really creates node 1 is expected.
813 */
814 RefPtr<UINode> node = caches.CreateNewNode(2);
815 EXPECT_NE(node, nullptr);
816
817 RefPtr<UINode> uinode = caches.DropFromL1("Key2");
818 EXPECT_NE(uinode, nullptr);
819 }
820
821 /**
822 * @tc.name: RepeatNodeCacheTest025
823 * @tc.desc: Test GetDistanceFromRange
824 * @tc.type: FUNC
825 */
826 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest025, TestSize.Level1)
827 {
828 RepeatVirtualScrollCaches caches(
829 cacheCountL24ttype, g_onCreateNode, g_onUpdateNode, g_onGetKeys4Range, g_onGetTypes4Range);
830
831 int32_t dist = caches.GetDistanceFromRange(UINT32_MAX);
832 EXPECT_EQ(dist, UINT32_MAX);
833
834 caches.lastActiveRanges_[0].first = 10;
835 caches.lastActiveRanges_[0].second = 30;
836 caches.lastActiveRanges_[1].first = 20;
837 dist = caches.GetDistanceFromRange(9);
838 EXPECT_EQ(dist, 0);
839
840 dist = caches.GetDistanceFromRange(11);
841 EXPECT_EQ(dist, 0);
842
843 caches.lastActiveRanges_[0].first = 10;
844 caches.lastActiveRanges_[0].second = 30;
845 caches.lastActiveRanges_[1].second = 20;
846 dist = caches.GetDistanceFromRange(29);
847 EXPECT_EQ(dist, 0);
848
849 dist = caches.GetDistanceFromRange(31);
850 EXPECT_EQ(dist, 0);
851 }
852
853 /**
854 * @tc.name: RepeatNodeCacheTest026
855 * @tc.desc: Test GetCachedNode4Key4Ttype
856 * @tc.type: FUNC
857 */
858 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest026, TestSize.Level1)
859 {
860 /**
861 * @tc.steps: step1. Create cached object with Keys function that limits keys to 5 (for unit testing)
862 * @tc.expected: Object is created correctly
863 */
864 RepeatVirtualScrollCaches caches(
865 cacheCountL24ttype, g_onCreateNode, g_onUpdateNode, g_onGetKeys4RangeMaxTo5, g_onGetTypes4Range);
866
867 auto ret = caches.GetCachedNode4Key4Ttype(std::nullopt, std::nullopt);
868 EXPECT_EQ(ret, nullptr);
869 ret = caches.GetCachedNode4Key4Ttype(std::string("a"), std::nullopt);
870 EXPECT_EQ(ret, nullptr);
871 ret = caches.GetCachedNode4Key4Ttype(std::nullopt, std::string("a"));
872 EXPECT_EQ(ret, nullptr);
873 ret = caches.GetCachedNode4Key4Ttype(std::string("a"), std::string("a"));
874 EXPECT_EQ(ret, nullptr);
875
876 // std::unordered_map<std::string, std::unordered_map<std::string, RefPtr<UINode>>> node4key4ttype_;
877 caches.node4key4ttype_.insert({ std::string("a"), { { std::string("a"), nullptr } } });
878 ret = caches.GetCachedNode4Key4Ttype(std::string("a"), std::string("a"));
879 EXPECT_EQ(ret, nullptr);
880 ret = caches.GetCachedNode4Key4Ttype(std::string("b"), std::string("a"));
881 EXPECT_EQ(ret, nullptr);
882 }
883
884 /**
885 * @tc.name: RepeatNodeCacheTest027
886 * @tc.desc: Test GetCachedNode4Key
887 * @tc.type: FUNC
888 */
889 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest027, TestSize.Level1)
890 {
891 /**
892 * @tc.steps: step1. Create cached object with Keys function that limits keys to 5 (for unit testing)
893 * @tc.expected: Object is created correctly
894 */
895 RepeatVirtualScrollCaches caches(
896 cacheCountL24ttype, g_onCreateNode, g_onUpdateNode, g_onGetKeys4RangeMaxTo5, g_onGetTypes4Range);
897
898 auto ret = caches.GetCachedNode4Key(std::nullopt);
899 EXPECT_FALSE(ret.has_value());
900 }
901
902 /**
903 * @tc.name: RepeatNodeCacheTest028
904 * @tc.desc: Test GetTType4Index
905 * @tc.type: FUNC
906 */
907 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest028, TestSize.Level1)
908 {
909 /**
910 * @tc.steps: step1. Create cached object with Keys function that limits keys to 5 (for unit testing)
911 * @tc.expected: Object is created correctly
912 */
913 RepeatVirtualScrollCaches caches(
914 cacheCountL24ttype, g_onCreateNode, g_onUpdateNode, g_onGetKeys4RangeMaxTo5, g_onGetTypes4Range);
915 std::string val("0");
916 caches.ttype4index_.insert({ 0, val });
917 auto ret = caches.GetTType4Index(0);
918 EXPECT_TRUE(ret.has_value());
919 }
920
921 /**
922 * @tc.name: RepeatNodeCacheTest029
923 * @tc.desc: Test GetIndex4Key
924 * @tc.type: FUNC
925 */
926 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest029, TestSize.Level1)
927 {
928 /**
929 * @tc.steps: step1. Create cached object with Keys function that limits keys to 5 (for unit testing)
930 * @tc.expected: Object is created correctly
931 */
932 RepeatVirtualScrollCaches caches(
933 cacheCountL24ttype, g_onCreateNode, g_onUpdateNode, g_onGetKeys4RangeMaxTo5, g_onGetTypes4Range);
934
935 std::string key("key");
936 caches.index4Key_.insert({ key, 0 });
937 auto ret = caches.GetIndex4Key(key);
938 EXPECT_EQ(ret, 0);
939 }
940
941 /**
942 * @tc.name: RepeatNodeCacheTest030
943 * @tc.desc: Test FindUnusedKeys
944 * @tc.type: FUNC
945 */
946 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest030, TestSize.Level1)
947 {
948 /**
949 * @tc.steps: step1. Create cached object with Keys function that limits keys to 5 (for unit testing)
950 * @tc.expected: Object is created correctly
951 */
952 RepeatVirtualScrollCaches caches(
953 cacheCountL24ttype, g_onCreateNode, g_onUpdateNode, g_onGetKeys4RangeMaxTo5, g_onGetTypes4Range);
954
955 std::string key("key");
956 caches.node4key_.insert({ key, CacheItem() });
957 std::set<std::pair<bool, std::string>> result;
958 caches.FindUnusedKeys(result);
959 EXPECT_EQ(result.size(), 1);
960
961 result.clear();
962 caches.index4Key_.insert({ key, 0 });
963 caches.FindUnusedKeys(result);
964 EXPECT_EQ(result.size(), 0);
965 }
966
967 /**
968 * @tc.name: RepeatNodeCacheTest031
969 * @tc.desc: Test UINodeHasBeenUpdated
970 * @tc.type: FUNC
971 */
972 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest031, TestSize.Level1)
973 {
974 /**
975 * @tc.steps: step1. Create cached object with Keys function that limits keys to 5 (for unit testing)
976 * @tc.expected: Object is created correctly
977 */
978 RepeatVirtualScrollCaches caches(
979 cacheCountL24ttype, g_onCreateNode, g_onUpdateNode, g_onGetKeys4RangeMaxTo5, g_onGetTypes4Range);
980
981 std::string key("key");
982 std::string key2("key2");
983 caches.node4key4ttype_.insert({ key, { { key2, nullptr } } });
984 auto ret = caches.UINodeHasBeenUpdated(key, std::string("a"), std::string("a"));
985 EXPECT_EQ(ret, nullptr);
986 ret = caches.UINodeHasBeenUpdated(key, key2, std::string("a"));
987 EXPECT_EQ(ret, nullptr);
988
989 caches.node4key_.insert({ key2, CacheItem() });
990 ret = caches.UINodeHasBeenUpdated(key, key2, std::string("a"));
991 EXPECT_EQ(ret, nullptr);
992 }
993
994 /**
995 * @tc.name: RepeatNodeCacheTest032
996 * @tc.desc: Test GetL1KeyToUpdate
997 * @tc.type: FUNC
998 */
999 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest032, TestSize.Level1)
1000 {
1001 RepeatVirtualScrollCaches caches(
1002 cacheCountL24ttype, g_onCreateNode, g_onUpdateNode, g_onGetKeys4Range, g_onGetTypes4Range);
1003
1004 std::string key("key");
1005 std::string key1("key1");
1006 caches.activeNodeKeysInL1_.insert(key);
1007 std::optional<std::string> ret = caches.GetL1KeyToUpdate(key1);
1008 EXPECT_EQ(ret, std::nullopt);
1009
1010 caches.index4Key_.insert({ key, 0 });
1011 ret = caches.GetL1KeyToUpdate(key1);
1012 EXPECT_EQ(ret, std::nullopt);
1013
1014 caches.index4Key_.clear();
1015 caches.node4key4ttype_.insert({ key1, {} });
1016 ret = caches.GetL1KeyToUpdate(key1);
1017 EXPECT_EQ(ret, std::nullopt);
1018
1019 caches.node4key4ttype_.clear();
1020 caches.node4key4ttype_.insert({ key1, { { key, nullptr } } });
1021 ret = caches.GetL1KeyToUpdate(key1);
1022 EXPECT_NE(ret, std::nullopt);
1023 }
1024
1025 /**
1026 * @tc.name: RepeatNodeCacheTest033
1027 * @tc.desc: Test GetL2KeyToUpdate
1028 * @tc.type: FUNC
1029 */
1030 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest033, TestSize.Level1)
1031 {
1032 RepeatVirtualScrollCaches caches(
1033 cacheCountL24ttype, g_onCreateNode, g_onUpdateNode, g_onGetKeys4Range, g_onGetTypes4Range);
1034
1035 auto ret = caches.GetL2KeyToUpdate(std::nullopt);
1036 EXPECT_EQ(ret, std::nullopt);
1037
1038 std::string key("key");
1039 ret = caches.GetL2KeyToUpdate(key);
1040 EXPECT_EQ(ret, std::nullopt);
1041
1042 caches.node4key4ttype_.insert({ key, { { key, nullptr } } });
1043 ret = caches.GetL2KeyToUpdate(key);
1044 EXPECT_NE(ret, std::nullopt);
1045
1046 caches.node4key4ttype_.clear();
1047 caches.node4key4ttype_.insert({ key, { { key, nullptr } } });
1048 ret = caches.GetL2KeyToUpdate(key);
1049 EXPECT_NE(ret, std::nullopt);
1050 }
1051
1052 /**
1053 * @tc.name: RepeatNodeCacheTest034
1054 * @tc.desc: Test GetFrameNodeIndex
1055 * @tc.type: FUNC
1056 */
1057 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest034, TestSize.Level1)
1058 {
1059 RepeatVirtualScrollCaches caches(
1060 cacheCountL24ttype, g_onCreateNode, g_onUpdateNode, g_onGetKeys4Range, g_onGetTypes4Range);
1061
1062 auto ret = caches.GetFrameNodeIndex(nullptr);
1063 EXPECT_EQ(ret, -1);
1064
1065 std::string key("key");
1066 caches.activeNodeKeysInL1_.insert(key);
1067 ret = caches.GetFrameNodeIndex(nullptr);
1068 EXPECT_EQ(ret, -1);
1069
1070 caches.node4key_.insert({ key, CacheItem() });
1071 caches.activeNodeKeysInL1_.insert(key);
1072 ret = caches.GetFrameNodeIndex(nullptr);
1073 EXPECT_EQ(ret, -1);
1074 }
1075 /**
1076 * @tc.name: RepeatNodeCacheTest035
1077 * @tc.desc: Test Multiple functions
1078 * @tc.type: FUNC
1079 */
1080 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest035, TestSize.Level1)
1081 {
1082 RepeatVirtualScrollCaches caches(cacheCountL24ttype,
1083 onCreateNode,
1084 g_onUpdateNode,
1085 g_onGetKeys4Range,
1086 g_onGetTypes4Range);
1087
1088 std::optional<std::string> key1 = caches.GetKey4Index(1, true);
1089 EXPECT_EQ(key1, "Key1");
1090 std::optional<std::string> key2 = caches.GetKey4Index(2, true);
1091 EXPECT_EQ(key2, "Key2");
1092 std::optional<std::string> key3 = caches.GetKey4Index(3, true);
1093 EXPECT_EQ(key3, "Key3");
1094 RefPtr<UINode> node1 = caches.CreateNewNode(1);
1095 EXPECT_NE(node1, nullptr);
1096 RefPtr<UINode> node2 = caches.CreateNewNode(2);
1097 EXPECT_NE(node2, nullptr);
1098 RefPtr<UINode> node3 = caches.CreateNewNode(3);
1099 EXPECT_NE(node3, nullptr);
1100
1101 auto repeatNode = RepeatVirtualScrollNode::GetOrCreateRepeatNode(
1102 1,
1103 3,
1104 templateCachedCountMap,
1105 onCreateNode,
1106 g_onUpdateNode,
1107 g_onGetKeys4Range,
1108 g_onGetTypes4Range,
1109 g_onSetActiveRange);
1110
1111 // Set caches to repeat.
1112 repeatNode->caches_ = caches;
1113 repeatNode->caches_.FetchMoreKeysTTypes(1, 3);
1114 repeatNode->caches_.AddKeyToL1("Key1");
1115 repeatNode->caches_.AddKeyToL1("Key2");
1116 repeatNode->caches_.AddKeyToL1("Key3");
1117
1118 std::set<int32_t> activeItems;
1119 const int largeValue = 100;
1120 for (int i = 0; i < largeValue; i++) {
1121 activeItems.insert(i);
1122 }
1123 std::set<int32_t> cachedItems;
1124 cachedItems.insert(1);
1125
1126 /**
1127 * @tc.steps: step2. Perform two DoSetActiveChildRange calls
1128 * First with valid value 1 and second too large value
1129 * @tc.expected: Functions do not return any value
1130 */
1131 repeatNode->DoSetActiveChildRange(activeItems, cachedItems, 1);
1132 repeatNode->DoSetActiveChildRange(activeItems, cachedItems, largeValue+1);
1133 }
1134
1135 /**
1136 * @tc.name: RepeatNodeCacheTest036
1137 * @tc.desc: Call functions that are currently empty implementations
1138 * @tc.type: FUNC
1139 */
1140 HWTEST_F(RepeatNodeCacheSyntaxTest, RepeatNodeCacheTest036, TestSize.Level1)
1141 {
1142 auto repeatNode = RepeatVirtualScrollNode::GetOrCreateRepeatNode(
1143 1,
1144 3,
1145 templateCachedCountMap,
1146 onCreateNode,
1147 g_onUpdateNode,
1148 g_onGetKeys4Range,
1149 g_onGetTypes4Range,
1150 g_onSetActiveRange);
1151
1152 EXPECT_NE(repeatNode, nullptr);
1153
__anona03fc19a0902(int32_t start, int32_t end) 1154 auto onMoveLambda = [](int32_t start, int32_t end) {
1155 };
1156 /**
1157 * @tc.steps: step1. Call functions with no implementation yet in repeat_virtual_scroll_node.cpp
1158 * @tc.expected: Not crash happens
1159 */
1160 repeatNode->SetOnMove(std::move(onMoveLambda));
1161 repeatNode->MoveData(0, 100);
1162 auto frameNode = repeatNode->GetFrameNode(1);
1163 repeatNode->InitDragManager(frameNode);
1164 repeatNode->InitAllChildrenDragManager(true);
1165 }
1166 } // namespace OHOS::Ace::NG