Blame testdict.c

Packit 423ecb
#include <string.h>
Packit 423ecb
#include <libxml/parser.h>
Packit 423ecb
#include <libxml/dict.h>
Packit 423ecb
Packit 423ecb
/* #define WITH_PRINT */
Packit 423ecb
Packit 423ecb
static const char *seeds1[] = {
Packit 423ecb
   "a", "b", "c",
Packit 423ecb
   "d", "e", "f",
Packit 423ecb
   "g", "h", "i",
Packit 423ecb
   "j", "k", "l",
Packit 423ecb
Packit 423ecb
   NULL
Packit 423ecb
};
Packit 423ecb
Packit 423ecb
static const char *seeds2[] = {
Packit 423ecb
   "m", "n", "o",
Packit 423ecb
   "p", "q", "r",
Packit 423ecb
   "s", "t", "u",
Packit 423ecb
   "v", "w", "x",
Packit 423ecb
Packit 423ecb
   NULL
Packit 423ecb
};
Packit 423ecb
Packit 423ecb
#define NB_STRINGS_NS 100
Packit 423ecb
#define NB_STRINGS_MAX 10000
Packit 423ecb
#define NB_STRINGS_MIN 10
Packit 423ecb
Packit 423ecb
static xmlChar *strings1[NB_STRINGS_MAX];
Packit 423ecb
static xmlChar *strings2[NB_STRINGS_MAX];
Packit 423ecb
static const xmlChar *test1[NB_STRINGS_MAX];
Packit 423ecb
static const xmlChar *test2[NB_STRINGS_MAX];
Packit 423ecb
static int nbErrors = 0;
Packit 423ecb
Packit 423ecb
static void fill_strings(void) {
Packit 423ecb
    int i, j, k;
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * That's a bit nasty but the output is fine and it doesn't take hours
Packit 423ecb
     * there is a small but sufficient number of duplicates, and we have
Packit 423ecb
     * ":xxx" and full QNames in the last NB_STRINGS_NS values
Packit 423ecb
     */
Packit 423ecb
    for (i = 0; seeds1[i] != NULL; i++) {
Packit 423ecb
        strings1[i] = xmlStrdup((const xmlChar *) seeds1[i]);
Packit 423ecb
	if (strings1[i] == NULL) {
Packit 423ecb
	    fprintf(stderr, "Out of memory while generating strings1\n");
Packit 423ecb
	    exit(1);
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
    for (j = 0, k = 0;i < NB_STRINGS_MAX - NB_STRINGS_NS;i++,j++) {
Packit 423ecb
        strings1[i] = xmlStrncatNew(strings1[j], strings1[k], -1);
Packit 423ecb
	if (strings1[i] == NULL) {
Packit 423ecb
	    fprintf(stderr, "Out of memory while generating strings1\n");
Packit 423ecb
	    exit(1);
Packit 423ecb
	}
Packit 423ecb
	if (j >= 50) {
Packit 423ecb
	    j = 0;
Packit 423ecb
	    k++;
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
    for (j = 0; (j < 50) && (i < NB_STRINGS_MAX); i++, j+=2) {
Packit 423ecb
        strings1[i] = xmlStrncatNew(strings1[j], (const xmlChar *) ":", -1);
Packit 423ecb
	if (strings1[i] == NULL) {
Packit 423ecb
	    fprintf(stderr, "Out of memory while generating strings1\n");
Packit 423ecb
	    exit(1);
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
    for (j = NB_STRINGS_MAX - NB_STRINGS_NS, k = 0;
Packit 423ecb
         i < NB_STRINGS_MAX;i++,j++) {
Packit 423ecb
        strings1[i] = xmlStrncatNew(strings1[j], strings1[k], -1);
Packit 423ecb
	if (strings1[i] == NULL) {
Packit 423ecb
	    fprintf(stderr, "Out of memory while generating strings1\n");
Packit 423ecb
	    exit(1);
Packit 423ecb
	}
Packit 423ecb
	k += 3;
Packit 423ecb
	if (k >= 50) k = 0;
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * Now do the same with the second pool of strings
Packit 423ecb
     */
Packit 423ecb
    for (i = 0; seeds2[i] != NULL; i++) {
Packit 423ecb
        strings2[i] = xmlStrdup((const xmlChar *) seeds2[i]);
Packit 423ecb
	if (strings2[i] == NULL) {
Packit 423ecb
	    fprintf(stderr, "Out of memory while generating strings2\n");
Packit 423ecb
	    exit(1);
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
    for (j = 0, k = 0;i < NB_STRINGS_MAX - NB_STRINGS_NS;i++,j++) {
Packit 423ecb
        strings2[i] = xmlStrncatNew(strings2[j], strings2[k], -1);
Packit 423ecb
	if (strings2[i] == NULL) {
Packit 423ecb
	    fprintf(stderr, "Out of memory while generating strings2\n");
Packit 423ecb
	    exit(1);
Packit 423ecb
	}
Packit 423ecb
	if (j >= 50) {
Packit 423ecb
	    j = 0;
Packit 423ecb
	    k++;
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
    for (j = 0; (j < 50) && (i < NB_STRINGS_MAX); i++, j+=2) {
Packit 423ecb
        strings2[i] = xmlStrncatNew(strings2[j], (const xmlChar *) ":", -1);
Packit 423ecb
	if (strings2[i] == NULL) {
Packit 423ecb
	    fprintf(stderr, "Out of memory while generating strings2\n");
Packit 423ecb
	    exit(1);
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
    for (j = NB_STRINGS_MAX - NB_STRINGS_NS, k = 0;
Packit 423ecb
         i < NB_STRINGS_MAX;i++,j++) {
Packit 423ecb
        strings2[i] = xmlStrncatNew(strings2[j], strings2[k], -1);
Packit 423ecb
	if (strings2[i] == NULL) {
Packit 423ecb
	    fprintf(stderr, "Out of memory while generating strings2\n");
Packit 423ecb
	    exit(1);
Packit 423ecb
	}
Packit 423ecb
	k += 3;
Packit 423ecb
	if (k >= 50) k = 0;
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef WITH_PRINT
Packit 423ecb
static void print_strings(void) {
Packit 423ecb
    int i;
Packit 423ecb
Packit 423ecb
    for (i = 0; i < NB_STRINGS_MAX;i++) {
Packit 423ecb
        printf("%s\n", strings1[i]);
Packit 423ecb
    }
Packit 423ecb
    for (i = 0; i < NB_STRINGS_MAX;i++) {
Packit 423ecb
        printf("%s\n", strings2[i]);
Packit 423ecb
    }
Packit 423ecb
}
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
static void clean_strings(void) {
Packit 423ecb
    int i;
Packit 423ecb
Packit 423ecb
    for (i = 0; i < NB_STRINGS_MAX; i++) {
Packit 423ecb
        if (strings1[i] != NULL) /* really should not happen */
Packit 423ecb
	    xmlFree(strings1[i]);
Packit 423ecb
    }
Packit 423ecb
    for (i = 0; i < NB_STRINGS_MAX; i++) {
Packit 423ecb
        if (strings2[i] != NULL) /* really should not happen */
Packit 423ecb
	    xmlFree(strings2[i]);
Packit 423ecb
    }
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/*
Packit 423ecb
 * This tests the sub-dictionary support
Packit 423ecb
 */
Packit 423ecb
static int run_test2(xmlDictPtr parent) {
Packit 423ecb
    int i, j;
Packit 423ecb
    xmlDictPtr dict;
Packit 423ecb
    int ret = 0;
Packit 423ecb
    xmlChar prefix[40];
Packit 423ecb
    xmlChar *cur, *pref;
Packit 423ecb
    const xmlChar *tmp;
Packit 423ecb
Packit 423ecb
    dict = xmlDictCreateSub(parent);
Packit 423ecb
    if (dict == NULL) {
Packit 423ecb
	fprintf(stderr, "Out of memory while creating sub-dictionary\n");
Packit 423ecb
	exit(1);
Packit 423ecb
    }
Packit 423ecb
    memset(test2, 0, sizeof(test2));
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * Fill in NB_STRINGS_MIN, at this point the dictionary should not grow
Packit 423ecb
     * and we allocate all those doing the fast key computations
Packit 423ecb
     * All the strings are based on a different seeds subset so we know
Packit 423ecb
     * they are allocated in the main dictionary, not coming from the parent
Packit 423ecb
     */
Packit 423ecb
    for (i = 0;i < NB_STRINGS_MIN;i++) {
Packit 423ecb
        test2[i] = xmlDictLookup(dict, strings2[i], -1);
Packit 423ecb
	if (test2[i] == NULL) {
Packit 423ecb
	    fprintf(stderr, "Failed lookup for '%s'\n", strings2[i]);
Packit 423ecb
	    ret = 1;
Packit 423ecb
	    nbErrors++;
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
    j = NB_STRINGS_MAX - NB_STRINGS_NS;
Packit 423ecb
    /* ":foo" like strings2 */
Packit 423ecb
    for (i = 0;i < NB_STRINGS_MIN;i++, j++) {
Packit 423ecb
        test2[j] = xmlDictLookup(dict, strings2[j], xmlStrlen(strings2[j]));
Packit 423ecb
	if (test2[j] == NULL) {
Packit 423ecb
	    fprintf(stderr, "Failed lookup for '%s'\n", strings2[j]);
Packit 423ecb
	    ret = 1;
Packit 423ecb
	    nbErrors++;
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
    /* "a:foo" like strings2 */
Packit 423ecb
    j = NB_STRINGS_MAX - NB_STRINGS_MIN;
Packit 423ecb
    for (i = 0;i < NB_STRINGS_MIN;i++, j++) {
Packit 423ecb
        test2[j] = xmlDictLookup(dict, strings2[j], xmlStrlen(strings2[j]));
Packit 423ecb
	if (test2[j] == NULL) {
Packit 423ecb
	    fprintf(stderr, "Failed lookup for '%s'\n", strings2[j]);
Packit 423ecb
	    ret = 1;
Packit 423ecb
	    nbErrors++;
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * At this point allocate all the strings
Packit 423ecb
     * the dictionary will grow in the process, reallocate more string tables
Packit 423ecb
     * and switch to the better key generator
Packit 423ecb
     */
Packit 423ecb
    for (i = 0;i < NB_STRINGS_MAX;i++) {
Packit 423ecb
        if (test2[i] != NULL)
Packit 423ecb
	    continue;
Packit 423ecb
	test2[i] = xmlDictLookup(dict, strings2[i], -1);
Packit 423ecb
	if (test2[i] == NULL) {
Packit 423ecb
	    fprintf(stderr, "Failed lookup for '%s'\n", strings2[i]);
Packit 423ecb
	    ret = 1;
Packit 423ecb
	    nbErrors++;
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * Now we can start to test things, first that all strings2 belongs to
Packit 423ecb
     * the dict, and that none of them was actually allocated in the parent
Packit 423ecb
     */
Packit 423ecb
    for (i = 0;i < NB_STRINGS_MAX;i++) {
Packit 423ecb
        if (!xmlDictOwns(dict, test2[i])) {
Packit 423ecb
	    fprintf(stderr, "Failed ownership failure for '%s'\n",
Packit 423ecb
	            strings2[i]);
Packit 423ecb
	    ret = 1;
Packit 423ecb
	    nbErrors++;
Packit 423ecb
	}
Packit 423ecb
        if (xmlDictOwns(parent, test2[i])) {
Packit 423ecb
	    fprintf(stderr, "Failed parent ownership failure for '%s'\n",
Packit 423ecb
	            strings2[i]);
Packit 423ecb
	    ret = 1;
Packit 423ecb
	    nbErrors++;
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * Also verify that all strings from the parent are seen from the subdict
Packit 423ecb
     */
Packit 423ecb
    for (i = 0;i < NB_STRINGS_MAX;i++) {
Packit 423ecb
        if (!xmlDictOwns(dict, test1[i])) {
Packit 423ecb
	    fprintf(stderr, "Failed sub-ownership failure for '%s'\n",
Packit 423ecb
	            strings1[i]);
Packit 423ecb
	    ret = 1;
Packit 423ecb
	    nbErrors++;
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * Then that another lookup to the string in sub will return the same
Packit 423ecb
     */
Packit 423ecb
    for (i = 0;i < NB_STRINGS_MAX;i++) {
Packit 423ecb
        if (xmlDictLookup(dict, strings2[i], -1) != test2[i]) {
Packit 423ecb
	    fprintf(stderr, "Failed re-lookup check for %d, '%s'\n",
Packit 423ecb
	            i, strings2[i]);
Packit 423ecb
	    ret = 1;
Packit 423ecb
	    nbErrors++;
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
    /*
Packit 423ecb
     * But also that any lookup for a string in the parent will be provided
Packit 423ecb
     * as in the parent
Packit 423ecb
     */
Packit 423ecb
    for (i = 0;i < NB_STRINGS_MAX;i++) {
Packit 423ecb
        if (xmlDictLookup(dict, strings1[i], -1) != test1[i]) {
Packit 423ecb
	    fprintf(stderr, "Failed parent string lookup check for %d, '%s'\n",
Packit 423ecb
	            i, strings1[i]);
Packit 423ecb
	    ret = 1;
Packit 423ecb
	    nbErrors++;
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * check the QName lookups
Packit 423ecb
     */
Packit 423ecb
    for (i = NB_STRINGS_MAX - NB_STRINGS_NS;i < NB_STRINGS_MAX;i++) {
Packit 423ecb
        cur = strings2[i];
Packit 423ecb
	pref = &prefix[0];
Packit 423ecb
	while (*cur != ':') *pref++ = *cur++;
Packit 423ecb
	cur++;
Packit 423ecb
	*pref = 0;
Packit 423ecb
	tmp = xmlDictQLookup(dict, &prefix[0], cur);
Packit 423ecb
	if (tmp != test2[i]) {
Packit 423ecb
	    fprintf(stderr, "Failed lookup check for '%s':'%s'\n",
Packit 423ecb
	            &prefix[0], cur);
Packit 423ecb
            ret = 1;
Packit 423ecb
	    nbErrors++;
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
    /*
Packit 423ecb
     * check the QName lookups for strings from the parent
Packit 423ecb
     */
Packit 423ecb
    for (i = NB_STRINGS_MAX - NB_STRINGS_NS;i < NB_STRINGS_MAX;i++) {
Packit 423ecb
        cur = strings1[i];
Packit 423ecb
	pref = &prefix[0];
Packit 423ecb
	while (*cur != ':') *pref++ = *cur++;
Packit 423ecb
	cur++;
Packit 423ecb
	*pref = 0;
Packit 423ecb
	tmp = xmlDictQLookup(dict, &prefix[0], cur);
Packit 423ecb
	if (xmlDictQLookup(dict, &prefix[0], cur) != test1[i]) {
Packit 423ecb
	    fprintf(stderr, "Failed parent lookup check for '%s':'%s'\n",
Packit 423ecb
	            &prefix[0], cur);
Packit 423ecb
            ret = 1;
Packit 423ecb
	    nbErrors++;
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    xmlDictFree(dict);
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/*
Packit 423ecb
 * Test a single dictionary
Packit 423ecb
 */
Packit 423ecb
static int run_test1(void) {
Packit 423ecb
    int i, j;
Packit 423ecb
    xmlDictPtr dict;
Packit 423ecb
    int ret = 0;
Packit 423ecb
    xmlChar prefix[40];
Packit 423ecb
    xmlChar *cur, *pref;
Packit 423ecb
    const xmlChar *tmp;
Packit 423ecb
Packit 423ecb
    dict = xmlDictCreate();
Packit 423ecb
    if (dict == NULL) {
Packit 423ecb
	fprintf(stderr, "Out of memory while creating dictionary\n");
Packit 423ecb
	exit(1);
Packit 423ecb
    }
Packit 423ecb
    memset(test1, 0, sizeof(test1));
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * Fill in NB_STRINGS_MIN, at this point the dictionary should not grow
Packit 423ecb
     * and we allocate all those doing the fast key computations
Packit 423ecb
     */
Packit 423ecb
    for (i = 0;i < NB_STRINGS_MIN;i++) {
Packit 423ecb
        test1[i] = xmlDictLookup(dict, strings1[i], -1);
Packit 423ecb
	if (test1[i] == NULL) {
Packit 423ecb
	    fprintf(stderr, "Failed lookup for '%s'\n", strings1[i]);
Packit 423ecb
	    ret = 1;
Packit 423ecb
	    nbErrors++;
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
    j = NB_STRINGS_MAX - NB_STRINGS_NS;
Packit 423ecb
    /* ":foo" like strings1 */
Packit 423ecb
    for (i = 0;i < NB_STRINGS_MIN;i++, j++) {
Packit 423ecb
        test1[j] = xmlDictLookup(dict, strings1[j], xmlStrlen(strings1[j]));
Packit 423ecb
	if (test1[j] == NULL) {
Packit 423ecb
	    fprintf(stderr, "Failed lookup for '%s'\n", strings1[j]);
Packit 423ecb
	    ret = 1;
Packit 423ecb
	    nbErrors++;
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
    /* "a:foo" like strings1 */
Packit 423ecb
    j = NB_STRINGS_MAX - NB_STRINGS_MIN;
Packit 423ecb
    for (i = 0;i < NB_STRINGS_MIN;i++, j++) {
Packit 423ecb
        test1[j] = xmlDictLookup(dict, strings1[j], xmlStrlen(strings1[j]));
Packit 423ecb
	if (test1[j] == NULL) {
Packit 423ecb
	    fprintf(stderr, "Failed lookup for '%s'\n", strings1[j]);
Packit 423ecb
	    ret = 1;
Packit 423ecb
	    nbErrors++;
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * At this point allocate all the strings
Packit 423ecb
     * the dictionary will grow in the process, reallocate more string tables
Packit 423ecb
     * and switch to the better key generator
Packit 423ecb
     */
Packit 423ecb
    for (i = 0;i < NB_STRINGS_MAX;i++) {
Packit 423ecb
        if (test1[i] != NULL)
Packit 423ecb
	    continue;
Packit 423ecb
	test1[i] = xmlDictLookup(dict, strings1[i], -1);
Packit 423ecb
	if (test1[i] == NULL) {
Packit 423ecb
	    fprintf(stderr, "Failed lookup for '%s'\n", strings1[i]);
Packit 423ecb
	    ret = 1;
Packit 423ecb
	    nbErrors++;
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * Now we can start to test things, first that all strings1 belongs to
Packit 423ecb
     * the dict
Packit 423ecb
     */
Packit 423ecb
    for (i = 0;i < NB_STRINGS_MAX;i++) {
Packit 423ecb
        if (!xmlDictOwns(dict, test1[i])) {
Packit 423ecb
	    fprintf(stderr, "Failed ownership failure for '%s'\n",
Packit 423ecb
	            strings1[i]);
Packit 423ecb
	    ret = 1;
Packit 423ecb
	    nbErrors++;
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * Then that another lookup to the string will return the same
Packit 423ecb
     */
Packit 423ecb
    for (i = 0;i < NB_STRINGS_MAX;i++) {
Packit 423ecb
        if (xmlDictLookup(dict, strings1[i], -1) != test1[i]) {
Packit 423ecb
	    fprintf(stderr, "Failed re-lookup check for %d, '%s'\n",
Packit 423ecb
	            i, strings1[i]);
Packit 423ecb
	    ret = 1;
Packit 423ecb
	    nbErrors++;
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * More complex, check the QName lookups
Packit 423ecb
     */
Packit 423ecb
    for (i = NB_STRINGS_MAX - NB_STRINGS_NS;i < NB_STRINGS_MAX;i++) {
Packit 423ecb
        cur = strings1[i];
Packit 423ecb
	pref = &prefix[0];
Packit 423ecb
	while (*cur != ':') *pref++ = *cur++;
Packit 423ecb
	cur++;
Packit 423ecb
	*pref = 0;
Packit 423ecb
	tmp = xmlDictQLookup(dict, &prefix[0], cur);
Packit 423ecb
	if (tmp != test1[i]) {
Packit 423ecb
	    fprintf(stderr, "Failed lookup check for '%s':'%s'\n",
Packit 423ecb
	            &prefix[0], cur);
Packit 423ecb
            ret = 1;
Packit 423ecb
	    nbErrors++;
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
Packit 423ecb
    run_test2(dict);
Packit 423ecb
Packit 423ecb
    xmlDictFree(dict);
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
int main(void)
Packit 423ecb
{
Packit 423ecb
    int ret;
Packit 423ecb
Packit 423ecb
    LIBXML_TEST_VERSION
Packit 423ecb
    fill_strings();
Packit 423ecb
#ifdef WITH_PRINT
Packit 423ecb
    print_strings();
Packit 423ecb
#endif
Packit 423ecb
    ret = run_test1();
Packit 423ecb
    if (ret == 0) {
Packit 423ecb
        printf("dictionary tests succeeded %d strings\n", 2 * NB_STRINGS_MAX);
Packit 423ecb
    } else {
Packit 423ecb
        printf("dictionary tests failed with %d errors\n", nbErrors);
Packit 423ecb
    }
Packit 423ecb
    clean_strings();
Packit 423ecb
    xmlCleanupParser();
Packit 423ecb
    xmlMemoryDump();
Packit 423ecb
    return(ret);
Packit 423ecb
}