LCOV - code coverage report
Current view: top level - testing - testing_api_cmd_purse_get.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 71.4 % 98 70
Test Date: 2026-03-07 14:54:45 Functions: 87.5 % 8 7

            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_purse_get.c
      21              :  * @brief Implement the GET /purse/$RID test command.
      22              :  * @author Marcello Stanisci
      23              :  */
      24              : #include "taler/platform.h"
      25              : #include "taler/taler_json_lib.h"
      26              : #include <gnunet/gnunet_curl_lib.h>
      27              : #include "taler/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 purse to check,
      43              :    * needed to resort the purse 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 purse to check,
      77              :    * needed to resort the purse key.
      78              :    */
      79              :   const char *purse_reference;
      80              : 
      81              :   /**
      82              :    * Handle to the "purse status" operation.
      83              :    */
      84              :   struct TALER_EXCHANGE_GetPursesHandle *pgh;
      85              : 
      86              :   /**
      87              :    * Expected purse balance.
      88              :    */
      89              :   const char *expected_balance;
      90              : 
      91              :   /**
      92              :    * Public key of the purse being analyzed.
      93              :    */
      94              :   const struct TALER_PurseContractPublicKeyP *purse_pub;
      95              : 
      96              :   /**
      97              :    * Interpreter state.
      98              :    */
      99              :   struct TALER_TESTING_Interpreter *is;
     100              : 
     101              :   /**
     102              :    * Expected HTTP response code.
     103              :    */
     104              :   unsigned int expected_response_code;
     105              : 
     106              :   /**
     107              :    * Are we waiting for a merge or a deposit?
     108              :    */
     109              :   bool wait_for_merge;
     110              : 
     111              : };
     112              : 
     113              : 
     114              : /**
     115              :  * Check that the purse balance and HTTP response code are
     116              :  * both acceptable.
     117              :  *
     118              :  * @param cls closure.
     119              :  * @param rs HTTP response details
     120              :  */
     121              : static void
     122           10 : purse_status_cb (void *cls,
     123              :                  const struct TALER_EXCHANGE_GetPursesResponse *rs)
     124              : {
     125           10 :   struct StatusState *ss = cls;
     126           10 :   struct TALER_TESTING_Interpreter *is = ss->is;
     127              : 
     128           10 :   ss->pgh = NULL;
     129           10 :   if (ss->expected_response_code != rs->hr.http_status)
     130              :   {
     131            0 :     TALER_TESTING_unexpected_status (is,
     132              :                                      rs->hr.http_status,
     133              :                                      ss->expected_response_code);
     134            0 :     return;
     135              :   }
     136           10 :   if (MHD_HTTP_OK == ss->expected_response_code)
     137              :   {
     138              :     struct TALER_Amount eb;
     139              : 
     140            6 :     GNUNET_assert (GNUNET_OK ==
     141              :                    TALER_string_to_amount (ss->expected_balance,
     142              :                                            &eb));
     143            6 :     if (0 != TALER_amount_cmp (&eb,
     144              :                                &rs->details.ok.balance))
     145              :     {
     146            0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     147              :                   "Unexpected amount in purse: %s\n",
     148              :                   TALER_amount_to_string (&rs->details.ok.balance));
     149            0 :       TALER_TESTING_interpreter_fail (ss->is);
     150            0 :       return;
     151              :     }
     152              :   }
     153           10 :   if (NULL != ss->ps)
     154              :   {
     155              :     /* force continuation on long poller */
     156            8 :     GNUNET_SCHEDULER_cancel (ss->ps->tt);
     157            8 :     ss->ps->tt = NULL;
     158            8 :     TALER_TESTING_interpreter_next (is);
     159            8 :     return;
     160              :   }
     161            2 :   if (GNUNET_TIME_relative_is_zero (ss->timeout))
     162            0 :     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           10 : status_run (void *cls,
     175              :             const struct TALER_TESTING_Command *cmd,
     176              :             struct TALER_TESTING_Interpreter *is)
     177              : {
     178           10 :   struct StatusState *ss = cls;
     179              :   const struct TALER_TESTING_Command *create_purse;
     180              : 
     181           10 :   ss->is = is;
     182              :   create_purse
     183           10 :     = TALER_TESTING_interpreter_lookup_command (is,
     184              :                                                 ss->purse_reference);
     185           10 :   GNUNET_assert (NULL != create_purse);
     186           10 :   if (GNUNET_OK !=
     187           10 :       TALER_TESTING_get_trait_purse_pub (create_purse,
     188              :                                          &ss->purse_pub))
     189              :   {
     190            0 :     GNUNET_break (0);
     191            0 :     TALER_LOG_ERROR ("Failed to find purse_pub for status query\n");
     192            0 :     TALER_TESTING_interpreter_fail (is);
     193           10 :     return;
     194              :   }
     195           10 :   ss->pgh = TALER_EXCHANGE_get_purses_create (
     196              :     TALER_TESTING_interpreter_get_context (is),
     197              :     TALER_TESTING_get_exchange_url (is),
     198              :     TALER_TESTING_get_keys (is),
     199              :     ss->purse_pub);
     200           10 :   if (NULL == ss->pgh)
     201              :   {
     202            0 :     GNUNET_break (0);
     203            0 :     TALER_TESTING_interpreter_fail (is);
     204            0 :     return;
     205              :   }
     206           10 :   TALER_EXCHANGE_get_purses_set_options (
     207              :     ss->pgh,
     208              :     TALER_EXCHANGE_get_purses_option_timeout (ss->timeout),
     209              :     TALER_EXCHANGE_get_purses_option_wait_for_merge (ss->wait_for_merge));
     210           10 :   if (TALER_EC_NONE !=
     211           10 :       TALER_EXCHANGE_get_purses_start (ss->pgh,
     212              :                                        &purse_status_cb,
     213              :                                        ss))
     214              :   {
     215            0 :     GNUNET_break (0);
     216            0 :     TALER_EXCHANGE_get_purses_cancel (ss->pgh);
     217            0 :     ss->pgh = NULL;
     218            0 :     TALER_TESTING_interpreter_fail (is);
     219            0 :     return;
     220              :   }
     221           10 :   if (! GNUNET_TIME_relative_is_zero (ss->timeout))
     222              :   {
     223           10 :     TALER_TESTING_interpreter_next (is);
     224           10 :     return;
     225              :   }
     226              : }
     227              : 
     228              : 
     229              : /**
     230              :  * Cleanup the state from a "purse status" CMD, and possibly
     231              :  * cancel a pending operation thereof.
     232              :  *
     233              :  * @param cls closure.
     234              :  * @param cmd the command which is being cleaned up.
     235              :  */
     236              : static void
     237           10 : status_cleanup (void *cls,
     238              :                 const struct TALER_TESTING_Command *cmd)
     239              : {
     240           10 :   struct StatusState *ss = cls;
     241              : 
     242           10 :   if (NULL != ss->pgh)
     243              :   {
     244            0 :     TALER_TESTING_command_incomplete (ss->is,
     245              :                                       cmd->label);
     246            0 :     TALER_EXCHANGE_get_purses_cancel (ss->pgh);
     247            0 :     ss->pgh = NULL;
     248              :   }
     249           10 :   GNUNET_free (ss);
     250           10 : }
     251              : 
     252              : 
     253              : struct TALER_TESTING_Command
     254           10 : TALER_TESTING_cmd_purse_poll (
     255              :   const char *label,
     256              :   unsigned int expected_http_status,
     257              :   const char *purse_ref,
     258              :   const char *expected_balance,
     259              :   bool wait_for_merge,
     260              :   struct GNUNET_TIME_Relative timeout)
     261              : {
     262              :   struct StatusState *ss;
     263              : 
     264           10 :   GNUNET_assert (NULL != purse_ref);
     265           10 :   ss = GNUNET_new (struct StatusState);
     266           10 :   ss->purse_reference = purse_ref;
     267           10 :   ss->expected_balance = expected_balance;
     268           10 :   ss->expected_response_code = expected_http_status;
     269           10 :   ss->timeout = timeout;
     270           10 :   ss->wait_for_merge = wait_for_merge;
     271              :   {
     272           10 :     struct TALER_TESTING_Command cmd = {
     273              :       .cls = ss,
     274              :       .label = label,
     275              :       .run = &status_run,
     276              :       .cleanup = &status_cleanup
     277              :     };
     278              : 
     279           10 :     return cmd;
     280              :   }
     281              : }
     282              : 
     283              : 
     284              : /**
     285              :  * Long poller timed out. Fail the test.
     286              :  *
     287              :  * @param cls a `struct PollState`
     288              :  */
     289              : static void
     290            0 : finish_timeout (void *cls)
     291              : {
     292            0 :   struct PollState *ps = cls;
     293              : 
     294            0 :   ps->tt = NULL;
     295            0 :   GNUNET_break (0);
     296            0 :   TALER_TESTING_interpreter_fail (ps->is);
     297            0 : }
     298              : 
     299              : 
     300              : /**
     301              :  * Run the command.
     302              :  *
     303              :  * @param cls closure.
     304              :  * @param cmd the command being executed.
     305              :  * @param is the interpreter state.
     306              :  */
     307              : static void
     308           10 : finish_run (void *cls,
     309              :             const struct TALER_TESTING_Command *cmd,
     310              :             struct TALER_TESTING_Interpreter *is)
     311              : {
     312           10 :   struct PollState *ps = cls;
     313              :   const struct TALER_TESTING_Command *poll_purse;
     314              :   struct StatusState *ss;
     315              : 
     316           10 :   ps->is = is;
     317              :   poll_purse
     318           10 :     = TALER_TESTING_interpreter_lookup_command (is,
     319              :                                                 ps->poll_reference);
     320           10 :   GNUNET_assert (NULL != poll_purse);
     321           10 :   GNUNET_assert (poll_purse->run == &status_run);
     322           10 :   ss = poll_purse->cls;
     323           10 :   if (NULL == ss->pgh)
     324              :   {
     325            2 :     TALER_TESTING_interpreter_next (is);
     326            2 :     return;
     327              :   }
     328            8 :   GNUNET_assert (NULL == ss->ps);
     329            8 :   ss->ps = ps;
     330            8 :   ps->tt = GNUNET_SCHEDULER_add_delayed (ps->timeout,
     331              :                                          &finish_timeout,
     332              :                                          ps);
     333              : }
     334              : 
     335              : 
     336              : /**
     337              :  * Cleanup the state from a "purse finish" CMD.
     338              :  *
     339              :  * @param cls closure.
     340              :  * @param cmd the command which is being cleaned up.
     341              :  */
     342              : static void
     343           10 : finish_cleanup (void *cls,
     344              :                 const struct TALER_TESTING_Command *cmd)
     345              : {
     346           10 :   struct PollState *ps = cls;
     347              : 
     348           10 :   if (NULL != ps->tt)
     349              :   {
     350            0 :     GNUNET_SCHEDULER_cancel (ps->tt);
     351            0 :     ps->tt = NULL;
     352              :   }
     353           10 :   GNUNET_free (ps);
     354           10 : }
     355              : 
     356              : 
     357              : struct TALER_TESTING_Command
     358           10 : TALER_TESTING_cmd_purse_poll_finish (const char *label,
     359              :                                      struct GNUNET_TIME_Relative timeout,
     360              :                                      const char *poll_reference)
     361              : {
     362              :   struct PollState *ps;
     363              : 
     364           10 :   GNUNET_assert (NULL != poll_reference);
     365           10 :   ps = GNUNET_new (struct PollState);
     366           10 :   ps->timeout = timeout;
     367           10 :   ps->poll_reference = poll_reference;
     368              :   {
     369           10 :     struct TALER_TESTING_Command cmd = {
     370              :       .cls = ps,
     371              :       .label = label,
     372              :       .run = &finish_run,
     373              :       .cleanup = &finish_cleanup
     374              :     };
     375              : 
     376           10 :     return cmd;
     377              :   }
     378              : }
        

Generated by: LCOV version 2.0-1