LUMIERA.clone/tests/library/test-psplay.c

472 lines
9.6 KiB
C

/*
test-psplay.c - test the probabilistic splay tree
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <time.h>
#include <stdlib.h>
#include <nobug.h>
#include "lib/psplay.h"
#include "tests/test.h"
struct testitem
{
psplaynode node;
char* key;
};
typedef struct testitem* TestItem;
TestItem
testitem_new (const char* str)
{
TestItem self = malloc (sizeof *self);
psplaynode_init (&self->node);
self->key = strdup (str);
return self;
}
void
testitem_delete (TestItem self)
{
free (self->key);
free (self);
}
static int
cmp_fn (const void*, const void*);
static const void*
key_fn (const PSplaynode);
static void
delete_fn (PSplaynode);
//static psplay_delete_fn
//action_fn (PSplaynode node, const enum psplay_order_e which, int level, void* data);
static int
fcmp_fn (const void*, const void*);
static const void*
fkey_fn (const PSplaynode);
static void
fdelete_fn (PSplaynode);
//static psplay_delete_fn
//action_fn (PSplaynode node, const enum psplay_order_e which, int level, void* data);
psplay_delete_fn
testitem_print_node (PSplaynode node, const enum psplay_order_enum which, int level, void* data)
{
FILE* fh = data;
static char* sp = " ";
if (level>40)
{
if (which == PSPLAY_PREORDER)
fprintf (fh, "%s ...\n", sp);
return PSPLAY_CONT;
}
switch (which)
{
case PSPLAY_PREORDER:
fprintf (fh, "%s%p '%s'\n", sp+40-level, node, ((TestItem)node)->key);
if (node->left) fprintf (fh, "%sleft %p '%s'\n", sp+40-level, node->left, ((TestItem)node->left)->key);
break;
case PSPLAY_INORDER:
if (node->right) fprintf (fh, "%sright %p '%s'\n", sp+40-level, node->right, ((TestItem)node->right)->key);
break;
case PSPLAY_POSTORDER:
break;
}
return PSPLAY_CONT;
}
void
testitem_dump (PSplay self, FILE* dest)
{
fprintf (dest, "root %p '%s'\n", self->tree, self->tree?((TestItem)self->tree)->key:"EMPTY");
psplay_walk (self, NULL, testitem_print_node, 0, dest);
fprintf (dest, "\n");
}
psplay_delete_fn
testitem_graphvizprint_node (PSplaynode node, const enum psplay_order_enum which, int level, void* data)
{
FILE* fh = data;
switch (which)
{
case PSPLAY_PREORDER:
if (node->left)
fprintf (fh, "\t\"%p:%s\":sw -> \"%p:%s\":ne;\n",
node,
((TestItem)node)->key,
node->left,
((TestItem)node->left)->key);
break;
case PSPLAY_INORDER:
if (node->right)
fprintf (fh, "\t\"%p:%s\":se -> \"%p:%s\":nw;\n",
node,
((TestItem)node)->key,
node->right,
((TestItem)node->right)->key);
break;
case PSPLAY_POSTORDER:
break;
}
return PSPLAY_CONT;
}
void
testitem_graphvizdump (PSplay self, FILE* dest)
{
static int cnt = 0;
if (!cnt) cnt = (time(NULL) % 1000) * 100;
char cmd[256];
sprintf(cmd,"dot -Tps >/var/tmp/dbg%d.ps; gv /var/tmp/dbg%d.ps",cnt,cnt);
FILE * graph = popen(cmd, "w");
fprintf(graph, "digraph \"%s\" { center=true; size=\"6,6\"; node [color=lightblue2, style=filled];", "psplay");
++cnt;
fprintf(graph, "\t\"root\":s -> \"%p:%s\":n;\n",
self->tree, self->tree?((TestItem)self->tree)->key:"EMPTY");
psplay_walk (self, NULL, testitem_graphvizprint_node, 0, graph);
fprintf(graph, "}");
pclose(graph);
}
TESTS_BEGIN
TEST ("basic")
{
psplay splay_tree;
psplay_init (&splay_tree, cmp_fn, key_fn, delete_fn);
psplay_dump (&splay_tree, stdout);
psplay_destroy (&splay_tree);
}
TEST ("basic_insert_dump")
{
CHECK (argv[2]);
psplay splay_tree;
psplay_init (&splay_tree, cmp_fn, key_fn, delete_fn);
int end = atoi (argv[2]);
char key[1024];
for (int i = 1; i <= end; ++i)
{
sprintf (key, "%d", i);
ECHO ("insert %s", key);
psplay_insert (&splay_tree, (PSplaynode)testitem_new (key), 100);
}
psplay_dump (&splay_tree, stderr);
#if 0
for (int i = 1; i <= end; ++i)
{
sprintf (key, "%d", i);
ECHO ("insert %s", key);
psplay_remove_key (&splay_tree, key);
psplay_dump (&splay_tree, stderr);
}
for (int i = end; i; --i)
{
sprintf (key, "%d", i);
ECHO ("insert %s", key);
psplay_remove_key (&splay_tree, key);
psplay_dump (&splay_tree, stderr);
}
#endif
psplay_destroy (&splay_tree);
printf ("done\n");
}
TEST ("insert_find")
{
psplay splay_tree;
psplay_init (&splay_tree, cmp_fn, key_fn, delete_fn);
psplay_insert (&splay_tree, (PSplaynode)testitem_new ("foo"), 100);
psplay_insert (&splay_tree, (PSplaynode)testitem_new ("bar"), 100);
psplay_insert (&splay_tree, (PSplaynode)testitem_new ("baz"), 100);
psplay_insert (&splay_tree, (PSplaynode)testitem_new ("test"), 100);
psplay_insert (&splay_tree, (PSplaynode)testitem_new ("pap"), 100);
psplay_insert (&splay_tree, (PSplaynode)testitem_new ("qux"), 100);
testitem_graphvizdump (&splay_tree, stdout);
psplay_dump (&splay_tree, stdout);
//TestItem f = (TestItem) psplay_find (&splay_tree, "baz", 100);
TestItem f = (TestItem) psplay_find (&splay_tree, "baz", 100);
CHECK (f);
printf ("found %p (%.4s)\n", &f->node, f->key);
psplay_dump (&splay_tree, stdout);
f = (TestItem) psplay_find (&splay_tree, "test", 100);
CHECK (f);
printf ("found %p (%.4s)\n", &f->node, f->key);
psplay_dump (&splay_tree, stdout);
f = (TestItem) psplay_find (&splay_tree, "test", 100);
CHECK (f);
printf ("found %p (%.4s)\n", &f->node, f->key);
psplay_dump (&splay_tree, stdout);
f = (TestItem) psplay_find (&splay_tree, "foo", 100);
CHECK (f);
printf ("found %p (%.4s)\n", &f->node, f->key);
psplay_dump (&splay_tree, stdout);
#if 0
psplay_delete (psplay_remove (&splay_tree, root.tree));
psplay_dump (&splay_tree, stdout);
psplay_delete (psplay_remove (&splay_tree, root.tree));
psplay_dump (&splay_tree, stdout);
psplay_delete (psplay_remove (&splay_tree, root.tree));
psplay_dump (&splay_tree, stdout);
#endif
printf ("destroying\n");
psplay_destroy (&splay_tree);
psplay_dump (&splay_tree, stdout);
#if 0
psplay_delete (psplay_remove (&splay_tree, root.tree));
psplay_dump (&splay_tree, stdout);
psplay_delete (psplay_remove (&splay_tree, root.tree));
psplay_dump (&splay_tree, stdout);
psplay_delete (psplay_remove (&splay_tree, root.tree));
psplay_dump (&splay_tree, stdout);
#endif
return 0;
}
TEST ("basic_insert_splay")
{
CHECK (argv[2]);
psplay splay_tree;
psplay_init (&splay_tree, cmp_fn, key_fn, delete_fn);
int end = atoi (argv[2]);
char key[1024];
for (int i = 1; i <= end; ++i)
{
sprintf (key, "%d", i);
ECHO ("insert %s", key);
psplay_insert (&splay_tree, (PSplaynode)testitem_new (key), 100);
}
for (int i = end/2; i <= end; ++i)
{
psplay_dump (&splay_tree, stderr);
sprintf (key, "%d", i);
psplay_find (&splay_tree, key, 100);
}
psplay_destroy (&splay_tree);
printf ("done\n");
}
TEST ("basic_rand_insert_dump")
{
CHECK (argv[2]);
psplay splay_tree;
psplay_init (&splay_tree, cmp_fn, key_fn, delete_fn);
int end = atoi (argv[2]);
char key[1024];
for (int i = 1; i <= end; ++i)
{
sprintf (key, "%d", i /*rand()*/);
psplay_insert (&splay_tree, (PSplaynode)testitem_new (key), 100);
}
testitem_graphvizdump (&splay_tree, stdout);
//testitem_dump (&splay_tree, stdout);
psplay_destroy (&splay_tree);
printf ("done\n");
}
TEST ("fast_insert")
{
CHECK (argv[2]);
psplay splay_tree;
psplay_init (&splay_tree, fcmp_fn, fkey_fn, fdelete_fn);
int end = atoi (argv[2]);
char key[1024];
for (int i = 1; i <= end; ++i)
{
sprintf (key, "%d", i);
psplay_insert (&splay_tree, (PSplaynode)testitem_new (key), 100);
}
psplay_destroy (&splay_tree);
printf ("done\n");
}
TEST ("nonexistant")
{
CHECK (argv[2]);
}
TEST ("insert")
{
CHECK (argv[2]);
}
TEST ("insert_rand")
{
CHECK (argv[2]);
}
TEST ("insert_fastcheck")
{
CHECK (argv[2]);
}
TESTS_END
/*
cuckoo support functions
*/
static int
cmp_fn (const void* a, const void* b)
{
CHECK (a);
CHECK (b);
return strcmp (a, b);
}
static const void*
key_fn (const PSplaynode node)
{
CHECK (node);
CHECK (((TestItem)node)->key);
return ((TestItem)node)->key;
}
static void
delete_fn (PSplaynode node)
{
CHECK (node);
testitem_delete ((TestItem) node);
}
//static psplay_delete_fn
//action_fn (PSplaynode node, const enum psplay_order_e which, int level, void* data)
//{
//}
static int
fcmp_fn (const void* a, const void* b)
{
return strcmp (a, b);
}
static const void*
fkey_fn (const PSplaynode node)
{
return ((TestItem)node)->key;
}
static void
fdelete_fn (PSplaynode node)
{
testitem_delete ((TestItem) node);
}
//static psplay_delete_fn
//action_fn (PSplaynode node, const enum psplay_order_e which, int level, void* data)
//{
//}
/*
// Local Variables:
// mode: C
// c-file-style: "gnu"
// indent-tabs-mode: nil
// End:
*/