1 /*************************************************************************************************
2 * The test cases of the abstract database API
3 * Copyright (C) 2006-2008 Mikio Hirabayashi
4 * This file is part of Tokyo Cabinet.
5 * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
6 * the GNU Lesser General Public License as published by the Free Software Foundation; either
7 * version 2.1 of the License or any later version. Tokyo Cabinet is distributed in the hope
8 * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
10 * License for more details.
11 * You should have received a copy of the GNU Lesser General Public License along with Tokyo
12 * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
13 * Boston, MA 02111-1307 USA.
14 *************************************************************************************************/
21 #define RECBUFSIZ 32 // buffer for records
24 /* global variables */
25 const char *g_progname; // program name
28 /* function prototypes */
29 int main(int argc, char **argv);
30 static void usage(void);
31 static void iprintf(const char *format, ...);
32 static void eprint(TCADB *adb, const char *func);
33 static int myrand(int range);
34 static int runwrite(int argc, char **argv);
35 static int runread(int argc, char **argv);
36 static int runremove(int argc, char **argv);
37 static int runrcat(int argc, char **argv);
38 static int runmisc(int argc, char **argv);
39 static int runwicked(int argc, char **argv);
40 static int procwrite(const char *name, int rnum);
41 static int procread(const char *name);
42 static int procremove(const char *name);
43 static int procrcat(const char *name, int rnum);
44 static int procmisc(const char *name, int rnum);
45 static int procwicked(const char *name, int rnum);
49 int main(int argc, char **argv){
51 srand((unsigned int)(tctime() * 1000) % UINT_MAX);
54 if(!strcmp(argv[1], "write")){
55 rv = runwrite(argc, argv);
56 } else if(!strcmp(argv[1], "read")){
57 rv = runread(argc, argv);
58 } else if(!strcmp(argv[1], "remove")){
59 rv = runremove(argc, argv);
60 } else if(!strcmp(argv[1], "rcat")){
61 rv = runrcat(argc, argv);
62 } else if(!strcmp(argv[1], "misc")){
63 rv = runmisc(argc, argv);
64 } else if(!strcmp(argv[1], "wicked")){
65 rv = runwicked(argc, argv);
73 /* print the usage and exit */
74 static void usage(void){
75 fprintf(stderr, "%s: test cases of the abstract database API of Tokyo Cabinet\n", g_progname);
76 fprintf(stderr, "\n");
77 fprintf(stderr, "usage:\n");
78 fprintf(stderr, " %s write name rnum\n", g_progname);
79 fprintf(stderr, " %s read name\n", g_progname);
80 fprintf(stderr, " %s remove name\n", g_progname);
81 fprintf(stderr, " %s rcat name rnum\n", g_progname);
82 fprintf(stderr, " %s misc name rnum\n", g_progname);
83 fprintf(stderr, " %s wicked name rnum\n", g_progname);
84 fprintf(stderr, "\n");
89 /* print formatted information string and flush the buffer */
90 static void iprintf(const char *format, ...){
99 /* print error message of abstract database */
100 static void eprint(TCADB *adb, const char *func){
101 fprintf(stderr, "%s: %s: error\n", g_progname, func);
105 /* get a random number */
106 static int myrand(int range){
107 return (int)((double)range * rand() / (RAND_MAX + 1.0));
111 /* parse arguments of write command */
112 static int runwrite(int argc, char **argv){
115 for(int i = 2; i < argc; i++){
116 if(!name && argv[i][0] == '-'){
126 if(!name || !rstr) usage();
127 int rnum = atoi(rstr);
128 if(rnum < 1) usage();
129 int rv = procwrite(name, rnum);
134 /* parse arguments of read command */
135 static int runread(int argc, char **argv){
137 for(int i = 2; i < argc; i++){
138 if(!name && argv[i][0] == '-'){
147 int rv = procread(name);
152 /* parse arguments of remove command */
153 static int runremove(int argc, char **argv){
155 for(int i = 2; i < argc; i++){
156 if(!name && argv[i][0] == '-'){
165 int rv = procremove(name);
170 /* parse arguments of rcat command */
171 static int runrcat(int argc, char **argv){
174 for(int i = 2; i < argc; i++){
175 if(!name && argv[i][0] == '-'){
185 if(!name || !rstr) usage();
186 int rnum = atoi(rstr);
187 if(rnum < 1) usage();
188 int rv = procrcat(name, rnum);
193 /* parse arguments of misc command */
194 static int runmisc(int argc, char **argv){
197 for(int i = 2; i < argc; i++){
198 if(!name && argv[i][0] == '-'){
208 if(!name || !rstr) usage();
209 int rnum = atoi(rstr);
210 if(rnum < 1) usage();
211 int rv = procmisc(name, rnum);
216 /* parse arguments of wicked command */
217 static int runwicked(int argc, char **argv){
220 for(int i = 2; i < argc; i++){
221 if(!name && argv[i][0] == '-'){
231 if(!name || !rstr) usage();
232 int rnum = atoi(rstr);
233 if(rnum < 1) usage();
234 int rv = procwicked(name, rnum);
239 /* perform write command */
240 static int procwrite(const char *name, int rnum){
241 iprintf("<Writing Test>\n name=%s rnum=%d\n\n", name, rnum);
243 double stime = tctime();
244 TCADB *adb = tcadbnew();
245 if(!tcadbopen(adb, name)){
246 eprint(adb, "tcadbopen");
249 for(int i = 1; i <= rnum; i++){
251 int len = sprintf(buf, "%08d", i);
252 if(!tcadbput(adb, buf, len, buf, len)){
253 eprint(adb, "tcadbput");
257 if(rnum > 250 && i % (rnum / 250) == 0){
260 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
263 iprintf("record number: %llu\n", (unsigned long long)tcadbrnum(adb));
264 iprintf("size: %llu\n", (unsigned long long)tcadbsize(adb));
265 if(!tcadbclose(adb)){
266 eprint(adb, "tcadbclose");
270 iprintf("time: %.3f\n", tctime() - stime);
271 iprintf("%s\n\n", err ? "error" : "ok");
276 /* perform read command */
277 static int procread(const char *name){
278 iprintf("<Reading Test>\n name=%s\n\n", name);
280 double stime = tctime();
281 TCADB *adb = tcadbnew();
282 if(!tcadbopen(adb, name)){
283 eprint(adb, "tcadbopen");
286 int rnum = tcadbrnum(adb);
287 for(int i = 1; i <= rnum; i++){
288 char kbuf[RECBUFSIZ];
289 int ksiz = sprintf(kbuf, "%08d", i);
291 char *vbuf = tcadbget(adb, kbuf, ksiz, &vsiz);
293 eprint(adb, "tcadbget");
298 if(rnum > 250 && i % (rnum / 250) == 0){
301 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
304 iprintf("record number: %llu\n", (unsigned long long)tcadbrnum(adb));
305 iprintf("size: %llu\n", (unsigned long long)tcadbsize(adb));
306 if(!tcadbclose(adb)){
307 eprint(adb, "tcadbclose");
311 iprintf("time: %.3f\n", tctime() - stime);
312 iprintf("%s\n\n", err ? "error" : "ok");
317 /* perform remove command */
318 static int procremove(const char *name){
319 iprintf("<Removing Test>\n name=%s\n\n", name);
321 double stime = tctime();
322 TCADB *adb = tcadbnew();
323 if(!tcadbopen(adb, name)){
324 eprint(adb, "tcadbopen");
327 int rnum = tcadbrnum(adb);
328 for(int i = 1; i <= rnum; i++){
329 char kbuf[RECBUFSIZ];
330 int ksiz = sprintf(kbuf, "%08d", i);
331 if(!tcadbout(adb, kbuf, ksiz)){
332 eprint(adb, "tcadbout");
336 if(rnum > 250 && i % (rnum / 250) == 0){
339 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
342 iprintf("record number: %llu\n", (unsigned long long)tcadbrnum(adb));
343 iprintf("size: %llu\n", (unsigned long long)tcadbsize(adb));
344 if(!tcadbclose(adb)){
345 eprint(adb, "tcadbclose");
349 iprintf("time: %.3f\n", tctime() - stime);
350 iprintf("%s\n\n", err ? "error" : "ok");
355 /* perform rcat command */
356 static int procrcat(const char *name, int rnum){
357 iprintf("<Random Concatenating Test>\n name=%s rnum=%d\n\n", name, rnum);
358 int pnum = rnum / 5 + 1;
360 double stime = tctime();
361 TCADB *adb = tcadbnew();
362 if(!tcadbopen(adb, name)){
363 eprint(adb, "tcadbopen");
366 for(int i = 1; i <= rnum; i++){
367 char kbuf[RECBUFSIZ];
368 int ksiz = sprintf(kbuf, "%d", myrand(pnum));
369 if(!tcadbputcat(adb, kbuf, ksiz, kbuf, ksiz)){
370 eprint(adb, "tcadbputcat");
374 if(rnum > 250 && i % (rnum / 250) == 0){
377 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
380 iprintf("record number: %llu\n", (unsigned long long)tcadbrnum(adb));
381 iprintf("size: %llu\n", (unsigned long long)tcadbsize(adb));
382 if(!tcadbclose(adb)){
383 eprint(adb, "tcadbclose");
387 iprintf("time: %.3f\n", tctime() - stime);
388 iprintf("%s\n\n", err ? "error" : "ok");
393 /* perform misc command */
394 static int procmisc(const char *name, int rnum){
395 iprintf("<Random Concatenating Test>\n name=%s rnum=%d\n\n", name, rnum);
397 double stime = tctime();
398 TCADB *adb = tcadbnew();
399 if(!tcadbopen(adb, name)){
400 eprint(adb, "tcadbopen");
403 iprintf("writing:\n");
404 for(int i = 1; i <= rnum; i++){
406 int len = sprintf(buf, "%08d", i);
407 if(!tcadbputkeep(adb, buf, len, buf, len)){
408 eprint(adb, "tcadbputkeep");
412 if(rnum > 250 && i % (rnum / 250) == 0){
415 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
418 iprintf("reading:\n");
419 for(int i = 1; i <= rnum; i++){
420 char kbuf[RECBUFSIZ];
421 int ksiz = sprintf(kbuf, "%08d", i);
423 char *vbuf = tcadbget(adb, kbuf, ksiz, &vsiz);
425 eprint(adb, "tcadbget");
428 } else if(vsiz != ksiz || memcmp(vbuf, kbuf, vsiz)){
429 eprint(adb, "(validation)");
435 if(rnum > 250 && i % (rnum / 250) == 0){
438 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
441 if(tcadbrnum(adb) != rnum){
442 eprint(adb, "(validation)");
445 iprintf("random writing:\n");
446 for(int i = 1; i <= rnum; i++){
447 char kbuf[RECBUFSIZ];
448 int ksiz = sprintf(kbuf, "%d", myrand(rnum));
449 char vbuf[RECBUFSIZ];
450 int vsiz = myrand(RECBUFSIZ);
451 memset(vbuf, '*', vsiz);
452 if(!tcadbput(adb, kbuf, ksiz, vbuf, vsiz)){
453 eprint(adb, "tcadbput");
458 char *rbuf = tcadbget(adb, kbuf, ksiz, &rsiz);
460 eprint(adb, "tcadbget");
464 if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
465 eprint(adb, "(validation)");
470 if(rnum > 250 && i % (rnum / 250) == 0){
473 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
477 iprintf("word writing:\n");
478 const char *words[] = {
479 "a", "A", "bb", "BB", "ccc", "CCC", "dddd", "DDDD", "eeeee", "EEEEEE",
480 "mikio", "hirabayashi", "tokyo", "cabinet", "hyper", "estraier", "19780211", "birth day",
481 "one", "first", "two", "second", "three", "third", "four", "fourth", "five", "fifth",
482 "_[1]_", "uno", "_[2]_", "dos", "_[3]_", "tres", "_[4]_", "cuatro", "_[5]_", "cinco",
483 "[\xe5\xb9\xb3\xe6\x9e\x97\xe5\xb9\xb9\xe9\x9b\x84]", "[\xe9\xa6\xac\xe9\xb9\xbf]", NULL
485 for(int i = 0; words[i] != NULL; i += 2){
486 const char *kbuf = words[i];
487 int ksiz = strlen(kbuf);
488 const char *vbuf = words[i+1];
489 int vsiz = strlen(vbuf);
490 if(!tcadbputkeep(adb, kbuf, ksiz, vbuf, vsiz)){
491 eprint(adb, "tcadbputkeep");
495 if(rnum > 250) putchar('.');
497 if(rnum > 250) iprintf(" (%08d)\n", sizeof(words) / sizeof(*words));
498 iprintf("random erasing:\n");
499 for(int i = 1; i <= rnum; i++){
500 char kbuf[RECBUFSIZ];
501 int ksiz = sprintf(kbuf, "%d", myrand(rnum));
502 tcadbout(adb, kbuf, ksiz);
503 if(rnum > 250 && i % (rnum / 250) == 0){
506 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
509 iprintf("writing:\n");
510 for(int i = 1; i <= rnum; i++){
511 char kbuf[RECBUFSIZ];
512 int ksiz = sprintf(kbuf, "[%d]", i);
513 char vbuf[RECBUFSIZ];
514 int vsiz = i % RECBUFSIZ;
515 memset(vbuf, '*', vsiz);
516 if(!tcadbputkeep(adb, kbuf, ksiz, vbuf, vsiz)){
517 eprint(adb, "tcadbputkeep");
523 for(int j = 0; j < PATH_MAX; j++){
524 tbuf[j] = myrand(0x100);
526 if(!tcadbput(adb, kbuf, ksiz, tbuf, PATH_MAX)){
527 eprint(adb, "tcadbput");
532 if(rnum > 250 && i % (rnum / 250) == 0){
535 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
538 iprintf("erasing:\n");
539 for(int i = 1; i <= rnum; i++){
541 char kbuf[RECBUFSIZ];
542 int ksiz = sprintf(kbuf, "[%d]", i);
543 if(!tcadbout(adb, kbuf, ksiz)){
544 eprint(adb, "tcadbout");
548 tcadbout(adb, kbuf, ksiz);
550 if(rnum > 250 && i % (rnum / 250) == 0){
553 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
556 iprintf("iterator checking:\n");
557 if(!tcadbiterinit(adb)){
558 eprint(adb, "tcadbiterinit");
564 for(int i = 1; (kbuf = tcadbiternext(adb, &ksiz)) != NULL; i++, inum++){
566 char *vbuf = tcadbget(adb, kbuf, ksiz, &vsiz);
568 eprint(adb, "tcadbget");
575 if(rnum > 250 && i % (rnum / 250) == 0){
578 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
581 if(rnum > 250) iprintf(" (%08d)\n", inum);
582 if(inum != tcadbrnum(adb)){
583 eprint(adb, "(validation)");
586 if(*name != '*' && !tcadbsync(adb)){
587 eprint(adb, "tcadbsync");
590 if(!tcadbvanish(adb)){
591 eprint(adb, "tcadbsync");
594 iprintf("record number: %llu\n", (unsigned long long)tcadbrnum(adb));
595 iprintf("size: %llu\n", (unsigned long long)tcadbsize(adb));
596 if(!tcadbclose(adb)){
597 eprint(adb, "tcadbclose");
601 iprintf("time: %.3f\n", tctime() - stime);
602 iprintf("%s\n\n", err ? "error" : "ok");
607 /* perform wicked command */
608 static int procwicked(const char *name, int rnum){
609 iprintf("<Wicked Writing Test>\n name=%s rnum=%d\n\n", name, rnum);
611 double stime = tctime();
612 TCADB *adb = tcadbnew();
613 if(!tcadbopen(adb, name)){
614 eprint(adb, "tcadbopen");
617 TCMAP *map = tcmapnew2(rnum / 5);
618 for(int i = 1; i <= rnum && !err; i++){
619 char kbuf[RECBUFSIZ];
620 int ksiz = sprintf(kbuf, "%d", myrand(rnum));
621 char vbuf[RECBUFSIZ];
622 int vsiz = myrand(RECBUFSIZ);
623 memset(vbuf, '*', vsiz);
629 if(!tcadbput(adb, kbuf, ksiz, vbuf, vsiz)){
630 eprint(adb, "tcadbput");
633 tcmapput(map, kbuf, ksiz, vbuf, vsiz);
637 if(!tcadbput2(adb, kbuf, vbuf)){
638 eprint(adb, "tcadbput2");
641 tcmapput2(map, kbuf, vbuf);
645 tcadbputkeep(adb, kbuf, ksiz, vbuf, vsiz);
646 tcmapputkeep(map, kbuf, ksiz, vbuf, vsiz);
650 tcadbputkeep2(adb, kbuf, vbuf);
651 tcmapputkeep2(map, kbuf, vbuf);
655 if(!tcadbputcat(adb, kbuf, ksiz, vbuf, vsiz)){
656 eprint(adb, "tcadbputcat");
659 tcmapputcat(map, kbuf, ksiz, vbuf, vsiz);
663 if(!tcadbputcat2(adb, kbuf, vbuf)){
664 eprint(adb, "tcadbputcat2");
667 tcmapputcat2(map, kbuf, vbuf);
672 tcadbout(adb, kbuf, ksiz);
673 tcmapout(map, kbuf, ksiz);
679 tcadbout2(adb, kbuf);
680 tcmapout2(map, kbuf);
685 if((rbuf = tcadbget(adb, kbuf, ksiz, &vsiz)) != NULL) free(rbuf);
689 if((rbuf = tcadbget2(adb, kbuf)) != NULL) free(rbuf);
693 tcadbvsiz(adb, kbuf, ksiz);
697 tcadbvsiz2(adb, kbuf);
701 if(myrand(rnum / 50) == 0){
702 if(!tcadbiterinit(adb)){
703 eprint(adb, "tcadbiterinit");
707 for(int j = myrand(rnum) / 1000 + 1; j >= 0; j--){
709 char *ikbuf = tcadbiternext(adb, &iksiz);
710 if(ikbuf) free(ikbuf);
715 if(myrand(10000) == 0) srand((unsigned int)(tctime() * 1000) % UINT_MAX);
718 if(i % 50 == 0) iprintf(" (%08d)\n", i);
720 if(rnum % 50 > 0) iprintf(" (%08d)\n", rnum);
722 if(tcadbrnum(adb) != tcmaprnum(map)){
723 eprint(adb, "(validation)");
726 for(int i = 1; i <= rnum && !err; i++){
727 char kbuf[RECBUFSIZ];
728 int ksiz = sprintf(kbuf, "%d", i - 1);
730 const char *vbuf = tcmapget(map, kbuf, ksiz, &vsiz);
732 char *rbuf = tcadbget(adb, kbuf, ksiz, &rsiz);
736 eprint(adb, "tcadbget");
738 } else if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
739 eprint(adb, "(validation)");
745 eprint(adb, "(validation)");
750 if(i % 50 == 0) iprintf(" (%08d)\n", i);
752 if(rnum % 50 > 0) iprintf(" (%08d)\n", rnum);
756 for(int i = 1; (kbuf = tcmapiternext(map, &ksiz)) != NULL; i++){
759 const char *vbuf = tcmapiterval(kbuf, &vsiz);
761 char *rbuf = tcadbget(adb, kbuf, ksiz, &rsiz);
763 eprint(adb, "tcadbget");
765 } else if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
766 eprint(adb, "(validation)");
770 if(!tcadbout(adb, kbuf, ksiz)){
771 eprint(adb, "tcadbout");
774 if(i % 50 == 0) iprintf(" (%08d)\n", i);
776 int mrnum = tcmaprnum(map);
777 if(mrnum % 50 > 0) iprintf(" (%08d)\n", mrnum);
778 if(tcadbrnum(adb) != 0){
779 eprint(adb, "(validation)");
782 iprintf("record number: %llu\n", (unsigned long long)tcadbrnum(adb));
783 iprintf("size: %llu\n", (unsigned long long)tcadbsize(adb));
785 if(!tcadbclose(adb)){
786 eprint(adb, "tcadbclose");
790 iprintf("time: %.3f\n", tctime() - stime);
791 iprintf("%s\n\n", err ? "error" : "ok");