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