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