exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

test_kyc_alerts.c (7040B)


      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_kyc_alerts.c
     18  * @brief tests for the exchangedb functions whose primary table is
     19  *        `kyc_alerts`
     20  * @author Christian Grothoff
     21  *
     22  * Covers #TALER_EXCHANGEDB_do_drain_kyc_alert().
     23  *
     24  * `kyc_alerts` is a work queue: the stored procedures that change the KYC
     25  * state of an account append a row, and taler-exchange-aggregator drains
     26  * it one row at a time.  Nothing exported writes to it directly, so the
     27  * rows here are produced through
     28  * #TALER_EXCHANGEDB_insert_aml_program_failure(), the cheapest of the
     29  * three producers.
     30  */
     31 #include "test_common.h"
     32 #include "exchange-database/do_drain_kyc_alert.h"
     33 #include "exchange-database/insert_aml_program_failure.h"
     34 
     35 
     36 /**
     37  * Trigger type the aggregator drains, and the only one any stored
     38  * procedure ever writes.
     39  */
     40 #define AGGREGATOR_TRIGGER 1
     41 
     42 
     43 /**
     44  * The two accounts we raise alerts for.
     45  */
     46 static struct TDB_Account account[2];
     47 
     48 
     49 /**
     50  * Nothing to drain while the queue is empty.
     51  *
     52  * @param pg the database context
     53  * @return 0 on success
     54  */
     55 static int
     56 check_empty (struct TALER_EXCHANGEDB_PostgresContext *pg)
     57 {
     58   struct TALER_NormalizedPaytoHashP h_payto;
     59 
     60   for (unsigned int i = 0; i < 2; i++)
     61     TDB_account (pg,
     62                  10 + i,
     63                  &account[i]);
     64   memset (&h_payto,
     65           0,
     66           sizeof (h_payto));
     67   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     68           TALER_EXCHANGEDB_do_drain_kyc_alert (pg,
     69                                                AGGREGATOR_TRIGGER,
     70                                                &h_payto));
     71   return 0;
     72 }
     73 
     74 
     75 /**
     76  * A KYC state change queues exactly one alert per account.
     77  *
     78  * @param pg the database context
     79  * @return 0 on success
     80  */
     81 static int
     82 check_raise (struct TALER_EXCHANGEDB_PostgresContext *pg)
     83 {
     84   for (unsigned int i = 0; i < 2; i++)
     85     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     86             TALER_EXCHANGEDB_insert_aml_program_failure (
     87               pg,
     88               0,
     89               &account[i].h_normalized,
     90               "no such AML program",
     91               TALER_EC_EXCHANGE_GENERIC_KYC_FAILED));
     92   FAILIF (2 != TDB_count (pg,
     93                           "FROM kyc_alerts"
     94                           " WHERE trigger_type=%d",
     95                           AGGREGATOR_TRIGGER));
     96 
     97   /* a second state change on an account that is already queued does not
     98      queue it twice */
     99   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    100           TALER_EXCHANGEDB_insert_aml_program_failure (
    101             pg,
    102             0,
    103             &account[0].h_normalized,
    104             "still no such AML program",
    105             TALER_EC_EXCHANGE_GENERIC_KYC_FAILED));
    106   FAILIF (2 != TDB_count (pg,
    107                           "FROM kyc_alerts"));
    108   return 0;
    109 }
    110 
    111 
    112 /**
    113  * Draining returns the queued accounts one by one and removes them.
    114  *
    115  * @param pg the database context
    116  * @return 0 on success
    117  */
    118 static int
    119 check_drain (struct TALER_EXCHANGEDB_PostgresContext *pg)
    120 {
    121   struct TALER_NormalizedPaytoHashP first;
    122   struct TALER_NormalizedPaytoHashP second;
    123 
    124   /* nobody listens for this trigger type, so the queue looks empty */
    125   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
    126           TALER_EXCHANGEDB_do_drain_kyc_alert (pg,
    127                                                AGGREGATOR_TRIGGER + 1,
    128                                                &first));
    129   FAILIF (2 != TDB_count (pg,
    130                           "FROM kyc_alerts"));
    131 
    132   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    133           TALER_EXCHANGEDB_do_drain_kyc_alert (pg,
    134                                                AGGREGATOR_TRIGGER,
    135                                                &first));
    136   FAILIF (1 != TDB_count (pg,
    137                           "FROM kyc_alerts"));
    138   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    139           TALER_EXCHANGEDB_do_drain_kyc_alert (pg,
    140                                                AGGREGATOR_TRIGGER,
    141                                                &second));
    142   FAILIF (0 != TDB_count (pg,
    143                           "FROM kyc_alerts"));
    144 
    145   /* both of our accounts came back, each exactly once */
    146   FAILIF (0 == GNUNET_memcmp (&first,
    147                               &second));
    148   for (unsigned int i = 0; i < 2; i++)
    149   {
    150     unsigned int seen = 0;
    151 
    152     if (0 == GNUNET_memcmp (&first,
    153                             &account[i].h_normalized))
    154       seen++;
    155     if (0 == GNUNET_memcmp (&second,
    156                             &account[i].h_normalized))
    157       seen++;
    158     FAILIF (1 != seen);
    159   }
    160 
    161   /* and the queue is empty again */
    162   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
    163           TALER_EXCHANGEDB_do_drain_kyc_alert (pg,
    164                                                AGGREGATOR_TRIGGER,
    165                                                &first));
    166   return 0;
    167 }
    168 
    169 
    170 /**
    171  * An account that was drained can be queued again.
    172  *
    173  * @param pg the database context
    174  * @return 0 on success
    175  */
    176 static int
    177 check_requeue (struct TALER_EXCHANGEDB_PostgresContext *pg)
    178 {
    179   struct TALER_NormalizedPaytoHashP h_payto;
    180 
    181   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    182           TALER_EXCHANGEDB_insert_aml_program_failure (
    183             pg,
    184             0,
    185             &account[1].h_normalized,
    186             "and again",
    187             TALER_EC_EXCHANGE_GENERIC_KYC_FAILED));
    188   FAILIF (1 != TDB_count (pg,
    189                           "FROM kyc_alerts"));
    190   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    191           TALER_EXCHANGEDB_do_drain_kyc_alert (pg,
    192                                                AGGREGATOR_TRIGGER,
    193                                                &h_payto));
    194   FAILIF (0 != GNUNET_memcmp (&h_payto,
    195                               &account[1].h_normalized));
    196   FAILIF (0 != TDB_count (pg,
    197                           "FROM kyc_alerts"));
    198   return 0;
    199 }
    200 
    201 
    202 /**
    203  * The checks to run, in order.
    204  */
    205 static const struct TDB_Test tests[] = {
    206   { "kyc-alerts-empty",
    207     &check_empty },
    208   { "kyc-alerts-raise",
    209     &check_raise },
    210   { "kyc-alerts-drain",
    211     &check_drain },
    212   { "kyc-alerts-requeue",
    213     &check_requeue },
    214   { NULL, NULL }
    215 };
    216 
    217 
    218 int
    219 main (int argc,
    220       char *const *argv)
    221 {
    222   int ret;
    223 
    224   ret = TDB_main (argc,
    225                   argv,
    226                   "test-kyc-alerts",
    227                   "Tests for the exchangedb `kyc_alerts' table",
    228                   tests);
    229   for (unsigned int i = 0; i < 2; i++)
    230     TDB_account_free (&account[i]);
    231   return ret;
    232 }
    233 
    234 
    235 /* end of test_kyc_alerts.c */