exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

test_auditordb.c (21088B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2016--2022 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 auditordb/test_auditordb.c
     18  * @brief test cases for DB interaction functions
     19  * @author Gabor X Toth
     20  * @author Christian Grothoff
     21  */
     22 #include <gnunet/gnunet_db_lib.h>
     23 #include "auditordb_lib.h"
     24 #include "auditor-database/create_tables.h"
     25 #include "auditor-database/delete_reserve_info.h"
     26 #include "auditor-database/delete_auditor_closure_lag.h"
     27 #include "auditor-database/drop_tables.h"
     28 #include "auditor-database/gc.h"
     29 #include "auditor-database/get_denomination_balance.h"
     30 #include "auditor-database/get_exists_historic_denom_revenue.h"
     31 #include "auditor-database/get_reserve_info.h"
     32 #include "auditor-database/insert_auditor_closure_lags.h"
     33 #include "auditor-database/insert_denomination_balance.h"
     34 #include "auditor-database/insert_historic_denom_revenue.h"
     35 #include "auditor-database/insert_historic_reserve_revenue.h"
     36 #include "auditor-database/insert_reserve_info.h"
     37 #include "auditor-database/preflight.h"
     38 #include "auditor-database/iterate_historic_denom_revenue.h"
     39 #include "auditor-database/iterate_historic_reserve_revenue.h"
     40 #include "auditor-database/start.h"
     41 #include "auditor-database/update_denomination_balance.h"
     42 #include "auditor-database/update_reserve_info.h"
     43 
     44 /**
     45  * Currency we use, must match CURRENCY in "test-auditor-db-postgres.conf".
     46  */
     47 #define CURRENCY "EUR"
     48 
     49 /**
     50  * Report line of error if @a cond is true, and jump to label "drop".
     51  */
     52 #define FAILIF(cond)                              \
     53         do {                                          \
     54           if (! (cond)) { break;}                     \
     55           GNUNET_break (0);                         \
     56           goto drop;                                \
     57         } while (0)
     58 
     59 /**
     60  * Initializes @a ptr with random data.
     61  */
     62 #define RND_BLK(ptr)                                                    \
     63         GNUNET_CRYPTO_random_block (ptr, sizeof (* \
     64                                                  ptr))
     65 
     66 /**
     67  * Initializes @a ptr with zeros.
     68  */
     69 #define ZR_BLK(ptr) \
     70         memset (ptr, 0, sizeof (*ptr))
     71 
     72 
     73 /**
     74  * Global result from the testcase.
     75  */
     76 static int result = -1;
     77 
     78 /**
     79  * Hash of denomination public key.
     80  */
     81 static struct TALER_DenominationHashP denom_pub_hash;
     82 
     83 /**
     84  * Another hash of a denomination public key.
     85  */
     86 static struct TALER_DenominationHashP rnd_hash;
     87 
     88 /**
     89  * Current time.
     90  */
     91 static struct GNUNET_TIME_Timestamp now;
     92 
     93 /**
     94  * Timestamp in the past.
     95  */
     96 static struct GNUNET_TIME_Timestamp past;
     97 
     98 /**
     99  * Timestamp in the future.
    100  */
    101 static struct GNUNET_TIME_Timestamp future;
    102 
    103 /**
    104  * Database under test.
    105  */
    106 static struct TALER_AUDITORDB_PostgresContext *pg;
    107 
    108 /**
    109  * Historic denomination revenue value.
    110  */
    111 static struct TALER_Amount rbalance;
    112 
    113 /**
    114  * Historic denomination loss value.
    115  */
    116 static struct TALER_Amount rloss;
    117 
    118 /**
    119  * Reserve profit value we are using.
    120  */
    121 static struct TALER_Amount reserve_profits;
    122 
    123 
    124 static enum GNUNET_GenericReturnValue
    125 select_historic_denom_revenue_result (
    126   void *cls,
    127   uint64_t rowid,
    128   const struct TALER_DenominationHashP *denom_pub_hash2,
    129   struct GNUNET_TIME_Timestamp revenue_timestamp2,
    130   const struct TALER_Amount *revenue_balance2,
    131   const struct TALER_Amount *loss2)
    132 {
    133   static int n = 0;
    134 
    135   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    136               "select_historic_denom_revenue_result: row %u\n", n);
    137 
    138   if ( (3 <= n++)
    139        || (cls != NULL)
    140        || ((0 != GNUNET_memcmp (&revenue_timestamp2,
    141                                 &past))
    142            && (0 != GNUNET_memcmp (&revenue_timestamp2,
    143                                    &now)))
    144        || ((0 != GNUNET_memcmp (denom_pub_hash2,
    145                                 &denom_pub_hash))
    146            && (0 != GNUNET_memcmp (denom_pub_hash2,
    147                                    &rnd_hash)))
    148        || (0 != TALER_amount_cmp (revenue_balance2,
    149                                   &rbalance))
    150        || (0 != TALER_amount_cmp (loss2,
    151                                   &rloss)))
    152   {
    153     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    154                 "select_historic_denom_revenue_result: result does not match\n")
    155     ;
    156     GNUNET_break (0);
    157     return GNUNET_SYSERR;
    158   }
    159   return GNUNET_OK;
    160 }
    161 
    162 
    163 static enum GNUNET_GenericReturnValue
    164 select_historic_reserve_revenue_result (
    165   void *cls,
    166   uint64_t rowid,
    167   struct GNUNET_TIME_Timestamp start_time2,
    168   struct GNUNET_TIME_Timestamp end_time2,
    169   const struct TALER_Amount *reserve_profits2)
    170 {
    171   static int n = 0;
    172 
    173   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    174               "select_historic_reserve_revenue_result: row %u\n", n);
    175 
    176   if ((2 <= n++)
    177       || (cls != NULL)
    178       || ((0 != GNUNET_memcmp (&start_time2,
    179                                &past))
    180           && (0 != GNUNET_memcmp (&start_time2,
    181                                   &now)))
    182       || (0 != GNUNET_memcmp (&end_time2,
    183                               &future))
    184       || (0 != TALER_amount_cmp (reserve_profits2,
    185                                  &reserve_profits)))
    186   {
    187     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    188                 "select_historic_reserve_revenue_result: result does not match\n");
    189     GNUNET_break (0);
    190     return GNUNET_SYSERR;
    191   }
    192   return GNUNET_OK;
    193 }
    194 
    195 
    196 /**
    197  * Main function that will be run by the scheduler.
    198  *
    199  * @param cls closure with config
    200  */
    201 static void
    202 run (void *cls)
    203 {
    204   struct GNUNET_CONFIGURATION_Handle *cfg = cls;
    205   uint64_t rowid;
    206   struct TALER_Amount value;
    207   struct TALER_Amount fee_withdraw;
    208   struct TALER_Amount fee_deposit;
    209   struct TALER_Amount fee_refresh;
    210   struct TALER_Amount fee_refund;
    211   struct TALER_ReservePublicKeyP reserve_pub;
    212   struct TALER_DenominationPrivateKey denom_priv;
    213   struct TALER_DenominationPublicKey denom_pub;
    214   struct GNUNET_TIME_Timestamp date;
    215 
    216   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    217               "connecting to database\n");
    218 
    219   if (NULL ==
    220       (pg = TALER_AUDITORDB_connect (cfg)))
    221   {
    222     result = 77;
    223     return;
    224   }
    225   GNUNET_assert (GNUNET_OK ==
    226                  TALER_AUDITORDB_preflight (pg));
    227   (void) TALER_AUDITORDB_drop_tables (pg,
    228                                       GNUNET_YES);
    229   if (GNUNET_OK !=
    230       TALER_AUDITORDB_create_tables (pg,
    231                                      false,
    232                                      0))
    233   {
    234     result = 77;
    235     goto unload;
    236   }
    237   if (GNUNET_SYSERR ==
    238       TALER_AUDITORDB_preflight (pg))
    239   {
    240     result = 77;
    241     goto drop;
    242   }
    243 
    244   FAILIF (GNUNET_OK !=
    245           TALER_AUDITORDB_start (pg,
    246                                  "test-auditordb"));
    247 
    248   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    249               "initializing\n");
    250 
    251   GNUNET_assert (GNUNET_OK ==
    252                  TALER_string_to_amount (CURRENCY ":1.000010",
    253                                          &value));
    254   GNUNET_assert (GNUNET_OK ==
    255                  TALER_string_to_amount (CURRENCY ":0.000011",
    256                                          &fee_withdraw));
    257   GNUNET_assert (GNUNET_OK ==
    258                  TALER_string_to_amount (CURRENCY ":0.000012",
    259                                          &fee_deposit));
    260   GNUNET_assert (GNUNET_OK ==
    261                  TALER_string_to_amount (CURRENCY ":0.000013",
    262                                          &fee_refresh));
    263   GNUNET_assert (GNUNET_OK ==
    264                  TALER_string_to_amount (CURRENCY ":0.000014",
    265                                          &fee_refund));
    266   RND_BLK (&reserve_pub);
    267   RND_BLK (&rnd_hash);
    268   GNUNET_assert (GNUNET_OK ==
    269                  TALER_denom_priv_create (&denom_priv,
    270                                           &denom_pub,
    271                                           GNUNET_CRYPTO_BSA_RSA,
    272                                           1024));
    273   TALER_denom_pub_hash (&denom_pub,
    274                         &denom_pub_hash);
    275   TALER_denom_priv_free (&denom_priv);
    276   TALER_denom_pub_free (&denom_pub);
    277 
    278   now = GNUNET_TIME_timestamp_get ();
    279   past = GNUNET_TIME_absolute_to_timestamp (
    280     GNUNET_TIME_absolute_subtract (now.abs_time,
    281                                    GNUNET_TIME_relative_multiply (
    282                                      GNUNET_TIME_UNIT_HOURS,
    283                                      4)));
    284   future = GNUNET_TIME_absolute_to_timestamp (
    285     GNUNET_TIME_absolute_add (now.abs_time,
    286                               GNUNET_TIME_relative_multiply (
    287                                 GNUNET_TIME_UNIT_HOURS,
    288                                 4)));
    289 
    290   {
    291     struct TALER_AUDITORDB_ReserveFeeBalance rfb;
    292     struct TALER_AUDITORDB_ReserveFeeBalance rfb2;
    293 
    294     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    295                 "Test: insert_reserve_info\n");
    296     GNUNET_assert (GNUNET_OK ==
    297                    TALER_string_to_amount (CURRENCY ":12.345678",
    298                                            &rfb.reserve_balance));
    299     GNUNET_assert (GNUNET_OK ==
    300                    TALER_string_to_amount (CURRENCY ":11.245678",
    301                                            &rfb.reserve_loss));
    302     GNUNET_assert (GNUNET_OK ==
    303                    TALER_string_to_amount (CURRENCY ":23.456789",
    304                                            &rfb.withdraw_fee_balance));
    305     GNUNET_assert (GNUNET_OK ==
    306                    TALER_string_to_amount (CURRENCY ":23.456719",
    307                                            &rfb.close_fee_balance));
    308     GNUNET_assert (GNUNET_OK ==
    309                    TALER_string_to_amount (CURRENCY ":33.456789",
    310                                            &rfb.purse_fee_balance));
    311     GNUNET_assert (GNUNET_OK ==
    312                    TALER_string_to_amount (CURRENCY ":43.456789",
    313                                            &rfb.open_fee_balance));
    314     GNUNET_assert (GNUNET_OK ==
    315                    TALER_string_to_amount (CURRENCY ":53.456789",
    316                                            &rfb.history_fee_balance));
    317     {
    318       struct TALER_FullPayto pt = {
    319         .full_payto = (char *) "payto://bla/blub?receiver-name=blub"
    320       };
    321 
    322       FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    323               TALER_AUDITORDB_insert_reserve_info (pg,
    324                                                    &reserve_pub,
    325                                                    &rfb,
    326                                                    past,
    327                                                    pt));
    328     }
    329     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    330                 "Test: update_reserve_info\n");
    331     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    332             TALER_AUDITORDB_update_reserve_info (pg,
    333                                                  &reserve_pub,
    334                                                  &rfb,
    335                                                  future));
    336     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    337                 "Test: get_reserve_info\n");
    338     {
    339       struct TALER_FullPayto payto;
    340 
    341       FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    342               TALER_AUDITORDB_get_reserve_info (pg,
    343                                                 &reserve_pub,
    344                                                 &rowid,
    345                                                 &rfb2,
    346                                                 &date,
    347                                                 &payto));
    348       FAILIF (0 != strcmp (payto.full_payto,
    349                            "payto://bla/blub?receiver-name=blub"));
    350       GNUNET_free (payto.full_payto);
    351     }
    352     FAILIF ( (0 != GNUNET_memcmp (&date,
    353                                   &future))
    354              || (0 != TALER_amount_cmp (&rfb2.reserve_balance,
    355                                         &rfb.reserve_balance))
    356              || (0 != TALER_amount_cmp (&rfb2.withdraw_fee_balance,
    357                                         &rfb.withdraw_fee_balance))
    358              || (0 != TALER_amount_cmp (&rfb2.close_fee_balance,
    359                                         &rfb.close_fee_balance))
    360              || (0 != TALER_amount_cmp (&rfb2.purse_fee_balance,
    361                                         &rfb.purse_fee_balance))
    362              || (0 != TALER_amount_cmp (&rfb2.open_fee_balance,
    363                                         &rfb.open_fee_balance))
    364              || (0 != TALER_amount_cmp (&rfb2.history_fee_balance,
    365                                         &rfb.history_fee_balance))
    366              );
    367   }
    368 
    369   {
    370     struct TALER_AUDITORDB_ClosureLags cl = {
    371       .problem_row_id = 42
    372     };
    373 
    374     GNUNET_assert (GNUNET_OK ==
    375                    TALER_string_to_amount (CURRENCY ":12.345678",
    376                                            &cl.amount));
    377     cl.account.full_payto
    378       = (char *) "payto://unspec/foo?receiver-name=bar";
    379     memset (&cl.wtid,
    380             42,
    381             sizeof (cl.wtid));
    382     cl.deadline = GNUNET_TIME_absolute_get ();
    383     FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
    384             TALER_AUDITORDB_delete_auditor_closure_lag (pg,
    385                                                         &cl.amount,
    386                                                         &cl.wtid,
    387                                                         cl.account));
    388     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    389             TALER_AUDITORDB_insert_auditor_closure_lags (pg,
    390                                                          &cl));
    391     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    392             TALER_AUDITORDB_delete_auditor_closure_lag (pg,
    393                                                         &cl.amount,
    394                                                         &cl.wtid,
    395                                                         cl.account));
    396   }
    397 
    398   {
    399     struct TALER_AUDITORDB_DenominationCirculationData dcd;
    400     struct TALER_AUDITORDB_DenominationCirculationData dcd2;
    401 
    402     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    403                 "Test: insert_denomination_balance\n");
    404     GNUNET_assert (GNUNET_OK ==
    405                    TALER_string_to_amount (CURRENCY ":12.345678",
    406                                            &dcd.denom_balance));
    407     GNUNET_assert (GNUNET_OK ==
    408                    TALER_string_to_amount (CURRENCY ":0.1",
    409                                            &dcd.denom_loss));
    410     GNUNET_assert (GNUNET_OK ==
    411                    TALER_string_to_amount (CURRENCY ":13.57986",
    412                                            &dcd.denom_risk));
    413     GNUNET_assert (GNUNET_OK ==
    414                    TALER_string_to_amount (CURRENCY ":12.57986",
    415                                            &dcd.recoup_loss));
    416     dcd.num_issued = 62;
    417     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    418             TALER_AUDITORDB_insert_denomination_balance (pg,
    419                                                          &denom_pub_hash,
    420                                                          &dcd));
    421     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    422                 "Test: update_denomination_balance\n");
    423     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    424             TALER_AUDITORDB_update_denomination_balance (pg,
    425                                                          &denom_pub_hash,
    426                                                          &dcd));
    427     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    428                 "Test: get_denomination_balance\n");
    429 
    430     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    431             TALER_AUDITORDB_get_denomination_balance (pg,
    432                                                       &denom_pub_hash,
    433                                                       &dcd2));
    434     FAILIF (0 != TALER_amount_cmp (&dcd2.denom_balance,
    435                                    &dcd.denom_balance));
    436     FAILIF (0 != TALER_amount_cmp (&dcd2.denom_loss,
    437                                    &dcd.denom_loss));
    438     FAILIF (0 != TALER_amount_cmp (&dcd2.denom_risk,
    439                                    &dcd.denom_risk));
    440     FAILIF (0 != TALER_amount_cmp (&dcd2.recoup_loss,
    441                                    &dcd.recoup_loss));
    442     FAILIF (dcd2.num_issued != dcd.num_issued);
    443   }
    444 
    445   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    446               "Test: insert_historic_denom_revenue\n");
    447   GNUNET_assert (GNUNET_OK ==
    448                  TALER_string_to_amount (CURRENCY ":12.345678",
    449                                          &rbalance));
    450   GNUNET_assert (GNUNET_OK ==
    451                  TALER_string_to_amount (CURRENCY ":23.456789",
    452                                          &rloss));
    453   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    454           TALER_AUDITORDB_insert_historic_denom_revenue (pg,
    455                                                          &denom_pub_hash,
    456                                                          past,
    457                                                          &rbalance,
    458                                                          &rloss));
    459   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    460           TALER_AUDITORDB_insert_historic_denom_revenue (pg,
    461                                                          &rnd_hash,
    462                                                          now,
    463                                                          &rbalance,
    464                                                          &rloss));
    465   /* The table is append-only: a denomination that is credited after it was
    466      booked as finished gets another row instead of an update. */
    467   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    468           TALER_AUDITORDB_insert_historic_denom_revenue (pg,
    469                                                          &denom_pub_hash,
    470                                                          now,
    471                                                          &rbalance,
    472                                                          &rloss));
    473   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    474               "Test: get_exists_historic_denom_revenue\n");
    475   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    476           TALER_AUDITORDB_get_exists_historic_denom_revenue (pg,
    477                                                              &denom_pub_hash));
    478   {
    479     struct TALER_DenominationHashP unknown_hash;
    480 
    481     RND_BLK (&unknown_hash);
    482     FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
    483             TALER_AUDITORDB_get_exists_historic_denom_revenue (
    484               pg,
    485               &unknown_hash));
    486   }
    487   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    488               "Test: select_historic_denom_revenue\n");
    489   FAILIF (0 >=
    490           TALER_AUDITORDB_iterate_historic_denom_revenue (
    491             pg,
    492             1024, /* limit */
    493             0, /* offset */
    494             &select_historic_denom_revenue_result,
    495             NULL));
    496   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    497               "Test: insert_historic_reserve_revenue\n");
    498   GNUNET_assert (GNUNET_OK ==
    499                  TALER_string_to_amount (CURRENCY ":56.789012",
    500                                          &reserve_profits));
    501   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    502           TALER_AUDITORDB_insert_historic_reserve_revenue (pg,
    503                                                            past,
    504                                                            future,
    505                                                            &reserve_profits));
    506   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    507           TALER_AUDITORDB_insert_historic_reserve_revenue (pg,
    508                                                            now,
    509                                                            future,
    510                                                            &reserve_profits));
    511   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    512               "Test: select_historic_reserve_revenue\n");
    513   FAILIF (0 >=
    514           TALER_AUDITORDB_iterate_historic_reserve_revenue (
    515             pg,
    516             1024, /* limit */
    517             0,    /* offset */
    518             &select_historic_reserve_revenue_result,
    519             NULL));
    520 
    521   FAILIF (0 >
    522           TALER_AUDITORDB_commit (pg));
    523 
    524   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    525           TALER_AUDITORDB_delete_reserve_info (pg,
    526                                                &reserve_pub));
    527 
    528 #if GC_IMPLEMENTED
    529   FAILIF (GNUNET_OK !=
    530           TALER_AUDITORDB_gc (pg));
    531 #endif
    532 
    533   result = 0;
    534 
    535 drop:
    536   TALER_AUDITORDB_rollback (pg);
    537   GNUNET_break (GNUNET_OK ==
    538                 TALER_AUDITORDB_drop_tables (pg,
    539                                              GNUNET_YES));
    540 unload:
    541   TALER_AUDITORDB_disconnect (pg);
    542   pg = NULL;
    543 }
    544 
    545 
    546 int
    547 main (int argc,
    548       char *const argv[])
    549 {
    550   struct GNUNET_CONFIGURATION_Handle *cfg;
    551 
    552   (void) argc;
    553   result = -1;
    554   GNUNET_log_setup (argv[0],
    555                     "WARNING",
    556                     NULL);
    557   cfg = GNUNET_CONFIGURATION_create (TALER_AUDITOR_project_data ());
    558   if (GNUNET_OK !=
    559       GNUNET_CONFIGURATION_parse (cfg,
    560                                   "test-auditor-db-postgres.conf"))
    561   {
    562     GNUNET_break (0);
    563     return 2;
    564   }
    565   GNUNET_SCHEDULER_run (&run,
    566                         cfg);
    567   GNUNET_CONFIGURATION_destroy (cfg);
    568   return result;
    569 }