LCOV - code coverage report
Current view: top level - testing - testing_api_cmd_tip_authorize.c (source / functions) Hit Total Coverage
Test: GNU Taler merchant coverage report Lines: 81 107 75.7 %
Date: 2021-08-30 06:54:17 Functions: 10 11 90.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2014-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             : /**
      21             :  * @file testing_api_cmd_tip_authorize.c
      22             :  * @brief command to test the tipping.
      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             : /**
      34             :  * State for a /tip-authorize CMD.
      35             :  */
      36             : struct TipAuthorizeState
      37             : {
      38             : 
      39             :   /**
      40             :    * Merchant base URL.
      41             :    */
      42             :   const char *merchant_url;
      43             : 
      44             :   /**
      45             :    * Expected HTTP response code.
      46             :    */
      47             :   unsigned int http_status;
      48             : 
      49             :   /**
      50             :    * Reference to the reserv to authorize the tip
      51             :    * from (if NULL, the merchant decides).
      52             :    */
      53             :   const char *reserve_reference;
      54             : 
      55             :   /**
      56             :    * Human-readable justification for the
      57             :    * tip authorization carried on by this CMD.
      58             :    */
      59             :   const char *justification;
      60             : 
      61             :   /**
      62             :    * Amount that should be authorized for tipping.
      63             :    */
      64             :   struct TALER_Amount amount;
      65             : 
      66             :   /**
      67             :    * Expected Taler error code for this CMD.
      68             :    */
      69             :   enum TALER_ErrorCode expected_ec;
      70             : 
      71             :   /**
      72             :    * Tip taler:// URI.
      73             :    */
      74             :   char *tip_uri;
      75             : 
      76             :   /**
      77             :    * The tip id; set when the CMD succeeds.
      78             :    */
      79             :   struct GNUNET_HashCode tip_id;
      80             : 
      81             :   /**
      82             :    * Expiration date for this tip.
      83             :    */
      84             :   struct GNUNET_TIME_Absolute tip_expiration;
      85             : 
      86             :   /**
      87             :    * Handle to the on-going /tip-authorize request.
      88             :    */
      89             :   struct TALER_MERCHANT_TipAuthorizeHandle *tao;
      90             : 
      91             :   /**
      92             :    * The interpreter state.
      93             :    */
      94             :   struct TALER_TESTING_Interpreter *is;
      95             : 
      96             :   /**
      97             :    * Task used for retries.
      98             :    */
      99             :   struct GNUNET_SCHEDULER_Task *retry_task;
     100             : 
     101             :   /**
     102             :    * How long do we wait between retries?
     103             :    */
     104             :   struct GNUNET_TIME_Relative backoff;
     105             : 
     106             :   /**
     107             :    * How many retries are left?
     108             :    */
     109             :   unsigned int retries_left;
     110             : 
     111             : };
     112             : 
     113             : 
     114             : /**
     115             :  * Run the main logic of talking to the merchant.
     116             :  *
     117             :  * @param cls a `struct TipAuthorizeState`.
     118             :  */
     119             : static void
     120             : do_retry (void *cls);
     121             : 
     122             : 
     123             : /**
     124             :  * Callback for a /tip-authorize request.  Set into the state
     125             :  * what was returned from the backend (@a tip_id and @a
     126             :  * tip_expiration).
     127             :  *
     128             :  * @param cls closure
     129             :  * @param hr HTTP response we got
     130             :  * @param tip_id unique identifier for the tip
     131             :  * @param taler_tip_uri URI to let the wallet know about the tip
     132             :  * @param expiration when the tip expires
     133             :  */
     134             : static void
     135           4 : tip_authorize_cb (void *cls,
     136             :                   const struct TALER_MERCHANT_HttpResponse *hr,
     137             :                   struct GNUNET_HashCode *tip_id,
     138             :                   const char *taler_tip_uri,
     139             :                   struct GNUNET_TIME_Absolute expiration)
     140             : {
     141           4 :   struct TipAuthorizeState *tas = cls;
     142             : 
     143           4 :   tas->tao = NULL;
     144           4 :   if (tas->http_status != hr->http_status)
     145             :   {
     146           0 :     if ( (MHD_HTTP_NOT_FOUND == hr->http_status) &&
     147           0 :          (0 < tas->retries_left) )
     148             :     {
     149           0 :       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     150             :                   "Reserve authorization failed. Reserve may not yet be ready, retrying %u more times.\n",
     151             :                   tas->retries_left);
     152           0 :       tas->retries_left--;
     153           0 :       tas->backoff = GNUNET_TIME_randomized_backoff (tas->backoff,
     154             :                                                      GNUNET_TIME_UNIT_SECONDS);
     155           0 :       tas->retry_task = GNUNET_SCHEDULER_add_delayed (tas->backoff,
     156             :                                                       &do_retry,
     157             :                                                       tas);
     158           0 :       return;
     159             :     }
     160             : 
     161           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     162             :                 "Unexpected response code %u (%d) to command %s\n",
     163             :                 hr->http_status,
     164             :                 hr->ec,
     165             :                 TALER_TESTING_interpreter_get_current_label (tas->is));
     166           0 :     TALER_TESTING_interpreter_fail (tas->is);
     167           0 :     return;
     168             :   }
     169             : 
     170           4 :   if (tas->expected_ec != hr->ec)
     171             :   {
     172           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     173             :                 "Unexpected error code %d (%u) to command %s\n",
     174             :                 (int) hr->ec,
     175             :                 hr->http_status,
     176             :                 TALER_TESTING_interpreter_get_current_label (tas->is));
     177           0 :     TALER_TESTING_interpreter_fail (tas->is);
     178           0 :     return;
     179             :   }
     180           4 :   if ( (MHD_HTTP_OK == hr->http_status) &&
     181           2 :        (TALER_EC_NONE == hr->ec) )
     182             :   {
     183           2 :     tas->tip_uri = strdup (taler_tip_uri);
     184           2 :     tas->tip_id = *tip_id;
     185           2 :     tas->tip_expiration = expiration;
     186             :   }
     187           4 :   TALER_TESTING_interpreter_next (tas->is);
     188             : }
     189             : 
     190             : 
     191             : /**
     192             :  * Offers information from the /tip-authorize CMD state to other
     193             :  * commands.
     194             :  *
     195             :  * @param cls closure
     196             :  * @param[out] ret result (could be anything)
     197             :  * @param trait name of the trait
     198             :  * @param index index number of the object to extract.
     199             :  * @return #GNUNET_OK on success
     200             :  */
     201             : static int
     202          33 : tip_authorize_traits (void *cls,
     203             :                       const void **ret,
     204             :                       const char *trait,
     205             :                       unsigned int index)
     206             : {
     207          33 :   struct TipAuthorizeState *tas = cls;
     208             : 
     209             :   {
     210             :     struct TALER_TESTING_Trait traits[] = {
     211          33 :       TALER_TESTING_make_trait_tip_id (0, &tas->tip_id),
     212          33 :       TALER_TESTING_make_trait_amount_obj (0, &tas->amount),
     213          33 :       TALER_TESTING_make_trait_string (0, tas->justification),
     214          33 :       TALER_TESTING_make_trait_absolute_time (0, &tas->tip_expiration),
     215          33 :       TALER_TESTING_trait_end (),
     216             :     };
     217             : 
     218          33 :     return TALER_TESTING_get_trait (traits,
     219             :                                     ret,
     220             :                                     trait,
     221             :                                     index);
     222             :   }
     223             : }
     224             : 
     225             : 
     226             : /**
     227             :  * Runs the /tip-authorize CMD
     228             :  *
     229             :  * @param cls closure
     230             :  * @param cmd the CMD representing _this_ command
     231             :  * @param is interpreter state
     232             :  */
     233             : static void
     234           4 : tip_authorize_run (void *cls,
     235             :                    const struct TALER_TESTING_Command *cmd,
     236             :                    struct TALER_TESTING_Interpreter *is)
     237             : {
     238           4 :   struct TipAuthorizeState *tas = cls;
     239             : 
     240           4 :   tas->retries_left = 16;
     241           4 :   tas->is = is;
     242           4 :   tas->retry_task = GNUNET_SCHEDULER_add_now (&do_retry,
     243             :                                               tas);
     244           4 : }
     245             : 
     246             : 
     247             : static void
     248           4 : do_retry (void *cls)
     249             : {
     250           4 :   struct TipAuthorizeState *tas = cls;
     251             : 
     252           4 :   tas->retry_task = NULL;
     253           4 :   if (NULL == tas->reserve_reference)
     254             :   {
     255           1 :     tas->tao = TALER_MERCHANT_tip_authorize (tas->is->ctx,
     256             :                                              tas->merchant_url,
     257             :                                              "http://merchant.com/pickup",
     258           1 :                                              &tas->amount,
     259             :                                              tas->justification,
     260             :                                              &tip_authorize_cb,
     261             :                                              tas);
     262             :   }
     263             :   else
     264             :   {
     265             :     const struct TALER_TESTING_Command *reserve_cmd;
     266             :     const struct TALER_ReservePublicKeyP *reserve_pub;
     267             : 
     268           3 :     reserve_cmd = TALER_TESTING_interpreter_lookup_command (
     269             :       tas->is,
     270             :       tas->reserve_reference);
     271           3 :     GNUNET_assert (GNUNET_OK ==
     272             :                    TALER_TESTING_get_trait_reserve_pub (reserve_cmd,
     273             :                                                         0,
     274             :                                                         &reserve_pub));
     275           3 :     tas->tao = TALER_MERCHANT_tip_authorize2 (tas->is->ctx,
     276             :                                               tas->merchant_url,
     277             :                                               reserve_pub,
     278             :                                               "http://merchant.com/pickup",
     279           3 :                                               &tas->amount,
     280             :                                               tas->justification,
     281             :                                               &tip_authorize_cb,
     282             :                                               tas);
     283             :   }
     284           4 :   GNUNET_assert (NULL != tas->tao);
     285           4 : }
     286             : 
     287             : 
     288             : /**
     289             :  * Run the /tip-authorize CMD, the "fake" version of it.
     290             :  *
     291             :  * @param cls closure
     292             :  * @param cmd the CMD representing _this_ command
     293             :  * @param is interpreter state *
     294             :  */
     295             : static void
     296           1 : tip_authorize_fake_run (void *cls,
     297             :                         const struct TALER_TESTING_Command *cmd,
     298             :                         struct TALER_TESTING_Interpreter *is)
     299             : {
     300           1 :   struct TipAuthorizeState *tas = cls;
     301             : 
     302             :   /* Make up a tip id.  */
     303           1 :   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
     304           1 :                               &tas->tip_id,
     305             :                               sizeof (struct GNUNET_HashCode));
     306             : 
     307           1 :   TALER_TESTING_interpreter_next (is);
     308           1 : }
     309             : 
     310             : 
     311             : /**
     312             :  * Free the state from a /tip-authorize CMD, and possibly
     313             :  * cancel any pending operation.
     314             :  *
     315             :  * @param cls closure
     316             :  * @param cmd the /tip-authorize CMD that is about to be freed.
     317             :  */
     318             : static void
     319           5 : tip_authorize_cleanup (void *cls,
     320             :                        const struct TALER_TESTING_Command *cmd)
     321             : {
     322           5 :   struct TipAuthorizeState *tas = cls;
     323             : 
     324           5 :   if (NULL != tas->tao)
     325             :   {
     326           0 :     TALER_LOG_WARNING ("Tip-autorize operation"
     327             :                        " did not complete\n");
     328           0 :     TALER_MERCHANT_tip_authorize_cancel (tas->tao);
     329             :   }
     330           5 :   if (NULL != tas->retry_task)
     331             :   {
     332           0 :     GNUNET_SCHEDULER_cancel (tas->retry_task);
     333           0 :     tas->retry_task = NULL;
     334             :   }
     335           5 :   GNUNET_free (tas->tip_uri);
     336           5 :   GNUNET_free (tas);
     337           5 : }
     338             : 
     339             : 
     340             : struct TALER_TESTING_Command
     341           0 : TALER_TESTING_cmd_tip_authorize_with_ec (const char *label,
     342             :                                          const char *merchant_url,
     343             :                                          const char *exchange_url,
     344             :                                          unsigned int http_status,
     345             :                                          const char *justification,
     346             :                                          const char *amount,
     347             :                                          enum TALER_ErrorCode ec)
     348             : {
     349             :   struct TipAuthorizeState *tas;
     350             : 
     351           0 :   tas = GNUNET_new (struct TipAuthorizeState);
     352           0 :   tas->merchant_url = merchant_url;
     353           0 :   tas->justification = justification;
     354           0 :   tas->http_status = http_status;
     355           0 :   tas->expected_ec = ec;
     356           0 :   GNUNET_assert (GNUNET_OK ==
     357             :                  TALER_string_to_amount (amount,
     358             :                                          &tas->amount));
     359             :   {
     360           0 :     struct TALER_TESTING_Command cmd = {
     361             :       .label = label,
     362             :       .cls = tas,
     363             :       .run = &tip_authorize_run,
     364             :       .cleanup = &tip_authorize_cleanup,
     365             :       .traits = &tip_authorize_traits
     366             :     };
     367             : 
     368           0 :     return cmd;
     369             :   }
     370             : }
     371             : 
     372             : 
     373             : struct TALER_TESTING_Command
     374           2 : TALER_TESTING_cmd_tip_authorize_from_reserve_with_ec (
     375             :   const char *label,
     376             :   const char *merchant_url,
     377             :   const char *exchange_url,
     378             :   const char *reserve_reference,
     379             :   unsigned int http_status,
     380             :   const char *justification,
     381             :   const char *amount,
     382             :   enum TALER_ErrorCode ec)
     383             : {
     384             :   struct TipAuthorizeState *tas;
     385             : 
     386           2 :   tas = GNUNET_new (struct TipAuthorizeState);
     387           2 :   tas->merchant_url = merchant_url;
     388           2 :   tas->justification = justification;
     389           2 :   tas->http_status = http_status;
     390           2 :   tas->expected_ec = ec;
     391           2 :   tas->reserve_reference = reserve_reference;
     392           2 :   GNUNET_assert (GNUNET_OK ==
     393             :                  TALER_string_to_amount (amount,
     394             :                                          &tas->amount));
     395             :   {
     396           2 :     struct TALER_TESTING_Command cmd = {
     397             :       .label = label,
     398             :       .cls = tas,
     399             :       .run = &tip_authorize_run,
     400             :       .cleanup = &tip_authorize_cleanup,
     401             :       .traits = &tip_authorize_traits
     402             :     };
     403             : 
     404           2 :     return cmd;
     405             :   }
     406             : }
     407             : 
     408             : 
     409             : struct TALER_TESTING_Command
     410           1 : TALER_TESTING_cmd_tip_authorize (const char *label,
     411             :                                  const char *merchant_url,
     412             :                                  const char *exchange_url,
     413             :                                  unsigned int http_status,
     414             :                                  const char *justification,
     415             :                                  const char *amount)
     416             : {
     417             :   struct TipAuthorizeState *tas;
     418             : 
     419           1 :   tas = GNUNET_new (struct TipAuthorizeState);
     420           1 :   tas->merchant_url = merchant_url;
     421           1 :   tas->justification = justification;
     422           1 :   tas->http_status = http_status;
     423           1 :   GNUNET_assert (GNUNET_OK ==
     424             :                  TALER_string_to_amount (amount,
     425             :                                          &tas->amount));
     426             :   {
     427           1 :     struct TALER_TESTING_Command cmd = {
     428             :       .label = label,
     429             :       .cls = tas,
     430             :       .run = &tip_authorize_run,
     431             :       .cleanup = &tip_authorize_cleanup,
     432             :       .traits = &tip_authorize_traits
     433             :     };
     434             : 
     435           1 :     return cmd;
     436             :   }
     437             : }
     438             : 
     439             : 
     440             : struct TALER_TESTING_Command
     441           1 : TALER_TESTING_cmd_tip_authorize_from_reserve (const char *label,
     442             :                                               const char *merchant_url,
     443             :                                               const char *exchange_url,
     444             :                                               const char *reserve_reference,
     445             :                                               unsigned int http_status,
     446             :                                               const char *justification,
     447             :                                               const char *amount)
     448             : {
     449             :   struct TipAuthorizeState *tas;
     450             : 
     451           1 :   tas = GNUNET_new (struct TipAuthorizeState);
     452           1 :   tas->merchant_url = merchant_url;
     453           1 :   tas->reserve_reference = reserve_reference;
     454           1 :   tas->justification = justification;
     455           1 :   tas->http_status = http_status;
     456           1 :   GNUNET_assert (GNUNET_OK ==
     457             :                  TALER_string_to_amount (amount,
     458             :                                          &tas->amount));
     459             :   {
     460           1 :     struct TALER_TESTING_Command cmd = {
     461             :       .label = label,
     462             :       .cls = tas,
     463             :       .run = &tip_authorize_run,
     464             :       .cleanup = &tip_authorize_cleanup,
     465             :       .traits = &tip_authorize_traits
     466             :     };
     467             : 
     468           1 :     return cmd;
     469             :   }
     470             : }
     471             : 
     472             : 
     473             : struct TALER_TESTING_Command
     474           1 : TALER_TESTING_cmd_tip_authorize_fake (const char *label)
     475             : {
     476             :   struct TipAuthorizeState *tas;
     477             : 
     478           1 :   tas = GNUNET_new (struct TipAuthorizeState);
     479             :   {
     480           1 :     struct TALER_TESTING_Command cmd = {
     481             :       .label = label,
     482             :       .cls = tas,
     483             :       .run = &tip_authorize_fake_run,
     484             :       .cleanup = &tip_authorize_cleanup,
     485             :       .traits = &tip_authorize_traits
     486             :     };
     487             : 
     488           1 :     return cmd;
     489             :   }
     490             : }
     491             : 
     492             : 
     493             : /* end of testing_api_cmd_tip_authorize.c */

Generated by: LCOV version 1.14