exchange

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

test_auditordb_checkpoints.c (11745B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2016--2024 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_checkpoints.c
     18  * @brief test cases for DB interaction functions
     19  * @author Christian Grothoff
     20  */
     21 #include <gnunet/gnunet_common.h>
     22 #include <gnunet/gnunet_db_lib.h>
     23 #include "auditordb_lib.h"
     24 #include "auditor-database/create_tables.h"
     25 #include "auditor-database/drop_tables.h"
     26 #include "auditor-database/get_auditor_progress.h"
     27 #include "auditor-database/get_balance.h"
     28 #include "auditor-database/insert_auditor_progress.h"
     29 #include "auditor-database/insert_balance.h"
     30 #include "auditor-database/preflight.h"
     31 #include "auditor-database/start.h"
     32 #include "auditor-database/update_auditor_progress.h"
     33 #include "auditor-database/update_balance.h"
     34 
     35 
     36 /**
     37  * Currency we use, must match CURRENCY in "test-auditor-db-postgres.conf".
     38  */
     39 #define CURRENCY "EUR"
     40 
     41 /**
     42  * Report line of error if @a cond is true, and jump to label "drop".
     43  */
     44 #define FAILIF(cond)                              \
     45         do {                                          \
     46           if (! (cond)) { break;}                     \
     47           GNUNET_break (0);                         \
     48           goto drop;                                \
     49         } while (0)
     50 
     51 /**
     52  * Initializes @a ptr with random data.
     53  */
     54 #define RND_BLK(ptr)                                                    \
     55         GNUNET_CRYPTO_random_block (ptr, \
     56                                     sizeof (*ptr))
     57 
     58 /**
     59  * Initializes @a ptr with zeros.
     60  */
     61 #define ZR_BLK(ptr) \
     62         memset (ptr, 0, sizeof (*ptr))
     63 
     64 
     65 /**
     66  * Global result from the testcase.
     67  */
     68 static int result = -1;
     69 
     70 /**
     71  * Database connection under test.
     72  */
     73 static struct TALER_AUDITORDB_PostgresContext *pg;
     74 
     75 
     76 /**
     77  * Main function that will be run by the scheduler.
     78  *
     79  * @param cls closure with config
     80  */
     81 static void
     82 run (void *cls)
     83 {
     84   struct GNUNET_CONFIGURATION_Handle *cfg = cls;
     85   struct TALER_Amount a1;
     86   struct TALER_Amount a2;
     87   struct TALER_Amount a3;
     88 
     89   GNUNET_assert (GNUNET_OK ==
     90                  TALER_string_to_amount (CURRENCY ":11.245678",
     91                                          &a1));
     92   GNUNET_assert (GNUNET_OK ==
     93                  TALER_string_to_amount (CURRENCY ":2",
     94                                          &a2));
     95   GNUNET_assert (GNUNET_OK ==
     96                  TALER_string_to_amount (CURRENCY ":3",
     97                                          &a3));
     98 
     99   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    100               "Connecting to database\n");
    101   if (NULL ==
    102       (pg = TALER_AUDITORDB_connect (cfg)))
    103   {
    104     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    105                 "Failed to connect to database\n");
    106     result = 77;
    107     return;
    108   }
    109   GNUNET_assert (GNUNET_OK ==
    110                  TALER_AUDITORDB_preflight (pg));
    111   (void) TALER_AUDITORDB_drop_tables (pg,
    112                                       GNUNET_YES);
    113   if (GNUNET_OK !=
    114       TALER_AUDITORDB_create_tables (pg,
    115                                      false,
    116                                      0))
    117   {
    118     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    119                 "Failed to 'create_tables'\n");
    120     result = 77;
    121     goto unload;
    122   }
    123   if (GNUNET_SYSERR ==
    124       TALER_AUDITORDB_preflight (pg))
    125   {
    126     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    127                 "Failed preflight check\n");
    128     result = 77;
    129     goto drop;
    130   }
    131 
    132   FAILIF (GNUNET_OK !=
    133           TALER_AUDITORDB_start (pg,
    134                                  "test-auditordb-checkpoints"));
    135 
    136   /* Test inserting a blank value, should tell us one result */
    137   GNUNET_assert (
    138     GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
    139     TALER_AUDITORDB_insert_auditor_progress (pg,
    140                                              "Test",
    141                                              69,
    142                                              NULL)
    143     );
    144   /* Test re-inserting the same value; should yield no results */
    145   GNUNET_assert (
    146     GNUNET_DB_STATUS_SUCCESS_NO_RESULTS ==
    147     TALER_AUDITORDB_insert_auditor_progress (pg,
    148                                              "Test",
    149                                              69,
    150                                              NULL)
    151     );
    152   /* Test inserting multiple values, with one already existing */
    153   GNUNET_assert (
    154     2 == TALER_AUDITORDB_insert_auditor_progress (pg,
    155                                                   "Test",
    156                                                   69,
    157                                                   "Test2",
    158                                                   123,
    159                                                   "Test3",
    160                                                   245,
    161                                                   NULL)
    162     );
    163   /* Test re-re-inserting the same key with a different value; should also yield no results */
    164   GNUNET_assert (
    165     GNUNET_DB_STATUS_SUCCESS_NO_RESULTS ==
    166     TALER_AUDITORDB_insert_auditor_progress (pg,
    167                                              "Test",
    168                                              42,
    169                                              NULL)
    170     );
    171   /* Test updating the same key (again) with a different value; should yield a result */
    172   GNUNET_assert (
    173     GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
    174     TALER_AUDITORDB_update_auditor_progress (pg,
    175                                              "Test",
    176                                              42,
    177                                              NULL)
    178     );
    179   /* Test updating a key that doesn't exist; should yield 0 */
    180   GNUNET_assert (
    181     GNUNET_DB_STATUS_SUCCESS_NO_RESULTS ==
    182     TALER_AUDITORDB_update_auditor_progress (pg,
    183                                              "NonexistentTest",
    184                                              1,
    185                                              NULL)
    186     );
    187 
    188   /* Right now, the state should look like this:
    189    * Test  = 42
    190    * Test2 = 123
    191    * Test3 = 245
    192    * Let's make sure that's the case! */
    193   {
    194     uint64_t value;
    195     uint64_t valueNX;
    196     uint64_t value3;
    197 
    198     GNUNET_assert (
    199       3 ==
    200       TALER_AUDITORDB_get_auditor_progress (
    201         pg,
    202         "Test",
    203         &value,
    204         "TestNX",
    205         &valueNX,
    206         "Test3",
    207         &value3,
    208         NULL)
    209       );
    210     GNUNET_assert (value == 42);
    211     GNUNET_assert (valueNX == 0);
    212     GNUNET_assert (value3 == 245);
    213   }
    214   /* Ensure the rest are also at their expected values */
    215   {
    216     uint64_t value;
    217 
    218     GNUNET_assert (
    219       GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
    220       TALER_AUDITORDB_get_auditor_progress (
    221         pg,
    222         "Test2",
    223         &value,
    224         NULL)
    225       );
    226     GNUNET_assert (value == 123);
    227   }
    228   {
    229     uint64_t value;
    230 
    231     GNUNET_assert (
    232       GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
    233       TALER_AUDITORDB_get_auditor_progress (
    234         pg,
    235         "Test3",
    236         &value,
    237         NULL)
    238       );
    239     GNUNET_assert (value == 245);
    240   }
    241   {
    242     uint64_t value;
    243 
    244     /* Try fetching value that does not exist */
    245     GNUNET_assert (
    246       GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
    247       TALER_AUDITORDB_get_auditor_progress (
    248         pg,
    249         "TestNX",
    250         &value,
    251         NULL)
    252       );
    253     GNUNET_assert (0 == value);
    254   }
    255 
    256   /* Test inserting a blank value, should tell us one result */
    257   GNUNET_assert (
    258     GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
    259     TALER_AUDITORDB_insert_balance (pg,
    260                                     "Test",
    261                                     &a1,
    262                                     NULL)
    263     );
    264   /* Test re-inserting the same value; should yield no results */
    265   GNUNET_assert (
    266     GNUNET_DB_STATUS_SUCCESS_NO_RESULTS ==
    267     TALER_AUDITORDB_insert_balance (pg,
    268                                     "Test",
    269                                     &a1,
    270                                     NULL)
    271     );
    272   /* Test inserting multiple values, with one already existing */
    273   GNUNET_assert (
    274     2 == TALER_AUDITORDB_insert_balance (pg,
    275                                          "Test",
    276                                          &a1,
    277                                          "Test2",
    278                                          &a2,
    279                                          "Test3",
    280                                          &a3,
    281                                          NULL)
    282     );
    283   /* Test re-re-inserting the same key with a different value; should also yield no results */
    284   GNUNET_assert (
    285     GNUNET_DB_STATUS_SUCCESS_NO_RESULTS ==
    286     TALER_AUDITORDB_insert_balance (pg,
    287                                     "Test",
    288                                     &a2,
    289                                     NULL)
    290     );
    291   /* Test updating the same key (again) with a different value; should yield a result */
    292   GNUNET_assert (
    293     GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
    294     TALER_AUDITORDB_update_balance (pg,
    295                                     "Test",
    296                                     &a2,
    297                                     NULL)
    298     );
    299   /* Test updating a key that doesn't exist; should yield 0 */
    300   GNUNET_assert (
    301     GNUNET_DB_STATUS_SUCCESS_NO_RESULTS ==
    302     TALER_AUDITORDB_update_balance (pg,
    303                                     "NonexistentTest",
    304                                     &a2,
    305                                     NULL)
    306     );
    307 
    308   /* Right now, the state should look like this:
    309    * Test  = a2
    310    * Test2 = a2
    311    * Test3 = a3
    312    * Let's make sure that's the case! */
    313   GNUNET_assert (
    314     GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
    315     TALER_AUDITORDB_get_balance (
    316       pg,
    317       "Test",
    318       &a1,
    319       NULL)
    320     );
    321   GNUNET_assert (0 ==
    322                  TALER_amount_cmp (&a1,
    323                                    &a2));
    324 
    325   /* Ensure the rest are also at their expected values */
    326   GNUNET_assert (
    327     GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
    328     TALER_AUDITORDB_get_balance (
    329       pg,
    330       "Test2",
    331       &a1,
    332       NULL)
    333     );
    334   GNUNET_assert (0 ==
    335                  TALER_amount_cmp (&a1,
    336                                    &a2));
    337   GNUNET_assert (
    338     GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
    339     TALER_AUDITORDB_get_balance (
    340       pg,
    341       "Test3",
    342       &a1,
    343       NULL)
    344     );
    345   GNUNET_assert (0 ==
    346                  TALER_amount_cmp (&a1,
    347                                    &a3));
    348 
    349   /* Try fetching value that does not exist */
    350   GNUNET_assert (
    351     GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
    352     TALER_AUDITORDB_get_balance (
    353       pg,
    354       "TestNX",
    355       &a1,
    356       NULL)
    357     );
    358   GNUNET_assert (TALER_amount_is_zero (&a1));
    359 
    360   result = 0;
    361   GNUNET_break (0 <=
    362                 TALER_AUDITORDB_commit (pg));
    363 drop:
    364   GNUNET_break (GNUNET_OK ==
    365                 TALER_AUDITORDB_drop_tables (pg,
    366                                              GNUNET_YES));
    367 unload:
    368   TALER_AUDITORDB_disconnect (pg);
    369   pg = NULL;
    370 }
    371 
    372 
    373 int
    374 main (int argc,
    375       char *const argv[])
    376 {
    377   struct GNUNET_CONFIGURATION_Handle *cfg;
    378 
    379   (void) argc;
    380   result = -1;
    381   GNUNET_log_setup (argv[0],
    382                     "INFO",
    383                     NULL);
    384   cfg = GNUNET_CONFIGURATION_create (TALER_AUDITOR_project_data ());
    385   if (GNUNET_OK !=
    386       GNUNET_CONFIGURATION_parse (cfg,
    387                                   "test-auditor-db-postgres.conf"))
    388   {
    389     GNUNET_break (0);
    390     return 2;
    391   }
    392   GNUNET_SCHEDULER_run (&run, cfg);
    393   GNUNET_CONFIGURATION_destroy (cfg);
    394   return result;
    395 }