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