summaryrefslogtreecommitdiffstats
path: root/test/ttst.c
blob: 53aab5e650a77ea44f1ed3e1324fc2857f45f7ae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright by The HDF Group.                                               *
 * Copyright by the Board of Trustees of the University of Illinois.         *
 * All rights reserved.                                                      *
 *                                                                           *
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
 * terms governing use, modification, and redistribution, is contained in    *
 * the COPYING file, which can be found at the root of the source code       *
 * distribution tree, or in https://www.hdfgroup.org/licenses.               *
 * If you do not have access to either file, you may request a copy from     *
 * help@hdfgroup.org.                                                        *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/*
   FILE
       tst.c
   Test HDF Ternary Search Tree (tst) routines.

   REMARKS

   DESIGN

   BUGS/LIMITATIONS

   EXPORTED ROUTINES

   AUTHOR
       Quincey Koziol

   MODIFICATION HISTORY
       12/9/02 - Started coding
 */

#include "testhdf5.h"
#include "H5STprivate.h"

/* Test words to insert into s TST */
static const char *words[] = {
    "We",      "hold",        "these",   "truths", "to",      "be",      "self-evident,",
    "that",    "all",         "men",     "are",    "created", "equal,",  "that",
    "they",    "are",         "endowed", "by",     "their",   "Creator", "with",
    "certain", "unalienable", "Rights,", "that",   "among",   "these",   "are",
    "Life,",   "Liberty",     "and",     "the",    "pursuit", "of",      "Happiness."};
/* Number of words in test words set */
size_t num_words;

/* Number of unique words in test word set */
size_t num_uniq_words;
/* Unique words in test word set */
char **uniq_words;
/* Randomized order version of words in test word set */
char **rand_uniq_words;
/* Sorted order version of words in test word set */
char **sort_uniq_words;

static int
tst_strcmp(const void *_s1, const void *_s2)
{
    return (HDstrcmp(*(const char *const *)_s1, *(const char *const *)_s2));
}

/****************************************************************
**
**  test_tst_init(): Test basic H5ST (ternary search tree) selection code.
**      Initialize data for TST testing
**
****************************************************************/
static void
test_tst_init(void)
{
    time_t curr_time; /* Current time, for seeding random number generator */
    char * tmp_word;  /* Temporary pointer to word in word set */
    size_t u, v, w;   /* Local index variables */

    /* Compute the number of words in the test set */
    num_words = sizeof(words) / sizeof(words[0]);

    /* Determine the number of unique words in test set */
    /* (Not particularly efficient, be careful if many words are added to set) */
    num_uniq_words = 0;
    for (u = 0; u < num_words; u++) {
        /* Assume word is unique */
        num_uniq_words++;
        for (v = 0; v < u; v++)
            /* If word is already found in words looked at, decrement unique count */
            if (!HDstrcmp(words[u], words[v])) {
                num_uniq_words--;
                break;
            } /* end if */
    }         /* end for */

    /* Allocate space for the array of unique words */
    uniq_words = (char **)HDmalloc(sizeof(char *) * num_uniq_words);

    /* Allocate space for the array of randomized order unique words also */
    rand_uniq_words = (char **)HDmalloc(sizeof(char *) * num_uniq_words);

    /* Allocate space for the array of sorted order unique words also */
    sort_uniq_words = (char **)HDmalloc(sizeof(char *) * num_uniq_words);

    /* Insert unique words from test set into unique word set */
    w = 0;
    for (u = 0; u < num_words; u++) {
        /* Assume word is unique */
        tmp_word = (char *)words[u];
        for (v = 0; v < u; v++)
            /* If word is already found in words looked at, decrement unique count */
            if (!HDstrcmp(words[u], words[v])) {
                tmp_word = NULL;
                break;
            } /* end if */

        /* Check if word was actually unique */
        if (tmp_word != NULL)
            uniq_words[w++] = tmp_word;
    } /* end for */

    /* Create randomized set of unique words */
    for (u = 0; u < num_uniq_words; u++)
        rand_uniq_words[u] = uniq_words[u];
    curr_time = HDtime(NULL);
    HDsrandom((unsigned)curr_time);
    for (u = 0; u < num_uniq_words; u++) {
        v = u + ((size_t)HDrandom() % (num_uniq_words - u));
        if (u != v) {
            tmp_word           = rand_uniq_words[u];
            rand_uniq_words[u] = rand_uniq_words[v];
            rand_uniq_words[v] = tmp_word;
        } /* end if */
    }     /* end for */

    /* Create sorted set of unique words */
    for (u = 0; u < num_uniq_words; u++)
        sort_uniq_words[u] = uniq_words[u];
    HDqsort(sort_uniq_words, num_uniq_words, sizeof(char *), tst_strcmp);
} /* end test_tst_init() */

