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

            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_legitimization_measures.c
      18              :  * @brief tests for the exchangedb functions whose primary table is
      19              :  *        `legitimization_measures`
      20              :  * @author Christian Grothoff
      21              :  *
      22              :  * Covers #TALER_EXCHANGEDB_do_trigger_kyc_rule_for_account(),
      23              :  * #TALER_EXCHANGEDB_insert_active_legitimization_measure(),
      24              :  * #TALER_EXCHANGEDB_insert_successor_measure(),
      25              :  * #TALER_EXCHANGEDB_get_pending_legitimization(),
      26              :  * #TALER_EXCHANGEDB_get_active_legitimization(),
      27              :  * #TALER_EXCHANGEDB_get_completed_legitimization(),
      28              :  * #TALER_EXCHANGEDB_get_kyc_status_by_token(),
      29              :  * #TALER_EXCHANGEDB_get_open_legitimization_measure(),
      30              :  * #TALER_EXCHANGEDB_get_legitimization_requirement_by_row() and
      31              :  * #TALER_EXCHANGEDB_iterate_aml_measures().
      32              :  *
      33              :  * A row of `legitimization_measures` is one set of KYC measures the
      34              :  * exchange put on an account.  It is keyed by the account's access token,
      35              :  * so `kyc_targets` has to exist first -- do_trigger_kyc_rule_for_account()
      36              :  * creates it when it has to.  Only one measure set per account is active
      37              :  * at a time: triggering a different set finishes the previous one.
      38              :  */
      39              : #include "test_common.h"
      40              : #include "exchange-database/do_trigger_kyc_rule_for_account.h"
      41              : #include "exchange-database/get_active_legitimization.h"
      42              : #include "exchange-database/get_completed_legitimization.h"
      43              : #include "exchange-database/get_kyc_status_by_token.h"
      44              : #include "exchange-database/get_legitimization_requirement_by_row.h"
      45              : #include "exchange-database/get_open_legitimization_measure.h"
      46              : #include "exchange-database/get_pending_legitimization.h"
      47              : #include "exchange-database/insert_active_legitimization_measure.h"
      48              : #include "exchange-database/insert_legitimization_process.h"
      49              : #include "exchange-database/insert_successor_measure.h"
      50              : #include "exchange-database/iterate_aml_measures.h"
      51              : 
      52              : 
      53              : /**
      54              :  * Account the checks put measures on.
      55              :  */
      56              : static struct TDB_Account account;
      57              : 
      58              : 
      59              : /**
      60              :  * Row of the measure set that check_trigger() created.
      61              :  */
      62              : static uint64_t measure_row;
      63              : 
      64              : 
      65              : /**
      66              :  * Key the account may use to authorise KYC work on itself.
      67              :  */
      68              : static union TALER_AccountPublicKeyP account_pub;
      69              : 
      70              : 
      71              : /**
      72              :  * Build a timestamp from a number of seconds since the epoch.
      73              :  *
      74              :  * @param secs seconds since the epoch
      75              :  * @return the timestamp
      76              :  */
      77              : static struct GNUNET_TIME_Timestamp
      78            4 : ts (uint64_t secs)
      79              : {
      80            4 :   struct GNUNET_TIME_Absolute abs = {
      81            4 :     .abs_value_us = secs * 1000LLU * 1000LLU
      82              :   };
      83              : 
      84            4 :   return GNUNET_TIME_absolute_to_timestamp (abs);
      85              : }
      86              : 
      87              : 
      88              : /**
      89              :  * Build a measure set naming @a check.
      90              :  *
      91              :  * @param check name of the check to demand
      92              :  * @return the measure set, to be freed with json_decref()
      93              :  */
      94              : static json_t *
      95            4 : make_measures (const char *check)
      96              : {
      97              :   json_t *j;
      98              : 
      99            4 :   j = GNUNET_JSON_PACK (
     100              :     GNUNET_JSON_pack_array_steal (
     101              :       "measures",
     102              :       json_pack ("[{s:s,s:s,s:s}]",
     103              :                  "check_name",
     104              :                  check,
     105              :                  "prog_name",
     106              :                  "skip",
     107              :                  "context",
     108              :                  "none")),
     109              :     GNUNET_JSON_pack_bool ("is_and_combinator",
     110              :                            true));
     111            4 :   GNUNET_assert (NULL != j);
     112            4 :   return j;
     113              : }
     114              : 
     115              : 
     116              : /**
     117              :  * Read the access token the database generated for our account.
     118              :  *
     119              :  * @param pg the database context
     120              :  * @param[out] access_token set to the account's access token
     121              :  */
     122              : static void
     123            3 : get_access_token (struct TALER_EXCHANGEDB_PostgresContext *pg,
     124              :                   struct TALER_AccountAccessTokenP *access_token)
     125              : {
     126            3 :   struct GNUNET_PQ_QueryParam params[] = {
     127            3 :     GNUNET_PQ_query_param_auto_from_type (&account.h_normalized),
     128              :     GNUNET_PQ_query_param_end
     129              :   };
     130            3 :   struct GNUNET_PQ_ResultSpec rs[] = {
     131            3 :     GNUNET_PQ_result_spec_auto_from_type ("access_token",
     132              :                                           access_token),
     133              :     GNUNET_PQ_result_spec_end
     134              :   };
     135              : 
     136            3 :   GNUNET_assert (GNUNET_OK ==
     137              :                  GNUNET_PQ_prepare_anon (pg->conn,
     138              :                                          "SELECT access_token"
     139              :                                          " FROM kyc_targets"
     140              :                                          " WHERE h_normalized_payto=$1;"));
     141            3 :   GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
     142              :                  GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
     143              :                                                            "",
     144              :                                                            params,
     145              :                                                            rs));
     146            3 : }
     147              : 
     148              : 
     149              : /**
     150              :  * Closure for #measure_cb().
     151              :  */
     152              : struct MeasureContext
     153              : {
     154              :   /**
     155              :    * How many measures did the callback see?
     156              :    */
     157              :   unsigned int total;
     158              : 
     159              :   /**
     160              :    * Row we are looking for, 0 to match nothing.
     161              :    */
     162              :   uint64_t measure_row;
     163              : 
     164              :   /**
     165              :    * How many times did we see it?
     166              :    */
     167              :   unsigned int matched;
     168              : 
     169              :   /**
     170              :    * Was it reported as finished?
     171              :    */
     172              :   bool is_finished;
     173              : 
     174              :   /**
     175              :    * Account it was reported for.
     176              :    */
     177              :   struct TALER_NormalizedPaytoHashP h_payto;
     178              : };
     179              : 
     180              : 
     181              : /**
     182              :  * Callback for #TALER_EXCHANGEDB_iterate_aml_measures().
     183              :  *
     184              :  * @param cls a `struct MeasureContext *`
     185              :  * @param h_payto account the measure applies to
     186              :  * @param start_time when the measure was imposed
     187              :  * @param jmeasures the measures
     188              :  * @param is_finished whether the measure was completed
     189              :  * @param measure_serial_id row of the measure
     190              :  */
     191              : static void
     192            9 : measure_cb (void *cls,
     193              :             struct TALER_NormalizedPaytoHashP *h_payto,
     194              :             struct GNUNET_TIME_Absolute start_time,
     195              :             const json_t *jmeasures,
     196              :             bool is_finished,
     197              :             uint64_t measure_serial_id)
     198              : {
     199            9 :   struct MeasureContext *ctx = cls;
     200              : 
     201              :   (void) start_time;
     202              :   (void) jmeasures;
     203            9 :   ctx->total++;
     204            9 :   if ( (0 != ctx->measure_row) &&
     205            0 :        (measure_serial_id == ctx->measure_row) )
     206              :   {
     207            0 :     ctx->matched++;
     208            0 :     ctx->is_finished = is_finished;
     209            0 :     ctx->h_payto = *h_payto;
     210              :   }
     211            9 : }
     212              : 
     213              : 
     214              : /**
     215              :  * Nothing is known while the table is empty.
     216              :  *
     217              :  * @param pg the database context
     218              :  * @return 0 on success
     219              :  */
     220              : static int
     221            1 : check_empty (struct TALER_EXCHANGEDB_PostgresContext *pg)
     222              : {
     223              :   struct TALER_NormalizedPaytoHashP h_payto;
     224              :   struct TALER_AccountAccessTokenP access_token;
     225              :   struct GNUNET_TIME_Absolute start_time;
     226            1 :   struct MeasureContext ctx = { 0 };
     227            1 :   json_t *jmeasures = NULL;
     228              :   uint64_t row;
     229              :   bool is_finished;
     230              :   bool is_wallet;
     231              : 
     232            1 :   TDB_FILL (h_payto,
     233              :             1);
     234            1 :   TDB_FILL (access_token,
     235              :             1);
     236            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     237              :           TALER_EXCHANGEDB_get_pending_legitimization (pg,
     238              :                                                        1,
     239              :                                                        &access_token,
     240              :                                                        &h_payto,
     241              :                                                        &jmeasures,
     242              :                                                        &is_finished,
     243              :                                                        &is_wallet));
     244            1 :   FAILIF (NULL != jmeasures);
     245            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     246              :           TALER_EXCHANGEDB_get_kyc_status_by_token (pg,
     247              :                                                     &access_token,
     248              :                                                     &row,
     249              :                                                     &jmeasures));
     250            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     251              :           TALER_EXCHANGEDB_get_open_legitimization_measure (pg,
     252              :                                                             &h_payto,
     253              :                                                             &row,
     254              :                                                             &start_time));
     255            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     256              :           TALER_EXCHANGEDB_iterate_aml_measures (pg,
     257              :                                                  NULL,
     258              :                                                  TALER_EXCHANGE_YNA_ALL,
     259              :                                                  0,
     260              :                                                  10,
     261              :                                                  &measure_cb,
     262              :                                                  &ctx));
     263            1 :   FAILIF (0 != ctx.total);
     264            1 :   return 0;
     265              : }
     266              : 
     267              : 
     268              : /**
     269              :  * Triggering a rule creates the account and the measure set.
     270              :  *
     271              :  * @param pg the database context
     272              :  * @return 0 on success
     273              :  */
     274              : static int
     275            1 : check_trigger (struct TALER_EXCHANGEDB_PostgresContext *pg)
     276              : {
     277              :   struct TALER_NormalizedPayto npayto;
     278              :   struct TALER_FullPayto payto;
     279              :   struct TALER_NormalizedPaytoHashP h_payto;
     280              :   struct TALER_AccountAccessTokenP access_token;
     281              :   struct TALER_AccountAccessTokenP got_token;
     282              :   struct TALER_NormalizedPaytoHashP got_payto;
     283            1 :   json_t *jmeasures = make_measures ("verify-id");
     284            1 :   json_t *got = NULL;
     285            1 :   uint64_t row = 0;
     286            1 :   bool bad_kyc_auth = false;
     287            1 :   bool is_finished = true;
     288            1 :   bool is_wallet = true;
     289              : 
     290            1 :   payto.full_payto = (char *)
     291              :                      "payto://x-taler-bank/localhost/lm?receiver-name=LM";
     292            1 :   TALER_full_payto_hash (payto,
     293              :                          &account.h_full);
     294            1 :   npayto = TALER_payto_normalize (payto);
     295            1 :   GNUNET_assert (NULL != npayto.normalized_payto);
     296            1 :   TALER_normalized_payto_hash (npayto,
     297              :                                &h_payto);
     298            1 :   GNUNET_free (npayto.normalized_payto);
     299            1 :   account.payto.full_payto = GNUNET_strdup (payto.full_payto);
     300            1 :   account.h_normalized = h_payto;
     301              : 
     302            1 :   TDB_FILL (account_pub,
     303              :             42);
     304            1 :   FAILIF_C (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     305              :             TALER_EXCHANGEDB_do_trigger_kyc_rule_for_account (
     306              :               pg,
     307              :               payto,
     308              :               &h_payto,
     309              :               &account_pub,
     310              :               NULL,
     311              :               jmeasures,
     312              :               1,
     313              :               &row,
     314              :               &bad_kyc_auth),
     315              :             json_decref (jmeasures));
     316            1 :   FAILIF_C (0 == row,
     317              :             json_decref (jmeasures));
     318              :   /* The account was not known, so there was no key to match against; the
     319              :      function reports that even though it just set one. */
     320            1 :   FAILIF_C (! bad_kyc_auth,
     321              :             json_decref (jmeasures));
     322            1 :   measure_row = row;
     323            1 :   FAILIF_C (1 != TDB_count (pg,
     324              :                             "FROM legitimization_measures"),
     325              :             json_decref (jmeasures));
     326              :   /* the account was created along the way */
     327            1 :   FAILIF_C (1 != TDB_count (pg,
     328              :                             "FROM kyc_targets"),
     329              :             json_decref (jmeasures));
     330            1 :   FAILIF_C (1 != TDB_count (pg,
     331              :                             "FROM wire_targets"),
     332              :             json_decref (jmeasures));
     333              : 
     334              :   /* the measure set can be read back by its row... */
     335            1 :   FAILIF_C (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     336              :             TALER_EXCHANGEDB_get_pending_legitimization (pg,
     337              :                                                          row,
     338              :                                                          &got_token,
     339              :                                                          &got_payto,
     340              :                                                          &got,
     341              :                                                          &is_finished,
     342              :                                                          &is_wallet),
     343              :             json_decref (jmeasures));
     344            1 :   FAILIF_C (0 != GNUNET_memcmp (&got_payto,
     345              :                                 &h_payto),
     346              :             json_decref (got); json_decref (jmeasures));
     347            1 :   FAILIF_C (is_finished,
     348              :             json_decref (got); json_decref (jmeasures));
     349            1 :   FAILIF_C (is_wallet,
     350              :             json_decref (got); json_decref (jmeasures));
     351            1 :   FAILIF_C (1 != json_equal (got,
     352              :                              jmeasures),
     353              :             json_decref (got); json_decref (jmeasures));
     354            1 :   json_decref (got);
     355            1 :   got = NULL;
     356              : 
     357              :   /* ...and by the account's access token */
     358            1 :   get_access_token (pg,
     359              :                     &access_token);
     360            1 :   FAILIF_C (0 != GNUNET_memcmp (&got_token,
     361              :                                 &access_token),
     362              :             json_decref (jmeasures));
     363            1 :   FAILIF_C (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     364              :             TALER_EXCHANGEDB_get_kyc_status_by_token (pg,
     365              :                                                       &access_token,
     366              :                                                       &row,
     367              :                                                       &got),
     368              :             json_decref (jmeasures));
     369            1 :   FAILIF_C (row != measure_row,
     370              :             json_decref (got); json_decref (jmeasures));
     371            1 :   json_decref (got);
     372              : 
     373              :   /* triggering the very same measure set again keeps the one row */
     374            1 :   FAILIF_C (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     375              :             TALER_EXCHANGEDB_do_trigger_kyc_rule_for_account (
     376              :               pg,
     377              :               payto,
     378              :               &h_payto,
     379              :               NULL,
     380              :               NULL,
     381              :               jmeasures,
     382              :               1,
     383              :               &row,
     384              :               &bad_kyc_auth),
     385              :             json_decref (jmeasures));
     386            1 :   FAILIF_C (row != measure_row,
     387              :             json_decref (jmeasures));
     388            1 :   FAILIF_C (1 != TDB_count (pg,
     389              :                             "FROM legitimization_measures"),
     390              :             json_decref (jmeasures));
     391            1 :   json_decref (jmeasures);
     392            1 :   return 0;
     393              : }
     394              : 
     395              : 
     396              : /**
     397              :  * A different measure set supersedes the previous one, which is marked
     398              :  * finished.
     399              :  *
     400              :  * @param pg the database context
     401              :  * @return 0 on success
     402              :  */
     403              : static int
     404            1 : check_supersede (struct TALER_EXCHANGEDB_PostgresContext *pg)
     405              : {
     406            1 :   json_t *jmeasures = make_measures ("verify-address");
     407            1 :   uint64_t row = 0;
     408            1 :   bool bad_kyc_auth = false;
     409              : 
     410            1 :   FAILIF_C (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     411              :             TALER_EXCHANGEDB_do_trigger_kyc_rule_for_account (
     412              :               pg,
     413              :               account.payto,
     414              :               &account.h_normalized,
     415              :               NULL,
     416              :               NULL,
     417              :               jmeasures,
     418              :               2,
     419              :               &row,
     420              :               &bad_kyc_auth),
     421              :             json_decref (jmeasures));
     422            1 :   json_decref (jmeasures);
     423            1 :   FAILIF (row == measure_row);
     424            1 :   FAILIF (2 != TDB_count (pg,
     425              :                           "FROM legitimization_measures"));
     426            1 :   FAILIF (1 != TDB_count (pg,
     427              :                           "FROM legitimization_measures"
     428              :                           " WHERE is_finished"));
     429            1 :   measure_row = row;
     430            1 :   return 0;
     431              : }
     432              : 
     433              : 
     434              : /**
     435              :  * The account's rule requirement and its open measure are reported.
     436              :  *
     437              :  * @param pg the database context
     438              :  * @return 0 on success
     439              :  */
     440              : static int
     441            1 : check_requirement (struct TALER_EXCHANGEDB_PostgresContext *pg)
     442              : {
     443              :   struct TALER_AccountAccessTokenP access_token;
     444              :   struct TALER_AccountAccessTokenP got_token;
     445              :   struct GNUNET_TIME_Absolute start_time;
     446              :   enum GNUNET_GenericReturnValue is_wallet;
     447            1 :   json_t *jrules = NULL;
     448            1 :   uint64_t rule_gen = 42;
     449            1 :   uint64_t row = 0;
     450            1 :   bool aml_review = true;
     451            1 :   bool kyc_required = false;
     452              : 
     453            1 :   get_access_token (pg,
     454              :                     &access_token);
     455            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     456              :           TALER_EXCHANGEDB_get_legitimization_requirement_by_row (
     457              :             pg,
     458              :             &account.h_normalized,
     459              :             &account_pub,
     460              :             &is_wallet,
     461              :             &got_token,
     462              :             &rule_gen,
     463              :             &jrules,
     464              :             &aml_review,
     465              :             &kyc_required));
     466            1 :   FAILIF_C (0 != GNUNET_memcmp (&got_token,
     467              :                                 &access_token),
     468              :             json_decref (jrules));
     469            1 :   FAILIF_C (GNUNET_NO != is_wallet,
     470              :             json_decref (jrules));
     471              :   /* no AML decision has been taken for the account */
     472            1 :   FAILIF_C (aml_review,
     473              :             json_decref (jrules));
     474            1 :   FAILIF_C (0 != rule_gen,
     475              :             json_decref (jrules));
     476              :   /* ...but a measure is pending, so KYC is required */
     477            1 :   FAILIF_C (! kyc_required,
     478              :             json_decref (jrules));
     479            1 :   json_decref (jrules);
     480              : 
     481              :   /* the exchange's own account of why it is holding back */
     482            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     483              :           TALER_EXCHANGEDB_get_open_legitimization_measure (
     484              :             pg,
     485              :             &account.h_normalized,
     486              :             &row,
     487              :             &start_time));
     488              :   /* the oldest undecided measure is the one from check_trigger() */
     489            1 :   FAILIF (0 == row);
     490            1 :   FAILIF (GNUNET_TIME_absolute_is_zero (start_time));
     491              : 
     492              :   /* an account nobody put a measure on has none */
     493              :   {
     494              :     struct TALER_NormalizedPaytoHashP other;
     495              : 
     496            1 :     TDB_FILL (other,
     497              :               98);
     498            1 :     FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     499              :             TALER_EXCHANGEDB_get_open_legitimization_measure (pg,
     500              :                                                               &other,
     501              :                                                               &row,
     502              :                                                               &start_time));
     503              :   }
     504            1 :   return 0;
     505              : }
     506              : 
     507              : 
     508              : /**
     509              :  * A legitimization process ties a measure set to the check it is
     510              :  * satisfying.
     511              :  *
     512              :  * @param pg the database context
     513              :  * @return 0 on success
     514              :  */
     515              : static int
     516            1 : check_process (struct TALER_EXCHANGEDB_PostgresContext *pg)
     517              : {
     518              :   struct TALER_AccountAccessTokenP access_token;
     519              :   struct TALER_NormalizedPaytoHashP h_payto;
     520            1 :   json_t *jmeasures = NULL;
     521            1 :   size_t attributes_len = 42;
     522            1 :   void *attributes = NULL;
     523            1 :   uint64_t process_row = 0;
     524            1 :   uint32_t measure_index = 99;
     525            1 :   bool is_finished = true;
     526            1 :   bool is_wallet = true;
     527              : 
     528            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     529              :           TALER_EXCHANGEDB_insert_legitimization_process (
     530              :             pg,
     531              :             &account.h_normalized,
     532              :             0,
     533              :             measure_row,
     534              :             "test-provider",
     535              :             "provider-account-1",
     536              :             "provider-legi-1",
     537              :             &process_row));
     538            1 :   FAILIF (0 == process_row);
     539              : 
     540            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     541              :           TALER_EXCHANGEDB_get_active_legitimization (pg,
     542              :                                                       process_row,
     543              :                                                       &measure_index,
     544              :                                                       &jmeasures));
     545            1 :   FAILIF_C (0 != measure_index,
     546              :             json_decref (jmeasures));
     547            1 :   FAILIF_C (NULL == jmeasures,
     548              :             json_decref (jmeasures));
     549            1 :   json_decref (jmeasures);
     550            1 :   jmeasures = NULL;
     551              : 
     552              :   /* a process that does not exist has no active measure */
     553            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     554              :           TALER_EXCHANGEDB_get_active_legitimization (pg,
     555              :                                                       process_row + 1000,
     556              :                                                       &measure_index,
     557              :                                                       &jmeasures));
     558              : 
     559              :   /* the completed view reaches the same measure through the process */
     560            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     561              :           TALER_EXCHANGEDB_get_completed_legitimization (pg,
     562              :                                                          measure_row,
     563              :                                                          0,
     564              :                                                          &access_token,
     565              :                                                          &h_payto,
     566              :                                                          &is_wallet,
     567              :                                                          &jmeasures,
     568              :                                                          &is_finished,
     569              :                                                          &attributes_len,
     570              :                                                          &attributes));
     571            1 :   FAILIF_C (0 != GNUNET_memcmp (&h_payto,
     572              :                                 &account.h_normalized),
     573              :             json_decref (jmeasures); GNUNET_free (attributes));
     574            1 :   FAILIF_C (is_finished,
     575              :             json_decref (jmeasures); GNUNET_free (attributes));
     576              :   /* no attributes have been collected yet */
     577            1 :   FAILIF_C (NULL != attributes,
     578              :             json_decref (jmeasures); GNUNET_free (attributes));
     579            1 :   json_decref (jmeasures);
     580            1 :   jmeasures = NULL;
     581              : 
     582              :   /* a measure index no process is working on is not found */
     583            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     584              :           TALER_EXCHANGEDB_get_completed_legitimization (pg,
     585              :                                                          measure_row,
     586              :                                                          7,
     587              :                                                          &access_token,
     588              :                                                          &h_payto,
     589              :                                                          &is_wallet,
     590              :                                                          &jmeasures,
     591              :                                                          &is_finished,
     592              :                                                          &attributes_len,
     593              :                                                          &attributes));
     594            1 :   return 0;
     595              : }
     596              : 
     597              : 
     598              : /**
     599              :  * A measure can also be created directly against an access token.
     600              :  *
     601              :  * @param pg the database context
     602              :  * @return 0 on success
     603              :  */
     604              : static int
     605            1 : check_insert_active (struct TALER_EXCHANGEDB_PostgresContext *pg)
     606              : {
     607              :   struct TALER_AccountAccessTokenP access_token;
     608            1 :   json_t *jmeasures = make_measures ("verify-phone");
     609            1 :   uint64_t row = 0;
     610              : 
     611            1 :   get_access_token (pg,
     612              :                     &access_token);
     613            1 :   FAILIF_C (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     614              :             TALER_EXCHANGEDB_insert_active_legitimization_measure (
     615              :               pg,
     616              :               &access_token,
     617              :               jmeasures,
     618              :               &row),
     619              :             json_decref (jmeasures));
     620            1 :   json_decref (jmeasures);
     621            1 :   FAILIF (0 == row);
     622            1 :   FAILIF (3 != TDB_count (pg,
     623              :                           "FROM legitimization_measures"));
     624              :   /* it becomes the one active measure for the account */
     625            1 :   FAILIF (1 != TDB_count (pg,
     626              :                           "FROM legitimization_measures"
     627              :                           " WHERE NOT is_finished"));
     628            1 :   measure_row = row;
     629              : 
     630            1 :   return 0;
     631              : }
     632              : 
     633              : 
     634              : /**
     635              :  * A successor measure replaces what is active for the account.
     636              :  *
     637              :  * @param pg the database context
     638              :  * @return 0 on success
     639              :  */
     640              : static int
     641            1 : check_successor (struct TALER_EXCHANGEDB_PostgresContext *pg)
     642              : {
     643              :   struct GNUNET_TIME_Timestamp last_date;
     644            1 :   json_t *jmeasures = make_measures ("verify-income");
     645            1 :   bool unknown_account = true;
     646              : 
     647            1 :   FAILIF_C (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     648              :             TALER_EXCHANGEDB_insert_successor_measure (
     649              :               pg,
     650              :               &account.h_normalized,
     651              :               ts (1600000000),
     652              :               "verify-income",
     653              :               jmeasures,
     654              :               &unknown_account,
     655              :               &last_date),
     656              :             json_decref (jmeasures));
     657            1 :   FAILIF_C (unknown_account,
     658              :             json_decref (jmeasures));
     659            1 :   FAILIF_C (4 != TDB_count (pg,
     660              :                             "FROM legitimization_measures"),
     661              :             json_decref (jmeasures));
     662              : 
     663              :   /* an older decision is ignored */
     664            1 :   FAILIF_C (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     665              :             TALER_EXCHANGEDB_insert_successor_measure (
     666              :               pg,
     667              :               &account.h_normalized,
     668              :               ts (1500000000),
     669              :               "verify-income",
     670              :               jmeasures,
     671              :               &unknown_account,
     672              :               &last_date),
     673              :             json_decref (jmeasures));
     674            1 :   FAILIF_C (GNUNET_TIME_timestamp_cmp (last_date,
     675              :                                        !=,
     676              :                                        ts (1600000000)),
     677              :             json_decref (jmeasures));
     678            1 :   FAILIF_C (4 != TDB_count (pg,
     679              :                             "FROM legitimization_measures"),
     680              :             json_decref (jmeasures));
     681              : 
     682              :   /* an account the exchange never saw is reported as unknown */
     683              :   {
     684              :     struct TALER_NormalizedPaytoHashP other;
     685              : 
     686            1 :     TDB_FILL (other,
     687              :               95);
     688            1 :     unknown_account = false;
     689            1 :     FAILIF_C (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     690              :               TALER_EXCHANGEDB_insert_successor_measure (
     691              :                 pg,
     692              :                 &other,
     693              :                 ts (1600000000),
     694              :                 "verify-income",
     695              :                 jmeasures,
     696              :                 &unknown_account,
     697              :                 &last_date),
     698              :               json_decref (jmeasures));
     699            1 :     FAILIF_C (! unknown_account,
     700              :               json_decref (jmeasures));
     701              :   }
     702            1 :   json_decref (jmeasures);
     703            1 :   return 0;
     704              : }
     705              : 
     706              : 
     707              : /**
     708              :  * The measure listing reports the account's measures, filtered.
     709              :  *
     710              :  * @param pg the database context
     711              :  * @return 0 on success
     712              :  */
     713              : static int
     714            1 : check_iterate (struct TALER_EXCHANGEDB_PostgresContext *pg)
     715              : {
     716              :   struct MeasureContext ctx;
     717              :   unsigned int all;
     718              : 
     719            1 :   memset (&ctx,
     720              :           0,
     721              :           sizeof (ctx));
     722            1 :   FAILIF (0 >=
     723              :           TALER_EXCHANGEDB_iterate_aml_measures (pg,
     724              :                                                  &account.h_normalized,
     725              :                                                  TALER_EXCHANGE_YNA_ALL,
     726              :                                                  0,
     727              :                                                  100,
     728              :                                                  &measure_cb,
     729              :                                                  &ctx));
     730            1 :   all = ctx.total;
     731            1 :   FAILIF (0 == all);
     732              : 
     733              :   /* the account filter matters */
     734              :   {
     735              :     struct TALER_NormalizedPaytoHashP other;
     736              : 
     737            1 :     TDB_FILL (other,
     738              :               94);
     739            1 :     memset (&ctx,
     740              :             0,
     741              :             sizeof (ctx));
     742            1 :     FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     743              :             TALER_EXCHANGEDB_iterate_aml_measures (pg,
     744              :                                                    &other,
     745              :                                                    TALER_EXCHANGE_YNA_ALL,
     746              :                                                    0,
     747              :                                                    100,
     748              :                                                    &measure_cb,
     749              :                                                    &ctx));
     750            1 :     FAILIF (0 != ctx.total);
     751              :   }
     752              : 
     753              :   /* only one measure is still open */
     754            1 :   memset (&ctx,
     755              :           0,
     756              :           sizeof (ctx));
     757            1 :   FAILIF (0 >=
     758              :           TALER_EXCHANGEDB_iterate_aml_measures (pg,
     759              :                                                  &account.h_normalized,
     760              :                                                  TALER_EXCHANGE_YNA_YES,
     761              :                                                  0,
     762              :                                                  100,
     763              :                                                  &measure_cb,
     764              :                                                  &ctx));
     765            1 :   FAILIF (1 != ctx.total);
     766              : 
     767              :   /* the finished ones make up the rest */
     768            1 :   memset (&ctx,
     769              :           0,
     770              :           sizeof (ctx));
     771            1 :   FAILIF (0 >=
     772              :           TALER_EXCHANGEDB_iterate_aml_measures (pg,
     773              :                                                  &account.h_normalized,
     774              :                                                  TALER_EXCHANGE_YNA_NO,
     775              :                                                  0,
     776              :                                                  100,
     777              :                                                  &measure_cb,
     778              :                                                  &ctx));
     779            1 :   FAILIF (all - 1 != ctx.total);
     780              : 
     781              :   /* the limit caps the result set */
     782            1 :   memset (&ctx,
     783              :           0,
     784              :           sizeof (ctx));
     785            1 :   FAILIF (1 !=
     786              :           TALER_EXCHANGEDB_iterate_aml_measures (pg,
     787              :                                                  NULL,
     788              :                                                  TALER_EXCHANGE_YNA_ALL,
     789              :                                                  0,
     790              :                                                  1,
     791              :                                                  &measure_cb,
     792              :                                                  &ctx));
     793            1 :   FAILIF (1 != ctx.total);
     794            1 :   return 0;
     795              : }
     796              : 
     797              : 
     798              : /**
     799              :  * The checks to run, in order.
     800              :  */
     801              : static const struct TDB_Test tests[] = {
     802              :   { "legitimization-measures-empty",
     803              :     &check_empty },
     804              :   { "legitimization-measures-trigger",
     805              :     &check_trigger },
     806              :   { "legitimization-measures-supersede",
     807              :     &check_supersede },
     808              :   { "legitimization-measures-requirement",
     809              :     &check_requirement },
     810              :   { "legitimization-measures-process",
     811              :     &check_process },
     812              :   { "legitimization-measures-insert-active",
     813              :     &check_insert_active },
     814              :   { "legitimization-measures-successor",
     815              :     &check_successor },
     816              :   { "legitimization-measures-iterate",
     817              :     &check_iterate },
     818              :   { NULL, NULL }
     819              : };
     820              : 
     821              : 
     822              : int
     823            1 : main (int argc,
     824              :       char *const *argv)
     825              : {
     826              :   int ret;
     827              : 
     828            1 :   ret = TDB_main (argc,
     829              :                   argv,
     830              :                   "test-legitimization-measures",
     831              :                   "Tests for the exchangedb `legitimization_measures' table",
     832              :                   tests);
     833            1 :   TDB_account_free (&account);
     834            1 :   return ret;
     835              : }
     836              : 
     837              : 
     838              : /* end of test_legitimization_measures.c */
        

Generated by: LCOV version 2.0-1