Home | History | Annotate | Download | only in libxml2
      1 #include <string.h>
      2 #include <libxml/parser.h>
      3 #include <libxml/dict.h>
      4 
      5 /* #define WITH_PRINT */
      6 
      7 static const char *seeds1[] = {
      8    "a", "b", "c",
      9    "d", "e", "f",
     10    "g", "h", "i",
     11    "j", "k", "l",
     12 
     13    NULL
     14 };
     15 
     16 static const char *seeds2[] = {
     17    "m", "n", "o",
     18    "p", "q", "r",
     19    "s", "t", "u",
     20    "v", "w", "x",
     21 
     22    NULL
     23 };
     24 
     25 #define NB_STRINGS_NS 100
     26 #define NB_STRINGS_MAX 10000
     27 #define NB_STRINGS_MIN 10
     28 
     29 static xmlChar *strings1[NB_STRINGS_MAX];
     30 static xmlChar *strings2[NB_STRINGS_MAX];
     31 static const xmlChar *test1[NB_STRINGS_MAX];
     32 static const xmlChar *test2[NB_STRINGS_MAX];
     33 static int nbErrors = 0;
     34 
     35 static void fill_strings(void) {
     36     int i, j, k;
     37 
     38     /*
     39      * That's a bit nasty but the output is fine and it doesn't take hours
     40      * there is a small but sufficient number of duplicates, and we have
     41      * ":xxx" and full QNames in the last NB_STRINGS_NS values
     42      */
     43     for (i = 0; seeds1[i] != NULL; i++) {
     44         strings1[i] = xmlStrdup((const xmlChar *) seeds1[i]);
     45 	if (strings1[i] == NULL) {
     46 	    fprintf(stderr, "Out of memory while generating strings1\n");
     47 	    exit(1);
     48 	}
     49     }
     50     for (j = 0, k = 0;i < NB_STRINGS_MAX - NB_STRINGS_NS;i++,j++) {
     51         strings1[i] = xmlStrncatNew(strings1[j], strings1[k], -1);
     52 	if (strings1[i] == NULL) {
     53 	    fprintf(stderr, "Out of memory while generating strings1\n");
     54 	    exit(1);
     55 	}
     56 	if (j >= 50) {
     57 	    j = 0;
     58 	    k++;
     59 	}
     60     }
     61     for (j = 0; (j < 50) && (i < NB_STRINGS_MAX); i++, j+=2) {
     62         strings1[i] = xmlStrncatNew(strings1[j], (const xmlChar *) ":", -1);
     63 	if (strings1[i] == NULL) {
     64 	    fprintf(stderr, "Out of memory while generating strings1\n");
     65 	    exit(1);
     66 	}
     67     }
     68     for (j = NB_STRINGS_MAX - NB_STRINGS_NS, k = 0;
     69          i < NB_STRINGS_MAX;i++,j++) {
     70         strings1[i] = xmlStrncatNew(strings1[j], strings1[k], -1);
     71 	if (strings1[i] == NULL) {
     72 	    fprintf(stderr, "Out of memory while generating strings1\n");
     73 	    exit(1);
     74 	}
     75 	k += 3;
     76 	if (k >= 50) k = 0;
     77     }
     78 
     79     /*
     80      * Now do the same with the second pool of strings
     81      */
     82     for (i = 0; seeds2[i] != NULL; i++) {
     83         strings2[i] = xmlStrdup((const xmlChar *) seeds2[i]);
     84 	if (strings2[i] == NULL) {
     85 	    fprintf(stderr, "Out of memory while generating strings2\n");
     86 	    exit(1);
     87 	}
     88     }
     89     for (j = 0, k = 0;i < NB_STRINGS_MAX - NB_STRINGS_NS;i++,j++) {
     90         strings2[i] = xmlStrncatNew(strings2[j], strings2[k], -1);
     91 	if (strings2[i] == NULL) {
     92 	    fprintf(stderr, "Out of memory while generating strings2\n");
     93 	    exit(1);
     94 	}
     95 	if (j >= 50) {
     96 	    j = 0;
     97 	    k++;
     98 	}
     99     }
    100     for (j = 0; (j < 50) && (i < NB_STRINGS_MAX); i++, j+=2) {
    101         strings2[i] = xmlStrncatNew(strings2[j], (const xmlChar *) ":", -1);
    102 	if (strings2[i] == NULL) {
    103 	    fprintf(stderr, "Out of memory while generating strings2\n");
    104 	    exit(1);
    105 	}
    106     }
    107     for (j = NB_STRINGS_MAX - NB_STRINGS_NS, k = 0;
    108          i < NB_STRINGS_MAX;i++,j++) {
    109         strings2[i] = xmlStrncatNew(strings2[j], strings2[k], -1);
    110 	if (strings2[i] == NULL) {
    111 	    fprintf(stderr, "Out of memory while generating strings2\n");
    112 	    exit(1);
    113 	}
    114 	k += 3;
    115 	if (k >= 50) k = 0;
    116     }
    117 
    118 }
    119 
    120 #ifdef WITH_PRINT
    121 static void print_strings(void) {
    122     int i;
    123 
    124     for (i = 0; i < NB_STRINGS_MAX;i++) {
    125         printf("%s\n", strings1[i]);
    126     }
    127     for (i = 0; i < NB_STRINGS_MAX;i++) {
    128         printf("%s\n", strings2[i]);
    129     }
    130 }
    131 #endif
    132 
    133 static void clean_strings(void) {
    134     int i;
    135 
    136     for (i = 0; i < NB_STRINGS_MAX; i++) {
    137         if (strings1[i] != NULL) /* really should not happen */
    138 	    xmlFree(strings1[i]);
    139     }
    140     for (i = 0; i < NB_STRINGS_MAX; i++) {
    141         if (strings2[i] != NULL) /* really should not happen */
    142 	    xmlFree(strings2[i]);
    143     }
    144 }
    145 
    146 /*
    147  * This tests the sub-dictionary support
    148  */
    149 static int run_test2(xmlDictPtr parent) {
    150     int i, j;
    151     xmlDictPtr dict;
    152     int ret = 0;
    153     xmlChar prefix[40];
    154     xmlChar *cur, *pref;
    155     const xmlChar *tmp;
    156 
    157     dict = xmlDictCreateSub(parent);
    158     if (dict == NULL) {
    159 	fprintf(stderr, "Out of memory while creating sub-dictionary\n");
    160 	exit(1);
    161     }
    162     memset(test2, 0, sizeof(test2));
    163 
    164     /*
    165      * Fill in NB_STRINGS_MIN, at this point the dictionary should not grow
    166      * and we allocate all those doing the fast key computations
    167      * All the strings are based on a different seeds subset so we know
    168      * they are allocated in the main dictionary, not coming from the parent
    169      */
    170     for (i = 0;i < NB_STRINGS_MIN;i++) {
    171         test2[i] = xmlDictLookup(dict, strings2[i], -1);
    172 	if (test2[i] == NULL) {
    173 	    fprintf(stderr, "Failed lookup for '%s'\n", strings2[i]);
    174 	    ret = 1;
    175 	    nbErrors++;
    176 	}
    177     }
    178     j = NB_STRINGS_MAX - NB_STRINGS_NS;
    179     /* ":foo" like strings2 */
    180     for (i = 0;i < NB_STRINGS_MIN;i++, j++) {
    181         test2[j] = xmlDictLookup(dict, strings2[j], xmlStrlen(strings2[j]));
    182 	if (test2[j] == NULL) {
    183 	    fprintf(stderr, "Failed lookup for '%s'\n", strings2[j]);
    184 	    ret = 1;
    185 	    nbErrors++;
    186 	}
    187     }
    188     /* "a:foo" like strings2 */
    189     j = NB_STRINGS_MAX - NB_STRINGS_MIN;
    190     for (i = 0;i < NB_STRINGS_MIN;i++, j++) {
    191         test2[j] = xmlDictLookup(dict, strings2[j], xmlStrlen(strings2[j]));
    192 	if (test2[j] == NULL) {
    193 	    fprintf(stderr, "Failed lookup for '%s'\n", strings2[j]);
    194 	    ret = 1;
    195 	    nbErrors++;
    196 	}
    197     }
    198 
    199     /*
    200      * At this point allocate all the strings
    201      * the dictionary will grow in the process, reallocate more string tables
    202      * and switch to the better key generator
    203      */
    204     for (i = 0;i < NB_STRINGS_MAX;i++) {
    205         if (test2[i] != NULL)
    206 	    continue;
    207 	test2[i] = xmlDictLookup(dict, strings2[i], -1);
    208 	if (test2[i] == NULL) {
    209 	    fprintf(stderr, "Failed lookup for '%s'\n", strings2[i]);
    210 	    ret = 1;
    211 	    nbErrors++;
    212 	}
    213     }
    214 
    215     /*
    216      * Now we can start to test things, first that all strings2 belongs to
    217      * the dict, and that none of them was actually allocated in the parent
    218      */
    219     for (i = 0;i < NB_STRINGS_MAX;i++) {
    220         if (!xmlDictOwns(dict, test2[i])) {
    221 	    fprintf(stderr, "Failed ownership failure for '%s'\n",
    222 	            strings2[i]);
    223 	    ret = 1;
    224 	    nbErrors++;
    225 	}
    226         if (xmlDictOwns(parent, test2[i])) {
    227 	    fprintf(stderr, "Failed parent ownership failure for '%s'\n",
    228 	            strings2[i]);
    229 	    ret = 1;
    230 	    nbErrors++;
    231 	}
    232     }
    233 
    234     /*
    235      * Also verify that all strings from the parent are seen from the subdict
    236      */
    237     for (i = 0;i < NB_STRINGS_MAX;i++) {
    238         if (!xmlDictOwns(dict, test1[i])) {
    239 	    fprintf(stderr, "Failed sub-ownership failure for '%s'\n",
    240 	            strings1[i]);
    241 	    ret = 1;
    242 	    nbErrors++;
    243 	}
    244     }
    245 
    246     /*
    247      * Then that another lookup to the string in sub will return the same
    248      */
    249     for (i = 0;i < NB_STRINGS_MAX;i++) {
    250         if (xmlDictLookup(dict, strings2[i], -1) != test2[i]) {
    251 	    fprintf(stderr, "Failed re-lookup check for %d, '%s'\n",
    252 	            i, strings2[i]);
    253 	    ret = 1;
    254 	    nbErrors++;
    255 	}
    256     }
    257     /*
    258      * But also that any lookup for a string in the parent will be provided
    259      * as in the parent
    260      */
    261     for (i = 0;i < NB_STRINGS_MAX;i++) {
    262         if (xmlDictLookup(dict, strings1[i], -1) != test1[i]) {
    263 	    fprintf(stderr, "Failed parent string lookup check for %d, '%s'\n",
    264 	            i, strings1[i]);
    265 	    ret = 1;
    266 	    nbErrors++;
    267 	}
    268     }
    269 
    270     /*
    271      * check the QName lookups
    272      */
    273     for (i = NB_STRINGS_MAX - NB_STRINGS_NS;i < NB_STRINGS_MAX;i++) {
    274         cur = strings2[i];
    275 	pref = &prefix[0];
    276 	while (*cur != ':') *pref++ = *cur++;
    277 	cur++;
    278 	*pref = 0;
    279 	tmp = xmlDictQLookup(dict, &prefix[0], cur);
    280 	if (tmp != test2[i]) {
    281 	    fprintf(stderr, "Failed lookup check for '%s':'%s'\n",
    282 	            &prefix[0], cur);
    283             ret = 1;
    284 	    nbErrors++;
    285 	}
    286     }
    287     /*
    288      * check the QName lookups for strings from the parent
    289      */
    290     for (i = NB_STRINGS_MAX - NB_STRINGS_NS;i < NB_STRINGS_MAX;i++) {
    291         cur = strings1[i];
    292 	pref = &prefix[0];
    293 	while (*cur != ':') *pref++ = *cur++;
    294 	cur++;
    295 	*pref = 0;
    296 	tmp = xmlDictQLookup(dict, &prefix[0], cur);
    297 	if (xmlDictQLookup(dict, &prefix[0], cur) != test1[i]) {
    298 	    fprintf(stderr, "Failed parent lookup check for '%s':'%s'\n",
    299 	            &prefix[0], cur);
    300             ret = 1;
    301 	    nbErrors++;
    302 	}
    303     }
    304 
    305     xmlDictFree(dict);
    306     return(ret);
    307 }
    308 
    309 /*
    310  * Test a single dictionary
    311  */
    312 static int run_test1(void) {
    313     int i, j;
    314     xmlDictPtr dict;
    315     int ret = 0;
    316     xmlChar prefix[40];
    317     xmlChar *cur, *pref;
    318     const xmlChar *tmp;
    319 
    320     dict = xmlDictCreate();
    321     if (dict == NULL) {
    322 	fprintf(stderr, "Out of memory while creating dictionary\n");
    323 	exit(1);
    324     }
    325     memset(test1, 0, sizeof(test1));
    326 
    327     /*
    328      * Fill in NB_STRINGS_MIN, at this point the dictionary should not grow
    329      * and we allocate all those doing the fast key computations
    330      */
    331     for (i = 0;i < NB_STRINGS_MIN;i++) {
    332         test1[i] = xmlDictLookup(dict, strings1[i], -1);
    333 	if (test1[i] == NULL) {
    334 	    fprintf(stderr, "Failed lookup for '%s'\n", strings1[i]);
    335 	    ret = 1;
    336 	    nbErrors++;
    337 	}
    338     }
    339     j = NB_STRINGS_MAX - NB_STRINGS_NS;
    340     /* ":foo" like strings1 */
    341     for (i = 0;i < NB_STRINGS_MIN;i++, j++) {
    342         test1[j] = xmlDictLookup(dict, strings1[j], xmlStrlen(strings1[j]));
    343 	if (test1[j] == NULL) {
    344 	    fprintf(stderr, "Failed lookup for '%s'\n", strings1[j]);
    345 	    ret = 1;
    346 	    nbErrors++;
    347 	}
    348     }
    349     /* "a:foo" like strings1 */
    350     j = NB_STRINGS_MAX - NB_STRINGS_MIN;
    351     for (i = 0;i < NB_STRINGS_MIN;i++, j++) {
    352         test1[j] = xmlDictLookup(dict, strings1[j], xmlStrlen(strings1[j]));
    353 	if (test1[j] == NULL) {
    354 	    fprintf(stderr, "Failed lookup for '%s'\n", strings1[j]);
    355 	    ret = 1;
    356 	    nbErrors++;
    357 	}
    358     }
    359 
    360     /*
    361      * At this point allocate all the strings
    362      * the dictionary will grow in the process, reallocate more string tables
    363      * and switch to the better key generator
    364      */
    365     for (i = 0;i < NB_STRINGS_MAX;i++) {
    366         if (test1[i] != NULL)
    367 	    continue;
    368 	test1[i] = xmlDictLookup(dict, strings1[i], -1);
    369 	if (test1[i] == NULL) {
    370 	    fprintf(stderr, "Failed lookup for '%s'\n", strings1[i]);
    371 	    ret = 1;
    372 	    nbErrors++;
    373 	}
    374     }
    375 
    376     /*
    377      * Now we can start to test things, first that all strings1 belongs to
    378      * the dict
    379      */
    380     for (i = 0;i < NB_STRINGS_MAX;i++) {
    381         if (!xmlDictOwns(dict, test1[i])) {
    382 	    fprintf(stderr, "Failed ownership failure for '%s'\n",
    383 	            strings1[i]);
    384 	    ret = 1;
    385 	    nbErrors++;
    386 	}
    387     }
    388 
    389     /*
    390      * Then that another lookup to the string will return the same
    391      */
    392     for (i = 0;i < NB_STRINGS_MAX;i++) {
    393         if (xmlDictLookup(dict, strings1[i], -1) != test1[i]) {
    394 	    fprintf(stderr, "Failed re-lookup check for %d, '%s'\n",
    395 	            i, strings1[i]);
    396 	    ret = 1;
    397 	    nbErrors++;
    398 	}
    399     }
    400 
    401     /*
    402      * More complex, check the QName lookups
    403      */
    404     for (i = NB_STRINGS_MAX - NB_STRINGS_NS;i < NB_STRINGS_MAX;i++) {
    405         cur = strings1[i];
    406 	pref = &prefix[0];
    407 	while (*cur != ':') *pref++ = *cur++;
    408 	cur++;
    409 	*pref = 0;
    410 	tmp = xmlDictQLookup(dict, &prefix[0], cur);
    411 	if (tmp != test1[i]) {
    412 	    fprintf(stderr, "Failed lookup check for '%s':'%s'\n",
    413 	            &prefix[0], cur);
    414             ret = 1;
    415 	    nbErrors++;
    416 	}
    417     }
    418 
    419     run_test2(dict);
    420 
    421     xmlDictFree(dict);
    422     return(ret);
    423 }
    424 
    425 int main(void)
    426 {
    427     int ret;
    428 
    429     LIBXML_TEST_VERSION
    430     fill_strings();
    431 #ifdef WITH_PRINT
    432     print_strings();
    433 #endif
    434     ret = run_test1();
    435     if (ret == 0) {
    436         printf("dictionary tests succeeded %d strings\n", 2 * NB_STRINGS_MAX);
    437     } else {
    438         printf("dictionary tests failed with %d errors\n", nbErrors);
    439     }
    440     clean_strings();
    441     xmlCleanupParser();
    442     xmlMemoryDump();
    443     return(ret);
    444 }
    445