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

Generated by: LCOV version 2.0-1