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 "repeat_virtual_2_test_ng.h"
17
18 using namespace testing;
19 using namespace testing::ext;
20
21 namespace OHOS::Ace::NG {
22
23 using CacheItem = RepeatVirtualScroll2Caches::CacheItem;
24 using OptCacheItem = RepeatVirtualScroll2Caches::OptCacheItem;
25 using GetFrameChildResult = RepeatVirtualScroll2Caches::GetFrameChildResult;
26
CreateNode(const std::string & tag)27 RefPtr<FrameNode> RepeatVirtual2TestNg::CreateNode(const std::string& tag)
28 {
29 auto pattern = AceType::MakeRefPtr<Pattern>();
30 auto frameNode = AceType::MakeRefPtr<FrameNode>(tag, elmtId_, pattern);
31 pattern->AttachToFrameNode(frameNode);
32 ViewStackProcessor::GetInstance()->Push(frameNode);
33 return frameNode;
34 }
35
CreateRepeatVirtualNode(uint32_t totalCount)36 RefPtr<RepeatVirtualScroll2Node> RepeatVirtual2TestNg::CreateRepeatVirtualNode(uint32_t totalCount)
37 {
38 l1Rid4Index_ = {
39 {0, 1},
40 {1, 2},
41 {2, 3},
42 {3, 4},
43 {4, 5},
44 {5, 6}
45 };
46 onGetRid4Index_ = [&](IndexType index) -> std::pair<RIDType, uint32_t> {
47 auto it = l1Rid4Index_.find(0);
48 if (it != l1Rid4Index_.end()) {
49 return {index, 2};
50 }
51 return {index, 1};
52 };
53 onRecycleItems_ = [](IndexType fromIndex, IndexType toIndex) -> void {
54 return;
55 };
56 onActiveRange_ = [](int32_t fromIndex, int32_t toIndex, int32_t vStart, int32_t vEnd, bool isLoop,
57 bool forceUpdate) -> void {
58 return;
59 };
60 onMoveFromTo_ = [](IndexType, IndexType) -> void {
61 return;
62 };
63 onPurge_ = []() -> void {
64 return;
65 };
66 return RepeatVirtualScroll2Node::GetOrCreateRepeatNode(
67 GetElmtId(), totalCount, totalCount, onGetRid4Index_, onRecycleItems_, onActiveRange_, onMoveFromTo_, onPurge_);
68 }
69
CreateListItemNode()70 RefPtr<FrameNode> RepeatVirtual2TestNg::CreateListItemNode()
71 {
72 auto tag = "TEXT_ETS_TAG";
73 auto* stack = ViewStackProcessor::GetInstance();
74 auto listItemFrameNode = FrameNode::GetOrCreateFrameNode(V2::LIST_ITEM_ETS_TAG, GetElmtId(), []() {
75 return AceType::MakeRefPtr<ListItemPattern>(nullptr, V2::ListItemStyle::NONE);
76 });
77
78 auto textNode = CreateNode(V2::TEXT_ETS_TAG);
79
80 auto pattern = AceType::MakeRefPtr<Pattern>();
81 auto textFrameNode = AceType::MakeRefPtr<FrameNode>(tag, GetElmtId(), pattern);
82 pattern->AttachToFrameNode(textFrameNode);
83 listItemFrameNode->AddChild(textFrameNode);
84
85 pattern = AceType::MakeRefPtr<Pattern>();
86 textFrameNode = AceType::MakeRefPtr<FrameNode>(tag, GetElmtId(), pattern);
87 pattern->AttachToFrameNode(textFrameNode);
88 listItemFrameNode->AddChild(textFrameNode);
89 stack->Push(listItemFrameNode);
90 return listItemFrameNode;
91 }
92
93 /**
94 * @tc.name: CreateRepeat001
95 * @tc.desc: Test creation of GetOrCreateRepeatNode
96 * @tc.type: FUNC
97 */
98 HWTEST_F(RepeatVirtual2TestNg, CreateRepeat001, TestSize.Level1)
99 {
100 auto* stack = ViewStackProcessor::GetInstance();
101 auto nodeId = stack->ClaimNodeId();
102 /**
103 * @tc.steps: step1. Create node object
104 * @tc.expected: Object is not nullptr.
105 */
106 auto repeatNode = RepeatVirtualScroll2Node::GetOrCreateRepeatNode(
107 nodeId, 10, 10, onGetRid4Index_, onRecycleItems_, onActiveRange_, onMoveFromTo_, onPurge_);
108
109 EXPECT_NE(repeatNode, nullptr);
110 }
111
112 /**
113 * @tc.name: FrameCount001
114 * @tc.desc: Test node.FrameCount
115 * @tc.type: FUNC
116 */
117 HWTEST_F(RepeatVirtual2TestNg, FrameCount001, TestSize.Level1)
118 {
119 auto repeatNode = CreateRepeatVirtualNode(10);
120
121 /**
122 * @tc.steps: step2. Get frame count
123 * @tc.expected: frame count should be 10
124 */
125 auto frameCount = repeatNode->FrameCount();
126 EXPECT_EQ(frameCount, 10);
127
128 /**
129 * @tc.steps: step2. Update totalCount to 2
130 * @tc.expected: frame count should be 2
131 */
132 repeatNode->UpdateTotalCount(2);
133 frameCount = repeatNode->FrameCount();
134 EXPECT_EQ(frameCount, 2);
135 }
136
137 /**
138 * @tc.name: GetChildren001
139 * @tc.desc: Test node.GetChildren
140 * @tc.type: FUNC
141 */
142 HWTEST_F(RepeatVirtual2TestNg, GetChildren001, TestSize.Level1)
143 {
144 /**
145 * @tc.steps: step1. Test node.GetChildren when repeat is empty
146 * @tc.expected: children size shoule be 0
147 */
148 auto repeatNode = CreateRepeatVirtualNode(10);
149 auto children = repeatNode->GetChildren();
150 EXPECT_EQ(children.size(), 0);
151
152 /**
153 * @tc.steps: step2. Test node.GetChildren when repeat has 1 item
154 * @tc.expected: children size shoule be 0
155 */
156 repeatNode->caches_.l1Rid4Index_ = {
157 {0, 1}
158 };
159 RefPtr<UINode> uiNode = AceType::MakeRefPtr<FrameNode>("node", 2002, AceType::MakeRefPtr<Pattern>());
160 CacheItem cacheItem = RepeatVirtualScroll2CacheItem::MakeCacheItem(uiNode, true);
161 std::map<RIDType, CacheItem> cacheItem4Rid_ = {{ 0, cacheItem }};
162 repeatNode->children_ = { uiNode };
163 children = repeatNode->GetChildren();
164 EXPECT_EQ(children.size(), 1);
165 }
166
167 /**
168 * @tc.name: GetFrameChild001
169 * @tc.desc: Test caches.GetFrameChild
170 * @tc.type: FUNC
171 */
172 HWTEST_F(RepeatVirtual2TestNg, GetFrameChild001, TestSize.Level1)
173 {
174 RepeatVirtualScroll2Caches caches(onGetRid4Index_);
175
176 /**
177 * @tc.steps: step1. give l1 cache items include item (rid == 1)
178 * @tc.expected: return rid
179 */
180 GetFrameChildResult result = caches.GetFrameChild(1, false);
181 EXPECT_EQ(result.second, 0);
182
183 /**
184 * @tc.steps: step2. give l1 cache items include item (rid == 10)
185 * @tc.expected: return nullptr
186 */
187 result = caches.GetFrameChild(10, false);
188 EXPECT_EQ(result.second, nullptr);
189 }
190
191 /**
192 * @tc.name: RemoveNode001
193 * @tc.desc: Test caches.RemoveNode
194 * @tc.type: FUNC
195 */
196 HWTEST_F(RepeatVirtual2TestNg, RemoveNode001, TestSize.Level1)
197 {
198 auto repeatNode = CreateRepeatVirtualNode(10);
199 repeatNode->caches_.l1Rid4Index_ = {
200 {0, 1}, {1, 2}, {2, 3}, {3, 4}
201 };
202 RefPtr<UINode> uiNode = AceType::MakeRefPtr<FrameNode>("node", 2004, AceType::MakeRefPtr<Pattern>());
203 CacheItem cacheItem = RepeatVirtualScroll2CacheItem::MakeCacheItem(uiNode, true);
204 repeatNode->caches_.cacheItem4Rid_ = {
205 { 1, cacheItem }, { 2, cacheItem }, { 3, cacheItem }, { 4, cacheItem }
206 };
207
208 /**
209 * @tc.steps: step1. remove 1 item from L1
210 * @tc.expected: repeat has 3 children left
211 */
212 EXPECT_EQ(repeatNode->GetChildren().size(), 4);
213 repeatNode->caches_.RemoveNode(2);
214 repeatNode->children_.clear();
215 EXPECT_EQ(repeatNode->GetChildren().size(), 3);
216 }
217
218 /**
219 * @tc.name: CheckActiveRange001
220 * @tc.desc: Test node.CheckActiveRange for List/Swiper-no-Loop scenario
221 * @tc.type: FUNC
222 */
223 HWTEST_F(RepeatVirtual2TestNg, CheckActiveRange001, TestSize.Level1)
224 {
225 auto repeatNode = CreateRepeatVirtualNode(10);
226 ActiveRangeType activeRange;
227
228 /**
229 * @tc.steps: step1. check active range: [0 1 2] 3 4 5..
230 * @tc.expected: active range is {0,4}
231 */
232 activeRange = repeatNode->CheckActiveRange(0, 2, 0, 2);
233 std::pair<IndexType, IndexType> expect_result1(0, 4);
234 EXPECT_EQ(activeRange, expect_result1);
235
236 /**
237 * @tc.steps: step2. check active range: ..1 2 [3 4 5] 6 7..
238 * @tc.expected: active range is {1,7}
239 */
240 activeRange = repeatNode->CheckActiveRange(3, 5, 2, 2);
241 std::pair<IndexType, IndexType> expect_result2(1, 7);
242 EXPECT_EQ(activeRange, expect_result2);
243
244 /**
245 * @tc.steps: step3. check active range: ..5 6 [7 8 9]
246 * @tc.expected: active range is {5,9}
247 */
248 activeRange = repeatNode->CheckActiveRange(7, 9, 2, 0);
249 std::pair<IndexType, IndexType> expect_result3(5, 9);
250 EXPECT_EQ(activeRange, expect_result3);
251 }
252
253 /**
254 * @tc.name: CheckActiveRange002
255 * @tc.desc: Test node.CheckActiveRange for Grid/WaterFlow scenario
256 * @tc.type: FUNC
257 */
258 HWTEST_F(RepeatVirtual2TestNg, CheckActiveRange002, TestSize.Level1)
259 {
260 auto repeatNode = CreateRepeatVirtualNode(10);
261 ActiveRangeType activeRange;
262
263 /**
264 * @tc.steps: step1. check active range for: [0 1 2] 3 4 5..
265 * @tc.expected: active range is {0,4}
266 */
267 activeRange = repeatNode->CheckActiveRange(0, 2, 2, 2);
268 std::pair<IndexType, IndexType> expect_result1(0, 4);
269 EXPECT_EQ(activeRange, expect_result1);
270
271 /**
272 * @tc.steps: step2. check active range for: ..1 2 [3 4 5] 6 7..
273 * @tc.expected: active range is {1,7}
274 */
275 activeRange = repeatNode->CheckActiveRange(3, 5, 2, 2);
276 std::pair<IndexType, IndexType> expect_result2(1, 7);
277 EXPECT_EQ(activeRange, expect_result2);
278
279 /**
280 * @tc.steps: step3. check active range for: ..5 6 [7 8 9]
281 * @tc.expected: active range is {5,9}
282 */
283 activeRange = repeatNode->CheckActiveRange(7, 9, 2, 2);
284 std::pair<IndexType, IndexType> expect_result3(5, 9);
285 EXPECT_EQ(activeRange, expect_result3);
286 }
287
288 /**
289 * @tc.name: CheckActiveRange003
290 * @tc.desc: Test node.CheckActiveRange for Swiper-Loop scenario
291 * @tc.type: FUNC
292 */
293 HWTEST_F(RepeatVirtual2TestNg, CheckActiveRange003, TestSize.Level1)
294 {
295 auto repeatNode = CreateRepeatVirtualNode(10);
296 repeatNode->SetIsLoop(true);
297 ActiveRangeType activeRange;
298
299 /**
300 * @tc.steps: step1. check active range for: ..8 9 [0 1 2] 3 4..
301 * @tc.expected: active range is {-2,4}
302 */
303 activeRange = repeatNode->CheckActiveRange(0, 2, 2, 2);
304 std::pair<IndexType, IndexType> expect_result1(-2, 4);
305 EXPECT_EQ(activeRange, expect_result1);
306
307 /**
308 * @tc.steps: step2. check active range for: ..7 8 [9 0 1] 2 3..
309 * @tc.expected: active range is {7,3}
310 */
311 activeRange = repeatNode->CheckActiveRange(9, 1, 2, 2);
312 std::pair<IndexType, IndexType> expect_result2(7, 3);
313 EXPECT_EQ(activeRange, expect_result2);
314
315 /**
316 * @tc.steps: step3. check active range for: ..5 6 [7 8 9] 0 1..
317 * @tc.expected: active range is {5,11}
318 */
319 activeRange = repeatNode->CheckActiveRange(7, 9, 2, 2);
320 std::pair<IndexType, IndexType> expect_result3(5, 11);
321 EXPECT_EQ(activeRange, expect_result3);
322
323 /**
324 * @tc.steps: step4. check active range for: 2 [3 0] 1
325 * @tc.expected: active range is {3,2} (overlapped)
326 */
327 auto repeatNode2 = CreateRepeatVirtualNode(4);
328 repeatNode2->SetIsLoop(true);
329 activeRange = repeatNode2->CheckActiveRange(3, 0, 2, 2);
330 std::pair<IndexType, IndexType> expect_result4(3, 2);
331 EXPECT_EQ(activeRange, expect_result4);
332
333 /**
334 * @tc.steps: step5. check active range for: [0 1] 2 3..
335 * @tc.expected: active range is {-2,3}
336 */
337 auto repeatNode3 = CreateRepeatVirtualNode(10);
338 repeatNode3->SetIsLoop(true);
339 activeRange = repeatNode3->CheckActiveRange(0, 1, 2, 2);
340 std::pair<IndexType, IndexType> expect_result5(-2, 3);
341 EXPECT_EQ(activeRange, expect_result5);
342 }
343
344 /**
345 * @tc.name: CheckActiveRange004
346 * @tc.desc: Test node.CheckActiveRange for List/Grid/WaterFlow/Swiper-no-Loop scenario (multiple components)
347 * X indicates a non-repeat child
348 * @tc.type: FUNC
349 */
350 HWTEST_F(RepeatVirtual2TestNg, CheckActiveRange004, TestSize.Level1)
351 {
352 auto repeatNode = CreateRepeatVirtualNode(10);
353 ActiveRangeType activeRange;
354
355 /**
356 * @tc.steps: step1. check active range for: ..[X X 0 1 2] 3 4..
357 * @tc.expected: active range is {0,4}
358 */
359 activeRange = repeatNode->CheckActiveRange(-2, 2, 2, 2);
360 std::pair<IndexType, IndexType> expect_result1(0, 4);
361 EXPECT_EQ(activeRange, expect_result1);
362
363 /**
364 * @tc.steps: step2. check active range for: ..[X X X] 0 1 2..
365 * @tc.expected: active range is {0,1}
366 */
367 activeRange = repeatNode->CheckActiveRange(-5, -1, 2, 2);
368 std::pair<IndexType, IndexType> expect_result2(0, 1);
369 EXPECT_EQ(activeRange, expect_result2);
370
371 /**
372 * @tc.steps: step3. check active range for: ..[X X X] X X 0 1..
373 * @tc.expected: active range is {INT32_MAX,INT32_MAX}
374 */
375 activeRange = repeatNode->CheckActiveRange(-5, -3, 2, 2);
376 std::pair<IndexType, IndexType> expect_result3(INT32_MAX, INT32_MAX);
377 EXPECT_EQ(activeRange, expect_result3);
378
379 /**
380 * @tc.steps: step4. check active range for: ..5 6 [7 8 9 X X]..
381 * @tc.expected: active range is {5,9}
382 */
383 activeRange = repeatNode->CheckActiveRange(7, 11, 2, 2);
384 std::pair<IndexType, IndexType> expect_result4(5, 9);
385 EXPECT_EQ(activeRange, expect_result4);
386
387 /**
388 * @tc.steps: step5. check active range for: ..8 9 [X X X]..
389 * @tc.expected: active range is {8,9}
390 */
391 activeRange = repeatNode->CheckActiveRange(10, 12, 2, 2);
392 std::pair<IndexType, IndexType> expect_result5(8, 9);
393 EXPECT_EQ(activeRange, expect_result5);
394
395 /**
396 * @tc.steps: step6. check active range for: ..8 9 X X [X X X]..
397 * @tc.expected: active range is {INT32_MAX,INT32_MAX}
398 */
399 activeRange = repeatNode->CheckActiveRange(12, 14, 2, 2);
400 std::pair<IndexType, IndexType> expect_result6(INT32_MAX, INT32_MAX);
401 EXPECT_EQ(activeRange, expect_result6);
402 }
403
404 /**
405 * @tc.name: CheckNodeInL1001
406 * @tc.desc: Test node.CheckNode4IndexInL1
407 * @tc.type: FUNC
408 */
409 HWTEST_F(RepeatVirtual2TestNg, CheckNodeInL1001, TestSize.Level1)
410 {
411 auto repeatNode = CreateRepeatVirtualNode(10);
412 RefPtr<UINode> uiNode = AceType::MakeRefPtr<FrameNode>("node", 2009, AceType::MakeRefPtr<Pattern>());
413 CacheItem cacheItem = RepeatVirtualScroll2CacheItem::MakeCacheItem(uiNode, true);
414 bool remainInL1;
415
416 /**
417 * @tc.steps: step1. check normal active range
418 * @tc.expected: node in L1 cache, return true
419 */
420 remainInL1 = repeatNode->CheckNode4IndexInL1(1, 0, 9, cacheItem);
421 EXPECT_EQ(remainInL1, true);
422 remainInL1 = repeatNode->CheckNode4IndexInL1(5, 6, 9, cacheItem);
423 EXPECT_EQ(remainInL1, false);
424 remainInL1 = repeatNode->CheckNode4IndexInL1(10, 6, 9, cacheItem);
425 EXPECT_EQ(remainInL1, false);
426
427 /**
428 * @tc.steps: step2. check swiper-loop range
429 * @tc.expected: node in L1 cache, return true
430 */
431 repeatNode->SetIsLoop(true);
432 remainInL1 = repeatNode->CheckNode4IndexInL1(5, 0, 9, cacheItem);
433 EXPECT_EQ(remainInL1, true);
434 remainInL1 = repeatNode->CheckNode4IndexInL1(3, 2, 1, cacheItem);
435 EXPECT_EQ(remainInL1, true);
436 }
437
438 /**
439 * @tc.name: SetActiveRange001
440 * @tc.desc: Test node.DoSetActiveChildRange
441 * @tc.type: FUNC
442 */
443 HWTEST_F(RepeatVirtual2TestNg, SetActiveRange001, TestSize.Level1)
444 {
445 auto repeatNode = CreateRepeatVirtualNode(10);
446
447 /**
448 * @tc.steps: step1. check normal active range
449 * @tc.expected: repeat has 8 items
450 */
451 repeatNode->children_.clear();
452 RefPtr<UINode> uiNode = AceType::MakeRefPtr<FrameNode>("node", 2010, AceType::MakeRefPtr<Pattern>());
453 CacheItem cacheItem = RepeatVirtualScroll2CacheItem::MakeCacheItem(uiNode, true);
454 for (int i = 0; i < 10; ++i) {
455 repeatNode->caches_.l1Rid4Index_.insert({i, i + 1});
456 repeatNode->caches_.cacheItem4Rid_.insert({i + 1, cacheItem});
457 }
458 repeatNode->DoSetActiveChildRange(0, 5, 2, 2);
459 EXPECT_EQ(repeatNode->GetChildren().size(), 8);
460
461 /**
462 * @tc.steps: step2. check swiper-loop range
463 * @tc.expected: repeat has 6 items
464 */
465 repeatNode->children_.clear();
466 repeatNode->caches_.l1Rid4Index_.clear();
467 for (int i = 0; i < 10; ++i) {
468 repeatNode->caches_.l1Rid4Index_.insert({i, i + 1});
469 repeatNode->caches_.cacheItem4Rid_.insert({i + 1, cacheItem});
470 }
471 repeatNode->SetIsLoop(true);
472 repeatNode->DoSetActiveChildRange(8, 1, 1, 1);
473 EXPECT_EQ(repeatNode->GetChildren().size(), 6);
474 }
475
476 /**
477 * @tc.name: GetL1Nodes001
478 * @tc.desc: Test caches.GetL1Index4Node
479 * @tc.type: FUNC
480 */
481 HWTEST_F(RepeatVirtual2TestNg, GetL1Nodes001, TestSize.Level1)
482 {
483 auto repeatNode = CreateRepeatVirtualNode(10);
484 RefPtr<UINode> uiNode = AceType::MakeRefPtr<FrameNode>("node", 2011, AceType::MakeRefPtr<Pattern>());
485 CacheItem cacheItem = RepeatVirtualScroll2CacheItem::MakeCacheItem(uiNode, true);
486 repeatNode->caches_.l1Rid4Index_ = {
487 {0, 1}
488 };
489 repeatNode->caches_.cacheItem4Rid_ = {
490 {1, cacheItem}
491 };
492
493 /**
494 * @tc.steps: step1.
495 * @tc.expected: GetL1Index4Node return 1
496 */
497 std::optional<IndexType> result = repeatNode->caches_.GetL1Index4Node(AceType::DynamicCast<FrameNode>(uiNode));
498 EXPECT_EQ(result.value(), 0);
499 }
500
501 /**
502 * @tc.name: GetAllNodes001
503 * @tc.desc: Test caches.GetCacheItem4RID
504 * @tc.type: FUNC
505 */
506 HWTEST_F(RepeatVirtual2TestNg, GetAllNodes001, TestSize.Level1)
507 {
508 auto repeatNode = CreateRepeatVirtualNode(10);
509 RefPtr<UINode> uiNode = AceType::MakeRefPtr<FrameNode>("node", 2012, AceType::MakeRefPtr<Pattern>());
510 CacheItem cacheItem = RepeatVirtualScroll2CacheItem::MakeCacheItem(uiNode, true);
511
512 /**
513 * @tc.steps: step1.
514 * @tc.expected: should return cacheItem
515 */
516 repeatNode->caches_.l1Rid4Index_ = {
517 {0, 1}
518 };
519 repeatNode->caches_.cacheItem4Rid_ = {
520 {1, cacheItem}
521 };
522 OptCacheItem optCacheItem = repeatNode->caches_.GetCacheItem4RID(1);
523 EXPECT_EQ(optCacheItem.has_value(), true);
524 }
525
526 /**
527 * @tc.name: GetRID4Index001
528 * @tc.desc: Test caches.GetRID4Index
529 * @tc.type: FUNC
530 */
531 HWTEST_F(RepeatVirtual2TestNg, GetRID4Index001, TestSize.Level1)
532 {
533 auto repeatNode = CreateRepeatVirtualNode(10);
534 RefPtr<UINode> uiNode = AceType::MakeRefPtr<FrameNode>("node", 2013, AceType::MakeRefPtr<Pattern>());
535 CacheItem cacheItem = RepeatVirtualScroll2CacheItem::MakeCacheItem(uiNode, true);
536
537 /**
538 * @tc.steps: step1.
539 * @tc.expected: should return rid=1
540 */
541 repeatNode->caches_.l1Rid4Index_ = {
542 {0, 1}
543 };
544 repeatNode->caches_.cacheItem4Rid_ = {
545 {1, cacheItem}
546 };
547 std::optional<RIDType> rid = repeatNode->caches_.GetRID4Index(0);
548 EXPECT_EQ(rid.value(), 1);
549 }
550
551 /**
552 * @tc.name: CallOnGetRid4Index001
553 * @tc.desc: Test caches.CallOnGetRid4Index
554 * @tc.type: FUNC
555 */
556 HWTEST_F(RepeatVirtual2TestNg, CallOnGetRid4Index001, TestSize.Level1)
557 {
558 auto repeatNode = CreateRepeatVirtualNode(10);
559
__anon31d030f10702(IndexType index)560 repeatNode->caches_.onGetRid4Index_ = [](IndexType index)->std::pair<RIDType, uint32_t> {
561 return {1, OnGetRid4IndexResult::CREATED_NEW_NODE}; };
562 auto item0 = repeatNode->caches_.CallOnGetRid4Index(0).value();
563 EXPECT_EQ(item0, nullptr);
564
__anon31d030f10802(IndexType index)565 repeatNode->caches_.onGetRid4Index_ = [&](IndexType index)->std::pair<RIDType, uint32_t> {
566 CreateListItemNode(); return {1, OnGetRid4IndexResult::CREATED_NEW_NODE}; };
567 auto item1 = repeatNode->caches_.CallOnGetRid4Index(0).value();
568 EXPECT_EQ(item1->node_->GetId(), 10002);
569
__anon31d030f10902(IndexType index)570 repeatNode->caches_.onGetRid4Index_ = [&](IndexType index)->std::pair<RIDType, uint32_t> {
571 CreateListItemNode(); return {0, OnGetRid4IndexResult::CREATED_NEW_NODE}; };
572 auto item2 = repeatNode->caches_.CallOnGetRid4Index(0);
573 EXPECT_EQ(item2, std::nullopt);
574
__anon31d030f10a02(IndexType index)575 repeatNode->caches_.onGetRid4Index_ = [](IndexType index)->std::pair<RIDType, uint32_t> {
576 return {1, OnGetRid4IndexResult::UPDATED_NODE}; };
577 auto item3 = repeatNode->caches_.CallOnGetRid4Index(0).value();
578 EXPECT_EQ(item3->node_->GetId(), 10002);
579
__anon31d030f10b02(IndexType index)580 repeatNode->caches_.onGetRid4Index_ = [](IndexType index)->std::pair<RIDType, uint32_t> {
581 return {2, OnGetRid4IndexResult::UPDATED_NODE}; };
582 auto item4 = repeatNode->caches_.CallOnGetRid4Index(0);
583 EXPECT_EQ(item4, std::nullopt);
584
__anon31d030f10c02(IndexType index)585 repeatNode->caches_.onGetRid4Index_ = [](IndexType index)->std::pair<RIDType, uint32_t> {
586 return {1, OnGetRid4IndexResult::UPDATED_NODE}; };
587 repeatNode->caches_.GetCacheItem4RID(1).value()->node_ = nullptr;
588 auto item5 = repeatNode->caches_.CallOnGetRid4Index(0);
589 EXPECT_EQ(item5, std::nullopt);
590
__anon31d030f10d02(IndexType index)591 repeatNode->caches_.onGetRid4Index_ = [](IndexType index)->std::pair<RIDType, uint32_t> {
592 return {0, OnGetRid4IndexResult::UPDATED_NODE}; };
593 auto item6 = repeatNode->caches_.CallOnGetRid4Index(0);
594 EXPECT_EQ(item6, std::nullopt);
595
__anon31d030f10e02(IndexType index)596 repeatNode->caches_.onGetRid4Index_ = [](IndexType index)->std::pair<RIDType, uint32_t> {
597 return {1, OnGetRid4IndexResult::NO_NODE}; };
598 auto item7 = repeatNode->caches_.CallOnGetRid4Index(0);
599 EXPECT_EQ(item7, std::nullopt);
600 }
601
602 /**
603 * @tc.name: ConvertFromToIndex001
604 * @tc.desc: Test caches.ConvertFromToIndex
605 * @tc.type: FUNC
606 */
607 HWTEST_F(RepeatVirtual2TestNg, ConvertFromToIndex001, TestSize.Level1)
608 {
609 auto repeatNode = CreateRepeatVirtualNode(6);
610 repeatNode->MoveData(0, 1);
611 repeatNode->MoveData(1, 2);
612 repeatNode->MoveData(2, 3);
613
614 /**
615 * @tc.steps: step1.
616 * @tc.expected: index is 0, mappedIndex should be 1.
617 */
618 IndexType mappedIndex = repeatNode->caches_.ConvertFromToIndex(0);
619 EXPECT_EQ(mappedIndex, 1);
620
621 /**
622 * @tc.steps: step2.
623 * @tc.expected: index is 1, mappedIndex should be 2.
624 */
625 mappedIndex = repeatNode->caches_.ConvertFromToIndex(1);
626 EXPECT_EQ(mappedIndex, 2);
627
628 /**
629 * @tc.steps: step3.
630 * @tc.expected: index is 2, mappedIndex should be 3.
631 */
632 mappedIndex = repeatNode->caches_.ConvertFromToIndex(2);
633 EXPECT_EQ(mappedIndex, 3);
634
635 /**
636 * @tc.steps: step4.
637 * @tc.expected: index is 3, mappedIndex should be 0.
638 */
639 mappedIndex = repeatNode->caches_.ConvertFromToIndex(3);
640 EXPECT_EQ(mappedIndex, 0);
641
642 /**
643 * @tc.steps: step5.
644 * @tc.expected: index is 4, 5, 6, mappedIndex should be same with index.
645 */
646 mappedIndex = repeatNode->caches_.ConvertFromToIndex(4);
647 EXPECT_EQ(mappedIndex, 4);
648 mappedIndex = repeatNode->caches_.ConvertFromToIndex(5);
649 EXPECT_EQ(mappedIndex, 5);
650 mappedIndex = repeatNode->caches_.ConvertFromToIndex(6);
651 EXPECT_EQ(mappedIndex, 6);
652 }
653
654 /**
655 * @tc.name: ConvertFromToIndex002
656 * @tc.desc: Test caches.ConvertFromToIndexRevert
657 * @tc.type: FUNC
658 */
659 HWTEST_F(RepeatVirtual2TestNg, ConvertFromToIndex002, TestSize.Level1)
660 {
661 auto repeatNode = CreateRepeatVirtualNode(6);
662 repeatNode->MoveData(0, 1);
663 repeatNode->MoveData(1, 2);
664 repeatNode->MoveData(2, 3);
665
666 /**
667 * @tc.steps: step1.
668 * @tc.expected: index is 0, mappedIndex should be 3.
669 */
670 IndexType mappedIndex = repeatNode->caches_.ConvertFromToIndexRevert(0);
671 EXPECT_EQ(mappedIndex, 3);
672
673 /**
674 * @tc.steps: step2.
675 * @tc.expected: index is 1, mappedIndex should be 0.
676 */
677 mappedIndex = repeatNode->caches_.ConvertFromToIndexRevert(1);
678 EXPECT_EQ(mappedIndex, 0);
679
680 /**
681 * @tc.steps: step3.
682 * @tc.expected: index is 2, mappedIndex should be 1.
683 */
684 mappedIndex = repeatNode->caches_.ConvertFromToIndexRevert(2);
685 EXPECT_EQ(mappedIndex, 1);
686
687 /**
688 * @tc.steps: step4.
689 * @tc.expected: index is 3, mappedIndex should be 2.
690 */
691 mappedIndex = repeatNode->caches_.ConvertFromToIndexRevert(3);
692 EXPECT_EQ(mappedIndex, 2);
693
694 /**
695 * @tc.steps: step5.
696 * @tc.expected: index is 4, 5, 6, mappedIndex should be same with index.
697 */
698 mappedIndex = repeatNode->caches_.ConvertFromToIndexRevert(4);
699 EXPECT_EQ(mappedIndex, 4);
700 mappedIndex = repeatNode->caches_.ConvertFromToIndexRevert(5);
701 EXPECT_EQ(mappedIndex, 5);
702 mappedIndex = repeatNode->caches_.ConvertFromToIndexRevert(6);
703 EXPECT_EQ(mappedIndex, 6);
704 }
705
706 /**
707 * @tc.name: UpdateFrameChildIndexRecord001
708 * @tc.desc: Test node.updateFrameChildIndexRecord
709 * @tc.type: FUNC
710 */
711 HWTEST_F(RepeatVirtual2TestNg, UpdateFrameChildIndexRecord001, TestSize.Level1)
712 {
713 auto repeatNode = CreateRepeatVirtualNode(6);
714 repeatNode->minFrameChildIndex_ = 0;
715 repeatNode->maxFrameChildIndex_ = 0;
716 repeatNode->needRecordFirstFrameChild_ = true;
717
718 /**
719 * @tc.steps: step1.
720 * @tc.expected: minFrameChildIndex_ is 2, maxFrameChildIndex_ is 2, needRecordFirstFrameChild_ is false.
721 */
722 repeatNode->updateFrameChildIndexRecord(2);
723 EXPECT_EQ(repeatNode->minFrameChildIndex_, 2);
724 EXPECT_EQ(repeatNode->maxFrameChildIndex_, 2);
725 EXPECT_EQ(repeatNode->needRecordFirstFrameChild_, false);
726
727 /**
728 * @tc.steps: step2.
729 * @tc.expected: minFrameChildIndex_ is 1, maxFrameChildIndex_ is 3
730 */
731 repeatNode->updateFrameChildIndexRecord(1);
732 repeatNode->updateFrameChildIndexRecord(3);
733 EXPECT_EQ(repeatNode->minFrameChildIndex_, 1);
734 EXPECT_EQ(repeatNode->maxFrameChildIndex_, 3);
735 }
736
737 /**
738 * @tc.name: NotifyColorModeChange001
739 * @tc.desc: Test caches.NotifyColorModeChange
740 * @tc.type: FUNC
741 */
742 HWTEST_F(RepeatVirtual2TestNg, NotifyColorModeChange001, TestSize.Level1)
743 {
744 auto repeatNode = CreateRepeatVirtualNode(10);
745 repeatNode->caches_.l1Rid4Index_ = {
746 {0, 1}, {1, 2}, {2, 3}, {3, 4}
747 };
748 RefPtr<UINode> uiNode = AceType::MakeRefPtr<FrameNode>("node", 2016, AceType::MakeRefPtr<Pattern>());
749 CacheItem cacheItem = RepeatVirtualScroll2CacheItem::MakeCacheItem(uiNode, true);
750 repeatNode->caches_.cacheItem4Rid_ = {
751 { 1, cacheItem }, { 2, cacheItem }, { 3, cacheItem }, { 4, cacheItem }
752 };
753 repeatNode->NotifyColorModeChange(1);
754 EXPECT_TRUE(cacheItem->node_->measureAnyWay_);
755 }
756
757 /**
758 * @tc.name: NotifyColorModeChange002
759 * @tc.desc: Test caches.NotifyColorModeChange
760 * @tc.type: FUNC
761 */
762 HWTEST_F(RepeatVirtual2TestNg, NotifyColorModeChange002, TestSize.Level1)
763 {
764 auto repeatNode = CreateRepeatVirtualNode(10);
765 repeatNode->caches_.l1Rid4Index_ = {
766 {0, 1}
767 };
768 RefPtr<UINode> uiNode = AceType::MakeRefPtr<CustomNode>(2016, "node");
769 RefPtr<UINode> childNode = AceType::MakeRefPtr<CustomNode>(2016, "childNode");
770 uiNode->children_ = { childNode };
771 uiNode->SetDarkMode(true);
772 CacheItem cacheItem = RepeatVirtualScroll2CacheItem::MakeCacheItem(uiNode, true);
773 repeatNode->caches_.cacheItem4Rid_ = {
774 { 1, cacheItem }
775 };
776 EXPECT_FALSE(childNode->CheckIsDarkMode());
777 repeatNode->NotifyColorModeChange(1);
778 EXPECT_TRUE(childNode->CheckIsDarkMode());
779 }
780
781 /**
782 * @tc.name: UpdateIsL1001
783 * @tc.desc: Test caches.UpdateIsL1
784 * @tc.type: FUNC
785 */
786 HWTEST_F(RepeatVirtual2TestNg, UpdateIsL1001, TestSize.Level1)
787 {
788 auto repeatNode = CreateRepeatVirtualNode(10);
789 RefPtr<UINode> uiNode = AceType::MakeRefPtr<FrameNode>("node", 2017, AceType::MakeRefPtr<Pattern>());
790 CacheItem cacheItem0 = RepeatVirtualScroll2CacheItem::MakeCacheItem(uiNode, true);
791 CacheItem cacheItem1 = RepeatVirtualScroll2CacheItem::MakeCacheItem(uiNode, true);
792 cacheItem0->node_ = nullptr;
793 repeatNode->caches_.UpdateIsL1(cacheItem0, false);
794 EXPECT_EQ(cacheItem0->isL1_, false);
795 EXPECT_EQ(repeatNode->caches_.recycledNodeIds_.size(), 0);
796 repeatNode->caches_.UpdateIsL1(cacheItem1, false);
797 EXPECT_EQ(cacheItem1->isL1_, false);
798 EXPECT_EQ(repeatNode->caches_.recycledNodeIds_.size(), 1);
799 repeatNode->caches_.UpdateIsL1(cacheItem0, true);
800 EXPECT_EQ(cacheItem0->isL1_, true);
801 EXPECT_EQ(repeatNode->caches_.recycledNodeIds_.size(), 1);
802 repeatNode->caches_.UpdateIsL1(cacheItem1, true);
803 EXPECT_EQ(cacheItem1->isL1_, true);
804 EXPECT_EQ(repeatNode->caches_.recycledNodeIds_.size(), 0);
805 repeatNode->caches_.UpdateIsL1(cacheItem1, false, false);
806 EXPECT_EQ(cacheItem1->isL1_, false);
807 EXPECT_EQ(repeatNode->caches_.recycledNodeIds_.size(), 0);
808 }
809
810 /**
811 * @tc.name: UpdateL1Rid4Index001
812 * @tc.desc: Test caches.UpdateL1Rid4Index
813 * @tc.type: FUNC
814 */
815 HWTEST_F(RepeatVirtual2TestNg, UpdateL1Rid4Index001, TestSize.Level1)
816 {
817 auto repeatNode = CreateRepeatVirtualNode(10);
818 RefPtr<UINode> uiNode0 = AceType::MakeRefPtr<FrameNode>("node", 2018, AceType::MakeRefPtr<Pattern>());
819 RefPtr<UINode> uiNode1 = AceType::MakeRefPtr<FrameNode>("node", 2019, AceType::MakeRefPtr<Pattern>());
820 RefPtr<UINode> uiNode2 = AceType::MakeRefPtr<FrameNode>("node", 2020, AceType::MakeRefPtr<Pattern>());
821 CacheItem cacheItem0 = RepeatVirtualScroll2CacheItem::MakeCacheItem(uiNode0, true);
822 CacheItem cacheItem1 = RepeatVirtualScroll2CacheItem::MakeCacheItem(uiNode1, true);
823 CacheItem cacheItem2 = RepeatVirtualScroll2CacheItem::MakeCacheItem(uiNode2, false);
824 repeatNode->caches_.cacheItem4Rid_ = {
825 { 1, cacheItem0 }, { 2, cacheItem1 }, { 3, cacheItem2 }
826 };
827 repeatNode->caches_.UpdateL1Rid4Index({ { 1, 2 }, { 2, 3 } }, { 2 });
828 EXPECT_EQ(cacheItem0->isL1_, false);
829 EXPECT_EQ(cacheItem1->isL1_, true);
830 EXPECT_EQ(cacheItem2->isL1_, true);
831 }
832
833 } // namespace OHOS::Ace::NG