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