/****************************************************************
**
**  test_tst_create(): Test basic H5ST (ternary search tree) selection code.
**      Tests creating and closing TSTs.
**
****************************************************************/
static void
test_tst_create(void)
{
    H5ST_tree_t *tree; /* TST created */
    herr_t       ret;  /* Generic return value */

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Creating & Closing TSTs\n"));

    /* Try closing a NULL tree */
    tree = NULL;
    ret  = H5ST_close(tree);
    VERIFY(ret, FAIL, "H5ST_close");

    /* Try creating a TST */
    tree = H5ST_create();
    CHECK_PTR(tree, "H5ST_create");

    /* Try closing a real tree */
    ret = H5ST_close(tree);
    CHECK(ret, FAIL, "H5ST_close");

} /* end test_tst_create() */

/****************************************************************
**
**  test_tst_insert(): Test basic H5ST (ternary search tree) selection code.
**      Tests inserting key/value pairs into TST
**
****************************************************************/
static void
test_tst_insert(void)
{
    H5ST_tree_t *tree;  /* TST created */
    H5ST_ptr_t   found; /* Pointer to TST node found */
    void *       obj;   /* Pointer to object located in TST */
    size_t       u;     /* Local index counter */
    htri_t       check; /* Is string in TST? */
    herr_t       ret;   /* Generic return value */

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Inserting Values into TSTs\n"));

    /* Create the TST */
    tree = H5ST_create();
    CHECK_PTR(tree, "H5ST_create");

    /* Insert unique words into TST, in random order */
    for (u = 0; u < num_uniq_words; u++) {
        ret = H5ST_insert(tree, rand_uniq_words[u], rand_uniq_words[u]);
        CHECK(ret, FAIL, "H5ST_insert");
    } /* end for */

    /* Verify that all words were inserted into TST properly */
    for (u = 0; u < num_uniq_words; u++) {
        /* Check that the word is present */
        check = H5ST_search(tree, uniq_words[u]);
        VERIFY(check, TRUE, "H5ST_search");

        /* Check that the value "payloads" are correct */
        found = H5ST_find(tree, uniq_words[u]);
        CHECK_PTR(found, "H5ST_find");

        if (HDstrcmp((const char *)found->eqkid, uniq_words[u]))
            TestErrPrintf("%d: TST node values don't match!, found->eqkid=%s, uniq_words[%u]=%s\n", __LINE__,
                          (char *)found->eqkid, (unsigned)u, uniq_words[u]);

        obj = H5ST_locate(tree, uniq_words[u]);
        CHECK_PTR(obj, "H5ST_locate");

        if (HDstrcmp((const char *)obj, uniq_words[u]))
            TestErrPrintf("%d: TST objects don't match!, obj=%s, uniq_words[%u]=%s\n", __LINE__, (char *)obj,
                          (unsigned)u, uniq_words[u]);
    } /* end for */

    /* Verify that words not in the TST aren't found */
    check = H5ST_search(tree, "foo");
    VERIFY(check, FALSE, "H5ST_search");
    check = H5ST_search(tree, "bar");
    VERIFY(check, FALSE, "H5ST_search");
    check = H5ST_search(tree, "baz");
    VERIFY(check, FALSE, "H5ST_search");

    /* Close the TST */
    ret = H5ST_close(tree);
    CHECK(ret, FAIL, "H5ST_close");
} /* end test_tst_insert() */

/****************************************************************
**
**  test_tst_iterate(): Test basic H5ST (ternary search tree) code.
**      Tests iterating through key/value pairs in TST
**
****************************************************************/
static void
test_tst_iterate(void)
{
    H5ST_tree_t *tree;  /* TST created */
    H5ST_ptr_t   found; /* Pointer to TST node found */
    size_t       u;     /* Local index counter */
    herr_t       ret;   /* Generic return value */

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Iterating Over TSTs\n"));

    /* Create the TST */
    tree = H5ST_create();
    CHECK_PTR(tree, "H5ST_create");

    /* Insert unique words into TST, in random order */
    for (u = 0; u < num_uniq_words; u++) {
        ret = H5ST_insert(tree, rand_uniq_words[u], rand_uniq_words[u]);
        CHECK(ret, FAIL, "H5ST_insert");
    } /* end for */

    /* Use findfirst/findnext calls to iterate through TST */
    found = H5ST_findfirst(tree);
    CHECK_PTR(found, "H5ST_findfirst");
    u = 0;
    do {
        /* Check that the strings in the TST are in the correct order */
        if (HDstrcmp((const char *)found->eqkid, sort_uniq_words[u]))
            TestErrPrintf("%d: TST node values don't match!, found->eqkid=%s, sort_uniq_words[%u]=%s\n",
                          __LINE__, (char *)found->eqkid, (unsigned)u, sort_uniq_words[u]);

        /* Advance to next string in TST */
        found = H5ST_findnext(found);
        u++;
    } while (found != NULL);

    /* Close the TST */
    ret = H5ST_close(tree);
    CHECK(ret, FAIL, "H5ST_close");
} /* end test_tst_iterate() */

