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