LCOV - code coverage report
Current view: top level - exchangedb - test_auditor_denom_sigs.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 98.3 % 58 57
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_auditor_denom_sigs.c
      18              :  * @brief tests for the exchangedb functions whose primary table is
      19              :  *        `auditor_denom_sigs`
      20              :  * @author Christian Grothoff
      21              :  *
      22              :  * Covers #TALER_EXCHANGEDB_insert_auditor_denom_sig(),
      23              :  * #TALER_EXCHANGEDB_get_auditor_denom_sig() and
      24              :  * #TALER_EXCHANGEDB_iterate_auditor_denominations().
      25              :  *
      26              :  * The table references `auditors` and `denominations`, and the insert
      27              :  * resolves both by their natural keys inside the statement -- so an unknown
      28              :  * auditor or denomination has to come back as "nothing inserted".  Fixtures
      29              :  * come from #TALER_EXCHANGEDB_insert_auditor() and TDB_denom(), whose own
      30              :  * tables are covered by test_auditors.c and test_denominations.c.
      31              :  */
      32              : #include "test_common.h"
      33              : #include "exchange-database/insert_auditor.h"
      34              : #include "exchange-database/update_auditor.h"
      35              : #include "exchange-database/insert_auditor_denom_sig.h"
      36              : #include "exchange-database/get_auditor_denom_sig.h"
      37              : #include "exchange-database/iterate_auditor_denominations.h"
      38              : 
      39              : 
      40              : /**
      41              :  * Closure for #count_cb().
      42              :  */
      43              : struct CountContext
      44              : {
      45              :   /**
      46              :    * Auditor we are looking for.
      47              :    */
      48              :   const struct TALER_AuditorPublicKeyP *auditor_pub;
      49              : 
      50              :   /**
      51              :    * Denomination we are looking for.
      52              :    */
      53              :   const struct TALER_DenominationHashP *h_denom_pub;
      54              : 
      55              :   /**
      56              :    * How many rows did the callback see in total?
      57              :    */
      58              :   unsigned int total;
      59              : 
      60              :   /**
      61              :    * How many times did we see the pair we are after?
      62              :    */
      63              :   unsigned int matched;
      64              : 
      65              :   /**
      66              :    * Signature reported for that pair.
      67              :    */
      68              :   struct TALER_AuditorSignatureP auditor_sig;
      69              : };
      70              : 
      71              : 
      72              : /**
      73              :  * Callback for #TALER_EXCHANGEDB_iterate_auditor_denominations().
      74              :  *
      75              :  * @param cls a `struct CountContext *`
      76              :  * @param auditor_pub public key of the auditor
      77              :  * @param h_denom_pub denomination audited by @a auditor_pub
      78              :  * @param auditor_sig the auditor's signature
      79              :  */
      80              : static void
      81            1 : count_cb (void *cls,
      82              :           const struct TALER_AuditorPublicKeyP *auditor_pub,
      83              :           const struct TALER_DenominationHashP *h_denom_pub,
      84              :           const struct TALER_AuditorSignatureP *auditor_sig)
      85              : {
      86            1 :   struct CountContext *ctx = cls;
      87              : 
      88            1 :   ctx->total++;
      89            1 :   if ( (0 != GNUNET_memcmp (auditor_pub,
      90            1 :                             ctx->auditor_pub)) ||
      91            1 :        (0 != GNUNET_memcmp (h_denom_pub,
      92              :                             ctx->h_denom_pub)) )
      93            0 :     return;
      94            1 :   ctx->matched++;
      95            1 :   ctx->auditor_sig = *auditor_sig;
      96              : }
      97              : 
      98              : 
      99              : /**
     100              :  * Neither half of the pair existing means nothing is inserted and nothing
     101              :  * is found.
     102              :  *
     103              :  * @param pg the database context
     104              :  * @return 0 on success
     105              :  */
     106              : static int
     107            1 : check_unknown_references (struct TALER_EXCHANGEDB_PostgresContext *pg)
     108              : {
     109              :   struct TALER_AuditorPublicKeyP auditor_pub;
     110              :   struct TALER_DenominationHashP h_denom_pub;
     111              :   struct TALER_AuditorSignatureP auditor_sig;
     112              :   struct TALER_AuditorSignatureP got;
     113              :   struct TDB_Denom denom;
     114              : 
     115            1 :   TDB_FILL (auditor_pub,
     116              :             1);
     117            1 :   TDB_FILL (h_denom_pub,
     118              :             1);
     119            1 :   TDB_FILL (auditor_sig,
     120              :             1);
     121            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     122              :           TALER_EXCHANGEDB_get_auditor_denom_sig (pg,
     123              :                                                   &h_denom_pub,
     124              :                                                   &auditor_pub,
     125              :                                                   &got));
     126              :   /* neither the auditor nor the denomination exist */
     127            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     128              :           TALER_EXCHANGEDB_insert_auditor_denom_sig (pg,
     129              :                                                      &h_denom_pub,
     130              :                                                      &auditor_pub,
     131              :                                                      &auditor_sig));
     132              :   /* the denomination exists, the auditor does not */
     133            1 :   TDB_denom (pg,
     134              :              10,
     135              :              "5",
     136              :              "0.1",
     137              :              &denom);
     138            1 :   FAILIF_C (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     139              :             TALER_EXCHANGEDB_insert_auditor_denom_sig (pg,
     140              :                                                        &denom.h_denom_pub,
     141              :                                                        &auditor_pub,
     142              :                                                        &auditor_sig),
     143              :             TDB_denom_free (&denom));
     144              :   /* the auditor exists, the denomination does not */
     145            1 :   FAILIF_C (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     146              :             TALER_EXCHANGEDB_insert_auditor (pg,
     147              :                                              &auditor_pub,
     148              :                                              "https://auditor.example/",
     149              :                                              "The Auditor",
     150              :                                              GNUNET_TIME_timestamp_get ()),
     151              :             TDB_denom_free (&denom));
     152            1 :   FAILIF_C (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     153              :             TALER_EXCHANGEDB_insert_auditor_denom_sig (pg,
     154              :                                                        &h_denom_pub,
     155              :                                                        &auditor_pub,
     156              :                                                        &auditor_sig),
     157              :             TDB_denom_free (&denom));
     158            1 :   FAILIF_C (0 != TDB_count (pg,
     159              :                             "FROM auditor_denom_sigs"),
     160              :             TDB_denom_free (&denom));
     161            1 :   TDB_denom_free (&denom);
     162            1 :   return 0;
     163              : }
     164              : 
     165              : 
     166              : /**
     167              :  * With both halves present the signature is stored, found and iterated;
     168              :  * a repeated insert is a no-op.
     169              :  *
     170              :  * @param pg the database context
     171              :  * @return 0 on success
     172              :  */
     173              : static int
     174            1 : check_insert_and_lookup (struct TALER_EXCHANGEDB_PostgresContext *pg)
     175              : {
     176              :   struct TALER_AuditorPublicKeyP auditor_pub;
     177              :   struct TALER_AuditorSignatureP auditor_sig;
     178              :   struct TALER_AuditorSignatureP other_sig;
     179              :   struct TALER_AuditorSignatureP got;
     180              :   struct TDB_Denom denom;
     181              :   struct CountContext ctx;
     182              : 
     183              :   /* the auditor and denomination from the previous check */
     184            1 :   TDB_FILL (auditor_pub,
     185              :             1);
     186            1 :   TDB_FILL (auditor_sig,
     187              :             1);
     188            1 :   TDB_FILL (other_sig,
     189              :             77);
     190            1 :   TDB_denom (pg,
     191              :              10,
     192              :              "5",
     193              :              "0.1",
     194              :              &denom);
     195              :   /* TDB_denom() with the same seed builds the same key, so the row is the
     196              :      one the previous check created; that is exactly what we want here. */
     197            1 :   FAILIF_C (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     198              :             TALER_EXCHANGEDB_insert_auditor_denom_sig (pg,
     199              :                                                        &denom.h_denom_pub,
     200              :                                                        &auditor_pub,
     201              :                                                        &auditor_sig),
     202              :             TDB_denom_free (&denom));
     203            1 :   memset (&got,
     204              :           0,
     205              :           sizeof (got));
     206            1 :   FAILIF_C (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     207              :             TALER_EXCHANGEDB_get_auditor_denom_sig (pg,
     208              :                                                     &denom.h_denom_pub,
     209              :                                                     &auditor_pub,
     210              :                                                     &got),
     211              :             TDB_denom_free (&denom));
     212            1 :   FAILIF_C (0 != GNUNET_memcmp (&got,
     213              :                                 &auditor_sig),
     214              :             TDB_denom_free (&denom));
     215              : 
     216              :   /* re-inserting with a different signature does nothing (ON CONFLICT DO
     217              :      NOTHING), and in particular does not overwrite the stored one */
     218            1 :   FAILIF_C (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     219              :             TALER_EXCHANGEDB_insert_auditor_denom_sig (pg,
     220              :                                                        &denom.h_denom_pub,
     221              :                                                        &auditor_pub,
     222              :                                                        &other_sig),
     223              :             TDB_denom_free (&denom));
     224            1 :   FAILIF_C (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     225              :             TALER_EXCHANGEDB_get_auditor_denom_sig (pg,
     226              :                                                     &denom.h_denom_pub,
     227              :                                                     &auditor_pub,
     228              :                                                     &got),
     229              :             TDB_denom_free (&denom));
     230            1 :   FAILIF_C (0 != GNUNET_memcmp (&got,
     231              :                                 &auditor_sig),
     232              :             TDB_denom_free (&denom));
     233              : 
     234            1 :   memset (&ctx,
     235              :           0,
     236              :           sizeof (ctx));
     237            1 :   ctx.auditor_pub = &auditor_pub;
     238            1 :   ctx.h_denom_pub = &denom.h_denom_pub;
     239            1 :   FAILIF_C (0 >=
     240              :             TALER_EXCHANGEDB_iterate_auditor_denominations (pg,
     241              :                                                             &count_cb,
     242              :                                                             &ctx),
     243              :             TDB_denom_free (&denom));
     244            1 :   FAILIF_C (1 != ctx.matched,
     245              :             TDB_denom_free (&denom));
     246            1 :   FAILIF_C (0 != GNUNET_memcmp (&ctx.auditor_sig,
     247              :                                 &auditor_sig),
     248              :             TDB_denom_free (&denom));
     249            1 :   TDB_denom_free (&denom);
     250            1 :   return 0;
     251              : }
     252              : 
     253              : 
     254              : /**
     255              :  * A disabled auditor keeps its rows but drops out of the iterator.
     256              :  *
     257              :  * @param pg the database context
     258              :  * @return 0 on success
     259              :  */
     260              : static int
     261            1 : check_disabled_auditor (struct TALER_EXCHANGEDB_PostgresContext *pg)
     262              : {
     263              :   struct TALER_AuditorPublicKeyP auditor_pub;
     264              :   struct TALER_AuditorSignatureP got;
     265              :   struct TDB_Denom denom;
     266              :   struct CountContext ctx;
     267              : 
     268            1 :   TDB_FILL (auditor_pub,
     269              :             1);
     270            1 :   TDB_denom (pg,
     271              :              10,
     272              :              "5",
     273              :              "0.1",
     274              :              &denom);
     275            1 :   FAILIF_C (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     276              :             TALER_EXCHANGEDB_update_auditor (pg,
     277              :                                              &auditor_pub,
     278              :                                              "https://auditor.example/",
     279              :                                              "The Auditor",
     280              :                                              GNUNET_TIME_timestamp_get (),
     281              :                                              false),
     282              :             TDB_denom_free (&denom));
     283            1 :   memset (&ctx,
     284              :           0,
     285              :           sizeof (ctx));
     286            1 :   ctx.auditor_pub = &auditor_pub;
     287            1 :   ctx.h_denom_pub = &denom.h_denom_pub;
     288            1 :   FAILIF_C (0 >
     289              :             TALER_EXCHANGEDB_iterate_auditor_denominations (pg,
     290              :                                                             &count_cb,
     291              :                                                             &ctx),
     292              :             TDB_denom_free (&denom));
     293            1 :   FAILIF_C (0 != ctx.matched,
     294              :             TDB_denom_free (&denom));
     295            1 :   FAILIF_C (0 != ctx.total,
     296              :             TDB_denom_free (&denom));
     297              :   /* the row itself is untouched, and the direct lookup ignores is_active */
     298            1 :   FAILIF_C (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     299              :             TALER_EXCHANGEDB_get_auditor_denom_sig (pg,
     300              :                                                     &denom.h_denom_pub,
     301              :                                                     &auditor_pub,
     302              :                                                     &got),
     303              :             TDB_denom_free (&denom));
     304            1 :   FAILIF_C (1 != TDB_count (pg,
     305              :                             "FROM auditor_denom_sigs"),
     306              :             TDB_denom_free (&denom));
     307            1 :   TDB_denom_free (&denom);
     308            1 :   return 0;
     309              : }
     310              : 
     311              : 
     312              : /**
     313              :  * The checks to run, in order.
     314              :  */
     315              : static const struct TDB_Test tests[] = {
     316              :   { "auditor-denom-sigs-unknown-references",
     317              :     &check_unknown_references },
     318              :   { "auditor-denom-sigs-insert-and-lookup",
     319              :     &check_insert_and_lookup },
     320              :   { "auditor-denom-sigs-disabled-auditor",
     321              :     &check_disabled_auditor },
     322              :   { NULL, NULL }
     323              : };
     324              : 
     325              : 
     326              : int
     327            1 : main (int argc,
     328              :       char *const *argv)
     329              : {
     330            1 :   return TDB_main (argc,
     331              :                    argv,
     332              :                    "test-auditor-denom-sigs",
     333              :                    "Tests for the exchangedb `auditor_denom_sigs' table",
     334              :                    tests);
     335              : }
     336              : 
     337              : 
     338              : /* end of test_auditor_denom_sigs.c */
        

Generated by: LCOV version 2.0-1