//
// $Id: DequeTest.m,v 1.13 2005/05/18 06:46:55 will_mason Exp $
//
// vi: set ft=objc:

/*
 * ObjectiveLib - a library of containers and algorithms for Objective-C
 *
 * Copyright (c) 2004
 * Will Mason
 *
 * Portions:
 *
 * Copyright (c) 1994
 * Hewlett-Packard Company
 *
 * Copyright (c) 1996,1997
 * Silicon Graphics Computer Systems, Inc.
 *
 * Copyright (c) 1997
 * Moscow Center for SPARC Technology
 *
 * Copyright (c) 1999 
 * Boris Fomitchev
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * You may contact the author at will_mason@users.sourceforge.net.
 */

#import "DequeTest.h"
#import <ObjectiveLib/Deque.h>
#import <Foundation/NSString.h>
#import <Foundation/NSValue.h>
#import <Foundation/NSData.h>
#import <Foundation/NSArchiver.h>
#if defined(HAVE_KEYED_ARCHIVES)
#import <Foundation/NSKeyedArchiver.h>
#endif
#import <stdlib.h>
#if defined(__NEXT_RUNTIME__)
#import <objc/objc-class.h>
#else
#import <objc/objc.h>
#endif

@implementation DequeTest

- (void) testAccesors
{
    NSNumber* nums[10000];
    OLPair* itors;
    OLDeque* d;
    int i;

    for (i = 0; i < 10000; i++)
        nums[i] = [[NSNumber alloc] initWithInt: i];
    itors = [OLArrayIterator pairWithPointer: nums andPointer: nums + 10000];
    d = [[OLDeque alloc] initFrom: [itors first] to: [itors second]];
    for (i = 0; i < 10000; i++)
        [nums[i] release];
    if ([[d front] intValue] != 0)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 0, but got %i", [[d front] intValue]];
    }
    if ([[d back] intValue] != 9999)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 9999, but got %i", [[d back] intValue]];
    }
    for (i = 0; i < 10000; i++)
    {
        if ([[d at: i] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                i, [[d at: i] intValue]];
        }
    }
    [d release];
}

- (void) testAssign
{
    NSString* strs[] = { @"one", @"two", @"three", @"four" };
    OLPair* p;
    OLDeque* d;
    NSNumber* num;
    int i;

    p = [OLArrayIterator pairWithPointer: strs andPointer: strs + 4];
    d = [[OLDeque alloc] initFrom: [p first] to: [p second]];
    [[p second] advanceBy: -2];
    [d assignFrom: [p first] to: [p second]];
    if ([d size] != 2)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 2, but got %u", [d size]];
    }
    if (![[d front] isEqual: strs[0]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"one\", but got \"%s\"", [[d front] cString]];
    }
    if (![[d back] isEqual: strs[1]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"two\", but got \"%s\"", [[d back] cString]];
    }
    [[p second] advanceBy: 2];
    [d assignFrom: [p first] to: [p second]];
    if ([d size] != 4)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 4, but got %u", [d size]];
    }
    for (i = 0; i < 4; i++)
    {
        if (![[d at: i] isEqual: strs[i]])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"%s\", but got \"%s\"",
                [strs[i] cString], [[d at: i] cString]];
        }
    }
    num = [[NSNumber alloc] initWithInt: 3];
    [d assign: 2 filledWith: num];
    if ([d size] != 2)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 2, but got %u", [d size]];
    }
    if (![[d front] isEqual: num])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected %i, but got %i",
            [num intValue], [[d front] intValue]];
    }
    if (![[d back] isEqual: num])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected %i, but got %i",
            [num intValue], [[d back] intValue]];
    }
    [num release];
    num = [[NSNumber alloc] initWithInt: 7];
    [d assign: 6000 filledWith: num];
    [num release];
    if ([d size] != 6000)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 6000, but got %u", [d size]];
    }
    for (i = 0; i < 6000; i++)
    {
        if ([[d at: i] intValue] != 7)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "At position %i expected 7, but got %i",
                i, [[d at: i] intValue]];
        }
    }
    num = [[NSNumber alloc] initWithInt: 12355];
    [d assignAt: 4325 value: num];
    [num release];
    if ([[d at: 4325] intValue] != 12355)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 12355, but got %i", [[d at: 4325] intValue]];
    }
    [d release];
}

