testing_api_cmd_get_unit.c (9630B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2025 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_get_unit.c 21 * @brief command to test GET /private/units/$ID 22 * @author Bohdan Potuzhnyi 23 */ 24 #include "taler/platform.h" 25 #include <jansson.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/get-private-units-UNIT.h> 30 31 32 /** 33 * State for a GET /private/units/$ID command. 34 */ 35 struct GetUnitState 36 { 37 /** 38 * In-flight request handle. 39 */ 40 struct TALER_MERCHANT_GetPrivateUnitHandle *ugh; 41 42 /** 43 * Interpreter context. 44 */ 45 struct TALER_TESTING_Interpreter *is; 46 47 /** 48 * Merchant backend base URL. 49 */ 50 const char *merchant_url; 51 52 /** 53 * Unit identifier to fetch. 54 */ 55 const char *unit_id; 56 57 /** 58 * Expected HTTP status. 59 */ 60 unsigned int http_status; 61 62 /** 63 * Optional command label providing expected traits. 64 */ 65 const char *reference; 66 }; 67 68 69 /** 70 * Compare response @a entry with traits from @a ref_cmd. 71 */ 72 static bool 73 unit_matches_reference (const struct TALER_MERCHANT_UnitEntry *entry, 74 const struct TALER_TESTING_Command *ref_cmd) 75 { 76 const char *unit_id; 77 78 if (GNUNET_OK != 79 TALER_TESTING_get_trait_unit_id (ref_cmd, 80 &unit_id)) 81 { 82 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 83 "Unit trait resolution failed for reference `%s'\n", 84 ref_cmd->label); 85 return false; 86 } 87 if (0 != strcmp (entry->unit, 88 unit_id)) 89 { 90 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 91 "Unit mismatch: expected id %s got %s\n", 92 unit_id, 93 entry->unit); 94 return false; 95 } 96 97 { 98 const char *unit_name_long = NULL; 99 100 if (GNUNET_OK == 101 TALER_TESTING_get_trait_unit_name_long (ref_cmd, 102 &unit_name_long)) 103 { 104 if ( (NULL != unit_name_long) && 105 (0 != strcmp (entry->unit_name_long, 106 unit_name_long)) ) 107 { 108 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 109 "Unit %s mismatch: expected long label '%s' got '%s'\n", 110 entry->unit, 111 unit_name_long, 112 entry->unit_name_long); 113 return false; 114 } 115 } 116 } 117 { 118 const char *unit_name_short = NULL; 119 120 if (GNUNET_OK == 121 TALER_TESTING_get_trait_unit_name_short (ref_cmd, 122 &unit_name_short)) 123 { 124 if ( (NULL != unit_name_short) && 125 (0 != strcmp (entry->unit_name_short, 126 unit_name_short)) ) 127 { 128 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 129 "Unit %s mismatch: expected short label '%s' got '%s'\n", 130 entry->unit, 131 unit_name_short, 132 entry->unit_name_short); 133 return false; 134 } 135 } 136 } 137 { 138 const bool *unit_allow_fraction = NULL; 139 140 if (GNUNET_OK == 141 TALER_TESTING_get_trait_unit_allow_fraction (ref_cmd, 142 &unit_allow_fraction)) 143 { 144 if ( (NULL != unit_allow_fraction) && 145 (*unit_allow_fraction != entry->unit_allow_fraction) ) 146 { 147 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 148 "Unit %s mismatch: expected allow_fraction %d got %d\n", 149 entry->unit, 150 (int) *unit_allow_fraction, 151 (int) entry->unit_allow_fraction); 152 return false; 153 } 154 } 155 } 156 { 157 const uint32_t *unit_precision_level = NULL; 158 159 if (GNUNET_OK == 160 TALER_TESTING_get_trait_unit_precision_level (ref_cmd, 161 &unit_precision_level)) 162 { 163 if ( (NULL != unit_precision_level) && 164 (*unit_precision_level != entry->unit_precision_level) ) 165 { 166 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 167 "Unit %s mismatch: expected precision %u got %u\n", 168 entry->unit, 169 (unsigned int) *unit_precision_level, 170 (unsigned int) entry->unit_precision_level); 171 return false; 172 } 173 } 174 } 175 { 176 const bool *unit_active = NULL; 177 178 if (GNUNET_OK == 179 TALER_TESTING_get_trait_unit_active (ref_cmd, 180 &unit_active)) 181 { 182 if ( (NULL != unit_active) && 183 (*unit_active != entry->unit_active) ) 184 { 185 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 186 "Unit %s mismatch: expected active flag %d got %d\n", 187 entry->unit, 188 (int) *unit_active, 189 (int) entry->unit_active); 190 return false; 191 } 192 } 193 } 194 { 195 const json_t *unit_name_long_i18n = NULL; 196 197 if (GNUNET_OK == 198 TALER_TESTING_get_trait_unit_name_long_i18n (ref_cmd, 199 &unit_name_long_i18n)) 200 { 201 if ( (NULL != unit_name_long_i18n) && 202 ( (NULL == entry->unit_name_long_i18n) || 203 (1 != json_equal (unit_name_long_i18n, 204 entry->unit_name_long_i18n)) ) ) 205 { 206 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 207 "Unit %s mismatch: long_i18n differs\n", 208 entry->unit); 209 return false; 210 } 211 } 212 } 213 { 214 const json_t *unit_name_short_i18n = NULL; 215 216 if (GNUNET_OK == 217 TALER_TESTING_get_trait_unit_name_short_i18n (ref_cmd, 218 &unit_name_short_i18n)) 219 { 220 if ( (NULL != unit_name_short_i18n) && 221 ( (NULL == entry->unit_name_short_i18n) || 222 (1 != json_equal (unit_name_short_i18n, 223 entry->unit_name_short_i18n)) ) ) 224 { 225 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 226 "Unit %s mismatch: short_i18n differs\n", 227 entry->unit); 228 return false; 229 } 230 } 231 } 232 return true; 233 } 234 235 236 /** 237 * Completion callback. 238 */ 239 static void 240 get_unit_cb (void *cls, 241 const struct TALER_MERCHANT_GetPrivateUnitResponse *ugr) 242 { 243 struct GetUnitState *gug = cls; 244 245 gug->ugh = NULL; 246 if (gug->http_status != ugr->hr.http_status) 247 { 248 TALER_TESTING_unexpected_status_with_body (gug->is, 249 ugr->hr.http_status, 250 gug->http_status, 251 ugr->hr.reply); 252 return; 253 } 254 if ( (MHD_HTTP_OK == ugr->hr.http_status) && 255 (NULL != gug->reference) ) 256 { 257 const struct TALER_TESTING_Command *ref_cmd; 258 259 ref_cmd = TALER_TESTING_interpreter_lookup_command (gug->is, 260 gug->reference); 261 if (NULL == ref_cmd) 262 { 263 GNUNET_break (0); 264 TALER_TESTING_interpreter_fail (gug->is); 265 return; 266 } 267 if (! unit_matches_reference (&ugr->details.ok.unit, 268 ref_cmd)) 269 { 270 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 271 "GET /private/units/%s response does not match expectation from `%s'\n", 272 gug->unit_id, 273 gug->reference); 274 TALER_TESTING_interpreter_fail (gug->is); 275 return; 276 } 277 } 278 TALER_TESTING_interpreter_next (gug->is); 279 } 280 281 282 /** 283 * Issue GET request. 284 */ 285 static void 286 get_unit_run (void *cls, 287 const struct TALER_TESTING_Command *cmd, 288 struct TALER_TESTING_Interpreter *is) 289 { 290 struct GetUnitState *gug = cls; 291 292 gug->is = is; 293 gug->ugh = TALER_MERCHANT_get_private_unit_create ( 294 TALER_TESTING_interpreter_get_context (is), 295 gug->merchant_url, 296 gug->unit_id); 297 { 298 enum TALER_ErrorCode ec; 299 300 ec = TALER_MERCHANT_get_private_unit_start ( 301 gug->ugh, 302 &get_unit_cb, 303 gug); 304 GNUNET_assert (TALER_EC_NONE == ec); 305 } 306 } 307 308 309 /** 310 * Cleanup. 311 */ 312 static void 313 get_unit_cleanup (void *cls, 314 const struct TALER_TESTING_Command *cmd) 315 { 316 struct GetUnitState *gug = cls; 317 318 if (NULL != gug->ugh) 319 { 320 TALER_MERCHANT_get_private_unit_cancel (gug->ugh); 321 gug->ugh = NULL; 322 } 323 GNUNET_free (gug); 324 } 325 326 327 struct TALER_TESTING_Command 328 TALER_TESTING_cmd_merchant_get_unit (const char *label, 329 const char *merchant_url, 330 const char *unit_id, 331 unsigned int http_status, 332 const char *reference) 333 { 334 struct GetUnitState *gug; 335 336 gug = GNUNET_new (struct GetUnitState); 337 gug->merchant_url = merchant_url; 338 gug->unit_id = unit_id; 339 gug->http_status = http_status; 340 gug->reference = reference; 341 342 { 343 struct TALER_TESTING_Command cmd = { 344 .cls = gug, 345 .label = label, 346 .run = &get_unit_run, 347 .cleanup = &get_unit_cleanup 348 }; 349 350 return cmd; 351 } 352 } 353 354 355 /* end of testing_api_cmd_get_unit.c */