blob: 4e8581f85c3e7fef8488de1089140f3ae6db35d5 [file] [log] [blame]
Daniel Veillardd68f8912008-08-08 10:09:19 +00001#include <string.h>
2#include <libxml/parser.h>
3#include <libxml/dict.h>
4
5/* #define WITH_PRINT */
6
Daniel Veillardd330f182008-08-08 12:03:22 +00007static const char *seeds1[] = {
Daniel Veillardd68f8912008-08-08 10:09:19 +00008 "a", "b", "c",
9 "d", "e", "f",
10 "g", "h", "i",
11 "j", "k", "l",
12
13 NULL
14};
15
Daniel Veillardd330f182008-08-08 12:03:22 +000016static const char *seeds2[] = {
17 "m", "n", "o",
18 "p", "q", "r",
19 "s", "t", "u",
20 "v", "w", "x",
21
22 NULL
23};
24
Daniel Veillardd68f8912008-08-08 10:09:19 +000025#define NB_STRINGS_NS 100
26#define NB_STRINGS_MAX 10000
27#define NB_STRINGS_MIN 10
28
Daniel Veillardd330f182008-08-08 12:03:22 +000029static xmlChar *strings1[NB_STRINGS_MAX];
30static xmlChar *strings2[NB_STRINGS_MAX];
Daniel Veillardd68f8912008-08-08 10:09:19 +000031static const xmlChar *test1[NB_STRINGS_MAX];
Daniel Veillardd330f182008-08-08 12:03:22 +000032static const xmlChar *test2[NB_STRINGS_MAX];
33static int nbErrors = 0;
Daniel Veillardd68f8912008-08-08 10:09:19 +000034
35static 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 */
Daniel Veillardd330f182008-08-08 12:03:22 +000043 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");
Daniel Veillardd68f8912008-08-08 10:09:19 +000047 exit(1);
48 }
49 }
50 for (j = 0, k = 0;i < NB_STRINGS_MAX - NB_STRINGS_NS;i++,j++) {
Daniel Veillardd330f182008-08-08 12:03:22 +000051 strings1[i] = xmlStrncatNew(strings1[j], strings1[k], -1);
52 if (strings1[i] == NULL) {
53 fprintf(stderr, "Out of memory while generating strings1\n");
Daniel Veillardd68f8912008-08-08 10:09:19 +000054 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) {
Daniel Veillardd330f182008-08-08 12:03:22 +000062 strings1[i] = xmlStrncatNew(strings1[j], (const xmlChar *) ":", -1);
63 if (strings1[i] == NULL) {
64 fprintf(stderr, "Out of memory while generating strings1\n");
Daniel Veillardd68f8912008-08-08 10:09:19 +000065 exit(1);
66 }
67 }
68 for (j = NB_STRINGS_MAX - NB_STRINGS_NS, k = 0;
69 i < NB_STRINGS_MAX;i++,j++) {
Daniel Veillardd330f182008-08-08 12:03:22 +000070 strings1[i] = xmlStrncatNew(strings1[j], strings1[k], -1);
71 if (strings1[i] == NULL) {
72 fprintf(stderr, "Out of memory while generating strings1\n");
Daniel Veillardd68f8912008-08-08 10:09:19 +000073 exit(1);
74 }
75 k += 3;
76 if (k >= 50) k = 0;
77 }
Daniel Veillardd330f182008-08-08 12:03:22 +000078
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
Daniel Veillardd68f8912008-08-08 10:09:19 +0000118}
119
120#ifdef WITH_PRINT
121static void print_strings(void) {
122 int i;
123
124 for (i = 0; i < NB_STRINGS_MAX;i++) {
Daniel Veillardd330f182008-08-08 12:03:22 +0000125 printf("%s\n", strings1[i]);
126 }
127 for (i = 0; i < NB_STRINGS_MAX;i++) {
128 printf("%s\n", strings2[i]);
Daniel Veillardd68f8912008-08-08 10:09:19 +0000129 }
130}
131#endif
132
133static void clean_strings(void) {
134 int i;
135
136 for (i = 0; i < NB_STRINGS_MAX; i++) {
Daniel Veillardd330f182008-08-08 12:03:22 +0000137 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]);
Daniel Veillardd68f8912008-08-08 10:09:19 +0000143 }
144}
145
Daniel Veillardd330f182008-08-08 12:03:22 +0000146/*
147 * This tests the sub-dictionary support
148 */
149static 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 */
Daniel Veillardd68f8912008-08-08 10:09:19 +0000312static int run_test1(void) {
313 int i, j;
314 xmlDictPtr dict;
315 int ret = 0;
316 xmlChar prefix[40];
Daniel Veillardd330f182008-08-08 12:03:22 +0000317 xmlChar *cur, *pref;
318 const xmlChar *tmp;
Daniel Veillardd68f8912008-08-08 10:09:19 +0000319
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++) {
Daniel Veillardd330f182008-08-08 12:03:22 +0000332 test1[i] = xmlDictLookup(dict, strings1[i], -1);
Daniel Veillardd68f8912008-08-08 10:09:19 +0000333 if (test1[i] == NULL) {
Daniel Veillardd330f182008-08-08 12:03:22 +0000334 fprintf(stderr, "Failed lookup for '%s'\n", strings1[i]);
Daniel Veillardd68f8912008-08-08 10:09:19 +0000335 ret = 1;
Daniel Veillardd330f182008-08-08 12:03:22 +0000336 nbErrors++;
Daniel Veillardd68f8912008-08-08 10:09:19 +0000337 }
338 }
339 j = NB_STRINGS_MAX - NB_STRINGS_NS;
Daniel Veillardd330f182008-08-08 12:03:22 +0000340 /* ":foo" like strings1 */
Daniel Veillardd68f8912008-08-08 10:09:19 +0000341 for (i = 0;i < NB_STRINGS_MIN;i++, j++) {
Daniel Veillardd330f182008-08-08 12:03:22 +0000342 test1[j] = xmlDictLookup(dict, strings1[j], xmlStrlen(strings1[j]));
Daniel Veillardd68f8912008-08-08 10:09:19 +0000343 if (test1[j] == NULL) {
Daniel Veillardd330f182008-08-08 12:03:22 +0000344 fprintf(stderr, "Failed lookup for '%s'\n", strings1[j]);
Daniel Veillardd68f8912008-08-08 10:09:19 +0000345 ret = 1;
Daniel Veillardd330f182008-08-08 12:03:22 +0000346 nbErrors++;
Daniel Veillardd68f8912008-08-08 10:09:19 +0000347 }
348 }
Daniel Veillardd330f182008-08-08 12:03:22 +0000349 /* "a:foo" like strings1 */
Daniel Veillardd68f8912008-08-08 10:09:19 +0000350 j = NB_STRINGS_MAX - NB_STRINGS_MIN;
351 for (i = 0;i < NB_STRINGS_MIN;i++, j++) {
Daniel Veillardd330f182008-08-08 12:03:22 +0000352 test1[j] = xmlDictLookup(dict, strings1[j], xmlStrlen(strings1[j]));
Daniel Veillardd68f8912008-08-08 10:09:19 +0000353 if (test1[j] == NULL) {
Daniel Veillardd330f182008-08-08 12:03:22 +0000354 fprintf(stderr, "Failed lookup for '%s'\n", strings1[j]);
Daniel Veillardd68f8912008-08-08 10:09:19 +0000355 ret = 1;
Daniel Veillardd330f182008-08-08 12:03:22 +0000356 nbErrors++;
Daniel Veillardd68f8912008-08-08 10:09:19 +0000357 }
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;
Daniel Veillardd330f182008-08-08 12:03:22 +0000368 test1[i] = xmlDictLookup(dict, strings1[i], -1);
Daniel Veillardd68f8912008-08-08 10:09:19 +0000369 if (test1[i] == NULL) {
Daniel Veillardd330f182008-08-08 12:03:22 +0000370 fprintf(stderr, "Failed lookup for '%s'\n", strings1[i]);
Daniel Veillardd68f8912008-08-08 10:09:19 +0000371 ret = 1;
Daniel Veillardd330f182008-08-08 12:03:22 +0000372 nbErrors++;
Daniel Veillardd68f8912008-08-08 10:09:19 +0000373 }
374 }
375
376 /*
Daniel Veillardd330f182008-08-08 12:03:22 +0000377 * Now we can start to test things, first that all strings1 belongs to
Daniel Veillardd68f8912008-08-08 10:09:19 +0000378 * 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",
Daniel Veillardd330f182008-08-08 12:03:22 +0000383 strings1[i]);
Daniel Veillardd68f8912008-08-08 10:09:19 +0000384 ret = 1;
Daniel Veillardd330f182008-08-08 12:03:22 +0000385 nbErrors++;
Daniel Veillardd68f8912008-08-08 10:09:19 +0000386 }
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++) {
Daniel Veillardd330f182008-08-08 12:03:22 +0000393 if (xmlDictLookup(dict, strings1[i], -1) != test1[i]) {
Daniel Veillardd68f8912008-08-08 10:09:19 +0000394 fprintf(stderr, "Failed re-lookup check for %d, '%s'\n",
Daniel Veillardd330f182008-08-08 12:03:22 +0000395 i, strings1[i]);
Daniel Veillardd68f8912008-08-08 10:09:19 +0000396 ret = 1;
Daniel Veillardd330f182008-08-08 12:03:22 +0000397 nbErrors++;
Daniel Veillardd68f8912008-08-08 10:09:19 +0000398 }
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++) {
Daniel Veillardd330f182008-08-08 12:03:22 +0000405 cur = strings1[i];
Daniel Veillardd68f8912008-08-08 10:09:19 +0000406 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;
Daniel Veillardd330f182008-08-08 12:03:22 +0000415 nbErrors++;
Daniel Veillardd68f8912008-08-08 10:09:19 +0000416 }
417 }
418
Daniel Veillardd330f182008-08-08 12:03:22 +0000419 run_test2(dict);
420
Daniel Veillardd68f8912008-08-08 10:09:19 +0000421 xmlDictFree(dict);
Daniel Veillardd330f182008-08-08 12:03:22 +0000422 return(ret);
Daniel Veillardd68f8912008-08-08 10:09:19 +0000423}
424
425int 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();
Daniel Veillardd330f182008-08-08 12:03:22 +0000435 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 }
Daniel Veillardd68f8912008-08-08 10:09:19 +0000440 clean_strings();
441 xmlCleanupParser();
442 xmlMemoryDump();
443 return(ret);
444}