LCOV - code coverage report
Current view: top level - testing - testing_api_cmd_reserve_get.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 68 99 68.7 %
Date: 2025-06-05 21:03:14 Functions: 8 9 88.9 %

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2014-2022 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 testing/testing_api_cmd_reserve_get.c
      21             :  * @brief Implement the GET /reserve/$RID test command.
      22             :  * @author Marcello Stanisci
      23             :  */
      24             : #include "platform.h"
      25             : #include "taler_json_lib.h"
      26             : #include <gnunet/gnunet_curl_lib.h>
      27             : #include "taler_testing_lib.h"
      28             : 
      29             : 
      30             : /**
      31             :  * State for a "poll" CMD.
      32             :  */
      33             : struct PollState
      34             : {
      35             : 
      36             :   /**
      37             :    * How long do we give the exchange to respond?
      38             :    */
      39             :   struct GNUNET_TIME_Relative timeout;
      40             : 
      41             :   /**
      42             :    * Label to the command which created the reserve to check,
      43             :    * needed to resort the reserve key.
      44             :    */
      45             :   const char *poll_reference;
      46             : 
      47             :   /**
      48             :    * Timeout to wait for at most.
      49             :    */
      50             :   struct GNUNET_SCHEDULER_Task *tt;
      51             : 
      52             :   /**
      53             :    * The interpreter we are using.
      54             :    */
      55             :   struct TALER_TESTING_Interpreter *is;
      56             : };
      57             : 
      58             : 
      59             : /**
      60             :  * State for a "status" CMD.
      61             :  */
      62             : struct StatusState
      63             : {
      64             : 
      65             :   /**
      66             :    * How long do we give the exchange to respond?
      67             :    */
      68             :   struct GNUNET_TIME_Relative timeout;
      69             : 
      70             :   /**
      71             :    * Poller waiting for us.
      72             :    */
      73             :   struct PollState *ps;
      74             : 
      75             :   /**
      76             :    * Label to the command which created the reserve to check,
      77             :    * needed to resort the reserve key.
      78             :    */
      79             :   const char *reserve_reference;
      80             : 
      81             :   /**
      82             :    * Handle to the "reserve status" operation.
      83             :    */
      84             :   struct TALER_EXCHANGE_ReservesGetHandle *rsh;
      85             : 
      86             :   /**
      87             :    * Expected reserve balance.
      88             :    */
      89             :   const char *expected_balance;
      90             : 
      91             :   /**
      92             :    * Public key of the reserve being analyzed.
      93             :    */
      94             :   const struct TALER_ReservePublicKeyP *reserve_pubp;
      95             : 
      96             :   /**
      97             :    * Expected HTTP response code.
      98             :    */
      99             :   unsigned int expected_response_code;
     100             : 
     101             :   /**
     102             :    * Interpreter state.
     103             :    */
     104             :   struct TALER_TESTING_Interpreter *is;
     105             : 
     106             : };
     107             : 
     108             : 
     109             : /**
     110             :  * Check that the reserve balance and HTTP response code are
     111             :  * both acceptable.
     112             :  *
     113             :  * @param cls closure.
     114             :  * @param rs HTTP response details
     115             :  */
     116             : static void
     117          30 : reserve_status_cb (void *cls,
     118             :                    const struct TALER_EXCHANGE_ReserveSummary *rs)
     119             : {
     120          30 :   struct StatusState *ss = cls;
     121          30 :   struct TALER_TESTING_Interpreter *is = ss->is;
     122             :   struct TALER_Amount eb;
     123             : 
     124          30 :   ss->rsh = NULL;
     125          30 :   if (ss->expected_response_code != rs->hr.http_status)
     126             :   {
     127           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     128             :                 "Unexpected HTTP response code: %d in %s:%u\n",
     129             :                 rs->hr.http_status,
     130             :                 __FILE__,
     131             :                 __LINE__);
     132           0 :     json_dumpf (rs->hr.reply,
     133             :                 stderr,
     134             :                 0);
     135           0 :     TALER_TESTING_interpreter_fail (ss->is);
     136           0 :     return;
     137             :   }
     138          30 :   if (MHD_HTTP_OK == ss->expected_response_code)
     139             :   {
     140          30 :     GNUNET_assert (GNUNET_OK ==
     141             :                    TALER_string_to_amount (ss->expected_balance,
     142             :                                            &eb));
     143          30 :     if (0 != TALER_amount_cmp (&eb,
     144             :                                &rs->details.ok.balance))
     145             :     {
     146           0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     147             :                   "Unexpected amount %s in reserve, wanted %s\n",
     148             :                   TALER_amount_to_string (&rs->details.ok.balance),
     149             :                   ss->expected_balance);
     150           0 :       TALER_TESTING_interpreter_fail (ss->is);
     151           0 :       return;
     152             :     }
     153             :   }
     154          30 :   if (NULL != ss->ps)
     155             :   {
     156             :     /* force continuation on long poller */
     157           0 :     GNUNET_SCHEDULER_cancel (ss->ps->tt);
     158           0 :     ss->ps->tt = NULL;
     159           0 :     TALER_TESTING_interpreter_next (is);
     160           0 :     return;
     161             :   }
     162          30 :   if (GNUNET_TIME_relative_is_zero (ss->timeout))
     163          23 :     TALER_TESTING_interpreter_next (is);
     164             : }
     165             : 
     166             : 
     167             : /**
     168             :  * Run the command.
     169             :  *
     170             :  * @param cls closure.
     171             :  * @param cmd the command being executed.
     172             :  * @param is the interpreter state.
     173             :  */
     174             : static void
     175          30 : status_run (void *cls,
     176             :             const struct TALER_TESTING_Command *cmd,
     177             :             struct TALER_TESTING_Interpreter *is)
     178             : {
     179          30 :   struct StatusState *ss = cls;
     180             :   const struct TALER_TESTING_Command *create_reserve;
     181             :   const char *exchange_url;
     182             : 
     183          30 :   ss->is = is;
     184          30 :   exchange_url = TALER_TESTING_get_exchange_url (is);
     185          30 :   if (NULL == exchange_url)
     186             :   {
     187           0 :     GNUNET_break (0);
     188           0 :     return;
     189             :   }
     190             :   create_reserve
     191          30 :     = TALER_TESTING_interpreter_lookup_command (is,
     192             :                                                 ss->reserve_reference);
     193          30 :   GNUNET_assert (NULL != create_reserve);
     194          30 :   if (GNUNET_OK !=
     195          30 :       TALER_TESTING_get_trait_reserve_pub (create_reserve,
     196             :                                            &ss->reserve_pubp))
     197             :   {
     198           0 :     GNUNET_break (0);
     199           0 :     TALER_LOG_ERROR ("Failed to find reserve_pub for status query\n");
     200           0 :     TALER_TESTING_interpreter_fail (is);
     201           0 :     return;
     202             :   }
     203          30 :   ss->rsh = TALER_EXCHANGE_reserves_get (
     204             :     TALER_TESTING_interpreter_get_context (is),
     205             :     exchange_url,
     206             :     ss->reserve_pubp,
     207             :     ss->timeout,
     208             :     &reserve_status_cb,
     209             :     ss);
     210          30 :   if (! GNUNET_TIME_relative_is_zero (ss->timeout))
     211             :   {
     212           7 :     TALER_TESTING_interpreter_next (is);
     213           7 :     return;
     214             :   }
     215             : }
     216             : 
     217             : 
     218             : /**
     219             :  * Cleanup the state from a "reserve status" CMD, and possibly
     220             :  * cancel a pending operation thereof.
     221             :  *
     222             :  * @param cls closure.
     223             :  * @param cmd the command which is being cleaned up.
     224             :  */
     225             : static void
     226          30 : status_cleanup (void *cls,
     227             :                 const struct TALER_TESTING_Command *cmd)
     228             : {
     229          30 :   struct StatusState *ss = cls;
     230             : 
     231          30 :   if (NULL != ss->rsh)
     232             :   {
     233           0 :     TALER_TESTING_command_incomplete (ss->is,
     234             :                                       cmd->label);
     235           0 :     TALER_EXCHANGE_reserves_get_cancel (ss->rsh);
     236           0 :     ss->rsh = NULL;
     237             :   }
     238          30 :   GNUNET_free (ss);
     239          30 : }
     240             : 
     241             : 
     242             : struct TALER_TESTING_Command
     243          23 : TALER_TESTING_cmd_status (const char *label,
     244             :                           const char *reserve_reference,
     245             :                           const char *expected_balance,
     246             :                           unsigned int expected_response_code)
     247             : {
     248             :   struct StatusState *ss;
     249             : 
     250          23 :   GNUNET_assert (NULL != reserve_reference);
     251          23 :   ss = GNUNET_new (struct StatusState);
     252          23 :   ss->reserve_reference = reserve_reference;
     253          23 :   ss->expected_balance = expected_balance;
     254          23 :   ss->expected_response_code = expected_response_code;
     255             :   {
     256          23 :     struct TALER_TESTING_Command cmd = {
     257             :       .cls = ss,
     258             :       .label = label,
     259             :       .run = &status_run,
     260             :       .cleanup = &status_cleanup
     261             :     };
     262             : 
     263          23 :     return cmd;
     264             :   }
     265             : }
     266             : 
     267             : 
     268             : struct TALER_TESTING_Command
     269           7 : TALER_TESTING_cmd_reserve_poll (const char *label,
     270             :                                 const char *reserve_reference,
     271             :                                 const char *expected_balance,
     272             :                                 struct GNUNET_TIME_Relative timeout,
     273             :                                 unsigned int expected_response_code)
     274             : {
     275             :   struct StatusState *ss;
     276             : 
     277           7 :   GNUNET_assert (NULL != reserve_reference);
     278           7 :   ss = GNUNET_new (struct StatusState);
     279           7 :   ss->reserve_reference = reserve_reference;
     280           7 :   ss->expected_balance = expected_balance;
     281           7 :   ss->expected_response_code = expected_response_code;
     282           7 :   ss->timeout = timeout;
     283             :   {
     284           7 :     struct TALER_TESTING_Command cmd = {
     285             :       .cls = ss,
     286             :       .label = label,
     287             :       .run = &status_run,
     288             :       .cleanup = &status_cleanup
     289             :     };
     290             : 
     291           7 :     return cmd;
     292             :   }
     293             : }
     294             : 
     295             : 
     296             : /**
     297             :  * Long poller timed out. Fail the test.
     298             :  *
     299             :  * @param cls a `struct PollState`
     300             :  */
     301             : static void
     302           0 : finish_timeout (void *cls)
     303             : {
     304           0 :   struct PollState *ps = cls;
     305             : 
     306           0 :   ps->tt = NULL;
     307           0 :   GNUNET_break (0);
     308           0 :   TALER_TESTING_interpreter_fail (ps->is);
     309           0 : }
     310             : 
     311             : 
     312             : /**
     313             :  * Run the command.
     314             :  *
     315             :  * @param cls closure.
     316             :  * @param cmd the command being executed.
     317             :  * @param is the interpreter state.
     318             :  */
     319             : static void
     320           7 : finish_run (void *cls,
     321             :             const struct TALER_TESTING_Command *cmd,
     322             :             struct TALER_TESTING_Interpreter *is)
     323             : {
     324           7 :   struct PollState *ps = cls;
     325             :   const struct TALER_TESTING_Command *poll_reserve;
     326             :   struct StatusState *ss;
     327             : 
     328           7 :   ps->is = is;
     329             :   poll_reserve
     330           7 :     = TALER_TESTING_interpreter_lookup_command (is,
     331             :                                                 ps->poll_reference);
     332           7 :   GNUNET_assert (NULL != poll_reserve);
     333           7 :   GNUNET_assert (poll_reserve->run == &status_run);
     334           7 :   ss = poll_reserve->cls;
     335           7 :   if (NULL == ss->rsh)
     336             :   {
     337           7 :     TALER_TESTING_interpreter_next (is);
     338           7 :     return;
     339             :   }
     340           0 :   GNUNET_assert (NULL == ss->ps);
     341           0 :   ss->ps = ps;
     342           0 :   ps->tt = GNUNET_SCHEDULER_add_delayed (ps->timeout,
     343             :                                          &finish_timeout,
     344             :                                          ps);
     345             : }
     346             : 
     347             : 
     348             : /**
     349             :  * Cleanup the state from a "reserve finish" CMD.
     350             :  *
     351             :  * @param cls closure.
     352             :  * @param cmd the command which is being cleaned up.
     353             :  */
     354             : static void
     355           7 : finish_cleanup (void *cls,
     356             :                 const struct TALER_TESTING_Command *cmd)
     357             : {
     358           7 :   struct PollState *ps = cls;
     359             : 
     360           7 :   if (NULL != ps->tt)
     361             :   {
     362           0 :     GNUNET_SCHEDULER_cancel (ps->tt);
     363           0 :     ps->tt = NULL;
     364             :   }
     365           7 :   GNUNET_free (ps);
     366           7 : }
     367             : 
     368             : 
     369             : struct TALER_TESTING_Command
     370           7 : TALER_TESTING_cmd_reserve_poll_finish (const char *label,
     371             :                                        struct GNUNET_TIME_Relative timeout,
     372             :                                        const char *poll_reference)
     373             : {
     374             :   struct PollState *ps;
     375             : 
     376           7 :   GNUNET_assert (NULL != poll_reference);
     377           7 :   ps = GNUNET_new (struct PollState);
     378           7 :   ps->timeout = timeout;
     379           7 :   ps->poll_reference = poll_reference;
     380             :   {
     381           7 :     struct TALER_TESTING_Command cmd = {
     382             :       .cls = ps,
     383             :       .label = label,
     384             :       .run = &finish_run,
     385             :       .cleanup = &finish_cleanup
     386             :     };
     387             : 
     388           7 :     return cmd;
     389             :   }
     390             : }

Generated by: LCOV version 1.16