testing_api_cmd_wallet_get_order.c (24083B)
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 wallet_get_order_cb ( 98 void *cls, 99 const struct TALER_MERCHANT_OrderWalletGetResponse *owgr) 100 { 101 struct WalletGetOrderState *gos = cls; 102 const struct TALER_MERCHANT_HttpResponse *hr = &owgr->hr; 103 104 gos->ogh = NULL; 105 if (gos->http_status != hr->http_status) 106 { 107 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 TALER_TESTING_interpreter_fail (gos->is); 113 return; 114 } 115 switch (hr->http_status) 116 { 117 case MHD_HTTP_OK: 118 if (gos->refunded != owgr->details.ok.refunded) 119 { 120 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 121 "Order refunded does not match\n"); 122 TALER_TESTING_interpreter_fail (gos->is); 123 return; 124 } 125 if (gos->refund_pending != owgr->details.ok.refund_pending) 126 { 127 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 128 "Order refund pending does not match\n"); 129 TALER_TESTING_interpreter_fail (gos->is); 130 return; 131 } 132 break; 133 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 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 rep_cmd = TALER_TESTING_interpreter_lookup_command ( 147 gos->is, 148 gos->repurchase_order_ref); 149 if (GNUNET_OK != 150 TALER_TESTING_get_trait_order_id (rep_cmd, 151 &rep_id)) 152 { 153 TALER_TESTING_FAIL (gos->is); 154 } 155 ri = owgr->details.payment_required.already_paid_order_id; 156 if ( (NULL == ri) || 157 (0 != 158 strcmp (ri, 159 rep_id)) ) 160 { 161 TALER_TESTING_FAIL (gos->is); 162 } 163 } 164 165 if (GNUNET_OK != 166 TALER_MERCHANT_parse_pay_uri ( 167 owgr->details.payment_required.taler_pay_uri, 168 &pud)) 169 { 170 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 171 "Taler pay uri `%s' is malformed\n", 172 owgr->details.payment_required.taler_pay_uri); 173 TALER_TESTING_interpreter_fail (gos->is); 174 return; 175 } 176 177 order_cmd = TALER_TESTING_interpreter_lookup_command ( 178 gos->is, 179 gos->order_reference); 180 181 if (GNUNET_OK != 182 TALER_TESTING_get_trait_order_id (order_cmd, 183 &order_id)) 184 { 185 TALER_MERCHANT_parse_pay_uri_free (&pud); 186 TALER_TESTING_FAIL (gos->is); 187 } 188 189 if (GNUNET_OK != 190 TALER_TESTING_get_trait_claim_token (order_cmd, 191 &claim_token)) 192 { 193 TALER_MERCHANT_parse_pay_uri_free (&pud); 194 TALER_TESTING_FAIL (gos->is); 195 } 196 197 { 198 char *host; 199 200 host = TALER_MERCHANT_TESTING_extract_host (gos->merchant_url); 201 if ((0 != strcmp (host, 202 pud.merchant_host)) || 203 (NULL != pud.merchant_prefix_path) || 204 (0 != strcmp (order_id, 205 pud.order_id)) || 206 (NULL != pud.ssid)) 207 { 208 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 TALER_TESTING_interpreter_fail (gos->is); 213 TALER_MERCHANT_parse_pay_uri_free (&pud); 214 GNUNET_free (host); 215 return; 216 } 217 GNUNET_free (host); 218 } 219 /* The claim token is not given in the pay uri if the order 220 has been claimed already. */ 221 if ((NULL != pud.claim_token) && 222 ((NULL == claim_token) || 223 (0 != GNUNET_memcmp (claim_token, 224 pud.claim_token)))) 225 { 226 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 TALER_TESTING_interpreter_fail (gos->is); 231 TALER_MERCHANT_parse_pay_uri_free (&pud); 232 return; 233 } 234 TALER_MERCHANT_parse_pay_uri_free (&pud); 235 } 236 break; 237 default: 238 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 239 "Unhandled HTTP status.\n"); 240 } 241 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 wallet_get_order_run (void *cls, 254 const struct TALER_TESTING_Command *cmd, 255 struct TALER_TESTING_Interpreter *is) 256 { 257 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 order_cmd = TALER_TESTING_interpreter_lookup_command ( 263 is, 264 gos->order_reference); 265 266 if (GNUNET_OK != 267 TALER_TESTING_get_trait_order_id (order_cmd, 268 &order_id)) 269 TALER_TESTING_FAIL (is); 270 271 if (GNUNET_OK != 272 TALER_TESTING_get_trait_h_contract_terms (order_cmd, 273 &h_contract)) 274 TALER_TESTING_FAIL (is); 275 276 gos->is = is; 277 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 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 wallet_get_order_cleanup (void *cls, 300 const struct TALER_TESTING_Command *cmd) 301 { 302 struct WalletGetOrderState *gos = cls; 303 304 if (NULL != gos->ogh) 305 { 306 TALER_LOG_WARNING ("Get order operation did not complete\n"); 307 TALER_MERCHANT_wallet_order_get_cancel (gos->ogh); 308 } 309 GNUNET_free (gos); 310 } 311 312 313 struct TALER_TESTING_Command 314 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 gos = GNUNET_new (struct WalletGetOrderState); 326 gos->merchant_url = merchant_url; 327 gos->order_reference = order_reference; 328 gos->http_status = http_status; 329 gos->paid = paid; 330 gos->refunded = refunded; 331 gos->refund_pending = refund_pending; 332 { 333 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 return cmd; 341 } 342 } 343 344 345 struct TALER_TESTING_Command 346 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 gos = GNUNET_new (struct WalletGetOrderState); 360 gos->merchant_url = merchant_url; 361 gos->order_reference = order_reference; 362 gos->http_status = http_status; 363 gos->paid = paid; 364 gos->session_id = session_id; 365 gos->refunded = refunded; 366 gos->refund_pending = refund_pending; 367 gos->repurchase_order_ref = repurchase_order_ref; 368 { 369 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 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 conclude_task (void *cls) 512 { 513 struct WalletPollOrderConcludeState *ppc = cls; 514 const struct TALER_TESTING_Command *poll_cmd; 515 struct WalletPollOrderStartState *cps; 516 struct GNUNET_TIME_Absolute now; 517 518 ppc->task = NULL; 519 poll_cmd = 520 TALER_TESTING_interpreter_lookup_command (ppc->is, 521 ppc->start_reference); 522 if (NULL == poll_cmd) 523 TALER_TESTING_FAIL (ppc->is); 524 cps = poll_cmd->cls; 525 if (NULL != cps->ogh) 526 { 527 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 528 "Expected poll GET /orders/$ORDER_ID to have completed, but it did not!\n"); 529 TALER_TESTING_FAIL (ppc->is); 530 } 531 if (cps->http_status != ppc->expected_http_status) 532 { 533 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 534 "Expected HTTP status %u, got %u\n", 535 ppc->expected_http_status, 536 cps->http_status); 537 TALER_TESTING_FAIL (ppc->is); 538 } 539 if (ppc->expected_refund != cps->refunded) 540 { 541 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 542 "Order was %srefunded, contrary to our expectations\n", 543 cps->refunded ? "" : "NOT "); 544 TALER_TESTING_FAIL (ppc->is); 545 } 546 if ( (NULL == ppc->already_paid_order_id) 547 ^ (NULL == cps->already_paid_order_id) ) 548 { 549 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 TALER_TESTING_FAIL (ppc->is); 554 } 555 if ( (NULL != ppc->already_paid_order_id) && 556 (0 != strcmp (ppc->already_paid_order_id, 557 cps->already_paid_order_id) ) ) 558 { 559 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 TALER_TESTING_FAIL (ppc->is); 564 } 565 566 if (cps->refunded) 567 { 568 if (0 != TALER_amount_cmp (&ppc->expected_refund_amount, 569 &cps->refund_available)) 570 { 571 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 572 "Refund amount %s does not match our expectation!\n", 573 TALER_amount2s (&cps->refund_available)); 574 TALER_TESTING_FAIL (ppc->is); 575 } 576 } 577 // FIXME: add checks for cps->paid/refund_available status flags? 578 now = GNUNET_TIME_absolute_get (); 579 if ((GNUNET_TIME_absolute_add (cps->deadline, 580 GNUNET_TIME_UNIT_SECONDS).abs_value_us < 581 now.abs_value_us) ) 582 { 583 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 TALER_TESTING_FAIL (ppc->is); 588 } 589 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 wallet_poll_order_cb ( 601 void *cls, 602 const struct TALER_MERCHANT_OrderWalletGetResponse *owgr) 603 { 604 struct WalletPollOrderStartState *pos = cls; 605 const struct TALER_MERCHANT_HttpResponse *hr = &owgr->hr; 606 607 pos->ogh = NULL; 608 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 609 "GET /orders/$ID finished with status %u.\n", 610 hr->http_status); 611 pos->http_status = hr->http_status; 612 switch (hr->http_status) 613 { 614 case MHD_HTTP_OK: 615 pos->paid = true; 616 pos->refunded = owgr->details.ok.refunded; 617 pos->refund_pending = owgr->details.ok.refund_pending; 618 if (owgr->details.ok.refunded) 619 pos->refund_available = owgr->details.ok.refund_amount; 620 break; 621 case MHD_HTTP_PAYMENT_REQUIRED: 622 if (NULL != owgr->details.payment_required.already_paid_order_id) 623 pos->already_paid_order_id = GNUNET_strdup ( 624 owgr->details.payment_required.already_paid_order_id); 625 break; 626 default: 627 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 628 "Unhandled HTTP status.\n"); 629 break; 630 } 631 if ( (NULL != pos->cs) && 632 (NULL != pos->cs->task) ) 633 { 634 GNUNET_SCHEDULER_cancel (pos->cs->task); 635 pos->cs->task = GNUNET_SCHEDULER_add_now (&conclude_task, 636 pos->cs); 637 } 638 } 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 wallet_poll_order_start_run (void *cls, 650 const struct TALER_TESTING_Command *cmd, 651 struct TALER_TESTING_Interpreter *is) 652 { 653 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 order_cmd = TALER_TESTING_interpreter_lookup_command ( 659 is, 660 pos->order_ref); 661 662 if (GNUNET_OK != 663 TALER_TESTING_get_trait_order_id (order_cmd, 664 &order_id)) 665 TALER_TESTING_FAIL (is); 666 667 if (GNUNET_OK != 668 TALER_TESTING_get_trait_h_contract_terms (order_cmd, 669 &h_contract)) 670 TALER_TESTING_FAIL (is); 671 672 /* add 1s grace time to timeout */ 673 pos->deadline 674 = GNUNET_TIME_absolute_add (GNUNET_TIME_relative_to_absolute (pos->timeout), 675 GNUNET_TIME_UNIT_SECONDS); 676 pos->is = is; 677 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 pos->wait_for_refund 685 ? &pos->refund_threshold 686 : NULL, 687 false, /* await_refund_obtained */ 688 &wallet_poll_order_cb, 689 pos); 690 GNUNET_assert (NULL != pos->ogh); 691 /* We CONTINUE to run the interpreter while the long-polled command 692 completes asynchronously! */ 693 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 wallet_poll_order_start_cleanup (void *cls, 706 const struct TALER_TESTING_Command *cmd) 707 { 708 struct WalletPollOrderStartState *pos = cls; 709 710 if (NULL != pos->ogh) 711 { 712 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 713 "Command `%s' was not terminated\n", 714 TALER_TESTING_interpreter_get_current_label ( 715 pos->is)); 716 TALER_MERCHANT_wallet_order_get_cancel (pos->ogh); 717 } 718 GNUNET_free (pos->already_paid_order_id); 719 GNUNET_free (pos); 720 } 721 722 723 struct TALER_TESTING_Command 724 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 pos = GNUNET_new (struct WalletPollOrderStartState); 734 pos->order_ref = order_ref; 735 pos->merchant_url = merchant_url; 736 pos->timeout = timeout; 737 if (NULL != await_refund) 738 { 739 pos->wait_for_refund = true; 740 GNUNET_assert (GNUNET_OK == 741 TALER_string_to_amount (await_refund, 742 &pos->refund_threshold)); 743 } 744 { 745 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 return cmd; 753 } 754 } 755 756 757 struct TALER_TESTING_Command 758 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 cmd = TALER_TESTING_cmd_wallet_poll_order_start (label, 770 merchant_url, 771 order_ref, 772 timeout, 773 await_refund); 774 pos = cmd.cls; 775 pos->session_id = session_id; 776 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 wallet_poll_order_conclude_run (void *cls, 789 const struct TALER_TESTING_Command *cmd, 790 struct TALER_TESTING_Interpreter *is) 791 { 792 struct WalletPollOrderConcludeState *poc = cls; 793 const struct TALER_TESTING_Command *poll_cmd; 794 struct WalletPollOrderStartState *pos; 795 796 poc->is = is; 797 poll_cmd = 798 TALER_TESTING_interpreter_lookup_command (is, 799 poc->start_reference); 800 if (NULL == poll_cmd) 801 TALER_TESTING_FAIL (poc->is); 802 GNUNET_assert (poll_cmd->run == &wallet_poll_order_start_run); 803 pos = poll_cmd->cls; 804 pos->cs = poc; 805 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 if (NULL == pos->ogh) 812 poc->task = GNUNET_SCHEDULER_add_now (&conclude_task, 813 poc); 814 else 815 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 wallet_poll_order_conclude_cleanup (void *cls, 830 const struct TALER_TESTING_Command *cmd) 831 { 832 struct WalletPollOrderConcludeState *poc = cls; 833 834 if (NULL != poc->task) 835 { 836 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 837 "Command `%s' was not terminated\n", 838 TALER_TESTING_interpreter_get_current_label ( 839 poc->is)); 840 GNUNET_SCHEDULER_cancel (poc->task); 841 poc->task = NULL; 842 } 843 GNUNET_free (poc); 844 } 845 846 847 struct TALER_TESTING_Command 848 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 cps = GNUNET_new (struct WalletPollOrderConcludeState); 857 cps->start_reference = poll_start_reference; 858 cps->expected_http_status = expected_http_status; 859 if (NULL != expected_refund_amount) 860 { 861 cps->expected_refund = true; 862 GNUNET_assert (GNUNET_OK == 863 TALER_string_to_amount (expected_refund_amount, 864 &cps->expected_refund_amount)); 865 } 866 { 867 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 return cmd; 875 } 876 } 877 878 879 struct TALER_TESTING_Command 880 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 cmd = TALER_TESTING_cmd_wallet_poll_order_conclude ( 891 label, 892 expected_http_status, 893 expected_refund_amount, 894 poll_start_reference); 895 cps = cmd.cls; 896 cps->already_paid_order_id = already_paid_order_id; 897 return cmd; 898 } 899 900 901 /* end of testing_api_cmd_wallet_get_order.c */