LCOV - code coverage report
Current view: top level - testing - testing_api_cmd_contract_get.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 65.3 % 98 64
Test Date: 2026-09-11 18:55:36 Functions: 100.0 % 5 5

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   Copyright (C) 2022 Taler Systems SA
       4              : 
       5              :   TALER is free software; you can redistribute it and/or modify it
       6              :   under the terms of the GNU General Public License as published by
       7              :   the Free Software Foundation; either version 3, or (at your
       8              :   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 GNU
      13              :   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_contract_get.c
      21              :  * @brief command for testing GET /contracts/$CPUB
      22              :  * @author Christian Grothoff
      23              :  */
      24              : #include "taler/taler_json_lib.h"
      25              : #include <gnunet/gnunet_curl_lib.h>
      26              : struct ContractGetState;
      27              : #define TALER_EXCHANGE_GET_CONTRACTS_RESULT_CLOSURE \
      28              :         struct ContractGetState
      29              : #include "taler/exchange/get-contracts-CONTRACT_PUB.h"
      30              : #include "taler/taler_testing_lib.h"
      31              : #include "taler/taler_signatures.h"
      32              : 
      33              : 
      34              : /**
      35              :  * State for a "contract get" CMD.
      36              :  */
      37              : struct ContractGetState
      38              : {
      39              : 
      40              :   /**
      41              :    * JSON string describing the resulting contract.
      42              :    */
      43              :   json_t *contract_terms;
      44              : 
      45              :   /**
      46              :    * Private key to decrypt the contract.
      47              :    */
      48              :   struct TALER_ContractDiffiePrivateP contract_priv;
      49              : 
      50              :   /**
      51              :    * Set to the returned merge key.
      52              :    */
      53              :   struct TALER_PurseMergePrivateKeyP merge_priv;
      54              : 
      55              :   /**
      56              :    * Public key of the purse.
      57              :    */
      58              :   struct TALER_PurseContractPublicKeyP purse_pub;
      59              : 
      60              :   /**
      61              :    * Reference to the command that uploaded the contract.
      62              :    */
      63              :   const char *contract_ref;
      64              : 
      65              :   /**
      66              :    * ContractGet handle while operation is running.
      67              :    */
      68              :   struct TALER_EXCHANGE_GetContractsHandle *dh;
      69              : 
      70              :   /**
      71              :    * Interpreter state.
      72              :    */
      73              :   struct TALER_TESTING_Interpreter *is;
      74              : 
      75              :   /**
      76              :    * Expected HTTP response code.
      77              :    */
      78              :   unsigned int expected_response_code;
      79              : 
      80              :   /**
      81              :    * True if this is for a 'merge' operation,
      82              :    * 'false' if this is for a 'deposit' operation.
      83              :    */
      84              :   bool merge;
      85              : 
      86              : };
      87              : 
      88              : 
      89              : /**
      90              :  * Callback to analyze the /contracts/$CPUB response, just used to check if
      91              :  * the response code is acceptable.
      92              :  *
      93              :  * @param ds closure.
      94              :  * @param dr get response details
      95              :  */
      96              : static void
      97            6 : get_cb (struct ContractGetState *ds,
      98              :         const struct TALER_EXCHANGE_GetContractsResponse *dr)
      99              : {
     100              :   const struct TALER_TESTING_Command *ref;
     101              : 
     102            6 :   ds->dh = NULL;
     103            6 :   if (ds->expected_response_code != dr->hr.http_status)
     104              :   {
     105            0 :     TALER_TESTING_unexpected_status (ds->is,
     106              :                                      dr->hr.http_status,
     107              :                                      ds->expected_response_code);
     108            0 :     return;
     109              :   }
     110            6 :   ref = TALER_TESTING_interpreter_lookup_command (ds->is,
     111              :                                                   ds->contract_ref);
     112            6 :   GNUNET_assert (NULL != ref);
     113            6 :   if (MHD_HTTP_OK == dr->hr.http_status)
     114              :   {
     115              :     const struct TALER_PurseMergePrivateKeyP *mp;
     116              :     const json_t *ct;
     117              : 
     118            6 :     ds->purse_pub = dr->details.ok.purse_pub;
     119            6 :     if (ds->merge)
     120              :     {
     121            3 :       if (GNUNET_OK !=
     122            3 :           TALER_TESTING_get_trait_merge_priv (ref,
     123              :                                               &mp))
     124              :       {
     125            0 :         GNUNET_break (0);
     126            0 :         TALER_TESTING_interpreter_fail (ds->is);
     127            0 :         return;
     128              :       }
     129            3 :       ds->contract_terms =
     130            3 :         TALER_CRYPTO_contract_decrypt_for_merge (
     131            3 :           &ds->contract_priv,
     132            3 :           &ds->purse_pub,
     133            3 :           dr->details.ok.econtract,
     134            3 :           dr->details.ok.econtract_size,
     135              :           &ds->merge_priv);
     136            3 :       if (0 !=
     137            3 :           GNUNET_memcmp (mp,
     138              :                          &ds->merge_priv))
     139              :       {
     140            0 :         GNUNET_break (0);
     141            0 :         TALER_TESTING_interpreter_fail (ds->is);
     142            0 :         return;
     143              :       }
     144              :     }
     145              :     else
     146              :     {
     147            3 :       ds->contract_terms =
     148            3 :         TALER_CRYPTO_contract_decrypt_for_deposit (
     149            3 :           &ds->contract_priv,
     150            3 :           dr->details.ok.econtract,
     151            3 :           dr->details.ok.econtract_size);
     152              :     }
     153            6 :     if (NULL == ds->contract_terms)
     154              :     {
     155            0 :       GNUNET_break (0);
     156            0 :       TALER_TESTING_interpreter_fail (ds->is);
     157            0 :       return;
     158              :     }
     159            6 :     if (GNUNET_OK !=
     160            6 :         TALER_TESTING_get_trait_contract_terms (ref,
     161              :                                                 &ct))
     162              :     {
     163            0 :       GNUNET_break (0);
     164            0 :       TALER_TESTING_interpreter_fail (ds->is);
     165            0 :       return;
     166              :     }
     167            6 :     if (1 != /* 1: equal, 0: not equal */
     168            6 :         json_equal (ct,
     169            6 :                     ds->contract_terms))
     170              :     {
     171            0 :       GNUNET_break (0);
     172            0 :       TALER_TESTING_interpreter_fail (ds->is);
     173            0 :       return;
     174              :     }
     175              :   }
     176            6 :   TALER_TESTING_interpreter_next (ds->is);
     177              : }
     178              : 
     179              : 
     180              : /**
     181              :  * Run the command.
     182              :  *
     183              :  * @param cls closure.
     184              :  * @param cmd the command to execute.
     185              :  * @param is the interpreter state.
     186              :  */
     187              : static void
     188            6 : get_run (void *cls,
     189              :          const struct TALER_TESTING_Command *cmd,
     190              :          struct TALER_TESTING_Interpreter *is)
     191              : {
     192            6 :   struct ContractGetState *ds = cls;
     193              :   const struct TALER_ContractDiffiePrivateP *contract_priv;
     194              :   const struct TALER_TESTING_Command *ref;
     195              :   const char *exchange_url;
     196              : 
     197              :   (void) cmd;
     198            6 :   ds->is = is;
     199            6 :   exchange_url = TALER_TESTING_get_exchange_url (is);
     200            6 :   if (NULL == exchange_url)
     201              :   {
     202            0 :     GNUNET_break (0);
     203            0 :     return;
     204              :   }
     205            6 :   ref = TALER_TESTING_interpreter_lookup_command (ds->is,
     206              :                                                   ds->contract_ref);
     207            6 :   GNUNET_assert (NULL != ref);
     208            6 :   if (GNUNET_OK !=
     209            6 :       TALER_TESTING_get_trait_contract_priv (ref,
     210              :                                              &contract_priv))
     211              :   {
     212            0 :     GNUNET_break (0);
     213            0 :     TALER_TESTING_interpreter_fail (ds->is);
     214            0 :     return;
     215              :   }
     216            6 :   ds->contract_priv = *contract_priv;
     217            6 :   ds->dh = TALER_EXCHANGE_get_contracts_create (
     218              :     TALER_TESTING_interpreter_get_context (is),
     219              :     exchange_url,
     220              :     contract_priv);
     221            6 :   if (NULL == ds->dh)
     222              :   {
     223            0 :     GNUNET_break (0);
     224            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     225              :                 "Could not GET contract\n");
     226            0 :     TALER_TESTING_interpreter_fail (is);
     227            0 :     return;
     228              :   }
     229            6 :   if (TALER_EC_NONE !=
     230            6 :       TALER_EXCHANGE_get_contracts_start (ds->dh,
     231              :                                           &get_cb,
     232              :                                           ds))
     233              :   {
     234            0 :     GNUNET_break (0);
     235            0 :     TALER_EXCHANGE_get_contracts_cancel (ds->dh);
     236            0 :     ds->dh = NULL;
     237            0 :     TALER_TESTING_interpreter_fail (is);
     238            0 :     return;
     239              :   }
     240              : }
     241              : 
     242              : 
     243              : /**
     244              :  * Free the state of a "get" CMD, and possibly cancel a
     245              :  * pending operation thereof.
     246              :  *
     247              :  * @param cls closure, must be a `struct ContractGetState`.
     248              :  * @param cmd the command which is being cleaned up.
     249              :  */
     250              : static void
     251            6 : get_cleanup (void *cls,
     252              :              const struct TALER_TESTING_Command *cmd)
     253              : {
     254            6 :   struct ContractGetState *ds = cls;
     255              : 
     256            6 :   if (NULL != ds->dh)
     257              :   {
     258            0 :     TALER_TESTING_command_incomplete (ds->is,
     259              :                                       cmd->label);
     260            0 :     TALER_EXCHANGE_get_contracts_cancel (ds->dh);
     261            0 :     ds->dh = NULL;
     262              :   }
     263            6 :   json_decref (ds->contract_terms);
     264            6 :   GNUNET_free (ds);
     265            6 : }
     266              : 
     267              : 
     268              : /**
     269              :  * Offer internal data from a "get" CMD, to other commands.
     270              :  *
     271              :  * @param cls closure.
     272              :  * @param[out] ret result.
     273              :  * @param trait name of the trait.
     274              :  * @param index index number of the object to offer.
     275              :  * @return #GNUNET_OK on success.
     276              :  */
     277              : static enum GNUNET_GenericReturnValue
     278           29 : get_traits (void *cls,
     279              :             const void **ret,
     280              :             const char *trait,
     281              :             unsigned int index)
     282              : {
     283           29 :   struct ContractGetState *ds = cls;
     284              :   struct TALER_TESTING_Trait traits[] = {
     285           29 :     TALER_TESTING_make_trait_merge_priv (&ds->merge_priv),
     286           29 :     TALER_TESTING_make_trait_purse_pub (&ds->purse_pub),
     287           29 :     TALER_TESTING_make_trait_contract_terms (ds->contract_terms),
     288           29 :     TALER_TESTING_trait_end ()
     289              :   };
     290              : 
     291              :   /* skip 'merge_priv' if we are in 'merge' mode */
     292           29 :   return TALER_TESTING_get_trait (&traits[ds->merge ? 0 : 1],
     293              :                                   ret,
     294              :                                   trait,
     295              :                                   index);
     296              : }
     297              : 
     298              : 
     299              : struct TALER_TESTING_Command
     300            6 : TALER_TESTING_cmd_contract_get (
     301              :   const char *label,
     302              :   unsigned int expected_http_status,
     303              :   bool for_merge,
     304              :   const char *contract_ref)
     305              : {
     306              :   struct ContractGetState *ds;
     307              : 
     308            6 :   ds = GNUNET_new (struct ContractGetState);
     309            6 :   ds->expected_response_code = expected_http_status;
     310            6 :   ds->contract_ref = contract_ref;
     311            6 :   ds->merge = for_merge;
     312              :   {
     313            6 :     struct TALER_TESTING_Command cmd = {
     314              :       .cls = ds,
     315              :       .label = label,
     316              :       .run = &get_run,
     317              :       .cleanup = &get_cleanup,
     318              :       .traits = &get_traits
     319              :     };
     320              : 
     321            6 :     return cmd;
     322              :   }
     323              : }
     324              : 
     325              : 
     326              : /* end of testing_api_cmd_contract_get.c */
        

Generated by: LCOV version 2.0-1