123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444 |
- #include <string.h>
- #include <libxml/parser.h>
- #include <libxml/dict.h>
- /* #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_NS 100
- #define NB_STRINGS_MAX 10000
- #define NB_STRINGS_MIN 10
- static xmlChar *strings1[NB_STRINGS_MAX];
- static xmlChar *strings2[NB_STRINGS_MAX];
- static const xmlChar *test1[NB_STRINGS_MAX];
- static const xmlChar *test2[NB_STRINGS_MAX];
- static int nbErrors = 0;
- static void fill_strings(void) {
- int i, j, k;
- /*
- * 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; seeds1[i] != NULL; i++) {
- strings1[i] = xmlStrdup((const xmlChar *) seeds1[i]);
- if (strings1[i] == NULL) {
- fprintf(stderr, "Out of memory while generating strings1\n");
- exit(1);
- }
- }
- for (j = 0, k = 0;i < NB_STRINGS_MAX - NB_STRINGS_NS;i++,j++) {
- strings1[i] = xmlStrncatNew(strings1[j], strings1[k], -1);
- if (strings1[i] == NULL) {
- fprintf(stderr, "Out of memory while generating strings1\n");
- exit(1);
- }
- if (j >= 50) {
- j = 0;
- k++;
- }
- }
- for (j = 0; (j < 50) && (i < NB_STRINGS_MAX); i++, j+=2) {
- strings1[i] = xmlStrncatNew(strings1[j], (const xmlChar *) ":", -1);
- if (strings1[i] == NULL) {
- fprintf(stderr, "Out of memory while generating strings1\n");
- exit(1);
- }
- }
- for (j = NB_STRINGS_MAX - NB_STRINGS_NS, k = 0;
- i < NB_STRINGS_MAX;i++,j++) {
- strings1[i] = xmlStrncatNew(strings1[j], strings1[k], -1);
- if (strings1[i] == NULL) {
- fprintf(stderr, "Out of memory while generating strings1\n");
- exit(1);
- }
- k += 3;
- if (k >= 50) k = 0;
- }
- /*
- * Now do the same with the second pool of strings
- */
- for (i = 0; seeds2[i] != NULL; i++) {
- strings2[i] = xmlStrdup((const xmlChar *) seeds2[i]);
- if (strings2[i] == NULL) {
- fprintf(stderr, "Out of memory while generating strings2\n");
- exit(1);
- }
- }
- for (j = 0, k = 0;i < NB_STRINGS_MAX - NB_STRINGS_NS;i++,j++) {
- strings2[i] = xmlStrncatNew(strings2[j], strings2[k], -1);
- if (strings2[i] == NULL) {
- fprintf(stderr, "Out of memory while generating strings2\n");
- exit(1);
- }
- if (j >= 50) {
- j = 0;
- k++;
- }
- }
- for (j = 0; (j < 50) && (i < NB_STRINGS_MAX); i++, j+=2) {
- strings2[i] = xmlStrncatNew(strings2[j], (const xmlChar *) ":", -1);
- if (strings2[i] == NULL) {
- fprintf(stderr, "Out of memory while generating strings2\n");
- exit(1);
- }
- }
- for (j = NB_STRINGS_MAX - NB_STRINGS_NS, k = 0;
- i < NB_STRINGS_MAX;i++,j++) {
- strings2[i] = xmlStrncatNew(strings2[j], strings2[k], -1);
- if (strings2[i] == NULL) {
- fprintf(stderr, "Out of memory while generating strings2\n");
- exit(1);
- }
- k += 3;
- if (k >= 50) 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 run_test2(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);
- }
- memset(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 (xmlDictQLookup(dict, &prefix[0], cur) != 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 run_test1(void) {
- int i, j;
- xmlDictPtr dict;
- int ret = 0;
- xmlChar prefix[40];
- xmlChar *cur, *pref;
- const xmlChar *tmp;
- dict = xmlDictCreate();
- if (dict == NULL) {
- fprintf(stderr, "Out of memory while creating dictionary\n");
- exit(1);
- }
- memset(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 (xmlDictQLookup(dict, &prefix[0], cur) != test1[i]) {
- fprintf(stderr, "Failed lookup check for '%s':'%s'\n",
- &prefix[0], cur);
- ret = 1;
- nbErrors++;
- }
- }
- run_test2(dict);
- xmlDictFree(dict);
- return(ret);
- }
- int main(void)
- {
- int ret;
- LIBXML_TEST_VERSION
- fill_strings();
- #ifdef WITH_PRINT
- print_strings();
- #endif
- ret = run_test1();
- if (ret == 0) {
- printf("dictionary tests succeeded %d strings\n", 2 * NB_STRINGS_MAX);
- } else {
- printf("dictionary tests failed with %d errors\n", nbErrors);
- }
- clean_strings();
- xmlCleanupParser();
- xmlMemoryDump();
- return(ret);
- }
|