- (void) testCoding
{
    NSMutableData* data;
    NSArchiver* archiver;
    NSData* archData;
    OLDeque* d1;
    OLDeque* d2;
    NSNumber* num;
    int i;


    d1 = [[OLDeque alloc] init];
    [self logMessage: "Building deque"];
    for (i = 0; i< 1000; i++)
    {
        num = [[NSNumber alloc] initWithInt: lrand48() % 10000];
        [d1 pushBack: num];
        [num release];
    }
    data = [[NSMutableData alloc] initWithCapacity: 1000];
    archiver = [[NSArchiver alloc] initForWritingWithMutableData: data];
    [self logMessage: "Encoding deque"];
    [archiver encodeRootObject: d1];
    [archiver release];
    [self logMessage: "Decoding deque"];
    d2 = [NSUnarchiver unarchiveObjectWithData: data];
    [data release];
    if (![d1 isEqual: d2])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The deques should be equal"];
    }
#if defined(HAVE_KEYED_ARCHIVES)
    [self logMessage: "Encoding deque with keys"];
    archData = [NSKeyedArchiver archivedDataWithRootObject: d1];
    [self logMessage: "Decoding deque with keys"];
    d2 = [NSKeyedUnarchiver unarchiveObjectWithData: archData];
    if (![d1 isEqual: d2])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The deques should be equal"];
    }
#endif
    [d1 release];
    [self logMessage: "Done"];
}

- (void) testErase
{
    NSNumber* nums[10000];
    OLPair* itors;
    OLDeque* d;
    OLDequeIterator* di;
    OLDequeIterator* di2;
    int i;
    int cur;
    int cur2;

    for (i = 0; i < 10000; i++)
        nums[i] = [[NSNumber alloc] initWithInt: i];
    itors = [OLArrayIterator pairWithPointer: nums andPointer: nums + 10000];
    d = [[OLDeque alloc] initFrom: [itors first] to: [itors second]];
    for (i = 0; i < 10000; i++)
        [nums[i] release];
    di = [[d begin] advanceBy: 2000];
    cur = [[di dereference] intValue];
    di = [d erase: di];
    if ([d size] != 9999)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 9999, but got %u", [d size]];
    }
    if ([[di dereference] intValue] != cur + 1)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected %i, but got %u",
            cur + 1, [[di dereference] intValue]];
    }
    for (i = 0; i < 9999; i++)
    {
        if ([[d at: i] intValue] == cur)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Found %i at position %i which should be erased", cur, i];
        }
    }
    [di advanceBy: 6000];
    cur = [[di dereference] intValue];
    di = [d erase: di];
    if ([d size] != 9998)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 9998, but got %u", [d size]];
    }
    if ([[di dereference] intValue] != cur + 1)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected %i, but got %u",
            cur + 1, [[di dereference] intValue]];
    }
    for (i = 0; i < 9998; i++)
    {
        if ([[d at: i] intValue] == cur)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Found %i at position %i which should be erased", cur, i];
        }
    }
    di2 = [di copy];
    [di2 advanceBy: 10];
    cur2 = [[di2 dereference] intValue];
    di = [d eraseFrom: di to: di2];
    if ([d size] != 9988)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 9988, but got %u", [d size]];
    }
    if ([[di dereference] intValue] != cur2)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected %i, but got %u",
            cur2, [[di dereference] intValue]];
    }
    for (i = 0; i < 9988; i++)
    {
        if ([[d at: i] intValue] >= cur && [[d at: i] intValue] < cur2)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Found %i in range (%i, %i]",
                [[d at: i] intValue], cur, cur2];
        }
    }
    [di2 release];
    [d clear];
    if ([d size] != 0)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 0, but got %u", [d size]];
    }
    [d release];
}

- (void) testConvenienceAllocators
{
    OLDeque* d;
    OLDeque* d2;
    NSNumber* num;

    d = [OLDeque deque];
    if (![d isMemberOfClass: [OLDeque class]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"%s\", but got \"%s\"",
            [OLDeque class]->name, [d class]->name];
    }
    if (![d empty])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The deque should be empty"];
    }
    num = [[NSNumber alloc] initWithInt: 5];
    [d pushBack: num];
    [num release];
    num = [[NSNumber alloc] initWithInt: 6];
    [d pushBack: num];
    [num release];
    num = [[NSNumber alloc] initWithInt: 7];
    [d pushBack: num];
    [num release];
    d2 = [OLDeque dequeFrom: [d begin] to: [d end]];
    if (![d isEqual: d2])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The deques should be equal"];
    }
    num = [[NSNumber alloc] initWithInt: 8];
    [d pushBack: num];
    [num release];
    num = [[NSNumber alloc] initWithInt: 9];
    [d pushBack: num];
    [num release];
    d2 = [OLDeque dequeWithDeque: d];
    if (![d isEqual: d2])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The deques should be equal"];
    }
    num = [[NSNumber alloc] initWithInt: 10];
    d = [OLDeque dequeWithSize: 666 filledWith: num];
    [num release];
    if (![d isMemberOfClass: [OLDeque class]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"%s\", but got \"%s\"",
            [OLDeque class]->name, [d class]->name];
    }
    if ([d size] != 666)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 666, but got %u", [d size]];
    }
}

