From e99e2660e9946c67a233bb45d6a0d4055cd4fb8c Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Fri, 16 Sep 2011 11:43:42 +0200 Subject: [PATCH] more fixes and tests for _CPKVCArray --- Foundation/CPArray+KVO.j | 34 +++++++++--- Tests/Foundation/CPKVCArrayTest.j | 88 +++++++++++++++++++++++++++++-- 2 files changed, 112 insertions(+), 10 deletions(-) diff --git a/Foundation/CPArray+KVO.j b/Foundation/CPArray+KVO.j index 8000d2076..d58666ff2 100644 --- a/Foundation/CPArray+KVO.j +++ b/Foundation/CPArray+KVO.j @@ -303,6 +303,32 @@ [self removeObject:anObject inRange:CPMakeRange(0, [self count])]; } +- (void)removeObjectsInArray:(CPArray)theObjects +{ + if (_removeMany) + { + var indexes = [CPIndexSet indexSet], + index = [theObjects count]; + + while (index--) + [indexes addIndex:[self indexOfObject:[theObjects objectAtIndex:index]]]; + + _removeMany(_proxyObject, _removeManySEL, indexes); + } + else if (_remove) + { + var index = [theObjects count]; + while (index--) + _remove(_proxyObject, _removeSEL, [self indexOfObject:[theObjects objectAtIndex:index]]); + } + else + { + var target = [[self _representedObject] copy]; + [target removeObjectsInArray:theObjects]; + [self _setRepresentedObject:target]; + } +} + - (void)removeObject:(id)theObject inRange:(CPRange)theRange { if (_remove) @@ -326,13 +352,7 @@ - (void)removeLastObject { - if (_remove) - return _remove(_proxyObject, _removeSEL, [self count] - 1); - - var target = [[self _representedObject] copy]; - - [target removeLastObject]; - [self _setRepresentedObject:target]; + [self removeObjectsAtIndexes:[CPIndexSet indexSetWithIndex:[self count] - 1]]; } - (void)removeObjectAtIndex:(unsigned)anIndex diff --git a/Tests/Foundation/CPKVCArrayTest.j b/Tests/Foundation/CPKVCArrayTest.j index f29bd7d91..52f087856 100644 --- a/Tests/Foundation/CPKVCArrayTest.j +++ b/Tests/Foundation/CPKVCArrayTest.j @@ -16,6 +16,29 @@ var COUNTER; - (void)_patchSelector:(SEL)theSelector { + var method_dtable = [[self object] class].method_dtable, + method_list = [[self object] class].method_list, + selectorsToRemove = [@selector(countOfValues), @selector(objectInValuesAtIndex), + @selector(objectInValuesAtIndex:), @selector(valuesAtIndexes:), + @selector(insertObject:inValuesAtIndex:), @selector(insertValues:atIndexes:), + @selector(removeObjectFromValuesAtIndex:), @selector(removeValuesAtIndexes:), + @selector(removeObjectFromValuesAtIndex:), + @selector(replaceObjectInValuesAtIndex:withObject:), + @selector(replaceValuesAtIndexes:withValues:)], + selectorIndex = [selectorsToRemove count]; + + while (selectorIndex--) + { + var selector = [selectorsToRemove objectAtIndex:selectorIndex], + implementation = method_dtable[selector]; + + if (!implementation) + continue; + + delete method_dtable[selector] + [method_list removeObject:implementation]; + } + var method = class_getInstanceMethod([[self implementedObject] class], theSelector), implementation = method_getImplementation(method); @@ -122,7 +145,7 @@ var COUNTER; message:@"insertValues:atIndexes: should have been called once for each object"]; } -- (void)testRemoveObjectAtIndexUsesRemoveKeyAtIndex +- (void)testRemoveObjectAtIndexUsesRemoveObjectFromKeyAtIndex { [self _patchSelector:@selector(removeObjectFromValuesAtIndex:)]; @@ -132,7 +155,7 @@ var COUNTER; [self assert:1 equals:COUNTER message:@"removeObjectFromValuesAtIndex: should have been called once"]; } -- (void)testRemoveObjectAtIndexesUsesRemoveKeyAtIndex +- (void)testRemoveObjectAtIndexesUsesRemoveObjectFromKeyAtIndex { [self _patchSelector:@selector(removeObjectFromValuesAtIndex:)]; @@ -142,7 +165,6 @@ var COUNTER; [self assert:[2, 3, 4, 5, 6, 7, 8, 9] equals:[[self object] values]]; [self assert:2 equals:COUNTER message:@"removeValuesAtIndex: should have been called once for each object"]; } - - (void)testRemoveObjectsAtIndexesUsesRemoveKeyAtIndex { [self _patchSelector:@selector(removeValuesAtIndexes:)]; @@ -166,6 +188,66 @@ var COUNTER; [self assert:1 equals:COUNTER message:@"removeValuesAtIndexes: should have been called once"]; } +- (void)testRemoveObjectUsesRemoveKeyAtIndex +{ + [self _patchSelector:@selector(removeObjectFromValuesAtIndex:)]; + + [[[self object] mutableArrayValueForKey:@"values"] removeObject:1]; + + [self assert:[0, 2, 3, 4, 5, 6, 7, 8, 9] equals:[[self object] values]]; + [self assert:1 equals:COUNTER message:"removeObjectFromValuesAtIndex: should have been called once"] +} + +- (void)testeRemoveObjectUsesRemoveKeyAtIndexes +{ + [self _patchSelector:@selector(removeValuesAtIndexes:)]; + + [[[self object] mutableArrayValueForKey:@"values"] removeObject:5]; + + [self assert:[0, 1, 2, 3, 4, 6, 7, 8, 9] equals:[[self object] values]]; + [self assert:1 equals:COUNTER message:@"removeValuesAtIndexes: should have been called once"]; +} + +- (void)testRemoveObjectsInArrayUsesRemoveKeyAtIndex +{ + [self _patchSelector:@selector(removeObjectFromValuesAtIndex:)]; + + [[[self object] mutableArrayValueForKey:@"values"] removeObjectsInArray:[3, 6]]; + + [self assert:[0, 1, 2, 4, 5, 7, 8, 9] equals:[[self object] values]]; + [self assert:2 equals:COUNTER message:"removeObjectFromValuesAtIndex: should have been called once"] +} + +- (void)testRemoveObjectsInArrayUsesRemoveKeyAtIndexes +{ + [self _patchSelector:@selector(removeValuesAtIndexes:)]; + + [[[self object] mutableArrayValueForKey:@"values"] removeObjectsInArray:[0, 9]]; + + [self assert:[1, 2, 3, 4, 5, 6, 7, 8] equals:[[self object] values]]; + [self assert:1 equals:COUNTER message:@"removeValuesAtIndexes: should have been called once"]; +} + +- (void)testRemoveLastObjectUsesRemoveKeyAtIndex +{ + [self _patchSelector:@selector(removeObjectFromValuesAtIndex:)]; + + [[[self object] mutableArrayValueForKey:@"values"] removeLastObject]; + + [self assert:[0, 1, 2, 3, 4, 5, 6, 7, 8] equals:[[self object] values]]; + [self assert:1 equals:COUNTER message:"removeObjectFromValuesAtIndex: should have been called once"] +} + +- (void)testRemoveLastObjectUsesRemoveKeyAtIndexes +{ + [self _patchSelector:@selector(removeValuesAtIndexes:)]; + + [[[self object] mutableArrayValueForKey:@"values"] removeLastObject]; + + [self assert:[0, 1, 2, 3, 4, 5, 6, 7, 8] equals:[[self object] values]]; + [self assert:1 equals:COUNTER message:@"removeValuesAtIndexes: should have been called once"]; +} + - (void)testReplaceObjectAtIndexWithObjectUsesReplaceObjectInKeyAtIndexWithObject { [self _patchSelector:@selector(replaceObjectInValuesAtIndex:withObject:)];