Skip to content
Snippets Groups Projects
testdict.c 11.4 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include <string.h>
    #include <libxml/parser.h>
    #include <libxml/dict.h>
    
    /* #define WITH_PRINT */
    
    
       "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");
    
    }
    
    #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 (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 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);
    
    	    fprintf(stderr, "Failed lookup for '%s'\n", strings1[i]);
    
        for (i = 0;i < NB_STRINGS_MIN;i++, j++) {
    
            test1[j] = xmlDictLookup(dict, strings1[j], xmlStrlen(strings1[j]));
    
    	    fprintf(stderr, "Failed lookup for '%s'\n", strings1[j]);
    
        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]));
    
    	    fprintf(stderr, "Failed lookup for '%s'\n", strings1[j]);
    
    	}
        }
    
        /*
         * 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);
    
    	    fprintf(stderr, "Failed lookup for '%s'\n", strings1[i]);
    
         * 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",
    
    	}
        }
    
        /*
         * 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",
    
    	}
        }
    
        /*
         * More complex, check the QName lookups
         */
        for (i = NB_STRINGS_MAX - NB_STRINGS_NS;i < NB_STRINGS_MAX;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;
    
    }
    
    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);
    }