3
3
* All rights reserved.
4
4
*
5
5
* This source code is licensed under the BSD-style license found in the
6
- * LICENSE file in the root directory of this source tree. An additional grant
6
+ * LICENSE file in the root directory of this source tree. An additional grant
7
7
* of patent rights can be found in the PATENTS file in the same directory.
8
8
*/
9
9
40
40
return [arr sortedArrayUsingSelector: @selector (compare: )];
41
41
}
42
42
43
+ static NSArray *updatedArray (NSArray *oldArray, NSArray *newArray, IGListIndexSetResult *diff) {
44
+ NSMutableArray *result = [oldArray mutableCopy ];
45
+
46
+ NSMutableIndexSet *deletes = [diff.deletes mutableCopy ];
47
+ NSMutableIndexSet *inserts = [diff.inserts mutableCopy ];
48
+
49
+ NSMutableIndexSet *fromIndexes = [NSMutableIndexSet new ];
50
+ NSMutableIndexSet *toIndexes = [NSMutableIndexSet new ];
51
+
52
+ for (IGListMoveIndex *move in diff.moves ) {
53
+ [fromIndexes addIndex: move.from];
54
+ [toIndexes addIndex: move.to];
55
+ }
56
+
57
+ [deletes addIndexes: fromIndexes];
58
+ [inserts addIndexes: toIndexes];
59
+
60
+ [result removeObjectsAtIndexes: deletes];
61
+
62
+ NSArray *insertedObjects = [newArray objectsAtIndexes: inserts];
63
+ [result insertObjects: insertedObjects atIndexes: inserts];
64
+
65
+ return result;
66
+ }
67
+
43
68
@implementation IGListDiffTests
44
69
45
70
- (void )test_whenDiffingEmptyArrays_thatResultHasNoChanges {
@@ -65,26 +90,26 @@ - (void)test_whenDiffingToEmptyArray_thatResultHasChanges {
65
90
XCTAssertEqual ([result changeCount ], 1 );
66
91
}
67
92
68
- - (void )test_whenSwappingObjects_thatResultHasMoves {
93
+ - (void )test_whenSwappingNeighbors_thatResultHasSingleMove {
69
94
NSArray *o = @[@1 , @2 ];
70
95
NSArray *n = @[@2 , @1 ];
71
96
IGListIndexSetResult *result = IGListDiff (o, n, IGListDiffEquality);
72
97
NSArray *expected = @[
73
- [[IGListMoveIndex alloc ] initWithFrom: 0 to: 1 ],
74
- [[IGListMoveIndex alloc ] initWithFrom: 1 to: 0 ],
98
+ [[IGListMoveIndex alloc ] initWithFrom: 1 to: 0 ]
75
99
];
76
- NSArray <IGListMoveIndexPath *> *sortedMoves = sorted (result.moves );
77
- XCTAssertEqualObjects (sortedMoves, expected);
78
- XCTAssertEqual ([result changeCount ], 2 );
100
+ XCTAssertEqualObjects (result.moves , expected);
101
+ XCTAssertEqual ([result changeCount ], 1 );
79
102
}
80
103
81
104
- (void )test_whenMovingObjectsTogether_thatResultHasMoves {
82
105
// "trick" is having multiple @3s
83
106
NSArray *o = @[@1 , @2 , @3 , @3 , @4 ];
84
107
NSArray *n = @[@2 , @3 , @1 , @3 , @4 ];
85
108
IGListIndexSetResult *result = IGListDiff (o, n, IGListDiffEquality);
86
- IGAssertContains (result.moves , [[IGListMoveIndex alloc ] initWithFrom: 1 to: 0 ]);
87
- IGAssertContains (result.moves , [[IGListMoveIndex alloc ] initWithFrom: 0 to: 2 ]);
109
+ // IGAssertContains(result.moves, [[IGListMoveIndex alloc] initWithFrom:1 to:0]);
110
+ // IGAssertContains(result.moves, [[IGListMoveIndex alloc] initWithFrom:0 to:2]);
111
+
112
+ XCTAssertEqualObjects (updatedArray (o, n, result), n);
88
113
}
89
114
90
115
- (void )test_whenDiffingWordsFromPaper_withIndexPaths_thatDeletesMatchPaper {
@@ -115,10 +140,8 @@ - (void)test_whenSwappingObjects_withIndexPaths_thatResultHasMoves {
115
140
IGListIndexPathResult *result = IGListDiffPaths (0 , 0 , o, n, IGListDiffEquality);
116
141
NSArray *expected = @[
117
142
[[IGListMoveIndexPath alloc ] initWithFrom: genIndexPath (2 , 0 ) to: genIndexPath (3 , 0 )],
118
- [[IGListMoveIndexPath alloc ] initWithFrom: genIndexPath (3 , 0 ) to: genIndexPath (1 , 0 )],
119
143
];
120
- NSArray <IGListMoveIndexPath *> *sortedMoves = sorted (result.moves );
121
- XCTAssertEqualObjects (sortedMoves, expected);
144
+ XCTAssertEqualObjects (result.moves , expected);
122
145
}
123
146
124
147
- (void )test_whenObjectEqualityChanges_thatResultHasUpdates {
@@ -279,7 +302,7 @@ - (void)test_whenMovingObjectShiftsOthers_thatMovesContainRequiredMoves {
279
302
NSArray *n = @[@1 , @4 , @5 , @2 , @3 , @6 , @7 ];
280
303
IGListIndexSetResult *result = IGListDiff (o, n, IGListDiffEquality);
281
304
IGAssertContains (result.moves , [[IGListMoveIndex alloc ] initWithFrom: 3 to: 1 ]);
282
- IGAssertContains (result.moves , [[IGListMoveIndex alloc ] initWithFrom: 1 to: 3 ]);
305
+ IGAssertContains (result.moves , [[IGListMoveIndex alloc ] initWithFrom: 4 to: 2 ]);
283
306
}
284
307
285
308
- (void )test_whenDiffing_thatOldIndexesMatch {
@@ -404,4 +427,151 @@ - (void)test_whenDiffing_withBatchUpdateResult_thatIndexPathsMatch {
404
427
XCTAssertEqualObjects (sorted (result.inserts ), expectedInserts);
405
428
}
406
429
430
+ - (void )test_whenMovingBackward_thatIndexesMatch {
431
+ NSArray *o = @[ @0 , @1 , @2 , @3 , @4 , @5 ];
432
+ NSArray *n = @[ @5 , @4 , @0 , @1 , @2 , @3 ];
433
+ IGListIndexSetResult *result = [IGListDiff (o, n, IGListDiffEquality) resultForBatchUpdates ];
434
+ XCTAssertEqual (result.updates .count , 0 );
435
+ NSArray *expectedMoves = @[ [[IGListMoveIndex alloc ] initWithFrom: 5 to: 0 ],
436
+ [[IGListMoveIndex alloc ] initWithFrom: 4 to: 1 ] ];
437
+ XCTAssertEqualObjects (result.moves , expectedMoves);
438
+ NSMutableIndexSet *expectedDeletes = [NSMutableIndexSet new ];
439
+ XCTAssertEqualObjects (result.deletes , expectedDeletes);
440
+ NSMutableIndexSet *expectedInserts = [NSMutableIndexSet new ];
441
+ XCTAssertEqualObjects (result.inserts , expectedInserts);
442
+ }
443
+
444
+ - (void )test_whenMovingBackwardWithInsertionBefore_thatIndexesMatch {
445
+ NSArray *o = @[ @0 , @1 , @2 , @3 , @4 , @5 ];
446
+ NSArray *n = @[ @100 , @5 , @0 , @1 , @2 , @3 , @4 ];
447
+ IGListIndexSetResult *result = [IGListDiff (o, n, IGListDiffEquality) resultForBatchUpdates ];
448
+ XCTAssertEqual (result.updates .count , 0 );
449
+ NSArray *expectedMoves = @[ [[IGListMoveIndex alloc ] initWithFrom: 5 to: 1 ] ];
450
+ XCTAssertEqualObjects (result.moves , expectedMoves);
451
+ NSMutableIndexSet *expectedDeletes = [NSMutableIndexSet new ];
452
+ XCTAssertEqualObjects (result.deletes , expectedDeletes);
453
+ NSIndexSet *expectedInserts = [NSIndexSet indexSetWithIndex: 0 ];
454
+ XCTAssertEqualObjects (result.inserts , expectedInserts);
455
+ }
456
+
457
+ - (void )test_whenMovingBackwardWithInsertionInBetween_thatIndexesMatch {
458
+ NSArray *o = @[ @0 , @1 , @2 , @3 , @4 , @5 ];
459
+ NSArray *n = @[ @5 , @100 , @0 , @1 , @2 , @3 , @4 ];
460
+ IGListIndexSetResult *result = [IGListDiff (o, n, IGListDiffEquality) resultForBatchUpdates ];
461
+ XCTAssertEqual (result.updates .count , 0 );
462
+ NSArray *expectedMoves = @[ [[IGListMoveIndex alloc ] initWithFrom: 5 to: 0 ] ];
463
+ XCTAssertEqualObjects (result.moves , expectedMoves);
464
+ NSMutableIndexSet *expectedDeletes = [NSMutableIndexSet new ];
465
+ XCTAssertEqualObjects (result.deletes , expectedDeletes);
466
+ NSIndexSet *expectedInserts = [NSIndexSet indexSetWithIndex: 1 ];
467
+ XCTAssertEqualObjects (result.inserts , expectedInserts);
468
+ }
469
+
470
+ - (void )test_whenMovingBackwardWithDeletionBefore_thatIndexesMatch {
471
+ NSArray *o = @[ @0 , @1 , @2 , @3 , @4 , @5 ];
472
+ NSArray *n = @[ @1 , @4 , @5 , @2 , @3 ];
473
+ IGListIndexSetResult *result = [IGListDiff (o, n, IGListDiffEquality) resultForBatchUpdates ];
474
+ XCTAssertEqual (result.updates .count , 0 );
475
+ NSArray *expectedMoves = @[ [[IGListMoveIndex alloc ] initWithFrom: 4 to: 1 ],
476
+ [[IGListMoveIndex alloc ] initWithFrom: 5 to: 2 ] ];
477
+ XCTAssertEqualObjects (result.moves , expectedMoves);
478
+ NSIndexSet *expectedDeletes = [NSIndexSet indexSetWithIndex: 0 ];
479
+ XCTAssertEqualObjects (result.deletes , expectedDeletes);
480
+ NSIndexSet *expectedInserts = [NSIndexSet new ];
481
+ XCTAssertEqualObjects (result.inserts , expectedInserts);
482
+ }
483
+
484
+ - (void )test_whenMovingBackwardWithDeletionInBetween_thatIndexesMatch {
485
+ NSArray *o = @[ @0 , @1 , @2 , @3 , @4 , @5 ];
486
+ NSArray *n = @[ @5 , @0 , @2 , @3 , @4 ];
487
+ IGListIndexSetResult *result = [IGListDiff (o, n, IGListDiffEquality) resultForBatchUpdates ];
488
+ XCTAssertEqual (result.updates .count , 0 );
489
+ NSArray *expectedMoves = @[ [[IGListMoveIndex alloc ] initWithFrom: 5 to: 0 ] ];
490
+ XCTAssertEqualObjects (result.moves , expectedMoves);
491
+ NSIndexSet *expectedDeletes = [NSIndexSet indexSetWithIndex: 1 ];
492
+ XCTAssertEqualObjects (result.deletes , expectedDeletes);
493
+ NSIndexSet *expectedInserts = [NSIndexSet new ];
494
+ XCTAssertEqualObjects (result.inserts , expectedInserts);
495
+ }
496
+
497
+ - (void )test_whenMovingForward_thatIndexesMatch {
498
+ NSArray *o = @[ @0 , @1 , @2 , @3 , @4 , @5 ];
499
+ NSArray *n = @[ @2 , @3 , @4 , @5 , @1 , @0 ];
500
+ IGListIndexSetResult *result = [IGListDiff (o, n, IGListDiffEquality) resultForBatchUpdates ];
501
+ XCTAssertEqual (result.updates .count , 0 );
502
+ NSArray *expectedMoves = @[ [[IGListMoveIndex alloc ] initWithFrom: 1 to: 4 ],
503
+ [[IGListMoveIndex alloc ] initWithFrom: 0 to: 5 ] ];
504
+ XCTAssertEqualObjects (result.moves , expectedMoves);
505
+ NSMutableIndexSet *expectedDeletes = [NSMutableIndexSet new ];
506
+ XCTAssertEqualObjects (result.deletes , expectedDeletes);
507
+ NSMutableIndexSet *expectedInserts = [NSMutableIndexSet new ];
508
+ XCTAssertEqualObjects (result.inserts , expectedInserts);
509
+ }
510
+
511
+ - (void )test_whenMovingBothWays_thatIndexesMatch {
512
+ NSArray *o = @[ @0 , @1 , @2 , @3 , @4 , @5 ];
513
+ NSArray *n = @[ @1 , @2 , @0 , @5 , @3 , @4 ];
514
+ IGListIndexSetResult *result = [IGListDiff (o, n, IGListDiffEquality) resultForBatchUpdates ];
515
+ XCTAssertEqual (result.updates .count , 0 );
516
+ NSArray *expectedMoves = @[ [[IGListMoveIndex alloc ] initWithFrom: 0 to: 2 ],
517
+ [[IGListMoveIndex alloc ] initWithFrom: 5 to: 3 ] ];
518
+ XCTAssertEqualObjects (result.moves , expectedMoves);
519
+ NSMutableIndexSet *expectedDeletes = [NSMutableIndexSet new ];
520
+ XCTAssertEqualObjects (result.deletes , expectedDeletes);
521
+ NSMutableIndexSet *expectedInserts = [NSMutableIndexSet new ];
522
+ XCTAssertEqualObjects (result.inserts , expectedInserts);
523
+ }
524
+
525
+ - (void )test_whenRandomlyUpdating_thatApplyingDiffProducesSameArray {
526
+ NSArray *o = @[ @0 , @1 , @2 , @3 , @4 , @5 , @6 , @7 , @8 , @9 ];
527
+
528
+ for (int testIdx = 0 ; testIdx < 1000 ; testIdx ++) {
529
+
530
+ NSMutableArray *n = [o mutableCopy ];
531
+
532
+ for (int i = 0 ; i < 2 ; i++) {
533
+ [n removeObjectAtIndex: arc4random_uniform ((uint32_t ) n.count)];
534
+ }
535
+
536
+ NSMutableIndexSet *fromIndexes = [NSMutableIndexSet new ];
537
+ NSMutableIndexSet *toIndexes = [NSMutableIndexSet new ];
538
+
539
+ for (int i = 0 ; i < 2 ; i++) {
540
+ NSUInteger fromIdx;
541
+ do {
542
+ fromIdx = arc4random_uniform ((uint32_t ) n.count );
543
+ } while ([fromIndexes containsIndex: fromIdx] || [toIndexes containsIndex: fromIdx]);
544
+ [fromIndexes addIndex: fromIdx];
545
+
546
+ NSUInteger toIdx;
547
+ do {
548
+ toIdx = arc4random_uniform ((uint32_t ) n.count );
549
+ } while ([toIndexes containsIndex: fromIdx] || [toIndexes containsIndex: toIdx]);
550
+ [toIndexes addIndex: toIdx];
551
+ }
552
+
553
+ NSArray *movedObjects = [n objectsAtIndexes: fromIndexes];
554
+ [n removeObjectsAtIndexes: fromIndexes];
555
+ [n insertObjects: movedObjects atIndexes: toIndexes];
556
+
557
+ NSMutableIndexSet *inserts = [NSMutableIndexSet new ];
558
+ NSMutableArray *insertedObjects = [NSMutableArray new ];
559
+
560
+ for (int i = 0 ; i < 3 ; i++) {
561
+ NSUInteger idx;
562
+ do {
563
+ idx = arc4random_uniform ((uint32_t ) n.count );
564
+ } while ([inserts containsIndex: idx]);
565
+ [inserts addIndex: idx];
566
+ [insertedObjects addObject: @(n.count + i + 10 )];
567
+ }
568
+
569
+ [n insertObjects: insertedObjects atIndexes: inserts];
570
+
571
+ IGListIndexSetResult *result = [IGListDiff (o, n, IGListDiffEquality) resultForBatchUpdates ];
572
+ XCTAssertEqualObjects (updatedArray (o, n, result), n);
573
+ }
574
+ }
575
+
407
576
@end
577
+
0 commit comments