/*
* Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
*
* All rights reserved.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3.0 only,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* version 3.0 for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* version 3.0 along with this program. If not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#import "OFDictionaryTests.h"
static OFString *keys[] = {
@"key1",
@"key2"
};
static OFString *objects[] = {
@"value1",
@"value2"
};
@interface CustomDictionary: OFDictionary
{
OFDictionary *_dictionary;
}
@end
@implementation OFDictionaryTests
- (Class)dictionaryClass
{
return [CustomDictionary class];
}
- (void)setUp
{
[super setUp];
_dictionary = [[self.dictionaryClass alloc] initWithObjects: objects
forKeys: keys
count: 2];
}
- (void)dealloc
{
[_dictionary release];
[super dealloc];
}
- (void)testObjectForKey
{
OTAssertEqualObjects([_dictionary objectForKey: keys[0]], objects[0]);
OTAssertEqualObjects([_dictionary objectForKey: keys[1]], objects[1]);
}
- (void)testCount
{
OTAssertEqual(_dictionary.count, 2);
}
- (void)testIsEqual
{
OTAssertEqualObjects(_dictionary,
[OFDictionary dictionaryWithObjects: objects
forKeys: keys
count: 2]);
OTAssertNotEqualObjects(_dictionary,
[OFDictionary dictionaryWithObjects: keys
forKeys: objects
count: 2]);
}
- (void)testHash
{
OTAssertEqual(_dictionary.hash,
[[OFDictionary dictionaryWithObjects: objects
forKeys: keys
count: 2] hash]);
OTAssertNotEqual(_dictionary.hash,
[[OFDictionary dictionaryWithObject: objects[0]
forKey: keys[0]] hash]);
}
- (void)testCopy
{
OTAssertEqualObjects([[_dictionary copy] autorelease], _dictionary);
}
- (void)testMutableCopy
{
OTAssertEqualObjects(
[[_dictionary mutableCopy] autorelease], _dictionary);
}
- (void)testValueForKey
{
OTAssertEqualObjects([_dictionary valueForKey: keys[0]], objects[0]);
OTAssertEqualObjects([_dictionary valueForKey: keys[1]], objects[1]);
OTAssertEqualObjects(
[_dictionary valueForKey: @"@count"], [OFNumber numberWithInt: 2]);
}
- (void)testSetValueForKey
{
OTAssertThrowsSpecific([_dictionary setValue: @"x" forKey: @"x"],
OFUndefinedKeyException);
}
- (void)testContainsObject
{
OTAssertTrue([_dictionary containsObject: objects[0]]);
OTAssertFalse([_dictionary containsObject: @"nonexistent"]);
}
- (void)testContainsObjectIdenticalTo
{
OTAssertTrue([_dictionary containsObjectIdenticalTo: objects[0]]);
OTAssertFalse([_dictionary containsObjectIdenticalTo:
[[objects[0] mutableCopy] autorelease]]);
}
- (void)testDescription
{
OTAssert(
[_dictionary.description isEqual:
@"{\n\tkey1 = value1;\n\tkey2 = value2;\n}"] ||
[_dictionary.description isEqual:
@"{\n\tkey2 = value2;\n\tkey1 = value1;\n}"]);
}
- (void)testAllKeys
{
OTAssert(
[_dictionary.allKeys isEqual:
([OFArray arrayWithObjects: keys[0], keys[1], nil])] ||
[_dictionary.allKeys isEqual:
([OFArray arrayWithObjects: keys[1], keys[0], nil])]);
}
- (void)testAllObjects
{
OTAssert(
[_dictionary.allObjects isEqual:
([OFArray arrayWithObjects: objects[0], objects[1], nil])] ||
[_dictionary.allObjects isEqual:
([OFArray arrayWithObjects: objects[1], objects[0], nil])]);
}
- (void)testKeyEnumerator
{
OFEnumerator *enumerator = [_dictionary keyEnumerator];
OFString *first, *second;
first = [enumerator nextObject];
second = [enumerator nextObject];
OTAssertNil([enumerator nextObject]);
OTAssert(
([first isEqual: keys[0]] && [second isEqual: keys[1]]) ||
([first isEqual: keys[1]] && [second isEqual: keys[0]]));
}
- (void)testObjectEnumerator
{
OFEnumerator *enumerator = [_dictionary objectEnumerator];
OFString *first, *second;
first = [enumerator nextObject];
second = [enumerator nextObject];
OTAssertNil([enumerator nextObject]);
OTAssert(
([first isEqual: objects[0]] && [second isEqual: objects[1]]) ||
([first isEqual: objects[1]] && [second isEqual: objects[0]]));
}
- (void)testFastEnumeration
{
size_t i = 0;
OFString *first = nil, *second = nil;
for (OFString *key in _dictionary) {
OTAssertLessThan(i, 2);
switch (i++) {
case 0:
first = key;
break;
case 1:
second = key;
break;
}
}
OTAssertEqual(i, 2);
OTAssert(
([first isEqual: keys[0]] && [second isEqual: keys[1]]) ||
([first isEqual: keys[1]] && [second isEqual: keys[0]]));
}
#ifdef OF_HAVE_BLOCKS
- (void)testEnumerateKeysAndObjectsUsingBlock
{
__block size_t i = 0;
__block OFString *first = nil, *second = nil;
[_dictionary enumerateKeysAndObjectsUsingBlock:
^ (id key, id object, bool *stop) {
OTAssertLessThan(i, 2);
switch (i++) {
case 0:
first = key;
break;
case 1:
second = key;
break;
}
}];
OTAssertEqual(i, 2);
OTAssert(
([first isEqual: keys[0]] && [second isEqual: keys[1]]) ||
([first isEqual: keys[1]] && [second isEqual: keys[0]]));
}
- (void)testMappedDictionaryUsingBlock
{
OTAssertEqualObjects([_dictionary mappedDictionaryUsingBlock:
^ id (id key, id object) {
if ([key isEqual: keys[0]])
return @"val1";
if ([key isEqual: keys[1]])
return @"val2";
return nil;
}],
([OFDictionary dictionaryWithKeysAndObjects:
@"key1", @"val1", @"key2", @"val2", nil]));
}
- (void)testFilteredDictionaryUsingBlock
{
OTAssertEqualObjects([_dictionary filteredDictionaryUsingBlock:
^ bool (id key, id object) {
return [key isEqual: keys[0]];
}],
[OFDictionary dictionaryWithObject: objects[0]
forKey: keys[0]]);
}
#endif
@end
@implementation CustomDictionary
- (instancetype)initWithObjects: (const id *)objects_
forKeys: (const id *)keys_
count: (size_t)count
{
self = [super init];
@try {
_dictionary = [[OFDictionary alloc] initWithObjects: objects_
forKeys: keys_
count: count];
} @catch (id e) {
[self release];
@throw e;
}
return self;
}
- (void)dealloc
{
[_dictionary release];
[super dealloc];
}
- (id)objectForKey: (id)key
{
return [_dictionary objectForKey: key];
}
- (size_t)count
{
return _dictionary.count;
}
- (OFEnumerator *)keyEnumerator
{
return [_dictionary keyEnumerator];
}
@end