LCOV - code coverage report
Current view: top level - testing - testing_api_cmd_wallet_get_order.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 75.9 % 253 192
Test Date: 2026-09-11 17:45:24 Functions: 100.0 % 15 15

            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 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           21 : wallet_get_order_cb (
     104              :   void *cls,
     105              :   const struct TALER_MERCHANT_GetOrdersResponse *owgr)
     106              : {
     107           21 :   struct WalletGetOrderState *gos = cls;
     108           21 :   const struct TALER_MERCHANT_HttpResponse *hr = &owgr->hr;
     109              : 
     110           21 :   gos->ogh = NULL;
     111           21 :   if (gos->http_status != hr->http_status)
     112              :   {
     113            0 :     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            0 :     TALER_TESTING_interpreter_fail (gos->is);
     119            0 :     return;
     120              :   }
     121           21 :   switch (hr->http_status)
     122              :   {
     123           14 :   case MHD_HTTP_OK:
     124           14 :     if (gos->refunded != owgr->details.ok.refunded)
     125              :     {
     126            0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     127              :                   "Order refunded does not match\n");
     128            0 :       TALER_TESTING_interpreter_fail (gos->is);
     129            0 :       return;
     130              :     }
     131           14 :     if (gos->refund_pending != owgr->details.ok.refund_pending)
     132              :     {
     133            0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     134              :                   "Order refund pending does not match\n");
     135            0 :       TALER_TESTING_interpreter_fail (gos->is);
     136            0 :       return;
     137              :     }
     138           14 :     break;
     139            7 :   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            7 :       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            2 :         rep_cmd = TALER_TESTING_interpreter_lookup_command (
     153              :           gos->is,
     154              :           gos->repurchase_order_ref);
     155            2 :         if (GNUNET_OK !=
     156            2 :             TALER_TESTING_get_trait_order_id (rep_cmd,
     157              :                                               &rep_id))
     158              :         {
     159            0 :           TALER_TESTING_FAIL (gos->is);
     160              :         }
     161            2 :         ri = owgr->details.payment_required.already_paid_order_id;
     162            2 :         if ( (NULL == ri) ||
     163              :              (0 !=
     164            2 :               strcmp (ri,
     165              :                       rep_id)) )
     166              :         {
     167            0 :           TALER_TESTING_FAIL (gos->is);
     168              :         }
     169              :       }
     170              : 
     171            7 :       if (GNUNET_OK !=
     172            7 :           TALER_MERCHANT_parse_pay_uri (
     173            7 :             owgr->details.payment_required.taler_pay_uri,
     174              :             &pud))
     175              :       {
     176            0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     177              :                     "Taler pay uri `%s' is malformed\n",
     178              :                     owgr->details.payment_required.taler_pay_uri);
     179            0 :         TALER_TESTING_interpreter_fail (gos->is);
     180            0 :         return;
     181              :       }
     182              : 
     183            7 :       order_cmd = TALER_TESTING_interpreter_lookup_command (
     184              :         gos->is,
     185              :         gos->order_reference);
     186              : 
     187            7 :       if (GNUNET_OK !=
     188            7 :           TALER_TESTING_get_trait_order_id (order_cmd,
     189              :                                             &order_id))
     190              :       {
     191            0 :         TALER_MERCHANT_parse_pay_uri_free (&pud);
     192            0 :         TALER_TESTING_FAIL (gos->is);
     193              :       }
     194              : 
     195            7 :       if (GNUNET_OK !=
     196            7 :           TALER_TESTING_get_trait_claim_token (order_cmd,
     197              :                                                &claim_token))
     198              :       {
     199            0 :         TALER_MERCHANT_parse_pay_uri_free (&pud);
     200            0 :         TALER_TESTING_FAIL (gos->is);
     201              :       }
     202              : 
     203              :       {
     204              :         char *host;
     205              : 
     206            7 :         host = TALER_MERCHANT_TESTING_extract_host (gos->merchant_url);
     207            7 :         if ((0 != strcmp (host,
     208            7 :                           pud.merchant_host)) ||
     209            7 :             (NULL != pud.merchant_prefix_path) ||
     210            7 :             (0 != strcmp (order_id,
     211            7 :                           pud.order_id)) ||
     212            7 :             (NULL != pud.ssid))
     213              :         {
     214            0 :           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            0 :           TALER_TESTING_interpreter_fail (gos->is);
     219            0 :           TALER_MERCHANT_parse_pay_uri_free (&pud);
     220            0 :           GNUNET_free (host);
     221            0 :           return;
     222              :         }
     223            7 :         GNUNET_free (host);
     224              :       }
     225              :       /* The claim token is not given in the pay uri if the order
     226              :          has been claimed already. */
     227            7 :       if ((NULL != pud.claim_token) &&
     228            0 :           ((NULL == claim_token) ||
     229            0 :            (0 != GNUNET_memcmp (claim_token,
     230              :                                 pud.claim_token))))
     231              :       {
     232            0 :         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            0 :         TALER_TESTING_interpreter_fail (gos->is);
     237            0 :         TALER_MERCHANT_parse_pay_uri_free (&pud);
     238            0 :         return;
     239              :       }
     240            7 :       TALER_MERCHANT_parse_pay_uri_free (&pud);
     241              :     }
     242            7 :     break;
     243            0 :   default:
     244            0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     245              :                 "Unhandled HTTP status.\n");
     246              :   }
     247           21 :   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           21 : wallet_get_order_run (void *cls,
     260              :                       const struct TALER_TESTING_Command *cmd,
     261              :                       struct TALER_TESTING_Interpreter *is)
     262              : {
     263           21 :   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           21 :   order_cmd = TALER_TESTING_interpreter_lookup_command (
     269              :     is,
     270              :     gos->order_reference);
     271              : 
     272           21 :   if (GNUNET_OK !=
     273           21 :       TALER_TESTING_get_trait_order_id (order_cmd,
     274              :                                         &order_id))
     275            0 :     TALER_TESTING_FAIL (is);
     276              : 
     277           21 :   if (GNUNET_OK !=
     278           21 :       TALER_TESTING_get_trait_h_contract_terms (order_cmd,
     279              :                                                 &h_contract))
     280            0 :     TALER_TESTING_FAIL (is);
     281              : 
     282           21 :   gos->is = is;
     283           21 :   gos->ogh = TALER_MERCHANT_get_orders_create (
     284              :     TALER_TESTING_interpreter_get_context (is),
     285              :     gos->merchant_url,
     286              :     order_id);
     287           21 :   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           21 :     ec = TALER_MERCHANT_get_orders_start (
     297              :       gos->ogh,
     298              :       &wallet_get_order_cb,
     299              :       gos);
     300           21 :     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           21 : wallet_get_order_cleanup (void *cls,
     314              :                           const struct TALER_TESTING_Command *cmd)
     315              : {
     316           21 :   struct WalletGetOrderState *gos = cls;
     317              : 
     318           21 :   if (NULL != gos->ogh)
     319              :   {
     320            0 :     TALER_LOG_WARNING ("Get order operation did not complete\n");
     321            0 :     TALER_MERCHANT_get_orders_cancel (gos->ogh);
     322              :   }
     323           21 :   GNUNET_free (gos);
     324           21 : }
     325              : 
     326              : 
     327              : struct TALER_TESTING_Command
     328           13 : 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           13 :   gos = GNUNET_new (struct WalletGetOrderState);
     340           13 :   gos->merchant_url = merchant_url;
     341           13 :   gos->order_reference = order_reference;
     342           13 :   gos->http_status = http_status;
     343           13 :   gos->paid = paid;
     344           13 :   gos->refunded = refunded;
     345           13 :   gos->refund_pending = refund_pending;
     346              :   {
     347           13 :     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           13 :     return cmd;
     355              :   }
     356              : }
     357              : 
     358              : 
     359              : struct TALER_TESTING_Command
     360            8 : 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            8 :   gos = GNUNET_new (struct WalletGetOrderState);
     374            8 :   gos->merchant_url = merchant_url;
     375            8 :   gos->order_reference = order_reference;
     376            8 :   gos->http_status = http_status;
     377            8 :   gos->paid = paid;
     378            8 :   gos->session_id = session_id;
     379            8 :   gos->refunded = refunded;
     380            8 :   gos->refund_pending = refund_pending;
     381            8 :   gos->repurchase_order_ref = repurchase_order_ref;
     382              :   {
     383            8 :     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            8 :     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            8 : conclude_task (void *cls)
     526              : {
     527            8 :   struct WalletPollOrderConcludeState *ppc = cls;
     528              :   const struct TALER_TESTING_Command *poll_cmd;
     529              :   struct WalletPollOrderStartState *cps;
     530              :   struct GNUNET_TIME_Absolute now;
     531              : 
     532            8 :   ppc->task = NULL;
     533              :   poll_cmd =
     534            8 :     TALER_TESTING_interpreter_lookup_command (ppc->is,
     535              :                                               ppc->start_reference);
     536            8 :   if (NULL == poll_cmd)
     537            0 :     TALER_TESTING_FAIL (ppc->is);
     538            8 :   cps = poll_cmd->cls;
     539            8 :   if (NULL != cps->ogh)
     540              :   {
     541            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     542              :                 "Expected poll GET /orders/$ORDER_ID to have completed, but it did not!\n");
     543            0 :     TALER_TESTING_FAIL (ppc->is);
     544              :   }
     545            8 :   if (cps->http_status != ppc->expected_http_status)
     546              :   {
     547            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     548              :                 "Expected HTTP status %u, got %u\n",
     549              :                 ppc->expected_http_status,
     550              :                 cps->http_status);
     551            0 :     TALER_TESTING_FAIL (ppc->is);
     552              :   }
     553            8 :   if (ppc->expected_refund != cps->refunded)
     554              :   {
     555            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     556              :                 "Order was %srefunded, contrary to our expectations\n",
     557              :                 cps->refunded ? "" : "NOT ");
     558            0 :     TALER_TESTING_FAIL (ppc->is);
     559              :   }
     560            8 :   if ( (NULL == ppc->already_paid_order_id)
     561            8 :        ^ (NULL == cps->already_paid_order_id) )
     562              :   {
     563            0 :     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            0 :     TALER_TESTING_FAIL (ppc->is);
     568              :   }
     569            8 :   if ( (NULL != ppc->already_paid_order_id) &&
     570            2 :        (0 != strcmp (ppc->already_paid_order_id,
     571            2 :                      cps->already_paid_order_id) ) )
     572              :   {
     573            0 :     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            0 :     TALER_TESTING_FAIL (ppc->is);
     578              :   }
     579              : 
     580            8 :   if (cps->refunded)
     581              :   {
     582            4 :     if (0 != TALER_amount_cmp (&ppc->expected_refund_amount,
     583            4 :                                &cps->refund_available))
     584              :     {
     585            0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     586              :                   "Refund amount %s does not match our expectation!\n",
     587              :                   TALER_amount2s (&cps->refund_available));
     588            0 :       TALER_TESTING_FAIL (ppc->is);
     589              :     }
     590              :   }
     591              :   // FIXME: add checks for cps->paid/refund_available status flags?
     592            8 :   now = GNUNET_TIME_absolute_get ();
     593            8 :   if ((GNUNET_TIME_absolute_add (cps->deadline,
     594            8 :                                  GNUNET_TIME_UNIT_SECONDS).abs_value_us <
     595            8 :        now.abs_value_us) )
     596              :   {
     597            0 :     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            0 :     TALER_TESTING_FAIL (ppc->is);
     602              :   }
     603            8 :   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            8 : wallet_poll_order_cb (
     618              :   void *cls,
     619              :   const struct TALER_MERCHANT_GetOrdersResponse *owgr)
     620              : {
     621            8 :   struct WalletPollOrderStartState *pos = cls;
     622            8 :   const struct TALER_MERCHANT_HttpResponse *hr = &owgr->hr;
     623              : 
     624            8 :   pos->ogh = NULL;
     625            8 :   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     626              :               "GET /orders/$ID finished with status %u.\n",
     627              :               hr->http_status);
     628            8 :   pos->http_status = hr->http_status;
     629            8 :   switch (hr->http_status)
     630              :   {
     631            6 :   case MHD_HTTP_OK:
     632            6 :     pos->paid = true;
     633            6 :     pos->refunded = owgr->details.ok.refunded;
     634            6 :     pos->refund_pending = owgr->details.ok.refund_pending;
     635            6 :     if (owgr->details.ok.refunded)
     636            4 :       pos->refund_available = owgr->details.ok.refund_amount;
     637            6 :     break;
     638            2 :   case MHD_HTTP_PAYMENT_REQUIRED:
     639            2 :     if (NULL != owgr->details.payment_required.already_paid_order_id)
     640            2 :       pos->already_paid_order_id = GNUNET_strdup (
     641              :         owgr->details.payment_required.already_paid_order_id);
     642            2 :     break;
     643            0 :   default:
     644            0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     645              :                 "Unhandled HTTP status.\n");
     646            0 :     break;
     647              :   }
     648            8 :   if ( (NULL != pos->cs) &&
     649            4 :        (NULL != pos->cs->task) )
     650              :   {
     651            4 :     GNUNET_SCHEDULER_cancel (pos->cs->task);
     652            4 :     pos->cs->task = GNUNET_SCHEDULER_add_now (&conclude_task,
     653            4 :                                               pos->cs);
     654              :   }
     655            8 : }
     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            8 : wallet_poll_order_start_run (void *cls,
     667              :                              const struct TALER_TESTING_Command *cmd,
     668              :                              struct TALER_TESTING_Interpreter *is)
     669              : {
     670            8 :   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            8 :   order_cmd = TALER_TESTING_interpreter_lookup_command (
     676              :     is,
     677              :     pos->order_ref);
     678              : 
     679            8 :   if (GNUNET_OK !=
     680            8 :       TALER_TESTING_get_trait_order_id (order_cmd,
     681              :                                         &order_id))
     682            0 :     TALER_TESTING_FAIL (is);
     683              : 
     684            8 :   if (GNUNET_OK !=
     685            8 :       TALER_TESTING_get_trait_h_contract_terms (order_cmd,
     686              :                                                 &h_contract))
     687            0 :     TALER_TESTING_FAIL (is);
     688              : 
     689              :   /* add 1s grace time to timeout */
     690              :   pos->deadline
     691            8 :     = GNUNET_TIME_absolute_add (GNUNET_TIME_relative_to_absolute (pos->timeout),
     692              :                                 GNUNET_TIME_UNIT_SECONDS);
     693            8 :   pos->is = is;
     694            8 :   pos->ogh = TALER_MERCHANT_get_orders_create (
     695              :     TALER_TESTING_interpreter_get_context (is),
     696              :     pos->merchant_url,
     697              :     order_id);
     698            8 :   TALER_MERCHANT_get_orders_set_options (
     699              :     pos->ogh,
     700              :     TALER_MERCHANT_get_orders_option_h_contract (*h_contract));
     701            8 :   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            8 :   if (pos->wait_for_refund)
     706            4 :     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            8 :     ec = TALER_MERCHANT_get_orders_start (
     713              :       pos->ogh,
     714              :       &wallet_poll_order_cb,
     715              :       pos);
     716            8 :     GNUNET_assert (TALER_EC_NONE == ec);
     717              :   }
     718              :   /* We CONTINUE to run the interpreter while the long-polled command
     719              :      completes asynchronously! */
     720            8 :   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            8 : wallet_poll_order_start_cleanup (void *cls,
     733              :                                  const struct TALER_TESTING_Command *cmd)
     734              : {
     735            8 :   struct WalletPollOrderStartState *pos = cls;
     736              : 
     737            8 :   if (NULL != pos->ogh)
     738              :   {
     739            0 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     740              :                 "Command `%s' was not terminated\n",
     741              :                 TALER_TESTING_interpreter_get_current_label (
     742              :                   pos->is));
     743            0 :     TALER_MERCHANT_get_orders_cancel (pos->ogh);
     744              :   }
     745            8 :   GNUNET_free (pos->already_paid_order_id);
     746            8 :   GNUNET_free (pos);
     747            8 : }
     748              : 
     749              : 
     750              : struct TALER_TESTING_Command
     751            8 : 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            8 :   pos = GNUNET_new (struct WalletPollOrderStartState);
     761            8 :   pos->order_ref = order_ref;
     762            8 :   pos->merchant_url = merchant_url;
     763            8 :   pos->timeout = timeout;
     764            8 :   if (NULL != await_refund)
     765              :   {
     766            4 :     pos->wait_for_refund = true;
     767            4 :     GNUNET_assert (GNUNET_OK ==
     768              :                    TALER_string_to_amount (await_refund,
     769              :                                            &pos->refund_threshold));
     770              :   }
     771              :   {
     772            8 :     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            8 :     return cmd;
     780              :   }
     781              : }
     782              : 
     783              : 
     784              : struct TALER_TESTING_Command
     785            2 : 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            2 :   cmd = TALER_TESTING_cmd_wallet_poll_order_start (label,
     797              :                                                    merchant_url,
     798              :                                                    order_ref,
     799              :                                                    timeout,
     800              :                                                    await_refund);
     801            2 :   pos = cmd.cls;
     802            2 :   pos->session_id = session_id;
     803            2 :   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            8 : wallet_poll_order_conclude_run (void *cls,
     816              :                                 const struct TALER_TESTING_Command *cmd,
     817              :                                 struct TALER_TESTING_Interpreter *is)
     818              : {
     819            8 :   struct WalletPollOrderConcludeState *poc = cls;
     820              :   const struct TALER_TESTING_Command *poll_cmd;
     821              :   struct WalletPollOrderStartState *pos;
     822              : 
     823            8 :   poc->is = is;
     824              :   poll_cmd =
     825            8 :     TALER_TESTING_interpreter_lookup_command (is,
     826              :                                               poc->start_reference);
     827            8 :   if (NULL == poll_cmd)
     828            0 :     TALER_TESTING_FAIL (poc->is);
     829            8 :   GNUNET_assert (poll_cmd->run == &wallet_poll_order_start_run);
     830            8 :   pos = poll_cmd->cls;
     831            8 :   pos->cs = poc;
     832            8 :   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            8 :   if (NULL == pos->ogh)
     839            4 :     poc->task = GNUNET_SCHEDULER_add_now (&conclude_task,
     840              :                                           poc);
     841              :   else
     842            4 :     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            8 : wallet_poll_order_conclude_cleanup (void *cls,
     857              :                                     const struct TALER_TESTING_Command *cmd)
     858              : {
     859            8 :   struct WalletPollOrderConcludeState *poc = cls;
     860              : 
     861            8 :   if (NULL != poc->task)
     862              :   {
     863            0 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     864              :                 "Command `%s' was not terminated\n",
     865              :                 TALER_TESTING_interpreter_get_current_label (
     866              :                   poc->is));
     867            0 :     GNUNET_SCHEDULER_cancel (poc->task);
     868            0 :     poc->task = NULL;
     869              :   }
     870            8 :   GNUNET_free (poc);
     871            8 : }
     872              : 
     873              : 
     874              : struct TALER_TESTING_Command
     875            8 : 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            8 :   cps = GNUNET_new (struct WalletPollOrderConcludeState);
     884            8 :   cps->start_reference = poll_start_reference;
     885            8 :   cps->expected_http_status = expected_http_status;
     886            8 :   if (NULL != expected_refund_amount)
     887              :   {
     888            4 :     cps->expected_refund = true;
     889            4 :     GNUNET_assert (GNUNET_OK ==
     890              :                    TALER_string_to_amount (expected_refund_amount,
     891              :                                            &cps->expected_refund_amount));
     892              :   }
     893              :   {
     894            8 :     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            8 :     return cmd;
     902              :   }
     903              : }
     904              : 
     905              : 
     906              : struct TALER_TESTING_Command
     907            2 : 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            2 :   cmd = TALER_TESTING_cmd_wallet_poll_order_conclude (
     918              :     label,
     919              :     expected_http_status,
     920              :     expected_refund_amount,
     921              :     poll_start_reference);
     922            2 :   cps = cmd.cls;
     923            2 :   cps->already_paid_order_id = already_paid_order_id;
     924            2 :   return cmd;
     925              : }
     926              : 
     927              : 
     928              : /* end of testing_api_cmd_wallet_get_order.c */
        

Generated by: LCOV version 2.0-1