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 */