LCOV - code coverage report
Current view: top level - lib - testing_api_cmd_refund.c (source / functions) Hit Total Coverage
Test: rcoverage.info Lines: 99 124 79.8 %
Date: 2018-05-16 06:16:58 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2014-2018 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             : /**
      21             :  * @file lib/testing_api_cmd_refund.c
      22             :  * @brief command to test refunds.
      23             :  * @author Marcello Stanisci
      24             :  */
      25             : 
      26             : #include "platform.h"
      27             : #include <taler/taler_exchange_service.h>
      28             : #include <taler/taler_testing_lib.h>
      29             : #include "taler_merchant_service.h"
      30             : #include "taler_merchant_testing_lib.h"
      31             : 
      32             : 
      33             : struct RefundIncreaseState
      34             : {
      35             :   struct TALER_MERCHANT_RefundIncreaseOperation *rio;
      36             : 
      37             :   const char *merchant_url;
      38             : 
      39             :   struct GNUNET_CURL_Context *ctx;
      40             : 
      41             :   const char *order_id;
      42             : 
      43             :   const char *refund_amount;
      44             : 
      45             :   const char *refund_fee;
      46             : 
      47             :   const char *reason;
      48             : 
      49             :   struct TALER_TESTING_Interpreter *is;
      50             : };
      51             : 
      52             : struct RefundLookupState
      53             : {
      54             :   struct TALER_MERCHANT_RefundLookupOperation *rlo;
      55             : 
      56             :   const char *merchant_url;
      57             : 
      58             :   struct GNUNET_CURL_Context *ctx;
      59             : 
      60             :   const char *order_id;
      61             : 
      62             :   const char *pay_reference;
      63             : 
      64             :   const char *increase_reference;
      65             : 
      66             :   struct TALER_TESTING_Interpreter *is;
      67             : };
      68             : 
      69             : 
      70             : /**
      71             :  * Clean up after the command.  Run during forced termination
      72             :  * (CTRL-C) or test failure or test success.
      73             :  *
      74             :  * @param cls closure
      75             :  */
      76             : static void
      77           1 : refund_increase_cleanup (void *cls,
      78             :                          const struct TALER_TESTING_Command *cmd)
      79             : {
      80           1 :   struct RefundIncreaseState *ris = cls;
      81             : 
      82           1 :   if (NULL != ris->rio)
      83             :   {
      84           0 :     TALER_LOG_WARNING ("Refund-increase operation"
      85             :                        " did not complete\n");
      86           0 :     TALER_MERCHANT_refund_increase_cancel (ris->rio);
      87             :   }
      88           1 :   GNUNET_free (ris);
      89           1 : }
      90             : 
      91             : /**
      92             :  * Clean up after the command.  Run during forced termination
      93             :  * (CTRL-C) or test failure or test success.
      94             :  *
      95             :  * @param cls closure
      96             :  */
      97             : static void
      98           1 : refund_lookup_cleanup (void *cls,
      99             :                        const struct TALER_TESTING_Command *cmd)
     100             : {
     101             :   /* FIXME: make sure no other data must be free'd */
     102           1 :   struct RefundLookupState *rls = cls;
     103             : 
     104           1 :   if (NULL != rls->rlo)
     105             :   {
     106           0 :     TALER_LOG_WARNING ("Refund-lookup operation"
     107             :                        " did not complete\n");
     108           0 :     TALER_MERCHANT_refund_lookup_cancel (rls->rlo);
     109             :   }
     110           1 :   GNUNET_free (rls);
     111           1 : }
     112             : 
     113             : /**
     114             :  * Process POST /refund (increase) response
     115             :  *
     116             :  * @param cls closure
     117             :  * @param http_status HTTP status code
     118             :  * @param ec taler-specific error object
     119             :  * @param obj response body; is NULL on success.
     120             :  */
     121             : static void
     122           1 : refund_increase_cb (void *cls,
     123             :                     unsigned int http_status,
     124             :                     enum TALER_ErrorCode ec,
     125             :                     const json_t *obj)
     126             : {
     127           1 :   struct RefundIncreaseState *ris = cls;
     128             : 
     129           1 :   ris->rio = NULL;
     130           1 :   if (MHD_HTTP_OK != http_status)
     131           0 :     TALER_TESTING_FAIL (ris->is);
     132             : 
     133           1 :   TALER_TESTING_interpreter_next (ris->is);
     134             : }
     135             : 
     136             : static void
     137           1 : refund_increase_run (void *cls,
     138             :                      const struct TALER_TESTING_Command *cmd,
     139             :                      struct TALER_TESTING_Interpreter *is)
     140             : {
     141           1 :   struct RefundIncreaseState *ris = cls;
     142             :   struct TALER_Amount refund_amount;
     143             : 
     144           1 :   ris->is = is;
     145           1 :   if (GNUNET_OK != TALER_string_to_amount (ris->refund_amount,
     146             :                                            &refund_amount))
     147           0 :     TALER_TESTING_FAIL (is);
     148           1 :   ris->rio = TALER_MERCHANT_refund_increase (ris->ctx,
     149             :                                              ris->merchant_url,
     150             :                                              ris->order_id,
     151             :                                              &refund_amount,
     152             :                                              ris->reason,
     153             :                                              "default",
     154             :                                              &refund_increase_cb,
     155             :                                              ris);
     156           1 :   GNUNET_assert (NULL != ris->rio);
     157             : }
     158             : 
     159             : /**
     160             :  * Callback that frees all the elements in the hashmap
     161             :  *
     162             :  * @param cls closure, NULL
     163             :  * @param key current key
     164             :  * @param value a `struct TALER_Amount`
     165             :  * @return always #GNUNET_YES (continue to iterate)
     166             :  */
     167             : static int
     168           1 : hashmap_free (void *cls,
     169             :               const struct GNUNET_HashCode *key,
     170             :               void *value)
     171             : {
     172           1 :   struct TALER_Amount *refund_amount = value;
     173             : 
     174           1 :   GNUNET_free (refund_amount);
     175           1 :   return GNUNET_YES;
     176             : }
     177             : 
     178             : 
     179             : /**
     180             :  * Process GET /refund (increase) response.
     181             :  *
     182             :  * @param cls closure
     183             :  * @param http_status HTTP status code
     184             :  * @param ec taler-specific error object
     185             :  * @param obj response body; is NULL on error.
     186             :  */
     187             : static void
     188           1 : refund_lookup_cb (void *cls,
     189             :                   unsigned int http_status,
     190             :                   enum TALER_ErrorCode ec,
     191             :                   const json_t *obj)
     192             : {
     193           1 :   struct RefundLookupState *rls = cls;
     194             :   struct GNUNET_CONTAINER_MultiHashMap *map;
     195             :   size_t index;
     196             :   json_t *elem;
     197             :   const char *error_name;
     198             :   unsigned int error_line;
     199             :   struct GNUNET_HashCode h_coin_pub;
     200             :   const char *coin_reference;
     201             :   char *coin_reference_dup;
     202             :   const char *icoin_reference;
     203             :   const struct TALER_TESTING_Command *pay_cmd;
     204             :   const struct TALER_TESTING_Command *icoin_cmd;
     205             :   const struct TALER_TESTING_Command *increase_cmd;
     206             :   const char *refund_amount;
     207             :   struct TALER_Amount acc;
     208             :   struct TALER_Amount ra;
     209             :   const json_t *arr;
     210             : 
     211           1 :   rls->rlo = NULL;
     212           1 :   if (MHD_HTTP_OK != http_status)
     213           0 :     TALER_TESTING_FAIL (rls->is);
     214             : 
     215           1 :   map = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
     216           1 :   arr = json_object_get (obj, "refund_permissions");
     217           1 :   if (NULL == arr)
     218           0 :     TALER_TESTING_FAIL (rls->is);
     219             : 
     220           2 :   json_array_foreach (arr, index, elem)
     221             :   {
     222             :     struct TALER_CoinSpendPublicKeyP coin_pub;
     223           1 :     struct TALER_Amount *irefund_amount = GNUNET_new
     224             :       (struct TALER_Amount);
     225           1 :     struct GNUNET_JSON_Specification spec[] = {
     226             :       GNUNET_JSON_spec_fixed_auto ("coin_pub", &coin_pub),
     227             :       TALER_JSON_spec_amount ("refund_amount", irefund_amount),
     228             :       GNUNET_JSON_spec_end ()
     229             :     };
     230             : 
     231           1 :     GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (elem,
     232             :                                                    spec,
     233             :                                                    &error_name,
     234             :                                                    &error_line));
     235           1 :     GNUNET_CRYPTO_hash (&coin_pub,
     236             :                         sizeof (struct TALER_CoinSpendPublicKeyP),
     237             :                         &h_coin_pub);
     238           1 :     GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put
     239             :       (map,
     240             :        &h_coin_pub, // which
     241             :        irefund_amount, // how much
     242             :        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
     243             :   };
     244             : 
     245           1 :   if ( NULL ==
     246           1 :      ( pay_cmd = TALER_TESTING_interpreter_lookup_command
     247             :        (rls->is, rls->pay_reference)))
     248           0 :     TALER_TESTING_FAIL (rls->is);
     249             : 
     250           1 :   if (GNUNET_OK != TALER_TESTING_get_trait_coin_reference
     251             :       (pay_cmd, 0, &coin_reference))
     252           0 :     TALER_TESTING_FAIL (rls->is);
     253             : 
     254           1 :   GNUNET_assert (GNUNET_OK == TALER_amount_get_zero ("EUR",
     255             :                                                      &acc));
     256           1 :   coin_reference_dup = GNUNET_strdup (coin_reference);
     257           3 :   for (icoin_reference = strtok (coin_reference_dup, ";");
     258             :        NULL != icoin_reference;
     259           1 :        icoin_reference = strtok (NULL, ";"))
     260             :   {
     261             :     struct TALER_CoinSpendPrivateKeyP *icoin_priv;
     262             :     struct TALER_CoinSpendPublicKeyP icoin_pub;
     263             :     struct GNUNET_HashCode h_icoin_pub;
     264             :     struct TALER_Amount *iamount;
     265             : 
     266           1 :     if ( NULL ==
     267           1 :        ( icoin_cmd = TALER_TESTING_interpreter_lookup_command
     268             :          (rls->is, icoin_reference)) )
     269             :     {
     270           0 :       GNUNET_break (0);
     271           0 :       TALER_LOG_ERROR ("Bad reference `%s'\n",
     272             :                        icoin_reference); 
     273           0 :       TALER_TESTING_interpreter_fail (rls->is);
     274           0 :       return;
     275             :     }
     276             : 
     277           1 :    if (GNUNET_OK != TALER_TESTING_get_trait_coin_priv
     278             :       (icoin_cmd, 0, &icoin_priv))
     279             :    {
     280           0 :      GNUNET_break (0);
     281           0 :      TALER_LOG_ERROR ("Command `%s' failed to give coin"
     282             :                       " priv trait\n",
     283             :                       icoin_reference); 
     284           0 :      TALER_TESTING_interpreter_fail (rls->is);
     285           0 :      return;
     286             :     }
     287             :      
     288           1 :     GNUNET_CRYPTO_eddsa_key_get_public (&icoin_priv->eddsa_priv,
     289             :                                         &icoin_pub.eddsa_pub);
     290           1 :     GNUNET_CRYPTO_hash (&icoin_pub,
     291             :                         sizeof (struct TALER_CoinSpendPublicKeyP),
     292             :                         &h_icoin_pub);
     293             : 
     294           1 :     iamount = GNUNET_CONTAINER_multihashmap_get
     295             :       (map, &h_icoin_pub);
     296             : 
     297             :     /* Can be NULL: not all coins are involved in refund */
     298           1 :     if (NULL == iamount)
     299           0 :       continue;
     300             : 
     301           1 :     GNUNET_assert (GNUNET_OK == TALER_amount_add (&acc,
     302             :                                                   &acc,
     303             :                                                   iamount));
     304             :   }
     305             : 
     306           1 :   GNUNET_free (coin_reference_dup);
     307             :   
     308           1 :   if (NULL ==
     309           1 :     (increase_cmd = TALER_TESTING_interpreter_lookup_command
     310             :       (rls->is, rls->increase_reference)))
     311           0 :     TALER_TESTING_FAIL (rls->is);
     312             : 
     313           1 :   if (GNUNET_OK != TALER_TESTING_get_trait_amount
     314             :       (increase_cmd, 0, &refund_amount))
     315           0 :     TALER_TESTING_FAIL (rls->is);
     316             : 
     317           1 :   if (GNUNET_OK != TALER_string_to_amount (refund_amount,
     318             :                                            &ra))
     319           0 :     TALER_TESTING_FAIL (rls->is);
     320             : 
     321           1 :   GNUNET_CONTAINER_multihashmap_iterate (map,
     322             :                                          &hashmap_free,
     323             :                                          NULL);
     324           1 :   GNUNET_CONTAINER_multihashmap_destroy (map);
     325             : 
     326           1 :   if (0 != TALER_amount_cmp (&acc,
     327             :                              &ra))
     328             :   {
     329           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     330             :                 "Incomplete refund: expected '%s', got '%s'\n",
     331             :                 refund_amount,
     332             :                 TALER_amount_to_string (&acc));
     333           0 :     TALER_TESTING_interpreter_fail (rls->is);
     334           0 :     return;
     335             :   }
     336             : 
     337           1 :   TALER_TESTING_interpreter_next (rls->is);
     338             : }
     339             : 
     340             : 
     341             : static void
     342           1 : refund_lookup_run (void *cls,
     343             :                    const struct TALER_TESTING_Command *cmd,
     344             :                    struct TALER_TESTING_Interpreter *is)
     345             : {
     346           1 :   struct RefundLookupState *rls = cls;
     347             :   
     348           1 :   rls->is = is;
     349           1 :   rls->rlo = TALER_MERCHANT_refund_lookup (rls->ctx,
     350             :                                            rls->merchant_url,
     351             :                                            rls->order_id,
     352             :                                            "default",
     353             :                                            &refund_lookup_cb,
     354             :                                            rls);
     355           1 :   GNUNET_assert (NULL != rls->rlo);
     356           1 : }
     357             : 
     358             : 
     359             : /**
     360             :  * Extract information from a command that is useful for other
     361             :  * commands.
     362             :  *
     363             :  * @param cls closure
     364             :  * @param ret[out] result (could be anything)
     365             :  * @param trait name of the trait
     366             :  * @param selector more detailed information about which object
     367             :  *                 to return in case there were multiple generated
     368             :  *                 by the command
     369             :  * @return #GNUNET_OK on success
     370             :  */
     371             : static int
     372           1 : refund_increase_traits (void *cls,
     373             :                         void **ret,
     374             :                         const char *trait,
     375             :                         unsigned int index)
     376             : {
     377           1 :   struct RefundIncreaseState *ris = cls;
     378             :   
     379           1 :   struct TALER_TESTING_Trait traits[] = {
     380           1 :     TALER_TESTING_make_trait_amount (0, ris->refund_amount),
     381             :     TALER_TESTING_trait_end ()
     382             :   };
     383             : 
     384           1 :   return TALER_TESTING_get_trait (traits,
     385             :                                   ret,
     386             :                                   trait,
     387             :                                   index);
     388             : 
     389             :   return GNUNET_SYSERR;
     390             : }
     391             : 
     392             : /**
     393             :  * FIXME
     394             :  */
     395             : struct TALER_TESTING_Command
     396           1 : TALER_TESTING_cmd_refund_increase
     397             :   (const char *label,
     398             :    const char *merchant_url,
     399             :    struct GNUNET_CURL_Context *ctx,
     400             :    const char *reason,
     401             :    const char *order_id,
     402             :    const char *refund_amount,
     403             :    const char *refund_fee)
     404             : {
     405             :   struct RefundIncreaseState *ris;
     406             :   struct TALER_TESTING_Command cmd;
     407             : 
     408           1 :   ris = GNUNET_new (struct RefundIncreaseState);
     409           1 :   ris->merchant_url = merchant_url;
     410           1 :   ris->ctx = ctx;
     411           1 :   ris->order_id = order_id;
     412           1 :   ris->refund_amount = refund_amount;
     413           1 :   ris->refund_fee = refund_fee;
     414           1 :   ris->reason = reason;
     415             : 
     416           1 :   cmd.cls = ris;
     417           1 :   cmd.label = label;
     418           1 :   cmd.run = &refund_increase_run;
     419           1 :   cmd.cleanup = &refund_increase_cleanup;
     420           1 :   cmd.traits = &refund_increase_traits;
     421             : 
     422           1 :   return cmd;
     423             : }
     424             : 
     425             : /**
     426             :  * FIXME
     427             :  */
     428             : struct TALER_TESTING_Command
     429           1 : TALER_TESTING_cmd_refund_lookup
     430             :   (const char *label,
     431             :    const char *merchant_url,
     432             :    struct GNUNET_CURL_Context *ctx,
     433             :    const char *increase_reference,
     434             :    const char *pay_reference,
     435             :    const char *order_id)
     436             : {
     437             :   struct RefundLookupState *rls;
     438             :   struct TALER_TESTING_Command cmd;
     439             : 
     440           1 :   rls = GNUNET_new (struct RefundLookupState);
     441           1 :   rls->merchant_url = merchant_url;
     442           1 :   rls->ctx = ctx;
     443           1 :   rls->order_id = order_id;
     444           1 :   rls->pay_reference = pay_reference;
     445           1 :   rls->increase_reference = increase_reference;
     446             : 
     447           1 :   cmd.cls = rls;
     448           1 :   cmd.label = label;
     449           1 :   cmd.run = &refund_lookup_run;
     450           1 :   cmd.cleanup = &refund_lookup_cleanup;
     451             : 
     452           1 :   return cmd;
     453             : }
     454             : 
     455             : 
     456             : 
     457             : /* end of testing_api_cmd_refund.c */

Generated by: LCOV version 1.13