Line data Source code
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/delete_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/iterate_historic_denom_revenue.h"
38 : #include "auditor-database/iterate_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 2 : 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 2 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
135 : "select_historic_denom_revenue_result: row %u\n", n);
136 :
137 2 : if ( (2 <= n++)
138 2 : || (cls != NULL)
139 2 : || ((0 != GNUNET_memcmp (&revenue_timestamp2,
140 : &past))
141 1 : && (0 != GNUNET_memcmp (&revenue_timestamp2,
142 : &now)))
143 2 : || ((0 != GNUNET_memcmp (denom_pub_hash2,
144 : &denom_pub_hash))
145 1 : && (0 != GNUNET_memcmp (denom_pub_hash2,
146 : &rnd_hash)))
147 2 : || (0 != TALER_amount_cmp (revenue_balance2,
148 : &rbalance))
149 2 : || (0 != TALER_amount_cmp (loss2,
150 : &rloss)))
151 : {
152 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
153 : "select_historic_denom_revenue_result: result does not match\n")
154 : ;
155 0 : GNUNET_break (0);
156 0 : return GNUNET_SYSERR;
157 : }
158 2 : return GNUNET_OK;
159 : }
160 :
161 :
162 : static enum GNUNET_GenericReturnValue
163 2 : 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 2 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
173 : "select_historic_reserve_revenue_result: row %u\n", n);
174 :
175 2 : if ((2 <= n++)
176 2 : || (cls != NULL)
177 2 : || ((0 != GNUNET_memcmp (&start_time2,
178 : &past))
179 1 : && (0 != GNUNET_memcmp (&start_time2,
180 : &now)))
181 2 : || (0 != GNUNET_memcmp (&end_time2,
182 : &future))
183 2 : || (0 != TALER_amount_cmp (reserve_profits2,
184 : &reserve_profits)))
185 : {
186 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
187 : "select_historic_reserve_revenue_result: result does not match\n");
188 0 : GNUNET_break (0);
189 0 : return GNUNET_SYSERR;
190 : }
191 2 : 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 1 : run (void *cls)
202 : {
203 1 : 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 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
216 : "connecting to database\n");
217 :
218 1 : if (NULL ==
219 1 : (pg = TALER_AUDITORDB_connect (cfg)))
220 : {
221 0 : result = 77;
222 0 : return;
223 : }
224 1 : GNUNET_assert (GNUNET_OK ==
225 : TALER_AUDITORDB_preflight (pg));
226 1 : (void) TALER_AUDITORDB_drop_tables (pg,
227 : GNUNET_YES);
228 1 : if (GNUNET_OK !=
229 1 : TALER_AUDITORDB_create_tables (pg,
230 : false,
231 : 0))
232 : {
233 0 : result = 77;
234 0 : goto unload;
235 : }
236 1 : if (GNUNET_SYSERR ==
237 1 : TALER_AUDITORDB_preflight (pg))
238 : {
239 0 : result = 77;
240 0 : goto drop;
241 : }
242 :
243 1 : FAILIF (GNUNET_OK !=
244 : TALER_AUDITORDB_start (pg,
245 : "test-auditordb"));
246 :
247 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
248 : "initializing\n");
249 :
250 1 : GNUNET_assert (GNUNET_OK ==
251 : TALER_string_to_amount (CURRENCY ":1.000010",
252 : &value));
253 1 : GNUNET_assert (GNUNET_OK ==
254 : TALER_string_to_amount (CURRENCY ":0.000011",
255 : &fee_withdraw));
256 1 : GNUNET_assert (GNUNET_OK ==
257 : TALER_string_to_amount (CURRENCY ":0.000012",
258 : &fee_deposit));
259 1 : GNUNET_assert (GNUNET_OK ==
260 : TALER_string_to_amount (CURRENCY ":0.000013",
261 : &fee_refresh));
262 1 : GNUNET_assert (GNUNET_OK ==
263 : TALER_string_to_amount (CURRENCY ":0.000014",
264 : &fee_refund));
265 1 : RND_BLK (&reserve_pub);
266 1 : RND_BLK (&rnd_hash);
267 1 : GNUNET_assert (GNUNET_OK ==
268 : TALER_denom_priv_create (&denom_priv,
269 : &denom_pub,
270 : GNUNET_CRYPTO_BSA_RSA,
271 : 1024));
272 1 : TALER_denom_pub_hash (&denom_pub,
273 : &denom_pub_hash);
274 1 : TALER_denom_priv_free (&denom_priv);
275 1 : TALER_denom_pub_free (&denom_pub);
276 :
277 1 : now = GNUNET_TIME_timestamp_get ();
278 1 : 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 1 : 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 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
294 : "Test: insert_reserve_info\n");
295 1 : GNUNET_assert (GNUNET_OK ==
296 : TALER_string_to_amount (CURRENCY ":12.345678",
297 : &rfb.reserve_balance));
298 1 : GNUNET_assert (GNUNET_OK ==
299 : TALER_string_to_amount (CURRENCY ":11.245678",
300 : &rfb.reserve_loss));
301 1 : GNUNET_assert (GNUNET_OK ==
302 : TALER_string_to_amount (CURRENCY ":23.456789",
303 : &rfb.withdraw_fee_balance));
304 1 : GNUNET_assert (GNUNET_OK ==
305 : TALER_string_to_amount (CURRENCY ":23.456719",
306 : &rfb.close_fee_balance));
307 1 : GNUNET_assert (GNUNET_OK ==
308 : TALER_string_to_amount (CURRENCY ":33.456789",
309 : &rfb.purse_fee_balance));
310 1 : GNUNET_assert (GNUNET_OK ==
311 : TALER_string_to_amount (CURRENCY ":43.456789",
312 : &rfb.open_fee_balance));
313 1 : GNUNET_assert (GNUNET_OK ==
314 : TALER_string_to_amount (CURRENCY ":53.456789",
315 : &rfb.history_fee_balance));
316 : {
317 1 : struct TALER_FullPayto pt = {
318 : .full_payto = (char *) "payto://bla/blub?receiver-name=blub"
319 : };
320 :
321 1 : 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 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
329 : "Test: update_reserve_info\n");
330 1 : FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
331 : TALER_AUDITORDB_update_reserve_info (pg,
332 : &reserve_pub,
333 : &rfb,
334 : future));
335 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
336 : "Test: get_reserve_info\n");
337 : {
338 : struct TALER_FullPayto payto;
339 :
340 1 : 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 1 : FAILIF (0 != strcmp (payto.full_payto,
348 : "payto://bla/blub?receiver-name=blub"));
349 1 : GNUNET_free (payto.full_payto);
350 : }
351 1 : 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 1 : struct TALER_AUDITORDB_ClosureLags cl = {
370 : .problem_row_id = 42
371 : };
372 :
373 1 : GNUNET_assert (GNUNET_OK ==
374 : TALER_string_to_amount (CURRENCY ":12.345678",
375 : &cl.amount));
376 : cl.account.full_payto
377 1 : = (char *) "payto://unspec/foo?receiver-name=bar";
378 1 : memset (&cl.wtid,
379 : 42,
380 : sizeof (cl.wtid));
381 1 : cl.deadline = GNUNET_TIME_absolute_get ();
382 1 : 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 1 : FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
388 : TALER_AUDITORDB_insert_auditor_closure_lags (pg,
389 : &cl));
390 1 : 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 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
402 : "Test: insert_denomination_balance\n");
403 1 : GNUNET_assert (GNUNET_OK ==
404 : TALER_string_to_amount (CURRENCY ":12.345678",
405 : &dcd.denom_balance));
406 1 : GNUNET_assert (GNUNET_OK ==
407 : TALER_string_to_amount (CURRENCY ":0.1",
408 : &dcd.denom_loss));
409 1 : GNUNET_assert (GNUNET_OK ==
410 : TALER_string_to_amount (CURRENCY ":13.57986",
411 : &dcd.denom_risk));
412 1 : GNUNET_assert (GNUNET_OK ==
413 : TALER_string_to_amount (CURRENCY ":12.57986",
414 : &dcd.recoup_loss));
415 1 : dcd.num_issued = 62;
416 1 : FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
417 : TALER_AUDITORDB_insert_denomination_balance (pg,
418 : &denom_pub_hash,
419 : &dcd));
420 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
421 : "Test: update_denomination_balance\n");
422 1 : FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
423 : TALER_AUDITORDB_update_denomination_balance (pg,
424 : &denom_pub_hash,
425 : &dcd));
426 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
427 : "Test: get_denomination_balance\n");
428 :
429 1 : FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
430 : TALER_AUDITORDB_get_denomination_balance (pg,
431 : &denom_pub_hash,
432 : &dcd2));
433 1 : FAILIF (0 != TALER_amount_cmp (&dcd2.denom_balance,
434 : &dcd.denom_balance));
435 1 : FAILIF (0 != TALER_amount_cmp (&dcd2.denom_loss,
436 : &dcd.denom_loss));
437 1 : FAILIF (0 != TALER_amount_cmp (&dcd2.denom_risk,
438 : &dcd.denom_risk));
439 1 : FAILIF (0 != TALER_amount_cmp (&dcd2.recoup_loss,
440 : &dcd.recoup_loss));
441 1 : FAILIF (dcd2.num_issued != dcd.num_issued);
442 : }
443 :
444 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
445 : "Test: insert_historic_denom_revenue\n");
446 1 : GNUNET_assert (GNUNET_OK ==
447 : TALER_string_to_amount (CURRENCY ":12.345678",
448 : &rbalance));
449 1 : GNUNET_assert (GNUNET_OK ==
450 : TALER_string_to_amount (CURRENCY ":23.456789",
451 : &rloss));
452 1 : 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 1 : 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 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
465 : "Test: select_historic_denom_revenue\n");
466 1 : FAILIF (0 >=
467 : TALER_AUDITORDB_iterate_historic_denom_revenue (
468 : pg,
469 : 1024, /* limit */
470 : 0, /* offset */
471 : &select_historic_denom_revenue_result,
472 : NULL));
473 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
474 : "Test: insert_historic_reserve_revenue\n");
475 1 : GNUNET_assert (GNUNET_OK ==
476 : TALER_string_to_amount (CURRENCY ":56.789012",
477 : &reserve_profits));
478 1 : FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
479 : TALER_AUDITORDB_insert_historic_reserve_revenue (pg,
480 : past,
481 : future,
482 : &reserve_profits));
483 1 : FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
484 : TALER_AUDITORDB_insert_historic_reserve_revenue (pg,
485 : now,
486 : future,
487 : &reserve_profits));
488 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
489 : "Test: select_historic_reserve_revenue\n");
490 1 : FAILIF (0 >=
491 : TALER_AUDITORDB_iterate_historic_reserve_revenue (
492 : pg,
493 : 1024, /* limit */
494 : 0, /* offset */
495 : &select_historic_reserve_revenue_result,
496 : NULL));
497 :
498 1 : FAILIF (0 >
499 : TALER_AUDITORDB_commit (pg));
500 :
501 1 : FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
502 : TALER_AUDITORDB_delete_reserve_info (pg,
503 : &reserve_pub));
504 :
505 : #if GC_IMPLEMENTED
506 : FAILIF (GNUNET_OK !=
507 : TALER_AUDITORDB_gc (pg));
508 : #endif
509 :
510 1 : result = 0;
511 :
512 1 : drop:
513 1 : TALER_AUDITORDB_rollback (pg);
514 1 : GNUNET_break (GNUNET_OK ==
515 : TALER_AUDITORDB_drop_tables (pg,
516 : GNUNET_YES));
517 1 : unload:
518 1 : TALER_AUDITORDB_disconnect (pg);
519 1 : pg = NULL;
520 : }
521 :
522 :
523 : int
524 1 : main (int argc,
525 : char *const argv[])
526 : {
527 : struct GNUNET_CONFIGURATION_Handle *cfg;
528 :
529 : (void) argc;
530 1 : result = -1;
531 1 : GNUNET_log_setup (argv[0],
532 : "WARNING",
533 : NULL);
534 1 : cfg = GNUNET_CONFIGURATION_create (TALER_AUDITOR_project_data ());
535 1 : if (GNUNET_OK !=
536 1 : GNUNET_CONFIGURATION_parse (cfg,
537 : "test-auditor-db-postgres.conf"))
538 : {
539 0 : GNUNET_break (0);
540 0 : return 2;
541 : }
542 1 : GNUNET_SCHEDULER_run (&run,
543 : cfg);
544 1 : GNUNET_CONFIGURATION_destroy (cfg);
545 1 : return result;
546 : }
|