LCOV - code coverage report
Current view: top level - testing - testing_api_cmd_abort_order.c (source / functions) Hit Total Coverage
Test: GNU Taler coverage report Lines: 0 103 0.0 %
Date: 2020-08-15 06:12:35 Functions: 0 6 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2014-2018, 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 lib/testing_api_cmd_abort_order.c
      21             :  * @brief command to test the abort feature.
      22             :  * @author Marcello Stanisci
      23             :  */
      24             : #include "platform.h"
      25             : #include <taler/taler_exchange_service.h>
      26             : #include <taler/taler_testing_lib.h>
      27             : #include <taler/taler_signatures.h>
      28             : #include "taler_merchant_service.h"
      29             : #include "taler_merchant_testing_lib.h"
      30             : 
      31             : #define AMOUNT_WITH_FEE 0
      32             : 
      33             : /**
      34             :  * State for a " abort" CMD.
      35             :  */
      36             : struct AbortState
      37             : {
      38             : 
      39             :   /**
      40             :    * Reference to the "pay" command to abort.
      41             :    */
      42             :   const char *pay_reference;
      43             : 
      44             :   /**
      45             :    * Merchant URL.
      46             :    */
      47             :   const char *merchant_url;
      48             : 
      49             :   /**
      50             :    * Handle to a "abort" operation.
      51             :    */
      52             :   struct TALER_MERCHANT_OrderAbortHandle *oah;
      53             : 
      54             :   /**
      55             :    * Interpreter state.
      56             :    */
      57             :   struct TALER_TESTING_Interpreter *is;
      58             : 
      59             :   /**
      60             :    * The actual abort/refund data.
      61             :    */
      62             :   struct TALER_MERCHANT_AbortedCoin *acs;
      63             : 
      64             :   /**
      65             :    * Expected HTTP response code.
      66             :    */
      67             :   unsigned int http_status;
      68             : 
      69             :   /**
      70             :    * How many refund permissions this CMD got
      71             :    * the right for.  Roughly, there is one refund
      72             :    * permission for one coin.
      73             :    */
      74             :   unsigned int acs_length;
      75             : 
      76             : };
      77             : 
      78             : 
      79             : /**
      80             :  * Parse the @a coins specification and grow the @a ac
      81             :  * array with the coins found, updating @a nac.
      82             :  *
      83             :  * @param[in,out] ac pointer to array of coins found
      84             :  * @param[in,out] nac length of array at @a pc
      85             :  * @param[in] coins string specifying coins to add to @a pc,
      86             :  *            clobbered in the process
      87             :  * @param is interpreter state
      88             :  * @param amount_with_fee total amount to be paid for a contract.
      89             :  * @param amount_without_fee to be removed, there is no
      90             :  *        per-contract fee, only per-coin exists.
      91             :  * @param refund_fee per-contract? per-coin?
      92             :  * @return #GNUNET_OK on success
      93             :  */
      94             : static int
      95           0 : build_coins (struct TALER_MERCHANT_AbortCoin **ac,
      96             :              unsigned int *nac,
      97             :              char *coins,
      98             :              struct TALER_TESTING_Interpreter *is,
      99             :              const char *amount_with_fee)
     100             : {
     101             :   char *token;
     102             : 
     103           0 :   for (token = strtok (coins, ";");
     104             :        NULL != token;
     105           0 :        token = strtok (NULL, ";"))
     106             :   {
     107             :     char *ctok;
     108             :     unsigned int ci;
     109             :     struct TALER_MERCHANT_AbortCoin *icoin;
     110             : 
     111             :     /* Token syntax is "LABEL[/NUMBER]" */
     112           0 :     ctok = strchr (token, '/');
     113           0 :     ci = 0;
     114           0 :     if (NULL != ctok)
     115             :     {
     116           0 :       *ctok = '\0';
     117           0 :       ctok++;
     118           0 :       if (1 != sscanf (ctok,
     119             :                        "%u",
     120             :                        &ci))
     121             :       {
     122           0 :         GNUNET_break (0);
     123           0 :         return GNUNET_SYSERR;
     124             :       }
     125             :     }
     126             :     // FIXME: ci not used!?
     127             :     {
     128             :       const struct TALER_TESTING_Command *coin_cmd;
     129           0 :       coin_cmd = TALER_TESTING_interpreter_lookup_command (is,
     130             :                                                            token);
     131           0 :       if (NULL == coin_cmd)
     132             :       {
     133           0 :         GNUNET_break (0);
     134           0 :         return GNUNET_SYSERR;
     135             :       }
     136           0 :       GNUNET_array_grow (*ac,
     137             :                          *nac,
     138             :                          (*nac) + 1);
     139           0 :       icoin = &((*ac)[(*nac) - 1]);
     140             : 
     141             :       {
     142             :         const struct TALER_CoinSpendPrivateKeyP *coin_priv;
     143             : 
     144           0 :         GNUNET_assert (GNUNET_OK ==
     145             :                        TALER_TESTING_get_trait_coin_priv (coin_cmd,
     146             :                                                           0,
     147             :                                                           &coin_priv));
     148           0 :         GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
     149             :                                             &icoin->coin_pub.eddsa_pub);
     150             :       }
     151           0 :       GNUNET_assert (GNUNET_OK ==
     152             :                      TALER_TESTING_get_trait_url (coin_cmd,
     153             :                                                   TALER_TESTING_UT_EXCHANGE_BASE_URL,
     154             :                                                   &icoin->exchange_url));
     155             :       {
     156             :         const struct TALER_Amount *denom_value;
     157           0 :         GNUNET_assert (GNUNET_OK
     158             :                        == TALER_TESTING_get_trait_amount_obj (coin_cmd,
     159             :                                                               0,
     160             :                                                               &denom_value));
     161           0 :         icoin->amount_with_fee = *denom_value;
     162             :       }
     163             : 
     164             :     }
     165             :   }
     166           0 :   return GNUNET_OK;
     167             : }
     168             : 
     169             : 
     170             : /**
     171             :  * Callback for a "pay abort" operation.  Mainly, check HTTP
     172             :  * response code was as expected and stores refund permissions
     173             :  * in the state.
     174             :  *
     175             :  * @param cls closure.
     176             :  * @param hr HTTP response
     177             :  * @param merchant_pub public key of the merchant refunding the
     178             :  *        contract.
     179             :  * @param h_contract the contract involved in the refund.
     180             :  * @param num_refunds length of the @a res array
     181             :  * @param res array containing the abort confirmations
     182             :  */
     183             : static void
     184           0 : abort_cb (void *cls,
     185             :           const struct TALER_MERCHANT_HttpResponse *hr,
     186             :           const struct TALER_MerchantPublicKeyP *merchant_pub,
     187             :           unsigned int num_aborts,
     188             :           const struct TALER_MERCHANT_AbortedCoin res[])
     189             : {
     190           0 :   struct AbortState *as = cls;
     191             : 
     192           0 :   as->oah = NULL;
     193           0 :   if (as->http_status != hr->http_status)
     194             :   {
     195           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     196             :                 "Unexpected response code %u (%d) to command %s\n",
     197             :                 hr->http_status,
     198             :                 (int) hr->ec,
     199             :                 TALER_TESTING_interpreter_get_current_label (as->is));
     200           0 :     TALER_TESTING_FAIL (as->is);
     201             :   }
     202           0 :   if ( (MHD_HTTP_OK == hr->http_status) &&
     203           0 :        (TALER_EC_NONE == hr->ec) )
     204             :   {
     205           0 :     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     206             :                 "Received %u refunds\n",
     207             :                 num_aborts);
     208           0 :     as->acs_length = num_aborts;
     209           0 :     as->acs = GNUNET_new_array (num_aborts,
     210             :                                 struct TALER_MERCHANT_AbortedCoin);
     211           0 :     memcpy (as->acs,
     212             :             res,
     213             :             num_aborts * sizeof (struct TALER_MERCHANT_AbortedCoin));
     214             :   }
     215           0 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     216             :               "Successful pay-abort (HTTP status: %u)\n",
     217             :               hr->http_status);
     218           0 :   TALER_TESTING_interpreter_next (as->is);
     219             : }
     220             : 
     221             : 
     222             : /**
     223             :  * Run an "abort" CMD.
     224             :  *
     225             :  * @param cls closure
     226             :  * @param cmd command being run.
     227             :  * @param is interpreter state
     228             :  */
     229             : static void
     230           0 : abort_run (void *cls,
     231             :            const struct TALER_TESTING_Command *cmd,
     232             :            struct TALER_TESTING_Interpreter *is)
     233             : {
     234           0 :   struct AbortState *as = cls;
     235             :   const struct TALER_TESTING_Command *pay_cmd;
     236             :   const char *proposal_reference;
     237             :   const char *coin_reference;
     238             :   const char *amount_with_fee;
     239             :   const struct TALER_TESTING_Command *proposal_cmd;
     240             :   const char *order_id;
     241             :   const struct GNUNET_HashCode *h_proposal;
     242             :   struct TALER_MerchantPublicKeyP merchant_pub;
     243             :   struct TALER_Amount total_amount;
     244             :   const char *error_name;
     245             :   unsigned int error_line;
     246             :   struct TALER_MERCHANT_AbortCoin *abort_coins;
     247             :   unsigned int nabort_coins;
     248             :   char *cr;
     249             : 
     250           0 :   as->is = is;
     251           0 :   pay_cmd = TALER_TESTING_interpreter_lookup_command (is,
     252             :                                                       as->pay_reference);
     253           0 :   if (NULL == pay_cmd)
     254           0 :     TALER_TESTING_FAIL (is);
     255           0 :   if (GNUNET_OK !=
     256           0 :       TALER_TESTING_get_trait_proposal_reference (pay_cmd,
     257             :                                                   0,
     258             :                                                   &proposal_reference))
     259           0 :     TALER_TESTING_FAIL (is);
     260           0 :   if (GNUNET_OK !=
     261           0 :       TALER_TESTING_get_trait_coin_reference (pay_cmd,
     262             :                                               0,
     263             :                                               &coin_reference))
     264           0 :     TALER_TESTING_FAIL (is);
     265           0 :   if (GNUNET_OK !=
     266           0 :       TALER_TESTING_get_trait_string (pay_cmd,
     267             :                                       AMOUNT_WITH_FEE,
     268             :                                       &amount_with_fee))
     269           0 :     TALER_TESTING_FAIL (is);
     270           0 :   proposal_cmd = TALER_TESTING_interpreter_lookup_command (is,
     271             :                                                            proposal_reference);
     272             : 
     273           0 :   if (NULL == proposal_cmd)
     274           0 :     TALER_TESTING_FAIL (is);
     275             : 
     276             :   {
     277             :     const json_t *contract_terms;
     278             : 
     279           0 :     if (GNUNET_OK !=
     280           0 :         TALER_TESTING_get_trait_contract_terms (proposal_cmd,
     281             :                                                 0,
     282             :                                                 &contract_terms))
     283           0 :       TALER_TESTING_FAIL (is);
     284             :     {
     285             :       /* Get information that needs to be put verbatim in the
     286             :        * deposit permission */
     287             :       struct GNUNET_JSON_Specification spec[] = {
     288           0 :         GNUNET_JSON_spec_string ("order_id",
     289             :                                  &order_id),
     290           0 :         GNUNET_JSON_spec_fixed_auto ("merchant_pub",
     291             :                                      &merchant_pub),
     292           0 :         TALER_JSON_spec_amount ("amount",
     293             :                                 &total_amount),
     294           0 :         GNUNET_JSON_spec_end ()
     295             :       };
     296             : 
     297           0 :       if (GNUNET_OK !=
     298           0 :           GNUNET_JSON_parse (contract_terms,
     299             :                              spec,
     300             :                              &error_name,
     301             :                              &error_line))
     302             :       {
     303             :         char *js;
     304             : 
     305           0 :         js = json_dumps (contract_terms,
     306             :                          JSON_INDENT (1));
     307           0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     308             :                     "Parser failed on %s:%u for input `%s'\n",
     309             :                     error_name,
     310             :                     error_line,
     311             :                     js);
     312           0 :         free (js);
     313           0 :         TALER_TESTING_FAIL (is);
     314             :       }
     315             :     }
     316             :   }
     317             : 
     318           0 :   cr = GNUNET_strdup (coin_reference);
     319           0 :   abort_coins = NULL;
     320           0 :   nabort_coins = 0;
     321           0 :   if (GNUNET_OK !=
     322           0 :       build_coins (&abort_coins,
     323             :                    &nabort_coins,
     324             :                    cr,
     325             :                    is,
     326             :                    amount_with_fee))
     327             :   {
     328           0 :     GNUNET_array_grow (abort_coins,
     329             :                        nabort_coins,
     330             :                        0);
     331           0 :     GNUNET_free (cr);
     332           0 :     TALER_TESTING_FAIL (is);
     333             :   }
     334           0 :   GNUNET_free (cr);
     335             : 
     336           0 :   if (GNUNET_OK !=
     337           0 :       TALER_TESTING_get_trait_h_contract_terms (proposal_cmd,
     338             :                                                 0,
     339             :                                                 &h_proposal))
     340           0 :     TALER_TESTING_FAIL (is);
     341           0 :   as->oah = TALER_MERCHANT_order_abort (is->ctx,
     342             :                                         as->merchant_url,
     343             :                                         order_id,
     344             :                                         &merchant_pub,
     345             :                                         h_proposal,
     346             :                                         nabort_coins,
     347             :                                         abort_coins,
     348             :                                         &abort_cb,
     349             :                                         as);
     350           0 :   GNUNET_array_grow (abort_coins,
     351             :                      nabort_coins,
     352             :                      0);
     353           0 :   if (NULL == as->oah)
     354           0 :     TALER_TESTING_FAIL (is);
     355             : }
     356             : 
     357             : 
     358             : /**
     359             :  * Free a "pay abort" CMD, and cancel it if need be.
     360             :  *
     361             :  * @param cls closure.
     362             :  * @param cmd command currently being freed.
     363             :  */
     364             : static void
     365           0 : abort_cleanup (void *cls,
     366             :                const struct TALER_TESTING_Command *cmd)
     367             : {
     368           0 :   struct AbortState *as = cls;
     369             : 
     370           0 :   if (NULL != as->oah)
     371             :   {
     372           0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     373             :                 "Command `%s' did not complete.\n",
     374             :                 TALER_TESTING_interpreter_get_current_label (
     375             :                   as->is));
     376           0 :     TALER_MERCHANT_order_abort_cancel (as->oah);
     377             :   }
     378           0 :   GNUNET_array_grow (as->acs,
     379             :                      as->acs_length,
     380             :                      0);
     381           0 :   GNUNET_free (as);
     382           0 : }
     383             : 
     384             : 
     385             : /**
     386             :  * Offer internal data useful to other commands.
     387             :  *
     388             :  * @param cls closure
     389             :  * @param ret[out] result (could be anything)
     390             :  * @param trait name of the trait
     391             :  * @param index index number of the object to extract.
     392             :  * @return #GNUNET_OK on success
     393             :  */
     394             : static int
     395           0 : abort_traits (void *cls,
     396             :               const void **ret,
     397             :               const char *trait,
     398             :               unsigned int index)
     399             : {
     400           0 :   struct AbortState *as = cls;
     401             :   struct TALER_TESTING_Trait traits[] = {
     402           0 :     TALER_TESTING_trait_end ()
     403             :   };
     404             : 
     405             :   (void) as;
     406           0 :   return TALER_TESTING_get_trait (traits,
     407             :                                   ret,
     408             :                                   trait,
     409             :                                   index);
     410             : }
     411             : 
     412             : 
     413             : /**
     414             :  * Make an "abort" test command.
     415             :  *
     416             :  * @param label command label
     417             :  * @param merchant_url merchant base URL
     418             :  * @param pay_reference reference to the payment to abort
     419             :  * @param http_status expected HTTP response code
     420             :  * @return the command
     421             :  */
     422             : struct TALER_TESTING_Command
     423           0 : TALER_TESTING_cmd_merchant_order_abort (const char *label,
     424             :                                         const char *merchant_url,
     425             :                                         const char *pay_reference,
     426             :                                         unsigned int http_status)
     427             : {
     428             :   struct AbortState *as;
     429             : 
     430           0 :   as = GNUNET_new (struct AbortState);
     431           0 :   as->http_status = http_status;
     432           0 :   as->pay_reference = pay_reference;
     433           0 :   as->merchant_url = merchant_url;
     434             :   {
     435           0 :     struct TALER_TESTING_Command cmd = {
     436             :       .cls = as,
     437             :       .label = label,
     438             :       .run = &abort_run,
     439             :       .cleanup = &abort_cleanup,
     440             :       .traits = &abort_traits
     441             :     };
     442             : 
     443           0 :     return cmd;
     444             :   }
     445             : }
     446             : 
     447             : 
     448             : /* end of testing_api_cmd_abort_order.c */

Generated by: LCOV version 1.14