exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

testing_api_cmd_wire.c (6336B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2018, 2023 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it
      6   under the terms of the GNU General Public License as published by
      7   the Free Software Foundation; either version 3, or (at your
      8   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 GNU
     13   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/testing_api_cmd_wire.c
     21  * @brief command for testing /wire.
     22  * @author Marcello Stanisci
     23  */
     24 #include "taler/platform.h"
     25 #include "taler/taler_json_lib.h"
     26 #include <gnunet/gnunet_curl_lib.h>
     27 #include "taler/taler_testing_lib.h"
     28 
     29 
     30 /**
     31  * State for a "wire" CMD.
     32  */
     33 struct WireState
     34 {
     35 
     36   /**
     37    * Handle to the /wire operation.
     38    */
     39   struct TALER_EXCHANGE_WireHandle *wh;
     40 
     41   /**
     42    * Our command.
     43    */
     44   const struct TALER_TESTING_Command *cmd;
     45 
     46   /**
     47    * Which wire-method we expect is offered by the exchange.
     48    */
     49   const char *expected_method;
     50 
     51   /**
     52    * Flag indicating if the expected method is actually
     53    * offered.
     54    */
     55   unsigned int method_found;
     56 
     57   /**
     58    * Fee we expect is charged for this wire-transfer method.
     59    */
     60   const char *expected_fee;
     61 
     62   /**
     63    * Expected HTTP response code.
     64    */
     65   unsigned int expected_response_code;
     66 
     67   /**
     68    * Interpreter state.
     69    */
     70   struct TALER_TESTING_Interpreter *is;
     71 };
     72 
     73 
     74 /**
     75  * Check whether the HTTP response code is acceptable, that
     76  * the expected wire method is offered by the exchange, and
     77  * that the wire fee is acceptable too.
     78  *
     79  * @param cls closure.
     80  * @param wr response details
     81  */
     82 static void
     83 wire_cb (void *cls,
     84          const struct TALER_EXCHANGE_WireResponse *wr)
     85 {
     86   struct WireState *ws = cls;
     87   const struct TALER_EXCHANGE_HttpResponse *hr = &wr->hr;
     88   struct TALER_Amount expected_fee;
     89 
     90   TALER_LOG_DEBUG ("Checking parsed /wire response\n");
     91   ws->wh = NULL;
     92   if (ws->expected_response_code != hr->http_status)
     93   {
     94     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     95                 "Received unexpected status code %u\n",
     96                 hr->http_status);
     97     TALER_TESTING_interpreter_fail (ws->is);
     98     return;
     99   }
    100 
    101   if (MHD_HTTP_OK == hr->http_status)
    102   {
    103     unsigned int accounts_len
    104       = wr->details.ok.accounts_len;
    105     unsigned int fees_len
    106       = wr->details.ok.fees_len;
    107     const struct TALER_EXCHANGE_WireAccount *accounts
    108       = wr->details.ok.accounts;
    109     const struct TALER_EXCHANGE_WireFeesByMethod *fees
    110       = wr->details.ok.fees;
    111 
    112     for (unsigned int i = 0; i<accounts_len; i++)
    113     {
    114       char *method;
    115 
    116       method = TALER_payto_get_method (accounts[i].payto_uri);
    117       if (NULL == method)
    118       {
    119         GNUNET_break (0);
    120         TALER_TESTING_interpreter_fail (ws->is);
    121         return;
    122       }
    123       if (0 == strcmp (ws->expected_method,
    124                        method))
    125       {
    126         ws->method_found = GNUNET_OK;
    127       }
    128       GNUNET_free (method);
    129     }
    130     if (NULL != ws->expected_fee)
    131     {
    132       bool fee_found = false;
    133 
    134       GNUNET_assert (GNUNET_OK ==
    135                      TALER_string_to_amount (ws->expected_fee,
    136                                              &expected_fee));
    137       for (unsigned int i = 0; i<fees_len; i++)
    138       {
    139         if (0 != strcmp (fees[i].method,
    140                          ws->expected_method))
    141           continue;
    142         for (const struct TALER_EXCHANGE_WireAggregateFees *waf
    143                = fees[i].fees_head;
    144              NULL != waf;
    145              waf = waf->next)
    146         {
    147           if (0 != TALER_amount_cmp (&waf->fees.wire,
    148                                      &expected_fee))
    149           {
    150             GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    151                         "Wire fee mismatch to command %s\n",
    152                         ws->cmd->label);
    153             TALER_TESTING_interpreter_fail (ws->is);
    154             return;
    155           }
    156           fee_found = true;
    157         }
    158       }
    159       if (! fee_found)
    160       {
    161         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    162                     "/wire does not contain expected fee '%s'\n",
    163                     ws->expected_fee);
    164         TALER_TESTING_interpreter_fail (ws->is);
    165         return;
    166       }
    167     }
    168     if (GNUNET_OK != ws->method_found)
    169     {
    170       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    171                   "/wire does not offer method '%s'\n",
    172                   ws->expected_method);
    173       TALER_TESTING_interpreter_fail (ws->is);
    174       return;
    175     }
    176   }
    177   TALER_TESTING_interpreter_next (ws->is);
    178 }
    179 
    180 
    181 /**
    182  * Run the command.
    183  *
    184  * @param cls closure.
    185  * @param cmd the command to execute.
    186  * @param is the interpreter state.
    187  */
    188 static void
    189 wire_run (void *cls,
    190           const struct TALER_TESTING_Command *cmd,
    191           struct TALER_TESTING_Interpreter *is)
    192 {
    193   struct WireState *ws = cls;
    194 
    195   ws->cmd = cmd;
    196   ws->is = is;
    197   ws->wh = TALER_EXCHANGE_wire (
    198     TALER_TESTING_interpreter_get_context (is),
    199     TALER_TESTING_get_exchange_url (is),
    200     TALER_TESTING_get_keys (is),
    201     &wire_cb,
    202     ws);
    203 }
    204 
    205 
    206 /**
    207  * Cleanup the state of a "wire" CMD, and possibly cancel a
    208  * pending operation thereof.
    209  *
    210  * @param cls closure.
    211  * @param cmd the command which is being cleaned up.
    212  */
    213 static void
    214 wire_cleanup (void *cls,
    215               const struct TALER_TESTING_Command *cmd)
    216 {
    217   struct WireState *ws = cls;
    218 
    219   if (NULL != ws->wh)
    220   {
    221     TALER_TESTING_command_incomplete (ws->is,
    222                                       cmd->label);
    223     TALER_EXCHANGE_wire_cancel (ws->wh);
    224     ws->wh = NULL;
    225   }
    226   GNUNET_free (ws);
    227 }
    228 
    229 
    230 struct TALER_TESTING_Command
    231 TALER_TESTING_cmd_wire (const char *label,
    232                         const char *expected_method,
    233                         const char *expected_fee,
    234                         unsigned int expected_response_code)
    235 {
    236   struct WireState *ws;
    237 
    238   ws = GNUNET_new (struct WireState);
    239   ws->expected_method = expected_method;
    240   ws->expected_fee = expected_fee;
    241   ws->expected_response_code = expected_response_code;
    242   {
    243     struct TALER_TESTING_Command cmd = {
    244       .cls = ws,
    245       .label = label,
    246       .run = &wire_run,
    247       .cleanup = &wire_cleanup
    248     };
    249 
    250     return cmd;
    251   }
    252 }