LCOV - code coverage report
Current view: top level - exchangedb - test_partners.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 28 28
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_partners.c
      18              :  * @brief tests for the exchangedb functions whose primary table is
      19              :  *        `partners`
      20              :  * @author Christian Grothoff
      21              :  *
      22              :  * Covers #TALER_EXCHANGEDB_insert_partner().  It is the only exported
      23              :  * function that writes the table; the rows are read back by the purse
      24              :  * machinery, which is covered in test_purse_merges.c and
      25              :  * test_purse_deposits.c.
      26              :  *
      27              :  * `partners` has no foreign keys.  The insert is ON CONFLICT DO NOTHING,
      28              :  * so re-inserting the same (key, validity period) is a no-op rather than a
      29              :  * failure.
      30              :  */
      31              : #include "test_common.h"
      32              : #include "exchange-database/insert_partner.h"
      33              : 
      34              : 
      35              : /**
      36              :  * Build a timestamp from a number of seconds since the epoch.
      37              :  *
      38              :  * @param secs seconds since the epoch
      39              :  * @return the timestamp
      40              :  */
      41              : static struct GNUNET_TIME_Timestamp
      42            8 : ts (uint64_t secs)
      43              : {
      44            8 :   struct GNUNET_TIME_Absolute abs = {
      45            8 :     .abs_value_us = secs * 1000LLU * 1000LLU
      46              :   };
      47              : 
      48            8 :   return GNUNET_TIME_absolute_to_timestamp (abs);
      49              : }
      50              : 
      51              : 
      52              : /**
      53              :  * Insert a partner exchange.
      54              :  *
      55              :  * @param pg the database context
      56              :  * @param seed seed for the partner's key and signature
      57              :  * @param from start of the validity period
      58              :  * @param until end of the validity period
      59              :  * @param url base URL of the partner
      60              :  * @return transaction status
      61              :  */
      62              : static enum GNUNET_DB_QueryStatus
      63            4 : add_partner (struct TALER_EXCHANGEDB_PostgresContext *pg,
      64              :              uint32_t seed,
      65              :              uint64_t from,
      66              :              uint64_t until,
      67              :              const char *url)
      68              : {
      69              :   struct TALER_MasterPublicKeyP master_pub;
      70              :   struct TALER_MasterSignatureP master_sig;
      71            4 :   struct TALER_Amount wad_fee = TDB_amount ("0.05");
      72              : 
      73            4 :   TDB_FILL (master_pub,
      74              :             seed);
      75            4 :   TDB_FILL (master_sig,
      76              :             seed);
      77            4 :   return TALER_EXCHANGEDB_insert_partner (pg,
      78              :                                           &master_pub,
      79              :                                           ts (from),
      80              :                                           ts (until),
      81              :                                           GNUNET_TIME_UNIT_HOURS,
      82              :                                           &wad_fee,
      83              :                                           url,
      84              :                                           &master_sig);
      85              : }
      86              : 
      87              : 
      88              : /**
      89              :  * Inserting a partner stores exactly the row we asked for.
      90              :  *
      91              :  * @param pg the database context
      92              :  * @return 0 on success
      93              :  */
      94              : static int
      95            1 : check_insert (struct TALER_EXCHANGEDB_PostgresContext *pg)
      96              : {
      97              :   struct TALER_MasterPublicKeyP master_pub;
      98            1 :   struct TALER_Amount wad_fee = TDB_amount ("0.05");
      99              :   char *hex;
     100              : 
     101            1 :   FAILIF (0 != TDB_count (pg,
     102              :                           "FROM partners"));
     103            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     104              :           add_partner (pg,
     105              :                        10,
     106              :                        1600000000,
     107              :                        1700000000,
     108              :                        "https://partner.example/"));
     109            1 :   TDB_FILL (master_pub,
     110              :             10);
     111            1 :   hex = TDB_hex (&master_pub,
     112              :                  sizeof (master_pub));
     113            1 :   FAILIF_C (1 != TDB_count (pg,
     114              :                             "FROM partners"
     115              :                             " WHERE partner_master_pub=decode('%s','hex')"
     116              :                             "   AND partner_base_url='https://partner.example/'"
     117              :                             "   AND wad_fee=ROW(%llu,%u)::taler_amount"
     118              :                             "   AND start_date=%llu"
     119              :                             "   AND end_date=%llu",
     120              :                             hex,
     121              :                             (unsigned long long) wad_fee.value,
     122              :                             (unsigned int) wad_fee.fraction,
     123              :                             (unsigned long long) 1600000000000000LLU,
     124              :                             (unsigned long long) 1700000000000000LLU),
     125              :             GNUNET_free (hex));
     126            1 :   GNUNET_free (hex);
     127            1 :   return 0;
     128              : }
     129              : 
     130              : 
     131              : /**
     132              :  * Re-inserting the identical row is a no-op, while a different validity
     133              :  * period for the same key is a new row.
     134              :  *
     135              :  * @param pg the database context
     136              :  * @return 0 on success
     137              :  */
     138              : static int
     139            1 : check_conflict (struct TALER_EXCHANGEDB_PostgresContext *pg)
     140              : {
     141              :   /* identical to what check_insert() stored */
     142            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
     143              :           add_partner (pg,
     144              :                        10,
     145              :                        1600000000,
     146              :                        1700000000,
     147              :                        "https://partner.example/"));
     148            1 :   FAILIF (1 != TDB_count (pg,
     149              :                           "FROM partners"));
     150              :   /* a later period for the same partner is a separate row */
     151            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     152              :           add_partner (pg,
     153              :                        10,
     154              :                        1700000000,
     155              :                        1800000000,
     156              :                        "https://partner.example/"));
     157            1 :   FAILIF (2 != TDB_count (pg,
     158              :                           "FROM partners"));
     159              :   /* and so is a different partner */
     160            1 :   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
     161              :           add_partner (pg,
     162              :                        11,
     163              :                        1600000000,
     164              :                        1700000000,
     165              :                        "https://other.example/"));
     166            1 :   FAILIF (3 != TDB_count (pg,
     167              :                           "FROM partners"));
     168            1 :   return 0;
     169              : }
     170              : 
     171              : 
     172              : /**
     173              :  * The checks to run, in order.
     174              :  */
     175              : static const struct TDB_Test tests[] = {
     176              :   { "partners-insert",
     177              :     &check_insert },
     178              :   { "partners-conflict",
     179              :     &check_conflict },
     180              :   { NULL, NULL }
     181              : };
     182              : 
     183              : 
     184              : int
     185            1 : main (int argc,
     186              :       char *const *argv)
     187              : {
     188            1 :   return TDB_main (argc,
     189              :                    argv,
     190              :                    "test-partners",
     191              :                    "Tests for the exchangedb `partners' table",
     192              :                    tests);
     193              : }
     194              : 
     195              : 
     196              : /* end of test_partners.c */
        

Generated by: LCOV version 2.0-1