test_auditordb.c (19915B)
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/del_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_reserve_info.h" 31 #include "auditor-database/insert_auditor_closure_lags.h" 32 #include "auditor-database/insert_denomination_balance.h" 33 #include "auditor-database/insert_historic_denom_revenue.h" 34 #include "auditor-database/insert_historic_reserve_revenue.h" 35 #include "auditor-database/insert_reserve_info.h" 36 #include "auditor-database/preflight.h" 37 #include "auditor-database/select_historic_denom_revenue.h" 38 #include "auditor-database/select_historic_reserve_revenue.h" 39 #include "auditor-database/start.h" 40 #include "auditor-database/update_denomination_balance.h" 41 #include "auditor-database/update_reserve_info.h" 42 43 /** 44 * Currency we use, must match CURRENCY in "test-auditor-db-postgres.conf". 45 */ 46 #define CURRENCY "EUR" 47 48 /** 49 * Report line of error if @a cond is true, and jump to label "drop". 50 */ 51 #define FAILIF(cond) \ 52 do { \ 53 if (! (cond)) { break;} \ 54 GNUNET_break (0); \ 55 goto drop; \ 56 } while (0) 57 58 /** 59 * Initializes @a ptr with random data. 60 */ 61 #define RND_BLK(ptr) \ 62 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, ptr, sizeof (* \ 63 ptr)) 64 65 /** 66 * Initializes @a ptr with zeros. 67 */ 68 #define ZR_BLK(ptr) \ 69 memset (ptr, 0, sizeof (*ptr)) 70 71 72 /** 73 * Global result from the testcase. 74 */ 75 static int result = -1; 76 77 /** 78 * Hash of denomination public key. 79 */ 80 static struct TALER_DenominationHashP denom_pub_hash; 81 82 /** 83 * Another hash of a denomination public key. 84 */ 85 static struct TALER_DenominationHashP rnd_hash; 86 87 /** 88 * Current time. 89 */ 90 static struct GNUNET_TIME_Timestamp now; 91 92 /** 93 * Timestamp in the past. 94 */ 95 static struct GNUNET_TIME_Timestamp past; 96 97 /** 98 * Timestamp in the future. 99 */ 100 static struct GNUNET_TIME_Timestamp future; 101 102 /** 103 * Database under test. 104 */ 105 static struct TALER_AUDITORDB_PostgresContext *pg; 106 107 /** 108 * Historic denomination revenue value. 109 */ 110 static struct TALER_Amount rbalance; 111 112 /** 113 * Historic denomination loss value. 114 */ 115 static struct TALER_Amount rloss; 116 117 /** 118 * Reserve profit value we are using. 119 */ 120 static struct TALER_Amount reserve_profits; 121 122 123 static enum GNUNET_GenericReturnValue 124 select_historic_denom_revenue_result ( 125 void *cls, 126 uint64_t rowid, 127 const struct TALER_DenominationHashP *denom_pub_hash2, 128 struct GNUNET_TIME_Timestamp revenue_timestamp2, 129 const struct TALER_Amount *revenue_balance2, 130 const struct TALER_Amount *loss2) 131 { 132 static int n = 0; 133 134 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 135 "select_historic_denom_revenue_result: row %u\n", n); 136 137 if ( (2 <= n++) 138 || (cls != NULL) 139 || ((0 != GNUNET_memcmp (&revenue_timestamp2, 140 &past)) 141 && (0 != GNUNET_memcmp (&revenue_timestamp2, 142 &now))) 143 || ((0 != GNUNET_memcmp (denom_pub_hash2, 144 &denom_pub_hash)) 145 && (0 != GNUNET_memcmp (denom_pub_hash2, 146 &rnd_hash))) 147 || (0 != TALER_amount_cmp (revenue_balance2, 148 &rbalance)) 149 || (0 != TALER_amount_cmp (loss2, 150 &rloss))) 151 { 152 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 153 "select_historic_denom_revenue_result: result does not match\n") 154 ; 155 GNUNET_break (0); 156 return GNUNET_SYSERR; 157 } 158 return GNUNET_OK; 159 } 160 161 162 static enum GNUNET_GenericReturnValue 163 select_historic_reserve_revenue_result ( 164 void *cls, 165 uint64_t rowid, 166 struct GNUNET_TIME_Timestamp start_time2, 167 struct GNUNET_TIME_Timestamp end_time2, 168 const struct TALER_Amount *reserve_profits2) 169 { 170 static int n = 0; 171 172 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 173 "select_historic_reserve_revenue_result: row %u\n", n); 174 175 if ((2 <= n++) 176 || (cls != NULL) 177 || ((0 != GNUNET_memcmp (&start_time2, 178 &past)) 179 && (0 != GNUNET_memcmp (&start_time2, 180 &now))) 181 || (0 != GNUNET_memcmp (&end_time2, 182 &future)) 183 || (0 != TALER_amount_cmp (reserve_profits2, 184 &reserve_profits))) 185 { 186 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 187 "select_historic_reserve_revenue_result: result does not match\n"); 188 GNUNET_break (0); 189 return GNUNET_SYSERR; 190 } 191 return GNUNET_OK; 192 } 193 194 195 /** 196 * Main function that will be run by the scheduler. 197 * 198 * @param cls closure with config 199 */ 200 static void 201 run (void *cls) 202 { 203 struct GNUNET_CONFIGURATION_Handle *cfg = cls; 204 uint64_t rowid; 205 struct TALER_Amount value; 206 struct TALER_Amount fee_withdraw; 207 struct TALER_Amount fee_deposit; 208 struct TALER_Amount fee_refresh; 209 struct TALER_Amount fee_refund; 210 struct TALER_ReservePublicKeyP reserve_pub; 211 struct TALER_DenominationPrivateKey denom_priv; 212 struct TALER_DenominationPublicKey denom_pub; 213 struct GNUNET_TIME_Timestamp date; 214 215 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 216 "connecting to database\n"); 217 218 if (NULL == 219 (pg = TALER_AUDITORDB_connect (cfg, 220 true))) 221 { 222 result = 77; 223 return; 224 } 225 226 (void) TALER_AUDITORDB_drop_tables (pg, 227 GNUNET_YES); 228 if (GNUNET_OK != 229 TALER_AUDITORDB_create_tables (cfg, 230 false, 231 0)) 232 { 233 result = 77; 234 goto unload; 235 } 236 if (GNUNET_SYSERR == 237 TALER_AUDITORDB_preflight (pg)) 238 { 239 result = 77; 240 goto drop; 241 } 242 243 FAILIF (GNUNET_OK != 244 TALER_AUDITORDB_start (pg)); 245 246 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 247 "initializing\n"); 248 249 GNUNET_assert (GNUNET_OK == 250 TALER_string_to_amount (CURRENCY ":1.000010", 251 &value)); 252 GNUNET_assert (GNUNET_OK == 253 TALER_string_to_amount (CURRENCY ":0.000011", 254 &fee_withdraw)); 255 GNUNET_assert (GNUNET_OK == 256 TALER_string_to_amount (CURRENCY ":0.000012", 257 &fee_deposit)); 258 GNUNET_assert (GNUNET_OK == 259 TALER_string_to_amount (CURRENCY ":0.000013", 260 &fee_refresh)); 261 GNUNET_assert (GNUNET_OK == 262 TALER_string_to_amount (CURRENCY ":0.000014", 263 &fee_refund)); 264 RND_BLK (&reserve_pub); 265 RND_BLK (&rnd_hash); 266 GNUNET_assert (GNUNET_OK == 267 TALER_denom_priv_create (&denom_priv, 268 &denom_pub, 269 GNUNET_CRYPTO_BSA_RSA, 270 1024)); 271 TALER_denom_pub_hash (&denom_pub, 272 &denom_pub_hash); 273 TALER_denom_priv_free (&denom_priv); 274 TALER_denom_pub_free (&denom_pub); 275 276 now = GNUNET_TIME_timestamp_get (); 277 past = GNUNET_TIME_absolute_to_timestamp ( 278 GNUNET_TIME_absolute_subtract (now.abs_time, 279 GNUNET_TIME_relative_multiply ( 280 GNUNET_TIME_UNIT_HOURS, 281 4))); 282 future = GNUNET_TIME_absolute_to_timestamp ( 283 GNUNET_TIME_absolute_add (now.abs_time, 284 GNUNET_TIME_relative_multiply ( 285 GNUNET_TIME_UNIT_HOURS, 286 4))); 287 288 { 289 struct TALER_AUDITORDB_ReserveFeeBalance rfb; 290 struct TALER_AUDITORDB_ReserveFeeBalance rfb2; 291 292 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 293 "Test: insert_reserve_info\n"); 294 GNUNET_assert (GNUNET_OK == 295 TALER_string_to_amount (CURRENCY ":12.345678", 296 &rfb.reserve_balance)); 297 GNUNET_assert (GNUNET_OK == 298 TALER_string_to_amount (CURRENCY ":11.245678", 299 &rfb.reserve_loss)); 300 GNUNET_assert (GNUNET_OK == 301 TALER_string_to_amount (CURRENCY ":23.456789", 302 &rfb.withdraw_fee_balance)); 303 GNUNET_assert (GNUNET_OK == 304 TALER_string_to_amount (CURRENCY ":23.456719", 305 &rfb.close_fee_balance)); 306 GNUNET_assert (GNUNET_OK == 307 TALER_string_to_amount (CURRENCY ":33.456789", 308 &rfb.purse_fee_balance)); 309 GNUNET_assert (GNUNET_OK == 310 TALER_string_to_amount (CURRENCY ":43.456789", 311 &rfb.open_fee_balance)); 312 GNUNET_assert (GNUNET_OK == 313 TALER_string_to_amount (CURRENCY ":53.456789", 314 &rfb.history_fee_balance)); 315 { 316 struct TALER_FullPayto pt = { 317 .full_payto = (char *) "payto://bla/blub?receiver-name=blub" 318 }; 319 320 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 321 TALER_AUDITORDB_insert_reserve_info (pg, 322 &reserve_pub, 323 &rfb, 324 past, 325 pt)); 326 } 327 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 328 "Test: update_reserve_info\n"); 329 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 330 TALER_AUDITORDB_update_reserve_info (pg, 331 &reserve_pub, 332 &rfb, 333 future)); 334 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 335 "Test: get_reserve_info\n"); 336 { 337 struct TALER_FullPayto payto; 338 339 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 340 TALER_AUDITORDB_get_reserve_info (pg, 341 &reserve_pub, 342 &rowid, 343 &rfb2, 344 &date, 345 &payto)); 346 FAILIF (0 != strcmp (payto.full_payto, 347 "payto://bla/blub?receiver-name=blub")); 348 GNUNET_free (payto.full_payto); 349 } 350 FAILIF ( (0 != GNUNET_memcmp (&date, 351 &future)) 352 || (0 != TALER_amount_cmp (&rfb2.reserve_balance, 353 &rfb.reserve_balance)) 354 || (0 != TALER_amount_cmp (&rfb2.withdraw_fee_balance, 355 &rfb.withdraw_fee_balance)) 356 || (0 != TALER_amount_cmp (&rfb2.close_fee_balance, 357 &rfb.close_fee_balance)) 358 || (0 != TALER_amount_cmp (&rfb2.purse_fee_balance, 359 &rfb.purse_fee_balance)) 360 || (0 != TALER_amount_cmp (&rfb2.open_fee_balance, 361 &rfb.open_fee_balance)) 362 || (0 != TALER_amount_cmp (&rfb2.history_fee_balance, 363 &rfb.history_fee_balance)) 364 ); 365 } 366 367 { 368 struct TALER_AUDITORDB_ClosureLags cl = { 369 .problem_row_id = 42 370 }; 371 372 GNUNET_assert (GNUNET_OK == 373 TALER_string_to_amount (CURRENCY ":12.345678", 374 &cl.amount)); 375 cl.account.full_payto 376 = (char *) "payto://unspec/foo?receiver-name=bar"; 377 memset (&cl.wtid, 378 42, 379 sizeof (cl.wtid)); 380 cl.deadline = GNUNET_TIME_absolute_get (); 381 FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != 382 TALER_AUDITORDB_delete_auditor_closure_lag (pg, 383 &cl.amount, 384 &cl.wtid, 385 cl.account)); 386 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 387 TALER_AUDITORDB_insert_auditor_closure_lags (pg, 388 &cl)); 389 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 390 TALER_AUDITORDB_delete_auditor_closure_lag (pg, 391 &cl.amount, 392 &cl.wtid, 393 cl.account)); 394 } 395 396 { 397 struct TALER_AUDITORDB_DenominationCirculationData dcd; 398 struct TALER_AUDITORDB_DenominationCirculationData dcd2; 399 400 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 401 "Test: insert_denomination_balance\n"); 402 GNUNET_assert (GNUNET_OK == 403 TALER_string_to_amount (CURRENCY ":12.345678", 404 &dcd.denom_balance)); 405 GNUNET_assert (GNUNET_OK == 406 TALER_string_to_amount (CURRENCY ":0.1", 407 &dcd.denom_loss)); 408 GNUNET_assert (GNUNET_OK == 409 TALER_string_to_amount (CURRENCY ":13.57986", 410 &dcd.denom_risk)); 411 GNUNET_assert (GNUNET_OK == 412 TALER_string_to_amount (CURRENCY ":12.57986", 413 &dcd.recoup_loss)); 414 dcd.num_issued = 62; 415 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 416 TALER_AUDITORDB_insert_denomination_balance (pg, 417 &denom_pub_hash, 418 &dcd)); 419 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 420 "Test: update_denomination_balance\n"); 421 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 422 TALER_AUDITORDB_update_denomination_balance (pg, 423 &denom_pub_hash, 424 &dcd)); 425 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 426 "Test: get_denomination_balance\n"); 427 428 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 429 TALER_AUDITORDB_get_denomination_balance (pg, 430 &denom_pub_hash, 431 &dcd2)); 432 FAILIF (0 != TALER_amount_cmp (&dcd2.denom_balance, 433 &dcd.denom_balance)); 434 FAILIF (0 != TALER_amount_cmp (&dcd2.denom_loss, 435 &dcd.denom_loss)); 436 FAILIF (0 != TALER_amount_cmp (&dcd2.denom_risk, 437 &dcd.denom_risk)); 438 FAILIF (0 != TALER_amount_cmp (&dcd2.recoup_loss, 439 &dcd.recoup_loss)); 440 FAILIF (dcd2.num_issued != dcd.num_issued); 441 } 442 443 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 444 "Test: insert_historic_denom_revenue\n"); 445 GNUNET_assert (GNUNET_OK == 446 TALER_string_to_amount (CURRENCY ":12.345678", 447 &rbalance)); 448 GNUNET_assert (GNUNET_OK == 449 TALER_string_to_amount (CURRENCY ":23.456789", 450 &rloss)); 451 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 452 TALER_AUDITORDB_insert_historic_denom_revenue (pg, 453 &denom_pub_hash, 454 past, 455 &rbalance, 456 &rloss)); 457 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 458 TALER_AUDITORDB_insert_historic_denom_revenue (pg, 459 &rnd_hash, 460 now, 461 &rbalance, 462 &rloss)); 463 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 464 "Test: select_historic_denom_revenue\n"); 465 FAILIF (0 >= 466 TALER_AUDITORDB_select_historic_denom_revenue ( 467 pg, 468 1024, /* limit */ 469 0, /* offset */ 470 &select_historic_denom_revenue_result, 471 NULL)); 472 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 473 "Test: insert_historic_reserve_revenue\n"); 474 GNUNET_assert (GNUNET_OK == 475 TALER_string_to_amount (CURRENCY ":56.789012", 476 &reserve_profits)); 477 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 478 TALER_AUDITORDB_insert_historic_reserve_revenue (pg, 479 past, 480 future, 481 &reserve_profits)); 482 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 483 TALER_AUDITORDB_insert_historic_reserve_revenue (pg, 484 now, 485 future, 486 &reserve_profits)); 487 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 488 "Test: select_historic_reserve_revenue\n"); 489 FAILIF (0 >= 490 TALER_AUDITORDB_select_historic_reserve_revenue ( 491 pg, 492 1024, /* limit */ 493 0, /* offset */ 494 &select_historic_reserve_revenue_result, 495 NULL)); 496 497 FAILIF (0 > 498 TALER_AUDITORDB_commit (pg)); 499 500 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 501 TALER_AUDITORDB_del_reserve_info (pg, 502 &reserve_pub)); 503 504 #if GC_IMPLEMENTED 505 FAILIF (GNUNET_OK != 506 TALER_AUDITORDB_gc (pg)); 507 #endif 508 509 result = 0; 510 511 drop: 512 TALER_AUDITORDB_rollback (pg); 513 GNUNET_break (GNUNET_OK == 514 TALER_AUDITORDB_drop_tables (pg, 515 GNUNET_YES)); 516 unload: 517 TALER_AUDITORDB_disconnect (pg); 518 pg = NULL; 519 } 520 521 522 int 523 main (int argc, 524 char *const argv[]) 525 { 526 struct GNUNET_CONFIGURATION_Handle *cfg; 527 528 (void) argc; 529 result = -1; 530 GNUNET_log_setup (argv[0], 531 "WARNING", 532 NULL); 533 cfg = GNUNET_CONFIGURATION_create (TALER_AUDITOR_project_data ()); 534 if (GNUNET_OK != 535 GNUNET_CONFIGURATION_parse (cfg, 536 "test-auditor-db-postgres.conf")) 537 { 538 GNUNET_break (0); 539 return 2; 540 } 541 GNUNET_SCHEDULER_run (&run, 542 cfg); 543 GNUNET_CONFIGURATION_destroy (cfg); 544 return result; 545 }