donau

Donation authority for GNU Taler (experimental)
Log | Files | Refs | Submodules | README | LICENSE

test_donaudb.c (15739B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 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 donaudb/test_donaudb.c
     18  * @brief test cases for DB interaction functions
     19  * @author Johannes Casaburi
     20  */
     21 #include "donau_config.h"
     22 #include <taler/taler_json_lib.h>
     23 #include "donaudb_lib.h"
     24 #include "donau_util.h"
     25 #include "donaudb_lib.h"
     26 #include "donau-database/commit.h"
     27 #include "donau-database/create_tables.h"
     28 #include "donau-database/do_charity_delete.h"
     29 #include "donau-database/drop_tables.h"
     30 #include "donau-database/event_listen_cancel.h"
     31 #include "donau-database/event_listen.h"
     32 #include "donau-database/event_notify.h"
     33 #include "donau-database/get_charities.h"
     34 #include "donau-database/get_history.h"
     35 #include "donau-database/insert_charity.h"
     36 #include "donau-database/insert_donation_unit.h"
     37 #include "donau-database/insert_history_entry.h"
     38 #include "donau-database/insert_issued_receipt.h"
     39 #include "donau-database/insert_signing_key.h"
     40 #include "donau-database/insert_submitted_receipts.h"
     41 #include "donau-database/iterate_active_signing_keys.h"
     42 #include "donau-database/iterate_donation_units.h"
     43 #include "donau-database/iterate_submitted_receipts.h"
     44 #include "donau-database/lookup_charity.h"
     45 #include "donau-database/lookup_donation_unit_amount.h"
     46 #include "donau-database/lookup_issued_receipts.h"
     47 #include "donau-database/lookup_signing_key.h"
     48 #include "donau-database/preflight.h"
     49 #include "donau-database/rollback.h"
     50 #include "donau-database/start.h"
     51 #include "donau-database/start_read_committed.h"
     52 #include "donau-database/start_read_only.h"
     53 #include "donau-database/update_charity.h"
     54 
     55 /**
     56  * Global result from the testcase.
     57  */
     58 static int result;
     59 
     60 /**
     61  * Report line of error if @a cond is true, and jump to label "drop".
     62  */
     63 #define FAILIF(cond)                              \
     64         do {                                          \
     65           if (! (cond)) { break;}                      \
     66           GNUNET_break (0);                           \
     67           goto drop;                                  \
     68         } while (0)
     69 
     70 
     71 /**
     72  * Initializes @a ptr with random data.
     73  */
     74 #define RND_BLK(ptr)                                                    \
     75         GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, ptr, sizeof (* \
     76                                                                              ptr))
     77 
     78 /**
     79  * Initializes @a ptr with zeros.
     80  */
     81 #define ZR_BLK(ptr) \
     82         memset (ptr, 0, sizeof (*ptr))
     83 
     84 /**
     85  * How big do we make the RSA keys?
     86  */
     87 #define RSA_KEY_SIZE 1024
     88 
     89 /**
     90  * Currency we use.  Must match test-donau-db-*.conf.
     91  */
     92 #define CURRENCY "EUR"
     93 
     94 /**
     95  * Database plugin under test.
     96  */
     97 static struct DONAUDB_PostgresContext *ctx;
     98 
     99 /**
    100  * Return charities information.
    101  *
    102  * @param cls closure
    103  */
    104 static enum GNUNET_GenericReturnValue
    105 charities_cb (
    106   void *cls,
    107   uint64_t charity_id,
    108   const struct DONAU_CharityPublicKeyP *charity_pub,
    109   const char *charity_name,
    110   const struct TALER_Amount *max_per_year,
    111   uint32_t current_year,
    112   const struct TALER_Amount *receipts_to_date)
    113 {
    114   (void) cls;
    115   (void) charity_id;
    116   (void) charity_name;
    117   (void) max_per_year;
    118   (void) current_year;
    119   (void) receipts_to_date;
    120   return GNUNET_OK;
    121 }
    122 
    123 
    124 /**
    125  * Function called with information about the donau's donation_unit keys.
    126  *
    127  * @param cls NULL
    128  * @param donation_unit_pub public key of the donation_unit
    129  * @param h_donation_unit_pub hash of @a donation_unit_pub
    130  * @param validity_year of the donation unit
    131  * @param value of the donation unit
    132  */
    133 static enum GNUNET_GenericReturnValue
    134 donation_unit_info_cb (
    135   void *cls,
    136   const struct DONAU_DonationUnitHashP *h_donation_unit_pub,
    137   const struct DONAU_DonationUnitPublicKey *donation_unit_pub,
    138   uint64_t validity_year,
    139   struct TALER_Amount *value)
    140 {
    141   (void) cls;
    142   (void) h_donation_unit_pub;
    143   (void) donation_unit_pub;
    144   (void) validity_year;
    145   (void) value;
    146   return GNUNET_OK;
    147 }
    148 
    149 
    150 /**
    151  * Function called with information about the donau's online signing keys.
    152  *
    153  * @param cls NULL
    154  * @param donau_pub the public key
    155  * @param meta meta data information about the denomination type (expirations)
    156  */
    157 static void
    158 iterate_active_signing_keys_cb (
    159   void *cls,
    160   const struct DONAU_DonauPublicKeyP *donau_pub,
    161   struct DONAUDB_SignkeyMetaData *meta)
    162 {
    163   (void) cls;
    164   (void) donau_pub;
    165   (void) meta;
    166 }
    167 
    168 
    169 /**
    170  * Main function that will be run by the scheduler.
    171  *
    172  * @param cls closure with config
    173  */
    174 static void
    175 run (void *cls)
    176 {
    177   struct GNUNET_CONFIGURATION_Handle *cfg = cls;
    178   struct GNUNET_TIME_Timestamp now;
    179 
    180   // Charity information
    181   json_t *charities;
    182   struct DONAU_CharityPublicKeyP charity_pub;
    183   struct DONAUDB_CharityMetaData charity_meta;
    184   const char *charity_name;
    185   const char *charity_url;
    186   struct TALER_Amount max_per_year;
    187   struct TALER_Amount receipts_to_date;
    188   uint64_t charity_id;
    189 
    190   // Donation unit information
    191   struct DONAU_DonationUnitHashP h_donation_unit_pub;
    192   uint64_t validity_year;
    193   struct TALER_Amount du_value;
    194 
    195   // Signing key information
    196   struct DONAU_DonauPublicKeyP donau_pub;
    197   struct DONAUDB_SignkeyMetaData sk_meta;
    198 
    199   // Issued receipts information
    200   size_t num_b_sigs = 1;
    201   struct DONAU_BlindedDonationUnitSignature du_sigs[num_b_sigs];
    202   struct DONAU_DonationReceiptHashP h_receipt;
    203   struct TALER_Amount amount_receipts;
    204   bool smaller_than_max_per_year;
    205   struct TALER_DenominationPrivateKey denom_priv;
    206   struct TALER_DenominationPublicKey denom_pub;
    207   struct DONAU_DonationUnitPublicKey du_pub;
    208   struct GNUNET_CRYPTO_BlindedMessage *rp;
    209   struct GNUNET_CRYPTO_RsaBlindedMessage *rsa;
    210 
    211   if (NULL ==
    212       (ctx = DONAUDB_connect (cfg)))
    213   {
    214     fprintf (stderr,
    215              "Failed to connect to database\n");
    216     result = 77;
    217     return;
    218   }
    219   (void) DONAUDB_drop_tables (ctx);
    220   if (GNUNET_OK !=
    221       DONAUDB_create_tables (ctx))
    222   {
    223     fprintf (stderr,
    224              "Failed to create DB tables\n");
    225     result = 77;
    226     goto cleanup;
    227   }
    228   DONAUDB_preflight (ctx);
    229   FAILIF (GNUNET_OK !=
    230           DONAUDB_start (ctx,
    231                          "test-1"));
    232 
    233   fprintf (stderr,
    234            "Running DB tests\n");
    235 
    236   /* test DB is empty */
    237   charity_id = 1;
    238   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
    239           DONAUDB_lookup_charity (ctx,
    240                                   charity_id,
    241                                   &charity_meta));
    242 
    243   /* test insert charity */
    244   charity_name = "charity_name";
    245   charity_url = "charity_url";
    246   charities = json_array ();
    247   RND_BLK (&charity_pub);
    248   GNUNET_assert (GNUNET_OK ==
    249                  TALER_string_to_amount (CURRENCY ":1.000010",
    250                                          &max_per_year));
    251   GNUNET_assert (GNUNET_OK ==
    252                  TALER_string_to_amount (CURRENCY ":0.000010",
    253                                          &receipts_to_date));
    254 
    255   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    256           DONAUDB_insert_charity (ctx,
    257                                   &charity_pub,
    258                                   charity_name,
    259                                   charity_url,
    260                                   &max_per_year,
    261                                   &charity_id));
    262 
    263   /* test get charities */
    264   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    265           DONAUDB_get_charities (ctx,
    266                                  &charities_cb,
    267                                  charities));
    268 
    269   {
    270     /* Update the charity and verify the new key and metadata persist. */
    271     const char *updated_charity_name = "charity_name_updated";
    272     const char *updated_charity_url = "charity_url_updated";
    273     struct TALER_Amount updated_max;
    274     struct DONAU_CharityPrivateKeyP updated_charity_priv;
    275     struct DONAU_CharityPublicKeyP updated_charity_pub;
    276 
    277     GNUNET_CRYPTO_eddsa_key_create (&updated_charity_priv.eddsa_priv);
    278     GNUNET_CRYPTO_eddsa_key_get_public (&updated_charity_priv.eddsa_priv,
    279                                         &updated_charity_pub.eddsa_pub);
    280 
    281     GNUNET_assert (GNUNET_OK ==
    282                    TALER_string_to_amount (CURRENCY ":2.000000",
    283                                            &updated_max));
    284     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    285             DONAUDB_update_charity (ctx,
    286                                     charity_id,
    287                                     &updated_charity_pub,
    288                                     updated_charity_name,
    289                                     updated_charity_url,
    290                                     &updated_max));
    291 
    292     ZR_BLK (&charity_meta);
    293     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    294             DONAUDB_lookup_charity (ctx,
    295                                     charity_id,
    296                                     &charity_meta));
    297     GNUNET_assert (0 == GNUNET_memcmp (&charity_meta.charity_pub,
    298                                        &updated_charity_pub));
    299     GNUNET_assert (0 == strcmp (charity_meta.charity_name,
    300                                 updated_charity_name));
    301     GNUNET_assert (0 == strcmp (charity_meta.charity_url,
    302                                 updated_charity_url));
    303     GNUNET_assert (0 == TALER_amount_cmp (&charity_meta.max_per_year,
    304                                           &updated_max));
    305     GNUNET_free (charity_meta.charity_name);
    306     GNUNET_free (charity_meta.charity_url);
    307 
    308     charity_name = updated_charity_name;
    309     charity_url = updated_charity_url;
    310     max_per_year = updated_max;
    311     charity_pub = updated_charity_pub;
    312   }
    313 
    314   /* test delete charity */
    315   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
    316           DONAUDB_do_charity_delete (ctx,
    317                                      charity_id));
    318 
    319   /* test insert donation unit */
    320   RND_BLK (&h_donation_unit_pub);
    321   GNUNET_assert (GNUNET_OK ==
    322                  TALER_denom_priv_create (&denom_priv,
    323                                           &denom_pub,
    324                                           GNUNET_CRYPTO_BSA_RSA,
    325                                           RSA_KEY_SIZE));
    326   du_pub.bsign_pub_key = denom_pub.bsign_pub_key;
    327   validity_year = 2024;
    328   GNUNET_assert (GNUNET_OK ==
    329                  TALER_string_to_amount (CURRENCY ":1.000010",
    330                                          &du_value));
    331 
    332   /* test iterate donation units */
    333   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
    334           DONAUDB_iterate_donation_units (ctx,
    335                                           &donation_unit_info_cb,
    336                                           NULL));
    337 
    338   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    339           DONAUDB_insert_donation_unit (ctx,
    340                                         &h_donation_unit_pub,
    341                                         &du_pub,
    342                                         validity_year,
    343                                         &du_value));
    344 
    345   /* test iterate donation units */
    346   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    347           DONAUDB_iterate_donation_units (ctx,
    348                                           &donation_unit_info_cb,
    349                                           NULL));
    350 
    351   TALER_denom_pub_free (&denom_pub);
    352 
    353   /* test insert signing key */
    354   RND_BLK (&donau_pub);
    355   now = GNUNET_TIME_timestamp_get ();
    356   sk_meta.expire_legal = now;
    357   sk_meta.expire_sign = now;
    358   sk_meta.valid_from = now;
    359 
    360   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    361           DONAUDB_insert_signing_key (ctx,
    362                                       &donau_pub,
    363                                       &sk_meta));
    364 
    365   /* test iterate signing key */
    366   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    367           DONAUDB_iterate_active_signing_keys (ctx,
    368                                                &iterate_active_signing_keys_cb,
    369                                                NULL));
    370 
    371   /* test insert issued receipt */
    372   rp = GNUNET_new (struct GNUNET_CRYPTO_BlindedMessage);
    373   rp->cipher = GNUNET_CRYPTO_BSA_RSA;
    374   rp->rc = 1;
    375   rsa = &rp->details.rsa_blinded_message;
    376   rsa->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
    377     GNUNET_CRYPTO_QUALITY_WEAK,
    378     (RSA_KEY_SIZE / 8) - 1);
    379   rsa->blinded_msg = GNUNET_malloc (rsa->blinded_msg_size);
    380   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
    381                               rsa->blinded_msg,
    382                               rsa->blinded_msg_size);
    383   smaller_than_max_per_year = false;
    384   GNUNET_assert (GNUNET_OK ==
    385                  TALER_string_to_amount (CURRENCY ":1.000010",
    386                                          &amount_receipts));
    387 
    388   du_sigs[0].blinded_sig =
    389     GNUNET_CRYPTO_blind_sign (denom_priv.bsign_priv_key,
    390                               "rw",
    391                               rp);
    392 
    393   GNUNET_assert (NULL != du_sigs[0].blinded_sig);
    394   TALER_denom_priv_free (&denom_priv);
    395 
    396   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    397           DONAUDB_insert_issued_receipt (ctx,
    398                                          num_b_sigs,
    399                                          du_sigs,
    400                                          charity_id,
    401                                          &h_receipt,
    402                                          &amount_receipts,
    403                                          &smaller_than_max_per_year));
    404 
    405   // FIXME
    406   // FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    407   //         DONAUDB_lookup_issued_receipts (ctx,
    408   //                                         &h_receipt,
    409   //                                         &ir_meta));
    410 
    411   /* test insert submitted receipts */
    412   // RND_BLK (&h_donor_tax_id);
    413   // RND_BLK (&donation_receipts[0].h_donation_unit_pub);
    414   // RND_BLK (&donation_receipts[0].nonce);
    415   // RND_BLK (&donation_receipts[0].donation_unit_sig);
    416   // FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
    417   //         DONAUDB_insert_submitted_receipts (ctx,
    418   //                                            &h_donor_tax_id,
    419   //                                            num_dr,
    420   //                                            donation_receipts,
    421   //                                            current_year));
    422 
    423   DONAUDB_preflight (ctx);
    424 
    425   result = 0;
    426 
    427 drop:
    428   if (0 != result)
    429     DONAUDB_rollback (ctx);
    430   GNUNET_break (GNUNET_OK ==
    431                 DONAUDB_drop_tables (ctx));
    432 cleanup:
    433   DONAUDB_disconnect (ctx);
    434   ctx = NULL;
    435 }
    436 
    437 
    438 int
    439 main (int argc,
    440       char *const argv[])
    441 {
    442   const char *plugin_name;
    443   char *config_filename;
    444   char *testname;
    445   struct GNUNET_CONFIGURATION_Handle *cfg;
    446 
    447   (void) argc;
    448   result = -1;
    449   if (NULL == (plugin_name = strrchr (argv[0], (int) '-')))
    450   {
    451     GNUNET_break (0);
    452     return -1;
    453   }
    454   GNUNET_log_setup (argv[0],
    455                     "INFO",
    456                     NULL);
    457   plugin_name++;
    458   (void) GNUNET_asprintf (&testname,
    459                           "test-donau-db-%s",
    460                           plugin_name);
    461   (void) GNUNET_asprintf (&config_filename,
    462                           "%s.conf",
    463                           testname);
    464   cfg = GNUNET_CONFIGURATION_create (DONAU_project_data ());
    465   if (GNUNET_OK !=
    466       GNUNET_CONFIGURATION_parse (cfg,
    467                                   config_filename))
    468   {
    469     GNUNET_break (0);
    470     GNUNET_free (config_filename);
    471     GNUNET_free (testname);
    472     return 2;
    473   }
    474   GNUNET_SCHEDULER_run (&run,
    475                         cfg);
    476   GNUNET_CONFIGURATION_destroy (cfg);
    477   GNUNET_free (config_filename);
    478   GNUNET_free (testname);
    479   return result;
    480 }
    481 
    482 
    483 /* end of test_donaudb.c */