LCOV - code coverage report
Current view: top level - testing - testing_api_cmd_post_using_templates.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 74.0 % 215 159
Test Date: 2026-09-11 17:45:24 Functions: 100.0 % 10 10

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   Copyright (C) 2022-2023 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_post_using_templates.c
      21              :  * @brief command to test POST /using-templates
      22              :  * @author Priscilla HUANG
      23              :  */
      24              : #include "platform.h"
      25              : struct PostUsingTemplatesState;
      26              : #define TALER_MERCHANT_POST_TEMPLATES_RESULT_CLOSURE struct PostUsingTemplatesState
      27              : #define TALER_MERCHANT_POST_ORDERS_CLAIM_RESULT_CLOSURE struct PostUsingTemplatesState
      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/post-templates-TEMPLATE_ID.h>
      33              : #include <taler/merchant/post-orders-ORDER_ID-claim.h>
      34              : 
      35              : 
      36              : /**
      37              :  * State of a "POST /templates" CMD.
      38              :  */
      39              : struct PostUsingTemplatesState
      40              : {
      41              : 
      42              :   /**
      43              :    * Handle for a "POST /templates/$TEMPLATE_ID" request.
      44              :    */
      45              :   struct TALER_MERCHANT_PostTemplatesHandle *iph;
      46              : 
      47              :   /**
      48              :    * The interpreter state.
      49              :    */
      50              :   struct TALER_TESTING_Interpreter *is;
      51              : 
      52              :   /**
      53              :    * The (initial) POST /orders/$ID/claim operation handle.
      54              :    * The logic is such that after an order creation,
      55              :    * we immediately claim the order.
      56              :    */
      57              :   struct TALER_MERCHANT_PostOrdersClaimHandle *och;
      58              : 
      59              :   /**
      60              :    * Base URL of the merchant serving the request.
      61              :    */
      62              :   const char *merchant_url;
      63              : 
      64              :   /**
      65              :    * ID of the using template to run.
      66              :    */
      67              :   const char *using_template_id;
      68              : 
      69              :   /**
      70              :    * Summary given by the customer.
      71              :    */
      72              :   const char *summary;
      73              : 
      74              :   /**
      75              :    * Amount given by the customer.
      76              :    */
      77              :   struct TALER_Amount amount;
      78              : 
      79              :   /**
      80              :    * Raw request body for inventory templates (if set).
      81              :    */
      82              :   json_t *details;
      83              : 
      84              :   /**
      85              :    * Label of a command that created the template we should use.
      86              :    */
      87              :   const char *template_ref;
      88              : 
      89              :   /**
      90              :    * Order id.
      91              :    */
      92              :   char *order_id;
      93              : 
      94              :   /**
      95              :    * The order id we expect the merchant to assign (if not NULL).
      96              :    */
      97              :   const char *expected_order_id;
      98              : 
      99              :   /**
     100              :    * Contract terms obtained from the backend.
     101              :    */
     102              :   json_t *contract_terms;
     103              : 
     104              :   /**
     105              :    * Order submitted to the backend.
     106              :    */
     107              :   json_t *order_terms;
     108              : 
     109              :   /**
     110              :    * Contract terms hash code.
     111              :    */
     112              :   struct TALER_PrivateContractHashP h_contract_terms;
     113              : 
     114              :   /**
     115              :    * Merchant signature over the orders.
     116              :    */
     117              :   struct TALER_MerchantSignatureP merchant_sig;
     118              : 
     119              :   /**
     120              :    * Merchant public key.
     121              :    */
     122              :   struct TALER_MerchantPublicKeyP merchant_pub;
     123              : 
     124              :   /**
     125              :    * The nonce.
     126              :    */
     127              :   struct GNUNET_CRYPTO_EddsaPublicKey nonce;
     128              : 
     129              :   /**
     130              :    * The claim token
     131              :    */
     132              :   struct TALER_ClaimTokenP claim_token;
     133              : 
     134              :   /**
     135              :    * Pay deadline returned when the template was instantiated.
     136              :    */
     137              :   struct GNUNET_TIME_Timestamp pay_deadline;
     138              : 
     139              :   /**
     140              :    * Time when the template instantiation request was started.
     141              :    */
     142              :   struct GNUNET_TIME_Absolute request_start;
     143              : 
     144              :   /**
     145              :    * Pay duration configured in the template.
     146              :    */
     147              :   struct GNUNET_TIME_Relative pay_duration;
     148              : 
     149              :   /**
     150              :    * Whether @e pay_duration is finite and non-zero and should be checked.
     151              :    */
     152              :   bool check_pay_duration;
     153              : 
     154              :   /**
     155              :    * Whether @e pay_duration was explicitly supplied as the expected duration.
     156              :    */
     157              :   bool have_expected_pay_duration;
     158              : 
     159              :   /**
     160              :    * Should the command also CLAIM the order?
     161              :    */
     162              :   bool with_claim;
     163              : 
     164              :   /**
     165              :    * If not NULL, the command should duplicate the request and verify the
     166              :    * response is the same as in this command.
     167              :    */
     168              :   const char *duplicate_of;
     169              : 
     170              :   /**
     171              :    * Label of command creating/updating OTP device, or NULL.
     172              :    */
     173              :   const char *otp_ref;
     174              : 
     175              :   /**
     176              :    * Encoded key for the payment verification.
     177              :    */
     178              :   const char *otp_key;
     179              : 
     180              :   /**
     181              :    * Option that add amount of the order
     182              :    */
     183              :   const enum TALER_MerchantConfirmationAlgorithm *otp_alg;
     184              : 
     185              :   /**
     186              :    * Expected HTTP response code.
     187              :    */
     188              :   unsigned int http_status;
     189              : 
     190              : };
     191              : 
     192              : /**
     193              :  * Used to fill the "using_template" CMD state with backend-provided
     194              :  * values.  Also double-checks that the using_template was correctly
     195              :  * created.
     196              :  *
     197              :  * @param cls closure
     198              :  * @param ocr response we got
     199              :  */
     200              : static void
     201           16 : using_claim_cb (struct PostUsingTemplatesState *tis,
     202              :                 const struct TALER_MERCHANT_PostOrdersClaimResponse *ocr)
     203              : {
     204              :   const char *error_name;
     205              :   unsigned int error_line;
     206              :   struct GNUNET_TIME_Timestamp pay_deadline;
     207              :   struct GNUNET_JSON_Specification spec[] = {
     208           16 :     GNUNET_JSON_spec_fixed_auto ("merchant_pub",
     209              :                                  &tis->merchant_pub),
     210           16 :     GNUNET_JSON_spec_timestamp ("pay_deadline",
     211              :                                 &pay_deadline),
     212           16 :     GNUNET_JSON_spec_end ()
     213              :   };
     214              : 
     215           16 :   tis->och = NULL;
     216           16 :   if (tis->http_status != ocr->hr.http_status)
     217              :   {
     218            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     219              :                 "Expected status %u, got %u\n",
     220              :                 tis->http_status,
     221              :                 ocr->hr.http_status);
     222            0 :     TALER_TESTING_FAIL (tis->is);
     223              :   }
     224           16 :   if (MHD_HTTP_OK != ocr->hr.http_status)
     225              :   {
     226            0 :     TALER_TESTING_interpreter_next (tis->is);
     227            0 :     return;
     228              :   }
     229           32 :   tis->contract_terms = json_deep_copy (
     230           16 :     (json_t *) ocr->details.ok.contract_terms);
     231           16 :   if (GNUNET_OK !=
     232           16 :       TALER_JSON_contract_hash (tis->contract_terms,
     233              :                                 &tis->h_contract_terms))
     234              :   {
     235            0 :     GNUNET_break (0);
     236            0 :     TALER_TESTING_FAIL (tis->is);
     237              :   }
     238           16 :   tis->merchant_sig = ocr->details.ok.merchant_sig;
     239           16 :   if (GNUNET_OK !=
     240           16 :       GNUNET_JSON_parse (tis->contract_terms,
     241              :                          spec,
     242              :                          &error_name,
     243              :                          &error_line))
     244              :   {
     245              :     char *log;
     246              : 
     247            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     248              :                 "Parser failed on %s:%u\n",
     249              :                 error_name,
     250              :                 error_line);
     251            0 :     log = json_dumps (tis->contract_terms,
     252              :                       JSON_INDENT (1));
     253            0 :     fprintf (stderr,
     254              :              "%s\n",
     255              :              log);
     256            0 :     free (log);
     257            0 :     TALER_TESTING_FAIL (tis->is);
     258              :   }
     259           16 :   if (GNUNET_TIME_timestamp_cmp (pay_deadline,
     260              :                                  !=,
     261              :                                  tis->pay_deadline))
     262              :   {
     263            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     264              :                 "Pay deadline in claimed contract does not match template instantiation response\n");
     265            0 :     TALER_TESTING_FAIL (tis->is);
     266              :   }
     267           16 :   TALER_TESTING_interpreter_next (tis->is);
     268              : }
     269              : 
     270              : 
     271              : /**
     272              :  * Callback for a POST /using-templates operation.
     273              :  *
     274              :  * @param cls closure for this function
     275              :  * @param por response being processed
     276              :  */
     277              : static void
     278           38 : post_using_templates_cb (struct PostUsingTemplatesState *tis,
     279              :                          const struct TALER_MERCHANT_PostTemplatesResponse *por)
     280              : {
     281              : 
     282           38 :   tis->iph = NULL;
     283           38 :   if (tis->http_status != por->hr.http_status)
     284              :   {
     285            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     286              :                 "Unexpected response code %u (%d) to command %s\n",
     287              :                 por->hr.http_status,
     288              :                 (int) por->hr.ec,
     289              :                 TALER_TESTING_interpreter_get_current_label (tis->is));
     290            0 :     TALER_TESTING_interpreter_fail (tis->is);
     291           22 :     return;
     292              :   }
     293           38 :   if (0 == tis->http_status)
     294              :   {
     295            0 :     TALER_LOG_DEBUG ("/using_templates, expected 0 status code\n");
     296            0 :     TALER_TESTING_interpreter_next (tis->is);
     297            0 :     return;
     298              :   }
     299              :   // check for order
     300           38 :   switch (por->hr.http_status)
     301              :   {
     302           16 :   case MHD_HTTP_OK:
     303           16 :     tis->pay_deadline = por->details.ok.pay_deadline;
     304           16 :     if (tis->check_pay_duration)
     305              :     {
     306              :       struct GNUNET_TIME_Absolute earliest;
     307              :       struct GNUNET_TIME_Absolute latest;
     308              : 
     309           16 :       earliest = GNUNET_TIME_absolute_subtract (
     310              :         GNUNET_TIME_absolute_add (tis->request_start,
     311              :                                   tis->pay_duration),
     312              :         GNUNET_TIME_UNIT_SECONDS);
     313           16 :       latest = GNUNET_TIME_absolute_add (
     314              :         GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
     315              :                                   tis->pay_duration),
     316              :         GNUNET_TIME_UNIT_SECONDS);
     317           16 :       if ( (GNUNET_TIME_absolute_cmp (tis->pay_deadline.abs_time,
     318              :                                      <,
     319           16 :                                      earliest)) ||
     320           16 :            (GNUNET_TIME_absolute_cmp (tis->pay_deadline.abs_time,
     321              :                                      >,
     322              :                                      latest)) )
     323              :       {
     324            0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     325              :                     "Template pay deadline does not match configured pay duration\n");
     326            0 :         TALER_TESTING_interpreter_fail (tis->is);
     327            0 :         return;
     328              :       }
     329              :     }
     330           16 :     if (NULL != por->details.ok.token)
     331           16 :       tis->claim_token = *por->details.ok.token;
     332           16 :     tis->order_id = GNUNET_strdup (por->details.ok.order_id);
     333           16 :     if ((NULL != tis->expected_order_id) &&
     334            0 :         (0 != strcmp (por->details.ok.order_id,
     335              :                       tis->expected_order_id)))
     336              :     {
     337            0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     338              :                   "Order id assigned does not match\n");
     339            0 :       TALER_TESTING_interpreter_fail (tis->is);
     340            0 :       return;
     341              :     }
     342           16 :     if (NULL != tis->duplicate_of)
     343              :     {
     344              :       const struct TALER_TESTING_Command *order_cmd;
     345              :       const struct TALER_ClaimTokenP *prev_token;
     346            0 :       struct TALER_ClaimTokenP zero_token = {0};
     347              :       const struct TALER_ClaimTokenP *resp_token;
     348              : 
     349            0 :       order_cmd = TALER_TESTING_interpreter_lookup_command (
     350              :         tis->is,
     351              :         tis->duplicate_of);
     352            0 :       if (GNUNET_OK !=
     353            0 :           TALER_TESTING_get_trait_claim_token (order_cmd,
     354              :                                                &prev_token))
     355              :       {
     356            0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     357              :                     "Could not fetch previous order claim token\n");
     358            0 :         TALER_TESTING_interpreter_fail (tis->is);
     359            0 :         return;
     360              :       }
     361              : 
     362            0 :       resp_token = (NULL != por->details.ok.token)
     363              :                    ? por->details.ok.token
     364            0 :                    : &zero_token;
     365            0 :       if (0 != GNUNET_memcmp (prev_token,
     366              :                               resp_token))
     367              :       {
     368            0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     369              :                     "Claim tokens for identical requests do not match\n");
     370            0 :         TALER_TESTING_interpreter_fail (tis->is);
     371            0 :         return;
     372              :       }
     373              :     }
     374           16 :     break;
     375            4 :   case MHD_HTTP_NOT_FOUND:
     376            4 :     TALER_TESTING_interpreter_next (tis->is);
     377            4 :     return;
     378            0 :   case MHD_HTTP_GONE:
     379            0 :     TALER_TESTING_interpreter_next (tis->is);
     380            0 :     return;
     381           18 :   case MHD_HTTP_CONFLICT:
     382           18 :     TALER_TESTING_interpreter_next (tis->is);
     383           18 :     return;
     384            0 :   default:
     385              :     {
     386            0 :       char *s = json_dumps (por->hr.reply,
     387              :                             JSON_COMPACT);
     388            0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     389              :                   "Unexpected status code from /orders: %u (%d) at %s; JSON: %s\n",
     390              :                   por->hr.http_status,
     391              :                   (int) por->hr.ec,
     392              :                   TALER_TESTING_interpreter_get_current_label (tis->is),
     393              :                   s);
     394            0 :       GNUNET_free (s);
     395              :       /**
     396              :        * Not failing, as test cases are _supposed_
     397              :        * to create non 200 OK situations.
     398              :        */
     399            0 :       TALER_TESTING_interpreter_next (tis->is);
     400              :     }
     401            0 :     return;
     402              :   }
     403              : 
     404           16 :   if (! tis->with_claim)
     405              :   {
     406            0 :     TALER_TESTING_interpreter_next (tis->is);
     407            0 :     return;
     408              :   }
     409           16 :   tis->och = TALER_MERCHANT_post_orders_claim_create (
     410              :     TALER_TESTING_interpreter_get_context (tis->is),
     411              :     tis->merchant_url,
     412           16 :     tis->order_id,
     413           16 :     &tis->nonce);
     414           16 :   if (NULL == tis->och)
     415            0 :     TALER_TESTING_FAIL (tis->is);
     416           16 :   TALER_MERCHANT_post_orders_claim_set_options (
     417              :     tis->och,
     418              :     TALER_MERCHANT_post_orders_claim_option_token (
     419              :       &tis->claim_token));
     420              :   {
     421              :     enum TALER_ErrorCode ec;
     422              : 
     423           16 :     ec = TALER_MERCHANT_post_orders_claim_start (tis->och,
     424              :                                                  &using_claim_cb,
     425              :                                                  tis);
     426           16 :     GNUNET_assert (TALER_EC_NONE == ec);
     427              :   }
     428              : }
     429              : 
     430              : 
     431              : /**
     432              :  * Run the "POST /using-templates" CMD.
     433              :  *
     434              :  *
     435              :  * @param cls closure.
     436              :  * @param cmd command being run now.
     437              :  * @param is interpreter state.
     438              :  */
     439              : static void
     440           38 : post_using_templates_run (void *cls,
     441              :                           const struct TALER_TESTING_Command *cmd,
     442              :                           struct TALER_TESTING_Interpreter *is)
     443              : {
     444           38 :   struct PostUsingTemplatesState *tis = cls;
     445              :   const struct TALER_TESTING_Command *ref;
     446              :   const char *template_id;
     447              :   const json_t *template_contract;
     448              : 
     449           38 :   tis->is = is;
     450           38 :   ref = TALER_TESTING_interpreter_lookup_command (is,
     451              :                                                   tis->template_ref);
     452           38 :   if (GNUNET_OK !=
     453           38 :       TALER_TESTING_get_trait_template_id (ref,
     454              :                                            &template_id))
     455            0 :     TALER_TESTING_FAIL (is);
     456           38 :   if (GNUNET_OK !=
     457           38 :       TALER_TESTING_get_trait_template_contract (ref,
     458              :                                                  &template_contract))
     459            0 :     TALER_TESTING_FAIL (is);
     460           38 :   if (tis->have_expected_pay_duration)
     461              :   {
     462              :     tis->check_pay_duration
     463            8 :       = (! GNUNET_TIME_relative_is_zero (tis->pay_duration)) &&
     464            8 :         (! GNUNET_TIME_relative_is_forever (tis->pay_duration));
     465              :   }
     466           34 :   else if (NULL !=
     467           34 :            json_object_get (template_contract,
     468              :                             "pay_duration"))
     469              :   {
     470              :     struct GNUNET_JSON_Specification spec[] = {
     471           34 :       GNUNET_JSON_spec_relative_time ("pay_duration",
     472              :                                       &tis->pay_duration),
     473           34 :       GNUNET_JSON_spec_end ()
     474              :     };
     475              : 
     476           34 :     GNUNET_assert (GNUNET_OK ==
     477              :                    GNUNET_JSON_parse ((json_t *) template_contract,
     478              :                                       spec,
     479              :                                       NULL,
     480              :                                       NULL));
     481              :     tis->check_pay_duration
     482           68 :       = (! GNUNET_TIME_relative_is_zero (tis->pay_duration)) &&
     483           68 :         (! GNUNET_TIME_relative_is_forever (tis->pay_duration));
     484              :   }
     485           38 :   if (NULL != tis->otp_ref)
     486              :   {
     487            2 :     ref = TALER_TESTING_interpreter_lookup_command (is,
     488              :                                                     tis->otp_ref);
     489            2 :     if (GNUNET_OK !=
     490            2 :         TALER_TESTING_get_trait_otp_key (ref,
     491              :                                          &tis->otp_key))
     492            0 :       TALER_TESTING_FAIL (is);
     493            2 :     if (GNUNET_OK !=
     494            2 :         TALER_TESTING_get_trait_otp_alg (ref,
     495              :                                          &tis->otp_alg))
     496            0 :       TALER_TESTING_FAIL (is);
     497              :   }
     498           38 :   GNUNET_CRYPTO_random_block (&tis->nonce,
     499              :                               sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
     500           38 :   tis->iph = TALER_MERCHANT_post_templates_create (
     501              :     TALER_TESTING_interpreter_get_context (is),
     502              :     tis->merchant_url,
     503              :     template_id);
     504           38 :   GNUNET_assert (NULL != tis->iph);
     505           38 :   if (NULL != tis->details)
     506              :   {
     507           20 :     TALER_MERCHANT_post_templates_set_options (
     508              :       tis->iph,
     509              :       TALER_MERCHANT_post_templates_option_details (
     510              :         tis->details));
     511              :   }
     512              :   else
     513              :   {
     514           18 :     if (NULL != tis->summary)
     515           12 :       TALER_MERCHANT_post_templates_set_options (
     516              :         tis->iph,
     517              :         TALER_MERCHANT_post_templates_option_summary (
     518              :           tis->summary));
     519           18 :     if (TALER_amount_is_valid (&tis->amount))
     520           12 :       TALER_MERCHANT_post_templates_set_options (
     521              :         tis->iph,
     522              :         TALER_MERCHANT_post_templates_option_amount (
     523              :           &tis->amount));
     524              :   }
     525              :   {
     526              :     enum TALER_ErrorCode ec;
     527              : 
     528           38 :     tis->request_start = GNUNET_TIME_absolute_get ();
     529           38 :     ec = TALER_MERCHANT_post_templates_start (tis->iph,
     530              :                                               &post_using_templates_cb,
     531              :                                               tis);
     532           38 :     GNUNET_assert (TALER_EC_NONE == ec);
     533              :   }
     534              : }
     535              : 
     536              : 
     537              : /**
     538              :  * Offers information from the POST /using-templates CMD state to other
     539              :  * commands.
     540              :  *
     541              :  * @param cls closure
     542              :  * @param[out] ret result (could be anything)
     543              :  * @param trait name of the trait
     544              :  * @param index index number of the object to extract.
     545              :  * @return #GNUNET_OK on success
     546              :  */
     547              : static enum GNUNET_GenericReturnValue
     548           30 : post_using_templates_traits (void *cls,
     549              :                              const void **ret,
     550              :                              const char *trait,
     551              :                              unsigned int index)
     552              : {
     553           30 :   struct PostUsingTemplatesState *pts = cls;
     554              :   struct TALER_TESTING_Trait traits[] = {
     555           30 :     TALER_TESTING_make_trait_order_id (pts->order_id),
     556           30 :     TALER_TESTING_make_trait_contract_terms (pts->contract_terms),
     557           30 :     TALER_TESTING_make_trait_order_terms (pts->order_terms),
     558           30 :     TALER_TESTING_make_trait_h_contract_terms (&pts->h_contract_terms),
     559           30 :     TALER_TESTING_make_trait_merchant_sig (&pts->merchant_sig),
     560           30 :     TALER_TESTING_make_trait_merchant_pub (&pts->merchant_pub),
     561           30 :     TALER_TESTING_make_trait_claim_nonce (&pts->nonce),
     562           30 :     TALER_TESTING_make_trait_claim_token (&pts->claim_token),
     563           30 :     TALER_TESTING_make_trait_otp_key (pts->otp_key),
     564           30 :     TALER_TESTING_make_trait_otp_alg (pts->otp_alg),
     565           30 :     TALER_TESTING_trait_end (),
     566              :   };
     567              : 
     568              :   (void) pts;
     569           30 :   return TALER_TESTING_get_trait (traits,
     570              :                                   ret,
     571              :                                   trait,
     572              :                                   index);
     573              : }
     574              : 
     575              : 
     576              : /**
     577              :  * Free the state of a "POST using-template" CMD, and possibly
     578              :  * cancel a pending operation thereof.
     579              :  *
     580              :  * @param cls closure.
     581              :  * @param cmd command being run.
     582              :  */
     583              : static void
     584           38 : post_using_templates_cleanup (void *cls,
     585              :                               const struct TALER_TESTING_Command *cmd)
     586              : {
     587           38 :   struct PostUsingTemplatesState *tis = cls;
     588              : 
     589           38 :   if (NULL != tis->iph)
     590              :   {
     591            0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     592              :                 "POST /using-templates operation did not complete\n");
     593            0 :     TALER_MERCHANT_post_templates_cancel (tis->iph);
     594              :   }
     595           38 :   json_decref (tis->order_terms);
     596           38 :   json_decref (tis->contract_terms);
     597           38 :   json_decref (tis->details);
     598           38 :   GNUNET_free (tis->order_id);
     599           38 :   GNUNET_free (tis);
     600           38 : }
     601              : 
     602              : 
     603              : /**
     604              :  * Mark part of the contract terms as possible to forget.
     605              :  *
     606              :  * @param cls pointer to the result of the forget operation.
     607              :  * @param object_id name of the object to forget.
     608              :  * @param parent parent of the object at @e object_id.
     609              :  */
     610              : static void
     611           72 : mark_forgettable (void *cls,
     612              :                   const char *object_id,
     613              :                   json_t *parent)
     614              : {
     615           72 :   GNUNET_assert (GNUNET_OK ==
     616              :                  TALER_JSON_contract_mark_forgettable (parent,
     617              :                                                        object_id));
     618           72 : }
     619              : 
     620              : 
     621              : /**
     622              :  * Constructs the json for a POST using template request.
     623              :  *
     624              :  * @param using_template_id the name of the using_template to add, can be NULL.
     625              :  * @param refund_deadline the deadline for refunds on this using template.
     626              :  * @param pay_deadline the deadline for payment on this using template.
     627              :  * @param amount the amount this using template is for.
     628              :  * @param[out] using_template where to write the json string.
     629              :  */
     630              : static void
     631           18 : make_order_json (const char *using_template_id,
     632              :                  struct GNUNET_TIME_Timestamp refund_deadline,
     633              :                  struct GNUNET_TIME_Timestamp pay_deadline,
     634              :                  const char *amount,
     635              :                  json_t **using_template)
     636              : {
     637           18 :   struct GNUNET_TIME_Timestamp refund = refund_deadline;
     638           18 :   struct GNUNET_TIME_Timestamp pay = pay_deadline;
     639              :   json_t *contract_terms;
     640              :   struct TALER_Amount tamount;
     641              :   json_t *arr;
     642              : 
     643           18 :   if (NULL != amount)
     644           12 :     GNUNET_assert (GNUNET_OK ==
     645              :                    TALER_string_to_amount (amount,
     646              :                                            &tamount));
     647              :   /* Include required fields and some dummy objects to test forgetting. */
     648           18 :   arr = json_array ();
     649           18 :   GNUNET_assert (NULL != arr);
     650           18 :   GNUNET_assert (0 ==
     651              :                  json_array_append_new (
     652              :                    arr,
     653              :                    GNUNET_JSON_PACK (
     654              :                      GNUNET_JSON_pack_string (
     655              :                        "item", "speakers"))));
     656           18 :   GNUNET_assert (0 ==
     657              :                  json_array_append_new (
     658              :                    arr,
     659              :                    GNUNET_JSON_PACK (
     660              :                      GNUNET_JSON_pack_string (
     661              :                        "item", "headphones"))));
     662           18 :   GNUNET_assert (0 ==
     663              :                  json_array_append_new (
     664              :                    arr,
     665              :                    GNUNET_JSON_PACK (
     666              :                      GNUNET_JSON_pack_string (
     667              :                        "item", "earbuds"))));
     668           18 :   contract_terms = GNUNET_JSON_PACK (
     669              :     GNUNET_JSON_pack_string ("summary",
     670              :                              "merchant-lib testcase"),
     671              :     GNUNET_JSON_pack_allow_null (
     672              :       GNUNET_JSON_pack_string (
     673              :         "using_template_id", using_template_id)),
     674              :     GNUNET_JSON_pack_conditional (
     675              :       NULL != amount,
     676              :       TALER_JSON_pack_amount ("amount",
     677              :                               &tamount)),
     678              :     GNUNET_JSON_pack_string ("fulfillment_url",
     679              :                              "https://example.com"),
     680              :     GNUNET_JSON_pack_allow_null (
     681              :       GNUNET_JSON_pack_timestamp ("refund_deadline",
     682              :                                   refund)),
     683              :     GNUNET_JSON_pack_allow_null (
     684              :       GNUNET_JSON_pack_timestamp ("pay_deadline",
     685              :                                   pay)),
     686              :     GNUNET_JSON_pack_string ("dummy_obj",
     687              :                              "EUR:1.0"),
     688              :     GNUNET_JSON_pack_array_steal ("dummy_array",
     689              :                                   arr));
     690           18 :   GNUNET_assert (GNUNET_OK ==
     691              :                  TALER_JSON_expand_path (contract_terms,
     692              :                                          "$.dummy_obj",
     693              :                                          &mark_forgettable,
     694              :                                          NULL));
     695           18 :   GNUNET_assert (GNUNET_OK ==
     696              :                  TALER_JSON_expand_path (contract_terms,
     697              :                                          "$.dummy_array[*].item",
     698              :                                          &mark_forgettable,
     699              :                                          NULL));
     700           18 :   *using_template = contract_terms;
     701           18 : }
     702              : 
     703              : 
     704              : struct TALER_TESTING_Command
     705           18 : TALER_TESTING_cmd_merchant_post_using_templates (
     706              :   const char *label,
     707              :   const char *template_ref,
     708              :   const char *otp_ref,
     709              :   const char *merchant_url,
     710              :   const char *using_template_id,
     711              :   const char *summary,
     712              :   const char *amount,
     713              :   struct GNUNET_TIME_Timestamp refund_deadline,
     714              :   struct GNUNET_TIME_Timestamp pay_deadline,
     715              :   unsigned int http_status)
     716              : {
     717              :   struct PostUsingTemplatesState *tis;
     718              : 
     719           18 :   tis = GNUNET_new (struct PostUsingTemplatesState);
     720           18 :   tis->template_ref = template_ref;
     721           18 :   tis->otp_ref = otp_ref;
     722           18 :   tis->merchant_url = merchant_url;
     723           18 :   tis->using_template_id = using_template_id;
     724           18 :   tis->http_status = http_status;
     725           18 :   tis->summary = summary;
     726           18 :   tis->with_claim = true;
     727           18 :   make_order_json (using_template_id,
     728              :                    refund_deadline,
     729              :                    pay_deadline,
     730              :                    amount,
     731              :                    &tis->order_terms);
     732           18 :   if (NULL != amount)
     733           12 :     GNUNET_assert (GNUNET_OK ==
     734              :                    TALER_string_to_amount (amount,
     735              :                                            &tis->amount));
     736              :   {
     737           18 :     struct TALER_TESTING_Command cmd = {
     738              :       .cls = tis,
     739              :       .label = label,
     740              :       .run = &post_using_templates_run,
     741              :       .cleanup = &post_using_templates_cleanup,
     742              :       .traits = &post_using_templates_traits
     743              :     };
     744              : 
     745           18 :     return cmd;
     746              :   }
     747              : }
     748              : 
     749              : 
     750              : struct TALER_TESTING_Command
     751            4 : TALER_TESTING_cmd_merchant_post_using_templates_with_expected_pay_duration (
     752              :   const char *label,
     753              :   const char *template_ref,
     754              :   const char *otp_ref,
     755              :   const char *merchant_url,
     756              :   const char *using_template_id,
     757              :   const char *summary,
     758              :   const char *amount,
     759              :   struct GNUNET_TIME_Timestamp refund_deadline,
     760              :   struct GNUNET_TIME_Timestamp pay_deadline,
     761              :   struct GNUNET_TIME_Relative expected_pay_duration,
     762              :   unsigned int http_status)
     763              : {
     764              :   struct TALER_TESTING_Command cmd;
     765              :   struct PostUsingTemplatesState *tis;
     766              : 
     767            4 :   cmd = TALER_TESTING_cmd_merchant_post_using_templates (
     768              :     label,
     769              :     template_ref,
     770              :     otp_ref,
     771              :     merchant_url,
     772              :     using_template_id,
     773              :     summary,
     774              :     amount,
     775              :     refund_deadline,
     776              :     pay_deadline,
     777              :     http_status);
     778            4 :   tis = cmd.cls;
     779            4 :   tis->pay_duration = expected_pay_duration;
     780            4 :   tis->have_expected_pay_duration = true;
     781            4 :   return cmd;
     782              : }
     783              : 
     784              : 
     785              : struct TALER_TESTING_Command
     786           20 : TALER_TESTING_cmd_merchant_post_using_templates2 (
     787              :   const char *label,
     788              :   const char *template_ref,
     789              :   const char *otp_ref,
     790              :   const char *merchant_url,
     791              :   const char *using_template_id,
     792              :   const json_t *details,
     793              :   unsigned int http_status)
     794              : {
     795              :   struct PostUsingTemplatesState *tis;
     796              : 
     797           20 :   tis = GNUNET_new (struct PostUsingTemplatesState);
     798           20 :   tis->template_ref = template_ref;
     799           20 :   tis->otp_ref = otp_ref;
     800           20 :   tis->merchant_url = merchant_url;
     801           20 :   tis->using_template_id = using_template_id;
     802           20 :   tis->http_status = http_status;
     803           20 :   tis->with_claim = true;
     804           20 :   if (NULL != details)
     805           20 :     tis->details = json_incref ((json_t *) details);
     806              :   {
     807           20 :     struct TALER_TESTING_Command cmd = {
     808              :       .cls = tis,
     809              :       .label = label,
     810              :       .run = &post_using_templates_run,
     811              :       .cleanup = &post_using_templates_cleanup,
     812              :       .traits = &post_using_templates_traits
     813              :     };
     814              : 
     815           20 :     return cmd;
     816              :   }
     817              : }
     818              : 
     819              : 
     820              : /* end of testing_api_cmd_post_using_templates.c */
        

Generated by: LCOV version 2.0-1