test_sync_db.c (32147B)
1 /* 2 This file is part of TALER 3 (C) 2019 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU Lesser General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License along with 14 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file syncdb/test_sync_db.c 18 * @brief testcase for sync postgres db 19 * @author Christian Grothoff 20 */ 21 #include "platform.h" 22 #include <gnunet/gnunet_util_lib.h> 23 #include <taler/taler_util.h> 24 #include "sync/sync_service.h" 25 #include "sync/sync_database_lib.h" 26 #include "sync/sync_util.h" 27 28 29 #define FAILIF(cond) \ 30 do { \ 31 if (! (cond)) { break;} \ 32 GNUNET_break (0); \ 33 goto drop; \ 34 } while (0) 35 36 #define RND_BLK(ptr) \ 37 GNUNET_CRYPTO_random_block (ptr, sizeof (*ptr)) 38 39 /** 40 * Global return value for the test. Initially #EXIT_FAILURE, set to 41 * 0 upon completion. Other values indicate some kind of error. 42 */ 43 static int result; 44 45 46 /** 47 * Function called on all pending payments for an account. 48 * 49 * @param cls closure 50 * @param timestamp for how long have we been waiting 51 * @param order_id order id in the backend 52 * @param token claim token, or NULL for none 53 * @param amount how much is the order for 54 */ 55 static void 56 payment_it (void *cls, 57 struct GNUNET_TIME_Timestamp timestamp, 58 const char *order_id, 59 const struct TALER_ClaimTokenP *token, 60 const struct TALER_Amount *amount) 61 { 62 (void) timestamp; 63 (void) token; 64 (void) amount; 65 GNUNET_assert (NULL == cls); 66 GNUNET_assert (0 == strcmp (order_id, 67 "fake-order-2")); 68 } 69 70 71 /** 72 * Iterator used by the #SYNCDB_lookup_block_range_TR() tests, 73 * simply counts the blocks it is called with. 74 * 75 * @param cls an `int *` counter to increment 76 * @param nonce block nonce 77 * @param block_hash hash of the block data 78 * @param prev_nonce previous block nonce (NULL if first) 79 * @param next_nonce next block nonce (NULL if last) 80 * @param data_size size of @a data 81 * @param data encrypted block contents 82 * @param upload_sig signature stored with the block 83 * @param old_hash hash of the replaced block data 84 * @param refs_hash hash over the object references 85 */ 86 static void 87 block_it (void *cls, 88 const struct SYNC_BlockNonce *nonce, 89 const struct GNUNET_HashCode *block_hash, 90 const struct SYNC_BlockNonce *prev_nonce, 91 const struct SYNC_BlockNonce *next_nonce, 92 size_t data_size, 93 const void *data, 94 const struct SYNC_AccountSignatureP *upload_sig, 95 const struct GNUNET_HashCode *old_hash, 96 const struct GNUNET_HashCode *refs_hash) 97 { 98 (void) upload_sig; 99 (void) old_hash; 100 (void) refs_hash; 101 int *cnt = cls; 102 103 (void) nonce; 104 (void) block_hash; 105 (void) prev_nonce; 106 (void) next_nonce; 107 (void) data_size; 108 (void) data; 109 (*cnt)++; 110 } 111 112 113 /** 114 * Create a paid account, so that the SQL entry points do not reject 115 * it with #SYNC_DB_PAYMENT_REQUIRED. 116 * 117 * @param account_pub account to activate 118 * @param order_id (unique) order ID to use for the fake payment 119 * @return #GNUNET_OK on success 120 */ 121 static enum GNUNET_GenericReturnValue 122 activate_account (const struct SYNC_AccountPublicKeyP *account_pub, 123 const char *order_id) 124 { 125 struct TALER_Amount amount; 126 struct TALER_ClaimTokenP token; 127 128 memset (&token, 3, sizeof (token)); 129 if (GNUNET_OK != 130 TALER_string_to_amount ("EUR:1", 131 &amount)) 132 { 133 GNUNET_break (0); 134 return GNUNET_SYSERR; 135 } 136 if (SYNC_DB_ONE_RESULT != 137 SYNCDB_store_payment_TR (account_pub, 138 order_id, 139 &token, 140 &amount, 141 GNUNET_TIME_UNIT_MINUTES)) 142 { 143 GNUNET_break (0); 144 return GNUNET_SYSERR; 145 } 146 if (SYNC_DB_ONE_RESULT != 147 SYNCDB_increment_lifetime_TR (account_pub, 148 order_id, 149 GNUNET_TIME_UNIT_MINUTES)) 150 { 151 GNUNET_break (0); 152 return GNUNET_SYSERR; 153 } 154 return GNUNET_OK; 155 } 156 157 158 /** 159 * Count the blocks currently stored for @a account_pub. 160 * 161 * @param account_pub account to count blocks of 162 * @return number of blocks found 163 */ 164 static int 165 count_blocks (const struct SYNC_AccountPublicKeyP *account_pub) 166 { 167 int got = 0; 168 169 SYNCDB_lookup_block_range_TR (account_pub, 170 NULL, 171 100, 172 &block_it, 173 &got); 174 return got; 175 } 176 177 178 /** 179 * Main function that will be run by the scheduler. 180 * 181 * @param cls closure with config 182 */ 183 static void 184 run (void *cls) 185 { 186 struct GNUNET_CONFIGURATION_Handle *cfg = cls; 187 struct TALER_Amount amount; 188 struct SYNC_AccountPublicKeyP account_pub; 189 struct GNUNET_HashCode h; 190 struct GNUNET_HashCode h2; 191 struct GNUNET_TIME_Absolute ts; 192 struct TALER_ClaimTokenP token; 193 /* P1: fake signature/refs for the DB-level tests (the procedures 194 store, they do not verify) */ 195 struct SYNC_AccountSignatureP fake_sig; 196 struct GNUNET_HashCode empty_refs; 197 198 memset (&fake_sig, 7, sizeof (fake_sig)); 199 GNUNET_CRYPTO_hash ("", 0, &empty_refs); 200 201 if (GNUNET_OK != 202 SYNCDB_init_admin (cfg)) 203 { 204 result = 77; 205 return; 206 } 207 if (GNUNET_OK != 208 SYNCDB_drop_tables ()) 209 { 210 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 211 "Dropping tables failed\n"); 212 } 213 if (GNUNET_OK != 214 SYNCDB_create_tables ()) 215 { 216 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 217 "Creating tables failed\n"); 218 } 219 GNUNET_assert (GNUNET_OK == 220 SYNCDB_preflight ()); 221 memset (&account_pub, 1, sizeof (account_pub)); 222 memset (&token, 3, sizeof (token)); 223 GNUNET_CRYPTO_hash ("data", 4, &h); 224 GNUNET_CRYPTO_hash ("DATA", 4, &h2); 225 GNUNET_assert (GNUNET_OK == 226 TALER_string_to_amount ("EUR:1", 227 &amount)); 228 FAILIF (SYNC_DB_ONE_RESULT != 229 SYNCDB_store_payment_TR ( 230 &account_pub, 231 "fake-order", 232 &token, 233 &amount, 234 GNUNET_TIME_UNIT_MINUTES)); 235 FAILIF (SYNC_DB_ONE_RESULT != 236 SYNCDB_increment_lifetime_TR ( 237 &account_pub, 238 "fake-order", 239 GNUNET_TIME_UNIT_MINUTES)); 240 241 FAILIF (0 != 242 SYNCDB_lookup_pending_payments_by_account_TR ( 243 &account_pub, 244 &payment_it, 245 NULL)); 246 memset (&account_pub, 2, sizeof (account_pub)); 247 FAILIF (SYNC_DB_ONE_RESULT != 248 SYNCDB_store_payment_TR ( 249 &account_pub, 250 "fake-order-2", 251 &token, 252 &amount, 253 GNUNET_TIME_UNIT_MINUTES)); 254 FAILIF (1 != 255 SYNCDB_lookup_pending_payments_by_account_TR ( 256 &account_pub, 257 &payment_it, 258 NULL)); 259 FAILIF (SYNC_DB_ONE_RESULT != 260 SYNCDB_increment_lifetime_TR ( 261 &account_pub, 262 "fake-order-2", 263 GNUNET_TIME_UNIT_MINUTES)); 264 /* --- DLL tests: append three blocks A->B->C and validate lookup --- */ 265 { 266 struct SYNC_BlockNonce nA; 267 struct SYNC_BlockNonce nB; 268 struct SYNC_BlockNonce nC; 269 struct GNUNET_HashCode hA; 270 struct GNUNET_HashCode hB; 271 struct GNUNET_HashCode hC; 272 char dataA[] = "A"; 273 char dataB[] = "B"; 274 char dataC[] = "C"; 275 int got; 276 277 RND_BLK (&nA); 278 RND_BLK (&nB); 279 RND_BLK (&nC); 280 GNUNET_CRYPTO_hash (dataA, sizeof dataA - 1, &hA); 281 GNUNET_CRYPTO_hash (dataB, sizeof dataB - 1, &hB); 282 GNUNET_CRYPTO_hash (dataC, sizeof dataC - 1, &hC); 283 284 /* Append A (prev NULL) */ 285 FAILIF (SYNC_DB_ONE_RESULT != 286 SYNCDB_append_block_TR ( 287 &account_pub, 288 &nA, 289 NULL, 290 &hA, 291 sizeof dataA - 1, 292 dataA, 293 0, 294 NULL, 295 NULL, 296 &fake_sig, 297 &empty_refs, 298 NULL, 299 NULL, 300 NULL)); 301 302 303 /* Append B (prev A) */ 304 FAILIF (SYNC_DB_ONE_RESULT != 305 SYNCDB_append_block_TR ( 306 &account_pub, 307 &nB, 308 &nA, 309 &hB, 310 sizeof dataB - 1, 311 dataB, 312 0, 313 NULL, 314 NULL, 315 &fake_sig, 316 &empty_refs, 317 &fake_sig, 318 &hA, 319 NULL)); 320 321 322 /* Append C (prev B) */ 323 FAILIF (SYNC_DB_ONE_RESULT != 324 SYNCDB_append_block_TR ( 325 &account_pub, 326 &nC, 327 &nB, 328 &hC, 329 sizeof dataC - 1, 330 dataC, 331 0, 332 NULL, 333 NULL, 334 &fake_sig, 335 &empty_refs, 336 &fake_sig, 337 &hB, 338 &nA)); 339 340 /* Verify lookup returns 3 blocks */ 341 got = 0; 342 FAILIF (3 != 343 SYNCDB_lookup_block_range_TR ( 344 &account_pub, 345 &nA, 346 10, 347 &block_it, 348 &got)); 349 FAILIF (got != 3); 350 351 /* The relink signature covers the neighbour's other link, so an 352 append whose view of it went stale must be refused rather than 353 stored (the caller reads the neighbour outside the transaction) */ 354 { 355 struct SYNC_BlockNonce nS; 356 struct GNUNET_HashCode hS; 357 char dataS[] = "S"; 358 359 RND_BLK (&nS); 360 GNUNET_CRYPTO_hash (dataS, sizeof dataS - 1, &hS); 361 FAILIF (SYNC_DB_OUTDATED_WRITE != 362 SYNCDB_append_block_TR ( 363 &account_pub, 364 &nS, 365 &nC, 366 &hS, 367 sizeof dataS - 1, 368 dataS, 369 0, 370 NULL, 371 NULL, 372 &fake_sig, 373 &empty_refs, 374 &fake_sig, 375 &hC, 376 /* C's predecessor is B, not A */ &nA)); 377 FAILIF (3 != count_blocks (&account_pub)); 378 } 379 380 /* Delete middle block B (use its prev and next) */ 381 FAILIF (SYNC_DB_ONE_RESULT != 382 SYNCDB_delete_block_TR ( 383 &account_pub, 384 &nB, 385 &nA, 386 &nC, 387 &hB, 388 0, 389 NULL, 390 NULL, 391 &fake_sig, 392 &hA, 393 NULL, 394 &fake_sig, 395 &hC, 396 NULL)); 397 398 /* Update block C (test update path) */ 399 { 400 struct GNUNET_HashCode newC; 401 char newDataC[] = "C-new"; 402 403 GNUNET_CRYPTO_hash (newDataC, sizeof newDataC - 1, &newC); 404 FAILIF (SYNC_DB_ONE_RESULT != 405 SYNCDB_update_block_TR ( 406 &account_pub, 407 &nC, 408 /* prev */ &nA, 409 /* next */ NULL, 410 &hC, 411 &newC, 412 sizeof newDataC - 1, 413 newDataC, 414 0, 415 NULL, 416 NULL, 417 &fake_sig, 418 &empty_refs)); 419 hC = newC; 420 } 421 422 /* --- Outdated-write tests --- */ 423 { 424 struct SYNC_BlockNonce nD; 425 struct GNUNET_HashCode hD; 426 char dataD[] = "D"; 427 struct GNUNET_HashCode bogus_old; 428 char newDataC2[] = "C-newer"; 429 struct GNUNET_HashCode newC2; 430 431 RND_BLK (&nD); 432 GNUNET_CRYPTO_hash (dataD, sizeof dataD - 1, &hD); 433 434 /* Appending with NULL prev when backup is non-empty should be outdated */ 435 FAILIF (SYNC_DB_OUTDATED_WRITE != 436 SYNCDB_append_block_TR ( 437 &account_pub, 438 &nD, 439 /* prev */ NULL, 440 &hD, 441 sizeof dataD - 1, 442 dataD, 443 0, 444 NULL, 445 NULL, 446 &fake_sig, 447 &empty_refs, 448 NULL, 449 NULL, 450 NULL)); 451 452 /* Updating C with wrong old-data-hash should be outdated */ 453 GNUNET_CRYPTO_hash ("bogus", 5, &bogus_old); 454 GNUNET_CRYPTO_hash (newDataC2, sizeof newDataC2 - 1, &newC2); 455 FAILIF (SYNC_DB_OUTDATED_WRITE != 456 SYNCDB_update_block_TR ( 457 &account_pub, 458 &nC, 459 /* prev */ &nA, 460 /* next */ NULL, 461 &bogus_old, 462 &newC2, 463 sizeof newDataC2 - 1, 464 newDataC2, 465 0, 466 NULL, 467 NULL, 468 &fake_sig, 469 &empty_refs)); 470 471 /* Deleting C with wrong prev nonce should be outdated */ 472 FAILIF (SYNC_DB_OUTDATED_WRITE != 473 SYNCDB_delete_block_TR ( 474 &account_pub, 475 &nC, 476 /* prev (wrong) */ &nB, 477 /* next */ NULL, 478 &hC, 479 0, 480 NULL, 481 NULL, 482 NULL, 483 NULL, 484 NULL, 485 NULL, 486 NULL, 487 NULL)); 488 } 489 } 490 491 /* --- Account status lookup --- */ 492 { 493 struct SYNC_AccountPublicKeyP acc; 494 struct SYNC_BlockNonce nonce; 495 struct GNUNET_HashCode bh; 496 char data[] = "account-status-block"; 497 struct GNUNET_TIME_Timestamp expiration; 498 uint64_t storage_used_bytes; 499 uint64_t block_count; 500 501 memset (&acc, 20, sizeof (acc)); 502 503 /* An account nobody has heard of is missing, not expired */ 504 FAILIF (SYNC_DB_TARGET_MISSING != 505 SYNCDB_lookup_account_TR (&acc, 506 &expiration, 507 &storage_used_bytes, 508 &block_count)); 509 510 FAILIF (GNUNET_OK != 511 activate_account (&acc, 512 "fake-order-account-status")); 513 514 /* A fresh account has an expiration and no storage in use */ 515 FAILIF (SYNC_DB_ONE_RESULT != 516 SYNCDB_lookup_account_TR (&acc, 517 &expiration, 518 &storage_used_bytes, 519 &block_count)); 520 FAILIF (GNUNET_TIME_absolute_is_zero (expiration.abs_time)); 521 FAILIF (0 != storage_used_bytes); 522 FAILIF (0 != block_count); 523 524 /* ... and the block it stores is reflected in both counters */ 525 RND_BLK (&nonce); 526 GNUNET_CRYPTO_hash (data, sizeof data - 1, &bh); 527 FAILIF (SYNC_DB_ONE_RESULT != 528 SYNCDB_append_block_TR (&acc, 529 &nonce, 530 NULL, 531 &bh, 532 sizeof data - 1, 533 data, 534 0, 535 NULL, 536 NULL, 537 &fake_sig, 538 &empty_refs, 539 NULL, 540 NULL, 541 NULL)); 542 FAILIF (SYNC_DB_ONE_RESULT != 543 SYNCDB_lookup_account_TR (&acc, 544 &expiration, 545 &storage_used_bytes, 546 &block_count)); 547 FAILIF (sizeof data - 1 != storage_used_bytes); 548 FAILIF (1 != block_count); 549 550 /* The blocks of other accounts must not be counted here */ 551 FAILIF (SYNC_DB_ONE_RESULT != 552 SYNCDB_lookup_account_TR (&account_pub, 553 &expiration, 554 &storage_used_bytes, 555 &block_count)); 556 FAILIF (1 == block_count); 557 } 558 559 /* --- Object store/lookup tests --- */ 560 { 561 struct SYNC_ObjectUID obj_uid; 562 struct GNUNET_HashCode obj_hash; 563 char obj_data[] = "objdata"; 564 int64_t refcount = 0; 565 struct GNUNET_TIME_Timestamp exp; 566 size_t data_sz = 0; 567 568 RND_BLK (&obj_uid); 569 GNUNET_CRYPTO_hash (obj_data, sizeof obj_data - 1, &obj_hash); 570 FAILIF (SYNC_DB_ONE_RESULT != 571 SYNCDB_store_object_TR ( 572 &obj_uid, 573 &account_pub, 574 &obj_hash, 575 GNUNET_TIME_UNIT_DAYS, 576 sizeof obj_data - 1, 577 obj_data)); 578 579 FAILIF (SYNC_DB_ONE_RESULT != 580 SYNCDB_lookup_object ( 581 &account_pub, 582 &obj_hash, 583 &refcount, 584 &exp, 585 &data_sz, 586 NULL)); 587 FAILIF (refcount < 0); 588 589 /* A missing object is a normal outcome, not a failure */ 590 { 591 struct GNUNET_HashCode bogus_hash; 592 593 GNUNET_CRYPTO_hash ("no-such-object", 594 14, 595 &bogus_hash); 596 FAILIF (SYNC_DB_NO_RESULTS != 597 SYNCDB_lookup_object (&account_pub, 598 &bogus_hash, 599 &refcount, 600 &exp, 601 &data_sz, 602 NULL)); 603 } 604 } 605 606 /* --- Referencing an object that was never uploaded --- */ 607 { 608 struct SYNC_AccountPublicKeyP acc; 609 struct SYNC_BlockNonce nonce; 610 struct GNUNET_HashCode bh; 611 struct SYNC_ObjectUID unknown_uid; 612 const int16_t inc = 1; 613 char data[] = "orphan"; 614 615 memset (&acc, 10, sizeof (acc)); 616 FAILIF (GNUNET_OK != 617 activate_account (&acc, 618 "fake-order-refs-missing")); 619 RND_BLK (&nonce); 620 RND_BLK (&unknown_uid); 621 GNUNET_CRYPTO_hash (data, sizeof data - 1, &bh); 622 FAILIF (SYNC_DB_INCONSISTENT_BACKUP != 623 SYNCDB_append_block_TR (&acc, 624 &nonce, 625 NULL, 626 &bh, 627 sizeof data - 1, 628 data, 629 1, 630 &unknown_uid, 631 &inc, 632 &fake_sig, 633 &empty_refs, 634 NULL, 635 NULL, 636 NULL)); 637 /* the rejected append must be a no-op */ 638 FAILIF (0 != count_blocks (&acc)); 639 } 640 641 /* --- A nonce that is already taken is a conflict --- */ 642 { 643 struct SYNC_AccountPublicKeyP acc_a; 644 struct SYNC_AccountPublicKeyP acc_b; 645 struct SYNC_BlockNonce nonce; 646 struct GNUNET_HashCode bh; 647 char data[] = "shared-nonce"; 648 649 memset (&acc_a, 11, sizeof (acc_a)); 650 memset (&acc_b, 12, sizeof (acc_b)); 651 FAILIF (GNUNET_OK != 652 activate_account (&acc_a, 653 "fake-order-nonce-a")); 654 FAILIF (GNUNET_OK != 655 activate_account (&acc_b, 656 "fake-order-nonce-b")); 657 RND_BLK (&nonce); 658 GNUNET_CRYPTO_hash (data, sizeof data - 1, &bh); 659 FAILIF (SYNC_DB_ONE_RESULT != 660 SYNCDB_append_block_TR (&acc_a, 661 &nonce, 662 NULL, 663 &bh, 664 sizeof data - 1, 665 data, 666 0, 667 NULL, 668 NULL, 669 &fake_sig, 670 &empty_refs, 671 NULL, 672 NULL, 673 NULL)); 674 FAILIF (SYNC_DB_OUTDATED_WRITE != 675 SYNCDB_append_block_TR (&acc_b, 676 &nonce, 677 NULL, 678 &bh, 679 sizeof data - 1, 680 data, 681 0, 682 NULL, 683 NULL, 684 &fake_sig, 685 &empty_refs, 686 NULL, 687 NULL, 688 NULL)); 689 /* the rejected append must not have touched account B */ 690 FAILIF (0 != count_blocks (&acc_b)); 691 } 692 693 /* --- Refcount lifecycle --- */ 694 { 695 struct SYNC_AccountPublicKeyP acc; 696 struct SYNC_BlockNonce nonce; 697 struct GNUNET_HashCode bh; 698 struct SYNC_ObjectUID uid; 699 struct GNUNET_HashCode oh; 700 const int16_t inc = 1; 701 const int16_t dec = -1; 702 const int16_t dec2 = -2; 703 char data[] = "refcounted"; 704 char obj[] = "payload"; 705 int64_t refcount = 0; 706 struct GNUNET_TIME_Timestamp exp; 707 size_t data_sz = 0; 708 709 memset (&acc, 13, sizeof (acc)); 710 FAILIF (GNUNET_OK != 711 activate_account (&acc, 712 "fake-order-refcount")); 713 RND_BLK (&nonce); 714 RND_BLK (&uid); 715 GNUNET_CRYPTO_hash (data, sizeof data - 1, &bh); 716 GNUNET_CRYPTO_hash (obj, sizeof obj - 1, &oh); 717 FAILIF (SYNC_DB_ONE_RESULT != 718 SYNCDB_store_object_TR (&uid, 719 &acc, 720 &oh, 721 GNUNET_TIME_UNIT_DAYS, 722 sizeof obj - 1, 723 obj)); 724 /* re-uploading the same UID is idempotent, not an error */ 725 FAILIF (SYNC_DB_ONE_RESULT != 726 SYNCDB_store_object_TR (&uid, 727 &acc, 728 &oh, 729 GNUNET_TIME_UNIT_DAYS, 730 sizeof obj - 1, 731 obj)); 732 FAILIF (SYNC_DB_ONE_RESULT != 733 SYNCDB_append_block_TR (&acc, 734 &nonce, 735 NULL, 736 &bh, 737 sizeof data - 1, 738 data, 739 1, 740 &uid, 741 &inc, 742 &fake_sig, 743 &empty_refs, 744 NULL, 745 NULL, 746 NULL)); 747 FAILIF (SYNC_DB_ONE_RESULT != 748 SYNCDB_lookup_object (&acc, 749 &oh, 750 &refcount, 751 &exp, 752 &data_sz, 753 NULL)); 754 FAILIF (1 != refcount); 755 756 /* decrementing below zero is refused, refcount untouched */ 757 FAILIF (SYNC_DB_INCONSISTENT_BACKUP != 758 SYNCDB_delete_block_TR (&acc, 759 &nonce, 760 NULL, 761 NULL, 762 &bh, 763 1, 764 &uid, 765 &dec2, 766 NULL, 767 NULL, 768 NULL, 769 NULL, 770 NULL, 771 NULL)); 772 FAILIF (SYNC_DB_ONE_RESULT != 773 SYNCDB_lookup_object (&acc, 774 &oh, 775 &refcount, 776 &exp, 777 &data_sz, 778 NULL)); 779 FAILIF (1 != refcount); 780 /* ... and the block must still be there */ 781 FAILIF (1 != count_blocks (&acc)); 782 783 /* the matching decrement drops it to 0, deleting the object */ 784 FAILIF (SYNC_DB_ONE_RESULT != 785 SYNCDB_delete_block_TR (&acc, 786 &nonce, 787 NULL, 788 NULL, 789 &bh, 790 1, 791 &uid, 792 &dec, 793 NULL, 794 NULL, 795 NULL, 796 NULL, 797 NULL, 798 NULL)); 799 FAILIF (SYNC_DB_NO_RESULTS != 800 SYNCDB_lookup_object (&acc, 801 &oh, 802 &refcount, 803 &exp, 804 &data_sz, 805 NULL)); 806 FAILIF (0 != count_blocks (&acc)); 807 } 808 809 /* --- Increments for the same UID are aggregated --- */ 810 { 811 struct SYNC_AccountPublicKeyP acc; 812 struct SYNC_BlockNonce nonce; 813 struct GNUNET_HashCode bh; 814 struct SYNC_ObjectUID uids[2]; 815 struct GNUNET_HashCode oh; 816 const int16_t incs[2] = { -1, 1 }; 817 char data[] = "net-zero"; 818 char obj[] = "aggregated"; 819 int64_t refcount = 0; 820 struct GNUNET_TIME_Timestamp exp; 821 size_t data_sz = 0; 822 823 memset (&acc, 14, sizeof (acc)); 824 FAILIF (GNUNET_OK != 825 activate_account (&acc, 826 "fake-order-aggregate")); 827 RND_BLK (&nonce); 828 RND_BLK (&uids[0]); 829 uids[1] = uids[0]; 830 GNUNET_CRYPTO_hash (data, sizeof data - 1, &bh); 831 GNUNET_CRYPTO_hash (obj, sizeof obj - 1, &oh); 832 FAILIF (SYNC_DB_ONE_RESULT != 833 SYNCDB_store_object_TR (&uids[0], 834 &acc, 835 &oh, 836 GNUNET_TIME_UNIT_DAYS, 837 sizeof obj - 1, 838 obj)); 839 FAILIF (SYNC_DB_ONE_RESULT != 840 SYNCDB_append_block_TR (&acc, 841 &nonce, 842 NULL, 843 &bh, 844 sizeof data - 1, 845 data, 846 2, 847 uids, 848 incs, 849 &fake_sig, 850 &empty_refs, 851 NULL, 852 NULL, 853 NULL)); 854 /* refcount unchanged, and the object still exists */ 855 FAILIF (SYNC_DB_ONE_RESULT != 856 SYNCDB_lookup_object (&acc, 857 &oh, 858 &refcount, 859 &exp, 860 &data_sz, 861 NULL)); 862 FAILIF (0 != refcount); 863 } 864 865 /* --- GC must not remove still-referenced objects --- */ 866 { 867 struct SYNC_AccountPublicKeyP acc; 868 struct SYNC_BlockNonce nonce; 869 struct GNUNET_HashCode bh; 870 struct SYNC_ObjectUID kept_uid; 871 struct SYNC_ObjectUID swept_uid; 872 struct GNUNET_HashCode kept_oh; 873 struct GNUNET_HashCode swept_oh; 874 const int16_t inc = 1; 875 char data[] = "gc-block"; 876 char kept[] = "still-referenced"; 877 char swept[] = "unreferenced"; 878 int64_t refcount = 0; 879 struct GNUNET_TIME_Timestamp exp; 880 size_t data_sz = 0; 881 struct GNUNET_TIME_Absolute future; 882 883 memset (&acc, 15, sizeof (acc)); 884 FAILIF (GNUNET_OK != 885 activate_account (&acc, 886 "fake-order-gc")); 887 RND_BLK (&nonce); 888 RND_BLK (&kept_uid); 889 RND_BLK (&swept_uid); 890 GNUNET_CRYPTO_hash (data, sizeof data - 1, &bh); 891 GNUNET_CRYPTO_hash (kept, sizeof kept - 1, &kept_oh); 892 GNUNET_CRYPTO_hash (swept, sizeof swept - 1, &swept_oh); 893 FAILIF (SYNC_DB_ONE_RESULT != 894 SYNCDB_store_object_TR (&kept_uid, 895 &acc, 896 &kept_oh, 897 GNUNET_TIME_UNIT_DAYS, 898 sizeof kept - 1, 899 kept)); 900 FAILIF (SYNC_DB_ONE_RESULT != 901 SYNCDB_store_object_TR (&swept_uid, 902 &acc, 903 &swept_oh, 904 GNUNET_TIME_UNIT_DAYS, 905 sizeof swept - 1, 906 swept)); 907 FAILIF (SYNC_DB_ONE_RESULT != 908 SYNCDB_append_block_TR (&acc, 909 &nonce, 910 NULL, 911 &bh, 912 sizeof data - 1, 913 data, 914 1, 915 &kept_uid, 916 &inc, 917 &fake_sig, 918 &empty_refs, 919 NULL, 920 NULL, 921 NULL)); 922 /* Leave accounts and payments alone, only sweep objects */ 923 future = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_YEARS); 924 FAILIF (GNUNET_OK != 925 SYNCDB_gc (GNUNET_TIME_UNIT_ZERO_ABS, 926 GNUNET_TIME_UNIT_ZERO_ABS, 927 future)); 928 /* the referenced object survives ... */ 929 FAILIF (SYNC_DB_ONE_RESULT != 930 SYNCDB_lookup_object (&acc, 931 &kept_oh, 932 &refcount, 933 &exp, 934 &data_sz, 935 NULL)); 936 FAILIF (1 != refcount); 937 /* ... the unreferenced one is collected */ 938 FAILIF (SYNC_DB_NO_RESULTS != 939 SYNCDB_lookup_object (&acc, 940 &swept_oh, 941 &refcount, 942 &exp, 943 &data_sz, 944 NULL)); 945 } 946 947 ts = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_YEARS); 948 FAILIF (GNUNET_OK != 949 SYNCDB_gc (ts, 950 ts, 951 ts)); 952 result = 0; 953 drop: 954 GNUNET_break (GNUNET_OK == 955 SYNCDB_drop_tables ()); 956 SYNCDB_fini (); 957 } 958 959 960 int 961 main (int argc, 962 char *const argv[]) 963 { 964 const char *plugin_name; 965 char *config_filename; 966 struct GNUNET_CONFIGURATION_Handle *cfg; 967 968 (void) argc; 969 result = EXIT_FAILURE; 970 /* the database backend is the suffix of our own binary name */ 971 if (NULL == (plugin_name = strrchr (argv[0], (int) '-'))) 972 { 973 GNUNET_break (0); 974 return EXIT_FAILURE; 975 } 976 plugin_name++; 977 GNUNET_log_setup (argv[0], 978 "DEBUG", 979 NULL); 980 GNUNET_asprintf (&config_filename, 981 "test_sync_db_%s.conf", 982 plugin_name); 983 cfg = GNUNET_CONFIGURATION_create (SYNC_project_data ()); 984 if (GNUNET_OK != 985 GNUNET_CONFIGURATION_parse (cfg, 986 config_filename)) 987 { 988 GNUNET_break (0); 989 GNUNET_CONFIGURATION_destroy (cfg); 990 GNUNET_free (config_filename); 991 return EXIT_NOTCONFIGURED; 992 } 993 GNUNET_SCHEDULER_run (&run, cfg); 994 GNUNET_CONFIGURATION_destroy (cfg); 995 GNUNET_free (config_filename); 996 return result; 997 } 998 999 1000 /* end of test_sync_db.c */