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 (24451B)


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