You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
216 lines
3.9 KiB
216 lines
3.9 KiB
2 months ago
|
/*
|
||
|
* UCW Library -- Byte-based trie -- Testing utility
|
||
|
*
|
||
|
* (c) 2008 Pavel Charvat <pchar@ucw.cz>
|
||
|
*
|
||
|
* This software may be freely distributed and used according to the terms
|
||
|
* of the GNU Lesser General Public License.
|
||
|
*/
|
||
|
|
||
|
#undef LOCAL_DEBUG
|
||
|
|
||
|
#include <ucw/lib.h>
|
||
|
#include <ucw/getopt.h>
|
||
|
|
||
|
#include <alloca.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#define TRIE_PREFIX(x) basic_##x
|
||
|
#define TRIE_NODE_TYPE char
|
||
|
#define TRIE_WANT_CLEANUP
|
||
|
#define TRIE_WANT_ADD
|
||
|
#define TRIE_WANT_DELETE
|
||
|
#define TRIE_WANT_FIND
|
||
|
#define TRIE_WANT_AUDIT
|
||
|
#ifdef LOCAL_DEBUG
|
||
|
#define TRIE_TRACE
|
||
|
#endif
|
||
|
#include <ucw/trie.h>
|
||
|
|
||
|
static void
|
||
|
basic_test(void)
|
||
|
{
|
||
|
basic_init();
|
||
|
basic_add("str1");
|
||
|
basic_add("str2");
|
||
|
if (!basic_find("str1") || !basic_find("str2") || basic_find("x") || basic_find("str123"))
|
||
|
ASSERT(0);
|
||
|
basic_audit();
|
||
|
basic_delete("str1");
|
||
|
if (basic_find("str1") || !basic_find("str2"))
|
||
|
ASSERT(0);
|
||
|
basic_audit();
|
||
|
basic_cleanup();
|
||
|
}
|
||
|
|
||
|
#define TRIE_PREFIX(x) dynamic_##x
|
||
|
#define TRIE_NODE_TYPE char
|
||
|
#define TRIE_REV
|
||
|
#define TRIE_DYNAMIC
|
||
|
#define TRIE_WANT_CLEANUP
|
||
|
#define TRIE_WANT_ADD
|
||
|
#define TRIE_WANT_FIND
|
||
|
#define TRIE_WANT_AUDIT
|
||
|
#ifdef LOCAL_DEBUG
|
||
|
#define TRIE_TRACE
|
||
|
#endif
|
||
|
#include <ucw/trie.h>
|
||
|
|
||
|
static void
|
||
|
dynamic_test(void)
|
||
|
{
|
||
|
struct dynamic_trie trie1, trie2;
|
||
|
dynamic_init(&trie1);
|
||
|
dynamic_init(&trie2);
|
||
|
dynamic_add(&trie1, "str1");
|
||
|
dynamic_add(&trie2, "str2");
|
||
|
if (!dynamic_find(&trie1, "str1") || dynamic_find(&trie1, "str2") || !dynamic_find(&trie2, "str2"))
|
||
|
ASSERT(0);
|
||
|
dynamic_audit(&trie1);
|
||
|
dynamic_audit(&trie2);
|
||
|
dynamic_cleanup(&trie1);
|
||
|
dynamic_cleanup(&trie2);
|
||
|
}
|
||
|
|
||
|
|
||
|
#define TRIE_PREFIX(x) random_##x
|
||
|
#define TRIE_NODE_TYPE char
|
||
|
#define TRIE_LEN_TYPE u16
|
||
|
#undef TRIE_REV
|
||
|
#define TRIE_WANT_CLEANUP
|
||
|
#define TRIE_WANT_FIND
|
||
|
#define TRIE_WANT_ADD
|
||
|
#define TRIE_WANT_REMOVE
|
||
|
#define TRIE_WANT_AUDIT
|
||
|
#ifdef LOCAL_DEBUG
|
||
|
#define TRIE_TRACE
|
||
|
#endif
|
||
|
#include <ucw/trie.h>
|
||
|
|
||
|
#define MAX_STRINGS 200
|
||
|
|
||
|
static uint count;
|
||
|
static char *str[MAX_STRINGS];
|
||
|
|
||
|
static char *
|
||
|
gen_string(void)
|
||
|
{
|
||
|
uint l = random_max(11);
|
||
|
char *s = xmalloc(l + 1);
|
||
|
for (uint i = 0; i < l; i++)
|
||
|
s[i] = random_max('z' - 'a') + 'a';
|
||
|
s[l] = 0;
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
static char *
|
||
|
gen_unique_string(void)
|
||
|
{
|
||
|
char *s;
|
||
|
again:
|
||
|
s = gen_string();
|
||
|
for (uint i = 0; i < count; i++)
|
||
|
if (!strcmp(s, str[i]))
|
||
|
{
|
||
|
xfree(s);
|
||
|
goto again;
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
insert(void)
|
||
|
{
|
||
|
if (count == MAX_STRINGS)
|
||
|
return;
|
||
|
char *s = gen_unique_string();
|
||
|
str[count++] = s;
|
||
|
DBG("add '%s'", s);
|
||
|
random_add(s);
|
||
|
random_audit();
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
delete(void)
|
||
|
{
|
||
|
if (!count)
|
||
|
return;
|
||
|
uint i = random_max(count);
|
||
|
DBG("remove '%s'", str[i]);
|
||
|
random_remove(str[i]);
|
||
|
random_audit();
|
||
|
xfree(str[i]);
|
||
|
str[i] = str[--count];
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
find(void)
|
||
|
{
|
||
|
if (!count || !random_max(4))
|
||
|
{
|
||
|
char *s = gen_unique_string();
|
||
|
DBG("negative find '%s'", s);
|
||
|
if (random_find(s))
|
||
|
ASSERT(0);
|
||
|
xfree(s);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
uint i = random_max(count);
|
||
|
DBG("positive find '%s'", str[i]);
|
||
|
if (random_find(str[i]) != str[i])
|
||
|
ASSERT(0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
reset(void)
|
||
|
{
|
||
|
DBG("reset");
|
||
|
random_cleanup();
|
||
|
for (uint i = 0; i < count; i++)
|
||
|
xfree(str[i]);
|
||
|
count = 0;
|
||
|
random_init();
|
||
|
random_audit();
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
random_test(void)
|
||
|
{
|
||
|
random_init();
|
||
|
for (uint i = 0; i < 10000; i++)
|
||
|
{
|
||
|
int r = random_max(1000);
|
||
|
if ((r -= 300) < 0)
|
||
|
insert();
|
||
|
else if ((r -= 150) < 0)
|
||
|
delete();
|
||
|
else if ((r -= 300) < 0)
|
||
|
find();
|
||
|
else if ((r -= 1) < 0)
|
||
|
reset();
|
||
|
}
|
||
|
random_cleanup();
|
||
|
}
|
||
|
|
||
|
int main(int argc, char **argv)
|
||
|
{
|
||
|
log_init(argv[0]);
|
||
|
if (cf_getopt(argc, argv, CF_SHORT_OPTS, CF_NO_LONG_OPTS, NULL) >= 0 || optind + 1 != argc)
|
||
|
die("Invalid usage, see the source code");
|
||
|
random_gen_seed();
|
||
|
|
||
|
char *test = argv[optind];
|
||
|
if (!strcmp(test, "basic"))
|
||
|
basic_test();
|
||
|
else if (!strcmp(test, "dynamic"))
|
||
|
dynamic_test();
|
||
|
else if (!strcmp(test, "random"))
|
||
|
random_test();
|
||
|
else
|
||
|
die("Unknown test case");
|
||
|
|
||
|
return 0;
|
||
|
}
|