test_legitimization_processes.c (24210B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2026 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU 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 exchangedb/test_legitimization_processes.c 18 * @brief tests for the exchangedb functions whose primary table is 19 * `legitimization_processes` 20 * @author Christian Grothoff 21 * 22 * Covers #TALER_EXCHANGEDB_insert_legitimization_process(), 23 * #TALER_EXCHANGEDB_update_legitimization_process_by_row(), 24 * #TALER_EXCHANGEDB_do_reserve_legitimization_process(), 25 * #TALER_EXCHANGEDB_complete_legitimization_process_start(), 26 * #TALER_EXCHANGEDB_insert_kyc_failure(), 27 * #TALER_EXCHANGEDB_insert_aml_program_failure(), 28 * #TALER_EXCHANGEDB_get_legitimization_process_by_account(), 29 * #TALER_EXCHANGEDB_get_pending_legitimization_process(), 30 * #TALER_EXCHANGEDB_get_kyc_provider_account() and 31 * #TALER_EXCHANGEDB_iterate_kyc_references(). 32 * 33 * A row of `legitimization_processes` is one run of one KYC provider 34 * against one account, working on one measure of a 35 * `legitimization_measures` set. The checks therefore create an account 36 * and a measure set first, and then walk a process from "started" through 37 * "redirect known" to "finished". 38 */ 39 #include "test_common.h" 40 #include "exchange-database/complete_legitimization_process_start.h" 41 #include "exchange-database/do_reserve_legitimization_process.h" 42 #include "exchange-database/do_trigger_kyc_rule_for_account.h" 43 #include "exchange-database/get_kyc_provider_account.h" 44 #include "exchange-database/get_legitimization_process_by_account.h" 45 #include "exchange-database/get_pending_legitimization_process.h" 46 #include "exchange-database/insert_aml_program_failure.h" 47 #include "exchange-database/insert_kyc_failure.h" 48 #include "exchange-database/insert_legitimization_process.h" 49 #include "exchange-database/iterate_kyc_references.h" 50 #include "exchange-database/update_legitimization_process_by_row.h" 51 52 53 /** 54 * Account the checks run processes against. 55 */ 56 static struct TDB_Account account; 57 58 59 /** 60 * Measure set the processes work on. 61 */ 62 static uint64_t measure_row; 63 64 65 /** 66 * Row of the process check_start() created. 67 */ 68 static uint64_t process_row; 69 70 71 /** 72 * Closure for #reference_cb(). 73 */ 74 struct ReferenceContext 75 { 76 /** 77 * How many references did the callback see? 78 */ 79 unsigned int total; 80 81 /** 82 * Provider we are looking for, NULL to match nothing. 83 */ 84 const char *provider; 85 86 /** 87 * How many times did we see it? 88 */ 89 unsigned int matched; 90 91 /** 92 * Provider account id reported for it, owned by this struct. 93 */ 94 char *user_id; 95 96 /** 97 * Provider legitimization id reported for it, owned by this struct. 98 */ 99 char *legi_id; 100 }; 101 102 103 /** 104 * Callback for #TALER_EXCHANGEDB_iterate_kyc_references(). 105 * 106 * @param cls a `struct ReferenceContext *` 107 * @param kyc_provider_name provider that ran the process 108 * @param provider_user_id account id at the provider 109 * @param legi_id legitimization id at the provider 110 */ 111 static void 112 reference_cb (void *cls, 113 const char *kyc_provider_name, 114 const char *provider_user_id, 115 const char *legi_id) 116 { 117 struct ReferenceContext *ctx = cls; 118 119 ctx->total++; 120 if ( (NULL != ctx->provider) && 121 (0 == strcmp (kyc_provider_name, 122 ctx->provider)) ) 123 { 124 ctx->matched++; 125 GNUNET_free (ctx->user_id); 126 GNUNET_free (ctx->legi_id); 127 ctx->user_id = (NULL == provider_user_id) 128 ? NULL 129 : GNUNET_strdup (provider_user_id); 130 ctx->legi_id = (NULL == legi_id) 131 ? NULL 132 : GNUNET_strdup (legi_id); 133 } 134 } 135 136 137 /** 138 * Put a measure on our account, creating the account on the way. 139 * 140 * @param pg the database context 141 */ 142 static void 143 setup_account (struct TALER_EXCHANGEDB_PostgresContext *pg) 144 { 145 json_t *jmeasures; 146 uint64_t row = 0; 147 bool bad_kyc_auth; 148 149 if (0 != measure_row) 150 return; 151 TDB_account (pg, 152 10, 153 &account); 154 jmeasures = GNUNET_JSON_PACK ( 155 GNUNET_JSON_pack_array_steal ( 156 "measures", 157 json_pack ("[{s:s,s:s,s:s}]", 158 "check_name", 159 "verify-id", 160 "prog_name", 161 "skip", 162 "context", 163 "none")), 164 GNUNET_JSON_pack_bool ("is_and_combinator", 165 true)); 166 GNUNET_assert (NULL != jmeasures); 167 GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 168 TALER_EXCHANGEDB_do_trigger_kyc_rule_for_account ( 169 pg, 170 account.payto, 171 &account.h_normalized, 172 NULL, 173 NULL, 174 jmeasures, 175 1, 176 &row, 177 &bad_kyc_auth)); 178 json_decref (jmeasures); 179 GNUNET_assert (0 != row); 180 measure_row = row; 181 } 182 183 184 /** 185 * Nothing is known while the table is empty. 186 * 187 * @param pg the database context 188 * @return 0 on success 189 */ 190 static int 191 check_empty (struct TALER_EXCHANGEDB_PostgresContext *pg) 192 { 193 struct TALER_NormalizedPaytoHashP h_payto; 194 struct GNUNET_TIME_Absolute expiration; 195 struct ReferenceContext ctx = { 0 }; 196 char *provider_account_id = NULL; 197 char *provider_legitimization_id = NULL; 198 char *redirect_url = NULL; 199 uint64_t row; 200 bool is_wallet; 201 202 setup_account (pg); 203 FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != 204 TALER_EXCHANGEDB_get_legitimization_process_by_account ( 205 pg, 206 "test-provider", 207 &account.h_normalized, 208 &row, 209 &expiration, 210 &provider_account_id, 211 &provider_legitimization_id, 212 &is_wallet)); 213 FAILIF (NULL != provider_account_id); 214 FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != 215 TALER_EXCHANGEDB_get_pending_legitimization_process ( 216 pg, 217 &account.h_normalized, 218 "test-provider", 219 &redirect_url)); 220 FAILIF (NULL != redirect_url); 221 FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != 222 TALER_EXCHANGEDB_get_kyc_provider_account (pg, 223 "test-provider", 224 "legi-1", 225 &h_payto, 226 &is_wallet, 227 &row)); 228 FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != 229 TALER_EXCHANGEDB_iterate_kyc_references (pg, 230 &account.h_normalized, 231 &reference_cb, 232 &ctx)); 233 FAILIF (0 != ctx.total); 234 return 0; 235 } 236 237 238 /** 239 * Starting a process records it and makes it findable by provider and by 240 * the provider's own identifiers. 241 * 242 * @param pg the database context 243 * @return 0 on success 244 */ 245 static int 246 check_start (struct TALER_EXCHANGEDB_PostgresContext *pg) 247 { 248 struct TALER_NormalizedPaytoHashP h_payto; 249 struct GNUNET_TIME_Absolute expiration; 250 struct ReferenceContext ctx; 251 char *provider_account_id = NULL; 252 char *provider_legitimization_id = NULL; 253 uint64_t row = 0; 254 bool is_wallet = true; 255 256 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 257 TALER_EXCHANGEDB_insert_legitimization_process ( 258 pg, 259 &account.h_normalized, 260 0, 261 measure_row, 262 "test-provider", 263 "provider-account-1", 264 "legi-1", 265 &process_row)); 266 FAILIF (0 == process_row); 267 FAILIF (1 != TDB_count (pg, 268 "FROM legitimization_processes")); 269 270 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 271 TALER_EXCHANGEDB_get_legitimization_process_by_account ( 272 pg, 273 "test-provider", 274 &account.h_normalized, 275 &row, 276 &expiration, 277 &provider_account_id, 278 &provider_legitimization_id, 279 &is_wallet)); 280 FAILIF (row != process_row); 281 FAILIF_C (0 != strcmp (provider_account_id, 282 "provider-account-1"), 283 GNUNET_free (provider_account_id); 284 GNUNET_free (provider_legitimization_id)); 285 FAILIF_C (0 != strcmp (provider_legitimization_id, 286 "legi-1"), 287 GNUNET_free (provider_account_id); 288 GNUNET_free (provider_legitimization_id)); 289 GNUNET_free (provider_account_id); 290 GNUNET_free (provider_legitimization_id); 291 FAILIF (is_wallet); 292 293 /* another provider has no process on this account */ 294 provider_account_id = NULL; 295 FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != 296 TALER_EXCHANGEDB_get_legitimization_process_by_account ( 297 pg, 298 "other-provider", 299 &account.h_normalized, 300 &row, 301 &expiration, 302 &provider_account_id, 303 &provider_legitimization_id, 304 &is_wallet)); 305 306 /* the provider's own identifier resolves back to the account */ 307 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 308 TALER_EXCHANGEDB_get_kyc_provider_account (pg, 309 "test-provider", 310 "legi-1", 311 &h_payto, 312 &is_wallet, 313 &row)); 314 FAILIF (0 != GNUNET_memcmp (&h_payto, 315 &account.h_normalized)); 316 FAILIF (row != process_row); 317 FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != 318 TALER_EXCHANGEDB_get_kyc_provider_account (pg, 319 "test-provider", 320 "legi-does-not-exist", 321 &h_payto, 322 &is_wallet, 323 &row)); 324 325 memset (&ctx, 326 0, 327 sizeof (ctx)); 328 ctx.provider = "test-provider"; 329 FAILIF (0 >= 330 TALER_EXCHANGEDB_iterate_kyc_references (pg, 331 &account.h_normalized, 332 &reference_cb, 333 &ctx)); 334 FAILIF_C (1 != ctx.matched, 335 GNUNET_free (ctx.user_id); GNUNET_free (ctx.legi_id)); 336 FAILIF_C (0 != strcmp (ctx.user_id, 337 "provider-account-1"), 338 GNUNET_free (ctx.user_id); GNUNET_free (ctx.legi_id)); 339 GNUNET_free (ctx.user_id); 340 GNUNET_free (ctx.legi_id); 341 return 0; 342 } 343 344 345 /** 346 * Updating a process records the redirect URL and can mark it finished. 347 * 348 * @param pg the database context 349 * @return 0 on success 350 */ 351 static int 352 check_update (struct TALER_EXCHANGEDB_PostgresContext *pg) 353 { 354 struct GNUNET_TIME_Absolute expiration 355 = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS); 356 char *redirect_url = NULL; 357 358 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 359 TALER_EXCHANGEDB_update_legitimization_process_by_row ( 360 pg, 361 process_row, 362 "test-provider", 363 &account.h_normalized, 364 "provider-account-1", 365 "legi-1", 366 "https://kyc.example/start", 367 expiration, 368 TALER_EC_NONE, 369 NULL, 370 false)); 371 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 372 TALER_EXCHANGEDB_get_pending_legitimization_process ( 373 pg, 374 &account.h_normalized, 375 "test-provider", 376 &redirect_url)); 377 FAILIF (NULL == redirect_url); 378 FAILIF_C (0 != strcmp (redirect_url, 379 "https://kyc.example/start"), 380 GNUNET_free (redirect_url)); 381 GNUNET_free (redirect_url); 382 383 /* a row that does not exist is not created */ 384 FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != 385 TALER_EXCHANGEDB_update_legitimization_process_by_row ( 386 pg, 387 process_row + 1000, 388 "test-provider", 389 &account.h_normalized, 390 "provider-account-1", 391 "legi-1", 392 "https://kyc.example/start", 393 expiration, 394 TALER_EC_NONE, 395 NULL, 396 false)); 397 FAILIF (1 != TDB_count (pg, 398 "FROM legitimization_processes")); 399 400 /* marking it finished takes it out of the pending view */ 401 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 402 TALER_EXCHANGEDB_update_legitimization_process_by_row ( 403 pg, 404 process_row, 405 "test-provider", 406 &account.h_normalized, 407 "provider-account-1", 408 "legi-1", 409 "https://kyc.example/start", 410 expiration, 411 TALER_EC_NONE, 412 NULL, 413 true)); 414 redirect_url = NULL; 415 FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != 416 TALER_EXCHANGEDB_get_pending_legitimization_process ( 417 pg, 418 &account.h_normalized, 419 "test-provider", 420 &redirect_url)); 421 FAILIF (NULL != redirect_url); 422 return 0; 423 } 424 425 426 /** 427 * A failed KYC check marks the process finished with an error. 428 * 429 * @param pg the database context 430 * @return 0 on success 431 */ 432 static int 433 check_kyc_failure (struct TALER_EXCHANGEDB_PostgresContext *pg) 434 { 435 uint64_t row = 0; 436 437 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 438 TALER_EXCHANGEDB_insert_legitimization_process ( 439 pg, 440 &account.h_normalized, 441 1, 442 measure_row, 443 "failing-provider", 444 "provider-account-2", 445 "legi-2", 446 &row)); 447 FAILIF (2 != TDB_count (pg, 448 "FROM legitimization_processes")); 449 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 450 TALER_EXCHANGEDB_insert_kyc_failure ( 451 pg, 452 row, 453 &account.h_normalized, 454 "failing-provider", 455 "provider-account-2", 456 "legi-2", 457 "the provider said no", 458 TALER_EC_EXCHANGE_KYC_GENERIC_PROVIDER_UNEXPECTED_REPLY)); 459 FAILIF (1 != TDB_count (pg, 460 "FROM legitimization_processes" 461 " WHERE finished" 462 " AND error_code=%u", 463 (unsigned int) 464 TALER_EC_EXCHANGE_KYC_GENERIC_PROVIDER_UNEXPECTED_REPLY)); 465 /* a row that does not exist is not created */ 466 FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != 467 TALER_EXCHANGEDB_insert_kyc_failure ( 468 pg, 469 row + 1000, 470 &account.h_normalized, 471 "failing-provider", 472 "provider-account-2", 473 "legi-2", 474 "the provider said no", 475 TALER_EC_EXCHANGE_KYC_GENERIC_PROVIDER_UNEXPECTED_REPLY)); 476 FAILIF (2 != TDB_count (pg, 477 "FROM legitimization_processes")); 478 return 0; 479 } 480 481 482 /** 483 * A failed AML program marks its process finished with an error too. 484 * 485 * @param pg the database context 486 * @return 0 on success 487 */ 488 static int 489 check_aml_program_failure (struct TALER_EXCHANGEDB_PostgresContext *pg) 490 { 491 uint64_t row = 0; 492 493 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 494 TALER_EXCHANGEDB_insert_legitimization_process ( 495 pg, 496 &account.h_normalized, 497 2, 498 measure_row, 499 "aml-provider", 500 "provider-account-3", 501 "legi-3", 502 &row)); 503 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 504 TALER_EXCHANGEDB_insert_aml_program_failure ( 505 pg, 506 row, 507 &account.h_normalized, 508 "the AML program crashed", 509 TALER_EC_EXCHANGE_KYC_AML_PROGRAM_FAILURE)); 510 FAILIF (1 != TDB_count (pg, 511 "FROM legitimization_processes" 512 " WHERE finished" 513 " AND error_code=%u", 514 (unsigned int) 515 TALER_EC_EXCHANGE_KYC_AML_PROGRAM_FAILURE)); 516 /* Unlike insert_kyc_failure(), a row that does not exist is *created* 517 here rather than ignored -- the stored procedure would rather keep a 518 record of the failed AML program than lose it. */ 519 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 520 TALER_EXCHANGEDB_insert_aml_program_failure ( 521 pg, 522 row + 1000, 523 &account.h_normalized, 524 "the AML program crashed", 525 TALER_EC_EXCHANGE_KYC_AML_PROGRAM_FAILURE)); 526 FAILIF (4 != TDB_count (pg, 527 "FROM legitimization_processes")); 528 return 0; 529 } 530 531 532 /** 533 * The reference listing reports every provider that worked on the 534 * account. 535 * 536 * @param pg the database context 537 * @return 0 on success 538 */ 539 static int 540 check_references (struct TALER_EXCHANGEDB_PostgresContext *pg) 541 { 542 struct ReferenceContext ctx; 543 544 memset (&ctx, 545 0, 546 sizeof (ctx)); 547 ctx.provider = "aml-provider"; 548 FAILIF (0 >= 549 TALER_EXCHANGEDB_iterate_kyc_references (pg, 550 &account.h_normalized, 551 &reference_cb, 552 &ctx)); 553 FAILIF_C (1 != ctx.matched, 554 GNUNET_free (ctx.user_id); GNUNET_free (ctx.legi_id)); 555 FAILIF_C (4 != ctx.total, 556 GNUNET_free (ctx.user_id); GNUNET_free (ctx.legi_id)); 557 GNUNET_free (ctx.user_id); 558 GNUNET_free (ctx.legi_id); 559 560 /* an account nobody checked has no references */ 561 { 562 struct TALER_NormalizedPaytoHashP other; 563 564 TDB_FILL (other, 565 98); 566 memset (&ctx, 567 0, 568 sizeof (ctx)); 569 FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != 570 TALER_EXCHANGEDB_iterate_kyc_references (pg, 571 &other, 572 &reference_cb, 573 &ctx)); 574 FAILIF (0 != ctx.total); 575 } 576 return 0; 577 } 578 579 580 /** 581 * Process initiation is reserved atomically, completed only by the owner, 582 * and restarted after its provider-side expiration. 583 * 584 * @param pg the database context 585 * @return 0 on success 586 */ 587 static int 588 check_reservation (struct TALER_EXCHANGEDB_PostgresContext *pg) 589 { 590 const char *provider = "reservation-provider"; 591 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); 592 struct GNUNET_TIME_Absolute lease_expiration 593 = GNUNET_TIME_absolute_add (now, 594 GNUNET_TIME_UNIT_MINUTES); 595 struct GNUNET_TIME_Absolute process_expiration 596 = GNUNET_TIME_absolute_add (now, 597 GNUNET_TIME_UNIT_HOURS); 598 struct GNUNET_TIME_Absolute start_time; 599 struct GNUNET_TIME_Absolute other_start_time; 600 struct GNUNET_TIME_Absolute restart_time; 601 struct GNUNET_TIME_Absolute restart_lease; 602 enum TALER_EXCHANGEDB_KycProcessReservationState state; 603 uint64_t row; 604 uint64_t other_row; 605 char *redirect_url = NULL; 606 607 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 608 TALER_EXCHANGEDB_do_reserve_legitimization_process ( 609 pg, 610 &account.h_normalized, 611 3, 612 measure_row, 613 provider, 614 now, 615 lease_expiration, 616 &row, 617 &start_time, 618 &redirect_url, 619 &state)); 620 FAILIF (TALER_EXCHANGEDB_KPRS_OWNER != state); 621 FAILIF (NULL != redirect_url); 622 623 /* A concurrent request must wait for the reservation owner. */ 624 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 625 TALER_EXCHANGEDB_do_reserve_legitimization_process ( 626 pg, 627 &account.h_normalized, 628 3, 629 measure_row, 630 provider, 631 now, 632 lease_expiration, 633 &other_row, 634 &other_start_time, 635 &redirect_url, 636 &state)); 637 FAILIF (TALER_EXCHANGEDB_KPRS_BUSY != state); 638 FAILIF (row != other_row); 639 FAILIF (start_time.abs_value_us != other_start_time.abs_value_us); 640 FAILIF (NULL != redirect_url); 641 642 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 643 TALER_EXCHANGEDB_complete_legitimization_process_start ( 644 pg, 645 row, 646 start_time, 647 provider, 648 &account.h_normalized, 649 "provider-account-reservation", 650 "provider-process-reservation", 651 "https://kyc.example/reserved", 652 process_expiration, 653 TALER_EC_NONE, 654 NULL, 655 false)); 656 657 /* Once initiation completed, all requests reuse its redirect. */ 658 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 659 TALER_EXCHANGEDB_do_reserve_legitimization_process ( 660 pg, 661 &account.h_normalized, 662 3, 663 measure_row, 664 provider, 665 now, 666 lease_expiration, 667 &other_row, 668 &other_start_time, 669 &redirect_url, 670 &state)); 671 FAILIF (TALER_EXCHANGEDB_KPRS_READY != state); 672 FAILIF (row != other_row); 673 FAILIF (NULL == redirect_url); 674 FAILIF_C (0 != strcmp (redirect_url, 675 "https://kyc.example/reserved"), 676 GNUNET_free (redirect_url)); 677 GNUNET_free (redirect_url); 678 redirect_url = NULL; 679 680 /* A callback from a superseded owner cannot overwrite the process. */ 681 other_start_time = GNUNET_TIME_absolute_add ( 682 start_time, 683 GNUNET_TIME_UNIT_SECONDS); 684 FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != 685 TALER_EXCHANGEDB_complete_legitimization_process_start ( 686 pg, 687 row, 688 other_start_time, 689 provider, 690 &account.h_normalized, 691 NULL, 692 NULL, 693 "https://kyc.example/late", 694 process_expiration, 695 TALER_EC_NONE, 696 NULL, 697 false)); 698 699 /* Expiration makes the next request the owner of a fresh start. */ 700 restart_time = GNUNET_TIME_absolute_add ( 701 process_expiration, 702 GNUNET_TIME_UNIT_SECONDS); 703 restart_lease = GNUNET_TIME_absolute_add ( 704 restart_time, 705 GNUNET_TIME_UNIT_MINUTES); 706 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 707 TALER_EXCHANGEDB_do_reserve_legitimization_process ( 708 pg, 709 &account.h_normalized, 710 3, 711 measure_row, 712 provider, 713 restart_time, 714 restart_lease, 715 &other_row, 716 &other_start_time, 717 &redirect_url, 718 &state)); 719 FAILIF (TALER_EXCHANGEDB_KPRS_OWNER != state); 720 FAILIF (row != other_row); 721 FAILIF (start_time.abs_value_us == other_start_time.abs_value_us); 722 FAILIF (NULL != redirect_url); 723 return 0; 724 } 725 726 727 /** 728 * The checks to run, in order. 729 */ 730 static const struct TDB_Test tests[] = { 731 { "legitimization-processes-empty", 732 &check_empty }, 733 { "legitimization-processes-start", 734 &check_start }, 735 { "legitimization-processes-update", 736 &check_update }, 737 { "legitimization-processes-kyc-failure", 738 &check_kyc_failure }, 739 { "legitimization-processes-aml-program-failure", 740 &check_aml_program_failure }, 741 { "legitimization-processes-references", 742 &check_references }, 743 { "legitimization-processes-reservation", 744 &check_reservation }, 745 { NULL, NULL } 746 }; 747 748 749 int 750 main (int argc, 751 char *const *argv) 752 { 753 int ret; 754 755 ret = TDB_main (argc, 756 argv, 757 "test-legitimization-processes", 758 "Tests for the exchangedb `legitimization_processes' table", 759 tests); 760 TDB_account_free (&account); 761 return ret; 762 } 763 764 765 /* end of test_legitimization_processes.c */