LCOV - code coverage report
Current view: top level - exchangedb - test_aggregation_transient.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 63 63
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_transient.c
      18              :  * @brief tests for the exchangedb functions whose primary table is
      19              :  *        `aggregation_transient`
      20              :  * @author Christian Grothoff
      21              :  *
      22              :  * Covers #TALER_EXCHANGEDB_insert_aggregation_transient(),
      23              :  * #TALER_EXCHANGEDB_update_aggregation_transient(),
      24              :  * #TALER_EXCHANGEDB_delete_aggregation_transient(),
      25              :  * #TALER_EXCHANGEDB_get_aggregation_transient(),
      26              :  * #TALER_EXCHANGEDB_get_aggregation_transient_by_wtid() and
      27              :  * #TALER_EXCHANGEDB_get_aggregation_transient_by_normalized_payto().
      28              :  *
      29              :  * The table holds what the aggregator decided to hold back for later; it
      30              :  * is updated in place and deleted on payout, so it has no serial ID.  It
      31              :  * references `wire_targets`, which TDB_account() creates.  The three
      32              :  * lookups reach the row by three different keys, which is what the checks
      33              :  * exercise.
      34              :  */
      35              : #include "test_common.h"
      36              : #include "exchange-database/delete_aggregation_transient.h"
      37              : #include "exchange-database/get_aggregation_transient.h"
      38              : #include "exchange-database/get_aggregation_transient_by_normalized_payto.h"
      39              : #include "exchange-database/get_aggregation_transient_by_wtid.h"
      40              : #include "exchange-database/insert_aggregation_transient.h"
      41              : #include "exchange-database/update_aggregation_transient.h"
      42              : 
      43              : 
      44              : /**
      45              :  * Exchange bank account the checks aggregate for.
      46              :  */
      47              : #define SECTION "exchange-account-1"
      48              : 
      49              : 
      50              : /**
      51              :  * Account the merchants of the checks are paid at.
      52              :  */
      53              : static struct TDB_Account account;
      54              : 
      55              : 
      56              : /**
      57              :  * Nothing is found while the table is empty, and updating or deleting a
      58              :  * row that is not there does nothing.
      59              :  *
      60              :  * @param pg the database context
      61              :  * @return 0 on success
      62              :  */
      63              : static int
      64            1 : check_empty (struct TALER_EXCHANGEDB_PostgresContext *pg)
      65              : {
      66              :   struct TALER_MerchantPublicKeyP merchant_pub;
      67              :   struct TALER_WireTransferIdentifierRawP wtid;
      68              :   struct TALER_Amount total;
      69            1 :   struct TALER_Amount one = TDB_amount ("1");
      70            1 :   struct TALER_FullPayto payto_uri = { NULL };
      71              :   uint64_t requirement_row;
      72              : 
      73            1 :   TDB_account (pg,
      74              :                10,
      75              :                &account);
      76            1 :   TDB_FILL (merchant_pub,
      77              :             1);
      78            1 :   TDB_FILL (wtid,
      79              :             1);
      80            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
      81              :           TALER_EXCHANGEDB_get_aggregation_transient (pg,
      82              :                                                       &account.h_full,
      83              :                                                       &merchant_pub,
      84              :                                                       SECTION,
      85              :                                                       &wtid,
      86              :                                                       &total));
      87            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
      88              :           TALER_EXCHANGEDB_get_aggregation_transient_by_wtid (
      89              :             pg,
      90              :             &account.h_full,
      91              :             &wtid,
      92              :             &total,
      93              :             &requirement_row));
      94            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
      95              :           TALER_EXCHANGEDB_get_aggregation_transient_by_normalized_payto (
      96              :             pg,
      97              :             &account.h_normalized,
      98              :             &payto_uri,
      99              :             &wtid,
     100              :             &merchant_pub,
     101              :             &total));
     102            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     103              :           TALER_EXCHANGEDB_update_aggregation_transient (pg,
     104              :                                                          &account.h_full,
     105              :                                                          &wtid,
     106              :                                                          0,
     107              :                                                          &one));
     108            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     109              :           TALER_EXCHANGEDB_delete_aggregation_transient (pg,
     110              :                                                          &account.h_full,
     111              :                                                          &wtid));
     112            1 :   FAILIF (0 != TDB_count (pg,
     113              :                           "FROM aggregation_transient"));
     114            1 :   return 0;
     115              : }
     116              : 
     117              : 
     118              : /**
     119              :  * An inserted row is found by all three lookups.
     120              :  *
     121              :  * @param pg the database context
     122              :  * @return 0 on success
     123              :  */
     124              : static int
     125            1 : check_insert_and_lookup (struct TALER_EXCHANGEDB_PostgresContext *pg)
     126              : {
     127              :   struct TALER_MerchantPublicKeyP merchant_pub;
     128              :   struct TALER_MerchantPublicKeyP got_merchant;
     129              :   struct TALER_WireTransferIdentifierRawP wtid;
     130              :   struct TALER_WireTransferIdentifierRawP got_wtid;
     131            1 :   struct TALER_Amount total = TDB_amount ("3");
     132              :   struct TALER_Amount got;
     133            1 :   struct TALER_FullPayto payto_uri = { NULL };
     134            1 :   uint64_t requirement_row = 42;
     135              : 
     136            1 :   TDB_FILL (merchant_pub,
     137              :             10);
     138            1 :   TDB_FILL (wtid,
     139              :             10);
     140            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     141              :           TALER_EXCHANGEDB_insert_aggregation_transient (pg,
     142              :                                                          &account.h_full,
     143              :                                                          SECTION,
     144              :                                                          &merchant_pub,
     145              :                                                          &wtid,
     146              :                                                          0,
     147              :                                                          &total));
     148            1 :   FAILIF (1 != TDB_count (pg,
     149              :                           "FROM aggregation_transient"));
     150              : 
     151              :   /* by (account, merchant, exchange account) */
     152            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     153              :           TALER_EXCHANGEDB_get_aggregation_transient (pg,
     154              :                                                       &account.h_full,
     155              :                                                       &merchant_pub,
     156              :                                                       SECTION,
     157              :                                                       &got_wtid,
     158              :                                                       &got));
     159            1 :   FAILIF (0 != GNUNET_memcmp (&got_wtid,
     160              :                               &wtid));
     161            1 :   FAILIF (0 != TALER_amount_cmp (&got,
     162              :                                  &total));
     163              : 
     164              :   /* by (account, wtid) */
     165            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     166              :           TALER_EXCHANGEDB_get_aggregation_transient_by_wtid (
     167              :             pg,
     168              :             &account.h_full,
     169              :             &wtid,
     170              :             &got,
     171              :             &requirement_row));
     172            1 :   FAILIF (0 != TALER_amount_cmp (&got,
     173              :                                  &total));
     174              :   /* no legitimization reason was recorded */
     175            1 :   FAILIF (0 != requirement_row);
     176              : 
     177              :   /* by normalized account */
     178            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     179              :           TALER_EXCHANGEDB_get_aggregation_transient_by_normalized_payto (
     180              :             pg,
     181              :             &account.h_normalized,
     182              :             &payto_uri,
     183              :             &got_wtid,
     184              :             &got_merchant,
     185              :             &got));
     186            1 :   FAILIF_C (0 != strcmp (payto_uri.full_payto,
     187              :                          account.payto.full_payto),
     188              :             GNUNET_free (payto_uri.full_payto));
     189            1 :   GNUNET_free (payto_uri.full_payto);
     190            1 :   FAILIF (0 != GNUNET_memcmp (&got_merchant,
     191              :                               &merchant_pub));
     192            1 :   FAILIF (0 != GNUNET_memcmp (&got_wtid,
     193              :                               &wtid));
     194              : 
     195              :   /* a different merchant on the same account has nothing */
     196              :   {
     197              :     struct TALER_MerchantPublicKeyP other;
     198              : 
     199            1 :     TDB_FILL (other,
     200              :               99);
     201            1 :     FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     202              :             TALER_EXCHANGEDB_get_aggregation_transient (pg,
     203              :                                                         &account.h_full,
     204              :                                                         &other,
     205              :                                                         SECTION,
     206              :                                                         &got_wtid,
     207              :                                                         &got));
     208              :   }
     209              :   /* and neither does a different exchange bank account */
     210            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     211              :           TALER_EXCHANGEDB_get_aggregation_transient (pg,
     212              :                                                       &account.h_full,
     213              :                                                       &merchant_pub,
     214              :                                                       "exchange-account-2",
     215              :                                                       &got_wtid,
     216              :                                                       &got));
     217            1 :   return 0;
     218              : }
     219              : 
     220              : 
     221              : /**
     222              :  * Updating a row changes the amount and the legitimization reason.
     223              :  *
     224              :  * @param pg the database context
     225              :  * @return 0 on success
     226              :  */
     227              : static int
     228            1 : check_update (struct TALER_EXCHANGEDB_PostgresContext *pg)
     229              : {
     230              :   struct TALER_MerchantPublicKeyP merchant_pub;
     231              :   struct TALER_WireTransferIdentifierRawP wtid;
     232              :   struct TALER_WireTransferIdentifierRawP got_wtid;
     233            1 :   struct TALER_Amount total = TDB_amount ("7");
     234              :   struct TALER_Amount got;
     235            1 :   uint64_t requirement_row = 0;
     236              : 
     237            1 :   TDB_FILL (merchant_pub,
     238              :             10);
     239            1 :   TDB_FILL (wtid,
     240              :             10);
     241            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     242              :           TALER_EXCHANGEDB_update_aggregation_transient (pg,
     243              :                                                          &account.h_full,
     244              :                                                          &wtid,
     245              :                                                          5,
     246              :                                                          &total));
     247            1 :   FAILIF (1 != TDB_count (pg,
     248              :                           "FROM aggregation_transient"));
     249            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     250              :           TALER_EXCHANGEDB_get_aggregation_transient (pg,
     251              :                                                       &account.h_full,
     252              :                                                       &merchant_pub,
     253              :                                                       SECTION,
     254              :                                                       &got_wtid,
     255              :                                                       &got));
     256            1 :   FAILIF (0 != TALER_amount_cmp (&got,
     257              :                                  &total));
     258            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     259              :           TALER_EXCHANGEDB_get_aggregation_transient_by_wtid (
     260              :             pg,
     261              :             &account.h_full,
     262              :             &wtid,
     263              :             &got,
     264              :             &requirement_row));
     265            1 :   FAILIF (5 != requirement_row);
     266              : 
     267              :   /* a wire transfer identifier that is not on file is not created */
     268              :   {
     269              :     struct TALER_WireTransferIdentifierRawP other;
     270              : 
     271            1 :     TDB_FILL (other,
     272              :               98);
     273            1 :     FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     274              :             TALER_EXCHANGEDB_update_aggregation_transient (pg,
     275              :                                                            &account.h_full,
     276              :                                                            &other,
     277              :                                                            0,
     278              :                                                            &total));
     279            1 :     FAILIF (1 != TDB_count (pg,
     280              :                             "FROM aggregation_transient"));
     281              :   }
     282            1 :   return 0;
     283              : }
     284              : 
     285              : 
     286              : /**
     287              :  * Deleting a row removes it, and a second delete does nothing.
     288              :  *
     289              :  * @param pg the database context
     290              :  * @return 0 on success
     291              :  */
     292              : static int
     293            1 : check_delete (struct TALER_EXCHANGEDB_PostgresContext *pg)
     294              : {
     295              :   struct TALER_MerchantPublicKeyP merchant_pub;
     296              :   struct TALER_WireTransferIdentifierRawP wtid;
     297              :   struct TALER_Amount got;
     298              : 
     299            1 :   TDB_FILL (merchant_pub,
     300              :             10);
     301            1 :   TDB_FILL (wtid,
     302              :             10);
     303            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     304              :           TALER_EXCHANGEDB_delete_aggregation_transient (pg,
     305              :                                                          &account.h_full,
     306              :                                                          &wtid));
     307            1 :   FAILIF (0 != TDB_count (pg,
     308              :                           "FROM aggregation_transient"));
     309            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     310              :           TALER_EXCHANGEDB_delete_aggregation_transient (pg,
     311              :                                                          &account.h_full,
     312              :                                                          &wtid));
     313            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     314              :           TALER_EXCHANGEDB_get_aggregation_transient (pg,
     315              :                                                       &account.h_full,
     316              :                                                       &merchant_pub,
     317              :                                                       SECTION,
     318              :                                                       &wtid,
     319              :                                                       &got));
     320            1 :   return 0;
     321              : }
     322              : 
     323              : 
     324              : /**
     325              :  * The checks to run, in order.
     326              :  */
     327              : static const struct TDB_Test tests[] = {
     328              :   { "aggregation-transient-empty",
     329              :     &check_empty },
     330              :   { "aggregation-transient-insert-and-lookup",
     331              :     &check_insert_and_lookup },
     332              :   { "aggregation-transient-update",
     333              :     &check_update },
     334              :   { "aggregation-transient-delete",
     335              :     &check_delete },
     336              :   { NULL, NULL }
     337              : };
     338              : 
     339              : 
     340              : int
     341            1 : main (int argc,
     342              :       char *const *argv)
     343              : {
     344              :   int ret;
     345              : 
     346            1 :   ret = TDB_main (argc,
     347              :                   argv,
     348              :                   "test-aggregation-transient",
     349              :                   "Tests for the exchangedb `aggregation_transient' table",
     350              :                   tests);
     351            1 :   TDB_account_free (&account);
     352            1 :   return ret;
     353              : }
     354              : 
     355              : 
     356              : /* end of test_aggregation_transient.c */
        

Generated by: LCOV version 2.0-1