LCOV - code coverage report
Current view: top level - exchangedb - test_kycauths_in.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 130 130
Test Date: 2026-09-11 18:55:36 Functions: 100.0 % 8 8

            Line data    Source code
       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_kycauths_in.c
      18              :  * @brief tests for the exchangedb functions whose primary table is
      19              :  *        `kycauths_in`
      20              :  * @author Christian Grothoff
      21              :  *
      22              :  * Covers #TALER_EXCHANGEDB_do_import_credits() (for its KYC-auth half; the
      23              :  * reserve half is in test_reserves_in.c),
      24              :  * #TALER_EXCHANGEDB_iterate_kycauth_in_above_serial_id_by_account() and
      25              :  * #TALER_EXCHANGEDB_iterate_exchange_kycauth_transfers().
      26              :  *
      27              :  * A KYC-auth transfer carries an account public key in its wire subject.
      28              :  * The import creates the `kyc_targets` and `wire_targets` rows for the
      29              :  * debited account on first sight and only sets `target_pub` afterwards, so
      30              :  * the checks import from the same account twice.  The primary key is
      31              :  * (account, wire reference), which is what makes a re-import a no-op.
      32              :  */
      33              : #include "test_common.h"
      34              : #include "exchange-database/begin_shard.h"
      35              : #include "exchange-database/do_import_credits.h"
      36              : #include "exchange-database/iterate_exchange_kycauth_transfers.h"
      37              : #include "exchange-database/iterate_kycauth_in_above_serial_id_by_account.h"
      38              : 
      39              : 
      40              : /**
      41              :  * Account the first two transfers come from.
      42              :  */
      43              : #define PAYTO_A "payto://x-taler-bank/localhost/ka-a?receiver-name=A"
      44              : 
      45              : /**
      46              :  * Account the third transfer comes from.
      47              :  */
      48              : #define PAYTO_B "payto://x-taler-bank/localhost/ka-b?receiver-name=B"
      49              : 
      50              : 
      51              : /**
      52              :  * Closure for #kycauth_cb().
      53              :  */
      54              : struct AuthContext
      55              : {
      56              :   /**
      57              :    * How many rows did the callback see?
      58              :    */
      59              :   unsigned int total;
      60              : 
      61              :   /**
      62              :    * Stop after this many rows; 0 for no limit.
      63              :    */
      64              :   unsigned int stop_after;
      65              : 
      66              :   /**
      67              :    * Account key we are looking for, NULL to match nothing.
      68              :    */
      69              :   const union TALER_AccountPublicKeyP *account_pub;
      70              : 
      71              :   /**
      72              :    * How many times did we see @e account_pub?
      73              :    */
      74              :   unsigned int matched;
      75              : 
      76              :   /**
      77              :    * Credit reported for @e account_pub.
      78              :    */
      79              :   struct TALER_Amount credit;
      80              : 
      81              :   /**
      82              :    * Sender account reported for @e account_pub, owned by this struct.
      83              :    */
      84              :   char *sender;
      85              : };
      86              : 
      87              : 
      88              : /**
      89              :  * Callback for #TALER_EXCHANGEDB_iterate_kycauth_in_above_serial_id_by_account().
      90              :  *
      91              :  * @param cls a `struct AuthContext *`
      92              :  * @param rowid row of the transfer
      93              :  * @param account_pub key the transfer associated with the account
      94              :  * @param credit amount that was transferred
      95              :  * @param sender_account_details account the money came from
      96              :  * @param wire_reference bank's identifier for the transfer
      97              :  * @param execution_date when the transfer was made
      98              :  * @return #GNUNET_OK to continue, #GNUNET_SYSERR to stop
      99              :  */
     100              : static enum GNUNET_GenericReturnValue
     101            5 : kycauth_cb (void *cls,
     102              :             uint64_t rowid,
     103              :             const union TALER_AccountPublicKeyP *account_pub,
     104              :             const struct TALER_Amount *credit,
     105              :             const struct TALER_FullPayto sender_account_details,
     106              :             uint64_t wire_reference,
     107              :             struct GNUNET_TIME_Timestamp execution_date)
     108              : {
     109            5 :   struct AuthContext *ctx = cls;
     110              : 
     111              :   (void) rowid;
     112              :   (void) wire_reference;
     113              :   (void) execution_date;
     114            5 :   ctx->total++;
     115            5 :   if ( (NULL != ctx->account_pub) &&
     116            4 :        (0 == GNUNET_memcmp (account_pub,
     117              :                             ctx->account_pub)) )
     118              :   {
     119            2 :     ctx->matched++;
     120            2 :     ctx->credit = *credit;
     121            2 :     GNUNET_free (ctx->sender);
     122            2 :     ctx->sender = (NULL == sender_account_details.full_payto)
     123              :       ? NULL
     124            2 :       : GNUNET_strdup (sender_account_details.full_payto);
     125              :   }
     126            5 :   if ( (0 != ctx->stop_after) &&
     127            1 :        (ctx->total >= ctx->stop_after) )
     128            1 :     return GNUNET_SYSERR;
     129            4 :   return GNUNET_OK;
     130              : }
     131              : 
     132              : 
     133              : /**
     134              :  * Closure for #transfer_cb().
     135              :  */
     136              : struct TransferContext
     137              : {
     138              :   /**
     139              :    * How many transfers did the callback see?
     140              :    */
     141              :   unsigned int total;
     142              : 
     143              :   /**
     144              :    * Row of the first transfer seen.
     145              :    */
     146              :   uint64_t first_row;
     147              : 
     148              :   /**
     149              :    * Sum of the whole-unit parts of the amounts seen.
     150              :    */
     151              :   uint64_t value_sum;
     152              : };
     153              : 
     154              : 
     155              : /**
     156              :  * Callback for #TALER_EXCHANGEDB_iterate_exchange_kycauth_transfers().
     157              :  *
     158              :  * @param cls a `struct TransferContext *`
     159              :  * @param row_id row of the transfer
     160              :  * @param payto_uri account the money came from
     161              :  * @param execution_time when the transfer was made
     162              :  * @param amount amount that was transferred
     163              :  */
     164              : static void
     165           11 : transfer_cb (void *cls,
     166              :              uint64_t row_id,
     167              :              const char *payto_uri,
     168              :              struct GNUNET_TIME_Absolute execution_time,
     169              :              const struct TALER_Amount *amount)
     170              : {
     171           11 :   struct TransferContext *ctx = cls;
     172              : 
     173              :   (void) payto_uri;
     174              :   (void) execution_time;
     175           11 :   if (0 == ctx->total++)
     176            5 :     ctx->first_row = row_id;
     177           11 :   ctx->value_sum += amount->value;
     178           11 : }
     179              : 
     180              : 
     181              : /**
     182              :  * Import one KYC authentication transfer, advancing a work shard of its
     183              :  * own along with it.
     184              :  *
     185              :  * @param pg the database context
     186              :  * @param job_name job whose shard to open and advance
     187              :  * @param account_name exchange bank account the transfer arrived at
     188              :  * @param payto account the money came from
     189              :  * @param seed seed for the account public key
     190              :  * @param wire_reference bank's identifier for the transfer
     191              :  * @param amount amount that was transferred, e.g. "10"
     192              :  * @param[out] account_pub set to the key the transfer carried
     193              :  * @return transaction status of the import
     194              :  */
     195              : static enum GNUNET_DB_QueryStatus
     196            4 : import_one (struct TALER_EXCHANGEDB_PostgresContext *pg,
     197              :             const char *job_name,
     198              :             const char *account_name,
     199              :             const char *payto,
     200              :             uint32_t seed,
     201              :             uint64_t wire_reference,
     202              :             const char *amount,
     203              :             union TALER_AccountPublicKeyP *account_pub)
     204              : {
     205            4 :   struct TALER_Amount balance = TDB_amount (amount);
     206              :   struct TALER_EXCHANGEDB_KycauthInInfo info;
     207              :   struct TALER_EXCHANGEDB_CreditBatch batch;
     208              :   uint64_t start;
     209              :   uint64_t end;
     210              :   uint64_t progress;
     211              : 
     212            4 :   GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
     213              :                  TALER_EXCHANGEDB_begin_shard (pg,
     214              :                                                job_name,
     215              :                                                GNUNET_TIME_UNIT_HOURS,
     216              :                                                1024,
     217              :                                                &start,
     218              :                                                &end,
     219              :                                                &progress));
     220            4 :   TDB_fill (account_pub,
     221              :             sizeof (*account_pub),
     222              :             seed);
     223            4 :   memset (&info,
     224              :           0,
     225              :           sizeof (info));
     226            4 :   info.account_pub = account_pub;
     227            4 :   info.balance = &balance;
     228            4 :   info.execution_time = GNUNET_TIME_timestamp_get ();
     229            4 :   info.sender_account_details.full_payto = (char *) payto;
     230            4 :   info.wire_reference = wire_reference;
     231            4 :   memset (&batch,
     232              :           0,
     233              :           sizeof (batch));
     234            4 :   batch.exchange_account_name = account_name;
     235            4 :   batch.kycauths = &info;
     236            4 :   batch.kycauths_length = 1;
     237            4 :   batch.job_name = job_name;
     238            4 :   batch.shard_start = start;
     239            4 :   batch.shard_end = end;
     240            4 :   batch.progress_row = end;
     241            4 :   batch.lease = GNUNET_TIME_UNIT_HOURS;
     242            4 :   return TALER_EXCHANGEDB_do_import_credits (pg,
     243              :                                              &batch,
     244              :                                              NULL);
     245              : }
     246              : 
     247              : 
     248              : /**
     249              :  * Nothing is known while the table is empty.
     250              :  *
     251              :  * @param pg the database context
     252              :  * @return 0 on success
     253              :  */
     254              : static int
     255            1 : check_empty (struct TALER_EXCHANGEDB_PostgresContext *pg)
     256              : {
     257            1 :   struct AuthContext ctx = { 0 };
     258            1 :   struct TransferContext tctx = { 0 };
     259            1 :   struct TALER_Amount zero = TDB_amount ("0");
     260              : 
     261            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     262              :           TALER_EXCHANGEDB_iterate_kycauth_in_above_serial_id_by_account (
     263              :             pg,
     264              :             "exchange-account-1",
     265              :             0,
     266              :             &kycauth_cb,
     267              :             &ctx));
     268            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     269              :           TALER_EXCHANGEDB_iterate_exchange_kycauth_transfers (pg,
     270              :                                                                &zero,
     271              :                                                                0,
     272              :                                                                10,
     273              :                                                                NULL,
     274              :                                                                &transfer_cb,
     275              :                                                                &tctx));
     276            1 :   FAILIF (0 != ctx.total);
     277            1 :   FAILIF (0 != tctx.total);
     278            1 :   FAILIF (0 != TDB_count (pg,
     279              :                           "FROM kycauths_in"));
     280            1 :   return 0;
     281              : }
     282              : 
     283              : 
     284              : /**
     285              :  * Importing a transfer registers the account key and creates the account
     286              :  * rows; importing it again is a no-op.
     287              :  *
     288              :  * @param pg the database context
     289              :  * @return 0 on success
     290              :  */
     291              : static int
     292            1 : check_import (struct TALER_EXCHANGEDB_PostgresContext *pg)
     293              : {
     294              :   union TALER_AccountPublicKeyP account_pub;
     295              :   struct AuthContext ctx;
     296            1 :   struct TALER_Amount expect = TDB_amount ("10");
     297              :   char *hex;
     298              : 
     299            1 :   FAILIF (0 >
     300              :           import_one (pg,
     301              :                       "ka-job-a",
     302              :                       "exchange-account-1",
     303              :                       PAYTO_A,
     304              :                       10,
     305              :                       1,
     306              :                       "10",
     307              :                       &account_pub));
     308            1 :   FAILIF (1 != TDB_count (pg,
     309              :                           "FROM kycauths_in"));
     310              :   /* the account is now known and carries the key from the wire subject */
     311            1 :   hex = TDB_hex (&account_pub,
     312              :                  sizeof (account_pub));
     313            1 :   FAILIF_C (1 != TDB_count (pg,
     314              :                             "FROM kyc_targets"
     315              :                             " WHERE target_pub=decode('%s','hex')",
     316              :                             hex),
     317              :             GNUNET_free (hex));
     318            1 :   GNUNET_free (hex);
     319            1 :   FAILIF (1 != TDB_count (pg,
     320              :                           "FROM wire_targets"));
     321              : 
     322              :   /* the same transfer again: the primary key is (account, wire reference) */
     323            1 :   FAILIF (0 >
     324              :           import_one (pg,
     325              :                       "ka-job-a",
     326              :                       "exchange-account-1",
     327              :                       PAYTO_A,
     328              :                       10,
     329              :                       1,
     330              :                       "10",
     331              :                       &account_pub));
     332            1 :   FAILIF (1 != TDB_count (pg,
     333              :                           "FROM kycauths_in"));
     334              : 
     335            1 :   memset (&ctx,
     336              :           0,
     337              :           sizeof (ctx));
     338            1 :   ctx.account_pub = &account_pub;
     339            1 :   FAILIF (0 >=
     340              :           TALER_EXCHANGEDB_iterate_kycauth_in_above_serial_id_by_account (
     341              :             pg,
     342              :             "exchange-account-1",
     343              :             0,
     344              :             &kycauth_cb,
     345              :             &ctx));
     346            1 :   FAILIF_C (1 != ctx.matched,
     347              :             GNUNET_free (ctx.sender));
     348            1 :   FAILIF_C (0 != TALER_amount_cmp (&ctx.credit,
     349              :                                    &expect),
     350              :             GNUNET_free (ctx.sender));
     351            1 :   FAILIF_C (0 != strcmp (ctx.sender,
     352              :                          PAYTO_A),
     353              :             GNUNET_free (ctx.sender));
     354            1 :   GNUNET_free (ctx.sender);
     355            1 :   return 0;
     356              : }
     357              : 
     358              : 
     359              : /**
     360              :  * With several transfers on file the by-account iterator filters by the
     361              :  * exchange bank account and honours an aborting callback.
     362              :  *
     363              :  * @param pg the database context
     364              :  * @return 0 on success
     365              :  */
     366              : static int
     367            1 : check_iterate (struct TALER_EXCHANGEDB_PostgresContext *pg)
     368              : {
     369              :   union TALER_AccountPublicKeyP a2;
     370              :   union TALER_AccountPublicKeyP a3;
     371              :   struct AuthContext ctx;
     372              : 
     373              :   /* a second transfer from the same account, replacing the key */
     374            1 :   FAILIF (0 >
     375              :           import_one (pg,
     376              :                       "ka-job-a",
     377              :                       "exchange-account-1",
     378              :                       PAYTO_A,
     379              :                       11,
     380              :                       2,
     381              :                       "2",
     382              :                       &a2));
     383              :   /* and one from a different account to a different exchange account */
     384            1 :   FAILIF (0 >
     385              :           import_one (pg,
     386              :                       "ka-job-b",
     387              :                       "exchange-account-2",
     388              :                       PAYTO_B,
     389              :                       12,
     390              :                       3,
     391              :                       "5",
     392              :                       &a3));
     393            1 :   FAILIF (3 != TDB_count (pg,
     394              :                           "FROM kycauths_in"));
     395              :   /* the second transfer from PAYTO_A took over its target_pub */
     396              :   {
     397            1 :     char *hex = TDB_hex (&a2,
     398              :                          sizeof (a2));
     399              : 
     400            1 :     FAILIF_C (1 != TDB_count (pg,
     401              :                               "FROM kyc_targets"
     402              :                               " WHERE target_pub=decode('%s','hex')",
     403              :                               hex),
     404              :               GNUNET_free (hex));
     405            1 :     GNUNET_free (hex);
     406              :   }
     407              : 
     408            1 :   memset (&ctx,
     409              :           0,
     410              :           sizeof (ctx));
     411            1 :   ctx.account_pub = &a3;
     412            1 :   FAILIF (2 !=
     413              :           TALER_EXCHANGEDB_iterate_kycauth_in_above_serial_id_by_account (
     414              :             pg,
     415              :             "exchange-account-1",
     416              :             0,
     417              :             &kycauth_cb,
     418              :             &ctx));
     419            1 :   FAILIF_C (0 != ctx.matched,
     420              :             GNUNET_free (ctx.sender));
     421            1 :   GNUNET_free (ctx.sender);
     422              : 
     423            1 :   memset (&ctx,
     424              :           0,
     425              :           sizeof (ctx));
     426            1 :   ctx.account_pub = &a3;
     427            1 :   FAILIF (1 !=
     428              :           TALER_EXCHANGEDB_iterate_kycauth_in_above_serial_id_by_account (
     429              :             pg,
     430              :             "exchange-account-2",
     431              :             0,
     432              :             &kycauth_cb,
     433              :             &ctx));
     434            1 :   FAILIF_C (1 != ctx.matched,
     435              :             GNUNET_free (ctx.sender));
     436            1 :   FAILIF_C (0 != strcmp (ctx.sender,
     437              :                          PAYTO_B),
     438              :             GNUNET_free (ctx.sender));
     439            1 :   GNUNET_free (ctx.sender);
     440              : 
     441              :   /* an exchange account nobody wired to */
     442            1 :   memset (&ctx,
     443              :           0,
     444              :           sizeof (ctx));
     445            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     446              :           TALER_EXCHANGEDB_iterate_kycauth_in_above_serial_id_by_account (
     447              :             pg,
     448              :             "exchange-account-nowhere",
     449              :             0,
     450              :             &kycauth_cb,
     451              :             &ctx));
     452            1 :   FAILIF (0 != ctx.total);
     453              : 
     454              :   /* the serial bound is inclusive, so a bound past the end finds nothing */
     455            1 :   memset (&ctx,
     456              :           0,
     457              :           sizeof (ctx));
     458            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     459              :           TALER_EXCHANGEDB_iterate_kycauth_in_above_serial_id_by_account (
     460              :             pg,
     461              :             "exchange-account-1",
     462              :             1000,
     463              :             &kycauth_cb,
     464              :             &ctx));
     465            1 :   FAILIF (0 != ctx.total);
     466              : 
     467              :   /* a callback that gives up stops the iteration without erroring out */
     468            1 :   memset (&ctx,
     469              :           0,
     470              :           sizeof (ctx));
     471            1 :   ctx.stop_after = 1;
     472            1 :   FAILIF (2 !=
     473              :           TALER_EXCHANGEDB_iterate_kycauth_in_above_serial_id_by_account (
     474              :             pg,
     475              :             "exchange-account-1",
     476              :             0,
     477              :             &kycauth_cb,
     478              :             &ctx));
     479            1 :   FAILIF (1 != ctx.total);
     480            1 :   GNUNET_free (ctx.sender);
     481            1 :   return 0;
     482              : }
     483              : 
     484              : 
     485              : /**
     486              :  * The AML view of the same rows filters by amount and by account, and can
     487              :  * walk the table backwards.
     488              :  *
     489              :  * @param pg the database context
     490              :  * @return 0 on success
     491              :  */
     492              : static int
     493            1 : check_kycauth_transfers (struct TALER_EXCHANGEDB_PostgresContext *pg)
     494              : {
     495              :   struct TALER_NormalizedPayto npayto;
     496              :   struct TALER_NormalizedPaytoHashP h_payto;
     497            1 :   struct TALER_FullPayto payto_a = {
     498              :     .full_payto = (char *) PAYTO_A
     499              :   };
     500            1 :   struct TALER_Amount zero = TDB_amount ("0");
     501            1 :   struct TALER_Amount five = TDB_amount ("5");
     502            1 :   struct TALER_Amount huge = TDB_amount ("1000");
     503              :   struct TransferContext ctx;
     504              :   uint64_t lowest;
     505              : 
     506            1 :   memset (&ctx,
     507              :           0,
     508              :           sizeof (ctx));
     509            1 :   FAILIF (3 !=
     510              :           TALER_EXCHANGEDB_iterate_exchange_kycauth_transfers (pg,
     511              :                                                                &zero,
     512              :                                                                0,
     513              :                                                                10,
     514              :                                                                NULL,
     515              :                                                                &transfer_cb,
     516              :                                                                &ctx));
     517            1 :   FAILIF (10 + 2 + 5 != ctx.value_sum);
     518            1 :   lowest = ctx.first_row;
     519              : 
     520            1 :   memset (&ctx,
     521              :           0,
     522              :           sizeof (ctx));
     523            1 :   FAILIF (2 !=
     524              :           TALER_EXCHANGEDB_iterate_exchange_kycauth_transfers (pg,
     525              :                                                                &five,
     526              :                                                                0,
     527              :                                                                10,
     528              :                                                                NULL,
     529              :                                                                &transfer_cb,
     530              :                                                                &ctx));
     531            1 :   FAILIF (10 + 5 != ctx.value_sum);
     532              : 
     533            1 :   memset (&ctx,
     534              :           0,
     535              :           sizeof (ctx));
     536            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     537              :           TALER_EXCHANGEDB_iterate_exchange_kycauth_transfers (pg,
     538              :                                                                &huge,
     539              :                                                                0,
     540              :                                                                10,
     541              :                                                                NULL,
     542              :                                                                &transfer_cb,
     543              :                                                                &ctx));
     544            1 :   FAILIF (0 != ctx.total);
     545              : 
     546            1 :   npayto = TALER_payto_normalize (payto_a);
     547            1 :   GNUNET_assert (NULL != npayto.normalized_payto);
     548            1 :   TALER_normalized_payto_hash (npayto,
     549              :                                &h_payto);
     550            1 :   GNUNET_free (npayto.normalized_payto);
     551            1 :   memset (&ctx,
     552              :           0,
     553              :           sizeof (ctx));
     554            1 :   FAILIF (2 !=
     555              :           TALER_EXCHANGEDB_iterate_exchange_kycauth_transfers (pg,
     556              :                                                                &zero,
     557              :                                                                0,
     558              :                                                                10,
     559              :                                                                &h_payto,
     560              :                                                                &transfer_cb,
     561              :                                                                &ctx));
     562            1 :   FAILIF (10 + 2 != ctx.value_sum);
     563              : 
     564            1 :   memset (&ctx,
     565              :           0,
     566              :           sizeof (ctx));
     567            1 :   FAILIF (1 !=
     568              :           TALER_EXCHANGEDB_iterate_exchange_kycauth_transfers (pg,
     569              :                                                                &zero,
     570              :                                                                0,
     571              :                                                                1,
     572              :                                                                NULL,
     573              :                                                                &transfer_cb,
     574              :                                                                &ctx));
     575            1 :   FAILIF (lowest != ctx.first_row);
     576              : 
     577            1 :   memset (&ctx,
     578              :           0,
     579              :           sizeof (ctx));
     580            1 :   FAILIF (3 !=
     581              :           TALER_EXCHANGEDB_iterate_exchange_kycauth_transfers (pg,
     582              :                                                                &zero,
     583              :                                                                1000,
     584              :                                                                -10,
     585              :                                                                NULL,
     586              :                                                                &transfer_cb,
     587              :                                                                &ctx));
     588            1 :   FAILIF (lowest == ctx.first_row);
     589            1 :   FAILIF (10 + 2 + 5 != ctx.value_sum);
     590            1 :   return 0;
     591              : }
     592              : 
     593              : 
     594              : /**
     595              :  * The checks to run, in order.
     596              :  */
     597              : static const struct TDB_Test tests[] = {
     598              :   { "kycauths-in-empty",
     599              :     &check_empty },
     600              :   { "kycauths-in-import",
     601              :     &check_import },
     602              :   { "kycauths-in-iterate",
     603              :     &check_iterate },
     604              :   { "kycauths-in-transfers",
     605              :     &check_kycauth_transfers },
     606              :   { NULL, NULL }
     607              : };
     608              : 
     609              : 
     610              : int
     611            1 : main (int argc,
     612              :       char *const *argv)
     613              : {
     614            1 :   return TDB_main (argc,
     615              :                    argv,
     616              :                    "test-kycauths-in",
     617              :                    "Tests for the exchangedb `kycauths_in' table",
     618              :                    tests);
     619              : }
     620              : 
     621              : 
     622              : /* end of test_kycauths_in.c */
        

Generated by: LCOV version 2.0-1