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

            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_aggregation_deferrals.c
      18              :  * @brief tests for the exchangedb functions whose primary table is
      19              :  *        `aggregation_deferrals`
      20              :  * @author Christian Grothoff
      21              :  *
      22              :  * Covers #TALER_EXCHANGEDB_insert_aggregation_deferral() and
      23              :  * #TALER_EXCHANGEDB_get_aggregation_deferral_by_wtid().
      24              :  *
      25              :  * The table is the exchange's append-only account of why it did not make a
      26              :  * wire transfer it had already decided on.  Each row hangs off the deposit
      27              :  * of the aggregate that is last to reach its wire deadline, so the insert
      28              :  * finds nothing to attach to until `aggregation_tracking` has been written
      29              :  * -- which is the first thing the checks pin down.  The lookup returns the
      30              :  * most recent claim, so the checks defer twice.
      31              :  */
      32              : #include "test_common.h"
      33              : #include "exchange-database/do_aggregate.h"
      34              : #include "exchange-database/get_aggregation_deferral_by_wtid.h"
      35              : #include "exchange-database/insert_aggregation_deferral.h"
      36              : 
      37              : 
      38              : /**
      39              :  * Account the merchants of the checks are paid at.
      40              :  */
      41              : static struct TDB_Account account;
      42              : 
      43              : 
      44              : /**
      45              :  * Denomination the checks deposit.
      46              :  */
      47              : static struct TDB_Denom denom;
      48              : 
      49              : 
      50              : /**
      51              :  * The wire transfer the checks aggregate into.
      52              :  */
      53              : static struct TALER_WireTransferIdentifierRawP wtid;
      54              : 
      55              : 
      56              : /**
      57              :  * Build a timestamp from a number of seconds since the epoch.
      58              :  *
      59              :  * @param secs seconds since the epoch
      60              :  * @return the timestamp
      61              :  */
      62              : static struct GNUNET_TIME_Timestamp
      63            7 : ts (uint64_t secs)
      64              : {
      65            7 :   struct GNUNET_TIME_Absolute abs = {
      66            7 :     .abs_value_us = secs * 1000LLU * 1000LLU
      67              :   };
      68              : 
      69            7 :   return GNUNET_TIME_absolute_to_timestamp (abs);
      70              : }
      71              : 
      72              : 
      73              : /**
      74              :  * Without an aggregation to hang off, nothing is recorded and nothing is
      75              :  * found.
      76              :  *
      77              :  * @param pg the database context
      78              :  * @return 0 on success
      79              :  */
      80              : static int
      81            1 : check_no_aggregation (struct TALER_EXCHANGEDB_PostgresContext *pg)
      82              : {
      83            1 :   struct TALER_Amount amount = TDB_amount ("1");
      84              :   struct TALER_Amount got;
      85              :   struct GNUNET_TIME_Timestamp deferral_time;
      86              :   enum TALER_EXCHANGEDB_DeferralReason reason;
      87              :   uint64_t requirement_row;
      88              : 
      89            1 :   TDB_denom (pg,
      90              :              10,
      91              :              "5",
      92              :              "0.1",
      93              :              &denom);
      94            1 :   TDB_account (pg,
      95              :                10,
      96              :                &account);
      97            1 :   TDB_FILL (wtid,
      98              :             10);
      99            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     100              :           TALER_EXCHANGEDB_get_aggregation_deferral_by_wtid (pg,
     101              :                                                              &wtid,
     102              :                                                              &got,
     103              :                                                              &reason,
     104              :                                                              &requirement_row,
     105              :                                                              &deferral_time));
     106            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     107              :           TALER_EXCHANGEDB_insert_aggregation_deferral (
     108              :             pg,
     109              :             &wtid,
     110              :             &account.h_full,
     111              :             &amount,
     112              :             TALER_EXCHANGEDB_DR_AMOUNT_TOO_SMALL,
     113              :             0,
     114              :             ts (1600000000)));
     115            1 :   FAILIF (0 != TDB_count (pg,
     116              :                           "FROM aggregation_deferrals"));
     117            1 :   return 0;
     118              : }
     119              : 
     120              : 
     121              : /**
     122              :  * With an aggregation on file, the deferral is recorded and read back.
     123              :  *
     124              :  * @param pg the database context
     125              :  * @return 0 on success
     126              :  */
     127              : static int
     128            1 : check_defer (struct TALER_EXCHANGEDB_PostgresContext *pg)
     129              : {
     130              :   struct TALER_CoinPublicInfo coin;
     131              :   struct TDB_Deposit dep;
     132              :   struct TALER_Amount total;
     133            1 :   struct TALER_Amount amount = TDB_amount ("0.9");
     134              :   struct TALER_Amount got;
     135              :   struct GNUNET_TIME_Timestamp deferral_time;
     136              :   enum TALER_EXCHANGEDB_DeferralReason reason;
     137            1 :   uint64_t requirement_row = 42;
     138              : 
     139            1 :   TDB_coin (pg,
     140              :             &denom,
     141              :             20,
     142              :             &coin,
     143              :             NULL);
     144            1 :   TDB_deposit (pg,
     145              :                &account,
     146              :                &coin,
     147              :                20,
     148              :                "1",
     149              :                "0.1",
     150              :                ts (1600000000),
     151              :                ts (1600000000),
     152              :                &dep);
     153            1 :   FAILIF_C (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     154              :             TALER_EXCHANGEDB_do_aggregate (pg,
     155              :                                            &account.h_full,
     156              :                                            &dep.merchant_pub,
     157              :                                            &wtid,
     158              :                                            &total),
     159              :             TDB_coin_free (&coin));
     160            1 :   TDB_coin_free (&coin);
     161              : 
     162            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     163              :           TALER_EXCHANGEDB_insert_aggregation_deferral (
     164              :             pg,
     165              :             &wtid,
     166              :             &account.h_full,
     167              :             &amount,
     168              :             TALER_EXCHANGEDB_DR_AMOUNT_TOO_SMALL,
     169              :             0,
     170              :             ts (1600000000)));
     171            1 :   FAILIF (1 != TDB_count (pg,
     172              :                           "FROM aggregation_deferrals"));
     173            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     174              :           TALER_EXCHANGEDB_get_aggregation_deferral_by_wtid (pg,
     175              :                                                              &wtid,
     176              :                                                              &got,
     177              :                                                              &reason,
     178              :                                                              &requirement_row,
     179              :                                                              &deferral_time));
     180            1 :   FAILIF (0 != TALER_amount_cmp (&got,
     181              :                                  &amount));
     182            1 :   FAILIF (TALER_EXCHANGEDB_DR_AMOUNT_TOO_SMALL != reason);
     183            1 :   FAILIF (0 != requirement_row);
     184            1 :   FAILIF (GNUNET_TIME_timestamp_cmp (deferral_time,
     185              :                                      !=,
     186              :                                      ts (1600000000)));
     187              : 
     188              :   /* a wire transfer nobody deferred is still unknown */
     189              :   {
     190              :     struct TALER_WireTransferIdentifierRawP other;
     191              : 
     192            1 :     TDB_FILL (other,
     193              :               99);
     194            1 :     FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     195              :             TALER_EXCHANGEDB_get_aggregation_deferral_by_wtid (
     196              :               pg,
     197              :               &other,
     198              :               &got,
     199              :               &reason,
     200              :               &requirement_row,
     201              :               &deferral_time));
     202              :   }
     203            1 :   return 0;
     204              : }
     205              : 
     206              : 
     207              : /**
     208              :  * The table is append-only: a second deferral is a second row, and the
     209              :  * lookup returns the newer one.
     210              :  *
     211              :  * @param pg the database context
     212              :  * @return 0 on success
     213              :  */
     214              : static int
     215            1 : check_append_only (struct TALER_EXCHANGEDB_PostgresContext *pg)
     216              : {
     217            1 :   struct TALER_Amount amount = TDB_amount ("0.9");
     218              :   struct TALER_Amount got;
     219              :   struct GNUNET_TIME_Timestamp deferral_time;
     220              :   enum TALER_EXCHANGEDB_DeferralReason reason;
     221            1 :   uint64_t requirement_row = 0;
     222              : 
     223            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     224              :           TALER_EXCHANGEDB_insert_aggregation_deferral (
     225              :             pg,
     226              :             &wtid,
     227              :             &account.h_full,
     228              :             &amount,
     229              :             TALER_EXCHANGEDB_DR_KYC,
     230              :             7,
     231              :             ts (1600003600)));
     232            1 :   FAILIF (2 != TDB_count (pg,
     233              :                           "FROM aggregation_deferrals"));
     234            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     235              :           TALER_EXCHANGEDB_get_aggregation_deferral_by_wtid (pg,
     236              :                                                              &wtid,
     237              :                                                              &got,
     238              :                                                              &reason,
     239              :                                                              &requirement_row,
     240              :                                                              &deferral_time));
     241            1 :   FAILIF (TALER_EXCHANGEDB_DR_KYC != reason);
     242            1 :   FAILIF (7 != requirement_row);
     243            1 :   FAILIF (GNUNET_TIME_timestamp_cmp (deferral_time,
     244              :                                      !=,
     245              :                                      ts (1600003600)));
     246            1 :   return 0;
     247              : }
     248              : 
     249              : 
     250              : /**
     251              :  * The checks to run, in order.
     252              :  */
     253              : static const struct TDB_Test tests[] = {
     254              :   { "aggregation-deferrals-no-aggregation",
     255              :     &check_no_aggregation },
     256              :   { "aggregation-deferrals-defer",
     257              :     &check_defer },
     258              :   { "aggregation-deferrals-append-only",
     259              :     &check_append_only },
     260              :   { NULL, NULL }
     261              : };
     262              : 
     263              : 
     264              : int
     265            1 : main (int argc,
     266              :       char *const *argv)
     267              : {
     268              :   int ret;
     269              : 
     270            1 :   ret = TDB_main (argc,
     271              :                   argv,
     272              :                   "test-aggregation-deferrals",
     273              :                   "Tests for the exchangedb `aggregation_deferrals' table",
     274              :                   tests);
     275            1 :   TDB_account_free (&account);
     276            1 :   TDB_denom_free (&denom);
     277            1 :   return ret;
     278              : }
     279              : 
     280              : 
     281              : /* end of test_aggregation_deferrals.c */
        

Generated by: LCOV version 2.0-1