ObjFW  OFListTests.m at [1af54eb2c2]

File tests/OFListTests.m artifact 48a2f18d5f part of check-in 1af54eb2c2


/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "ObjFW.h"
#import "ObjFWTest.h"

@interface OFListTests: OTTestCase
{
	OFList *_list;
}
@end

@implementation OFListTests
- (void)setUp
{
	[super setUp];

	_list = [[OFList alloc] init];
	[_list appendObject: @"Foo"];
	[_list appendObject: @"Bar"];
	[_list appendObject: @"Baz"];
}

- (void)dealloc
{
	[_list release];

	[super dealloc];
}

- (void)testCount
{
	OTAssertEqual(_list.count, 3);
}

- (void)testAppendObject
{
	OFListItem item;

	[_list appendObject: @"Qux"];

	item = _list.firstListItem;
	OTAssertEqualObjects(OFListItemObject(item), @"Foo");

	item = OFListItemNext(item);
	OTAssertEqualObjects(OFListItemObject(item), @"Bar");

	item = OFListItemNext(item);
	OTAssertEqualObjects(OFListItemObject(item), @"Baz");

	item = OFListItemNext(item);
	OTAssertEqualObjects(OFListItemObject(item), @"Qux");

	item = OFListItemNext(item);
	OTAssertEqual(item, NULL);
}

- (void)testFirstListItem
{
	OTAssertEqualObjects(OFListItemObject(_list.firstListItem), @"Foo");
}

- (void)testFirstObject
{
	OTAssertEqualObjects(_list.firstObject, @"Foo");
}

- (void)testLastListItem
{
	OTAssertEqualObjects(OFListItemObject(_list.lastListItem), @"Baz");
}

- (void)testLastObject
{
	OTAssertEqualObjects(_list.lastObject, @"Baz");
}

- (void)testListItemNext
{
	OTAssertEqualObjects(
	    OFListItemObject(OFListItemNext(_list.firstListItem)), @"Bar");
}

- (void)testListItemPrevious
{
	OTAssertEqualObjects(
	    OFListItemObject(OFListItemPrevious(_list.lastListItem)), @"Bar");
}

- (void)testRemoveListItem
{
	OFListItem item;

	[_list removeListItem: OFListItemNext(_list.firstListItem)];

	item = _list.firstListItem;
	OTAssertEqualObjects(OFListItemObject(item), @"Foo");

	item = OFListItemNext(item);
	OTAssertEqualObjects(OFListItemObject(item), @"Baz");

	item = OFListItemNext(item);
	OTAssertEqual(item, NULL);
}

- (void)testInsertObjectBeforeListItem
{
	OFListItem item;

	[_list insertObject: @"Qux" beforeListItem: _list.lastListItem];

	item = _list.firstListItem;
	OTAssertEqualObjects(OFListItemObject(item), @"Foo");

	item = OFListItemNext(item);
	OTAssertEqualObjects(OFListItemObject(item), @"Bar");

	item = OFListItemNext(item);
	OTAssertEqualObjects(OFListItemObject(item), @"Qux");

	item = OFListItemNext(item);
	OTAssertEqualObjects(OFListItemObject(item), @"Baz");

	item = OFListItemNext(item);
	OTAssertEqual(item, NULL);
}

- (void)testInsertObjectAfterListItem
{
	OFListItem item;

	[_list insertObject: @"Qux" afterListItem: _list.firstListItem];

	item = _list.firstListItem;
	OTAssertEqualObjects(OFListItemObject(item), @"Foo");

	item = OFListItemNext(item);
	OTAssertEqualObjects(OFListItemObject(item), @"Qux");

	item = OFListItemNext(item);
	OTAssertEqualObjects(OFListItemObject(item), @"Bar");

	item = OFListItemNext(item);
	OTAssertEqualObjects(OFListItemObject(item), @"Baz");

	item = OFListItemNext(item);
	OTAssertEqual(item, NULL);
}

- (void)testContainsObject
{
	OTAssertTrue([_list containsObject: @"Foo"]);
	OTAssertFalse([_list containsObject: @"Qux"]);
}

- (void)testContainsObjectIdenticalTo
{
	OFString *foo = _list.firstObject;

	OTAssertTrue([_list containsObjectIdenticalTo: foo]);
	OTAssertFalse(
	    [_list containsObjectIdenticalTo: [[foo mutableCopy] autorelease]]);
}

- (void)testIsEqual
{
	OFList *list = [OFList list];

	[list appendObject: @"Foo"];
	[list appendObject: @"Bar"];
	[list appendObject: @"Baz"];

	OTAssertEqualObjects(list, _list);

	[list appendObject: @"Qux"];

	OTAssertNotEqualObjects(list, _list);
}

- (void)testHash
{
	OFList *list = [OFList list];

	[list appendObject: @"Foo"];
	[list appendObject: @"Bar"];
	[list appendObject: @"Baz"];

	OTAssertEqual(list.hash, _list.hash);

	[list appendObject: @"Qux"];

	OTAssertNotEqual(list.hash, _list.hash);
}

- (void)testCopy
{
	OTAssertEqualObjects([[_list copy] autorelease], _list);
}

- (void)testDescription
{
	OTAssertEqualObjects(_list.description, @"[\n\tFoo,\n\tBar,\n\tBaz\n]");
}

- (void)testEnumerator
{
	OFEnumerator *enumerator = [_list objectEnumerator];

	OTAssertEqualObjects([enumerator nextObject], @"Foo");
	OTAssertEqualObjects([enumerator nextObject], @"Bar");
	OTAssertEqualObjects([enumerator nextObject], @"Baz");
	OTAssertNil([enumerator nextObject]);
}

- (void)testDetectMutationDuringEnumeration
{
	OFEnumerator *enumerator = [_list objectEnumerator];

	[_list removeListItem: _list.firstListItem];

	OTAssertThrowsSpecific([enumerator nextObject],
	    OFEnumerationMutationException);
}

- (void)testFastEnumeration
{
	size_t i = 0;

	for (OFString *object in _list) {
		OTAssertLessThan(i, 3);

		switch (i++) {
		case 0:
			OTAssertEqualObjects(object, @"Foo");
			break;
		case 1:
			OTAssertEqualObjects(object, @"Bar");
			break;
		case 2:
			OTAssertEqualObjects(object, @"Baz");
			break;
		}
	}

	OTAssertEqual(i, 3);
}

- (void)testDetectMutationDuringFastEnumeration
{
	bool detected = false;

	@try {
		for (OFString *object in _list) {
			(void)object;
			[_list removeListItem: _list.firstListItem];
		}
	} @catch (OFEnumerationMutationException *e) {
		detected = true;
	}

	OTAssertTrue(detected);
}
@end