diff --git a/AppKit/CPRuleEditor/CPRuleEditor.j b/AppKit/CPRuleEditor/CPRuleEditor.j index e537a9199..9f30eb120 100644 --- a/AppKit/CPRuleEditor/CPRuleEditor.j +++ b/AppKit/CPRuleEditor/CPRuleEditor.j @@ -507,7 +507,7 @@ var CPRuleEditorItemPBoardType = @"CPRuleEditorItemPBoardType", - (int)parentRowForRow:(int)rowIndex { if (rowIndex < 0 || rowIndex >= [self numberOfRows]) - [CPException raise:CPRangeException reason:_cmd+@" row " + rowIndex + " is out of range"]; + [CPException raise:CPRangeException reason:_cmd + @" row " + rowIndex + " is out of range"]; var targetObject = [[self _rowCacheForIndex:rowIndex] rowObject]; @@ -548,7 +548,7 @@ TODO: implement - (CPRuleEditorRowType)rowTypeForRow:(int)rowIndex { if (rowIndex < 0 || rowIndex > [self numberOfRows]) - [CPException raise:CPRangeException reason:_cmd+@"row " + rowIndex + " is out of range"]; + [CPException raise:CPRangeException reason:_cmd + @"row " + rowIndex + " is out of range"]; var rowcache = [self _rowCacheForIndex:rowIndex]; if (rowcache) @@ -588,7 +588,7 @@ TODO: implement if (indexInSubrows !== CPNotFound) { [indexes addIndex:i]; - objectsCount --; + objectsCount--; if ([self rowTypeForRow:i] === CPRuleEditorRowTypeCompound) i += [[self subrowIndexesForRow:i] count]; @@ -848,7 +848,7 @@ TODO: implement } catch(error) { - CPLogConsole(@"Compound predicate error: [%@]\npredicateType:%i",[error description],compoundType); + CPLogConsole(@"Compound predicate error: [%@]\npredicateType:%i", [error description], compoundType); compoundPredicate = nil; } finally @@ -893,23 +893,21 @@ TODO: implement try { if (selector !== nil) - predicate = [CPComparisonPredicate - predicateWithLeftExpression:lhs - rightExpression:rhs - customSelector:selector + predicate = [CPComparisonPredicate predicateWithLeftExpression:lhs + rightExpression:rhs + customSelector:selector ]; else - predicate = [CPComparisonPredicate - predicateWithLeftExpression:lhs - rightExpression:rhs - modifier:(modifier || CPDirectPredicateModifier) - type:operator - options:(options || CPCaseInsensitivePredicateOption) + predicate = [CPComparisonPredicate predicateWithLeftExpression:lhs + rightExpression:rhs + modifier:(modifier || CPDirectPredicateModifier) + type:operator + options:(options || CPCaseInsensitivePredicateOption) ]; } catch(error) { - CPLogConsole(@"Row predicate error: ["+[error description]+"] for row "+aRow); + CPLogConsole(@"Row predicate error: [" + [error description] + "] for row " + aRow); predicate = nil; } finally @@ -1135,7 +1133,7 @@ TODO: implement - (_CPRuleEditorViewSliceDropSeparator)_createSliceDropSeparator { - var view = [[_CPRuleEditorViewSliceDropSeparator alloc] initWithFrame:CGRectMake(0,-10, [self frame].size.width, 2)]; + var view = [[_CPRuleEditorViewSliceDropSeparator alloc] initWithFrame:CGRectMake(0, -10, [self frame].size.width, 2)]; [view setAutoresizingMask:CPViewWidthSizable]; return view; } @@ -1316,7 +1314,7 @@ TODO: implement return [_boundArrayOwner mutableArrayValueForKey:_boundArrayKeyPath]; } -- (BOOL)_nextUnusedItems:({CPArray})items andValues:({CPArray})values forRow:(int)rowIndex forRowType:(unsigned int)type +- (BOOL)_nextUnusedItems:(CPArray)items andValues:(CPArray)values forRow:(int)rowIndex forRowType:(unsigned int)type { var parentItem = [items lastObject], // if empty items array, this is NULL aka the root item; childrenCount = [self _queryNumberOfChildrenOfItem:parentItem withRowType:type], @@ -1398,7 +1396,7 @@ TODO: implement { var item = [items objectAtIndex:i], value = [values objectAtIndex:i], - itemAndValue = [CPDictionary dictionaryWithObjects:[item,value] forKeys:["item","value"]]; + itemAndValue = [CPDictionary dictionaryWithObjects:[item, value] forKeys:["item", "value"]]; [itemsAndValues addObject:itemAndValue]; } @@ -2109,9 +2107,9 @@ TODO: implement mainRowIndex = [slice rowIndex], draggingRows = [CPIndexSet indexSetWithIndex:mainRowIndex], selected_indices = [self _selectedSliceIndices], - pasteboard = [CPPasteboard pasteboardWithName: CPDragPboard]; + pasteboard = [CPPasteboard pasteboardWithName:CPDragPboard]; - [pasteboard declareTypes:[CPArray arrayWithObjects: CPRuleEditorItemPBoardType, nil] owner: self]; + [pasteboard declareTypes:[CPArray arrayWithObjects:CPRuleEditorItemPBoardType, nil] owner: self]; if ([selected_indices containsIndex:mainRowIndex]) [draggingRows addIndexes:selected_indices]; @@ -2314,7 +2312,7 @@ TODO: implement { var rowObject = [[self _rowCacheForIndex:current_index] rowObject], subrows = [self _subrowObjectsOfObject:rowObject], - subIndexes = [self _globalIndexesForSubrowIndexes:[CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0,[subrows count])] ofParentObject:rowObject]; + subIndexes = [self _globalIndexesForSubrowIndexes:[CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [subrows count])] ofParentObject:rowObject]; numberOfChildrenOfPreviousBrother = [subIndexes count]; } @@ -2416,17 +2414,17 @@ var CPRuleEditorAlignmentGridWidthKey = @"CPRuleEditorAlignmentGridWidth", if (self !== nil) { [self setFormattingStringsFilename:[coder decodeObjectForKey:CPRuleEditorStringsFilenameKey]]; - _alignmentGridWidth = [coder decodeFloatForKey:CPRuleEditorAlignmentGridWidthKey]; - _sliceHeight = [coder decodeDoubleForKey:CPRuleEditorSliceHeightKey]; + _alignmentGridWidth = [coder decodeFloatForKey:CPRuleEditorAlignmentGridWidthKey]; + _sliceHeight = [coder decodeDoubleForKey:CPRuleEditorSliceHeightKey]; _editable = [coder decodeBoolForKey:CPRuleEditorEditableKey]; _allowsEmptyCompoundRows = [coder decodeBoolForKey:CPRuleEditorAllowsEmptyCompoundRowsKey]; _disallowEmpty = [coder decodeBoolForKey:CPRuleEditorDisallowEmptyKey]; - _nestingMode = [coder decodeIntForKey:CPRuleEditorNestingModeKey]; - _typeKeyPath = [coder decodeObjectForKey:CPRuleEditorRowTypeKeyPathKey]; - _itemsKeyPath = [coder decodeObjectForKey:CPRuleEditorItemsKeyPathKey]; - _valuesKeyPath = [coder decodeObjectForKey:CPRuleEditorValuesKeyPathKey]; - _subrowsArrayKeyPath = [coder decodeObjectForKey:CPRuleEditorSubrowsArrayKeyPathKey]; - _boundArrayKeyPath = [coder decodeObjectForKey:CPRuleEditorBoundArrayKeyPathKey]; + _nestingMode = [coder decodeIntForKey:CPRuleEditorNestingModeKey]; + _typeKeyPath = [coder decodeObjectForKey:CPRuleEditorRowTypeKeyPathKey]; + _itemsKeyPath = [coder decodeObjectForKey:CPRuleEditorItemsKeyPathKey]; + _valuesKeyPath = [coder decodeObjectForKey:CPRuleEditorValuesKeyPathKey]; + _subrowsArrayKeyPath = [coder decodeObjectForKey:CPRuleEditorSubrowsArrayKeyPathKey]; + _boundArrayKeyPath = [coder decodeObjectForKey:CPRuleEditorBoundArrayKeyPathKey]; _slicesHolder = [[self subviews] objectAtIndex:0]; _boundArrayOwner = [coder decodeObjectForKey:CPRuleEditorBoundArrayOwnerKey]; diff --git a/AppKit/Cib/CPCib.j b/AppKit/Cib/CPCib.j index 7277e8bca..c9c9a3da0 100644 --- a/AppKit/Cib/CPCib.j +++ b/AppKit/Cib/CPCib.j @@ -162,7 +162,7 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey"; - (BOOL)instantiateCibWithOwner:(id)anOwner topLevelObjects:(CPArray)topLevelObjects { - return [self instantiateCibWithExternalNameTable:[CPDictionary dictionaryWithObjectsAndKeys:anOwner, CPCibOwner, topLevelObjects, CPCibTopLevelObjects]]; + return [self instantiateCibWithExternalNameTable:[CPDictionary dictionaryWithObjects:[anOwner, topLevelObjects] forKeys:[CPCibOwner, CPCibTopLevelObjects]]]; } @end diff --git a/Foundation/CPArray+KVO.j b/Foundation/CPArray+KVO.j index 11068d42e..fc65294ef 100644 --- a/Foundation/CPArray+KVO.j +++ b/Foundation/CPArray+KVO.j @@ -514,6 +514,31 @@ @implementation CPArray (KeyValueObserving) +/*! + Raises an exception. + + CPArray objects are not observable, so this method raises an exception when invoked on an CPArray object. + Instead of observing a array, observe the ordered to-many relationship for which the array is the collection of related objects. +*/ +- (void)addObserver:(id)anObserver forKeyPath:(CPString)aKeyPath options:(CPKeyValueObservingOptions)anOptions context:(id)aContext +{ + [CPException raise:CPInvalidArgumentException reason:"[CPArray " + CPStringFromSelector(_cmd) + "] is not supported. Key path: " + aKeyPath]; +} + +/*! + Raises an exception. + + CPArray objects are not observable, so this method raises an exception when invoked on an CPArray object. + Instead of observing a array, observe the ordered to-many relationship for which the array is the collection of related objects. +*/ +- (void)removeObserver:(id)anObserver forKeyPath:(CPString)aKeyPath +{ + [CPException raise:CPInvalidArgumentException reason:"[CPArray " + CPStringFromSelector(_cmd) + "] is not supported. Key path: " + aKeyPath]; +} + +/*! + Registers an observer to receive key value observer notifications for the specified key-path relative to the objects at the indexes. +*/ - (void)addObserver:(id)anObserver toObjectsAtIndexes:(CPIndexSet)indexes forKeyPath:(CPString)aKeyPath options:(unsigned)options context:(id)context { var index = [indexes firstIndex]; @@ -526,6 +551,9 @@ } } +/*! + Removes anObserver from all key value observer notifications associated with the specified keyPath relative to the array’s objects at indexes. +*/ - (void)removeObserver:(id)anObserver fromObjectsAtIndexes:(CPIndexSet)indexes forKeyPath:(CPString)aKeyPath { var index = [indexes firstIndex]; diff --git a/Foundation/CPNumberFormatter.j b/Foundation/CPNumberFormatter.j index 3bb9489a9..0197d02ef 100644 --- a/Foundation/CPNumberFormatter.j +++ b/Foundation/CPNumberFormatter.j @@ -57,6 +57,7 @@ CPNumberFormatterRoundHalfUp = CPRoundPlain; { CPNumberFormatterStyle _numberStyle @accessors(property=numberStyle); CPString _perMillSymbol @accessors(property=perMillSymbol); + CPString _groupingSeparator @accessors(property=groupingSeparator); CPNumberFormatterRoundingMode _roundingMode @accessors(property=roundingMode); CPUInteger _maximumFractionalDigits @accessors(property=maximalFractionalDigits); @@ -69,6 +70,7 @@ CPNumberFormatterRoundHalfUp = CPRoundPlain; { _roundingMode = CPNumberFormatterRoundHalfUp; _maximumFractionalDigits = 3; + _groupingSeparator = @","; } return self; @@ -90,17 +92,18 @@ CPNumberFormatterRoundHalfUp = CPRoundPlain; preFraction = parts[0], fraction = parts.length > 1 ? parts[1] : "", preFractionLength = [preFraction length], - commaPosition = 3, - perMillSymbol = [self _effectivePerMillSymbol]; + commaPosition = 3; // TODO This is just a temporary solution. Should be generalised. // Add in thousands separators. - if (perMillSymbol) - while (commaPosition < [preFraction length]) + if (_groupingSeparator) + { + for (var commaPosition = 3, prefLength = [preFraction length]; commaPosition < prefLength; commaPosition += 4) { - preFraction = [preFraction stringByReplacingCharactersInRange:CPMakeRange(commaPosition, 0) withString:perMillSymbol]; - commaPosition += 4; + preFraction = [preFraction stringByReplacingCharactersInRange:CPMakeRange(prefLength - commaPosition, 0) withString:_groupingSeparator]; + prefLength += 1; } + } if (fraction) return preFraction + "." + fraction; @@ -139,17 +142,6 @@ CPNumberFormatterRoundHalfUp = CPRoundPlain; return YES; } -/*! - @ignore - Return the perMillSymbol if set, otherwise the locale default. -*/ -- (CPString)_effectivePerMillSymbol -{ - if (_perMillSymbol === nil || _perMillSymbol === undefined) - return ","; // (FIXME US Locale specific.) - return _perMillSymbol; -} - - (void)setRoundingMode:(CPNumberFormatterRoundingMode)aRoundingMode { _roundingMode = aRoundingMode; diff --git a/Foundation/CPSet/_CPConcreteMutableSet.j b/Foundation/CPSet/_CPConcreteMutableSet.j index 299c093cd..c5e3f9c91 100644 --- a/Foundation/CPSet/_CPConcreteMutableSet.j +++ b/Foundation/CPSet/_CPConcreteMutableSet.j @@ -48,13 +48,21 @@ var hasOwnProperty = Object.prototype.hasOwnProperty; { var UID = [anObject UID]; - if (!hasOwnProperty.call(_contents, UID)) - return nil; + if (hasOwnProperty.call(_contents, UID)) + return _contents[UID]; + else + { + for (var objectUID in _contents) + { + if (!hasOwnProperty.call(_contents, objectUID)) + continue; - var object = _contents[UID]; + var object = _contents[objectUID]; - if (object === anObject || [object isEqual:anObject]) - return object; + if (object === anObject || [object isEqual:anObject]) + return object; + } + } return nil; } @@ -100,11 +108,19 @@ var hasOwnProperty = Object.prototype.hasOwnProperty; */ - (void)removeObject:(id)anObject { - if (![self containsObject:anObject]) - return; + // Removing nil is an error. + if (anObject === nil || anObject === undefined) + [CPException raise:CPInvalidArgumentException reason:@"attempt to remove nil or undefined"]; - delete _contents[[anObject UID]]; - _count--; + // anObject might be isEqual: another object in the set. We need the exact instance so we can remove it by UID. + var object = [self member:anObject]; + + // ...but removing an object not present in the set is not an error. + if (object !== nil) + { + delete _contents[[object UID]]; + _count--; + } } /* diff --git a/Tests/Foundation/CPArrayTest.j b/Tests/Foundation/CPArrayTest.j index 0c4e23cd4..107b33fb0 100644 --- a/Tests/Foundation/CPArrayTest.j +++ b/Tests/Foundation/CPArrayTest.j @@ -673,6 +673,14 @@ [self assertTrue:s2[0] === A message:s2[0] + " is larger then " + A + " when sorting descending"]; } +- (void)testDisallowObservers +{ + var anArray = [CPArray arrayWithObject:0]; + + [self assertThrows:function() { [anArray addObserver:self forKeyPath:@"self" options:0 context:nil]; }]; + [self assertThrows:function() { [anArray removeObserver:self forKeyPath:@"self"]; }]; +} + @end @implementation AlwaysEqual : CPObject diff --git a/Tests/Foundation/CPIndexSetTest.j b/Tests/Foundation/CPIndexSetTest.j index 8641ae5c7..fefbd220d 100644 --- a/Tests/Foundation/CPIndexSetTest.j +++ b/Tests/Foundation/CPIndexSetTest.j @@ -288,6 +288,9 @@ function descriptionWithoutEntity(aString) { [self assert:[_set lastIndex] equals:19]; [self assert:[[CPIndexSet indexSet] lastIndex] equals:CPNotFound]; + + var singleIndexSet = [CPIndexSet indexSetWithIndex:3]; + [self assert:3 equals:[singleIndexSet lastIndex]]; } /* - (void)testAddSpeed diff --git a/Tests/Foundation/CPNumberFormatterTest.j b/Tests/Foundation/CPNumberFormatterTest.j index 05ded5fc9..67f4addcb 100644 --- a/Tests/Foundation/CPNumberFormatterTest.j +++ b/Tests/Foundation/CPNumberFormatterTest.j @@ -16,6 +16,29 @@ [self assert:@"122,344.456" equals:formattedNumberString]; } +- (void)testSetGroupingSeparator_ +{ + var numberFormatter = [CPNumberFormatter new]; + [numberFormatter setNumberStyle:CPNumberFormatterDecimalStyle]; + + [self assert:@"1" equals:[numberFormatter stringFromNumber:[CPNumber numberWithInt:1]]]; + [self assert:@"12" equals:[numberFormatter stringFromNumber:[CPNumber numberWithInt:12]]]; + [self assert:@"123" equals:[numberFormatter stringFromNumber:[CPNumber numberWithInt:123]]]; + [self assert:@"1,234" equals:[numberFormatter stringFromNumber:[CPNumber numberWithInt:1234]]]; + [self assert:@"12,345" equals:[numberFormatter stringFromNumber:[CPNumber numberWithInt:12345]]]; + [self assert:@"123,456" equals:[numberFormatter stringFromNumber:[CPNumber numberWithInt:123456]]]; + [self assert:@"1,234,567" equals:[numberFormatter stringFromNumber:[CPNumber numberWithInt:1234567]]]; + + [numberFormatter setGroupingSeparator:@" "]; + [self assert:@"1" equals:[numberFormatter stringFromNumber:[CPNumber numberWithInt:1]]]; + [self assert:@"12" equals:[numberFormatter stringFromNumber:[CPNumber numberWithInt:12]]]; + [self assert:@"123" equals:[numberFormatter stringFromNumber:[CPNumber numberWithInt:123]]]; + [self assert:@"1 234" equals:[numberFormatter stringFromNumber:[CPNumber numberWithInt:1234]]]; + [self assert:@"12 345" equals:[numberFormatter stringFromNumber:[CPNumber numberWithInt:12345]]]; + [self assert:@"123 456" equals:[numberFormatter stringFromNumber:[CPNumber numberWithInt:123456]]]; + [self assert:@"1 234 567" equals:[numberFormatter stringFromNumber:[CPNumber numberWithInt:1234567]]]; +} + - (void)testRoundingMode { var numberFormatter = [[CPNumberFormatter alloc] init], diff --git a/Tests/Foundation/CPPredicateTest.j b/Tests/Foundation/CPPredicateTest.j index 3001b08cb..c68cbe8f4 100644 --- a/Tests/Foundation/CPPredicateTest.j +++ b/Tests/Foundation/CPPredicateTest.j @@ -121,17 +121,17 @@ var expression = [CPExpression expressionForVariable:@"variable"], bindings = [CPDictionary dictionaryWithObject:20 forKey:@"variable"], eval = [expression expressionValueWithObject:@"variable" context:bindings]; - [self assertTrue:(eval == 20) message:"'"+ eval + "' should be 20"]; + [self assertTrue:(eval == 20) message:"'" + eval + "' should be 20"]; // Replace with constant expression bindings = [CPDictionary dictionaryWithObject:[CPExpression expressionForConstantValue:10] forKey:@"variable"]; eval = [expression expressionValueWithObject:nil context:bindings]; - [self assertTrue:(eval == 10) message:"'"+ eval + "' should be 10"]; + [self assertTrue:(eval == 10) message:"'" + eval + "' should be 10"]; // Replace with keypath expression bindings = [CPDictionary dictionaryWithObject:[CPExpression expressionForKeyPath:@"Record1.Age"] forKey:@"variable"]; eval = [expression expressionValueWithObject:dict context:bindings]; - [self assertTrue:(eval == 34) message:"'"+ eval + "' should be 34"]; + [self assertTrue:(eval == 34) message:"'" + eval + "' should be 34"]; } - (void)testSubqueryExpressionEvaluation @@ -143,40 +143,40 @@ var expression = [CPExpression expressionForSubquery:collection usingIteratorVariable:iteratorVariable predicate:predicate], eval = [expression expressionValueWithObject:dict context:nil], expected = [CPArray arrayWithObjects:"Kid1", "Kid2"]; - [self assertTrue:([eval isEqual:expected]) message:"'"+ [expression predicateFormat] + "' result is "+ eval + "but should be " + expected]; + [self assertTrue:([eval isEqual:expected]) message:"'" + [expression predicateFormat] + "' result is "+ eval + "but should be " + expected]; } - (void)testOptions { var pred = [[CPComparisonPredicate alloc] initWithLeftExpression:[CPExpression expressionForConstantValue:@"àa"] rightExpression:[CPExpression expressionForConstantValue:@"aà"] modifier:CPDirectPredicateModifier type:CPLikePredicateOperatorType options:3]; - [self assertTrue:[pred evaluateWithObject:nil] message:"/"+ [pred description] + "/ should be true"]; + [self assertTrue:[pred evaluateWithObject:nil] message:"/" + [pred description] + "/ should be true"]; pred = [[CPComparisonPredicate alloc] initWithLeftExpression:[CPExpression expressionForConstantValue:@"aB"] rightExpression:[CPExpression expressionForConstantValue:@"Ab"] modifier:CPDirectPredicateModifier type:CPLikePredicateOperatorType options:1]; - [self assertTrue:[pred evaluateWithObject:nil] message:"/"+ [pred description] + "/ should be true"]; + [self assertTrue:[pred evaluateWithObject:nil] message:"/" + [pred description] + "/ should be true"]; } - (void)testModifier { var pred = [[CPComparisonPredicate alloc] initWithLeftExpression:[CPExpression expressionForKeyPath:@"Record2.Children"] rightExpression:[CPExpression expressionForConstantValue:@"Gi"] modifier:CPAnyPredicateModifier type:CPBeginsWithPredicateOperatorType options:0]; - [self assertTrue:[pred evaluateWithObject:dict] message:"'"+ [pred description] + "' should be true"]; + [self assertTrue:[pred evaluateWithObject:dict] message:"'" + [pred description] + "' should be true"]; pred = [[CPComparisonPredicate alloc] initWithLeftExpression:[CPExpression expressionForKeyPath:@"Record1.Children"] rightExpression:[CPExpression expressionForConstantValue:@"Kid"] modifier:CPAllPredicateModifier type:CPBeginsWithPredicateOperatorType options:0]; - [self assertTrue:[pred evaluateWithObject:dict] message:"'"+ [pred description] + "' should be true"]; + [self assertTrue:[pred evaluateWithObject:dict] message:"'" + [pred description] + "' should be true"]; } - (void)testOperators { var pred = [[CPComparisonPredicate alloc] initWithLeftExpression:[CPExpression expressionForConstantValue:"Farenight 451"] rightExpression:[CPExpression expressionForConstantValue:"(F|g)\\w+\\s\\d{3}"] modifier:CPDirectPredicateModifier type:CPMatchesPredicateOperatorType options:2]; - [self assertTrue:[pred evaluateWithObject:nil] message:"'"+ [pred description] + "' should be true"]; + [self assertTrue:[pred evaluateWithObject:nil] message:"'" + [pred description] + "' should be true"]; pred = [[CPComparisonPredicate alloc] initWithLeftExpression:[CPExpression expressionForConstantValue:@"b"] rightExpression:[CPExpression expressionForConstantValue:@"[a-c]"] modifier:CPDirectPredicateModifier type:CPLikePredicateOperatorType options:1]; - [self assertTrue:[pred evaluateWithObject:nil] message:"'"+ [pred description] + "' should be true"]; + [self assertTrue:[pred evaluateWithObject:nil] message:"'" + [pred description] + "' should be true"]; pred = [[CPComparisonPredicate alloc] initWithLeftExpression:[CPExpression expressionForConstantValue:@"Aa"] rightExpression:[CPExpression expressionForConstantValue:@"ab"] modifier:CPDirectPredicateModifier type:CPLessThanPredicateOperatorType options:0]; - [self assertTrue:[pred evaluateWithObject:nil] message:"'"+ [pred description] + "' should be true"]; + [self assertTrue:[pred evaluateWithObject:nil] message:"'" + [pred description] + "' should be true"]; pred = [[CPComparisonPredicate alloc] initWithLeftExpression:[CPExpression expressionForConstantValue:@"Ac"] rightExpression:[CPExpression expressionForConstantValue:@"ab"] modifier:CPDirectPredicateModifier type:CPLessThanPredicateOperatorType options:2]; - [self assertTrue:[pred evaluateWithObject:nil] message:"'"+ [pred description] + "' should be true"]; + [self assertTrue:[pred evaluateWithObject:nil] message:"'" + [pred description] + "' should be true"]; } @@ -186,7 +186,7 @@ predTwo = [[CPComparisonPredicate alloc] initWithLeftExpression:[CPExpression expressionForKeyPath:@"Record1.Age"] rightExpression:[CPExpression expressionForConstantValue:[CPNumber numberWithInt:40]] modifier:CPDirectPredicateModifier type:CPLessThanPredicateOperatorType options:0], pred = [[CPCompoundPredicate alloc] initWithType:CPAndPredicateType subpredicates:[CPArray arrayWithObjects:predOne,predTwo]]; - [self assertTrue:[pred evaluateWithObject:dict] message:"'"+ [pred description] + "' should be true"]; + [self assertTrue:[pred evaluateWithObject:dict] message:"'" + [pred description] + "' should be true"]; } - (void)testBeginsWithEndsWithPredicate @@ -216,28 +216,28 @@ // Custom Selector Predicate var pred = [[CPComparisonPredicate alloc] initWithLeftExpression:[CPExpression expressionForKeyPath:@"Record1.Name"] rightExpression:[CPExpression expressionForConstantValue:nil] customSelector:@selector(yes:)]; - [self assertTrue:[pred evaluateWithObject:dict] message:"'"+ [pred description] + "' should be true"]; + [self assertTrue:[pred evaluateWithObject:dict] message:"'" + [pred description] + "' should be true"]; pred = [[CPComparisonPredicate alloc] initWithLeftExpression:[CPExpression expressionForConstantValue:nil] rightExpression:[CPExpression expressionForConstantValue:nil] customSelector:@selector(yes:)]; - [self assertFalse:[pred evaluateWithObject:dict] message:"'"+ [pred description] + "' should be false"]; + [self assertFalse:[pred evaluateWithObject:dict] message:"'" + [pred description] + "' should be false"]; pred = [[CPComparisonPredicate alloc] initWithLeftExpression:[CPExpression expressionForKeyPath:@"Record1.Name"] rightExpression:[CPExpression expressionForConstantValue:nil] modifier:CPDirectPredicateModifier type:CPBeginsWithPredicateOperatorType options:0]; - [self assertFalse:[pred evaluateWithObject:dict] message:"'"+ [pred description] + "' should be false"]; + [self assertFalse:[pred evaluateWithObject:dict] message:"'" + [pred description] + "' should be false"]; // Predicates with operators pred = [[CPComparisonPredicate alloc] initWithLeftExpression:[CPExpression expressionForKeyPath:@"Record1.Age"] rightExpression:[CPExpression expressionForConstantValue:nil] modifier:CPDirectPredicateModifier type:CPGreaterThanPredicateOperatorType options:0]; - [self assertFalse:[pred evaluateWithObject:dict] message:"'"+ [pred description] + "' should be false"]; + [self assertFalse:[pred evaluateWithObject:dict] message:"'" + [pred description] + "' should be false"]; pred = [[CPComparisonPredicate alloc] initWithLeftExpression:[CPExpression expressionForConstantValue:nil] rightExpression:[CPExpression expressionForConstantValue:nil] modifier:CPDirectPredicateModifier type:CPGreaterThanOrEqualToPredicateOperatorType options:0]; - [self assertTrue:[pred evaluateWithObject:dict] message:"'"+ [pred description] + "' should be true"]; + [self assertTrue:[pred evaluateWithObject:dict] message:"'" + [pred description] + "' should be true"]; pred = [[CPComparisonPredicate alloc] initWithLeftExpression:[CPExpression expressionForConstantValue:nil] rightExpression:[CPExpression expressionForConstantValue:nil] modifier:CPDirectPredicateModifier type:CPBeginsWithPredicateOperatorType options:0]; - [self assertFalse:[pred evaluateWithObject:dict] message:"'"+ [pred description] + "' should be false"]; + [self assertFalse:[pred evaluateWithObject:dict] message:"'" + [pred description] + "' should be false"]; } - (void)testPredicateParsing diff --git a/Tests/Foundation/CPSetTest.j b/Tests/Foundation/CPSetTest.j index 8bd32e3f1..3a6afc80a 100644 --- a/Tests/Foundation/CPSetTest.j +++ b/Tests/Foundation/CPSetTest.j @@ -174,16 +174,28 @@ [self assertTrue:[set containsObject:"foo"]]; [set removeObject:"foo"]; [self assertFalse:[set containsObject:"foo"]]; + + var dict1 = [CPDictionary dictionaryWithObject:self forKey:@"key"], + dict2 = [CPDictionary dictionaryWithObject:self forKey:@"key"], + set2 = [CPMutableSet new]; + + [set2 addObject:dict1]; + [set2 removeObject:dict2]; + [self assertTrue:[set2 count] === 0]; + + // Removing an object not in the set is not an error. + [set2 removeObject:dict2]; } - (void)testRemoveZeroObject { var set = [CPSet new]; + // In Objective-J this is equivalent to [set addObject:[CPNumber numberWithInt:0]]; [set addObject:0]; - [self assertTrue:[set containsObject:0]]; + [self assertTrue:[set containsObject:0] message:@"adding 0 to a set should work"]; [set removeObject:0]; - [self assertFalse:[set containsObject:0]]; + [self assertFalse:[set containsObject:0] message:@"removing 0 from a set should work"]; } - (void)testAddNilObject @@ -212,7 +224,7 @@ [self assertThrows:function() { [set addObject:nil] }]; [self assertFalse:[set containsObject:nil]]; - [set removeObject:nil]; + [self assertThrows:function() { [set removeObject:nil] }]; [self assertFalse:[set containsObject:nil]]; } @@ -261,4 +273,14 @@ [self assert:[b valueForKeyPath:@"@max.name"] equals:@"Tom"]; } +- (void)testMember +{ + var dict1 = [CPDictionary dictionaryWithObject:self forKey:@"key"], + dict2 = [CPDictionary dictionaryWithObject:self forKey:@"key"], + set2 = [CPMutableSet new]; + + [set2 addObject:dict1]; + [self assertTrue:[set2 member:dict2] === dict1]; +} + @end