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