LCOV - code coverage report
Current view: top level - testing - testing_api_cmd_wallet_post_orders_refund.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 71.8 % 78 56
Test Date: 2026-09-11 17:45:24 Functions: 100.0 % 4 4

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   Copyright (C) 2020-2023 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_post_orders_refund.c
      21              :  * @brief command to test refunds.
      22              :  * @author Marcello Stanisci
      23              :  * @author Christian Grothoff
      24              :  */
      25              : #include "platform.h"
      26              : struct WalletRefundState;
      27              : #define TALER_MERCHANT_POST_ORDERS_REFUND_RESULT_CLOSURE struct WalletRefundState
      28              : #include <taler/taler_exchange_service.h>
      29              : #include <taler/taler_testing_lib.h>
      30              : #include "taler/taler_merchant_service.h"
      31              : #include "taler/taler_merchant_testing_lib.h"
      32              : #include <taler/merchant/post-orders-ORDER_ID-refund.h>
      33              : 
      34              : 
      35              : /**
      36              :  * State for an "obtain refunds" CMD.
      37              :  */
      38              : struct WalletRefundState
      39              : {
      40              :   /**
      41              :    * Operation handle for a (public) POST /orders/$ID/refund request.
      42              :    */
      43              :   struct TALER_MERCHANT_PostOrdersRefundHandle *orh;
      44              : 
      45              :   /**
      46              :    * Base URL of the merchant serving the request.
      47              :    */
      48              :   const char *merchant_url;
      49              : 
      50              :   /**
      51              :    * Interpreter state.
      52              :    */
      53              :   struct TALER_TESTING_Interpreter *is;
      54              : 
      55              :   /**
      56              :    * Expected HTTP response code.
      57              :    */
      58              :   unsigned int http_code;
      59              : 
      60              :   /**
      61              :    * Label of the command that created the order we want to obtain refunds for.
      62              :    */
      63              :   const char *proposal_reference;
      64              : 
      65              :   /**
      66              :    * A list of refunds associated with this order.
      67              :    */
      68              :   const char **refunds;
      69              : 
      70              :   /**
      71              :    * The length of @e refunds.
      72              :    */
      73              :   unsigned int refunds_length;
      74              : };
      75              : 
      76              : 
      77              : /**
      78              :  * Process POST /refund (increase) response; just checking
      79              :  * if the HTTP response code is the one expected.
      80              :  *
      81              :  * @param cls closure
      82              :  * @param wrr response
      83              :  */
      84              : static void
      85            2 : refund_cb (
      86              :   struct WalletRefundState *wrs,
      87              :   const struct TALER_MERCHANT_PostOrdersRefundResponse *wrr)
      88              : {
      89              : 
      90            2 :   wrs->orh = NULL;
      91            2 :   if (wrs->http_code != wrr->hr.http_status)
      92              :   {
      93            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
      94              :                 "Expected status %u, got %u(%d) for refund increase\n",
      95              :                 wrs->http_code,
      96              :                 wrr->hr.http_status,
      97              :                 (int) wrr->hr.ec);
      98            0 :     TALER_TESTING_FAIL (wrs->is);
      99              :   }
     100            2 :   switch (wrr->hr.http_status)
     101              :   {
     102            2 :   case MHD_HTTP_OK:
     103              :     {
     104              :       struct TALER_Amount refunded_total;
     105            2 :       if (wrr->details.ok.num_refunds != wrs->refunds_length)
     106              :       {
     107            0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     108              :                     "Number of refunds found (%u) does not match expected (%u)\n",
     109              :                     wrr->details.ok.num_refunds,
     110              :                     wrs->refunds_length);
     111            0 :         TALER_TESTING_interpreter_fail (wrs->is);
     112            0 :         return;
     113              :       }
     114            2 :       if (wrr->details.ok.num_refunds > 0)
     115            2 :         GNUNET_assert (GNUNET_OK ==
     116              :                        TALER_amount_set_zero (
     117              :                          wrr->details.ok.refunds[0].refund_amount.currency,
     118              :                          &refunded_total));
     119            6 :       for (unsigned int i = 0; i < wrr->details.ok.num_refunds; ++i)
     120              :       {
     121            4 :         const struct TALER_MERCHANT_PostOrdersRefundDetail *refund
     122            4 :           = &wrr->details.ok.refunds[wrr->details.ok.num_refunds - 1 - i];
     123              :         const struct TALER_TESTING_Command *refund_cmd;
     124              :         const struct TALER_Amount *expected_amount;
     125              : 
     126            4 :         refund_cmd = TALER_TESTING_interpreter_lookup_command (
     127              :           wrs->is,
     128            4 :           wrs->refunds[i]);
     129              : 
     130            4 :         if (GNUNET_OK !=
     131            4 :             TALER_TESTING_get_trait_amount (refund_cmd,
     132              :                                             &expected_amount))
     133              :         {
     134            0 :           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     135              :                       "Could not fetch refund amount\n");
     136            0 :           TALER_TESTING_interpreter_fail (wrs->is);
     137            0 :           return;
     138              :         }
     139              :         /* The most recent refunds are returned first */
     140            4 :         GNUNET_assert (0 <= TALER_amount_add (&refunded_total,
     141              :                                               &refunded_total,
     142              :                                               &refund->refund_amount));
     143            4 :         if ( (GNUNET_OK !=
     144            4 :               TALER_amount_cmp_currency (expected_amount,
     145            4 :                                          &refunded_total)) ||
     146            4 :              (0 != TALER_amount_cmp (expected_amount,
     147              :                                      &refunded_total)) )
     148              :         {
     149            0 :           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     150              :                       "Refund amounts do not match\n");
     151            0 :           TALER_TESTING_interpreter_fail (wrs->is);
     152            0 :           return;
     153              :         }
     154              :       }
     155              :     }
     156            2 :     break;
     157            0 :   default:
     158            0 :     break;
     159              :   }
     160            2 :   TALER_TESTING_interpreter_next (wrs->is);
     161              : }
     162              : 
     163              : 
     164              : /**
     165              :  * Run the "refund increase" CMD.
     166              :  *
     167              :  * @param cls closure.
     168              :  * @param cmd command currently being run.
     169              :  * @param is the interpreter state.
     170              :  */
     171              : static void
     172            2 : obtain_refunds_run (void *cls,
     173              :                     const struct TALER_TESTING_Command *cmd,
     174              :                     struct TALER_TESTING_Interpreter *is)
     175              : {
     176            2 :   struct WalletRefundState *wrs = cls;
     177              :   const struct TALER_TESTING_Command *proposal_cmd =
     178            2 :     TALER_TESTING_interpreter_lookup_command (is,
     179              :                                               wrs->proposal_reference);
     180              :   const struct TALER_PrivateContractHashP *h_contract_terms;
     181              :   const char *order_id;
     182              : 
     183            2 :   if (NULL == proposal_cmd)
     184            0 :     TALER_TESTING_FAIL (is);
     185            2 :   if (GNUNET_OK !=
     186            2 :       TALER_TESTING_get_trait_h_contract_terms (proposal_cmd,
     187              :                                                 &h_contract_terms))
     188            0 :     TALER_TESTING_FAIL (is);
     189              : 
     190              :   {
     191              :     const json_t *contract_terms;
     192              :     const char *error_name;
     193              :     unsigned int error_line;
     194              : 
     195            2 :     if (GNUNET_OK !=
     196            2 :         TALER_TESTING_get_trait_contract_terms (proposal_cmd,
     197              :                                                 &contract_terms))
     198            0 :       TALER_TESTING_FAIL (is);
     199              :     {
     200              :       /* Get information that needs to be put verbatim in the
     201              :        * deposit permission */
     202              :       struct GNUNET_JSON_Specification spec[] = {
     203            2 :         TALER_JSON_spec_slug ("order_id",
     204              :                               &order_id),
     205            2 :         GNUNET_JSON_spec_end ()
     206              :       };
     207              : 
     208            2 :       if (GNUNET_OK !=
     209            2 :           GNUNET_JSON_parse (contract_terms,
     210              :                              spec,
     211              :                              &error_name,
     212              :                              &error_line))
     213              :       {
     214              :         char *js;
     215              : 
     216            0 :         js = json_dumps (contract_terms,
     217              :                          JSON_INDENT (1));
     218            0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     219              :                     "Parser failed on %s:%u for input `%s'\n",
     220              :                     error_name,
     221              :                     error_line,
     222              :                     js);
     223            0 :         free (js);
     224            0 :         TALER_TESTING_FAIL (is);
     225              :       }
     226              :     }
     227              :   }
     228              : 
     229            2 :   wrs->is = is;
     230            2 :   wrs->orh = TALER_MERCHANT_post_orders_refund_create (
     231              :     TALER_TESTING_interpreter_get_context (is),
     232              :     wrs->merchant_url,
     233              :     order_id,
     234              :     h_contract_terms);
     235              :   {
     236              :     enum TALER_ErrorCode ec;
     237              : 
     238            2 :     ec = TALER_MERCHANT_post_orders_refund_start (
     239              :       wrs->orh,
     240              :       &refund_cb,
     241              :       wrs);
     242            2 :     GNUNET_assert (TALER_EC_NONE == ec);
     243              :   }
     244              : }
     245              : 
     246              : 
     247              : /**
     248              :  * Free the state of a "refund increase" CMD, and
     249              :  * possibly cancel a pending "refund increase" operation.
     250              :  *
     251              :  * @param cls closure
     252              :  * @param cmd command currently being freed.
     253              :  */
     254              : static void
     255            2 : obtain_refunds_cleanup (void *cls,
     256              :                         const struct TALER_TESTING_Command *cmd)
     257              : {
     258            2 :   struct WalletRefundState *wrs = cls;
     259              : 
     260            2 :   if (NULL != wrs->orh)
     261              :   {
     262            0 :     TALER_LOG_WARNING ("Refund operation did not complete\n");
     263            0 :     TALER_MERCHANT_post_orders_refund_cancel (wrs->orh);
     264              :   }
     265            2 :   GNUNET_array_grow (wrs->refunds,
     266              :                      wrs->refunds_length,
     267              :                      0);
     268            2 :   GNUNET_free (wrs);
     269            2 : }
     270              : 
     271              : 
     272              : struct TALER_TESTING_Command
     273            2 : TALER_TESTING_cmd_wallet_order_refund (const char *label,
     274              :                                        const char *merchant_url,
     275              :                                        const char *order_ref,
     276              :                                        unsigned int http_code,
     277              :                                        ...)
     278              : {
     279              :   struct WalletRefundState *wrs;
     280              : 
     281            2 :   wrs = GNUNET_new (struct WalletRefundState);
     282            2 :   wrs->merchant_url = merchant_url;
     283            2 :   wrs->proposal_reference = order_ref;
     284            2 :   wrs->http_code = http_code;
     285            2 :   wrs->refunds_length = 0;
     286              :   {
     287              :     const char *clabel;
     288              :     va_list ap;
     289              : 
     290            2 :     va_start (ap, http_code);
     291            6 :     while (NULL != (clabel = va_arg (ap, const char *)))
     292              :     {
     293            4 :       GNUNET_array_append (wrs->refunds,
     294              :                            wrs->refunds_length,
     295              :                            clabel);
     296              :     }
     297            2 :     va_end (ap);
     298              :   }
     299              :   {
     300            2 :     struct TALER_TESTING_Command cmd = {
     301              :       .cls = wrs,
     302              :       .label = label,
     303              :       .run = &obtain_refunds_run,
     304              :       .cleanup = &obtain_refunds_cleanup
     305              :     };
     306              : 
     307            2 :     return cmd;
     308              :   }
     309              : }
        

Generated by: LCOV version 2.0-1