Line data Source code
1 : /*
2 : This file is part of TALER
3 : (C) 2016-2020 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 : /**
18 : * @file testing/test_taler_exchange_aggregator.c
19 : * @brief Tests for taler-exchange-aggregator logic
20 : * @author Christian Grothoff <christian@grothoff.org>
21 : * @author Marcello Stanisci
22 : */
23 : #include "platform.h"
24 : #include "taler_util.h"
25 : #include <gnunet/gnunet_json_lib.h>
26 : #include "taler_json_lib.h"
27 : #include "taler_exchangedb_lib.h"
28 : #include <microhttpd.h>
29 : #include "taler_fakebank_lib.h"
30 : #include "taler_testing_lib.h"
31 :
32 :
33 : /**
34 : * Our credentials.
35 : */
36 : struct TALER_TESTING_Credentials cred;
37 :
38 : /**
39 : * Name of the configuration file to use.
40 : */
41 : static char *config_filename;
42 :
43 : #define USER42_ACCOUNT "42"
44 : #define USER43_ACCOUNT "43"
45 : #define USER44_ACCOUNT "44"
46 :
47 :
48 : /**
49 : * Execute the taler-exchange-aggregator, closer and transfer commands with
50 : * our configuration file.
51 : *
52 : * @param label label to use for the command.
53 : * @param cfg_fn configuration file to use
54 : */
55 : #define CMD_EXEC_AGGREGATOR(label, cfg_fn) \
56 : TALER_TESTING_cmd_exec_aggregator (label "-aggregator", cfg_fn), \
57 : TALER_TESTING_cmd_exec_transfer (label "-transfer", cfg_fn)
58 :
59 :
60 : /**
61 : * Collects all the tests.
62 : */
63 : static void
64 1 : run (void *cls,
65 : struct TALER_TESTING_Interpreter *is)
66 : {
67 : struct TALER_TESTING_Command all[] = {
68 1 : TALER_TESTING_cmd_run_fakebank ("run-fakebank",
69 1 : cred.cfg,
70 : "exchange-account-1"),
71 1 : TALER_TESTING_cmd_system_start ("start-taler",
72 : config_filename,
73 : "-e",
74 : NULL),
75 1 : CMD_EXEC_AGGREGATOR ("run-aggregator-on-empty-db",
76 : config_filename),
77 1 : TALER_TESTING_cmd_check_bank_empty ("expect-empty-transactions-on-start"),
78 :
79 : /* check aggregation happens on the simplest case:
80 : one deposit into the database. */
81 2 : TALER_TESTING_cmd_insert_deposit ("do-deposit-1",
82 1 : cred.cfg,
83 : "bob",
84 : USER42_ACCOUNT,
85 : GNUNET_TIME_timestamp_get (),
86 1 : GNUNET_TIME_UNIT_ZERO,
87 : "EUR:1",
88 : "EUR:0.1"),
89 1 : CMD_EXEC_AGGREGATOR ("run-aggregator-on-deposit-1",
90 : config_filename),
91 :
92 1 : TALER_TESTING_cmd_check_bank_transfer ("expect-deposit-1",
93 1 : cred.exchange_url,
94 : "EUR:0.89",
95 : cred.exchange_payto,
96 : cred.user42_payto),
97 1 : TALER_TESTING_cmd_check_bank_empty ("expect-empty-transactions-after-1"),
98 :
99 : /* check aggregation accumulates well. */
100 2 : TALER_TESTING_cmd_insert_deposit ("do-deposit-2a",
101 1 : cred.cfg,
102 : "bob",
103 : USER42_ACCOUNT,
104 : GNUNET_TIME_timestamp_get (),
105 1 : GNUNET_TIME_UNIT_ZERO,
106 : "EUR:1",
107 : "EUR:0.1"),
108 :
109 2 : TALER_TESTING_cmd_insert_deposit ("do-deposit-2b",
110 1 : cred.cfg,
111 : "bob",
112 : USER42_ACCOUNT,
113 : GNUNET_TIME_timestamp_get (),
114 1 : GNUNET_TIME_UNIT_ZERO,
115 : "EUR:1",
116 : "EUR:0.1"),
117 :
118 1 : CMD_EXEC_AGGREGATOR ("run-aggregator-deposit-2",
119 : config_filename),
120 :
121 1 : TALER_TESTING_cmd_check_bank_transfer ("expect-deposit-2",
122 1 : cred.exchange_url,
123 : "EUR:1.79",
124 : cred.exchange_payto,
125 : cred.user42_payto),
126 1 : TALER_TESTING_cmd_check_bank_empty ("expect-empty-transactions-after-2"),
127 :
128 : /* check that different merchants stem different aggregations. */
129 2 : TALER_TESTING_cmd_insert_deposit ("do-deposit-3a",
130 1 : cred.cfg,
131 : "bob",
132 : USER43_ACCOUNT,
133 : GNUNET_TIME_timestamp_get (),
134 1 : GNUNET_TIME_UNIT_ZERO,
135 : "EUR:1",
136 : "EUR:0.1"),
137 2 : TALER_TESTING_cmd_insert_deposit ("do-deposit-3b",
138 1 : cred.cfg,
139 : "bob",
140 : USER44_ACCOUNT,
141 : GNUNET_TIME_timestamp_get (),
142 1 : GNUNET_TIME_UNIT_ZERO,
143 : "EUR:1",
144 : "EUR:0.1"),
145 2 : TALER_TESTING_cmd_insert_deposit ("do-deposit-3c",
146 1 : cred.cfg,
147 : "alice",
148 : USER43_ACCOUNT,
149 : GNUNET_TIME_timestamp_get (),
150 1 : GNUNET_TIME_UNIT_ZERO,
151 : "EUR:1",
152 : "EUR:0.1"),
153 1 : CMD_EXEC_AGGREGATOR ("run-aggregator-deposit-3",
154 : config_filename),
155 :
156 1 : TALER_TESTING_cmd_check_bank_transfer ("expect-deposit-3a",
157 1 : cred.exchange_url,
158 : "EUR:0.89",
159 : cred.exchange_payto,
160 : cred.user43_payto),
161 1 : TALER_TESTING_cmd_check_bank_transfer ("expect-deposit-3b",
162 1 : cred.exchange_url,
163 : "EUR:0.89",
164 : cred.exchange_payto,
165 : cred.user43_payto),
166 1 : TALER_TESTING_cmd_check_bank_transfer ("expect-deposit-3c",
167 1 : cred.exchange_url,
168 : "EUR:0.89",
169 : cred.exchange_payto,
170 : cred.user44_payto),
171 1 : TALER_TESTING_cmd_check_bank_empty ("expect-empty-transactions-after-3"),
172 :
173 : /* checking that aggregator waits for the deadline. */
174 1 : TALER_TESTING_cmd_insert_deposit ("do-deposit-4a",
175 1 : cred.cfg,
176 : "bob",
177 : USER42_ACCOUNT,
178 : GNUNET_TIME_timestamp_get (),
179 : GNUNET_TIME_relative_multiply
180 : (GNUNET_TIME_UNIT_SECONDS,
181 : 5),
182 : "EUR:0.2",
183 : "EUR:0.1"),
184 1 : TALER_TESTING_cmd_insert_deposit ("do-deposit-4b",
185 1 : cred.cfg,
186 : "bob",
187 : USER42_ACCOUNT,
188 : GNUNET_TIME_timestamp_get (),
189 : GNUNET_TIME_relative_multiply
190 : (GNUNET_TIME_UNIT_SECONDS,
191 : 5),
192 : "EUR:0.2",
193 : "EUR:0.1"),
194 1 : CMD_EXEC_AGGREGATOR ("run-aggregator-deposit-4-early",
195 : config_filename),
196 1 : TALER_TESTING_cmd_check_bank_empty (
197 : "expect-empty-transactions-after-4-fast"),
198 :
199 1 : TALER_TESTING_cmd_sleep ("wait (5s)", 5),
200 :
201 1 : CMD_EXEC_AGGREGATOR ("run-aggregator-deposit-4-delayed",
202 : config_filename),
203 1 : TALER_TESTING_cmd_check_bank_transfer ("expect-deposit-4",
204 1 : cred.exchange_url,
205 : "EUR:0.19",
206 : cred.exchange_payto,
207 : cred.user42_payto),
208 :
209 : // test picking all deposits at earliest deadline
210 1 : TALER_TESTING_cmd_insert_deposit ("do-deposit-5a",
211 1 : cred.cfg,
212 : "bob",
213 : USER42_ACCOUNT,
214 : GNUNET_TIME_timestamp_get (),
215 : GNUNET_TIME_relative_multiply
216 : (GNUNET_TIME_UNIT_SECONDS,
217 : 10),
218 : "EUR:0.2",
219 : "EUR:0.1"),
220 :
221 1 : TALER_TESTING_cmd_insert_deposit ("do-deposit-5b",
222 1 : cred.cfg,
223 : "bob",
224 : USER42_ACCOUNT,
225 : GNUNET_TIME_timestamp_get (),
226 : GNUNET_TIME_relative_multiply
227 : (GNUNET_TIME_UNIT_SECONDS,
228 : 5),
229 : "EUR:0.2",
230 : "EUR:0.1"),
231 1 : CMD_EXEC_AGGREGATOR ("run-aggregator-deposit-5-early",
232 : config_filename),
233 :
234 1 : TALER_TESTING_cmd_check_bank_empty (
235 : "expect-empty-transactions-after-5-early"),
236 1 : TALER_TESTING_cmd_sleep ("wait (5s)", 5),
237 :
238 1 : CMD_EXEC_AGGREGATOR ("run-aggregator-deposit-5-delayed",
239 : config_filename),
240 1 : TALER_TESTING_cmd_check_bank_transfer ("expect-deposit-5",
241 1 : cred.exchange_url,
242 : "EUR:0.19",
243 : cred.exchange_payto,
244 : cred.user42_payto),
245 : /* Test NEVER running 'tiny' unless they make up minimum unit */
246 2 : TALER_TESTING_cmd_insert_deposit ("do-deposit-6a",
247 1 : cred.cfg,
248 : "bob",
249 : USER42_ACCOUNT,
250 : GNUNET_TIME_timestamp_get (),
251 1 : GNUNET_TIME_UNIT_ZERO,
252 : "EUR:0.102",
253 : "EUR:0.1"),
254 1 : CMD_EXEC_AGGREGATOR ("run-aggregator-deposit-6a-tiny",
255 : config_filename),
256 1 : TALER_TESTING_cmd_check_bank_empty (
257 : "expect-empty-transactions-after-6a-tiny"),
258 2 : TALER_TESTING_cmd_insert_deposit ("do-deposit-6b",
259 1 : cred.cfg,
260 : "bob",
261 : USER42_ACCOUNT,
262 : GNUNET_TIME_timestamp_get (),
263 1 : GNUNET_TIME_UNIT_ZERO,
264 : "EUR:0.102",
265 : "EUR:0.1"),
266 2 : TALER_TESTING_cmd_insert_deposit ("do-deposit-6c",
267 1 : cred.cfg,
268 : "bob",
269 : USER42_ACCOUNT,
270 : GNUNET_TIME_timestamp_get (),
271 1 : GNUNET_TIME_UNIT_ZERO,
272 : "EUR:0.102",
273 : "EUR:0.1"),
274 1 : CMD_EXEC_AGGREGATOR ("run-aggregator-deposit-6c-tiny",
275 : config_filename),
276 1 : TALER_TESTING_cmd_check_bank_empty (
277 : "expect-empty-transactions-after-6c-tiny"),
278 2 : TALER_TESTING_cmd_insert_deposit ("do-deposit-6d",
279 1 : cred.cfg,
280 : "bob",
281 : USER42_ACCOUNT,
282 : GNUNET_TIME_timestamp_get (),
283 1 : GNUNET_TIME_UNIT_ZERO,
284 : "EUR:0.102",
285 : "EUR:0.1"),
286 1 : CMD_EXEC_AGGREGATOR ("run-aggregator-deposit-6d-tiny",
287 : config_filename),
288 1 : TALER_TESTING_cmd_check_bank_empty (
289 : "expect-empty-transactions-after-6d-tiny"),
290 2 : TALER_TESTING_cmd_insert_deposit ("do-deposit-6e",
291 1 : cred.cfg,
292 : "bob",
293 : USER42_ACCOUNT,
294 : GNUNET_TIME_timestamp_get (),
295 1 : GNUNET_TIME_UNIT_ZERO,
296 : "EUR:0.112",
297 : "EUR:0.1"),
298 1 : CMD_EXEC_AGGREGATOR ("run-aggregator-deposit-6e",
299 : config_filename),
300 1 : TALER_TESTING_cmd_check_bank_transfer ("expect-deposit-6",
301 1 : cred.exchange_url,
302 : "EUR:0.01",
303 : cred.exchange_payto,
304 : cred.user42_payto),
305 :
306 : /* Test profiteering if wire deadline is short */
307 2 : TALER_TESTING_cmd_insert_deposit ("do-deposit-7a",
308 1 : cred.cfg,
309 : "bob",
310 : USER42_ACCOUNT,
311 : GNUNET_TIME_timestamp_get (),
312 1 : GNUNET_TIME_UNIT_ZERO,
313 : "EUR:0.109",
314 : "EUR:0.1"),
315 1 : CMD_EXEC_AGGREGATOR ("run-aggregator-deposit-7a-tiny",
316 : config_filename),
317 1 : TALER_TESTING_cmd_check_bank_empty (
318 : "expect-empty-transactions-after-7a-tiny"),
319 2 : TALER_TESTING_cmd_insert_deposit ("do-deposit-7b",
320 1 : cred.cfg,
321 : "bob",
322 : USER42_ACCOUNT,
323 : GNUNET_TIME_timestamp_get (),
324 1 : GNUNET_TIME_UNIT_ZERO,
325 : "EUR:0.119",
326 : "EUR:0.1"),
327 1 : CMD_EXEC_AGGREGATOR ("run-aggregator-deposit-7-profit",
328 : config_filename),
329 1 : TALER_TESTING_cmd_check_bank_transfer ("expect-deposit-7",
330 1 : cred.exchange_url,
331 : "EUR:0.01",
332 : cred.exchange_payto,
333 : cred.user42_payto),
334 :
335 : /* Now check profit was actually taken */
336 2 : TALER_TESTING_cmd_insert_deposit ("do-deposit-7c",
337 1 : cred.cfg,
338 : "bob",
339 : USER42_ACCOUNT,
340 : GNUNET_TIME_timestamp_get (),
341 1 : GNUNET_TIME_UNIT_ZERO,
342 : "EUR:0.122",
343 : "EUR:0.1"),
344 1 : CMD_EXEC_AGGREGATOR ("run-aggregator-deposit-7-loss",
345 : config_filename),
346 1 : TALER_TESTING_cmd_check_bank_transfer ("expect-deposit-7",
347 1 : cred.exchange_url,
348 : "EUR:0.01",
349 : cred.exchange_payto,
350 : cred.user42_payto),
351 :
352 : /* Test that aggregation would happen fully if wire deadline is long */
353 1 : TALER_TESTING_cmd_insert_deposit ("do-deposit-8a",
354 1 : cred.cfg,
355 : "bob",
356 : USER42_ACCOUNT,
357 : GNUNET_TIME_timestamp_get (),
358 : GNUNET_TIME_relative_multiply
359 : (GNUNET_TIME_UNIT_SECONDS,
360 : 5),
361 : "EUR:0.109",
362 : "EUR:0.1"),
363 1 : CMD_EXEC_AGGREGATOR ("run-aggregator-deposit-8a-tiny",
364 : config_filename),
365 1 : TALER_TESTING_cmd_check_bank_empty (
366 : "expect-empty-transactions-after-8a-tiny"),
367 1 : TALER_TESTING_cmd_insert_deposit ("do-deposit-8b",
368 1 : cred.cfg,
369 : "bob",
370 : USER42_ACCOUNT,
371 : GNUNET_TIME_timestamp_get (),
372 : GNUNET_TIME_relative_multiply
373 : (GNUNET_TIME_UNIT_SECONDS,
374 : 5),
375 : "EUR:0.109",
376 : "EUR:0.1"),
377 1 : CMD_EXEC_AGGREGATOR ("run-aggregator-deposit-8b-tiny",
378 : config_filename),
379 1 : TALER_TESTING_cmd_check_bank_empty (
380 : "expect-empty-transactions-after-8b-tiny"),
381 :
382 : /* now trigger aggregate with large transaction and short deadline */
383 2 : TALER_TESTING_cmd_insert_deposit ("do-deposit-8c",
384 1 : cred.cfg,
385 : "bob",
386 : USER42_ACCOUNT,
387 : GNUNET_TIME_timestamp_get (),
388 1 : GNUNET_TIME_UNIT_ZERO,
389 : "EUR:0.122",
390 : "EUR:0.1"),
391 1 : CMD_EXEC_AGGREGATOR ("run-aggregator-deposit-8",
392 : config_filename),
393 1 : TALER_TESTING_cmd_check_bank_transfer ("expect-deposit-8",
394 1 : cred.exchange_url,
395 : "EUR:0.03",
396 : cred.exchange_payto,
397 : cred.user42_payto),
398 :
399 : /* Test aggregation with fees and rounding profits. */
400 1 : TALER_TESTING_cmd_insert_deposit ("do-deposit-9a",
401 1 : cred.cfg,
402 : "bob",
403 : USER42_ACCOUNT,
404 : GNUNET_TIME_timestamp_get (),
405 : GNUNET_TIME_relative_multiply
406 : (GNUNET_TIME_UNIT_SECONDS,
407 : 5),
408 : "EUR:0.104",
409 : "EUR:0.1"),
410 1 : CMD_EXEC_AGGREGATOR ("run-aggregator-deposit-9a-tiny",
411 : config_filename),
412 1 : TALER_TESTING_cmd_check_bank_empty (
413 : "expect-empty-transactions-after-9a-tiny"),
414 1 : TALER_TESTING_cmd_insert_deposit ("do-deposit-9b",
415 1 : cred.cfg,
416 : "bob",
417 : USER42_ACCOUNT,
418 : GNUNET_TIME_timestamp_get (),
419 : GNUNET_TIME_relative_multiply
420 : (GNUNET_TIME_UNIT_SECONDS,
421 : 5),
422 : "EUR:0.105",
423 : "EUR:0.1"),
424 1 : CMD_EXEC_AGGREGATOR ("run-aggregator-deposit-9b-tiny",
425 : config_filename),
426 1 : TALER_TESTING_cmd_check_bank_empty (
427 : "expect-empty-transactions-after-9b-tiny"),
428 :
429 : /* now trigger aggregate with large transaction and short deadline */
430 2 : TALER_TESTING_cmd_insert_deposit ("do-deposit-9c",
431 1 : cred.cfg,
432 : "bob",
433 : USER42_ACCOUNT,
434 : GNUNET_TIME_timestamp_get (),
435 1 : GNUNET_TIME_UNIT_ZERO,
436 : "EUR:0.112",
437 : "EUR:0.1"),
438 1 : CMD_EXEC_AGGREGATOR ("run-aggregator-deposit-9",
439 : config_filename),
440 : /* 0.009 + 0.009 + 0.022 - 0.001 - 0.002 - 0.008 = 0.029 => 0.02 */
441 1 : TALER_TESTING_cmd_check_bank_transfer ("expect-deposit-9",
442 1 : cred.exchange_url,
443 : "EUR:0.01",
444 : cred.exchange_payto,
445 : cred.user42_payto),
446 1 : TALER_TESTING_cmd_end ()
447 : };
448 :
449 1 : TALER_TESTING_run (is,
450 : all);
451 1 : }
452 :
453 :
454 : int
455 1 : main (int argc,
456 : char *const argv[])
457 : {
458 : const char *plugin_name;
459 :
460 1 : if (NULL == (plugin_name = strrchr (argv[0], (int) '-')))
461 : {
462 0 : GNUNET_break (0);
463 0 : return -1;
464 : }
465 1 : plugin_name++;
466 1 : (void) GNUNET_asprintf (&config_filename,
467 : "test-taler-exchange-aggregator-%s.conf",
468 : plugin_name);
469 1 : return TALER_TESTING_main (argv,
470 : "INFO",
471 : config_filename,
472 : "exchange-account-1",
473 : TALER_TESTING_BS_FAKEBANK,
474 : &cred,
475 : &run,
476 : NULL);
477 : }
478 :
479 :
480 : /* end of test_taler_exchange_aggregator.c */
|