LCOV - code coverage report
Current view: top level - testing - testing_api_cmd_post_orders.c (source / functions) Hit Total Coverage
Test: GNU Taler merchant coverage report Lines: 0 220 0.0 %
Date: 2022-06-30 06:15:34 Functions: 0 11 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2014-2021 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             : /**
      21             :  * @file testing_api_cmd_post_orders.c
      22             :  * @brief command to run POST /orders
      23             :  * @author Marcello Stanisci
      24             :  */
      25             : 
      26             : #include "platform.h"
      27             : #include <taler/taler_exchange_service.h>
      28             : #include <taler/taler_testing_lib.h>
      29             : #include "taler_merchant_service.h"
      30             : #include "taler_merchant_testing_lib.h"
      31             : 
      32             : /**
      33             :  * State for a "POST /orders" CMD.
      34             :  */
      35             : struct OrdersState
      36             : {
      37             : 
      38             :   /**
      39             :    * Expected status code.
      40             :    */
      41             :   unsigned int http_status;
      42             : 
      43             :   /**
      44             :    * Order id.
      45             :    */
      46             :   const char *order_id;
      47             : 
      48             :   /**
      49             :    * The order id we expect the merchant to assign (if not NULL).
      50             :    */
      51             :   const char *expected_order_id;
      52             : 
      53             :   /**
      54             :    * Contract terms obtained from the backend.
      55             :    */
      56             :   json_t *contract_terms;
      57             : 
      58             :   /**
      59             :    * Order submitted to the backend.
      60             :    */
      61             :   json_t *order_terms;
      62             : 
      63             :   /**
      64             :    * Contract terms hash code.
      65             :    */
      66             :   struct TALER_PrivateContractHashP h_contract_terms;
      67             : 
      68             :   /**
      69             :    * The /orders operation handle.
      70             :    */
      71             :   struct TALER_MERCHANT_PostOrdersHandle *po;
      72             : 
      73             :   /**
      74             :    * The (initial) POST /orders/$ID/claim operation handle.
      75             :    * The logic is such that after an order creation,
      76             :    * we immediately claim the order.
      77             :    */
      78             :   struct TALER_MERCHANT_OrderClaimHandle *och;
      79             : 
      80             :   /**
      81             :    * The nonce.
      82             :    */
      83             :   struct GNUNET_CRYPTO_EddsaPublicKey nonce;
      84             : 
      85             :   /**
      86             :    * Whether to generate a claim token.
      87             :    */
      88             :   bool make_claim_token;
      89             : 
      90             :   /**
      91             :    * The claim token
      92             :    */
      93             :   struct TALER_ClaimTokenP claim_token;
      94             : 
      95             :   /**
      96             :    * URL of the merchant backend.
      97             :    */
      98             :   const char *merchant_url;
      99             : 
     100             :   /**
     101             :    * The interpreter state.
     102             :    */
     103             :   struct TALER_TESTING_Interpreter *is;
     104             : 
     105             :   /**
     106             :    * Merchant signature over the orders.
     107             :    */
     108             :   struct TALER_MerchantSignatureP merchant_sig;
     109             : 
     110             :   /**
     111             :    * Merchant public key.
     112             :    */
     113             :   struct TALER_MerchantPublicKeyP merchant_pub;
     114             : 
     115             :   /**
     116             :    * The payment target for the order
     117             :    */
     118             :   const char *payment_target;
     119             : 
     120             :   /**
     121             :    * The products the order is purchasing.
     122             :    */
     123             :   const char *products;
     124             : 
     125             :   /**
     126             :    * The locks that the order should release.
     127             :    */
     128             :   const char *locks;
     129             : 
     130             :   /**
     131             :    * Should the command also CLAIM the order?
     132             :    */
     133             :   bool with_claim;
     134             : 
     135             :   /**
     136             :    * If not NULL, the command should duplicate the request and verify the
     137             :    * response is the same as in this command.
     138             :    */
     139             :   const char *duplicate_of;
     140             : };
     141             : 
     142             : 
     143             : /**
     144             :  * Offer internal data to other commands.
     145             :  *
     146             :  * @param cls closure
     147             :  * @param[out] ret result (could be anything)
     148             :  * @param trait name of the trait
     149             :  * @param index index number of the object to extract.
     150             :  * @return #GNUNET_OK on success
     151             :  */
     152             : static enum GNUNET_GenericReturnValue
     153           0 : orders_traits (void *cls,
     154             :                const void **ret,
     155             :                const char *trait,
     156             :                unsigned int index)
     157             : {
     158           0 :   struct OrdersState *ps = cls;
     159             :   struct TALER_TESTING_Trait traits[] = {
     160           0 :     TALER_TESTING_make_trait_order_id (&ps->order_id),
     161           0 :     TALER_TESTING_make_trait_contract_terms (ps->contract_terms),
     162           0 :     TALER_TESTING_make_trait_order_terms (ps->order_terms),
     163           0 :     TALER_TESTING_make_trait_h_contract_terms (&ps->h_contract_terms),
     164           0 :     TALER_TESTING_make_trait_merchant_sig (&ps->merchant_sig),
     165           0 :     TALER_TESTING_make_trait_merchant_pub (&ps->merchant_pub),
     166           0 :     TALER_TESTING_make_trait_claim_nonce (&ps->nonce),
     167           0 :     TALER_TESTING_make_trait_claim_token (&ps->claim_token),
     168           0 :     TALER_TESTING_trait_end ()
     169             :   };
     170             : 
     171           0 :   return TALER_TESTING_get_trait (traits,
     172             :                                   ret,
     173             :                                   trait,
     174             :                                   index);
     175             : }
     176             : 
     177             : 
     178             : /**
     179             :  * Used to fill the "orders" CMD state with backend-provided
     180             :  * values.  Also double-checks that the order was correctly
     181             :  * created.
     182             :  *
     183             :  * @param cls closure
     184             :  * @param hr HTTP response we got
     185             :  * @param contract_terms contract terms of this order
     186             :  * @param sig merchant's signature
     187             :  * @param hash hash over the contract
     188             :  */
     189             : static void
     190           0 : orders_claim_cb (void *cls,
     191             :                  const struct TALER_MERCHANT_HttpResponse *hr,
     192             :                  const json_t *contract_terms,
     193             :                  const struct TALER_MerchantSignatureP *sig,
     194             :                  const struct TALER_PrivateContractHashP *hash)
     195             : {
     196           0 :   struct OrdersState *ps = cls;
     197             :   struct TALER_MerchantPublicKeyP merchant_pub;
     198             :   const char *error_name;
     199             :   unsigned int error_line;
     200             :   struct GNUNET_JSON_Specification spec[] = {
     201           0 :     GNUNET_JSON_spec_fixed_auto ("merchant_pub",
     202             :                                  &merchant_pub),
     203           0 :     GNUNET_JSON_spec_end ()
     204             :   };
     205             : 
     206           0 :   ps->och = NULL;
     207           0 :   if (ps->http_status != hr->http_status)
     208           0 :     TALER_TESTING_FAIL (ps->is);
     209             : 
     210           0 :   ps->contract_terms = json_deep_copy (contract_terms);
     211           0 :   ps->h_contract_terms = *hash;
     212           0 :   ps->merchant_sig = *sig;
     213           0 :   if (GNUNET_OK !=
     214           0 :       GNUNET_JSON_parse (contract_terms,
     215             :                          spec,
     216             :                          &error_name,
     217             :                          &error_line))
     218             :   {
     219             :     char *log;
     220             : 
     221           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     222             :                 "Parser failed on %s:%u\n",
     223             :                 error_name,
     224             :                 error_line);
     225           0 :     log = json_dumps (ps->contract_terms,
     226             :                       JSON_INDENT (1));
     227           0 :     fprintf (stderr,
     228             :              "%s\n",
     229             :              log);
     230           0 :     free (log);
     231           0 :     TALER_TESTING_FAIL (ps->is);
     232             :   }
     233           0 :   ps->merchant_pub = merchant_pub;
     234           0 :   TALER_TESTING_interpreter_next (ps->is);
     235             : }
     236             : 
     237             : 
     238             : /**
     239             :  * Callback that processes the response following a
     240             :  * POST /orders.  NOTE: no contract terms are included
     241             :  * here; they need to be taken via the "orders lookup"
     242             :  * method.
     243             :  *
     244             :  * @param cls closure.
     245             :  * @param por details about the response
     246             :  */
     247             : static void
     248           0 : order_cb (void *cls,
     249             :           const struct TALER_MERCHANT_PostOrdersReply *por)
     250             : {
     251           0 :   struct OrdersState *ps = cls;
     252             : 
     253           0 :   ps->po = NULL;
     254           0 :   if (ps->http_status != por->hr.http_status)
     255             :   {
     256           0 :     TALER_LOG_ERROR ("Given vs expected: %u(%d) vs %u\n",
     257             :                      por->hr.http_status,
     258             :                      (int) por->hr.ec,
     259             :                      ps->http_status);
     260           0 :     TALER_TESTING_FAIL (ps->is);
     261             :   }
     262           0 :   if (0 == ps->http_status)
     263             :   {
     264           0 :     TALER_LOG_DEBUG ("/orders, expected 0 status code\n");
     265           0 :     TALER_TESTING_interpreter_next (ps->is);
     266           0 :     return;
     267             :   }
     268           0 :   switch (por->hr.http_status)
     269             :   {
     270           0 :   case MHD_HTTP_OK:
     271           0 :     if (NULL != por->details.ok.token)
     272           0 :       ps->claim_token = *por->details.ok.token;
     273           0 :     ps->order_id = GNUNET_strdup (por->details.ok.order_id);
     274           0 :     if ((NULL != ps->expected_order_id) &&
     275           0 :         (0 != strcmp (por->details.ok.order_id,
     276             :                       ps->expected_order_id)))
     277             :     {
     278           0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     279             :                   "Order id assigned does not match\n");
     280           0 :       TALER_TESTING_interpreter_fail (ps->is);
     281           0 :       return;
     282             :     }
     283           0 :     if (NULL != ps->duplicate_of)
     284             :     {
     285             :       const struct TALER_TESTING_Command *order_cmd;
     286             :       const struct TALER_ClaimTokenP *prev_token;
     287           0 :       struct TALER_ClaimTokenP zero_token = {0};
     288             : 
     289           0 :       order_cmd = TALER_TESTING_interpreter_lookup_command (
     290             :         ps->is,
     291             :         ps->duplicate_of);
     292           0 :       if (GNUNET_OK !=
     293           0 :           TALER_TESTING_get_trait_claim_token (order_cmd,
     294             :                                                &prev_token))
     295             :       {
     296           0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     297             :                     "Could not fetch previous order claim token\n");
     298           0 :         TALER_TESTING_interpreter_fail (ps->is);
     299           0 :         return;
     300             :       }
     301           0 :       if (NULL == por->details.ok.token)
     302           0 :         prev_token = &zero_token;
     303           0 :       if (0 != GNUNET_memcmp (prev_token,
     304             :                               por->details.ok.token))
     305             :       {
     306           0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     307             :                     "Claim tokens for identical requests do not match\n");
     308           0 :         TALER_TESTING_interpreter_fail (ps->is);
     309           0 :         return;
     310             :       }
     311             :     }
     312           0 :     break;
     313           0 :   case MHD_HTTP_NOT_FOUND:
     314           0 :     TALER_TESTING_interpreter_next (ps->is);
     315           0 :     return;
     316           0 :   case MHD_HTTP_GONE:
     317           0 :     TALER_TESTING_interpreter_next (ps->is);
     318           0 :     return;
     319           0 :   case MHD_HTTP_CONFLICT:
     320           0 :     TALER_TESTING_interpreter_next (ps->is);
     321           0 :     return;
     322           0 :   default:
     323             :     {
     324           0 :       char *s = json_dumps (por->hr.reply,
     325             :                             JSON_COMPACT);
     326           0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     327             :                   "Unexpected status code from /orders: %u (%d) at %s; JSON: %s\n",
     328             :                   por->hr.http_status,
     329             :                   (int) por->hr.ec,
     330             :                   TALER_TESTING_interpreter_get_current_label (ps->is),
     331             :                   s);
     332           0 :       GNUNET_free (s);
     333             :       /**
     334             :        * Not failing, as test cases are _supposed_
     335             :        * to create non 200 OK situations.
     336             :        */
     337           0 :       TALER_TESTING_interpreter_next (ps->is);
     338             :     }
     339           0 :     return;
     340             :   }
     341             : 
     342           0 :   if (! ps->with_claim)
     343             :   {
     344           0 :     TALER_TESTING_interpreter_next (ps->is);
     345           0 :     return;
     346             :   }
     347           0 :   if (NULL ==
     348           0 :       (ps->och = TALER_MERCHANT_order_claim (ps->is->ctx,
     349             :                                              ps->merchant_url,
     350             :                                              ps->order_id,
     351           0 :                                              &ps->nonce,
     352           0 :                                              &ps->claim_token,
     353             :                                              &orders_claim_cb,
     354             :                                              ps)))
     355           0 :     TALER_TESTING_FAIL (ps->is);
     356             : }
     357             : 
     358             : 
     359             : /**
     360             :  * Run a "orders" CMD.
     361             :  *
     362             :  * @param cls closure.
     363             :  * @param cmd command currently being run.
     364             :  * @param is interpreter state.
     365             :  */
     366             : static void
     367           0 : orders_run (void *cls,
     368             :             const struct TALER_TESTING_Command *cmd,
     369             :             struct TALER_TESTING_Interpreter *is)
     370             : {
     371           0 :   struct OrdersState *ps = cls;
     372             : 
     373           0 :   ps->is = is;
     374           0 :   if (NULL == json_object_get (ps->order_terms,
     375             :                                "order_id"))
     376             :   {
     377             :     struct GNUNET_TIME_Absolute now;
     378             :     char *order_id;
     379             : 
     380           0 :     now = GNUNET_TIME_absolute_get_monotonic (is->cfg);
     381           0 :     order_id = GNUNET_STRINGS_data_to_string_alloc (
     382             :       &now,
     383             :       sizeof (now));
     384           0 :     GNUNET_assert (0 ==
     385             :                    json_object_set_new (ps->order_terms,
     386             :                                         "order_id",
     387             :                                         json_string (order_id)));
     388           0 :     GNUNET_free (order_id);
     389             :   }
     390           0 :   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
     391           0 :                               &ps->nonce,
     392             :                               sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
     393           0 :   ps->po = TALER_MERCHANT_orders_post (is->ctx,
     394             :                                        ps->merchant_url,
     395           0 :                                        ps->order_terms,
     396           0 :                                        GNUNET_TIME_UNIT_ZERO,
     397             :                                        &order_cb,
     398             :                                        ps);
     399           0 :   GNUNET_assert (NULL != ps->po);
     400           0 : }
     401             : 
     402             : 
     403             : /**
     404             :  * Run a "orders" CMD.
     405             :  *
     406             :  * @param cls closure.
     407             :  * @param cmd command currently being run.
     408             :  * @param is interpreter state.
     409             :  */
     410             : static void
     411           0 : orders_run2 (void *cls,
     412             :              const struct TALER_TESTING_Command *cmd,
     413             :              struct TALER_TESTING_Interpreter *is)
     414             : {
     415           0 :   struct OrdersState *ps = cls;
     416             :   const json_t *order;
     417           0 :   char *products_string = GNUNET_strdup (ps->products);
     418           0 :   char *locks_string = GNUNET_strdup (ps->locks);
     419             :   char *token;
     420           0 :   struct TALER_MERCHANT_InventoryProduct *products = NULL;
     421           0 :   unsigned int products_length = 0;
     422           0 :   const char **locks = NULL;
     423           0 :   unsigned int locks_length = 0;
     424             : 
     425           0 :   ps->is = is;
     426           0 :   if (NULL != ps->duplicate_of)
     427             :   {
     428             :     const struct TALER_TESTING_Command *order_cmd;
     429             :     const json_t *ct;
     430             : 
     431           0 :     order_cmd = TALER_TESTING_interpreter_lookup_command (
     432             :       is,
     433             :       ps->duplicate_of);
     434           0 :     if (GNUNET_OK !=
     435           0 :         TALER_TESTING_get_trait_order_terms (order_cmd,
     436             :                                              &ct))
     437             :     {
     438           0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     439             :                   "Could not fetch previous order string\n");
     440           0 :       TALER_TESTING_interpreter_fail (is);
     441           0 :       return;
     442             :     }
     443           0 :     order = (json_t *) ct;
     444             :   }
     445             :   else
     446             :   {
     447           0 :     if (NULL == json_object_get (ps->order_terms,
     448             :                                  "order_id"))
     449             :     {
     450             :       struct GNUNET_TIME_Absolute now;
     451             :       char *order_id;
     452             : 
     453           0 :       now = GNUNET_TIME_absolute_get_monotonic (is->cfg);
     454           0 :       order_id = GNUNET_STRINGS_data_to_string_alloc (
     455             :         &now.abs_value_us,
     456             :         sizeof (now.abs_value_us));
     457           0 :       GNUNET_assert (0 ==
     458             :                      json_object_set_new (ps->order_terms,
     459             :                                           "order_id",
     460             :                                           json_string (order_id)));
     461           0 :       GNUNET_free (order_id);
     462             :     }
     463           0 :     order = ps->order_terms;
     464             :   }
     465           0 :   if (NULL == order)
     466             :   {
     467           0 :     GNUNET_break (0);
     468           0 :     TALER_TESTING_interpreter_fail (is);
     469           0 :     return;
     470             :   }
     471             : 
     472           0 :   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
     473           0 :                               &ps->nonce,
     474             :                               sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
     475           0 :   for (token = strtok (products_string, ";");
     476             :        NULL != token;
     477           0 :        token = strtok (NULL, ";"))
     478             :   {
     479             :     char *ctok;
     480             :     struct TALER_MERCHANT_InventoryProduct pd;
     481             : 
     482             :     /* Token syntax is "[product_id]/[quantity]" */
     483           0 :     ctok = strchr (token, '/');
     484           0 :     if (NULL != ctok)
     485             :     {
     486           0 :       *ctok = '\0';
     487           0 :       ctok++;
     488           0 :       if (1 != sscanf (ctok,
     489             :                        "%u",
     490             :                        &pd.quantity))
     491             :       {
     492           0 :         GNUNET_break (0);
     493           0 :         break;
     494             :       }
     495             :     }
     496             :     else
     497             :     {
     498           0 :       pd.quantity = 1;
     499             :     }
     500           0 :     pd.product_id = token;
     501             : 
     502           0 :     GNUNET_array_append (products,
     503             :                          products_length,
     504             :                          pd);
     505             :   }
     506           0 :   for (token = strtok (locks_string, ";");
     507             :        NULL != token;
     508           0 :        token = strtok (NULL, ";"))
     509             :   {
     510             :     const struct TALER_TESTING_Command *lock_cmd;
     511             :     const char **uuid;
     512             : 
     513           0 :     lock_cmd = TALER_TESTING_interpreter_lookup_command (
     514             :       is,
     515             :       token);
     516             : 
     517           0 :     if (GNUNET_OK !=
     518           0 :         TALER_TESTING_get_trait_lock_uuid (lock_cmd,
     519             :                                            &uuid))
     520             :     {
     521           0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     522             :                   "Could not fetch lock uuid\n");
     523           0 :       TALER_TESTING_interpreter_fail (is);
     524           0 :       return;
     525             :     }
     526             : 
     527           0 :     GNUNET_array_append (locks,
     528             :                          locks_length,
     529             :                          *uuid);
     530             :   }
     531           0 :   ps->po = TALER_MERCHANT_orders_post2 (is->ctx,
     532             :                                         ps->merchant_url,
     533             :                                         order,
     534           0 :                                         GNUNET_TIME_UNIT_ZERO,
     535             :                                         ps->payment_target,
     536             :                                         products_length,
     537             :                                         products,
     538             :                                         locks_length,
     539             :                                         locks,
     540           0 :                                         ps->make_claim_token,
     541             :                                         &order_cb,
     542             :                                         ps);
     543           0 :   GNUNET_free (products_string);
     544           0 :   GNUNET_free (locks_string);
     545           0 :   GNUNET_array_grow (products,
     546             :                      products_length,
     547             :                      0);
     548           0 :   GNUNET_array_grow (locks,
     549             :                      locks_length,
     550             :                      0);
     551           0 :   GNUNET_assert (NULL != ps->po);
     552             : }
     553             : 
     554             : 
     555             : /**
     556             :  * Free the state of a "orders" CMD, and possibly
     557             :  * cancel it if it did not complete.
     558             :  *
     559             :  * @param cls closure.
     560             :  * @param cmd command being freed.
     561             :  */
     562             : static void
     563           0 : orders_cleanup (void *cls,
     564             :                 const struct TALER_TESTING_Command *cmd)
     565             : {
     566           0 :   struct OrdersState *ps = cls;
     567             : 
     568           0 :   if (NULL != ps->po)
     569             :   {
     570           0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     571             :                 "Command '%s' did not complete (orders put)\n",
     572             :                 cmd->label);
     573           0 :     TALER_MERCHANT_orders_post_cancel (ps->po);
     574           0 :     ps->po = NULL;
     575             :   }
     576             : 
     577           0 :   if (NULL != ps->och)
     578             :   {
     579           0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     580             :                 "Command '%s' did not complete (orders lookup)\n",
     581             :                 cmd->label);
     582           0 :     TALER_MERCHANT_order_claim_cancel (ps->och);
     583           0 :     ps->och = NULL;
     584             :   }
     585             : 
     586           0 :   json_decref (ps->contract_terms);
     587           0 :   json_decref (ps->order_terms);
     588           0 :   GNUNET_free_nz ((void *) ps->order_id);
     589           0 :   GNUNET_free (ps);
     590           0 : }
     591             : 
     592             : 
     593             : /**
     594             :  * Mark part of the contract terms as possible to forget.
     595             :  *
     596             :  * @param cls pointer to the result of the forget operation.
     597             :  * @param object_id name of the object to forget.
     598             :  * @param parent parent of the object at @e object_id.
     599             :  */
     600             : static void
     601           0 : mark_forgettable (void *cls,
     602             :                   const char *object_id,
     603             :                   json_t *parent)
     604             : {
     605           0 :   GNUNET_assert (GNUNET_OK ==
     606             :                  TALER_JSON_contract_mark_forgettable (parent,
     607             :                                                        object_id));
     608           0 : }
     609             : 
     610             : 
     611             : /**
     612             :  * Constructs the json for a POST order request.
     613             :  *
     614             :  * @param order_id the name of the order to add, can be NULL.
     615             :  * @param refund_deadline the deadline for refunds on this order.
     616             :  * @param pay_deadline the deadline for payment on this order.
     617             :  * @param amount the amount this order is for.
     618             :  * @param[out] order where to write the json string.
     619             :  */
     620             : static void
     621           0 : make_order_json (const char *order_id,
     622             :                  struct GNUNET_TIME_Timestamp refund_deadline,
     623             :                  struct GNUNET_TIME_Timestamp pay_deadline,
     624             :                  const char *amount,
     625             :                  json_t **order)
     626             : {
     627           0 :   struct GNUNET_TIME_Timestamp refund = refund_deadline;
     628           0 :   struct GNUNET_TIME_Timestamp pay = pay_deadline;
     629             :   json_t *contract_terms;
     630             : 
     631             :   /* Include required fields and some dummy objects to test forgetting. */
     632           0 :   contract_terms = json_pack (
     633             :     "{s:s, s:s?, s:s, s:s, s:o, s:o, s:s, s:[{s:s}, {s:s}, {s:s}]}",
     634             :     "summary", "merchant-lib testcase",
     635             :     "order_id", order_id,
     636             :     "amount", amount,
     637             :     "fulfillment_url", "https://example.com",
     638             :     "refund_deadline", GNUNET_JSON_from_timestamp (refund),
     639             :     "pay_deadline", GNUNET_JSON_from_timestamp (pay),
     640             :     "dummy_obj", "EUR:1.0",
     641             :     "dummy_array", /* For testing forgetting parts of arrays */
     642             :     "item", "speakers",
     643             :     "item", "headphones",
     644             :     "item", "earbuds"
     645             :     );
     646           0 :   GNUNET_assert (GNUNET_OK ==
     647             :                  TALER_JSON_expand_path (contract_terms,
     648             :                                          "$.dummy_obj",
     649             :                                          &mark_forgettable,
     650             :                                          NULL));
     651           0 :   GNUNET_assert (GNUNET_OK ==
     652             :                  TALER_JSON_expand_path (contract_terms,
     653             :                                          "$.dummy_array[*].item",
     654             :                                          &mark_forgettable,
     655             :                                          NULL));
     656           0 :   *order = contract_terms;
     657           0 : }
     658             : 
     659             : 
     660             : struct TALER_TESTING_Command
     661           0 : TALER_TESTING_cmd_merchant_post_orders_no_claim (
     662             :   const char *label,
     663             :   const char *merchant_url,
     664             :   unsigned int http_status,
     665             :   const char *order_id,
     666             :   struct GNUNET_TIME_Timestamp refund_deadline,
     667             :   struct GNUNET_TIME_Timestamp pay_deadline,
     668             :   const char *amount)
     669             : {
     670             :   struct OrdersState *ps;
     671             : 
     672           0 :   ps = GNUNET_new (struct OrdersState);
     673           0 :   make_order_json (order_id,
     674             :                    refund_deadline,
     675             :                    pay_deadline,
     676             :                    amount,
     677             :                    &ps->order_terms);
     678           0 :   ps->http_status = http_status;
     679           0 :   ps->expected_order_id = order_id;
     680           0 :   ps->merchant_url = merchant_url;
     681           0 :   ps->with_claim = false;
     682             :   {
     683           0 :     struct TALER_TESTING_Command cmd = {
     684             :       .cls = ps,
     685             :       .label = label,
     686             :       .run = &orders_run,
     687             :       .cleanup = &orders_cleanup,
     688             :       .traits = &orders_traits
     689             :     };
     690             : 
     691           0 :     return cmd;
     692             :   }
     693             : }
     694             : 
     695             : 
     696             : struct TALER_TESTING_Command
     697           0 : TALER_TESTING_cmd_merchant_post_orders (
     698             :   const char *label,
     699             :   const char *merchant_url,
     700             :   unsigned int http_status,
     701             :   const char *order_id,
     702             :   struct GNUNET_TIME_Timestamp refund_deadline,
     703             :   struct GNUNET_TIME_Timestamp pay_deadline,
     704             :   const char *amount)
     705             : {
     706             :   struct OrdersState *ps;
     707             : 
     708           0 :   ps = GNUNET_new (struct OrdersState);
     709           0 :   make_order_json (order_id,
     710             :                    refund_deadline,
     711             :                    pay_deadline,
     712             :                    amount,
     713             :                    &ps->order_terms);
     714           0 :   ps->http_status = http_status;
     715           0 :   ps->expected_order_id = order_id;
     716           0 :   ps->merchant_url = merchant_url;
     717           0 :   ps->with_claim = true;
     718             :   {
     719           0 :     struct TALER_TESTING_Command cmd = {
     720             :       .cls = ps,
     721             :       .label = label,
     722             :       .run = &orders_run,
     723             :       .cleanup = &orders_cleanup,
     724             :       .traits = &orders_traits
     725             :     };
     726             : 
     727           0 :     return cmd;
     728             :   }
     729             : }
     730             : 
     731             : 
     732             : struct TALER_TESTING_Command
     733           0 : TALER_TESTING_cmd_merchant_post_orders2 (
     734             :   const char *label,
     735             :   const char *merchant_url,
     736             :   unsigned int http_status,
     737             :   const char *order_id,
     738             :   struct GNUNET_TIME_Timestamp refund_deadline,
     739             :   struct GNUNET_TIME_Timestamp pay_deadline,
     740             :   bool claim_token,
     741             :   const char *amount,
     742             :   const char *payment_target,
     743             :   const char *products,
     744             :   const char *locks,
     745             :   const char *duplicate_of)
     746             : {
     747             :   struct OrdersState *ps;
     748             : 
     749           0 :   ps = GNUNET_new (struct OrdersState);
     750           0 :   make_order_json (order_id,
     751             :                    refund_deadline,
     752             :                    pay_deadline,
     753             :                    amount,
     754             :                    &ps->order_terms);
     755           0 :   ps->http_status = http_status;
     756           0 :   ps->expected_order_id = order_id;
     757           0 :   ps->merchant_url = merchant_url;
     758           0 :   ps->payment_target = payment_target;
     759           0 :   ps->products = products;
     760           0 :   ps->locks = locks;
     761           0 :   ps->with_claim = (NULL == duplicate_of);
     762           0 :   ps->make_claim_token = claim_token;
     763           0 :   ps->duplicate_of = duplicate_of;
     764             :   {
     765           0 :     struct TALER_TESTING_Command cmd = {
     766             :       .cls = ps,
     767             :       .label = label,
     768             :       .run = &orders_run2,
     769             :       .cleanup = &orders_cleanup,
     770             :       .traits = &orders_traits
     771             :     };
     772             : 
     773           0 :     return cmd;
     774             :   }
     775             : }

Generated by: LCOV version 1.14