Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2020 Taler Systems SA
4 :
5 : TALER is free software; you can redistribute it and/or modify
6 : it under the terms of the GNU General Public License as
7 : published by the Free Software Foundation; either version 3, or
8 : (at your option) any later version.
9 :
10 : TALER is distributed in the hope that it will be useful, but
11 : WITHOUT ANY WARRANTY; without even the implied warranty of
12 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : GNU General Public License for more details.
14 :
15 : You should have received a copy of the GNU General Public
16 : License along with TALER; see the file COPYING. If not, see
17 : <http://www.gnu.org/licenses/>
18 : */
19 : /**
20 : * @file testing_api_cmd_wallet_get_order.c
21 : * @brief command to test GET /order/$ORDER_ID
22 : * @author Jonathan Buchanan
23 : */
24 : #include "platform.h"
25 : #include <taler/taler_exchange_service.h>
26 : #include <taler/taler_testing_lib.h>
27 : #include "taler_merchant_service.h"
28 : #include "taler_merchant_testing_lib.h"
29 :
30 :
31 : /**
32 : * State for a GET /orders/$ORDER_ID CMD.
33 : */
34 : struct WalletGetOrderState
35 : {
36 : /**
37 : * The merchant base URL.
38 : */
39 : const char *merchant_url;
40 :
41 : /**
42 : * Expected HTTP response code for this CMD.
43 : */
44 : unsigned int http_status;
45 :
46 : /**
47 : * The handle to the current GET /orders/$ORDER_ID request.
48 : */
49 : struct TALER_MERCHANT_OrderWalletGetHandle *ogh;
50 :
51 : /**
52 : * The interpreter state.
53 : */
54 : struct TALER_TESTING_Interpreter *is;
55 :
56 : /**
57 : * Reference to a command that created an order.
58 : */
59 : const char *order_reference;
60 :
61 : /**
62 : * Reference to a command that created a paid
63 : * equivalent order that we expect to be referred
64 : * to during repurchase detection, or NULL.
65 : */
66 : const char *repurchase_order_ref;
67 :
68 : /**
69 : * Session Id the order needs to be bound to.
70 : */
71 : const char *session_id;
72 :
73 : /**
74 : * Whether the order was paid or not.
75 : */
76 : bool paid;
77 :
78 : /**
79 : * Whether the order was refunded or not.
80 : */
81 : bool refunded;
82 :
83 : /**
84 : * Whether the order has refunds pending.
85 : */
86 : bool refund_pending;
87 : };
88 :
89 :
90 : /**
91 : * Callback to process a GET /orders/$ID request
92 : *
93 : * @param cls closure
94 : * @param owgr response details
95 : */
96 : static void
97 20 : wallet_get_order_cb (
98 : void *cls,
99 : const struct TALER_MERCHANT_OrderWalletGetResponse *owgr)
100 : {
101 20 : struct WalletGetOrderState *gos = cls;
102 20 : const struct TALER_MERCHANT_HttpResponse *hr = &owgr->hr;
103 :
104 20 : gos->ogh = NULL;
105 20 : if (gos->http_status != hr->http_status)
106 : {
107 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
108 : "Unexpected response code %u (%d) to command %s\n",
109 : hr->http_status,
110 : (int) hr->ec,
111 : TALER_TESTING_interpreter_get_current_label (gos->is));
112 0 : TALER_TESTING_interpreter_fail (gos->is);
113 0 : return;
114 : }
115 20 : switch (hr->http_status)
116 : {
117 14 : case MHD_HTTP_OK:
118 14 : if (gos->refunded != owgr->details.ok.refunded)
119 : {
120 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
121 : "Order refunded does not match\n");
122 0 : TALER_TESTING_interpreter_fail (gos->is);
123 0 : return;
124 : }
125 14 : if (gos->refund_pending != owgr->details.ok.refund_pending)
126 : {
127 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
128 : "Order refund pending does not match\n");
129 0 : TALER_TESTING_interpreter_fail (gos->is);
130 0 : return;
131 : }
132 14 : break;
133 6 : case MHD_HTTP_PAYMENT_REQUIRED:
134 : {
135 : struct TALER_MERCHANT_PayUriData pud;
136 : const struct TALER_TESTING_Command *order_cmd;
137 : const char *order_id;
138 : const struct TALER_ClaimTokenP *claim_token;
139 :
140 6 : if (NULL != gos->repurchase_order_ref)
141 : {
142 : const struct TALER_TESTING_Command *rep_cmd;
143 : const char *rep_id;
144 : const char *ri;
145 :
146 2 : rep_cmd = TALER_TESTING_interpreter_lookup_command (
147 : gos->is,
148 : gos->repurchase_order_ref);
149 2 : if (GNUNET_OK !=
150 2 : TALER_TESTING_get_trait_order_id (rep_cmd,
151 : &rep_id))
152 : {
153 0 : TALER_TESTING_FAIL (gos->is);
154 : }
155 2 : ri = owgr->details.payment_required.already_paid_order_id;
156 2 : if ( (NULL == ri) ||
157 : (0 !=
158 2 : strcmp (ri,
159 : rep_id)) )
160 : {
161 0 : TALER_TESTING_FAIL (gos->is);
162 : }
163 : }
164 :
165 6 : if (GNUNET_OK !=
166 6 : TALER_MERCHANT_parse_pay_uri (
167 6 : owgr->details.payment_required.taler_pay_uri,
168 : &pud))
169 : {
170 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
171 : "Taler pay uri `%s' is malformed\n",
172 : owgr->details.payment_required.taler_pay_uri);
173 0 : TALER_TESTING_interpreter_fail (gos->is);
174 0 : return;
175 : }
176 :
177 6 : order_cmd = TALER_TESTING_interpreter_lookup_command (
178 : gos->is,
179 : gos->order_reference);
180 :
181 6 : if (GNUNET_OK !=
182 6 : TALER_TESTING_get_trait_order_id (order_cmd,
183 : &order_id))
184 : {
185 0 : TALER_MERCHANT_parse_pay_uri_free (&pud);
186 0 : TALER_TESTING_FAIL (gos->is);
187 : }
188 :
189 6 : if (GNUNET_OK !=
190 6 : TALER_TESTING_get_trait_claim_token (order_cmd,
191 : &claim_token))
192 : {
193 0 : TALER_MERCHANT_parse_pay_uri_free (&pud);
194 0 : TALER_TESTING_FAIL (gos->is);
195 : }
196 :
197 : {
198 : char *host;
199 :
200 6 : host = TALER_MERCHANT_TESTING_extract_host (gos->merchant_url);
201 6 : if ((0 != strcmp (host,
202 6 : pud.merchant_host)) ||
203 6 : (NULL != pud.merchant_prefix_path) ||
204 6 : (0 != strcmp (order_id,
205 6 : pud.order_id)) ||
206 6 : (NULL != pud.ssid))
207 : {
208 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
209 : "Order pay uri `%s' does not match `%s'\n",
210 : owgr->details.payment_required.taler_pay_uri,
211 : pud.order_id);
212 0 : TALER_TESTING_interpreter_fail (gos->is);
213 0 : TALER_MERCHANT_parse_pay_uri_free (&pud);
214 0 : GNUNET_free (host);
215 0 : return;
216 : }
217 6 : GNUNET_free (host);
218 : }
219 : /* The claim token is not given in the pay uri if the order
220 : has been claimed already. */
221 6 : if ((NULL != pud.claim_token) &&
222 0 : ((NULL == claim_token) ||
223 0 : (0 != GNUNET_memcmp (claim_token,
224 : pud.claim_token))))
225 : {
226 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
227 : "Order pay uri claim token does not match (%d/%d)\n",
228 : NULL == pud.claim_token,
229 : NULL == claim_token);
230 0 : TALER_TESTING_interpreter_fail (gos->is);
231 0 : TALER_MERCHANT_parse_pay_uri_free (&pud);
232 0 : return;
233 : }
234 6 : TALER_MERCHANT_parse_pay_uri_free (&pud);
235 : }
236 6 : break;
237 0 : default:
238 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
239 : "Unhandled HTTP status.\n");
240 : }
241 20 : TALER_TESTING_interpreter_next (gos->is);
242 : }
243 :
244 :
245 : /**
246 : * Run the "GET order" CMD.
247 : *
248 : * @param cls closure.
249 : * @param cmd command being run now.
250 : * @param is interpreter state.
251 : */
252 : static void
253 20 : wallet_get_order_run (void *cls,
254 : const struct TALER_TESTING_Command *cmd,
255 : struct TALER_TESTING_Interpreter *is)
256 : {
257 20 : struct WalletGetOrderState *gos = cls;
258 : const struct TALER_TESTING_Command *order_cmd;
259 : const char *order_id;
260 : const struct TALER_PrivateContractHashP *h_contract;
261 :
262 20 : order_cmd = TALER_TESTING_interpreter_lookup_command (
263 : is,
264 : gos->order_reference);
265 :
266 20 : if (GNUNET_OK !=
267 20 : TALER_TESTING_get_trait_order_id (order_cmd,
268 : &order_id))
269 0 : TALER_TESTING_FAIL (is);
270 :
271 20 : if (GNUNET_OK !=
272 20 : TALER_TESTING_get_trait_h_contract_terms (order_cmd,
273 : &h_contract))
274 0 : TALER_TESTING_FAIL (is);
275 :
276 20 : gos->is = is;
277 20 : gos->ogh = TALER_MERCHANT_wallet_order_get (
278 : TALER_TESTING_interpreter_get_context (is),
279 : gos->merchant_url,
280 : order_id,
281 : h_contract,
282 20 : GNUNET_TIME_UNIT_ZERO,
283 : gos->session_id,
284 : NULL,
285 : false,
286 : &wallet_get_order_cb,
287 : gos);
288 : }
289 :
290 :
291 : /**
292 : * Free the state of a "GET order" CMD, and possibly
293 : * cancel a pending operation thereof.
294 : *
295 : * @param cls closure.
296 : * @param cmd command being run.
297 : */
298 : static void
299 20 : wallet_get_order_cleanup (void *cls,
300 : const struct TALER_TESTING_Command *cmd)
301 : {
302 20 : struct WalletGetOrderState *gos = cls;
303 :
304 20 : if (NULL != gos->ogh)
305 : {
306 0 : TALER_LOG_WARNING ("Get order operation did not complete\n");
307 0 : TALER_MERCHANT_wallet_order_get_cancel (gos->ogh);
308 : }
309 20 : GNUNET_free (gos);
310 20 : }
311 :
312 :
313 : struct TALER_TESTING_Command
314 12 : TALER_TESTING_cmd_wallet_get_order (
315 : const char *label,
316 : const char *merchant_url,
317 : const char *order_reference,
318 : bool paid,
319 : bool refunded,
320 : bool refund_pending,
321 : unsigned int http_status)
322 : {
323 : struct WalletGetOrderState *gos;
324 :
325 12 : gos = GNUNET_new (struct WalletGetOrderState);
326 12 : gos->merchant_url = merchant_url;
327 12 : gos->order_reference = order_reference;
328 12 : gos->http_status = http_status;
329 12 : gos->paid = paid;
330 12 : gos->refunded = refunded;
331 12 : gos->refund_pending = refund_pending;
332 : {
333 12 : struct TALER_TESTING_Command cmd = {
334 : .cls = gos,
335 : .label = label,
336 : .run = &wallet_get_order_run,
337 : .cleanup = &wallet_get_order_cleanup
338 : };
339 :
340 12 : return cmd;
341 : }
342 : }
343 :
344 :
345 : struct TALER_TESTING_Command
346 8 : TALER_TESTING_cmd_wallet_get_order2 (
347 : const char *label,
348 : const char *merchant_url,
349 : const char *order_reference,
350 : const char *session_id,
351 : bool paid,
352 : bool refunded,
353 : bool refund_pending,
354 : const char *repurchase_order_ref,
355 : unsigned int http_status)
356 : {
357 : struct WalletGetOrderState *gos;
358 :
359 8 : gos = GNUNET_new (struct WalletGetOrderState);
360 8 : gos->merchant_url = merchant_url;
361 8 : gos->order_reference = order_reference;
362 8 : gos->http_status = http_status;
363 8 : gos->paid = paid;
364 8 : gos->session_id = session_id;
365 8 : gos->refunded = refunded;
366 8 : gos->refund_pending = refund_pending;
367 8 : gos->repurchase_order_ref = repurchase_order_ref;
368 : {
369 8 : struct TALER_TESTING_Command cmd = {
370 : .cls = gos,
371 : .label = label,
372 : .run = &wallet_get_order_run,
373 : .cleanup = &wallet_get_order_cleanup
374 : };
375 :
376 8 : return cmd;
377 : }
378 : }
379 :
380 :
381 : struct WalletPollOrderConcludeState
382 : {
383 : /**
384 : * The interpreter state.
385 : */
386 : struct TALER_TESTING_Interpreter *is;
387 :
388 : /**
389 : * Reference to a command that can provide a poll order start command.
390 : */
391 : const char *start_reference;
392 :
393 : /**
394 : * Already paid order ID expected, or NULL for none.
395 : */
396 : const char *already_paid_order_id;
397 :
398 : /**
399 : * Task to wait for the deadline.
400 : */
401 : struct GNUNET_SCHEDULER_Task *task;
402 :
403 : /**
404 : * Amount of a refund expected.
405 : */
406 : struct TALER_Amount expected_refund_amount;
407 :
408 : /**
409 : * Expected HTTP response status code.
410 : */
411 : unsigned int expected_http_status;
412 :
413 : /**
414 : * Are we expecting a refund?
415 : */
416 : bool expected_refund;
417 : };
418 :
419 :
420 : struct WalletPollOrderStartState
421 : {
422 : /**
423 : * The merchant base URL.
424 : */
425 : const char *merchant_url;
426 :
427 : /**
428 : * The handle to the current GET /orders/$ORDER_ID request.
429 : */
430 : struct TALER_MERCHANT_OrderWalletGetHandle *ogh;
431 :
432 : /**
433 : * The interpreter state.
434 : */
435 : struct TALER_TESTING_Interpreter *is;
436 :
437 : /**
438 : * Reference to a command that created an order.
439 : */
440 : const char *order_ref;
441 :
442 : /**
443 : * Which session ID to poll for.
444 : */
445 : const char *session_id;
446 :
447 : /**
448 : * How long to wait for server to return a response.
449 : */
450 : struct GNUNET_TIME_Relative timeout;
451 :
452 : /**
453 : * Conclude state waiting for completion (if any).
454 : */
455 : struct WalletPollOrderConcludeState *cs;
456 :
457 : /**
458 : * The HTTP status code returned by the backend.
459 : */
460 : unsigned int http_status;
461 :
462 : /**
463 : * When the request should be completed by.
464 : */
465 : struct GNUNET_TIME_Absolute deadline;
466 :
467 : /**
468 : * Minimum refund to wait for.
469 : */
470 : struct TALER_Amount refund_threshold;
471 :
472 : /**
473 : * Available refund as returned by the merchant.
474 : */
475 : struct TALER_Amount refund_available;
476 :
477 : /**
478 : * Already paid order ID returned, or NULL for none.
479 : */
480 : char *already_paid_order_id;
481 :
482 : /**
483 : * Should we poll for a refund?
484 : */
485 : bool wait_for_refund;
486 :
487 : /**
488 : * Did we receive a refund according to response from the merchant?
489 : */
490 : bool refunded;
491 :
492 : /**
493 : * Was the order paid according to response from the merchant?
494 : */
495 : bool paid;
496 :
497 : /**
498 : * Has the order a pending refund according to response from the merchant?
499 : */
500 : bool refund_pending;
501 : };
502 :
503 :
504 : /**
505 : * Task called when either the timeout for the GET /private/order/$ID command
506 : * expired or we got a response. Checks if the result is what we expected.
507 : *
508 : * @param cls a `struct WalletPollOrderConcludeState`
509 : */
510 : static void
511 8 : conclude_task (void *cls)
512 : {
513 8 : struct WalletPollOrderConcludeState *ppc = cls;
514 : const struct TALER_TESTING_Command *poll_cmd;
515 : struct WalletPollOrderStartState *cps;
516 : struct GNUNET_TIME_Absolute now;
517 :
518 8 : ppc->task = NULL;
519 : poll_cmd =
520 8 : TALER_TESTING_interpreter_lookup_command (ppc->is,
521 : ppc->start_reference);
522 8 : if (NULL == poll_cmd)
523 0 : TALER_TESTING_FAIL (ppc->is);
524 8 : cps = poll_cmd->cls;
525 8 : if (NULL != cps->ogh)
526 : {
527 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
528 : "Expected poll GET /orders/$ORDER_ID to have completed, but it did not!\n");
529 0 : TALER_TESTING_FAIL (ppc->is);
530 : }
531 8 : if (cps->http_status != ppc->expected_http_status)
532 : {
533 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
534 : "Expected HTTP status %u, got %u\n",
535 : ppc->expected_http_status,
536 : cps->http_status);
537 0 : TALER_TESTING_FAIL (ppc->is);
538 : }
539 8 : if (ppc->expected_refund != cps->refunded)
540 : {
541 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
542 : "Order was %srefunded, contrary to our expectations\n",
543 : cps->refunded ? "" : "NOT ");
544 0 : TALER_TESTING_FAIL (ppc->is);
545 : }
546 8 : if ( (NULL == ppc->already_paid_order_id)
547 8 : ^ (NULL == cps->already_paid_order_id) )
548 : {
549 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
550 : "Mismatch in already paid order IDs: %s vs %s\n",
551 : ppc->already_paid_order_id,
552 : cps->already_paid_order_id);
553 0 : TALER_TESTING_FAIL (ppc->is);
554 : }
555 8 : if ( (NULL != ppc->already_paid_order_id) &&
556 2 : (0 != strcmp (ppc->already_paid_order_id,
557 2 : cps->already_paid_order_id) ) )
558 : {
559 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
560 : "Mismatch in already paid order IDs: %s vs %s\n",
561 : ppc->already_paid_order_id,
562 : cps->already_paid_order_id);
563 0 : TALER_TESTING_FAIL (ppc->is);
564 : }
565 :
566 8 : if (cps->refunded)
567 : {
568 4 : if (0 != TALER_amount_cmp (&ppc->expected_refund_amount,
569 4 : &cps->refund_available))
570 : {
571 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
572 : "Refund amount %s does not match our expectation!\n",
573 : TALER_amount2s (&cps->refund_available));
574 0 : TALER_TESTING_FAIL (ppc->is);
575 : }
576 : }
577 : // FIXME: add checks for cps->paid/refund_available status flags?
578 8 : now = GNUNET_TIME_absolute_get ();
579 8 : if ((GNUNET_TIME_absolute_add (cps->deadline,
580 8 : GNUNET_TIME_UNIT_SECONDS).abs_value_us <
581 8 : now.abs_value_us) )
582 : {
583 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
584 : "Expected answer to be delayed until %llu, but got response at %llu\n",
585 : (unsigned long long) cps->deadline.abs_value_us,
586 : (unsigned long long) now.abs_value_us);
587 0 : TALER_TESTING_FAIL (ppc->is);
588 : }
589 8 : TALER_TESTING_interpreter_next (ppc->is);
590 : }
591 :
592 :
593 : /**
594 : * Process response from a GET /orders/$ID request
595 : *
596 : * @param cls a `struct WalletPollOrderStartState *`
597 : * @param owgr response details
598 : */
599 : static void
600 8 : wallet_poll_order_cb (
601 : void *cls,
602 : const struct TALER_MERCHANT_OrderWalletGetResponse *owgr)
603 : {
604 8 : struct WalletPollOrderStartState *pos = cls;
605 8 : const struct TALER_MERCHANT_HttpResponse *hr = &owgr->hr;
606 :
607 8 : pos->ogh = NULL;
608 8 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
609 : "GET /orders/$ID finished with status %u.\n",
610 : hr->http_status);
611 8 : pos->http_status = hr->http_status;
612 8 : switch (hr->http_status)
613 : {
614 6 : case MHD_HTTP_OK:
615 6 : pos->paid = true;
616 6 : pos->refunded = owgr->details.ok.refunded;
617 6 : pos->refund_pending = owgr->details.ok.refund_pending;
618 6 : if (owgr->details.ok.refunded)
619 4 : pos->refund_available = owgr->details.ok.refund_amount;
620 6 : break;
621 2 : case MHD_HTTP_PAYMENT_REQUIRED:
622 2 : if (NULL != owgr->details.payment_required.already_paid_order_id)
623 2 : pos->already_paid_order_id = GNUNET_strdup (
624 : owgr->details.payment_required.already_paid_order_id);
625 2 : break;
626 0 : default:
627 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
628 : "Unhandled HTTP status.\n");
629 0 : break;
630 : }
631 8 : if ( (NULL != pos->cs) &&
632 4 : (NULL != pos->cs->task) )
633 : {
634 4 : GNUNET_SCHEDULER_cancel (pos->cs->task);
635 4 : pos->cs->task = GNUNET_SCHEDULER_add_now (&conclude_task,
636 4 : pos->cs);
637 : }
638 8 : }
639 :
640 :
641 : /**
642 : * Run the "GET order" CMD.
643 : *
644 : * @param cls closure.
645 : * @param cmd command being run now.
646 : * @param is interpreter state.
647 : */
648 : static void
649 8 : wallet_poll_order_start_run (void *cls,
650 : const struct TALER_TESTING_Command *cmd,
651 : struct TALER_TESTING_Interpreter *is)
652 : {
653 8 : struct WalletPollOrderStartState *pos = cls;
654 : const struct TALER_TESTING_Command *order_cmd;
655 : const char *order_id;
656 : const struct TALER_PrivateContractHashP *h_contract;
657 :
658 8 : order_cmd = TALER_TESTING_interpreter_lookup_command (
659 : is,
660 : pos->order_ref);
661 :
662 8 : if (GNUNET_OK !=
663 8 : TALER_TESTING_get_trait_order_id (order_cmd,
664 : &order_id))
665 0 : TALER_TESTING_FAIL (is);
666 :
667 8 : if (GNUNET_OK !=
668 8 : TALER_TESTING_get_trait_h_contract_terms (order_cmd,
669 : &h_contract))
670 0 : TALER_TESTING_FAIL (is);
671 :
672 : /* add 1s grace time to timeout */
673 : pos->deadline
674 8 : = GNUNET_TIME_absolute_add (GNUNET_TIME_relative_to_absolute (pos->timeout),
675 : GNUNET_TIME_UNIT_SECONDS);
676 8 : pos->is = is;
677 8 : pos->ogh = TALER_MERCHANT_wallet_order_get (
678 : TALER_TESTING_interpreter_get_context (is),
679 : pos->merchant_url,
680 : order_id,
681 : h_contract,
682 : pos->timeout,
683 : pos->session_id,
684 8 : pos->wait_for_refund
685 : ? &pos->refund_threshold
686 : : NULL,
687 : false, /* await_refund_obtained */
688 : &wallet_poll_order_cb,
689 : pos);
690 8 : GNUNET_assert (NULL != pos->ogh);
691 : /* We CONTINUE to run the interpreter while the long-polled command
692 : completes asynchronously! */
693 8 : TALER_TESTING_interpreter_next (pos->is);
694 : }
695 :
696 :
697 : /**
698 : * Free the state of a "GET order" CMD, and possibly
699 : * cancel a pending operation thereof.
700 : *
701 : * @param cls closure.
702 : * @param cmd command being run.
703 : */
704 : static void
705 8 : wallet_poll_order_start_cleanup (void *cls,
706 : const struct TALER_TESTING_Command *cmd)
707 : {
708 8 : struct WalletPollOrderStartState *pos = cls;
709 :
710 8 : if (NULL != pos->ogh)
711 : {
712 0 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
713 : "Command `%s' was not terminated\n",
714 : TALER_TESTING_interpreter_get_current_label (
715 : pos->is));
716 0 : TALER_MERCHANT_wallet_order_get_cancel (pos->ogh);
717 : }
718 8 : GNUNET_free (pos->already_paid_order_id);
719 8 : GNUNET_free (pos);
720 8 : }
721 :
722 :
723 : struct TALER_TESTING_Command
724 8 : TALER_TESTING_cmd_wallet_poll_order_start (
725 : const char *label,
726 : const char *merchant_url,
727 : const char *order_ref,
728 : struct GNUNET_TIME_Relative timeout,
729 : const char *await_refund)
730 : {
731 : struct WalletPollOrderStartState *pos;
732 :
733 8 : pos = GNUNET_new (struct WalletPollOrderStartState);
734 8 : pos->order_ref = order_ref;
735 8 : pos->merchant_url = merchant_url;
736 8 : pos->timeout = timeout;
737 8 : if (NULL != await_refund)
738 : {
739 4 : pos->wait_for_refund = true;
740 4 : GNUNET_assert (GNUNET_OK ==
741 : TALER_string_to_amount (await_refund,
742 : &pos->refund_threshold));
743 : }
744 : {
745 8 : struct TALER_TESTING_Command cmd = {
746 : .cls = pos,
747 : .label = label,
748 : .run = &wallet_poll_order_start_run,
749 : .cleanup = &wallet_poll_order_start_cleanup
750 : };
751 :
752 8 : return cmd;
753 : }
754 : }
755 :
756 :
757 : struct TALER_TESTING_Command
758 2 : TALER_TESTING_cmd_wallet_poll_order_start2 (
759 : const char *label,
760 : const char *merchant_url,
761 : const char *order_ref,
762 : struct GNUNET_TIME_Relative timeout,
763 : const char *await_refund,
764 : const char *session_id)
765 : {
766 : struct WalletPollOrderStartState *pos;
767 : struct TALER_TESTING_Command cmd;
768 :
769 2 : cmd = TALER_TESTING_cmd_wallet_poll_order_start (label,
770 : merchant_url,
771 : order_ref,
772 : timeout,
773 : await_refund);
774 2 : pos = cmd.cls;
775 2 : pos->session_id = session_id;
776 2 : return cmd;
777 : }
778 :
779 :
780 : /**
781 : * Run the "GET order conclude" CMD.
782 : *
783 : * @param cls closure.
784 : * @param cmd command being run now.
785 : * @param is interpreter state.
786 : */
787 : static void
788 8 : wallet_poll_order_conclude_run (void *cls,
789 : const struct TALER_TESTING_Command *cmd,
790 : struct TALER_TESTING_Interpreter *is)
791 : {
792 8 : struct WalletPollOrderConcludeState *poc = cls;
793 : const struct TALER_TESTING_Command *poll_cmd;
794 : struct WalletPollOrderStartState *pos;
795 :
796 8 : poc->is = is;
797 : poll_cmd =
798 8 : TALER_TESTING_interpreter_lookup_command (is,
799 : poc->start_reference);
800 8 : if (NULL == poll_cmd)
801 0 : TALER_TESTING_FAIL (poc->is);
802 8 : GNUNET_assert (poll_cmd->run == &wallet_poll_order_start_run);
803 8 : pos = poll_cmd->cls;
804 8 : pos->cs = poc;
805 8 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
806 : "Waiting on GET /orders/$ID of %s (%s)\n",
807 : poc->start_reference,
808 : (NULL == pos->ogh)
809 : ? "finished"
810 : : "active");
811 8 : if (NULL == pos->ogh)
812 4 : poc->task = GNUNET_SCHEDULER_add_now (&conclude_task,
813 : poc);
814 : else
815 4 : poc->task = GNUNET_SCHEDULER_add_at (pos->deadline,
816 : &conclude_task,
817 : poc);
818 : }
819 :
820 :
821 : /**
822 : * Free the state of a "GET order" CMD, and possibly
823 : * cancel a pending operation thereof.
824 : *
825 : * @param cls closure.
826 : * @param cmd command being run.
827 : */
828 : static void
829 8 : wallet_poll_order_conclude_cleanup (void *cls,
830 : const struct TALER_TESTING_Command *cmd)
831 : {
832 8 : struct WalletPollOrderConcludeState *poc = cls;
833 :
834 8 : if (NULL != poc->task)
835 : {
836 0 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
837 : "Command `%s' was not terminated\n",
838 : TALER_TESTING_interpreter_get_current_label (
839 : poc->is));
840 0 : GNUNET_SCHEDULER_cancel (poc->task);
841 0 : poc->task = NULL;
842 : }
843 8 : GNUNET_free (poc);
844 8 : }
845 :
846 :
847 : struct TALER_TESTING_Command
848 8 : TALER_TESTING_cmd_wallet_poll_order_conclude (
849 : const char *label,
850 : unsigned int expected_http_status,
851 : const char *expected_refund_amount,
852 : const char *poll_start_reference)
853 : {
854 : struct WalletPollOrderConcludeState *cps;
855 :
856 8 : cps = GNUNET_new (struct WalletPollOrderConcludeState);
857 8 : cps->start_reference = poll_start_reference;
858 8 : cps->expected_http_status = expected_http_status;
859 8 : if (NULL != expected_refund_amount)
860 : {
861 4 : cps->expected_refund = true;
862 4 : GNUNET_assert (GNUNET_OK ==
863 : TALER_string_to_amount (expected_refund_amount,
864 : &cps->expected_refund_amount));
865 : }
866 : {
867 8 : struct TALER_TESTING_Command cmd = {
868 : .cls = cps,
869 : .label = label,
870 : .run = &wallet_poll_order_conclude_run,
871 : .cleanup = &wallet_poll_order_conclude_cleanup
872 : };
873 :
874 8 : return cmd;
875 : }
876 : }
877 :
878 :
879 : struct TALER_TESTING_Command
880 2 : TALER_TESTING_cmd_wallet_poll_order_conclude2 (
881 : const char *label,
882 : unsigned int expected_http_status,
883 : const char *expected_refund_amount,
884 : const char *poll_start_reference,
885 : const char *already_paid_order_id)
886 : {
887 : struct WalletPollOrderConcludeState *cps;
888 : struct TALER_TESTING_Command cmd;
889 :
890 2 : cmd = TALER_TESTING_cmd_wallet_poll_order_conclude (
891 : label,
892 : expected_http_status,
893 : expected_refund_amount,
894 : poll_start_reference);
895 2 : cps = cmd.cls;
896 2 : cps->already_paid_order_id = already_paid_order_id;
897 2 : return cmd;
898 : }
899 :
900 :
901 : /* end of testing_api_cmd_wallet_get_order.c */
|