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 "taler/taler_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 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 : true)))
221 : {
222 0 : result = 77;
223 0 : return;
224 : }
225 :
226 1 : (void) TALER_AUDITORDB_drop_tables (pg,
227 : GNUNET_YES);
228 1 : if (GNUNET_OK !=
229 1 : TALER_AUDITORDB_create_tables (cfg,
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 :
246 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
247 : "initializing\n");
248 :
249 1 : GNUNET_assert (GNUNET_OK ==
250 : TALER_string_to_amount (CURRENCY ":1.000010",
251 : &value));
252 1 : GNUNET_assert (GNUNET_OK ==
253 : TALER_string_to_amount (CURRENCY ":0.000011",
254 : &fee_withdraw));
255 1 : GNUNET_assert (GNUNET_OK ==
256 : TALER_string_to_amount (CURRENCY ":0.000012",
257 : &fee_deposit));
258 1 : GNUNET_assert (GNUNET_OK ==
259 : TALER_string_to_amount (CURRENCY ":0.000013",
260 : &fee_refresh));
261 1 : GNUNET_assert (GNUNET_OK ==
262 : TALER_string_to_amount (CURRENCY ":0.000014",
263 : &fee_refund));
264 1 : RND_BLK (&reserve_pub);
265 1 : RND_BLK (&rnd_hash);
266 1 : GNUNET_assert (GNUNET_OK ==
267 : TALER_denom_priv_create (&denom_priv,
268 : &denom_pub,
269 : GNUNET_CRYPTO_BSA_RSA,
270 : 1024));
271 1 : TALER_denom_pub_hash (&denom_pub,
272 : &denom_pub_hash);
273 1 : TALER_denom_priv_free (&denom_priv);
274 1 : TALER_denom_pub_free (&denom_pub);
275 :
276 1 : now = GNUNET_TIME_timestamp_get ();
277 1 : 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 1 : 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 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
293 : "Test: insert_reserve_info\n");
294 1 : GNUNET_assert (GNUNET_OK ==
295 : TALER_string_to_amount (CURRENCY ":12.345678",
296 : &rfb.reserve_balance));
297 1 : GNUNET_assert (GNUNET_OK ==
298 : TALER_string_to_amount (CURRENCY ":11.245678",
299 : &rfb.reserve_loss));
300 1 : GNUNET_assert (GNUNET_OK ==
301 : TALER_string_to_amount (CURRENCY ":23.456789",
302 : &rfb.withdraw_fee_balance));
303 1 : GNUNET_assert (GNUNET_OK ==
304 : TALER_string_to_amount (CURRENCY ":23.456719",
305 : &rfb.close_fee_balance));
306 1 : GNUNET_assert (GNUNET_OK ==
307 : TALER_string_to_amount (CURRENCY ":33.456789",
308 : &rfb.purse_fee_balance));
309 1 : GNUNET_assert (GNUNET_OK ==
310 : TALER_string_to_amount (CURRENCY ":43.456789",
311 : &rfb.open_fee_balance));
312 1 : GNUNET_assert (GNUNET_OK ==
313 : TALER_string_to_amount (CURRENCY ":53.456789",
314 : &rfb.history_fee_balance));
315 : {
316 1 : struct TALER_FullPayto pt = {
317 : .full_payto = (char *) "payto://bla/blub?receiver-name=blub"
318 : };
319 :
320 1 : 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 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
328 : "Test: update_reserve_info\n");
329 1 : FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
330 : TALER_AUDITORDB_update_reserve_info (pg,
331 : &reserve_pub,
332 : &rfb,
333 : future));
334 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
335 : "Test: get_reserve_info\n");
336 : {
337 : struct TALER_FullPayto payto;
338 :
339 1 : 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 1 : FAILIF (0 != strcmp (payto.full_payto,
347 : "payto://bla/blub?receiver-name=blub"));
348 1 : GNUNET_free (payto.full_payto);
349 : }
350 1 : 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 1 : struct TALER_AUDITORDB_ClosureLags cl = {
369 : .problem_row_id = 42
370 : };
371 :
372 1 : GNUNET_assert (GNUNET_OK ==
373 : TALER_string_to_amount (CURRENCY ":12.345678",
374 : &cl.amount));
375 : cl.account.full_payto
376 1 : = (char *) "payto://unspec/foo?receiver-name=bar";
377 1 : memset (&cl.wtid,
378 : 42,
379 : sizeof (cl.wtid));
380 1 : cl.deadline = GNUNET_TIME_absolute_get ();
381 1 : 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 1 : FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
387 : TALER_AUDITORDB_insert_auditor_closure_lags (pg,
388 : &cl));
389 1 : 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 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
401 : "Test: insert_denomination_balance\n");
402 1 : GNUNET_assert (GNUNET_OK ==
403 : TALER_string_to_amount (CURRENCY ":12.345678",
404 : &dcd.denom_balance));
405 1 : GNUNET_assert (GNUNET_OK ==
406 : TALER_string_to_amount (CURRENCY ":0.1",
407 : &dcd.denom_loss));
408 1 : GNUNET_assert (GNUNET_OK ==
409 : TALER_string_to_amount (CURRENCY ":13.57986",
410 : &dcd.denom_risk));
411 1 : GNUNET_assert (GNUNET_OK ==
412 : TALER_string_to_amount (CURRENCY ":12.57986",
413 : &dcd.recoup_loss));
414 1 : dcd.num_issued = 62;
415 1 : FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
416 : TALER_AUDITORDB_insert_denomination_balance (pg,
417 : &denom_pub_hash,
418 : &dcd));
419 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
420 : "Test: update_denomination_balance\n");
421 1 : FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
422 : TALER_AUDITORDB_update_denomination_balance (pg,
423 : &denom_pub_hash,
424 : &dcd));
425 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
426 : "Test: get_denomination_balance\n");
427 :
428 1 : FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
429 : TALER_AUDITORDB_get_denomination_balance (pg,
430 : &denom_pub_hash,
431 : &dcd2));
432 1 : FAILIF (0 != TALER_amount_cmp (&dcd2.denom_balance,
433 : &dcd.denom_balance));
434 1 : FAILIF (0 != TALER_amount_cmp (&dcd2.denom_loss,
435 : &dcd.denom_loss));
436 1 : FAILIF (0 != TALER_amount_cmp (&dcd2.denom_risk,
437 : &dcd.denom_risk));
438 1 : FAILIF (0 != TALER_amount_cmp (&dcd2.recoup_loss,
439 : &dcd.recoup_loss));
440 1 : FAILIF (dcd2.num_issued != dcd.num_issued);
441 : }
442 :
443 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
444 : "Test: insert_historic_denom_revenue\n");
445 1 : GNUNET_assert (GNUNET_OK ==
446 : TALER_string_to_amount (CURRENCY ":12.345678",
447 : &rbalance));
448 1 : GNUNET_assert (GNUNET_OK ==
449 : TALER_string_to_amount (CURRENCY ":23.456789",
450 : &rloss));
451 1 : 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 1 : 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 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
464 : "Test: select_historic_denom_revenue\n");
465 1 : 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 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
473 : "Test: insert_historic_reserve_revenue\n");
474 1 : GNUNET_assert (GNUNET_OK ==
475 : TALER_string_to_amount (CURRENCY ":56.789012",
476 : &reserve_profits));
477 1 : FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
478 : TALER_AUDITORDB_insert_historic_reserve_revenue (pg,
479 : past,
480 : future,
481 : &reserve_profits));
482 1 : FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
483 : TALER_AUDITORDB_insert_historic_reserve_revenue (pg,
484 : now,
485 : future,
486 : &reserve_profits));
487 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
488 : "Test: select_historic_reserve_revenue\n");
489 1 : 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 1 : FAILIF (0 >
498 : TALER_AUDITORDB_commit (pg));
499 :
500 1 : 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 1 : result = 0;
510 :
511 1 : drop:
512 1 : TALER_AUDITORDB_rollback (pg);
513 1 : GNUNET_break (GNUNET_OK ==
514 : TALER_AUDITORDB_drop_tables (pg,
515 : GNUNET_YES));
516 1 : unload:
517 1 : TALER_AUDITORDB_disconnect (pg);
518 1 : pg = NULL;
519 : }
520 :
521 :
522 : int
523 1 : main (int argc,
524 : char *const argv[])
525 : {
526 : struct GNUNET_CONFIGURATION_Handle *cfg;
527 :
528 : (void) argc;
529 1 : result = -1;
530 1 : GNUNET_log_setup (argv[0],
531 : "WARNING",
532 : NULL);
533 1 : cfg = GNUNET_CONFIGURATION_create (TALER_AUDITOR_project_data ());
534 1 : if (GNUNET_OK !=
535 1 : GNUNET_CONFIGURATION_parse (cfg,
536 : "test-auditor-db-postgres.conf"))
537 : {
538 0 : GNUNET_break (0);
539 0 : return 2;
540 : }
541 1 : GNUNET_SCHEDULER_run (&run,
542 : cfg);
543 1 : GNUNET_CONFIGURATION_destroy (cfg);
544 1 : return result;
545 : }
|