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