LCOV - code coverage report
Current view: top level - testing - testing_api_cmd_reserve_get.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 65.2 % 112 73
Test Date: 2026-04-14 15:39:31 Functions: 88.9 % 9 8

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

Generated by: LCOV version 2.0-1