#include <CUnit/TestDB.h>
#include <string.h>

#include "timeoutlist.h"

/**
 * Test creation & deletion of a list with one element
 */
static void
test_basic1( void )
{
	struct timeoutlist* list;
	struct tol_entry* entry;
	int count = 0;

	list = tol_new();
	ASSERT( list != NULL );

	entry = tol_add(list, "test", time(NULL) + 5);
	ASSERT( entry != NULL );
	ASSERT( strcmp(entry->name,"test") == 0 );

	entry = tol_delete(list);
	ASSERT( entry != NULL );

	while( entry != NULL )
	{
		ASSERT( strcmp(entry->name,"test") == 0 );
		entry = tol_delete_entry( entry );
		ASSERT( entry == NULL );
		count++;
	}

	ASSERT( entry == NULL );
	ASSERT( count == 1 );
}

/**
 * multiple elements
 */
static void
test_basic2( void )
{
	struct timeoutlist* list;
	struct tol_entry* entry;
	struct tol_entry* test1;
	struct tol_entry* test2;

	list = tol_new();
	test1 = tol_add(list, "test1", 5 );
	test2 = tol_add(list, "test2", 10 );

	// Basic linkage checks
	ASSERT( test1->prev == NULL );
	ASSERT( test1->next == test2 );
	ASSERT( test2->prev == test1 );
	ASSERT( test2->next == NULL );

	// Check list start & finish
	ASSERT( list->start == test1 );
	ASSERT( list->finish == test2 );

	// Delete list and get entries
	entry = tol_delete(list);
	ASSERT( entry != NULL );
	ASSERT( entry == test1 );

	entry = tol_delete_entry(entry);
	ASSERT( entry == test2 );

	entry = tol_delete_entry(entry);
	ASSERT( entry == NULL );
}

/**
 * multiple elements, and expire one
 */
static void
test_basic3( void )
{
	struct timeoutlist* list;

	struct tol_entry* entry;
	struct tol_entry* entry2;
	struct tol_entry* entry3;

	struct tol_entry* tmp;

	list = tol_new();

	// Add 3 spaced entries
	entry = tol_add(list, "entry1", 5);
	entry2 = tol_add(list, "entry2", 10);
	entry3 = tol_add(list, "entry3", 15);

	ASSERT( tol_expiry(list) == 5 );

	// Perform some searches
	ASSERT( tol_search(list, "entry1") == entry );
	ASSERT( tol_search(list, "entry2") == entry2 );
	ASSERT( tol_search(list, "entry3") == entry3 );

	// Expire `entry`
	tmp = tol_expire(list, 7);
	ASSERT( tmp == entry );
	ASSERT( tol_expiry(list) == 10 );

	// And ensure its been unlinked properly
	tmp = tol_delete_entry(tmp);
	ASSERT( tmp == NULL );

	// Remove
	tmp = tol_delete(list);
	ASSERT( tmp != NULL );

	// Must not contain expired ones
	while( tmp != NULL )
	{
		ASSERT( tmp != entry );
		tmp = tol_delete_entry(tmp);
	}
	ASSERT( tmp == NULL );
	ASSERT( tol_expiry(list) == 0 );
}

void
test_tol_init()
{
	PTestGroup group;

	group = add_test_group("Timeout List", NULL, NULL);
	add_test_case(group, "single add", test_basic1);
	add_test_case(group, "multi add", test_basic2);
	add_test_case(group, "expire", test_basic3);
}
