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

Generated by: LCOV version 2.0-1