/* $Id: list-test.c,v 1.5 2007-09-26 13:31:58 jmlarsen Exp $
 *
 * This file is part of the FORS Library
 * Copyright (C) 2002-2006 European Southern Observatory
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 */

/*
 * $Author: jmlarsen $
 * $Date: 2007-09-26 13:31:58 $
 * $Revision: 1.5 $
 * $Name: not supported by cvs2svn $
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#define LIST_ELEM int
#include <list.h>

#include <test.h>

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

#define LIST_DEFINE
#define LIST_ELEM int
#include <list.h>

/**
 * @defgroup list_test  List unit test
 */

/**@{*/

static int *
int_duplicate(const int *i)
{
    int *j = cpl_malloc(sizeof *j);
    *j = *i;
    return j;
}

static void
int_delete(int **i)
{
    if (i && *i) {
        cpl_free(*i); *i = NULL;
    }
    return;
}

static bool
int_less_than(const int *i, const int *j, void *data)
{
    data = data;
    return (*i < *j);
}

static double
int_evaluate(const int *i, void *data)
{
    data = data;
    return *i;
}

static void
test_list(void)
{
    int_list *l = int_list_new();
    int x = 8;
    
    test( l != NULL );
    test( int_list_size(l) == 0 );

    int_list_insert(l, int_duplicate(&x));
    int_list_insert(l, int_duplicate(&x));
    x = 0;
    int_list_insert(l, int_duplicate(&x));

    test( int_list_size(l) == 3 );

    x = 7;

    test_eq( *int_list_min    (l, int_less_than, NULL), 0 );
    test_eq( *int_list_max    (l, int_less_than, NULL), 8 );
    test_eq( *int_list_min_val(l, int_evaluate, NULL), 0 );
    test_eq( *int_list_max_val(l, int_evaluate, NULL), 8 );

    {
        const int_list *l2 = int_list_duplicate(l, int_duplicate);
        
        test( *int_list_kth_const(l2, 1, int_less_than, NULL) == 0 );
        test( *int_list_kth_const(l2, 3, int_less_than, NULL) == 8 );
        test( *int_list_kth_const(l2, 3, int_less_than, NULL) == 8 );
        test( *int_list_kth_const(l2, 2, int_less_than, NULL) == 8 );
        
        test( *int_list_max_const(l2, int_less_than, NULL) == 8 );

        {
            int num_pairs = 0;
            const int *p1, *p2;
            for (int_list_first_pair_const(l2, &p1, &p2);
                 p1 != NULL;
                 int_list_next_pair_const(l2, &p1, &p2)) {

                test( p1 != p2 );
                num_pairs += 1;
            }
            test( p2 == NULL );
            test_eq( num_pairs, (3*2/2));
        }

        int_list_delete_const(&l2, int_delete);
        test( l2 == NULL );
    }

    {
        int *ip;
        ip = int_list_remove(l, int_list_first(l));
        int_delete(&ip);
        
        test( int_list_size(l) == 2 );
        
        int_list_first(l);
        ip = int_list_remove(l, int_list_next(l));
        int_delete(&ip);
        test( int_list_size(l) == 1 );
        
        ip = int_list_remove(l, int_list_first(l));
        int_delete(&ip);
        test( int_list_size(l) == 0 );
    }

    int_list_delete(&l, int_delete);
    
    test( l == NULL );

    return;
}


/**
 * @brief   main
 */
int main(void)
{
    TEST_INIT;

    test_list();

    TEST_END;
}

/**@}*/