- (void) testInsert
{
    NSString* strs[] = { @"one", @"two", @"three", @"four" };
    OLDeque* d;
    NSNumber* pi = [NSNumber numberWithDouble: 3.141592653589];
    OLArrayIterator* ab;
    OLArrayIterator* ae;
    int i;
    int j;

    d = [[OLDeque alloc] init];
    [d insertAt: [d begin] value: strs[0]];
    if (![d size] == 1)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 1, but got %u", [d size]];
    }
    if (![[d front] isEqual: strs[0]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"%s\", but got \"%s\"",
            [strs[0] cString], [[d front] cString]];
    }
    [d insertAt: [d end] value: strs[3]];
    if (![d size] == 2)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 2, but got %u", [d size]];
    }
    if (![[d front] isEqual: strs[0]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"%s\", but got \"%s\"",
            [strs[0] cString], [[d front] cString]];
    }
    if (![[d back] isEqual: strs[3]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"%s\", but got \"%s\"",
            [strs[3] cString], [[d back] cString]];
    }
    [d insertAt: [[d begin] advance] value: strs[2]];
    if (![d size] == 3)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 3, but got %u", [d size]];
    }
    if (![[d front] isEqual: strs[0]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"%s\", but got \"%s\"",
            [strs[0] cString], [[d front] cString]];
    }
    if (![[d back] isEqual: strs[3]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"%s\", but got \"%s\"",
            [strs[2] cString], [[d back] cString]];
    }
    if (![[d at: 1] isEqual: strs[2]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"%s\", but got \"%s\"",
            [strs[2] cString], [[d at: 1] cString]];
    }
    [d insertAt: [[d begin] advance] value: strs[1]];
    if (![d size] == 4)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 4, but got %u", [d size]];
    }
    if (![[d front] isEqual: strs[0]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"%s\", but got \"%s\"",
            [strs[0] cString], [[d front] cString]];
    }
    if (![[d back] isEqual: strs[3]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"%s\", but got \"%s\"",
            [strs[2] cString], [[d back] cString]];
    }
    if (![[d at: 1] isEqual: strs[1]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"%s\", but got \"%s\"",
            [strs[1] cString], [[d at: 1] cString]];
    }
    if (![[d at: 2] isEqual: strs[2]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"%s\", but got \"%s\"",
            [strs[2] cString], [[d at: 2] cString]];
    }
    [d insertAt: [d begin] count: 1000 filledWith: @"doggy"];
    if (![d size] == 1004)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 1004, but got %u", [d size]];
    }
    for (i = 0; i < 1000; i++)
    {
        if (![[d at: i] isEqual: @"doggy"])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"doggy\", but got \"%s\"", [[d at: i] cString]];
        }
    }
    for (i = 0; i < 4; i++)
    {
        if (![[d at: i + 1000] isEqual: strs[i]])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"%s\", but got \"%s\"",
                [strs[i] cString], [[d at: 1000 + i] cString]];
        }
    }
    [d insertAt: [d end] count: 3000 filledWith: @"chunks"];
    if (![d size] == 4004)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 4004, but got %u", [d size]];
    }
    for (i = 0; i < 1000; i++)
    {
        if (![[d at: i] isEqual: @"doggy"])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"doggy\", but got \"%s\"", [[d at: i] cString]];
        }
    }
    for (i = 0; i < 4; i++)
    {
        if (![[d at: i + 1000] isEqual: strs[i]])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"%s\", but got \"%s\"",
                [strs[i] cString], [[d at: 1000 + i] cString]];
        }
    }
    for (i = 0; i < 3000; i++)
    {
        if (![[d at: i + 1004] isEqual: @"chunks"])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"chunks\", but got \"%s\"", [[d at: i + 1004] cString]];
        }
    }
    [d insertAt: [[d begin] advanceBy: 500] count: 500 filledWith: @"blow"];
    if (![d size] == 4504)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 4504, but got %u", [d size]];
    }
    for (i = 0; i < 500; i++)
    {
        if (![[d at: i] isEqual: @"doggy"])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"doggy\", but got \"%s\"", [[d at: i] cString]];
        }
    }
    for (i = 0; i < 500; i++)
    {
        if (![[d at: i + 500] isEqual: @"blow"])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"blow\", but got \"%s\"", [[d at: i + 500] cString]];
        }
    }
    for (i = 0; i < 500; i++)
    {
        if (![[d at: i + 1000] isEqual: @"doggy"])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"doggy\", but got \"%s\"", [[d at: i + 1000] cString]];
        }
    }
    for (i = 0; i < 4; i++)
    {
        if (![[d at: i + 1500] isEqual: strs[i]])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"%s\", but got \"%s\"",
                [strs[i] cString], [[d at: 1500 + i] cString]];
        }
    }
    for (i = 0; i < 3000; i++)
    {
        if (![[d at: i + 1504] isEqual: @"chunks"])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"chunks\", but got \"%s\"", [[d at: i + 1504] cString]];
        }
    }
    [d insertAt: [[d end] advanceBy: -50] count: 1000 filledWith: pi];
    if (![d size] == 5504)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 5504, but got %u", [d size]];
    }
    for (i = 0; i < 500; i++)
    {
        if (![[d at: i] isEqual: @"doggy"])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"doggy\", but got \"%s\"", [[d at: i] cString]];
        }
    }
    for (i = 0; i < 500; i++)
    {
        if (![[d at: i + 500] isEqual: @"blow"])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"blow\", but got \"%s\"", [[d at: i + 500] cString]];
        }
    }
    for (i = 0; i < 500; i++)
    {
        if (![[d at: i + 1000] isEqual: @"doggy"])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"doggy\", but got \"%s\"", [[d at: i + 1000] cString]];
        }
    }
    for (i = 0; i < 4; i++)
    {
        if (![[d at: i + 1500] isEqual: strs[i]])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"%s\", but got \"%s\"",
                [strs[i] cString], [[d at: 1500 + i] cString]];
        }
    }
    for (i = 0; i < 2950; i++)
    {
        if (![[d at: i + 1504] isEqual: @"chunks"])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"chunks\", but got \"%s\"", [[d at: i + 1504] cString]];
        }
    }
    for (i = 0; i < 1000; i++)
    {
        if (![[d at: i + 1504 + 2950] isEqual: pi])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %f, but got %f",
                [pi doubleValue], [[d at: i + 1504 + 2950] doubleValue]];
        }
    }
    for (i = 0; i < 50; i++)
    {
        if (![[d at: i + 1504 + 2950 + 1000] isEqual: @"chunks"])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"chunks\", but got \"%s\"",
                [[d at: i + 1504 + 2950 + 1000] cString]];
        }
    }
    [d release];
    d = [[OLDeque alloc] init];
    ab = [[OLArrayIterator alloc] initWithPointer: strs];
    ae = [[OLArrayIterator alloc] initWithPointer: strs + 4];
    [d insertAt: [d begin] from: ab to: ae];
    if (![d size] == 4)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 4, but got %u", [d size]];
    }
    for (i = 0; i < 4; i++)
    {
        if (![[d at: i] isEqual: strs[i]])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"%s\", but got \"%s\"",
                [strs[i] cString], [[d at: i] cString]];
        }
    }
    [d insertAt: [d end] from: ab to: ae];
    if (![d size] == 8)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 8, but got %u", [d size]];
    }
    for (j = 0; j < 2; j++)
    {
        for (i = 0; i < 4; i++)
        {
            if (![[d at: i + (j * 4)] isEqual: strs[i]])
            {
                [self errInFile: __FILE__ line: __LINE__
                    format: "Expected \"%s\", but got \"%s\"",
                    [strs[i] cString], [[d at: i + (j * 4)] cString]];
            }
        }
    }
    [d insertAt: [[d begin] advanceBy: 4] from: ab to: ae];
    if (![d size] == 12)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 12, but got %u", [d size]];
    }
    for (j = 0; j < 3; j++)
    {
        for (i = 0; i < 4; i++)
        {
            if (![[d at: i + (j * 4)] isEqual: strs[i]])
            {
                [self errInFile: __FILE__ line: __LINE__
                    format: "Expected \"%s\", but got \"%s\"",
                    [strs[i] cString], [[d at: i + (j * 4)] cString]];
            }
        }
    }
    [d release];
    [ab release];
    [ae release];
}

