//
// $Id: HashMultiSetTest.m,v 1.9 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 "HashMultiSetTest.h"
#import <ObjectiveLib/HashSet.h>
#import <ObjectiveLib/Algorithm.h>
#import <Foundation/NSString.h>
#import <Foundation/NSValue.h>
#if defined(__NEXT_RUNTIME__)
#import <objc/objc-class.h>
#endif

@implementation HashMultiSetTest

- (void) testConvenienceAllocators
{
    OLHashMultiSet* s;
    OLHashMultiSet* s2;
    NSNumber* num;

    s = [OLHashMultiSet hashMultiSet];
    if (![s isMemberOfClass: [OLHashMultiSet class]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"%s\", but got \"%s\"",
            [OLHashMultiSet class]->name, [s class]->name];
    }
    if (![s empty])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The map should be empty"];
    }
    num = [[NSNumber alloc] initWithInt: 1];
    [s insert: num];
    [num release];
    num = [[NSNumber alloc] initWithInt: 2];
    [s insert: num];
    [num release];
    num = [[NSNumber alloc] initWithInt: 3];
    [s insert: num];
    [num release];
    s2 = [OLHashMultiSet hashMultiSetFrom: [s begin] to: [s end]];
    if (![s isEqual: s2])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The maps should be equal"];
    }
    num = [[NSNumber alloc] initWithInt: 4];
    [s insert: num];
    [num release];
    num = [[NSNumber alloc] initWithInt: 5];
    [s insert: num];
    [num release];
    s2 = [OLHashMultiSet hashMultiSetWithHashSet: s];
    if (![s isEqual: s2])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The maps should be equal"];
    }
}

- (void) testCounting
{
    OLHashMultiSet* s;
    NSNumber* nums[1019];
    NSNumber* num;
    OLPair* p;
    int i;
    unsigned count;

    for (i = 0; i < 1000; i++)
        nums[i] = [[NSNumber alloc] initWithInt: i];
    for ( ; i < 1019; i++)
        nums[i] = [[NSNumber alloc] initWithInt: 725];
    p = [OLArrayIterator pairWithPointer: nums distance: 1019];
    [OLAlgorithm randomShuffleFrom: [p first] to: [p second]];
    s = [[OLHashMultiSet alloc] initFrom: [p first] to: [p second]];
    for (i = 0; i < 1019; i++)
        [nums[i] release];
    num = [[NSNumber alloc] initWithInt: 725];
    count = [s count: num];
    [num release];
    if (count != 20)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 20, but got %u", count];
    }
    for (i = 0; i < 1000; i++)
    {
        if (i != 725)
        {
            num = [[NSNumber alloc] initWithInt: i];
            count = [s count: num];
            [num release];
            if (count != 1)
            {
                [self errInFile: __FILE__ line: __LINE__
                    format: "Expected 1, but got %u", count];
            }
        }
    }
    [s release];
}

- (void) testEqualRange
{
    OLHashMultiSet* s;
    NSString* strs[] = { @"one", @"two", @"three", @"one", @"four" };
    OLPair* p;
    unsigned dist;

    p = [OLArrayIterator pairWithPointer: strs distance: 5];
    s = [[OLHashMultiSet alloc] initFrom: [p first] to: [p second]];
    p = [s equalRange: @"two"];
    dist = [OLIterator distanceFrom: [p first] to: [p second]];
    if (dist != 1)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 1, but got %u", dist];
    }
    if (![[[p first] dereference] isEqual: @"two"])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"two\", but got \"%s\"",
            [[[p first] dereference] cString]];
    }
    p = [s equalRange: @"one"];
    dist = [OLIterator distanceFrom: [p first] to: [p second]];
    if (dist != 2)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 1, but got %u", dist];
    }
    for ( ; ![[p first] isEqual: [p second]]; [[p first] advance])
    {
        if (![[[p first] dereference] isEqual: @"one"])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"one\", but got \"%s\"",
                [[[p first] dereference] cString]];
        }
    }
    p = [s equalRange: @"seven"];
    dist = [OLIterator distanceFrom: [p first] to: [p second]];
    if (dist != 0)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 0, but got %u", dist];
    }
    if (![[p first] isEqual: [s end]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected the end"];
    }
    if (![[p second] isEqual: [s end]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected the end"];
    }
    [s release];
}

- (void) testInsert
{
    OLHashMultiSet* s;
    OLHashIterator* r;
    NSString* strs[] = { @"dog", @"has", @"fleas" };
    OLPair* p;
    int i;
    unsigned count;

    s = [[OLHashMultiSet alloc] init];
    r = [s insert: @"my"];
    if ([s size] != 1)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 1, but got %u", [s size]];
    }
    if (![[r dereference] isEqual: @"my"])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"my\", but got \"%s\"", [[r dereference] cString]];
    }
    r = [s insert: @"my"];
    if ([s size] != 2)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 2, but got %u", [s size]];
    }
    if (![[r dereference] isEqual: @"my"])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"my\", but got \"%s\"", [[r dereference] cString]];
    }
    p = [OLArrayIterator pairWithPointer: strs distance: 3];
    [s insertFrom: [p first] to: [p second]];
    if ([s size] != 5)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 5, but got %u", [s size]];
    }
    count = [s count: @"my"];
    if (count != 2)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 2, but got %u", count];
    }
    for (i = 0; i < 3; i++)
    {
        count = [s count: strs[i]];
        if (count != 1)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected 1, but got %u", count];
        }
    }
    [s release];
}

- (void) testInitializers
{
    OLHashMultiSet* s;
    NSString* strs[] = { @"my", @"dog", @"my", @"has", @"fleas", @"dog" };
    OLPair* p;
    unsigned count;

    p = [OLArrayIterator pairWithPointer: strs distance: 6];
    s = [[OLHashMultiSet alloc] initFrom: [p first] to: [p second]];
    if ([s size] != 6)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 6, but got %u", [s size]];
    }
    count = [s count: @"my"];
    if (count != 2)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 2, but got %u", count];
    }
    count = [s count: @"dog"];
    if (count != 2)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 2, but got %u", count];
    }
    count = [s count: @"has"];
    if (count != 1)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 1, but got %u", count];
    }
    count = [s count: @"fleas"];
    if (count != 1)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 1, but got %u", count];
    }
    [s release];
}

@end
