| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823 |
- #include <stdlib.h>
- #include <string.h>
- #include <libxml/parser.h>
- #include <libxml/dict.h>
- /**** dictionary tests ****/
- #ifdef __clang__
- #define ATTRIBUTE_NO_SANITIZE_INTEGER \
- __attribute__ ((no_sanitize("unsigned-integer-overflow"))) \
- __attribute__ ((no_sanitize("unsigned-shift-base")))
- #else
- #define ATTRIBUTE_NO_SANITIZE_INTEGER
- #endif
- /* #define WITH_PRINT */
- static const char *seeds1[] = {
- "a", "b", "c",
- "d", "e", "f",
- "g", "h", "i",
- "j", "k", "l",
- NULL
- };
- static const char *seeds2[] = {
- "m", "n", "o",
- "p", "q", "r",
- "s", "t", "u",
- "v", "w", "x",
- NULL
- };
- #define NB_STRINGS_MAX 100000
- #define NB_STRINGS_NS 10000
- #define NB_STRINGS_PREFIX (NB_STRINGS_NS / 20)
- #define NB_STRINGS_MIN 10
- static xmlChar **strings1;
- static xmlChar **strings2;
- static const xmlChar **test1;
- static const xmlChar **test2;
- static int nbErrors = 0;
- static void
- fill_string_pool(xmlChar **strings, const char **seeds) {
- int i, j, k;
- int start_ns = NB_STRINGS_MAX - NB_STRINGS_NS;
- /*
- * That's a bit nasty but the output is fine and it doesn't take hours
- * there is a small but sufficient number of duplicates, and we have
- * ":xxx" and full QNames in the last NB_STRINGS_NS values
- */
- for (i = 0; seeds[i] != NULL; i++) {
- strings[i] = xmlStrdup((const xmlChar *) seeds[i]);
- if (strings[i] == NULL) {
- fprintf(stderr, "Out of memory while generating strings\n");
- exit(1);
- }
- }
- for (j = 0, k = 0; i < start_ns; i++) {
- strings[i] = xmlStrncatNew(strings[j], strings[k], -1);
- if (strings[i] == NULL) {
- fprintf(stderr, "Out of memory while generating strings\n");
- exit(1);
- }
- if (xmlStrlen(strings[i]) > 30) {
- fprintf(stderr, "### %s %s\n", strings[start_ns+j], strings[k]);
- abort();
- }
- j++;
- if (j >= 50) {
- j = 0;
- k++;
- }
- }
- for (j = 0, k = 0; (j < NB_STRINGS_PREFIX) && (i < NB_STRINGS_MAX);
- i++, j++) {
- strings[i] = xmlStrncatNew(strings[k], (const xmlChar *) ":", -1);
- if (strings[i] == NULL) {
- fprintf(stderr, "Out of memory while generating strings\n");
- exit(1);
- }
- k += 1;
- if (k >= start_ns) k = 0;
- }
- for (j = 0, k = 0; i < NB_STRINGS_MAX; i++) {
- strings[i] = xmlStrncatNew(strings[start_ns+j], strings[k], -1);
- if (strings[i] == NULL) {
- fprintf(stderr, "Out of memory while generating strings\n");
- exit(1);
- }
- j++;
- if (j >= NB_STRINGS_PREFIX) j = 0;
- k += 5;
- if (k >= start_ns) k = 0;
- }
- }
- #ifdef WITH_PRINT
- static void print_strings(void) {
- int i;
- for (i = 0; i < NB_STRINGS_MAX;i++) {
- printf("%s\n", strings1[i]);
- }
- for (i = 0; i < NB_STRINGS_MAX;i++) {
- printf("%s\n", strings2[i]);
- }
- }
- #endif
- static void clean_strings(void) {
- int i;
- for (i = 0; i < NB_STRINGS_MAX; i++) {
- if (strings1[i] != NULL) /* really should not happen */
- xmlFree(strings1[i]);
- }
- for (i = 0; i < NB_STRINGS_MAX; i++) {
- if (strings2[i] != NULL) /* really should not happen */
- xmlFree(strings2[i]);
- }
- }
- /*
- * This tests the sub-dictionary support
- */
- static int
- test_subdict(xmlDictPtr parent) {
- int i, j;
- xmlDictPtr dict;
- int ret = 0;
- xmlChar prefix[40];
- xmlChar *cur, *pref;
- const xmlChar *tmp;
- dict = xmlDictCreateSub(parent);
- if (dict == NULL) {
- fprintf(stderr, "Out of memory while creating sub-dictionary\n");
- exit(1);
- }
- /* Cast to avoid buggy warning on MSVC. */
- memset((void *) test2, 0, sizeof(test2));
- /*
- * Fill in NB_STRINGS_MIN, at this point the dictionary should not grow
- * and we allocate all those doing the fast key computations
- * All the strings are based on a different seeds subset so we know
- * they are allocated in the main dictionary, not coming from the parent
- */
- for (i = 0;i < NB_STRINGS_MIN;i++) {
- test2[i] = xmlDictLookup(dict, strings2[i], -1);
- if (test2[i] == NULL) {
- fprintf(stderr, "Failed lookup for '%s'\n", strings2[i]);
- ret = 1;
- nbErrors++;
- }
- }
- j = NB_STRINGS_MAX - NB_STRINGS_NS;
- /* ":foo" like strings2 */
- for (i = 0;i < NB_STRINGS_MIN;i++, j++) {
- test2[j] = xmlDictLookup(dict, strings2[j], xmlStrlen(strings2[j]));
- if (test2[j] == NULL) {
- fprintf(stderr, "Failed lookup for '%s'\n", strings2[j]);
- ret = 1;
- nbErrors++;
- }
- }
- /* "a:foo" like strings2 */
- j = NB_STRINGS_MAX - NB_STRINGS_MIN;
- for (i = 0;i < NB_STRINGS_MIN;i++, j++) {
- test2[j] = xmlDictLookup(dict, strings2[j], xmlStrlen(strings2[j]));
- if (test2[j] == NULL) {
- fprintf(stderr, "Failed lookup for '%s'\n", strings2[j]);
- ret = 1;
- nbErrors++;
- }
- }
- /*
- * At this point allocate all the strings
- * the dictionary will grow in the process, reallocate more string tables
- * and switch to the better key generator
- */
- for (i = 0;i < NB_STRINGS_MAX;i++) {
- if (test2[i] != NULL)
- continue;
- test2[i] = xmlDictLookup(dict, strings2[i], -1);
- if (test2[i] == NULL) {
- fprintf(stderr, "Failed lookup for '%s'\n", strings2[i]);
- ret = 1;
- nbErrors++;
- }
- }
- /*
- * Now we can start to test things, first that all strings2 belongs to
- * the dict, and that none of them was actually allocated in the parent
- */
- for (i = 0;i < NB_STRINGS_MAX;i++) {
- if (!xmlDictOwns(dict, test2[i])) {
- fprintf(stderr, "Failed ownership failure for '%s'\n",
- strings2[i]);
- ret = 1;
- nbErrors++;
- }
- if (xmlDictOwns(parent, test2[i])) {
- fprintf(stderr, "Failed parent ownership failure for '%s'\n",
- strings2[i]);
- ret = 1;
- nbErrors++;
- }
- }
- /*
- * Also verify that all strings from the parent are seen from the subdict
- */
- for (i = 0;i < NB_STRINGS_MAX;i++) {
- if (!xmlDictOwns(dict, test1[i])) {
- fprintf(stderr, "Failed sub-ownership failure for '%s'\n",
- strings1[i]);
- ret = 1;
- nbErrors++;
- }
- }
- /*
- * Then that another lookup to the string in sub will return the same
- */
- for (i = 0;i < NB_STRINGS_MAX;i++) {
- if (xmlDictLookup(dict, strings2[i], -1) != test2[i]) {
- fprintf(stderr, "Failed re-lookup check for %d, '%s'\n",
- i, strings2[i]);
- ret = 1;
- nbErrors++;
- }
- }
- /*
- * But also that any lookup for a string in the parent will be provided
- * as in the parent
- */
- for (i = 0;i < NB_STRINGS_MAX;i++) {
- if (xmlDictLookup(dict, strings1[i], -1) != test1[i]) {
- fprintf(stderr, "Failed parent string lookup check for %d, '%s'\n",
- i, strings1[i]);
- ret = 1;
- nbErrors++;
- }
- }
- /*
- * check the QName lookups
- */
- for (i = NB_STRINGS_MAX - NB_STRINGS_NS;i < NB_STRINGS_MAX;i++) {
- cur = strings2[i];
- pref = &prefix[0];
- while (*cur != ':') *pref++ = *cur++;
- cur++;
- *pref = 0;
- tmp = xmlDictQLookup(dict, &prefix[0], cur);
- if (tmp != test2[i]) {
- fprintf(stderr, "Failed lookup check for '%s':'%s'\n",
- &prefix[0], cur);
- ret = 1;
- nbErrors++;
- }
- }
- /*
- * check the QName lookups for strings from the parent
- */
- for (i = NB_STRINGS_MAX - NB_STRINGS_NS;i < NB_STRINGS_MAX;i++) {
- cur = strings1[i];
- pref = &prefix[0];
- while (*cur != ':') *pref++ = *cur++;
- cur++;
- *pref = 0;
- tmp = xmlDictQLookup(dict, &prefix[0], cur);
- if (xmlDictQLookup(dict, &prefix[0], cur) != test1[i]) {
- fprintf(stderr, "Failed parent lookup check for '%s':'%s'\n",
- &prefix[0], cur);
- ret = 1;
- nbErrors++;
- }
- }
- xmlDictFree(dict);
- return(ret);
- }
- /*
- * Test a single dictionary
- */
- static int
- test_dict(xmlDict *dict) {
- int i, j;
- int ret = 0;
- xmlChar prefix[40];
- xmlChar *cur, *pref;
- const xmlChar *tmp;
- /* Cast to avoid buggy warning on MSVC. */
- memset((void *) test1, 0, sizeof(test1));
- /*
- * Fill in NB_STRINGS_MIN, at this point the dictionary should not grow
- * and we allocate all those doing the fast key computations
- */
- for (i = 0;i < NB_STRINGS_MIN;i++) {
- test1[i] = xmlDictLookup(dict, strings1[i], -1);
- if (test1[i] == NULL) {
- fprintf(stderr, "Failed lookup for '%s'\n", strings1[i]);
- ret = 1;
- nbErrors++;
- }
- }
- j = NB_STRINGS_MAX - NB_STRINGS_NS;
- /* ":foo" like strings1 */
- for (i = 0;i < NB_STRINGS_MIN;i++, j++) {
- test1[j] = xmlDictLookup(dict, strings1[j], xmlStrlen(strings1[j]));
- if (test1[j] == NULL) {
- fprintf(stderr, "Failed lookup for '%s'\n", strings1[j]);
- ret = 1;
- nbErrors++;
- }
- }
- /* "a:foo" like strings1 */
- j = NB_STRINGS_MAX - NB_STRINGS_MIN;
- for (i = 0;i < NB_STRINGS_MIN;i++, j++) {
- test1[j] = xmlDictLookup(dict, strings1[j], xmlStrlen(strings1[j]));
- if (test1[j] == NULL) {
- fprintf(stderr, "Failed lookup for '%s'\n", strings1[j]);
- ret = 1;
- nbErrors++;
- }
- }
- /*
- * At this point allocate all the strings
- * the dictionary will grow in the process, reallocate more string tables
- * and switch to the better key generator
- */
- for (i = 0;i < NB_STRINGS_MAX;i++) {
- if (test1[i] != NULL)
- continue;
- test1[i] = xmlDictLookup(dict, strings1[i], -1);
- if (test1[i] == NULL) {
- fprintf(stderr, "Failed lookup for '%s'\n", strings1[i]);
- ret = 1;
- nbErrors++;
- }
- }
- /*
- * Now we can start to test things, first that all strings1 belongs to
- * the dict
- */
- for (i = 0;i < NB_STRINGS_MAX;i++) {
- if (!xmlDictOwns(dict, test1[i])) {
- fprintf(stderr, "Failed ownership failure for '%s'\n",
- strings1[i]);
- ret = 1;
- nbErrors++;
- }
- }
- /*
- * Then that another lookup to the string will return the same
- */
- for (i = 0;i < NB_STRINGS_MAX;i++) {
- if (xmlDictLookup(dict, strings1[i], -1) != test1[i]) {
- fprintf(stderr, "Failed re-lookup check for %d, '%s'\n",
- i, strings1[i]);
- ret = 1;
- nbErrors++;
- }
- }
- /*
- * More complex, check the QName lookups
- */
- for (i = NB_STRINGS_MAX - NB_STRINGS_NS;i < NB_STRINGS_MAX;i++) {
- cur = strings1[i];
- pref = &prefix[0];
- while (*cur != ':') *pref++ = *cur++;
- cur++;
- *pref = 0;
- tmp = xmlDictQLookup(dict, &prefix[0], cur);
- if (tmp != test1[i]) {
- fprintf(stderr, "Failed lookup check for '%s':'%s'\n",
- &prefix[0], cur);
- ret = 1;
- nbErrors++;
- }
- }
- return(ret);
- }
- static int
- testall_dict(void) {
- xmlDictPtr dict;
- int ret = 0;
- strings1 = xmlMalloc(NB_STRINGS_MAX * sizeof(strings1[0]));
- memset(strings1, 0, NB_STRINGS_MAX * sizeof(strings1[0]));
- strings2 = xmlMalloc(NB_STRINGS_MAX * sizeof(strings2[0]));
- memset(strings2, 0, NB_STRINGS_MAX * sizeof(strings2[0]));
- test1 = xmlMalloc(NB_STRINGS_MAX * sizeof(test1[0]));
- memset(test1, 0, NB_STRINGS_MAX * sizeof(test1[0]));
- test2 = xmlMalloc(NB_STRINGS_MAX * sizeof(test2[0]));
- memset(test2, 0, NB_STRINGS_MAX * sizeof(test2[0]));
- fill_string_pool(strings1, seeds1);
- fill_string_pool(strings2, seeds2);
- #ifdef WITH_PRINT
- print_strings();
- #endif
- dict = xmlDictCreate();
- if (dict == NULL) {
- fprintf(stderr, "Out of memory while creating dictionary\n");
- exit(1);
- }
- if (test_dict(dict) != 0) {
- ret = 1;
- }
- if (test_subdict(dict) != 0) {
- ret = 1;
- }
- xmlDictFree(dict);
- clean_strings();
- xmlFree(strings1);
- xmlFree(strings2);
- xmlFree(test1);
- xmlFree(test2);
- return ret;
- }
- /**** Hash table tests ****/
- static unsigned
- rng_state[2] = { 123, 456 };
- #define HASH_ROL(x,n) ((x) << (n) | ((x) & 0xFFFFFFFF) >> (32 - (n)))
- ATTRIBUTE_NO_SANITIZE_INTEGER
- static unsigned
- my_rand(unsigned max) {
- unsigned s0 = rng_state[0];
- unsigned s1 = rng_state[1];
- unsigned result = HASH_ROL(s0 * 0x9E3779BB, 5) * 5;
- s1 ^= s0;
- rng_state[0] = HASH_ROL(s0, 26) ^ s1 ^ (s1 << 9);
- rng_state[1] = HASH_ROL(s1, 13);
- return((result & 0xFFFFFFFF) % max);
- }
- static xmlChar *
- gen_random_string(xmlChar id) {
- unsigned size = my_rand(64) + 1;
- unsigned id_pos = my_rand(size);
- size_t j;
- xmlChar *str = xmlMalloc(size + 1);
- for (j = 0; j < size; j++) {
- str[j] = 'a' + my_rand(26);
- }
- str[id_pos] = id;
- str[size] = 0;
- /* Generate QName in 75% of cases */
- if (size > 3 && my_rand(4) > 0) {
- unsigned colon_pos = my_rand(size - 3) + 1;
- if (colon_pos >= id_pos)
- colon_pos++;
- str[colon_pos] = ':';
- }
- return str;
- }
- typedef struct {
- xmlChar **strings;
- size_t num_entries;
- size_t num_keys;
- size_t num_strings;
- size_t index;
- xmlChar id;
- } StringPool;
- static StringPool *
- pool_new(size_t num_entries, size_t num_keys, xmlChar id) {
- StringPool *ret;
- size_t num_strings;
- ret = xmlMalloc(sizeof(*ret));
- ret->num_entries = num_entries;
- ret->num_keys = num_keys;
- num_strings = num_entries * num_keys;
- ret->strings = xmlMalloc(num_strings * sizeof(ret->strings[0]));
- memset(ret->strings, 0, num_strings * sizeof(ret->strings[0]));
- ret->num_strings = num_strings;
- ret->index = 0;
- ret->id = id;
- return ret;
- }
- static void
- pool_free(StringPool *pool) {
- size_t i;
- for (i = 0; i < pool->num_strings; i++) {
- xmlFree(pool->strings[i]);
- }
- xmlFree(pool->strings);
- xmlFree(pool);
- }
- static int
- pool_done(StringPool *pool) {
- return pool->index >= pool->num_strings;
- }
- static void
- pool_reset(StringPool *pool) {
- pool->index = 0;
- }
- static int
- pool_bulk_insert(StringPool *pool, xmlHashTablePtr hash, size_t num) {
- size_t i, j;
- int ret = 0;
- for (i = pool->index, j = 0; i < pool->num_strings && j < num; j++) {
- xmlChar *str[3];
- size_t k;
- while (1) {
- xmlChar tmp_key[1];
- int res;
- for (k = 0; k < pool->num_keys; k++)
- str[k] = gen_random_string(pool->id);
- switch (pool->num_keys) {
- case 1:
- res = xmlHashAddEntry(hash, str[0], tmp_key);
- if (res == 0 &&
- xmlHashUpdateEntry(hash, str[0], str[0], NULL) != 0)
- ret = -1;
- break;
- case 2:
- res = xmlHashAddEntry2(hash, str[0], str[1], tmp_key);
- if (res == 0 &&
- xmlHashUpdateEntry2(hash, str[0], str[1], str[0],
- NULL) != 0)
- ret = -1;
- break;
- case 3:
- res = xmlHashAddEntry3(hash, str[0], str[1], str[2],
- tmp_key);
- if (res == 0 &&
- xmlHashUpdateEntry3(hash, str[0], str[1], str[2],
- str[0], NULL) != 0)
- ret = -1;
- break;
- }
- if (res == 0)
- break;
- for (k = 0; k < pool->num_keys; k++)
- xmlFree(str[k]);
- }
- for (k = 0; k < pool->num_keys; k++)
- pool->strings[i++] = str[k];
- }
- pool->index = i;
- return ret;
- }
- static xmlChar *
- hash_qlookup(xmlHashTable *hash, xmlChar **names, size_t num_keys) {
- xmlChar *prefix[3];
- const xmlChar *local[3];
- xmlChar *res;
- size_t i;
- for (i = 0; i < 3; ++i) {
- if (i >= num_keys) {
- prefix[i] = NULL;
- local[i] = NULL;
- } else {
- const xmlChar *name = names[i];
- const xmlChar *colon = BAD_CAST strchr((const char *) name, ':');
- if (colon == NULL) {
- prefix[i] = NULL;
- local[i] = name;
- } else {
- prefix[i] = xmlStrndup(name, colon - name);
- local[i] = &colon[1];
- }
- }
- }
- res = xmlHashQLookup3(hash, prefix[0], local[0], prefix[1], local[1],
- prefix[2], local[2]);
- for (i = 0; i < 3; ++i)
- xmlFree(prefix[i]);
- return res;
- }
- static int
- pool_bulk_lookup(StringPool *pool, xmlHashTablePtr hash, size_t num,
- int existing) {
- size_t i, j;
- int ret = 0;
- for (i = pool->index, j = 0; i < pool->num_strings && j < num; j++) {
- xmlChar **str = &pool->strings[i];
- int q;
- for (q = 0; q < 2; q++) {
- xmlChar *res = NULL;
- if (q) {
- res = hash_qlookup(hash, str, pool->num_keys);
- } else {
- switch (pool->num_keys) {
- case 1:
- res = xmlHashLookup(hash, str[0]);
- break;
- case 2:
- res = xmlHashLookup2(hash, str[0], str[1]);
- break;
- case 3:
- res = xmlHashLookup3(hash, str[0], str[1], str[2]);
- break;
- }
- }
- if (existing) {
- if (res != str[0])
- ret = -1;
- } else {
- if (res != NULL)
- ret = -1;
- }
- }
- i += pool->num_keys;
- }
- pool->index = i;
- return ret;
- }
- static int
- pool_bulk_remove(StringPool *pool, xmlHashTablePtr hash, size_t num) {
- size_t i, j;
- int ret = 0;
- for (i = pool->index, j = 0; i < pool->num_strings && j < num; j++) {
- xmlChar **str = &pool->strings[i];
- int res = -1;
- switch (pool->num_keys) {
- case 1:
- res = xmlHashRemoveEntry(hash, str[0], NULL);
- break;
- case 2:
- res = xmlHashRemoveEntry2(hash, str[0], str[1], NULL);
- break;
- case 3:
- res = xmlHashRemoveEntry3(hash, str[0], str[1], str[2], NULL);
- break;
- }
- if (res != 0)
- ret = -1;
- i += pool->num_keys;
- }
- pool->index = i;
- return ret;
- }
- static int
- test_hash(size_t num_entries, size_t num_keys, int use_dict) {
- xmlDict *dict = NULL;
- xmlHashTable *hash;
- StringPool *pool1, *pool2;
- int ret = 0;
- if (use_dict) {
- dict = xmlDictCreate();
- hash = xmlHashCreateDict(0, dict);
- } else {
- hash = xmlHashCreate(0);
- }
- pool1 = pool_new(num_entries, num_keys, '1');
- pool2 = pool_new(num_entries, num_keys, '2');
- /* Insert all strings from pool2 and about half of pool1. */
- while (!pool_done(pool2)) {
- if (pool_bulk_insert(pool1, hash, my_rand(50)) != 0) {
- fprintf(stderr, "pool1: hash insert failed\n");
- ret = 1;
- }
- if (pool_bulk_insert(pool2, hash, my_rand(100)) != 0) {
- fprintf(stderr, "pool1: hash insert failed\n");
- ret = 1;
- }
- }
- /* Check existing entries */
- pool_reset(pool2);
- if (pool_bulk_lookup(pool2, hash, pool2->num_entries, 1) != 0) {
- fprintf(stderr, "pool2: hash lookup failed\n");
- ret = 1;
- }
- /* Remove all strings from pool2 and insert the rest of pool1. */
- pool_reset(pool2);
- while (!pool_done(pool1) || !pool_done(pool2)) {
- if (pool_bulk_insert(pool1, hash, my_rand(50)) != 0) {
- fprintf(stderr, "pool1: hash insert failed\n");
- ret = 1;
- }
- if (pool_bulk_remove(pool2, hash, my_rand(100)) != 0) {
- fprintf(stderr, "pool2: hash remove failed\n");
- ret = 1;
- }
- }
- /* Check existing entries */
- pool_reset(pool1);
- if (pool_bulk_lookup(pool1, hash, pool1->num_entries, 1) != 0) {
- fprintf(stderr, "pool1: hash lookup failed\n");
- ret = 1;
- }
- /* Check removed entries */
- pool_reset(pool2);
- if (pool_bulk_lookup(pool2, hash, pool2->num_entries, 0) != 0) {
- fprintf(stderr, "pool2: hash lookup succeeded unexpectedly\n");
- ret = 1;
- }
- pool_free(pool1);
- pool_free(pool2);
- xmlHashFree(hash, NULL);
- xmlDictFree(dict);
- return ret;
- }
- static int
- testall_hash(void) {
- size_t num_keys;
- for (num_keys = 1; num_keys <= 3; num_keys++) {
- size_t num_strings;
- size_t max_strings = num_keys == 1 ? 100000 : 1000;
- for (num_strings = 10; num_strings <= max_strings; num_strings *= 10) {
- size_t reps, i;
- reps = 1000 / num_strings;
- if (reps == 0)
- reps = 1;
- for (i = 0; i < reps; i++) {
- if (test_hash(num_strings, num_keys, /* use_dict */ 0) != 0)
- return(1);
- }
- if (test_hash(num_strings, num_keys, /* use_dict */ 1) != 0)
- return(1);
- }
- }
- return(0);
- }
- /**** main ****/
- int
- main(void) {
- int ret = 0;
- LIBXML_TEST_VERSION
- if (testall_dict() != 0) {
- fprintf(stderr, "dictionary tests failed\n");
- ret = 1;
- }
- if (testall_hash() != 0) {
- fprintf(stderr, "hash tests failed\n");
- ret = 1;
- }
- xmlCleanupParser();
- return(ret);
- }
|