00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <errno.h>
00024 #include <fcntl.h>
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <sys/mman.h>
00029 #include <sys/stat.h>
00030 #include <sys/types.h>
00031 #include <unistd.h>
00032
00033 #include <ccn/btree.h>
00034 #include <ccn/btree_content.h>
00035 #include <ccn/ccn.h>
00036 #include <ccn/charbuf.h>
00037 #include <ccn/indexbuf.h>
00038 #include <ccn/hashtb.h>
00039 #include <ccn/uri.h>
00040
00041 #define FAILIF(cond) do {} while ((cond) && fatal(__func__, __LINE__))
00042 #define CHKSYS(res) FAILIF((res) == -1)
00043 #define CHKPTR(p) FAILIF((p) == NULL)
00044
00045 static int
00046 fatal(const char *fn, int lineno)
00047 {
00048 char buf[80] = {0};
00049 snprintf(buf, sizeof(buf)-1, "OOPS - function %s, line %d", fn, lineno);
00050 perror(buf);
00051 exit(1);
00052 return(0);
00053 }
00054
00055
00056
00057
00058
00059
00060 static int
00061 test_directory_creation(void)
00062 {
00063 int res;
00064 struct ccn_charbuf *dirbuf;
00065 char *temp;
00066
00067 dirbuf = ccn_charbuf_create();
00068 CHKPTR(dirbuf);
00069 res = ccn_charbuf_putf(dirbuf, "./%s", "_bt_XXXXXX");
00070 CHKSYS(res);
00071 temp = mkdtemp(ccn_charbuf_as_string(dirbuf));
00072 CHKPTR(temp);
00073 res = ccn_charbuf_putf(dirbuf, "/%s", "_test");
00074 CHKSYS(res);
00075 res = mkdir(ccn_charbuf_as_string(dirbuf), 0777);
00076 CHKSYS(res);
00077 printf("Created directory %s\n", ccn_charbuf_as_string(dirbuf));
00078 setenv("TEST_DIRECTORY", ccn_charbuf_as_string(dirbuf), 1);
00079 ccn_charbuf_destroy(&dirbuf);
00080 return(res);
00081 }
00082
00083
00084
00085
00086
00087
00088 static int
00089 test_btree_io(void)
00090 {
00091 int res;
00092 struct ccn_btree_node nodespace = {0};
00093 struct ccn_btree_node *node = &nodespace;
00094 struct ccn_btree_io *io = NULL;
00095
00096
00097 io = ccn_btree_io_from_directory(getenv("TEST_DIRECTORY"), NULL);
00098 CHKPTR(io);
00099 node->buf = ccn_charbuf_create();
00100 CHKPTR(node->buf);
00101 node->nodeid = 12345;
00102 res = io->btopen(io, node);
00103 CHKSYS(res);
00104 FAILIF(node->iodata == NULL);
00105 ccn_charbuf_putf(node->buf, "smoke");
00106 res = io->btwrite(io, node);
00107 CHKSYS(res);
00108 node->buf->length = 0;
00109 ccn_charbuf_putf(node->buf, "garbage");
00110 res = io->btread(io, node, 500000);
00111 CHKSYS(res);
00112 FAILIF(node->buf->length != 5);
00113 FAILIF(node->buf->limit > 10000);
00114 node->clean = 5;
00115 ccn_charbuf_putf(node->buf, "r");
00116 res = io->btwrite(io, node);
00117 CHKSYS(res);
00118 node->buf->length--;
00119 ccn_charbuf_putf(node->buf, "d");
00120 res = io->btread(io, node, 1000);
00121 CHKSYS(res);
00122 FAILIF(0 != strcmp("smoker", ccn_charbuf_as_string(node->buf)));
00123 node->buf->length--;
00124 res = io->btwrite(io, node);
00125 CHKSYS(res);
00126 node->buf->length = 0;
00127 ccn_charbuf_putf(node->buf, "garbage");
00128 node->clean = 0;
00129 res = io->btread(io, node, 1000);
00130 CHKSYS(res);
00131 res = io->btclose(io, node);
00132 CHKSYS(res);
00133 FAILIF(node->iodata != NULL);
00134 FAILIF(0 != strcmp("smoke", ccn_charbuf_as_string(node->buf)));
00135 res = io->btdestroy(&io);
00136 CHKSYS(res);
00137 ccn_charbuf_destroy(&node->buf);
00138 return(res);
00139 }
00140
00141
00142
00143
00144
00145
00146 static void
00147 check_structure_size(const char *what, int sz)
00148 {
00149 printf("%s size is %d bytes\n", what, sz);
00150 errno=EINVAL;
00151 FAILIF(sz % CCN_BT_SIZE_UNITS != 0);
00152 }
00153
00154
00155
00156
00157
00158
00159
00160 int
00161 test_structure_sizes(void)
00162 {
00163 check_structure_size("ccn_btree_entry_trailer",
00164 sizeof(struct ccn_btree_entry_trailer));
00165 check_structure_size("ccn_btree_internal_entry",
00166 sizeof(struct ccn_btree_internal_entry));
00167 check_structure_size("ccn_btree_content_entry",
00168 sizeof(struct ccn_btree_content_entry));
00169 return(0);
00170 }
00171
00172
00173
00174
00175 int
00176 test_btree_lockfile(void)
00177 {
00178 int res;
00179 struct ccn_btree_io *io = NULL;
00180 struct ccn_btree_io *io2 = NULL;
00181
00182 io = ccn_btree_io_from_directory(getenv("TEST_DIRECTORY"), NULL);
00183 CHKPTR(io);
00184
00185 errno = 0;
00186 io2 = ccn_btree_io_from_directory(getenv("TEST_DIRECTORY"), NULL);
00187 FAILIF(io2 != NULL || errno == 0);
00188 errno=EINVAL;
00189 res = io->btdestroy(&io);
00190 CHKSYS(res);
00191 FAILIF(io != NULL);
00192 return(res);
00193 }
00194
00195 struct entry_example {
00196 unsigned char p[CCN_BT_SIZE_UNITS];
00197 struct ccn_btree_entry_trailer t;
00198 };
00199
00200 struct node_example {
00201 struct ccn_btree_node_header hdr;
00202 unsigned char ss[64];
00203 struct entry_example e[3];
00204 } ex1 = {
00205 {{0x05, 0x3a, 0xde, 0x78}, {1}},
00206 "goodstuff<------ WASTE---------->d<----><-------------- free -->",
00207
00208 {
00209 {.t={.koff0={0,0,0,33+8}, .ksiz0={0,1}, .entdx={0,0}, .entsz={3}}},
00210 {.t={.koff0={0,0,0,0+8}, .ksiz0={0,9}, .entdx={0,1}, .entsz={3}}},
00211 {.t={.koff0={0,0,0,2+8}, .ksiz0={0,2}, .entdx={0,2}, .entsz={3},
00212 .koff1={0,0,0,3+8}, .ksiz1={0,1}}},
00213 }
00214 };
00215
00216 struct node_example ex2 = {
00217 {{0x05, 0x3a, 0xde, 0x78}, {1}},
00218 "struthiomimus",
00219 {
00220 {.t={.koff1={0,0,0,2+8}, .ksiz1={0,3}, .entdx={0,0}, .entsz={3}}},
00221 {.t={.koff0={0,0,0,0+8}, .ksiz0={0,5}, .entdx={0,1}, .entsz={3}}},
00222 {.t={.koff0={0,0,0,1+8}, .ksiz0={0,5}, .entdx={0,2}, .entsz={3}}},
00223 }
00224 };
00225
00226 struct root_example {
00227 struct ccn_btree_node_header hdr;
00228 unsigned char ss[CCN_BT_SIZE_UNITS];
00229 struct ccn_btree_internal_entry e[2];
00230 } rootex1 = {
00231 {{0x05, 0x3a, 0xde, 0x78}, {1}, {'R'}, {1}},
00232 "ru",
00233 {
00234 { {.magic={0xcc}, .child={0,0,0,2}},
00235 {.entdx={0,0}, .level={1}, .entsz={3}}},
00236 { {.magic={0xcc}, .child={0,0,0,3}},
00237 {.koff1={0,0,0,0+8}, .ksiz1={0,2},
00238 .entdx={0,1}, .level={1}, .entsz={3}}},
00239 }
00240 };
00241
00242 int
00243 test_btree_chknode(void)
00244 {
00245 int res;
00246 struct ccn_btree_node *node = NULL;
00247 struct node_example *ex = NULL;
00248
00249 node = calloc(1, sizeof(*node));
00250 CHKPTR(node);
00251 node->buf = ccn_charbuf_create();
00252 CHKPTR(node->buf);
00253 ccn_charbuf_append(node->buf, &ex1, sizeof(ex1));
00254 res = ccn_btree_chknode(node);
00255 CHKSYS(res);
00256 FAILIF(node->corrupt != 0);
00257 FAILIF(node->freelow != 8 + 34);
00258 ex = (void *)node->buf->buf;
00259 ex->e[1].t.ksiz0[2] = 100;
00260 res = ccn_btree_chknode(node);
00261 FAILIF(res != -1);
00262 FAILIF(node->corrupt == 0);
00263 ccn_charbuf_destroy(&node->buf);
00264 free(node);
00265 return(0);
00266 }
00267
00268 int
00269 test_btree_key_fetch(void)
00270 {
00271 int i;
00272 int res;
00273 struct ccn_charbuf *cb = NULL;
00274 struct ccn_btree_node *node = NULL;
00275 struct node_example ex = ex1;
00276
00277 const char *expect[3] = { "d", "goodstuff", "odd" };
00278
00279 node = calloc(1, sizeof(*node));
00280 CHKPTR(node);
00281 node->buf = ccn_charbuf_create();
00282 CHKPTR(node->buf);
00283 ccn_charbuf_append(node->buf, &ex, sizeof(ex));
00284
00285 cb = ccn_charbuf_create();
00286
00287 for (i = 0; i < 3; i++) {
00288 res = ccn_btree_key_fetch(cb, node, i);
00289 CHKSYS(res);
00290 FAILIF(cb->length != strlen(expect[i]));
00291 FAILIF(0 != memcmp(cb->buf, expect[i], cb->length));
00292 }
00293
00294 res = ccn_btree_key_fetch(cb, node, i);
00295 FAILIF(res != -1);
00296 res = ccn_btree_key_fetch(cb, node, -1);
00297 FAILIF(res != -1);
00298 FAILIF(node->corrupt);
00299
00300 ex.e[1].t.koff0[2] = 1;
00301 node->buf->length = 0;
00302 ccn_charbuf_append(node->buf, &ex, sizeof(ex));
00303
00304 res = ccn_btree_key_append(cb, node, 0);
00305 CHKSYS(res);
00306
00307 res = ccn_btree_key_append(cb, node, 1);
00308 FAILIF(res != -1);
00309 FAILIF(!node->corrupt);
00310 printf("line %d code = %d\n", __LINE__, node->corrupt);
00311
00312 ccn_charbuf_destroy(&cb);
00313 ccn_charbuf_destroy(&node->buf);
00314 free(node);
00315 return(0);
00316 }
00317
00318 int
00319 test_btree_compare(void)
00320 {
00321 int i, j;
00322 int res;
00323 struct ccn_btree_node *node = NULL;
00324 struct node_example ex = ex1;
00325
00326 const char *expect[3] = { "d", "goodstuff", "odd" };
00327
00328 node = calloc(1, sizeof(*node));
00329 CHKPTR(node);
00330 node->buf = ccn_charbuf_create();
00331 CHKPTR(node->buf);
00332 ccn_charbuf_append(node->buf, &ex, sizeof(ex));
00333
00334 for (i = 0; i < 3; i++) {
00335 for (j = 0; j < 3; j++) {
00336 res = ccn_btree_compare((const void *)expect[i], strlen(expect[i]),
00337 node, j);
00338 FAILIF( (i < j) != (res < 0));
00339 FAILIF( (i > j) != (res > 0));
00340 FAILIF( (i == j) != (res == 0));
00341 }
00342 }
00343 ccn_charbuf_destroy(&node->buf);
00344 free(node);
00345 return(0);
00346 }
00347
00348 int
00349 test_btree_searchnode(void)
00350 {
00351 int i;
00352 int res;
00353 struct ccn_btree_node *node = NULL;
00354 struct node_example ex = ex1;
00355 const int yes = 1;
00356 const int no = 0;
00357
00358 struct {
00359 const char *s;
00360 int expect;
00361 } testvec[] = {
00362 {"", CCN_BT_ENCRES(0, no)},
00363 {"c", CCN_BT_ENCRES(0, no)},
00364 {"d", CCN_BT_ENCRES(0, yes)},
00365 {"d1", CCN_BT_ENCRES(1, no)},
00366 {"goodstuff", CCN_BT_ENCRES(1, yes)},
00367 {"goodstuff1", CCN_BT_ENCRES(2, no)},
00368 {"odc++++++", CCN_BT_ENCRES(2, no)},
00369 {"odd", CCN_BT_ENCRES(2, yes)},
00370 {"odd1", CCN_BT_ENCRES(3, no)},
00371 {"ode", CCN_BT_ENCRES(3, no)}
00372 };
00373
00374 node = calloc(1, sizeof(*node));
00375 CHKPTR(node);
00376 node->buf = ccn_charbuf_create();
00377 CHKPTR(node->buf);
00378 ccn_charbuf_append(node->buf, &ex, sizeof(ex));
00379
00380 res = ccn_btree_node_nent(node);
00381 FAILIF(res != 3);
00382
00383 for (i = 0; i < sizeof(testvec)/sizeof(testvec[0]); i++) {
00384 const char *s = testvec[i].s;
00385 res = ccn_btree_searchnode((const void *)s, strlen(s), node);
00386 printf("search %s => %d, expected %d\n", s, res, testvec[i].expect);
00387 FAILIF(res != testvec[i].expect);
00388 }
00389 ccn_charbuf_destroy(&node->buf);
00390 free(node);
00391 return(0);
00392 }
00393
00394 int
00395 test_btree_init(void)
00396 {
00397 struct ccn_btree *btree = NULL;
00398 int res;
00399 struct ccn_btree_node *node = NULL;
00400 struct ccn_btree_node *node0 = NULL;
00401 struct ccn_btree_node *node1 = NULL;
00402
00403 btree = ccn_btree_create();
00404 CHKPTR(btree);
00405 node0 = ccn_btree_getnode(btree, 0, 0);
00406 CHKPTR(node0);
00407 node1 = ccn_btree_getnode(btree, 1, 0);
00408 FAILIF(node0 == node1);
00409 FAILIF(hashtb_n(btree->resident) != 2);
00410 node = ccn_btree_rnode(btree, 0);
00411 FAILIF(node != node0);
00412 node = ccn_btree_rnode(btree, 1);
00413 FAILIF(node != node1);
00414 node = ccn_btree_rnode(btree, 2);
00415 FAILIF(node != NULL);
00416 res = ccn_btree_destroy(&btree);
00417 FAILIF(btree != NULL);
00418 return(res);
00419 }
00420
00421 struct ccn_btree *
00422 example_btree_small(void)
00423 {
00424 struct ccn_btree *btree = NULL;
00425 struct ccn_btree_node *root = NULL;
00426 struct ccn_btree_node *leaf = NULL;
00427 int res = 0;
00428
00429 btree = ccn_btree_create();
00430 CHKPTR(btree);
00431 leaf = ccn_btree_getnode(btree, 2, 0);
00432 CHKPTR(leaf);
00433 ccn_charbuf_append(leaf->buf, &ex1, sizeof(ex1));
00434 res = ccn_btree_chknode(leaf);
00435 CHKSYS(res);
00436 leaf = ccn_btree_getnode(btree, 3, 0);
00437 CHKPTR(leaf);
00438 ccn_charbuf_append(leaf->buf, &ex2, sizeof(ex2));
00439 res = ccn_btree_chknode(leaf);
00440 CHKSYS(res);
00441 root = ccn_btree_getnode(btree, 1, 0);
00442 CHKPTR(root);
00443 ccn_charbuf_append(root->buf, &rootex1, sizeof(rootex1));
00444 res = ccn_btree_chknode(root);
00445 CHKSYS(res);
00446 btree->nextnodeid = 4;
00447 return(btree);
00448 }
00449
00450 int
00451 test_btree_lookup(void)
00452 {
00453 const int yes = 1;
00454 const int no = 0;
00455 struct ccn_btree *btree = NULL;
00456 struct ccn_btree_node *leaf = NULL;
00457 int i;
00458 int res;
00459 struct {
00460 const char *s;
00461 int expectnode;
00462 int expectres;
00463 } testvec[] = {
00464 {"d", 2, CCN_BT_ENCRES(0, yes)},
00465 {"goodstuff", 2, CCN_BT_ENCRES(1, yes)},
00466 {"odd", 2, CCN_BT_ENCRES(2, yes)},
00467 {"truth", 3, CCN_BT_ENCRES(2, yes)},
00468 {"tooth", 3, CCN_BT_ENCRES(2, no)},
00469 };
00470
00471 btree = example_btree_small();
00472 CHKPTR(btree);
00473
00474 for (i = 0; i < sizeof(testvec)/sizeof(testvec[0]); i++) {
00475 const char *s = testvec[i].s;
00476 res = ccn_btree_lookup(btree, (const void *)s, strlen(s), &leaf);
00477 printf("lookup %s => %d, %d, expected %d, %d\n", s,
00478 leaf->nodeid, res,
00479 testvec[i].expectnode, testvec[i].expectres);
00480 FAILIF(res != testvec[i].expectres);
00481 FAILIF(leaf->nodeid != testvec[i].expectnode);
00482 FAILIF(leaf->parent != 1);
00483 res = ccn_btree_node_level(leaf);
00484 FAILIF(res != 0);
00485 }
00486 res = ccn_btree_check(btree, stderr);
00487 res = ccn_btree_destroy(&btree);
00488 FAILIF(btree != NULL);
00489 return(res);
00490 }
00491
00492 int
00493 test_basic_btree_insert_entry(void)
00494 {
00495 struct ccn_btree *btree = NULL;
00496 struct ccn_btree_node *leaf = NULL;
00497 int res;
00498 int ndx;
00499 const char *s = "";
00500 unsigned char payload[6] = "@12345";
00501 unsigned char *c = NULL;
00502 unsigned char canary = 42;
00503 unsigned cage = 10000;
00504 unsigned perch = 1000;
00505
00506 btree = example_btree_small();
00507 CHKPTR(btree);
00508 s = "beauty";
00509 res = ccn_btree_lookup(btree, (const void *)s, strlen(s), &leaf);
00510 CHKSYS(res);
00511 FAILIF(CCN_BT_SRCH_FOUND(res));
00512 ndx = CCN_BT_SRCH_INDEX(res);
00513 FAILIF(ndx != 0);
00514 memset(ccn_charbuf_reserve(leaf->buf, cage), canary, cage);
00515 res = ccn_btree_chknode(leaf);
00516 CHKSYS(res);
00517 res = ccn_btree_insert_entry(leaf, ndx,
00518 (const void *)s, strlen(s),
00519 payload, sizeof(payload));
00520 CHKSYS(res);
00521 res = ccn_btree_chknode(leaf);
00522 CHKSYS(res);
00523 c = &leaf->buf->buf[leaf->buf->length];
00524 FAILIF(c[0] != canary);
00525 FAILIF(0 != memcmp(c, c + 1, perch - 1));
00526 res = ccn_btree_lookup(btree, (const void *)s, strlen(s), &leaf);
00527 FAILIF(res != 1);
00528 res = ccn_btree_lookup(btree, (const void *)"d", 1, &leaf);
00529 FAILIF(res != 3);
00530 s = "age";
00531 payload[0] = 'A';
00532 res = ccn_btree_lookup(btree, (const void *)s, strlen(s), &leaf);
00533 FAILIF(res != 0);
00534 res = ccn_btree_insert_entry(leaf, ndx,
00535 (const void *)s, strlen(s),
00536 payload, sizeof(payload));
00537 CHKSYS(res);
00538 res = ccn_btree_lookup(btree, (const void *)s, strlen(s), &leaf);
00539 FAILIF(res != 1);
00540 res = ccn_btree_lookup(btree, (const void *)"d", 1, &leaf);
00541 FAILIF(res != 5);
00542 c = &leaf->buf->buf[leaf->buf->length];
00543 FAILIF(c[0] != canary);
00544 FAILIF(0 != memcmp(c, c + 1, perch - 1));
00545
00546 btree->nextnodeid = 101;
00547 res = ccn_btree_split(btree, leaf);
00548 CHKSYS(res);
00549 FAILIF(btree->errors != 0);
00550 res = ccn_btree_destroy(&btree);
00551 FAILIF(btree != NULL);
00552 return(res);
00553 }
00554
00555 int
00556 test_btree_inserts_from_stdin(void)
00557 {
00558 struct ccn_charbuf *c;
00559 char payload[8] = "TestTree";
00560 int res;
00561 int item = 0;
00562 int dups = 0;
00563 int unique = 0;
00564 struct ccn_btree *btree = NULL;
00565 struct ccn_btree_node *node = NULL;
00566 struct ccn_btree_node *leaf = NULL;
00567
00568
00569 btree = ccn_btree_create();
00570 CHKPTR(btree);
00571 FAILIF(btree->nextnodeid != 1);
00572 node = ccn_btree_getnode(btree, btree->nextnodeid++, 0);
00573 CHKPTR(node);
00574 res = ccn_btree_init_node(node, 0, 'R', 0);
00575 CHKPTR(node);
00576 FAILIF(btree->nextnodeid < 2);
00577 res = ccn_btree_chknode(node);
00578 CHKSYS(res);
00579 btree->full = 5;
00580
00581 c = ccn_charbuf_create();
00582 CHKPTR(c);
00583 CHKPTR(ccn_charbuf_reserve(c, 8800));
00584 while (fgets((char *)c->buf, c->limit, stdin)) {
00585 item++;
00586 c->length = strlen((char *)c->buf);
00587 if (c->length > 0 && c->buf[c->length - 1] == '\n')
00588 c->length--;
00589
00590 res = ccn_btree_lookup(btree, c->buf, c->length, &leaf);
00591 CHKSYS(res);
00592 if (CCN_BT_SRCH_FOUND(res)) {
00593 dups++;
00594 }
00595 else {
00596 unique++;
00597 res = ccn_btree_insert_entry(leaf, CCN_BT_SRCH_INDEX(res),
00598 c->buf, c->length,
00599 payload, sizeof(payload));
00600 CHKSYS(res);
00601 if (res > 7) {
00602 int limit = 20;
00603 res = ccn_btree_split(btree, leaf);
00604 CHKSYS(res);
00605 while (btree->nextsplit != 0) {
00606 node = ccn_btree_rnode(btree, btree->nextsplit);
00607 CHKPTR(node);
00608 res = ccn_btree_split(btree, node);
00609 CHKSYS(res);
00610 FAILIF(!--limit);
00611 }
00612 FAILIF(btree->missedsplit);
00613 }
00614 }
00615 }
00616 res = ccn_btree_check(btree, stderr);
00617 CHKSYS(res);
00618 printf("%d unique, %d duplicate, %d errors\n", unique, dups, btree->errors);
00619 FAILIF(btree->errors != 0);
00620 res = ccn_btree_lookup(btree, c->buf, 0, &leaf);
00621 CHKSYS(res);
00622 printf("Leaf nodes:");
00623 while (leaf != NULL) {
00624 printf(" %u", leaf->nodeid);
00625 node = leaf;
00626 res = ccn_btree_next_leaf(btree, leaf, &leaf);
00627 CHKSYS(res);
00628 }
00629 printf("\n");
00630 printf("Reversed leaf nodes:");
00631 for (leaf = node; leaf != NULL;) {
00632 printf(" %u", leaf->nodeid);
00633 res = ccn_btree_prev_leaf(btree, leaf, &leaf);
00634 CHKSYS(res);
00635 }
00636 printf("\n");
00637 res = ccn_btree_destroy(&btree);
00638 FAILIF(btree != NULL);
00639 return(res);
00640 }
00641
00642 int
00643 test_flatname(void)
00644 {
00645 unsigned char L0[1] = { 0x00 };
00646 unsigned char A[2] = { 0x01, 'A' };
00647 unsigned char C1[128] = { 0x7F, 0xC1, '.', 'x', '~'};
00648 unsigned char XL[130] = { 0x81, 0x00, 0x39, ' ', 'e', 't', 'c' };
00649 struct {unsigned char *x; size_t l;} ex[] = {
00650 {L0, 0},
00651 {L0, sizeof(L0)},
00652 {A, sizeof(A)},
00653 {C1, sizeof(C1)},
00654 {XL, sizeof(XL)},
00655 {0,0}
00656 };
00657 struct ccn_charbuf *flat;
00658 struct ccn_charbuf *flatout;
00659 struct ccn_charbuf *ccnb;
00660 struct ccn_charbuf *uri;
00661 int i;
00662 int res;
00663 const char *expect = NULL;
00664
00665 flat = ccn_charbuf_create();
00666 flatout = ccn_charbuf_create();
00667 ccnb = ccn_charbuf_create();
00668 uri = ccn_charbuf_create();
00669
00670 res = ccn_flatname_ncomps(flat->buf, flat->length);
00671 FAILIF(res != 0);
00672 for (i = 0; ex[i].x != NULL; i++) {
00673 res = ccn_name_init(ccnb);
00674 FAILIF(res < 0);
00675 flat->length = 0;
00676 ccn_charbuf_append(flat, ex[i].x, ex[i].l);
00677 res = ccn_flatname_ncomps(flat->buf, flat->length);
00678 FAILIF(res != (i > 0));
00679 res = ccn_name_append_flatname(ccnb, flat->buf, flat->length, 0, -1);
00680 FAILIF(res < 0);
00681 res = ccn_flatname_from_ccnb(flatout, ccnb->buf, ccnb->length);
00682 FAILIF(res < 0);
00683 FAILIF(flatout->length != flat->length);
00684 FAILIF(0 != memcmp(flatout->buf, flat->buf,flat->length));
00685 uri->length = 0;
00686 res = ccn_uri_append(uri, ccnb->buf, ccnb->length, 1);
00687 printf("flatname %d: %s\n", i, ccn_charbuf_as_string(uri));
00688 }
00689 ccnb->length = 0;
00690 res = ccn_name_from_uri(ccnb, "ccnx:/10/9/8/7/6/5/4/3/2/1/...");
00691 FAILIF(res < 0);
00692 flat->length = 0;
00693 for (i = 12; i >= 0; i--) {
00694 res = ccn_flatname_append_from_ccnb(flat, ccnb->buf, ccnb->length, i, 1);
00695 FAILIF(res != (i < 11));
00696 }
00697 res = ccn_flatname_append_from_ccnb(flat, ccnb->buf, ccnb->length, 1, 30);
00698 FAILIF(res != 10);
00699 uri->length = 0;
00700 res = ccn_uri_append_flatname(uri, flat->buf, flat->length, 0);
00701 printf("palindrome: %s\n", ccn_charbuf_as_string(uri));
00702 FAILIF(res < 0);
00703 expect = "/.../1/2/3/4/5/6/7/8/9/10/9/8/7/6/5/4/3/2/1/...";
00704 FAILIF(0 != strcmp(ccn_charbuf_as_string(uri), expect));
00705 res = ccn_flatname_ncomps(flat->buf, flat->length);
00706 FAILIF(res != 21);
00707 res = ccn_flatname_ncomps(flat->buf, flat->length - 2);
00708 FAILIF(res != -1);
00709 ccn_charbuf_reserve(flat, 1)[0] = 0x80;
00710 res = ccn_flatname_ncomps(flat->buf, flat->length + 1);
00711 FAILIF(res != -1);
00712 ccn_charbuf_reserve(flat, 1)[0] = 1;
00713 res = ccn_flatname_ncomps(flat->buf, flat->length + 1);
00714 FAILIF(res != -1);
00715 ccn_charbuf_destroy(&flat);
00716 ccn_charbuf_destroy(&flatout);
00717 ccn_charbuf_destroy(&ccnb);
00718 ccn_charbuf_destroy(&uri);
00719 return(0);
00720 }
00721
00722
00723
00724
00725
00726
00727 static int
00728 testhelp_count_matches(struct ccn_btree *btree,
00729 unsigned char *msg, size_t size)
00730 {
00731 struct ccn_btree_node *leaf = NULL;
00732 struct ccn_charbuf *flat = NULL;
00733 struct ccn_charbuf *scratch = NULL;
00734 struct ccn_parsed_interest parsed_interest = {0};
00735 struct ccn_parsed_interest *pi = &parsed_interest;
00736 int cmp;
00737 int i;
00738 int matches;
00739 int n;
00740 int res;
00741
00742 flat = ccn_charbuf_create();
00743 CHKPTR(flat);
00744 res = ccn_flatname_from_ccnb(flat, msg, size);
00745 if (res < 0)
00746 goto Bail;
00747 res = ccn_parse_interest(msg, size, pi, NULL);
00748 if (res < 0) {
00749 if (flat->length > 0)
00750 pi = NULL;
00751 else
00752 goto Bail;
00753 }
00754 res = ccn_btree_lookup(btree, flat->buf, flat->length, &leaf);
00755 CHKSYS(res);
00756 matches = 0;
00757
00758 scratch = ccn_charbuf_create();
00759 n = ccn_btree_node_nent(leaf);
00760 for (i = CCN_BT_SRCH_INDEX(res); i < n; i++) {
00761 cmp = ccn_btree_compare(flat->buf, flat->length, leaf, i);
00762 if (cmp == 0 || cmp == -9999) {
00763
00764 if (pi == NULL)
00765 res = 0;
00766 else
00767 res = ccn_btree_match_interest(leaf, i, msg, pi, scratch);
00768 CHKSYS(res);
00769 if (res == 1) {
00770
00771 matches++;
00772 }
00773 }
00774 else if (cmp > 0) {
00775
00776 FAILIF(1);
00777 }
00778 else {
00779
00780 break;
00781 }
00782 }
00783 res = matches;
00784 Bail:
00785 ccn_charbuf_destroy(&flat);
00786 return(res);
00787 }
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797 int
00798 test_insert_content(void)
00799 {
00800 const char *filename = NULL;
00801 unsigned char *cb = NULL;
00802 unsigned char *cob = NULL;
00803 struct stat statbuf;
00804 int dres;
00805 int fd;
00806 int i;
00807 int res;
00808 size_t cob_offset;
00809 size_t cob_size;
00810 size_t size;
00811 struct ccn_skeleton_decoder decoder = {0};
00812 struct ccn_skeleton_decoder *d = &decoder;
00813 struct ccn_parsed_ContentObject pcobject = {0};
00814 struct ccn_parsed_ContentObject *pc = &pcobject;
00815 struct ccn_charbuf *flatname = NULL;
00816 struct ccn_charbuf *temp = NULL;
00817 struct ccn_indexbuf *comps = NULL;
00818 struct ccn_btree *btree = NULL;
00819 struct ccn_btree_node *node = NULL;
00820 struct ccn_btree_node *leaf = NULL;
00821
00822 filename = getenv("TEST_CONTENT");
00823 if (filename == NULL || filename[0] == 0)
00824 return(1);
00825 printf("Opening %s\n", filename);
00826 fd = open(filename, O_RDONLY, 0);
00827 CHKSYS(fd);
00828 res = fstat(fd, &statbuf);
00829 CHKSYS(res);
00830 size = statbuf.st_size;
00831 printf("Mapping %zd bytes from file %s\n", size, filename);
00832 cb = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
00833 FAILIF(cb == MAP_FAILED && size != 0);
00834
00835
00836 btree = ccn_btree_create();
00837 CHKPTR(btree);
00838 FAILIF(btree->nextnodeid != 1);
00839 node = ccn_btree_getnode(btree, btree->nextnodeid++, 0);
00840 CHKPTR(node);
00841 res = ccn_btree_init_node(node, 0, 'R', 0);
00842 CHKPTR(node);
00843 FAILIF(btree->nextnodeid < 2);
00844 res = ccn_btree_chknode(node);
00845 CHKSYS(res);
00846 btree->full = 50;
00847
00848 flatname = ccn_charbuf_create();
00849 CHKPTR(flatname);
00850 temp = ccn_charbuf_create();
00851 CHKPTR(temp);
00852 comps = ccn_indexbuf_create();
00853 CHKPTR(comps);
00854 while (d->index < size) {
00855 dres = ccn_skeleton_decode(d, cb + d->index, size - d->index);
00856 if (!CCN_FINAL_DSTATE(d->state))
00857 break;
00858 cob_offset = d->index - dres;
00859 cob = cb + cob_offset;
00860 cob_size = dres;
00861 printf("offset %zd, size %zd\n", cob_offset, cob_size);
00862 res = ccn_parse_ContentObject(cob, cob_size, pc, comps);
00863 if (res < 0) {
00864 res = testhelp_count_matches(btree, cob, cob_size);
00865 if (res < 0) {
00866 printf(" . . . skipping non-ContentObject\n");
00867 }
00868 else {
00869 printf(" . . . interest processing res = %d\n", res);
00870 }
00871 }
00872 else {
00873 res = ccn_flatname_from_ccnb(flatname, cob, cob_size);
00874 FAILIF(res != comps->n - 1);
00875 ccn_digest_ContentObject(cob, pc);
00876 FAILIF(pc->digest_bytes != 32);
00877 res = ccn_flatname_append_component(flatname,
00878 pc->digest, pc->digest_bytes);
00879 CHKSYS(res);
00880 temp->length = 0;
00881 ccn_uri_append_flatname(temp, flatname->buf, flatname->length, 1);
00882 res = ccn_btree_lookup(btree, flatname->buf, flatname->length, &leaf);
00883 CHKSYS(res);
00884 if (CCN_BT_SRCH_FOUND(res)) {
00885 printf("FOUND %s\n", ccn_charbuf_as_string(temp));
00886 }
00887 else {
00888 i = CCN_BT_SRCH_INDEX(res);
00889 res = ccn_btree_insert_content(leaf, i,
00890 cob_offset + 1,
00891 cob,
00892 pc,
00893 flatname);
00894 CHKSYS(res);
00895 printf("INSERTED %s\n", ccn_charbuf_as_string(temp));
00896
00897 }
00898 }
00899 }
00900 FAILIF(d->index != size);
00901 FAILIF(!CCN_FINAL_DSTATE(d->state));
00902 if (cb != MAP_FAILED) {
00903 res = munmap(cb, size);
00904 CHKSYS(res);
00905 cb = NULL;
00906 size = 0;
00907 }
00908 res = close(fd);
00909 CHKSYS(res);
00910 ccn_charbuf_destroy(&flatname);
00911 ccn_charbuf_destroy(&temp);
00912 ccn_indexbuf_destroy(&comps);
00913 return(0);
00914 }
00915
00916 int
00917 ccnbtreetest_main(int argc, char **argv)
00918 {
00919 int res;
00920
00921 if (argv[1] && 0 == strcmp(argv[1], "-")) {
00922 res = test_btree_inserts_from_stdin();
00923 CHKSYS(res);
00924 exit(0);
00925 }
00926 res = test_directory_creation();
00927 CHKSYS(res);
00928 res = test_btree_io();
00929 CHKSYS(res);
00930 res = test_btree_lockfile();
00931 CHKSYS(res);
00932 res = test_structure_sizes();
00933 CHKSYS(res);
00934 res = test_btree_chknode();
00935 CHKSYS(res);
00936 res = test_btree_key_fetch();
00937 CHKSYS(res);
00938 res = test_btree_compare();
00939 CHKSYS(res);
00940 res = test_btree_searchnode();
00941 CHKSYS(res);
00942 res = test_btree_init();
00943 CHKSYS(res);
00944 res = test_btree_lookup();
00945 CHKSYS(res);
00946 res = test_basic_btree_insert_entry();
00947 CHKSYS(res);
00948 res = test_flatname();
00949 CHKSYS(res);
00950 res = test_insert_content();
00951 CHKSYS(res);
00952 if (res != 0)
00953 fprintf(stderr, "test_insert_content() => %d\n", res);
00954 return(0);
00955 }