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


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