/****************************************************************
**
**  test_tst_remove(): Test basic H5ST (ternary search tree) code.
**      Tests removing key/value pairs by string value in TST
**
****************************************************************/
static void
test_tst_remove(void)
{
    H5ST_tree_t *tree;  /* TST created */
    H5ST_ptr_t   found; /* Pointer to TST node found */
    void *       obj;   /* Pointer to object removed from TST */
    htri_t       check; /* Is string in TST? */
    size_t       u;     /* Local index counter */
    herr_t       ret;   /* Generic return value */

    /* Output message about test being performed */
    MESSAGE(5, ("Testing Removing String Values from TSTs\n"));

    /* Create the TST */
    tree = H5ST_create();
    CHECK_PTR(tree, "H5ST_create");

    /* Insert unique words into TST, in random order */
    for (u = 0; u < num_uniq_words; u++) {
        ret = H5ST_insert(tree, rand_uniq_words[u], rand_uniq_words[u]);
        CHECK(ret, FAIL, "H5ST_insert");
    } /* end for */

    /* Remove strings from TST in random order */
    for (u = 0; u < num_uniq_words; u++) {
        obj = H5ST_remove(tree, rand_uniq_words[u]);
        CHECK_PTR(obj, "H5ST_remove");

        /* Check that the correct string was removed from TST */
        if (HDstrcmp((const char *)obj, rand_uniq_words[u]))
            TestErrPrintf("%d: TST node values don't match!, obj=%s, rand_uniq_words[%u]=%s\n", __LINE__,
                          (char *)obj, (unsigned)u, rand_uniq_words[u]);

        /* Check that the string can't be found in the TST any longer */
        check = H5ST_search(tree, rand_uniq_words[u]);
        VERIFY(check, FALSE, "H5ST_search");
    } /* end for */

    /* Re-insert unique words into TST, in random order */
    for (u = 0; u < num_uniq_words; u++) {
        ret = H5ST_insert(tree, rand_uniq_words[u], rand_uniq_words[u]);
        CHECK(ret, FAIL, "H5ST_insert");
    } /* end for */

    /* Remove TST nodes from TST in random order */
    for (u = 0; u < num_uniq_words; u++) {
        /* Get the pointer to the node to delete */
        found = H5ST_find(tree, rand_uniq_words[u]);
        CHECK_PTR(found, "H5ST_find");

        /* Check that the correct object will be removed from TST */
        if (HDstrcmp((const char *)found->eqkid, rand_uniq_words[u]))
            TestErrPrintf("%d: TST node values don't match!, found->eqkid=%s, rand_uniq_words[%u]=%s\n",
                          __LINE__, (char *)found->eqkid, (unsigned)u, rand_uniq_words[u]);

        /* Remove the node */
        ret = H5ST_delete(tree, found);
        CHECK(ret, FAIL, "H5ST_delete");

        /* Check that the string can't be found in the TST any longer */
        check = H5ST_search(tree, rand_uniq_words[u]);
        VERIFY(check, FALSE, "H5ST_search");
    } /* end for */

    /* Close the TST */
    ret = H5ST_close(tree);
    CHECK(ret, FAIL, "H5ST_close");
} /* end test_tst_remove() */

/****************************************************************
**
**  test_tst_finalize(): Test basic H5ST (ternary search tree) selection code.
**      Wrap up data for TST testing
**
****************************************************************/
static void
test_tst_finalize(void)
{
    /* Release memory for unordered, randomized and sorted order unique words */
    HDfree(uniq_words);
    HDfree(rand_uniq_words);
    HDfree(sort_uniq_words);
} /* end test_tst_finalize() */

/****************************************************************
**
**  test_tst(): Main H5ST selection testing routine.
**
****************************************************************/
void
test_tst(void)
{
    /* Output message about test being performed */
    MESSAGE(5, ("Testing Ternary Search Trees\n"));

    /* Initialize TST testing data */
    test_tst_init();

    /* Actual TST tests */
    test_tst_create();  /* Test TST creation */
    test_tst_insert();  /* Test TST insertion */
    test_tst_iterate(); /* Test TST iteration */
    test_tst_remove();  /* Test TST deletion */

    /* Finalize TST testing data */
    test_tst_finalize();
} /* end test_tst() */