testing_api_cmd_lock_product.c (7711B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2020 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_lock_product.c 21 * @brief command to test LOCK /product 22 * @author Christian Grothoff 23 */ 24 #include "platform.h" 25 struct LockProductState; 26 #define TALER_MERCHANT_POST_PRIVATE_PRODUCTS_LOCK_RESULT_CLOSURE struct LockProductState 27 #include <taler/taler_exchange_service.h> 28 #include <taler/taler_testing_lib.h> 29 #include "taler/taler_merchant_service.h" 30 #include "taler/taler_merchant_testing_lib.h" 31 #include <taler/merchant/post-private-products-PRODUCT_ID-lock.h> 32 33 34 /** 35 * State of a "POST /products/$ID" CMD. 36 */ 37 struct LockProductState 38 { 39 40 /** 41 * Handle for a "GET product" request. 42 */ 43 struct TALER_MERCHANT_PostPrivateProductsLockHandle *iph; 44 45 /** 46 * The interpreter state. 47 */ 48 struct TALER_TESTING_Interpreter *is; 49 50 /** 51 * Base URL of the merchant serving the request. 52 */ 53 const char *merchant_url; 54 55 /** 56 * ID of the product to run GET for. 57 */ 58 const char *product_id; 59 60 /** 61 * UUID that identifies the client holding the lock 62 */ 63 char *uuid; 64 65 /** 66 * duration how long should the lock be held 67 */ 68 struct GNUNET_TIME_Relative duration; 69 70 /** 71 * how much product should be locked 72 */ 73 uint32_t quantity; 74 75 /** 76 * Fractional component of the quantity (units of 1/TALER_MERCHANT_UNIT_FRAC_BASE) when 77 * @e use_fractional_quantity is true. 78 */ 79 uint32_t quantity_frac; 80 81 /** 82 * Set to true if @e quantity_frac should be sent along with @e quantity. 83 */ 84 bool use_fractional_quantity; 85 86 /** 87 * Expected HTTP response code. 88 */ 89 unsigned int http_status; 90 91 }; 92 93 94 /** 95 * Callback for a POST /products/$ID/lock operation. 96 * 97 * @param cls closure for this function 98 * @param plr response being processed 99 */ 100 static void 101 lock_product_cb (struct LockProductState *pis, 102 const struct TALER_MERCHANT_PostPrivateProductsLockResponse * 103 plr) 104 { 105 106 pis->iph = NULL; 107 if (pis->http_status != plr->hr.http_status) 108 { 109 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 110 "Unexpected response code %u (%d) to command %s\n", 111 plr->hr.http_status, 112 (int) plr->hr.ec, 113 TALER_TESTING_interpreter_get_current_label (pis->is)); 114 TALER_TESTING_interpreter_fail (pis->is); 115 return; 116 } 117 switch (plr->hr.http_status) 118 { 119 case MHD_HTTP_NO_CONTENT: 120 break; 121 case MHD_HTTP_FORBIDDEN: 122 break; 123 case MHD_HTTP_NOT_FOUND: 124 break; 125 case MHD_HTTP_GONE: 126 break; 127 default: 128 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 129 "Unhandled HTTP status %u for lock product.\n", 130 plr->hr.http_status); 131 } 132 TALER_TESTING_interpreter_next (pis->is); 133 } 134 135 136 /** 137 * Run the "LOCK /products/$ID" CMD. 138 * 139 * 140 * @param cls closure. 141 * @param cmd command being run now. 142 * @param is interpreter state. 143 */ 144 static void 145 lock_product_run (void *cls, 146 const struct TALER_TESTING_Command *cmd, 147 struct TALER_TESTING_Interpreter *is) 148 { 149 struct LockProductState *pis = cls; 150 151 pis->is = is; 152 pis->iph = TALER_MERCHANT_post_private_products_lock_create ( 153 TALER_TESTING_interpreter_get_context (is), 154 pis->merchant_url, 155 pis->product_id, 156 pis->uuid, 157 pis->duration, 158 pis->quantity); 159 if (pis->use_fractional_quantity) 160 TALER_MERCHANT_post_private_products_lock_set_options ( 161 pis->iph, 162 TALER_MERCHANT_post_private_products_lock_option_quantity_frac ( 163 pis->quantity_frac), 164 TALER_MERCHANT_post_private_products_lock_option_use_frac_quantity ()); 165 { 166 enum TALER_ErrorCode ec; 167 168 ec = TALER_MERCHANT_post_private_products_lock_start ( 169 pis->iph, 170 &lock_product_cb, 171 pis); 172 GNUNET_assert (TALER_EC_NONE == ec); 173 } 174 } 175 176 177 /** 178 * Free the state of a "GET product" CMD, and possibly 179 * cancel a pending operation thereof. 180 * 181 * @param cls closure. 182 * @param cmd command being run. 183 */ 184 static void 185 lock_product_cleanup (void *cls, 186 const struct TALER_TESTING_Command *cmd) 187 { 188 struct LockProductState *pis = cls; 189 190 if (NULL != pis->iph) 191 { 192 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 193 "POST /product/$ID/lock operation did not complete\n"); 194 TALER_MERCHANT_post_private_products_lock_cancel (pis->iph); 195 } 196 GNUNET_free (pis->uuid); 197 GNUNET_free (pis); 198 } 199 200 201 /** 202 * Offer internal data to other commands. 203 * 204 * @param cls closure 205 * @param[out] ret result (could be anything) 206 * @param trait name of the trait 207 * @param index index number of the object to extract. 208 * @return #GNUNET_OK on success 209 */ 210 static enum GNUNET_GenericReturnValue 211 lock_product_traits (void *cls, 212 const void **ret, 213 const char *trait, 214 unsigned int index) 215 { 216 struct LockProductState *lps = cls; 217 struct TALER_TESTING_Trait traits[] = { 218 TALER_TESTING_make_trait_lock_uuid (lps->uuid), 219 TALER_TESTING_trait_end () 220 }; 221 222 return TALER_TESTING_get_trait (traits, 223 ret, 224 trait, 225 index); 226 } 227 228 229 struct TALER_TESTING_Command 230 TALER_TESTING_cmd_merchant_lock_product ( 231 const char *label, 232 const char *merchant_url, 233 const char *product_id, 234 struct GNUNET_TIME_Relative duration, 235 uint32_t quantity, 236 unsigned int http_status) 237 { 238 struct LockProductState *pis; 239 struct GNUNET_Uuid uuid; 240 241 pis = GNUNET_new (struct LockProductState); 242 pis->merchant_url = merchant_url; 243 pis->product_id = product_id; 244 pis->http_status = http_status; 245 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, 246 &uuid, 247 sizeof (struct GNUNET_Uuid)); 248 pis->uuid = GNUNET_STRINGS_data_to_string_alloc (&uuid, 249 sizeof (uuid)); 250 pis->duration = duration; 251 pis->quantity = quantity; 252 pis->quantity_frac = 0; 253 pis->use_fractional_quantity = false; 254 255 { 256 struct TALER_TESTING_Command cmd = { 257 .cls = pis, 258 .label = label, 259 .run = &lock_product_run, 260 .cleanup = &lock_product_cleanup, 261 .traits = &lock_product_traits 262 }; 263 264 return cmd; 265 } 266 } 267 268 269 struct TALER_TESTING_Command 270 TALER_TESTING_cmd_merchant_lock_product2 ( 271 const char *label, 272 const char *merchant_url, 273 const char *product_id, 274 struct GNUNET_TIME_Relative duration, 275 uint32_t quantity, 276 uint32_t quantity_frac, 277 bool use_fractional_quantity, 278 unsigned int http_status) 279 { 280 struct LockProductState *pis; 281 struct TALER_TESTING_Command cmd; 282 283 cmd = TALER_TESTING_cmd_merchant_lock_product (label, 284 merchant_url, 285 product_id, 286 duration, 287 quantity, 288 http_status); 289 pis = cmd.cls; 290 pis->quantity_frac = quantity_frac; 291 pis->use_fractional_quantity = use_fractional_quantity; 292 return cmd; 293 } 294 295 296 /* end of testing_api_cmd_lock_product.c */