LCOV - code coverage report
Current view: top level - testing - testing_api_cmd_instance_token.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 74.3 % 101 75
Test Date: 2026-09-11 17:45:24 Functions: 100.0 % 9 9

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   Copyright (C) 2025 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 src/testing/testing_api_cmd_instance_token.c
      21              :  * @brief command to test /private/token POSTing
      22              :  * @author Martin Schanzenbach
      23              :  */
      24              : #include "platform.h"
      25              : struct TokenInstanceState;
      26              : #define TALER_MERCHANT_DELETE_PRIVATE_TOKEN_RESULT_CLOSURE struct TokenInstanceState
      27              : #define TALER_MERCHANT_POST_PRIVATE_TOKEN_RESULT_CLOSURE struct TokenInstanceState
      28              : #include <taler/taler_exchange_service.h>
      29              : #include <taler/taler_testing_lib.h>
      30              : #include "taler/taler_merchant_service.h"
      31              : #include "taler/taler_merchant_testing_lib.h"
      32              : #include <taler/merchant/delete-private-tokens-SERIAL.h>
      33              : #include <taler/merchant/post-private-token.h>
      34              : 
      35              : 
      36              : /**
      37              :  * State of a "POST /instances/$ID/private/token" CMD.
      38              :  */
      39              : struct TokenInstanceState
      40              : {
      41              : 
      42              :   /**
      43              :    * Handle for a "POST token" request.
      44              :    */
      45              :   struct TALER_MERCHANT_PostPrivateTokenHandle *itph;
      46              : 
      47              :   /**
      48              :    * Handle for a "DELETE token" request.
      49              :    */
      50              :   struct TALER_MERCHANT_DeletePrivateTokenHandle *itdh;
      51              : 
      52              :   /**
      53              :    * The interpreter state.
      54              :    */
      55              :   struct TALER_TESTING_Interpreter *is;
      56              : 
      57              :   /**
      58              :    * Base URL of the merchant serving the request.
      59              :    */
      60              :   const char *merchant_url;
      61              : 
      62              :   /**
      63              :    * ID of the instance to run GET for.
      64              :    */
      65              :   const char *instance_id;
      66              : 
      67              :   /**
      68              :    * The received token (if any).
      69              :    */
      70              :   char *token;
      71              : 
      72              :   /**
      73              :    * Desired scope. Can be NULL
      74              :    */
      75              :   const char *scope;
      76              : 
      77              :   /**
      78              :    * Desired duration.
      79              :    */
      80              :   struct GNUNET_TIME_Relative duration;
      81              : 
      82              :   /**
      83              :    * Refreshable?
      84              :    */
      85              :   bool refreshable;
      86              : 
      87              :   /**
      88              :    * Expected HTTP response code.
      89              :    */
      90              :   unsigned int http_status;
      91              : 
      92              :   /**
      93              :    * DELETE or POST.
      94              :    */
      95              :   unsigned int is_delete;
      96              : 
      97              : };
      98              : 
      99              : /**
     100              :  * Callback for a POST /instances/$ID/private/token operation.
     101              :  *
     102              :  * @param cls closure for this function
     103              :  * @param ptr response being processed
     104              :  */
     105              : static void
     106            4 : token_instance_post_cb (struct TokenInstanceState *tis,
     107              :                         const struct TALER_MERCHANT_PostPrivateTokenResponse *
     108              :                         ptr)
     109              : {
     110              : 
     111            4 :   tis->itph = NULL;
     112            4 :   if (tis->http_status != ptr->hr.http_status)
     113              :   {
     114            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     115              :                 "Unexpected response code %u (%d) to command %s\n",
     116              :                 ptr->hr.http_status,
     117              :                 (int) ptr->hr.ec,
     118              :                 TALER_TESTING_interpreter_get_current_label (tis->is));
     119            0 :     TALER_TESTING_interpreter_fail (tis->is);
     120            0 :     return;
     121              :   }
     122            4 :   switch (ptr->hr.http_status)
     123              :   {
     124            4 :   case MHD_HTTP_OK:
     125            4 :     if (NULL != ptr->details.ok.access_token)
     126            4 :       tis->token = GNUNET_strdup (ptr->details.ok.access_token);
     127            4 :     break;
     128            0 :   case MHD_HTTP_BAD_REQUEST:
     129              :     /* likely invalid auth value, we do not check client-side */
     130            0 :     break;
     131            0 :   case MHD_HTTP_FORBIDDEN:
     132            0 :     break;
     133            0 :   default:
     134            0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     135              :                 "Unhandled HTTP status %u (%d) returned from /private/token operation.\n",
     136              :                 ptr->hr.http_status,
     137              :                 ptr->hr.ec);
     138              :   }
     139            4 :   TALER_TESTING_interpreter_next (tis->is);
     140              : }
     141              : 
     142              : 
     143              : /**
     144              :  * Callback for a DELETE /private/tokens/$SERIAL operation.
     145              :  *
     146              :  * @param cls closure for this function
     147              :  * @param dtr response being processed
     148              :  */
     149              : static void
     150            2 : token_instance_delete_cb (
     151              :   struct TokenInstanceState *tis,
     152              :   const struct TALER_MERCHANT_DeletePrivateTokenResponse *dtr)
     153              : {
     154              : 
     155            2 :   tis->itdh = NULL;
     156            2 :   if (tis->http_status != dtr->hr.http_status)
     157              :   {
     158            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     159              :                 "Unexpected response code %u (%d) to command %s\n",
     160              :                 dtr->hr.http_status,
     161              :                 (int) dtr->hr.ec,
     162              :                 TALER_TESTING_interpreter_get_current_label (tis->is));
     163            0 :     TALER_TESTING_interpreter_fail (tis->is);
     164            0 :     return;
     165              :   }
     166            2 :   switch (dtr->hr.http_status)
     167              :   {
     168            2 :   case MHD_HTTP_NO_CONTENT:
     169            2 :     break;
     170            0 :   case MHD_HTTP_FORBIDDEN:
     171            0 :     break;
     172            0 :   default:
     173            0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     174              :                 "Unhandled HTTP status %u (%d) returned from DELETE /private/tokens operation.\n",
     175              :                 dtr->hr.http_status,
     176              :                 dtr->hr.ec);
     177              :   }
     178            2 :   TALER_TESTING_interpreter_next (tis->is);
     179              : }
     180              : 
     181              : 
     182              : /**
     183              :  * set a token
     184              :  *
     185              :  *
     186              :  * @param cls closure.
     187              :  * @param cmd command being run now.
     188              :  * @param is interpreter state.
     189              :  */
     190              : static void
     191            4 : set_token_instance_run (void *cls,
     192              :                         const struct TALER_TESTING_Command *cmd,
     193              :                         struct TALER_TESTING_Interpreter *is)
     194              : {
     195            4 :   const char *token_job_label = cls;
     196              :   const char *token;
     197              :   const struct TALER_TESTING_Command *tok_cmd;
     198              :   struct GNUNET_CURL_Context *cctx;
     199              :   char *authorization;
     200              : 
     201            4 :   cctx = TALER_TESTING_interpreter_get_context (is);
     202            4 :   GNUNET_assert (NULL != cctx);
     203            4 :   tok_cmd = TALER_TESTING_interpreter_lookup_command (
     204              :     is,
     205              :     token_job_label);
     206            4 :   if (NULL == tok_cmd)
     207              :   {
     208            0 :     GNUNET_break (0);
     209            0 :     TALER_TESTING_interpreter_fail (is);
     210            0 :     return;
     211              :   }
     212            4 :   if (GNUNET_OK !=
     213            4 :       TALER_TESTING_get_trait_bearer_token (tok_cmd,
     214              :                                             &token))
     215              :   {
     216            0 :     GNUNET_break (0);
     217            0 :     TALER_TESTING_interpreter_fail (is);
     218            0 :     return;
     219              :   }
     220            4 :   GNUNET_assert (NULL != token);
     221              : 
     222            4 :   GNUNET_asprintf (&authorization,
     223              :                    "%s: Bearer %s",
     224              :                    MHD_HTTP_HEADER_AUTHORIZATION,
     225              :                    token);
     226            4 :   GNUNET_assert (GNUNET_OK ==
     227              :                  GNUNET_CURL_append_header (cctx,
     228              :                                             authorization));
     229            4 :   GNUNET_free (authorization);
     230            4 :   TALER_TESTING_interpreter_next (is);
     231              : }
     232              : 
     233              : 
     234              : /**
     235              :  * Run the "token /instances/$ID" CMD.
     236              :  *
     237              :  * @param cls closure.
     238              :  * @param cmd command being run now.
     239              :  * @param is interpreter state.
     240              :  */
     241              : static void
     242            6 : token_instance_run (void *cls,
     243              :                     const struct TALER_TESTING_Command *cmd,
     244              :                     struct TALER_TESTING_Interpreter *is)
     245              : {
     246            6 :   struct TokenInstanceState *tis = cls;
     247              : 
     248            6 :   tis->is = is;
     249            6 :   if (GNUNET_NO == tis->is_delete)
     250              :   {
     251            4 :     tis->itph = TALER_MERCHANT_post_private_token_create (
     252              :       TALER_TESTING_interpreter_get_context (is),
     253              :       tis->merchant_url,
     254              :       tis->instance_id,
     255              :       tis->scope);
     256            4 :     GNUNET_assert (GNUNET_OK ==
     257              :                    TALER_MERCHANT_post_private_token_set_options (
     258              :                      tis->itph,
     259              :                      TALER_MERCHANT_post_private_token_option_duration (
     260              :                        tis->duration),
     261              :                      TALER_MERCHANT_post_private_token_option_refreshable (
     262              :                        tis->refreshable)));
     263              :     {
     264              :       enum TALER_ErrorCode ec;
     265              : 
     266            4 :       ec = TALER_MERCHANT_post_private_token_start (
     267              :         tis->itph,
     268              :         &token_instance_post_cb,
     269              :         tis);
     270            4 :       GNUNET_assert (TALER_EC_NONE == ec);
     271              :     }
     272              :   }
     273              :   else
     274              :   {
     275            2 :     tis->itdh = TALER_MERCHANT_delete_private_token_create (
     276              :       TALER_TESTING_interpreter_get_context (is),
     277              :       tis->merchant_url,
     278              :       tis->instance_id);
     279              :     {
     280              :       enum TALER_ErrorCode ec;
     281              : 
     282            2 :       ec = TALER_MERCHANT_delete_private_token_start (
     283              :         tis->itdh,
     284              :         &token_instance_delete_cb,
     285              :         tis);
     286            2 :       GNUNET_assert (TALER_EC_NONE == ec);
     287              :     }
     288              :   }
     289            6 : }
     290              : 
     291              : 
     292              : /**
     293              :  * Free the state of a "POST instance token" CMD, and possibly
     294              :  * cancel a pending operation thereof.
     295              :  *
     296              :  * @param cls closure.
     297              :  * @param cmd command being run.
     298              :  */
     299              : static void
     300            6 : token_instance_cleanup (void *cls,
     301              :                         const struct TALER_TESTING_Command *cmd)
     302              : {
     303            6 :   struct TokenInstanceState *tis = cls;
     304              : 
     305            6 :   if (NULL != tis->itph)
     306              :   {
     307            0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     308              :                 "POST /instance/$ID/token operation did not complete\n");
     309            0 :     TALER_MERCHANT_post_private_token_cancel (tis->itph);
     310              :   }
     311            6 :   if (NULL != tis->itdh)
     312              :   {
     313            0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     314              :                 "DELETE /instance/$ID/token operation did not complete\n");
     315            0 :     TALER_MERCHANT_delete_private_token_cancel (tis->itdh);
     316              :   }
     317            6 :   GNUNET_free (tis->token);
     318            6 :   GNUNET_free (tis);
     319            6 : }
     320              : 
     321              : 
     322              : /**
     323              :  * Offer internal data to other commands.
     324              :  *
     325              :  * @param cls closure
     326              :  * @param[out] ret result (could be anything)
     327              :  * @param trait name of the trait
     328              :  * @param index index number of the object to extract.
     329              :  * @return #GNUNET_OK on success
     330              :  */
     331              : static enum GNUNET_GenericReturnValue
     332            4 : token_instance_traits (void *cls,
     333              :                        const void **ret,
     334              :                        const char *trait,
     335              :                        unsigned int index)
     336              : {
     337            4 :   struct TokenInstanceState *ais = cls;
     338              :   struct TALER_TESTING_Trait traits[] = {
     339            4 :     TALER_TESTING_make_trait_bearer_token (ais->token),
     340            4 :     TALER_TESTING_trait_end ()
     341              :   };
     342              : 
     343            4 :   return TALER_TESTING_get_trait (traits,
     344              :                                   ret,
     345              :                                   trait,
     346              :                                   index);
     347              : }
     348              : 
     349              : 
     350              : struct TALER_TESTING_Command
     351            2 : TALER_TESTING_cmd_merchant_delete_instance_token (const char *label,
     352              :                                                   const char *merchant_url,
     353              :                                                   const char *instance_id,
     354              :                                                   unsigned int http_status)
     355              : {
     356              :   struct TokenInstanceState *tis;
     357              : 
     358            2 :   tis = GNUNET_new (struct TokenInstanceState);
     359            2 :   tis->merchant_url = merchant_url;
     360            2 :   tis->instance_id = instance_id;
     361            2 :   tis->is_delete = GNUNET_YES;
     362            2 :   tis->http_status = http_status;
     363              : 
     364              :   {
     365            2 :     struct TALER_TESTING_Command cmd = {
     366              :       .cls = tis,
     367              :       .label = label,
     368              :       .run = &token_instance_run,
     369              :       .cleanup = &token_instance_cleanup,
     370              :       .traits = &token_instance_traits
     371              :     };
     372              : 
     373            2 :     return cmd;
     374              :   }
     375              : }
     376              : 
     377              : 
     378              : struct TALER_TESTING_Command
     379            4 : TALER_TESTING_cmd_merchant_set_instance_token (const char *label,
     380              :                                                const char *token_job_label)
     381              : {
     382              :   {
     383            4 :     struct TALER_TESTING_Command cmd = {
     384              :       .cls = (void*) token_job_label, // FIXME scope
     385              :       .label = label,
     386              :       .run = &set_token_instance_run,
     387              :       .cleanup = NULL,
     388              :       .traits = NULL
     389              :     };
     390              : 
     391            4 :     return cmd;
     392              :   }
     393              : }
     394              : 
     395              : 
     396              : struct TALER_TESTING_Command
     397            4 : TALER_TESTING_cmd_merchant_post_instance_token (const char *label,
     398              :                                                 const char *merchant_url,
     399              :                                                 const char *instance_id,
     400              :                                                 const char *scope,
     401              :                                                 struct GNUNET_TIME_Relative
     402              :                                                 duration,
     403              :                                                 bool refreshable,
     404              :                                                 unsigned int http_status)
     405              : {
     406              :   struct TokenInstanceState *tis;
     407              : 
     408            4 :   tis = GNUNET_new (struct TokenInstanceState);
     409            4 :   tis->merchant_url = merchant_url;
     410            4 :   tis->instance_id = instance_id;
     411            4 :   tis->scope = scope;
     412            4 :   tis->duration = duration;
     413            4 :   tis->refreshable = refreshable;
     414            4 :   tis->is_delete = GNUNET_NO;
     415            4 :   tis->http_status = http_status;
     416              : 
     417              :   {
     418            4 :     struct TALER_TESTING_Command cmd = {
     419              :       .cls = tis,
     420              :       .label = label,
     421              :       .run = &token_instance_run,
     422              :       .cleanup = &token_instance_cleanup,
     423              :       .traits = &token_instance_traits
     424              :     };
     425              : 
     426            4 :     return cmd;
     427              :   }
     428              : }
     429              : 
     430              : 
     431              : /* end of testing_api_cmd_token_instance.c */
        

Generated by: LCOV version 2.0-1