1 /*************************************************************************************************
2  * Test cases of Cabin
3  *                                                      Copyright (C) 2000-2007 Mikio Hirabayashi
4  * This file is part of QDBM, Quick Database Manager.
5  * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU
6  * Lesser General Public License as published by the Free Software Foundation; either version
7  * 2.1 of the License or any later version.  QDBM is distributed in the hope that it will be
8  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
10  * details.
11  * You should have received a copy of the GNU Lesser General Public License along with QDBM; if
12  * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
13  * 02111-1307 USA.
14  *************************************************************************************************/
15 
16 
17 #include <cabin.h>
18 #include <stdio.h>
19 #include <cabin.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <stdarg.h>
23 #include <limits.h>
24 #include <time.h>
25 
26 #undef TRUE
27 #define TRUE           1                 /* boolean true */
28 #undef FALSE
29 #define FALSE          0                 /* boolean false */
30 
31 #define RECBUFSIZ      32                /* buffer for records */
32 #define TEXTBUFSIZ     262144            /* buffer for text */
33 
34 
35 /* for RISC OS */
36 #if defined(__riscos__) || defined(__riscos)
37 #include <unixlib/local.h>
38 int __riscosify_control = __RISCOSIFY_NO_PROCESS;
39 #endif
40 
41 
42 /* global variables */
43 const char *progname;                    /* program name */
44 
45 
46 /* function prototypes */
47 int main(int argc, char **argv);
48 void usage(void);
49 int runsort(int argc, char **argv);
50 int runstrstr(int argc, char **argv);
51 int runlist(int argc, char **argv);
52 int runmap(int argc, char **argv);
53 int runheap(int argc, char **argv);
54 int runwicked(int argc, char **argv);
55 int runmisc(int argc, char **argv);
56 int printfflush(const char *format, ...);
57 int strpcmp(const void *ap, const void *bp);
58 int intpcmp(const void *ap, const void *bp);
59 int myrand(void);
60 int dosort(int rnum, int disp);
61 int dostrstr(int rnum, int disp);
62 int dolist(int rnum, int disp);
63 int domap(int rnum, int bnum, int disp);
64 int doheap(int rnum, int max, int disp);
65 int dowicked(int rnum);
66 int domisc(void);
67 
68 
69 /* main routine */
main(int argc,char ** argv)70 int main(int argc, char **argv){
71   int rv;
72   cbstdiobin();
73   progname = argv[0];
74   if(argc < 2) usage();
75   rv = 0;
76   if(!strcmp(argv[1], "sort")){
77     rv = runsort(argc, argv);
78   } else if(!strcmp(argv[1], "strstr")){
79     rv = runstrstr(argc, argv);
80   } else if(!strcmp(argv[1], "list")){
81     rv = runlist(argc, argv);
82   } else if(!strcmp(argv[1], "map")){
83     rv = runmap(argc, argv);
84   } else if(!strcmp(argv[1], "heap")){
85     rv = runheap(argc, argv);
86   } else if(!strcmp(argv[1], "wicked")){
87     rv = runwicked(argc, argv);
88   } else if(!strcmp(argv[1], "misc")){
89     rv = runmisc(argc, argv);
90   } else {
91     usage();
92   }
93   return rv;
94 }
95 
96 
97 /* print the usage and exit */
usage(void)98 void usage(void){
99   fprintf(stderr, "%s: test cases for Cabin\n", progname);
100   fprintf(stderr, "\n");
101   fprintf(stderr, "usage:\n");
102   fprintf(stderr, "  %s sort [-d] rnum\n", progname);
103   fprintf(stderr, "  %s strstr [-d] rnum\n", progname);
104   fprintf(stderr, "  %s list [-d] rnum\n", progname);
105   fprintf(stderr, "  %s map [-d] rnum [bnum]\n", progname);
106   fprintf(stderr, "  %s heap [-d] rnum [top]\n", progname);
107   fprintf(stderr, "  %s wicked rnum\n", progname);
108   fprintf(stderr, "  %s misc\n", progname);
109   fprintf(stderr, "\n");
110   exit(1);
111 }
112 
113 
114 /* parse arguments of sort command */
runsort(int argc,char ** argv)115 int runsort(int argc, char **argv){
116   int i, rnum, disp, rv;
117   char *rstr;
118   rstr = NULL;
119   rnum = 0;
120   disp = FALSE;
121   for(i = 2; i < argc; i++){
122     if(argv[i][0] == '-'){
123       if(!strcmp(argv[i], "-d")){
124         disp = TRUE;
125       } else {
126         usage();
127       }
128     } else if(!rstr){
129       rstr = argv[i];
130     } else {
131       usage();
132     }
133   }
134   if(!rstr) usage();
135   rnum = atoi(rstr);
136   if(rnum < 1) usage();
137   rv = dosort(rnum, disp);
138   return rv;
139 }
140 
141 
142 /* parse arguments of strstr command */
runstrstr(int argc,char ** argv)143 int runstrstr(int argc, char **argv){
144   int i, rnum, disp, rv;
145   char *rstr;
146   rstr = NULL;
147   rnum = 0;
148   disp = FALSE;
149   for(i = 2; i < argc; i++){
150     if(argv[i][0] == '-'){
151       if(!strcmp(argv[i], "-d")){
152         disp = TRUE;
153       } else {
154         usage();
155       }
156     } else if(!rstr){
157       rstr = argv[i];
158     } else {
159       usage();
160     }
161   }
162   if(!rstr) usage();
163   rnum = atoi(rstr);
164   if(rnum < 1) usage();
165   rv = dostrstr(rnum, disp);
166   return rv;
167 }
168 
169 
170 /* parse arguments of list command */
runlist(int argc,char ** argv)171 int runlist(int argc, char **argv){
172   int i, rnum, disp, rv;
173   char *rstr;
174   rstr = NULL;
175   rnum = 0;
176   disp = FALSE;
177   for(i = 2; i < argc; i++){
178     if(argv[i][0] == '-'){
179       if(!strcmp(argv[i], "-d")){
180         disp = TRUE;
181       } else {
182         usage();
183       }
184     } else if(!rstr){
185       rstr = argv[i];
186     } else {
187       usage();
188     }
189   }
190   if(!rstr) usage();
191   rnum = atoi(rstr);
192   if(rnum < 1) usage();
193   rv = dolist(rnum, disp);
194   return rv;
195 }
196 
197 
198 /* parse arguments of map command */
runmap(int argc,char ** argv)199 int runmap(int argc, char **argv){
200   int i, rnum, bnum, disp, rv;
201   char *rstr, *bstr;
202   rstr = NULL;
203   bstr = NULL;
204   rnum = 0;
205   bnum = -1;
206   disp = FALSE;
207   for(i = 2; i < argc; i++){
208     if(argv[i][0] == '-'){
209       if(!strcmp(argv[i], "-d")){
210         disp = TRUE;
211       } else {
212         usage();
213       }
214     } else if(!rstr){
215       rstr = argv[i];
216     } else if(!bstr){
217       bstr = argv[i];
218     } else {
219       usage();
220     }
221   }
222   if(!rstr) usage();
223   rnum = atoi(rstr);
224   if(rnum < 1) usage();
225   if(bstr) bnum = atoi(bstr);
226   rv = domap(rnum, bnum, disp);
227   return rv;
228 }
229 
230 
231 /* parse arguments of heap command */
runheap(int argc,char ** argv)232 int runheap(int argc, char **argv){
233   int i, rnum, max, disp, rv;
234   char *rstr, *mstr;
235   rstr = NULL;
236   mstr = NULL;
237   rnum = 0;
238   max = -1;
239   disp = FALSE;
240   for(i = 2; i < argc; i++){
241     if(argv[i][0] == '-'){
242       if(!strcmp(argv[i], "-d")){
243         disp = TRUE;
244       } else {
245         usage();
246       }
247     } else if(!rstr){
248       rstr = argv[i];
249     } else if(!mstr){
250       mstr = argv[i];
251     } else {
252       usage();
253     }
254   }
255   if(!rstr) usage();
256   rnum = atoi(rstr);
257   if(rnum < 1) usage();
258   if(mstr) max = atoi(mstr);
259   if(max < 0) max = rnum;
260   rv = doheap(rnum, max, disp);
261   rv = 0;
262   return rv;
263 }
264 
265 
266 /* parse arguments of wicked command */
runwicked(int argc,char ** argv)267 int runwicked(int argc, char **argv){
268   int i, rnum, rv;
269   char *rstr;
270   rstr = NULL;
271   rnum = 0;
272   for(i = 2; i < argc; i++){
273     if(argv[i][0] == '-'){
274       usage();
275     } else if(!rstr){
276       rstr = argv[i];
277     } else {
278       usage();
279     }
280   }
281   if(!rstr) usage();
282   rnum = atoi(rstr);
283   if(rnum < 1) usage();
284   rv = dowicked(rnum);
285   return rv;
286 }
287 
288 
289 /* parse arguments of misc command */
runmisc(int argc,char ** argv)290 int runmisc(int argc, char **argv){
291   int rv;
292   rv = domisc();
293   return rv;
294 }
295 
296 
297 /* print formatted string and flush the buffer */
printfflush(const char * format,...)298 int printfflush(const char *format, ...){
299   va_list ap;
300   int rv;
301   va_start(ap, format);
302   rv = vprintf(format, ap);
303   if(fflush(stdout) == EOF) rv = -1;
304   va_end(ap);
305   return rv;
306 }
307 
308 
309 /* comparing function for strings */
strpcmp(const void * ap,const void * bp)310 int strpcmp(const void *ap, const void *bp){
311   return strcmp(*(char **)ap, *(char **)bp);
312 }
313 
314 
315 /* comparing function for integers */
intpcmp(const void * ap,const void * bp)316 int intpcmp(const void *ap, const void *bp){
317   return *(int *)ap - *(int *)bp;
318 }
319 
320 
321 /* pseudo random number generator */
myrand(void)322 int myrand(void){
323   static int cnt = 0;
324   if(cnt == 0) srand(time(NULL));
325   return (rand() * rand() + (rand() >> (sizeof(int) * 4)) + (cnt++)) & INT_MAX;
326 }
327 
328 
329 /* perform sort command */
dosort(int rnum,int disp)330 int dosort(int rnum, int disp){
331   char **ivector1, **ivector2, **ivector3, **ivector4, **ivector5;
332   char buf[RECBUFSIZ];
333   int i, len, err;
334   if(!disp) printfflush("<Sorting Test>\n  rnum=%d\n\n", rnum);
335   ivector1 = cbmalloc(rnum * sizeof(ivector1[0]));
336   ivector2 = cbmalloc(rnum * sizeof(ivector2[0]));
337   ivector3 = cbmalloc(rnum * sizeof(ivector3[0]));
338   ivector4 = cbmalloc(rnum * sizeof(ivector4[0]));
339   ivector5 = cbmalloc(rnum * sizeof(ivector5[0]));
340   err = FALSE;
341   for(i = 0; i < rnum; i++){
342     len = sprintf(buf, "%08d", myrand() % rnum + 1);
343     ivector1[i] = cbmemdup(buf, len);
344     ivector2[i] = cbmemdup(buf, len);
345     ivector3[i] = cbmemdup(buf, len);
346     ivector4[i] = cbmemdup(buf, len);
347     ivector5[i] = cbmemdup(buf, len);
348   }
349   if(!disp) printfflush("Sorting with insert sort ... ");
350   cbisort(ivector1, rnum, sizeof(ivector1[0]), strpcmp);
351   if(!disp) printfflush("ok\n");
352   if(!disp) printfflush("Sorting with shell sort ... ");
353   cbssort(ivector2, rnum, sizeof(ivector2[0]), strpcmp);
354   if(!disp) printfflush("ok\n");
355   if(!disp) printfflush("Sorting with heap sort ... ");
356   cbhsort(ivector3, rnum, sizeof(ivector3[0]), strpcmp);
357   if(!disp) printfflush("ok\n");
358   if(!disp) printfflush("Sorting with quick sort ... ");
359   cbqsort(ivector4, rnum, sizeof(ivector4[0]), strpcmp);
360   if(!disp) printfflush("ok\n");
361   for(i = 0; i < rnum; i++){
362     if(disp) printfflush("%s\t%s\t%s\t%s\t[%s]\n",
363                         ivector1[i], ivector2[i], ivector3[i], ivector4[i], ivector5[i]);
364     if(strcmp(ivector1[i], ivector2[i])) err = TRUE;
365     if(strcmp(ivector1[i], ivector3[i])) err = TRUE;
366     if(strcmp(ivector1[i], ivector4[i])) err = TRUE;
367     free(ivector1[i]);
368     free(ivector2[i]);
369     free(ivector3[i]);
370     free(ivector4[i]);
371     free(ivector5[i]);
372   }
373   free(ivector1);
374   free(ivector2);
375   free(ivector3);
376   free(ivector4);
377   free(ivector5);
378   if(err) fprintf(stderr, "%s: sorting failed\n", progname);
379   if(!disp && !err) printfflush("all ok\n\n");
380   return err ? 1 : 0;
381 }
382 
383 
384 /* perform strstr command */
dostrstr(int rnum,int disp)385 int dostrstr(int rnum, int disp){
386   char *text, buf[RECBUFSIZ], *std, *kmp, *bm;
387   int i, j, len, err;
388   text = cbmalloc(TEXTBUFSIZ);
389   for(i = 0; i < TEXTBUFSIZ - 1; i++){
390     text[i] = 'a' + myrand() % ('z' - 'a');
391   }
392   text[i] = '\0';
393   err = FALSE;
394   if(!disp) printfflush("Locating substrings ... ");
395   for(i = 0; i < rnum; i++){
396     len = myrand() % (RECBUFSIZ - 1);
397     for(j = 0; j < len; j++){
398       buf[j] = 'a' + myrand() % ('z' - 'a');
399     }
400     buf[j] = 0;
401     std = strstr(text, buf);
402     kmp = cbstrstrkmp(text, buf);
403     bm = cbstrstrbm(text, buf);
404     if(kmp != std || bm != std){
405       err = TRUE;
406       break;
407     }
408     if(disp && std) printf("%s\n", buf);
409   }
410   if(err) fprintf(stderr, "%s: string scanning failed\n", progname);
411   if(!disp && !err){
412     printfflush("ok\n");
413     printfflush("all ok\n\n");
414   }
415   free(text);
416   return err ? 1 : 0;
417 }
418 
419 
420 /* perform list command */
dolist(int rnum,int disp)421 int dolist(int rnum, int disp){
422   CBLIST *list;
423   const char *vbuf;
424   char buf[RECBUFSIZ], *tmp;
425   int i, err, len, vsiz;
426   if(!disp) printfflush("<List Writing Test>\n  rnum=%d\n\n", rnum);
427   list = cblistopen();
428   err = FALSE;
429   for(i = 1; i <= rnum; i++){
430     len = sprintf(buf, "%08d", i);
431     cblistpush(list, buf, len);
432     if(!disp && rnum > 250 && i % (rnum / 250) == 0){
433       putchar('.');
434       fflush(stdout);
435       if(i == rnum || i % (rnum / 10) == 0){
436         printfflush(" (%08d)\n", i);
437       }
438     }
439   }
440   if(disp){
441     for(i = 0; i < cblistnum(list); i++){
442       if((vbuf = cblistval(list, i, &vsiz)) != NULL){
443         printfflush("%s:%d\n", vbuf, vsiz);
444       } else {
445         fprintf(stderr, "%s: val error\n", progname);
446         err = TRUE;
447         break;
448       }
449     }
450     printfflush("\n");
451     while((tmp = cblistpop(list, &vsiz)) != NULL){
452       printfflush("%s:%d\n", tmp, vsiz);
453       free(tmp);
454     }
455   }
456   cblistclose(list);
457   if(!disp && !err) printfflush("ok\n\n");
458   return err ? 1 : 0;
459 }
460 
461 
462 /* perform list command */
domap(int rnum,int bnum,int disp)463 int domap(int rnum, int bnum, int disp){
464   CBMAP *map;
465   const char *kbuf, *vbuf;
466   char buf[RECBUFSIZ];
467   int i, err, len, ksiz, vsiz;
468   if(!disp) printfflush("<Map Writing Test>\n  rnum=%d  bnum=%d\n\n", rnum, bnum);
469   map = bnum > 0 ? cbmapopenex(bnum) : cbmapopen();
470   err = FALSE;
471   for(i = 1; i <= rnum; i++){
472     len = sprintf(buf, "%08d", i);
473     if(!cbmapput(map, buf, len, buf, len, FALSE)){
474       fprintf(stderr, "%s: put error\n", progname);
475       err = TRUE;
476       break;
477     }
478     if(!disp && rnum > 250 && i % (rnum / 250) == 0){
479       putchar('.');
480       fflush(stdout);
481       if(i == rnum || i % (rnum / 10) == 0){
482         printfflush(" (%08d)\n", i);
483       }
484     }
485   }
486   if(disp){
487     for(i = 1; i <= rnum; i++){
488       len = sprintf(buf, "%08d", i);
489       if((vbuf = cbmapget(map, buf, len, &vsiz)) != NULL){
490         printfflush("%s:%d\t%s:%d\n", buf, len, vbuf, vsiz);
491       } else {
492         fprintf(stderr, "%s: get error\n", progname);
493       }
494     }
495     printfflush("\n");
496     cbmapiterinit(map);
497     while((kbuf = cbmapiternext(map, &ksiz)) != NULL){
498       vbuf = cbmapiterval(kbuf, &vsiz);
499       printfflush("%s:%d\t%s:%d\n", kbuf, ksiz, vbuf, vsiz);
500     }
501   }
502   cbmapclose(map);
503   if(!disp && !err) printfflush("ok\n\n");
504   return err ? 1 : 0;
505 }
506 
507 
508 /* perform heap command */
doheap(int rnum,int max,int disp)509 int doheap(int rnum, int max, int disp){
510   CBHEAP *heap;
511   int *orig, *ary;
512   int i, err, num, anum;
513   if(!disp) printfflush("<Heap Writing Test>\n  rnum=%d  max=%d\n\n", rnum, max);
514   orig = disp ? cbmalloc(rnum * sizeof(int) + 1) : NULL;
515   heap = cbheapopen(sizeof(int), max, intpcmp);
516   err = FALSE;
517   for(i = 1; i <= rnum; i++){
518     num = myrand() % rnum + 1;
519     if(orig) orig[i-1] = num;
520     cbheapinsert(heap, &num);
521     if(!disp && rnum > 250 && i % (rnum / 250) == 0){
522       putchar('.');
523       fflush(stdout);
524       if(i == rnum || i % (rnum / 10) == 0){
525         printfflush(" (%08d)\n", i);
526       }
527     }
528   }
529   if(disp){
530     for(i = 0; i < cbheapnum(heap); i++){
531       printf("%d\n", *(int *)cbheapval(heap, i));
532     }
533     printf("\n");
534     qsort(orig, rnum, sizeof(int), intpcmp);
535     ary = (int *)cbheaptomalloc(heap, &anum);
536     if(anum != rnum && anum != max) err = TRUE;
537     for(i = 0; i < anum; i++){
538       printf("%d\t%d\n", ary[i], orig[i]);
539       if(ary[i] != orig[i]) err = TRUE;
540     }
541     free(ary);
542   } else {
543     cbheapclose(heap);
544   }
545   free(orig);
546   if(!disp && !err) printfflush("ok\n\n");
547   return err ? 1 : 0;
548 }
549 
550 
551 /* perform wicked command */
dowicked(int rnum)552 int dowicked(int rnum){
553   CBLIST *list;
554   CBMAP *map;
555   int i, len;
556   char buf[RECBUFSIZ], *tmp;
557   printfflush("<Wicked Writing Test>\n  rnum=%d\n\n", rnum);
558   list = cblistopen();
559   for(i = 1; i <= rnum; i++){
560     len = sprintf(buf, "%d", myrand() % rnum + 1);
561     switch(myrand() % 16){
562     case 0:
563       free(cblistpop(list, NULL));
564       putchar('O');
565       break;
566     case 1:
567       cblistunshift(list, buf, len);
568       putchar('U');
569       break;
570     case 2:
571       free(cblistshift(list, NULL));
572       putchar('S');
573       break;
574     case 3:
575       cblistinsert(list, myrand() % (cblistnum(list) + 1), buf, len);
576       putchar('I');
577       break;
578     case 4:
579       free(cblistremove(list, myrand() % (cblistnum(list) + 1), NULL));
580       putchar('R');
581       break;
582     case 5:
583       cblistover(list, myrand() % (cblistnum(list) + 1), buf, len);
584       putchar('V');
585       break;
586     case 6:
587       tmp = cbmemdup(buf, len);
588       cblistpushbuf(list, tmp, len);
589       putchar('B');
590       break;
591     default:
592       cblistpush(list, buf, len);
593       putchar('P');
594       break;
595     }
596     if(i % 50 == 0) printfflush(" (%08d)\n", i);
597   }
598   cblistclose(list);
599   map = cbmapopen();
600   for(i = 1; i <= rnum; i++){
601     len = sprintf(buf, "%d", myrand() % rnum + 1);
602     switch(myrand() % 16){
603     case 0:
604       cbmapput(map, buf, len, buf, len, FALSE);
605       putchar('I');
606       break;
607     case 1:
608       cbmapputcat(map, buf, len, buf, len);
609       putchar('C');
610       break;
611     case 2:
612       cbmapget(map, buf, len, NULL);
613       putchar('V');
614       break;
615     case 3:
616       cbmapout(map, buf, len);
617       putchar('D');
618       break;
619     case 4:
620       cbmapmove(map, buf, len, myrand() % 2);
621       putchar('M');
622       break;
623     default:
624       cbmapput(map, buf, len, buf, len, TRUE);
625       putchar('O');
626       break;
627     }
628     if(i % 50 == 0) printfflush(" (%08d)\n", i);
629   }
630   cbmapclose(map);
631   printfflush("ok\n\n");
632   return 0;
633 }
634 
635 
636 /* perform misc command */
domisc(void)637 int domisc(void){
638   CBDATUM *odatum, *ndatum;
639   CBLIST *olist, *nlist, *elems, *glist;
640   CBMAP *omap, *nmap, *pairs, *gmap;
641   int i, j, ssiz, osiz, tsiz, jl;
642   char kbuf[RECBUFSIZ], vbuf[RECBUFSIZ], *sbuf, spbuf[1024], *tmp, *orig, renc[64];
643   const char *op, *np;
644   time_t t;
645   printfflush("<Miscellaneous Test>\n\n");
646   printfflush("Checking memory allocation ... ");
647   tmp = cbmalloc(1024);
648   for(i = 1; i <= 65536; i *= 2){
649     tmp = cbrealloc(tmp, i);
650   }
651   cbfree(tmp);
652   printfflush("ok\n");
653   printfflush("Checking basic datum ... ");
654   odatum = cbdatumopen("x", -1);
655   for(i = 0; i < 1000; i++){
656     cbdatumcat(odatum, "x", 1);
657   }
658   cbdatumclose(odatum);
659   tmp = cbmalloc(3);
660   memcpy(tmp, "abc", 3);
661   odatum = cbdatumopenbuf(tmp, 3);
662   for(i = 0; i < 1000; i++){
663     cbdatumcat(odatum, ".", 1);
664   }
665   ndatum = cbdatumdup(odatum);
666   for(i = 0; i < 1000; i++){
667     cbdatumcat(ndatum, "*", 1);
668   }
669   for(i = 0; i < 1000; i++){
670     tmp = cbmalloc(3);
671     memcpy(tmp, "123", 3);
672     cbdatumsetbuf(ndatum, tmp, 3);
673   }
674   cbdatumprintf(ndatum, "[%s\t%08d\t%08o\t%08x\t%08.1f\t%@\t%?\t%:]",
675                 "mikio", 1978, 1978, 1978, 1978.0211, "<>&#!+-*/%", "<>&#!+-*/%", "<>&#!+-*/%");
676   cbdatumclose(ndatum);
677   cbdatumclose(odatum);
678   printfflush("ok\n");
679   printfflush("Checking serialization of list ... ");
680   olist = cblistopen();
681   for(i = 1; i <= 1000; i++){
682     sprintf(vbuf, "%d", i);
683     cblistpush(olist, vbuf, -1);
684   }
685   sbuf = cblistdump(olist, &ssiz);
686   nlist = cblistload(sbuf, ssiz);
687   free(sbuf);
688   for(i = 0; i < cblistnum(olist); i++){
689     op = cblistval(olist, i, NULL);
690     np = cblistval(nlist, i, NULL);
691     if(!op || !np || strcmp(op, np)){
692       cblistclose(nlist);
693       cblistclose(olist);
694       fprintf(stderr, "%s: validation failed\n", progname);
695       return 1;
696     }
697   }
698   cblistclose(nlist);
699   cblistclose(olist);
700   printfflush("ok\n");
701   printfflush("Checking serialization of map ... ");
702   omap = cbmapopen();
703   for(i = 1; i <= 1000; i++){
704     sprintf(kbuf, "%X", i);
705     sprintf(vbuf, "[%d]", i);
706     cbmapput(omap, kbuf, -1, vbuf, -1, TRUE);
707   }
708   sbuf = cbmapdump(omap, &ssiz);
709   nmap = cbmapload(sbuf, ssiz);
710   free(cbmaploadone(sbuf, ssiz, "1", 2, &tsiz));
711   free(cbmaploadone(sbuf, ssiz, "33", 2, &tsiz));
712   free(sbuf);
713   cbmapiterinit(omap);
714   while((op = cbmapiternext(omap, NULL)) != NULL){
715     if(!(np = cbmapget(nmap, op, -1, NULL))){
716       cbmapclose(nmap);
717       cbmapclose(omap);
718       fprintf(stderr, "%s: validation failed\n", progname);
719       return 1;
720     }
721   }
722   cbmapclose(nmap);
723   cbmapclose(omap);
724   printfflush("ok\n");
725   printfflush("Checking string utilities ... ");
726   sprintf(spbuf, "[%08d/%08o/%08u/%08x/%08X/%08.3e/%08.3E/%08.3f/%08.3g/%08.3G/%c/%s/%%]",
727           123456, 123456, 123456, 123456, 123456,
728           123456.789, 123456.789, 123456.789, 123456.789, 123456.789,
729           'A', "hoge");
730   tmp = cbsprintf("[%08d/%08o/%08u/%08x/%08X/%08.3e/%08.3E/%08.3f/%08.3g/%08.3G/%c/%s/%%]",
731                   123456, 123456, 123456, 123456, 123456,
732                   123456.789, 123456.789, 123456.789, 123456.789, 123456.789,
733                   'A', "hoge");
734   while(strcmp(spbuf, tmp)){
735     free(tmp);
736     fprintf(stderr, "%s: cbsprintf is invalid\n", progname);
737     return 1;
738   }
739   free(tmp);
740   pairs = cbmapopen();
741   cbmapput(pairs, "aa", -1, "AAA", -1, TRUE);
742   cbmapput(pairs, "bb", -1, "BBB", -1, TRUE);
743   cbmapput(pairs, "cc", -1, "CCC", -1, TRUE);
744   cbmapput(pairs, "ZZZ", -1, "z", -1, TRUE);
745   tmp = cbreplace("[aaaaabbbbbcccccdddddZZZZ]", pairs);
746   if(strcmp(tmp, "[AAAAAAaBBBBBBbCCCCCCcdddddzZ]")){
747     free(tmp);
748     cbmapclose(pairs);
749     fprintf(stderr, "%s: cbreplace is invalid\n", progname);
750     return 1;
751   }
752   free(tmp);
753   cbmapclose(pairs);
754   elems = cbsplit("aa bb,ccc-dd,", -1, " ,-");
755   if(cblistnum(elems) != 5 || strcmp(cblistval(elems, 0, NULL), "aa") ||
756      strcmp(cblistval(elems, 1, NULL), "bb") || strcmp(cblistval(elems, 2, NULL), "ccc") ||
757      strcmp(cblistval(elems, 3, NULL), "dd") || strcmp(cblistval(elems, 4, NULL), "")){
758     cblistclose(elems);
759     fprintf(stderr, "%s: cbsplit is invalid\n", progname);
760     return 1;
761   }
762   cblistclose(elems);
763   if(cbstricmp("abc", "ABC") || !cbstricmp("abc", "abcd")){
764     fprintf(stderr, "%s: cbstricmp is invalid\n", progname);
765     return 1;
766   }
767   if(!cbstrfwmatch("abcd", "abc") || cbstrfwmatch("abc", "abcd")){
768     fprintf(stderr, "%s: cbstrfwmatch is invalid\n", progname);
769     return 1;
770   }
771   if(!cbstrfwimatch("abcd", "ABC") || cbstrfwmatch("abc", "ABCD")){
772     fprintf(stderr, "%s: cbstrfwimatch is invalid\n", progname);
773     return 1;
774   }
775   if(!cbstrbwmatch("dcba", "cba") || cbstrbwmatch("cba", "dcba")){
776     fprintf(stderr, "%s: cbstrbwmatch is invalid\n", progname);
777     return 1;
778   }
779   if(!cbstrbwimatch("dcba", "CBA") || cbstrbwimatch("cba", "DCBA")){
780     fprintf(stderr, "%s: cbstrbwimatch is invalid\n", progname);
781     return 1;
782   }
783   tmp = cbmemdup(" \r\n[Quick   Database Manager]\r\n ", -1);
784   if(cbstrtoupper(tmp) != tmp || strcmp(tmp, " \r\n[QUICK   DATABASE MANAGER]\r\n ")){
785     free(tmp);
786     fprintf(stderr, "%s: cbstrtoupper is invalid\n", progname);
787     return 1;
788   }
789   if(cbstrtolower(tmp) != tmp || strcmp(tmp, " \r\n[quick   database manager]\r\n ")){
790     free(tmp);
791     fprintf(stderr, "%s: cbstrtolower is invalid\n", progname);
792     return 1;
793   }
794   if(cbstrtrim(tmp) != tmp || strcmp(tmp, "[quick   database manager]")){
795     free(tmp);
796     fprintf(stderr, "%s: cbstrtrim is invalid\n", progname);
797     return 1;
798   }
799   if(cbstrsqzspc(tmp) != tmp || strcmp(tmp, "[quick database manager]")){
800     free(tmp);
801     fprintf(stderr, "%s: cbstrsqzspc is invalid\n", progname);
802     return 1;
803   }
804   cbstrcututf(tmp, 5);
805   if(cbstrcountutf(tmp) != 5){
806     free(tmp);
807     fprintf(stderr, "%s: cbstrcututf or cbstrcountutf is invalid\n", progname);
808     return 1;
809   }
810   free(tmp);
811   printfflush("ok\n");
812   printfflush("Checking encoding utilities ... ");
813   strcpy(spbuf, "My name is \xca\xbf\xce\xd3\xb4\xb4\xcd\xba.\n\n<Love & Peace!>\n");
814   tmp = cbbaseencode(spbuf, -1);
815   orig = cbbasedecode(tmp, &osiz);
816   if(osiz != strlen(spbuf) || strcmp(orig, spbuf)){
817     free(orig);
818     free(tmp);
819     fprintf(stderr, "%s: Base64 encoding is invalid\n", progname);
820     return 1;
821   }
822   free(orig);
823   free(tmp);
824   strcpy(spbuf, "My name is \xca\xbf\xce\xd3\xb4\xb4\xcd\xba.\n\n<Love & Peace!>\n");
825   tmp = cbquoteencode(spbuf, -1);
826   orig = cbquotedecode(tmp, &osiz);
827   if(osiz != strlen(spbuf) || strcmp(orig, spbuf)){
828     free(orig);
829     free(tmp);
830     fprintf(stderr, "%s: quoted-printable encoding is invalid\n", progname);
831     return 1;
832   }
833   free(orig);
834   free(tmp);
835   strcpy(spbuf, "My name is \xca\xbf\xce\xd3\xb4\xb4\xcd\xba.\n\n<Love & Peace!>\n");
836   tmp = cbmimeencode(spbuf, "ISO-8859-1", TRUE);
837   orig = cbmimedecode(tmp, renc);
838   if(osiz != strlen(spbuf) || strcmp(orig, spbuf) || strcmp(renc, "ISO-8859-1")){
839     free(orig);
840     free(tmp);
841     fprintf(stderr, "%s: MIME encoding is invalid\n", progname);
842     return 1;
843   }
844   free(orig);
845   free(tmp);
846   strcpy(spbuf, "\"He says...\r\n\"\"What PROGRAM are they watching?\"\"\"");
847   tmp = cbcsvunescape(spbuf);
848   orig = cbcsvescape(tmp);
849   if(strcmp(orig, spbuf)){
850     free(orig);
851     free(tmp);
852     fprintf(stderr, "%s: CSV escaping is invalid\n", progname);
853     return 1;
854   }
855   free(orig);
856   free(tmp);
857   strcpy(spbuf, "&lt;Nuts&amp;Milk&gt; is &quot;very&quot; surfin&apos;!");
858   tmp = cbxmlunescape(spbuf);
859   orig = cbxmlescape(tmp);
860   if(strcmp(orig, spbuf)){
861     free(orig);
862     free(tmp);
863     fprintf(stderr, "%s: XML escaping is invalid\n", progname);
864     return 1;
865   }
866   free(orig);
867   free(tmp);
868   printfflush("ok\n");
869   printfflush("Checking date utilities ... ");
870   for(i = 0; i < 200; i++){
871     jl = (myrand() % 23) * 1800;
872     if(myrand() % 2 == 0) jl *= -1;
873     t = myrand() % (INT_MAX - 3600 * 24 * 365 * 6) + 3600 * 24 * 365 * 5;
874     tmp = cbdatestrwww(t, jl);
875     t = cbstrmktime(tmp);
876     orig = cbdatestrwww(t, jl);
877     if(strcmp(orig, tmp)){
878       free(orig);
879       free(tmp);
880       fprintf(stderr, "%s: W3CDTF formatter is invalid\n", progname);
881       return 1;
882     }
883     free(orig);
884     free(tmp);
885     tmp = cbdatestrhttp(t, jl);
886     t = cbstrmktime(tmp);
887     orig = cbdatestrhttp(t, jl);
888     if(strcmp(orig, tmp)){
889       free(orig);
890       free(tmp);
891       fprintf(stderr, "%s: RFC 822 date formatter is invalid\n", progname);
892       return 1;
893     }
894     free(orig);
895     free(tmp);
896   }
897   printfflush("ok\n");
898   printfflush("Checking the global garbage collector ... ");
899   for(i = 0; i < 512; i++){
900     glist = cblistopen();
901     cbglobalgc(glist, (void (*)(void *))cblistclose);
902     for(j = 0; j < 10; j++){
903       sprintf(kbuf, "%08d", j);
904       cblistpush(glist, kbuf, -1);
905     }
906     gmap = cbmapopen();
907     cbglobalgc(gmap, (void (*)(void *))cbmapclose);
908     for(j = 0; j < 10; j++){
909       sprintf(kbuf, "%08d", j);
910       cbmapput(gmap, kbuf, -1, kbuf, -1, TRUE);
911     }
912     if(myrand() % 64 == 0){
913       cbvmemavail(100);
914       cbggcsweep();
915     }
916   }
917   printfflush("ok\n");
918   printfflush("all ok\n\n");
919   return 0;
920 }
921 
922 
923 
924 /* END OF FILE */
925