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