- (void) testInitializers
{
    OLDeque* d;
    OLDeque* d2;
    OLDequeIterator* itor;
    NSString* strs[] = { @"one", @"two", @"three" };
    OLArrayIterator* sb;
    OLArrayIterator* se;
    OLDequeIterator* end;
    int i;

    d = [[OLDeque alloc] init];
    if (![d empty])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The deque should be empty"];
    }
    if (![d size] == 0)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 0, but got %u", [d size]];
    }
    [d release];
    d = [[OLDeque alloc] initWithSize: 992 filledWith: @"one"];
    if ([d empty])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The deque should not be empty"];
    }
    if ([d size] != 992)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 992, but got %u", [d size]];
    }
    end = [d end];
    for (itor = [d begin]; ![itor isEqual: end]; [itor advance])
    {
        if (![[itor dereference] isEqual: @"one"])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"one\", but got \"%s\"", [[itor dereference] cString]];
        }
    }
    [d release];
    sb = [[OLArrayIterator alloc] initWithPointer: strs];
    se = [[OLArrayIterator alloc] initWithPointer: strs + 3];
    d = [[OLDeque alloc] initFrom: sb to: se];
    [sb release];
    [se release];
    if ([d size] != 3)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 3, but got %u", [d size]];
    }
    end = [d end];
    for (itor = [d begin], i = 0; ![itor isEqual: end]; [itor advance], i++)
    {
        if (![[itor dereference] isEqual: strs[i]])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"%s\", but got \"%s\"",
                [strs[i] cString], [[itor dereference] cString]];
        }
    }
    d2 = [[OLDeque alloc] initWithDeque: d];
    if (![d isEqual: d2])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The deques must be equal"];
    }
    [d release];
    if ([d2 size] != 3)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 3, but got %u", [d2 size]];
    }
    end = [d2 end];
    for (itor = [d2 begin], i = 0; ![itor isEqual: end]; [itor advance], i++)
    {
        if (![[itor dereference] isEqual: strs[i]])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"%s\", but got \"%s\"",
                [strs[i] cString], [[itor dereference] cString]];
        }
    }
    [d2 release];
}

