test_auditordb.c (19945B)
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 (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 { 221 result = 77; 222 return; 223 } 224 GNUNET_assert (GNUNET_OK == 225 TALER_AUDITORDB_preflight (pg)); 226 (void) TALER_AUDITORDB_drop_tables (pg, 227 GNUNET_YES); 228 if (GNUNET_OK != 229 TALER_AUDITORDB_create_tables (pg, 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 "test-auditordb")); 246 247 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 248 "initializing\n"); 249 250 GNUNET_assert (GNUNET_OK == 251 TALER_string_to_amount (CURRENCY ":1.000010", 252 &value)); 253 GNUNET_assert (GNUNET_OK == 254 TALER_string_to_amount (CURRENCY ":0.000011", 255 &fee_withdraw)); 256 GNUNET_assert (GNUNET_OK == 257 TALER_string_to_amount (CURRENCY ":0.000012", 258 &fee_deposit)); 259 GNUNET_assert (GNUNET_OK == 260 TALER_string_to_amount (CURRENCY ":0.000013", 261 &fee_refresh)); 262 GNUNET_assert (GNUNET_OK == 263 TALER_string_to_amount (CURRENCY ":0.000014", 264 &fee_refund)); 265 RND_BLK (&reserve_pub); 266 RND_BLK (&rnd_hash); 267 GNUNET_assert (GNUNET_OK == 268 TALER_denom_priv_create (&denom_priv, 269 &denom_pub, 270 GNUNET_CRYPTO_BSA_RSA, 271 1024)); 272 TALER_denom_pub_hash (&denom_pub, 273 &denom_pub_hash); 274 TALER_denom_priv_free (&denom_priv); 275 TALER_denom_pub_free (&denom_pub); 276 277 now = GNUNET_TIME_timestamp_get (); 278 past = GNUNET_TIME_absolute_to_timestamp ( 279 GNUNET_TIME_absolute_subtract (now.abs_time, 280 GNUNET_TIME_relative_multiply ( 281 GNUNET_TIME_UNIT_HOURS, 282 4))); 283 future = GNUNET_TIME_absolute_to_timestamp ( 284 GNUNET_TIME_absolute_add (now.abs_time, 285 GNUNET_TIME_relative_multiply ( 286 GNUNET_TIME_UNIT_HOURS, 287 4))); 288 289 { 290 struct TALER_AUDITORDB_ReserveFeeBalance rfb; 291 struct TALER_AUDITORDB_ReserveFeeBalance rfb2; 292 293 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 294 "Test: insert_reserve_info\n"); 295 GNUNET_assert (GNUNET_OK == 296 TALER_string_to_amount (CURRENCY ":12.345678", 297 &rfb.reserve_balance)); 298 GNUNET_assert (GNUNET_OK == 299 TALER_string_to_amount (CURRENCY ":11.245678", 300 &rfb.reserve_loss)); 301 GNUNET_assert (GNUNET_OK == 302 TALER_string_to_amount (CURRENCY ":23.456789", 303 &rfb.withdraw_fee_balance)); 304 GNUNET_assert (GNUNET_OK == 305 TALER_string_to_amount (CURRENCY ":23.456719", 306 &rfb.close_fee_balance)); 307 GNUNET_assert (GNUNET_OK == 308 TALER_string_to_amount (CURRENCY ":33.456789", 309 &rfb.purse_fee_balance)); 310 GNUNET_assert (GNUNET_OK == 311 TALER_string_to_amount (CURRENCY ":43.456789", 312 &rfb.open_fee_balance)); 313 GNUNET_assert (GNUNET_OK == 314 TALER_string_to_amount (CURRENCY ":53.456789", 315 &rfb.history_fee_balance)); 316 { 317 struct TALER_FullPayto pt = { 318 .full_payto = (char *) "payto://bla/blub?receiver-name=blub" 319 }; 320 321 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 322 TALER_AUDITORDB_insert_reserve_info (pg, 323 &reserve_pub, 324 &rfb, 325 past, 326 pt)); 327 } 328 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 329 "Test: update_reserve_info\n"); 330 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 331 TALER_AUDITORDB_update_reserve_info (pg, 332 &reserve_pub, 333 &rfb, 334 future)); 335 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 336 "Test: get_reserve_info\n"); 337 { 338 struct TALER_FullPayto payto; 339 340 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 341 TALER_AUDITORDB_get_reserve_info (pg, 342 &reserve_pub, 343 &rowid, 344 &rfb2, 345 &date, 346 &payto)); 347 FAILIF (0 != strcmp (payto.full_payto, 348 "payto://bla/blub?receiver-name=blub")); 349 GNUNET_free (payto.full_payto); 350 } 351 FAILIF ( (0 != GNUNET_memcmp (&date, 352 &future)) 353 || (0 != TALER_amount_cmp (&rfb2.reserve_balance, 354 &rfb.reserve_balance)) 355 || (0 != TALER_amount_cmp (&rfb2.withdraw_fee_balance, 356 &rfb.withdraw_fee_balance)) 357 || (0 != TALER_amount_cmp (&rfb2.close_fee_balance, 358 &rfb.close_fee_balance)) 359 || (0 != TALER_amount_cmp (&rfb2.purse_fee_balance, 360 &rfb.purse_fee_balance)) 361 || (0 != TALER_amount_cmp (&rfb2.open_fee_balance, 362 &rfb.open_fee_balance)) 363 || (0 != TALER_amount_cmp (&rfb2.history_fee_balance, 364 &rfb.history_fee_balance)) 365 ); 366 } 367 368 { 369 struct TALER_AUDITORDB_ClosureLags cl = { 370 .problem_row_id = 42 371 }; 372 373 GNUNET_assert (GNUNET_OK == 374 TALER_string_to_amount (CURRENCY ":12.345678", 375 &cl.amount)); 376 cl.account.full_payto 377 = (char *) "payto://unspec/foo?receiver-name=bar"; 378 memset (&cl.wtid, 379 42, 380 sizeof (cl.wtid)); 381 cl.deadline = GNUNET_TIME_absolute_get (); 382 FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != 383 TALER_AUDITORDB_delete_auditor_closure_lag (pg, 384 &cl.amount, 385 &cl.wtid, 386 cl.account)); 387 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 388 TALER_AUDITORDB_insert_auditor_closure_lags (pg, 389 &cl)); 390 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 391 TALER_AUDITORDB_delete_auditor_closure_lag (pg, 392 &cl.amount, 393 &cl.wtid, 394 cl.account)); 395 } 396 397 { 398 struct TALER_AUDITORDB_DenominationCirculationData dcd; 399 struct TALER_AUDITORDB_DenominationCirculationData dcd2; 400 401 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 402 "Test: insert_denomination_balance\n"); 403 GNUNET_assert (GNUNET_OK == 404 TALER_string_to_amount (CURRENCY ":12.345678", 405 &dcd.denom_balance)); 406 GNUNET_assert (GNUNET_OK == 407 TALER_string_to_amount (CURRENCY ":0.1", 408 &dcd.denom_loss)); 409 GNUNET_assert (GNUNET_OK == 410 TALER_string_to_amount (CURRENCY ":13.57986", 411 &dcd.denom_risk)); 412 GNUNET_assert (GNUNET_OK == 413 TALER_string_to_amount (CURRENCY ":12.57986", 414 &dcd.recoup_loss)); 415 dcd.num_issued = 62; 416 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 417 TALER_AUDITORDB_insert_denomination_balance (pg, 418 &denom_pub_hash, 419 &dcd)); 420 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 421 "Test: update_denomination_balance\n"); 422 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 423 TALER_AUDITORDB_update_denomination_balance (pg, 424 &denom_pub_hash, 425 &dcd)); 426 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 427 "Test: get_denomination_balance\n"); 428 429 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 430 TALER_AUDITORDB_get_denomination_balance (pg, 431 &denom_pub_hash, 432 &dcd2)); 433 FAILIF (0 != TALER_amount_cmp (&dcd2.denom_balance, 434 &dcd.denom_balance)); 435 FAILIF (0 != TALER_amount_cmp (&dcd2.denom_loss, 436 &dcd.denom_loss)); 437 FAILIF (0 != TALER_amount_cmp (&dcd2.denom_risk, 438 &dcd.denom_risk)); 439 FAILIF (0 != TALER_amount_cmp (&dcd2.recoup_loss, 440 &dcd.recoup_loss)); 441 FAILIF (dcd2.num_issued != dcd.num_issued); 442 } 443 444 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 445 "Test: insert_historic_denom_revenue\n"); 446 GNUNET_assert (GNUNET_OK == 447 TALER_string_to_amount (CURRENCY ":12.345678", 448 &rbalance)); 449 GNUNET_assert (GNUNET_OK == 450 TALER_string_to_amount (CURRENCY ":23.456789", 451 &rloss)); 452 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 453 TALER_AUDITORDB_insert_historic_denom_revenue (pg, 454 &denom_pub_hash, 455 past, 456 &rbalance, 457 &rloss)); 458 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 459 TALER_AUDITORDB_insert_historic_denom_revenue (pg, 460 &rnd_hash, 461 now, 462 &rbalance, 463 &rloss)); 464 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 465 "Test: select_historic_denom_revenue\n"); 466 FAILIF (0 >= 467 TALER_AUDITORDB_select_historic_denom_revenue ( 468 pg, 469 1024, /* limit */ 470 0, /* offset */ 471 &select_historic_denom_revenue_result, 472 NULL)); 473 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 474 "Test: insert_historic_reserve_revenue\n"); 475 GNUNET_assert (GNUNET_OK == 476 TALER_string_to_amount (CURRENCY ":56.789012", 477 &reserve_profits)); 478 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 479 TALER_AUDITORDB_insert_historic_reserve_revenue (pg, 480 past, 481 future, 482 &reserve_profits)); 483 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 484 TALER_AUDITORDB_insert_historic_reserve_revenue (pg, 485 now, 486 future, 487 &reserve_profits)); 488 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 489 "Test: select_historic_reserve_revenue\n"); 490 FAILIF (0 >= 491 TALER_AUDITORDB_select_historic_reserve_revenue ( 492 pg, 493 1024, /* limit */ 494 0, /* offset */ 495 &select_historic_reserve_revenue_result, 496 NULL)); 497 498 FAILIF (0 > 499 TALER_AUDITORDB_commit (pg)); 500 501 FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != 502 TALER_AUDITORDB_del_reserve_info (pg, 503 &reserve_pub)); 504 505 #if GC_IMPLEMENTED 506 FAILIF (GNUNET_OK != 507 TALER_AUDITORDB_gc (pg)); 508 #endif 509 510 result = 0; 511 512 drop: 513 TALER_AUDITORDB_rollback (pg); 514 GNUNET_break (GNUNET_OK == 515 TALER_AUDITORDB_drop_tables (pg, 516 GNUNET_YES)); 517 unload: 518 TALER_AUDITORDB_disconnect (pg); 519 pg = NULL; 520 } 521 522 523 int 524 main (int argc, 525 char *const argv[]) 526 { 527 struct GNUNET_CONFIGURATION_Handle *cfg; 528 529 (void) argc; 530 result = -1; 531 GNUNET_log_setup (argv[0], 532 "WARNING", 533 NULL); 534 cfg = GNUNET_CONFIGURATION_create (TALER_AUDITOR_project_data ()); 535 if (GNUNET_OK != 536 GNUNET_CONFIGURATION_parse (cfg, 537 "test-auditor-db-postgres.conf")) 538 { 539 GNUNET_break (0); 540 return 2; 541 } 542 GNUNET_SCHEDULER_run (&run, 543 cfg); 544 GNUNET_CONFIGURATION_destroy (cfg); 545 return result; 546 }