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: 169 228 74.1 %
Date: 2021-08-30 06:54:17 Functions: 11 11 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14