Git init
[external/libxml2.git] / testdict.c
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 (xmlDictQLookup(dict, &prefix[0], cur) != 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 (xmlDictQLookup(dict, &prefix[0], cur) != 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 }