//
// $Id: main.m,v 1.37 2005/05/18 06:46:56 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 <time.h>

#import "UnitTestRunner.h"
#import "BitSetTest.h"
#import "DequeTest.h"
#import "FunctionalTest.h"
#import "ListTest.h"
#import "PairTest.h"
#import "SetTest.h"
#import "VectorTest.h"
#import <ObjectiveLib/Memory.h>
#import "AlgorithmTest.h"
#import "HashSetTest.h"
#import "MapTest.h"
#import "StackTest.h"
#import "MultiSetTest.h"
#import "QueueTest.h"
#import "PriorityQueueTest.h"
#import "HashMapTest.h"
#import "MultiMapTest.h"
#import "HashMultiSetTest.h"
#import "HashMultiMapTest.h"
#import "BoolVectorTest.h"
#import "BasicStreamTest.h"
#import "ObjectStreamTest.h"
#import "FileStreamTest.h"
#import "BufferingStreamTest.h"
#import "ZlibStreamTest.h"
#import "GzipStreamTest.h"
#import "BzlibStreamTest.h"
#import "SocketAddressTest.h"
#if defined(OL_HAVE_UNIX_SOCKETS)
#import "UnixSocketTest.h"
#endif
#import "InternetSocketTest.h"
#import "LayeredStreamTest.h"
#import <unistd.h>
#import <Foundation/NSArray.h>

static Class testClass;
static NSMutableArray* testNames;
static BOOL pauseForLeakCheck;
static BOOL listNames;

static void usage()
{
    printf("Usage: TestObjectiveLib [-m] [-l] [-t <test>] [-n <name>]\n");
    printf("    -m\tPause at the end of the run so that 'leaks' may be run\n");
    printf("    -t\tThe unit test to run, like AlgorithmTest\n");
    printf("    -l\tList the test names available for <test>\n");
    printf("    -n\tThe name of the individual test. If no name is given all names from <test> are run. Multiple names may be specified.\n");
    exit(1);
}

static void processArguments(int argc, char* const argv[])
{
    int ch;

    testClass = nil;
    testNames = nil;
    pauseForLeakCheck = NO;
    listNames = NO;

    ch = getopt(argc, argv, "t:n:lm");
    while (ch != -1)
    {
        if (ch == 't')
        {
            if (testClass != nil)
            {
                printf("Only one test may be specified\n");
                usage();
            }
            testClass = NSClassFromString([NSString stringWithUTF8String: optarg]);
        }
        else if (ch == 'n')
        {
            if (testClass == nil)
                usage();
            if (testNames == nil)
                testNames = [NSMutableArray array];
            [testNames addObject: [NSString stringWithFormat: @"[%@ %s]",
                NSStringFromClass(testClass), optarg]];
        }
        else if (ch == 'm')
        {
            pauseForLeakCheck = YES;
        }
        else if (ch == 'l')
        {
            listNames = YES;
        }
        else
        {
            printf("Illegal option: %c\n", optopt);
            usage();
        }
        ch = getopt(argc, argv, "t:n:lm");
    }
}

int main(int argc, const char *argv[])
{
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    UnitTestRunner* runner = [[UnitTestRunner alloc] init];
    NSArray* testList;
    NSEnumerator* itor;
    id cur;
    Class classes[] =
    {
        [AlgorithmTest class],
        [BasicStreamTest class],
        [BitSetTest class],
        [BoolVectorTest class],
        [BufferingStreamTest class],
#if defined(HAVE_BZLIB)
        [BzlibStreamTest class],
#endif
        [DequeTest class],
        [FileStreamTest class],
        [FunctionalTest class],
#if defined(HAVE_ZLIB)
        [GzipStreamTest class],
#endif
        [HashMapTest class],
        [HashMultiMapTest class],
        [HashMultiSetTest class],
        [HashSetTest class],
        [InternetSocketTest class],
        [LayeredStreamTest class],
        [MapTest class],
        [MultiMapTest class],
        [MultiSetTest class],
        [ListTest class],
        [ObjectStreamTest class],
        [PairTest class],
        [PriorityQueueTest class],
        [QueueTest class],
        [SetTest class],
        [SocketAddressTest class],
        [StackTest class],
#if defined(OL_HAVE_UNIX_SOCKETS)
        [UnixSocketTest class],
#endif
        [VectorTest class],
#if defined(HAVE_ZLIB)
        [ZlibStreamTest class],
#endif
        NULL
    };

    srand48((long)time(NULL));
    processArguments(argc, (char**)argv);

    if (testClass != nil)
    {
        [runner loadTestsForClass: testClass];
        if (listNames)
        {
            testList = [runner testListQualified: NO];
            itor = [testList objectEnumerator];
            while (cur = [itor nextObject])
                printf("%s\n", [cur UTF8String]);
            exit(0);
        }
        if (testNames == nil)
            [runner runAllTests];
        else
            [runner runTestsWithNames: testNames];
    }
    else
    {
        [runner loadTestsForClasses: classes];
        if (listNames)
        {
            testList = [runner testListQualified: YES];
            itor = [testList objectEnumerator];
            while (cur = [itor nextObject])
                printf("%s\n", [cur UTF8String]);
            exit(0);
        }
        [runner runAllTests];
    }
    [runner summarize];
    [runner release];
    [pool release];

    if (pauseForLeakCheck)
        sleep(60 * 60);
    
    return 0;
}
