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