- (void) testIterators
{
    NSNumber* nums[10000];
    OLPair* itors;
    OLDeque* d;
    OLDequeIterator* di;
    OLReverseRandomIterator* ri;
    OLReverseRandomIterator* rend;
    int i;
    int diff;

    for (i = 0; i < 10000; i++)
        nums[i] = [[NSNumber alloc] initWithInt: i];
    itors = [OLArrayIterator pairWithPointer: nums andPointer: nums + 10000];
    d = [[OLDeque alloc] initFrom: [itors first] to: [itors second]];
    for (i = 0; i < 10000; i++)
        [nums[i] release];
    for (di = [d begin], i = 0; ![di isEqual: [d end]]; [di advance], i++)
    {
        if ([[di dereference] intValue] != [nums[i] intValue])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                [nums[i] intValue], [[di dereference] intValue]];
        }
    }
    di = [d begin];
    if ([[di dereference] intValue] != 0)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 0, but got %u", [[di dereference] intValue]];
    }
    if ([[[di advance] dereference] intValue] != 1)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 1, but got %u", [[di dereference] intValue]];
    }
    if ([[[di advanceBy: 4999] dereference] intValue] != 5000)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 5000, but got %u", [[di dereference] intValue]];
    }
    if ([[[di reverse] dereference] intValue] != 4999)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 4999, but got %u", [[di dereference] intValue]];
    }
    if ([[[di advanceBy: -1999] dereference] intValue] != 3000)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 3000, but got %u", [[di dereference] intValue]];
    }
    diff = [di difference: [d begin]];
    if (diff != 3000)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 3000, but got %i", diff];
    }
    diff = [di difference: [d end]];
    if (diff != -7000)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected -7000, but got %i", diff];
    }
    rend = [d rend];
    for (ri = [d rbegin], i = 9999; ![ri isEqual: rend]; [ri advance], i--)
    {
        if ([[ri dereference] intValue] != [nums[i] intValue])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                [nums[i] intValue], [[ri dereference] intValue]];
        }
    }
    [d release];
}

