testing_api_cmd_wire.c (6308B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2018, 2023 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it 6 under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3, or (at your 8 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 GNU 13 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/testing_api_cmd_wire.c 21 * @brief command for testing /wire. 22 * @author Marcello Stanisci 23 */ 24 #include "taler/taler_json_lib.h" 25 #include <gnunet/gnunet_curl_lib.h> 26 #include "taler/taler_testing_lib.h" 27 28 29 /** 30 * State for a "wire" CMD. 31 */ 32 struct WireState 33 { 34 35 /** 36 * Handle to the /wire operation. 37 */ 38 struct TALER_EXCHANGE_WireHandle *wh; 39 40 /** 41 * Our command. 42 */ 43 const struct TALER_TESTING_Command *cmd; 44 45 /** 46 * Which wire-method we expect is offered by the exchange. 47 */ 48 const char *expected_method; 49 50 /** 51 * Flag indicating if the expected method is actually 52 * offered. 53 */ 54 unsigned int method_found; 55 56 /** 57 * Fee we expect is charged for this wire-transfer method. 58 */ 59 const char *expected_fee; 60 61 /** 62 * Expected HTTP response code. 63 */ 64 unsigned int expected_response_code; 65 66 /** 67 * Interpreter state. 68 */ 69 struct TALER_TESTING_Interpreter *is; 70 }; 71 72 73 /** 74 * Check whether the HTTP response code is acceptable, that 75 * the expected wire method is offered by the exchange, and 76 * that the wire fee is acceptable too. 77 * 78 * @param cls closure. 79 * @param wr response details 80 */ 81 static void 82 wire_cb (void *cls, 83 const struct TALER_EXCHANGE_WireResponse *wr) 84 { 85 struct WireState *ws = cls; 86 const struct TALER_EXCHANGE_HttpResponse *hr = &wr->hr; 87 struct TALER_Amount expected_fee; 88 89 TALER_LOG_DEBUG ("Checking parsed /wire response\n"); 90 ws->wh = NULL; 91 if (ws->expected_response_code != hr->http_status) 92 { 93 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 94 "Received unexpected status code %u\n", 95 hr->http_status); 96 TALER_TESTING_interpreter_fail (ws->is); 97 return; 98 } 99 100 if (MHD_HTTP_OK == hr->http_status) 101 { 102 unsigned int accounts_len 103 = wr->details.ok.accounts_len; 104 unsigned int fees_len 105 = wr->details.ok.fees_len; 106 const struct TALER_EXCHANGE_WireAccount *accounts 107 = wr->details.ok.accounts; 108 const struct TALER_EXCHANGE_WireFeesByMethod *fees 109 = wr->details.ok.fees; 110 111 for (unsigned int i = 0; i<accounts_len; i++) 112 { 113 char *method; 114 115 method = TALER_payto_get_method (accounts[i].payto_uri); 116 if (NULL == method) 117 { 118 GNUNET_break (0); 119 TALER_TESTING_interpreter_fail (ws->is); 120 return; 121 } 122 if (0 == strcmp (ws->expected_method, 123 method)) 124 { 125 ws->method_found = GNUNET_OK; 126 } 127 GNUNET_free (method); 128 } 129 if (NULL != ws->expected_fee) 130 { 131 bool fee_found = false; 132 133 GNUNET_assert (GNUNET_OK == 134 TALER_string_to_amount (ws->expected_fee, 135 &expected_fee)); 136 for (unsigned int i = 0; i<fees_len; i++) 137 { 138 if (0 != strcmp (fees[i].method, 139 ws->expected_method)) 140 continue; 141 for (const struct TALER_EXCHANGE_WireAggregateFees *waf 142 = fees[i].fees_head; 143 NULL != waf; 144 waf = waf->next) 145 { 146 if (0 != TALER_amount_cmp (&waf->fees.wire, 147 &expected_fee)) 148 { 149 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 150 "Wire fee mismatch to command %s\n", 151 ws->cmd->label); 152 TALER_TESTING_interpreter_fail (ws->is); 153 return; 154 } 155 fee_found = true; 156 } 157 } 158 if (! fee_found) 159 { 160 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 161 "/wire does not contain expected fee '%s'\n", 162 ws->expected_fee); 163 TALER_TESTING_interpreter_fail (ws->is); 164 return; 165 } 166 } 167 if (GNUNET_OK != ws->method_found) 168 { 169 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 170 "/wire does not offer method '%s'\n", 171 ws->expected_method); 172 TALER_TESTING_interpreter_fail (ws->is); 173 return; 174 } 175 } 176 TALER_TESTING_interpreter_next (ws->is); 177 } 178 179 180 /** 181 * Run the command. 182 * 183 * @param cls closure. 184 * @param cmd the command to execute. 185 * @param is the interpreter state. 186 */ 187 static void 188 wire_run (void *cls, 189 const struct TALER_TESTING_Command *cmd, 190 struct TALER_TESTING_Interpreter *is) 191 { 192 struct WireState *ws = cls; 193 194 ws->cmd = cmd; 195 ws->is = is; 196 ws->wh = TALER_EXCHANGE_wire ( 197 TALER_TESTING_interpreter_get_context (is), 198 TALER_TESTING_get_exchange_url (is), 199 TALER_TESTING_get_keys (is), 200 &wire_cb, 201 ws); 202 } 203 204 205 /** 206 * Cleanup the state of a "wire" CMD, and possibly cancel a 207 * pending operation thereof. 208 * 209 * @param cls closure. 210 * @param cmd the command which is being cleaned up. 211 */ 212 static void 213 wire_cleanup (void *cls, 214 const struct TALER_TESTING_Command *cmd) 215 { 216 struct WireState *ws = cls; 217 218 if (NULL != ws->wh) 219 { 220 TALER_TESTING_command_incomplete (ws->is, 221 cmd->label); 222 TALER_EXCHANGE_wire_cancel (ws->wh); 223 ws->wh = NULL; 224 } 225 GNUNET_free (ws); 226 } 227 228 229 struct TALER_TESTING_Command 230 TALER_TESTING_cmd_wire (const char *label, 231 const char *expected_method, 232 const char *expected_fee, 233 unsigned int expected_response_code) 234 { 235 struct WireState *ws; 236 237 ws = GNUNET_new (struct WireState); 238 ws->expected_method = expected_method; 239 ws->expected_fee = expected_fee; 240 ws->expected_response_code = expected_response_code; 241 { 242 struct TALER_TESTING_Command cmd = { 243 .cls = ws, 244 .label = label, 245 .run = &wire_run, 246 .cleanup = &wire_cleanup 247 }; 248 249 return cmd; 250 } 251 }