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

            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_prewire.c
      18              :  * @brief tests for the exchangedb functions whose primary table is `prewire`
      19              :  * @author Christian Grothoff
      20              :  *
      21              :  * Covers #TALER_EXCHANGEDB_insert_prewire(),
      22              :  * #TALER_EXCHANGEDB_iterate_prewires(),
      23              :  * #TALER_EXCHANGEDB_update_to_prewire_finished() and
      24              :  * #TALER_EXCHANGEDB_update_to_prewire_failed().
      25              :  *
      26              :  * `prewire` has no foreign keys.  The table is a work queue: the iterator
      27              :  * only reports rows that are neither finished nor failed, which is what the
      28              :  * checks below are about.
      29              :  */
      30              : #include "test_common.h"
      31              : #include "exchange-database/insert_prewire.h"
      32              : #include "exchange-database/iterate_prewires.h"
      33              : #include "exchange-database/update_to_prewire_finished.h"
      34              : #include "exchange-database/update_to_prewire_failed.h"
      35              : 
      36              : 
      37              : /**
      38              :  * Closure for #prewire_cb().
      39              :  */
      40              : struct PrewireContext
      41              : {
      42              :   /**
      43              :    * How many rows did the callback see?
      44              :    */
      45              :   unsigned int total;
      46              : 
      47              :   /**
      48              :    * Row of the first entry seen.
      49              :    */
      50              :   uint64_t first_row;
      51              : 
      52              :   /**
      53              :    * Payload of the first entry seen, owned by this struct.
      54              :    */
      55              :   char *first_buf;
      56              : 
      57              :   /**
      58              :    * Number of bytes in @e first_buf.
      59              :    */
      60              :   size_t first_buf_size;
      61              : 
      62              :   /**
      63              :    * Wire method of the first entry seen, owned by this struct.
      64              :    */
      65              :   char *first_method;
      66              : };
      67              : 
      68              : 
      69              : /**
      70              :  * Callback for #TALER_EXCHANGEDB_iterate_prewires().
      71              :  *
      72              :  * @param cls a `struct PrewireContext *`
      73              :  * @param rowid row of the entry
      74              :  * @param wire_method wire method of the entry
      75              :  * @param buf payload of the entry
      76              :  * @param buf_size number of bytes in @a buf
      77              :  */
      78              : static void
      79            7 : prewire_cb (void *cls,
      80              :             uint64_t rowid,
      81              :             const char *wire_method,
      82              :             const char *buf,
      83              :             size_t buf_size)
      84              : {
      85            7 :   struct PrewireContext *ctx = cls;
      86              : 
      87            7 :   if (0 == ctx->total++)
      88              :   {
      89            5 :     ctx->first_row = rowid;
      90            5 :     ctx->first_buf = GNUNET_memdup (buf,
      91              :                                     buf_size);
      92            5 :     ctx->first_buf_size = buf_size;
      93            5 :     ctx->first_method = GNUNET_strdup (wire_method);
      94              :   }
      95            7 : }
      96              : 
      97              : 
      98              : /**
      99              :  * Release what #prewire_cb() allocated.
     100              :  *
     101              :  * @param[in,out] ctx context to clean up
     102              :  */
     103              : static void
     104            6 : ctx_free (struct PrewireContext *ctx)
     105              : {
     106            6 :   GNUNET_free (ctx->first_buf);
     107            6 :   GNUNET_free (ctx->first_method);
     108            6 : }
     109              : 
     110              : 
     111              : /**
     112              :  * An empty queue yields nothing, and marking rows that do not exist does
     113              :  * nothing.
     114              :  *
     115              :  * @param pg the database context
     116              :  * @return 0 on success
     117              :  */
     118              : static int
     119            1 : check_empty (struct TALER_EXCHANGEDB_PostgresContext *pg)
     120              : {
     121            1 :   struct PrewireContext ctx = { 0 };
     122              : 
     123            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     124              :           TALER_EXCHANGEDB_iterate_prewires (pg,
     125              :                                              0,
     126              :                                              10,
     127              :                                              &prewire_cb,
     128              :                                              &ctx));
     129            1 :   FAILIF (0 != ctx.total);
     130            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     131              :           TALER_EXCHANGEDB_update_to_prewire_finished (pg,
     132              :                                                        1));
     133            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     134              :           TALER_EXCHANGEDB_update_to_prewire_failed (pg,
     135              :                                                      1));
     136            1 :   return 0;
     137              : }
     138              : 
     139              : 
     140              : /**
     141              :  * Inserted rows come back in order, with their payload intact.
     142              :  *
     143              :  * @param pg the database context
     144              :  * @return 0 on success
     145              :  */
     146              : static int
     147            1 : check_insert_and_iterate (struct TALER_EXCHANGEDB_PostgresContext *pg)
     148              : {
     149              :   static const char buf1[] = "first-transfer";
     150              :   static const char buf2[] = "second-transfer";
     151              :   struct PrewireContext ctx;
     152              :   uint64_t row1;
     153              : 
     154            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     155              :           TALER_EXCHANGEDB_insert_prewire (pg,
     156              :                                            "x-taler-bank",
     157              :                                            buf1,
     158              :                                            sizeof (buf1)));
     159            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     160              :           TALER_EXCHANGEDB_insert_prewire (pg,
     161              :                                            "iban",
     162              :                                            buf2,
     163              :                                            sizeof (buf2)));
     164            1 :   memset (&ctx,
     165              :           0,
     166              :           sizeof (ctx));
     167            1 :   FAILIF (0 >=
     168              :           TALER_EXCHANGEDB_iterate_prewires (pg,
     169              :                                              0,
     170              :                                              10,
     171              :                                              &prewire_cb,
     172              :                                              &ctx));
     173            1 :   FAILIF_C (2 != ctx.total,
     174              :             ctx_free (&ctx));
     175            1 :   FAILIF_C (sizeof (buf1) != ctx.first_buf_size,
     176              :             ctx_free (&ctx));
     177            1 :   FAILIF_C (0 != memcmp (ctx.first_buf,
     178              :                          buf1,
     179              :                          sizeof (buf1)),
     180              :             ctx_free (&ctx));
     181            1 :   FAILIF_C (0 != strcmp (ctx.first_method,
     182              :                          "x-taler-bank"),
     183              :             ctx_free (&ctx));
     184            1 :   row1 = ctx.first_row;
     185            1 :   ctx_free (&ctx);
     186              : 
     187              :   /* the limit is honoured */
     188            1 :   memset (&ctx,
     189              :           0,
     190              :           sizeof (ctx));
     191            1 :   FAILIF (0 >=
     192              :           TALER_EXCHANGEDB_iterate_prewires (pg,
     193              :                                              0,
     194              :                                              1,
     195              :                                              &prewire_cb,
     196              :                                              &ctx));
     197            1 :   FAILIF_C (1 != ctx.total,
     198              :             ctx_free (&ctx));
     199            1 :   ctx_free (&ctx);
     200              : 
     201              :   /* ...and so is the starting row */
     202            1 :   memset (&ctx,
     203              :           0,
     204              :           sizeof (ctx));
     205            1 :   FAILIF (0 >=
     206              :           TALER_EXCHANGEDB_iterate_prewires (pg,
     207              :                                              row1 + 1,
     208              :                                              10,
     209              :                                              &prewire_cb,
     210              :                                              &ctx));
     211            1 :   FAILIF_C (1 != ctx.total,
     212              :             ctx_free (&ctx));
     213            1 :   FAILIF_C (0 != strcmp (ctx.first_method,
     214              :                          "iban"),
     215              :             ctx_free (&ctx));
     216            1 :   ctx_free (&ctx);
     217            1 :   return 0;
     218              : }
     219              : 
     220              : 
     221              : /**
     222              :  * Finished and failed rows drop out of the queue.
     223              :  *
     224              :  * @param pg the database context
     225              :  * @return 0 on success
     226              :  */
     227              : static int
     228            1 : check_finished_and_failed (struct TALER_EXCHANGEDB_PostgresContext *pg)
     229              : {
     230              :   struct PrewireContext ctx;
     231              :   uint64_t row1;
     232              :   uint64_t row2;
     233              : 
     234            1 :   memset (&ctx,
     235              :           0,
     236              :           sizeof (ctx));
     237            1 :   FAILIF (0 >=
     238              :           TALER_EXCHANGEDB_iterate_prewires (pg,
     239              :                                              0,
     240              :                                              10,
     241              :                                              &prewire_cb,
     242              :                                              &ctx));
     243            1 :   FAILIF_C (2 != ctx.total,
     244              :             ctx_free (&ctx));
     245            1 :   row1 = ctx.first_row;
     246            1 :   ctx_free (&ctx);
     247              : 
     248            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     249              :           TALER_EXCHANGEDB_update_to_prewire_finished (pg,
     250              :                                                        row1));
     251            1 :   memset (&ctx,
     252              :           0,
     253              :           sizeof (ctx));
     254            1 :   FAILIF (0 >=
     255              :           TALER_EXCHANGEDB_iterate_prewires (pg,
     256              :                                              0,
     257              :                                              10,
     258              :                                              &prewire_cb,
     259              :                                              &ctx));
     260            1 :   FAILIF_C (1 != ctx.total,
     261              :             ctx_free (&ctx));
     262            1 :   row2 = ctx.first_row;
     263            1 :   ctx_free (&ctx);
     264            1 :   FAILIF (row2 == row1);
     265              : 
     266            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     267              :           TALER_EXCHANGEDB_update_to_prewire_failed (pg,
     268              :                                                      row2));
     269            1 :   memset (&ctx,
     270              :           0,
     271              :           sizeof (ctx));
     272            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     273              :           TALER_EXCHANGEDB_iterate_prewires (pg,
     274              :                                              0,
     275              :                                              10,
     276              :                                              &prewire_cb,
     277              :                                              &ctx));
     278            1 :   FAILIF_C (0 != ctx.total,
     279              :             ctx_free (&ctx));
     280            1 :   ctx_free (&ctx);
     281              : 
     282              :   /* both rows are still on file, one finished and one failed */
     283            1 :   FAILIF (2 != TDB_count (pg,
     284              :                           "FROM prewire"));
     285            1 :   FAILIF (1 != TDB_count (pg,
     286              :                           "FROM prewire WHERE finished"));
     287            1 :   FAILIF (1 != TDB_count (pg,
     288              :                           "FROM prewire WHERE failed"));
     289              :   /* marking again is still reported as a row touched */
     290            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     291              :           TALER_EXCHANGEDB_update_to_prewire_finished (pg,
     292              :                                                        row1));
     293            1 :   return 0;
     294              : }
     295              : 
     296              : 
     297              : /**
     298              :  * The checks to run, in order.
     299              :  */
     300              : static const struct TDB_Test tests[] = {
     301              :   { "prewire-empty",
     302              :     &check_empty },
     303              :   { "prewire-insert-and-iterate",
     304              :     &check_insert_and_iterate },
     305              :   { "prewire-finished-and-failed",
     306              :     &check_finished_and_failed },
     307              :   { NULL, NULL }
     308              : };
     309              : 
     310              : 
     311              : int
     312            1 : main (int argc,
     313              :       char *const *argv)
     314              : {
     315            1 :   return TDB_main (argc,
     316              :                    argv,
     317              :                    "test-prewire",
     318              :                    "Tests for the exchangedb `prewire' table",
     319              :                    tests);
     320              : }
     321              : 
     322              : 
     323              : /* end of test_prewire.c */
        

Generated by: LCOV version 2.0-1