- (void) testProperties
{
    OLDeque* d;
    OLDeque* d2;

    d = [[OLDeque alloc] init];
    if (![d empty])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The deque should be empty"];
    }
    if ([d size] != 0)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 0, but got %u", [d size]];
    }
    [d pushBack: @"doggy"];
    if ([d empty])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The deque should not be empty"];
    }
    if ([d size] != 1)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 1, but got %u", [d size]];
    }
    if (![[d allocator] isEqual: [OLAllocator defaultAllocator]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The allocator is incorrect"];
    }
    if ([d allocator] != [OLAllocator defaultAllocator])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The allocator is incorrect"];
    }
    d2 = [[OLDeque alloc] init];
    if ([d isEqual: d2])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The deques are not equal"];
    }
    [d2 pushBack: @"doggy"];
    if (![d isEqual: d2])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The deques are equal"];
    }
    if ([d maxSize] != [d2 maxSize])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "All deques must have the same max size"];
    }
    [self logMessage: "The max size of a deque is %u", [d maxSize]];
    [d release];
    [d2 release];
}

- (void) testPushPop
{
    NSNumber* nums[10000];
    OLPair* itors;
    OLDeque* d;
    int i;

    for (i = 0; i < 10000; i++)
        nums[i] = [[NSNumber alloc] initWithInt: i];
    itors = [OLArrayIterator pairWithPointer: nums andPointer: nums + 10000];
    d = [[OLDeque alloc] initFrom: [itors first] to: [itors second]];
    for (i = 0; i < 10000; i++)
        [nums[i] release];
    [d pushBack: @"doggy"];
    if ([d size] != 10001)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 10001, but got %u", [d size]];
    }
    if (![[d back] isEqual: @"doggy"])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"doggy\", but got \"%s\"", [[d back] cString]];
    }
    [d popBack];
    if ([d size] != 10000)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 10000, but got %u", [d size]];
    }
    if ([[d back] intValue] != 9999)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 9999, but got %i", [[d back] intValue]];
    }
    [d pushFront: @"doggy"];
    if ([d size] != 10001)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 10001, but got %u", [d size]];
    }
    if (![[d front] isEqual: @"doggy"])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"doggy\", but got \"%s\"", [[d front] cString]];
    }
    [d popFront];
    if ([d size] != 10000)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 10000, but got %u", [d size]];
    }
    if ([[d front] intValue] != 0)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 0, but got %i", [[d front] intValue]];
    }
    [d release];
}

- (void) testResize
{
    NSNumber* nums[10000];
    OLPair* itors;
    OLDeque* d;
    int i;

    for (i = 0; i < 10000; i++)
        nums[i] = [[NSNumber alloc] initWithInt: i];
    itors = [OLArrayIterator pairWithPointer: nums andPointer: nums + 10000];
    d = [[OLDeque alloc] initFrom: [itors first] to: [itors second]];
    for (i = 0; i < 10000; i++)
        [nums[i] release];
    [d resize: 5000 filledWith: @"doggy"];
    if ([d size] != 5000)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 10001, but got %u", [d size]];
    }
    for (i = 0; i < 5000; i++)
    {
        if ([[d at: i] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                i, [[d at: i] intValue]];
        }
    }
    [d resize: 100000 filledWith: @"doggy"];
    if ([d size] != 100000)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 100000, but got %u", [d size]];
    }
    for (i = 0; i < 5000; i++)
    {
        if ([[d at: i] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                i, [[d at: i] intValue]];
        }
    }
    for (i = 5000; i < 100000; i++)
    {
        if (![[d at: i] isEqual: @"doggy"])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"doggy\", but got \"%s\"", [[d at: i] cString]];
        }
    }
    [d release];
}

- (void) testSwap
{
    NSNumber* nums[10000];
    OLPair* itors;
    OLDeque* d;
    OLDeque* d2;
    int i;

    for (i = 0; i < 10000; i++)
        nums[i] = [[NSNumber alloc] initWithInt: i];
    itors = [OLArrayIterator pairWithPointer: nums andPointer: nums + 10000];
    d = [[OLDeque alloc] initFrom: [itors first] to: [itors second]];
    for (i = 0; i < 10000; i++)
        [nums[i] release];
    d2 = [[OLDeque alloc] init];
    [d2 pushBack: @"doggy"];
    [d swap: d2];
    if ([d size] != 1)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 1, but got %u", [d size]];
    }
    if (![[d front] isEqual: @"doggy"])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"doggy\", but got \"%s\"", [[d front] cString]];
    }
    if ([d2 size] != 10000)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 10000, but got %u", [d2 size]];
    }
    for (i = 0; i < 10000; i++)
    {
        if ([[d2 at: i] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                i, [[d2 at: i] intValue]];
        }
    }
    [d release];
    [d2 release];
}

@end
