Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2014-2020, 2024 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 : /**
21 : * @file testing/testing_api_cmd_transfer_get.c
22 : * @brief Implement the testing CMDs for the /transfer GET operation.
23 : * @author Marcello Stanisci
24 : */
25 : #include "platform.h"
26 : #include "taler_json_lib.h"
27 : #include <gnunet/gnunet_curl_lib.h>
28 : #include "taler_testing_lib.h"
29 :
30 : /**
31 : * State for a "track transfer" CMD.
32 : */
33 : struct TrackTransferState
34 : {
35 :
36 : /**
37 : * Expected amount for the WTID being tracked.
38 : */
39 : const char *expected_total_amount;
40 :
41 : /**
42 : * Expected fee for this WTID.
43 : */
44 : const char *expected_wire_fee;
45 :
46 : /**
47 : * Our command.
48 : */
49 : const struct TALER_TESTING_Command *cmd;
50 :
51 : /**
52 : * Reference to any operation that can provide a WTID.
53 : * Will be the WTID to track.
54 : */
55 : const char *wtid_reference;
56 :
57 : /**
58 : * Reference to any operation that can provide wire details.
59 : * Those wire details will then be matched against the credit
60 : * bank account of the tracked WTID. This way we can test that
61 : * a wire transfer paid back one particular bank account.
62 : */
63 : const char *wire_details_reference;
64 :
65 : /**
66 : * Reference to any operation that can provide an amount.
67 : * This way we can check that the transferred amount matches
68 : * our expectations.
69 : */
70 : const char *total_amount_reference;
71 :
72 : /**
73 : * Handle to a pending "track transfer" operation.
74 : */
75 : struct TALER_EXCHANGE_TransfersGetHandle *tth;
76 :
77 : /**
78 : * Interpreter state.
79 : */
80 : struct TALER_TESTING_Interpreter *is;
81 :
82 : /**
83 : * Expected HTTP response code.
84 : */
85 : unsigned int expected_response_code;
86 :
87 : };
88 :
89 :
90 : /**
91 : * Cleanup the state for a "track transfer" CMD, and possibly
92 : * cancel a pending operation thereof.
93 : *
94 : * @param cls closure.
95 : * @param cmd the command which is being cleaned up.
96 : */
97 : static void
98 6 : track_transfer_cleanup (
99 : void *cls,
100 : const struct TALER_TESTING_Command *cmd)
101 : {
102 6 : struct TrackTransferState *tts = cls;
103 :
104 6 : if (NULL != tts->tth)
105 : {
106 0 : TALER_TESTING_command_incomplete (tts->is,
107 : cmd->label);
108 0 : TALER_EXCHANGE_transfers_get_cancel (tts->tth);
109 0 : tts->tth = NULL;
110 : }
111 6 : GNUNET_free (tts);
112 6 : }
113 :
114 :
115 : /**
116 : * Check whether the HTTP response code from a "track transfer"
117 : * operation is acceptable, and all other values like total amount,
118 : * wire fees and hashed wire details as well.
119 : *
120 : * @param cls closure.
121 : * @param tgr response details
122 : */
123 : static void
124 6 : track_transfer_cb (
125 : void *cls,
126 : const struct TALER_EXCHANGE_TransfersGetResponse *tgr)
127 : {
128 6 : struct TrackTransferState *tts = cls;
129 6 : const struct TALER_EXCHANGE_HttpResponse *hr = &tgr->hr;
130 6 : struct TALER_TESTING_Interpreter *is = tts->is;
131 : struct TALER_Amount expected_amount;
132 :
133 6 : tts->tth = NULL;
134 6 : if (tts->expected_response_code != hr->http_status)
135 : {
136 0 : TALER_TESTING_unexpected_status (is,
137 : hr->http_status,
138 : tts->expected_response_code);
139 0 : return;
140 : }
141 :
142 6 : switch (hr->http_status)
143 : {
144 4 : case MHD_HTTP_OK:
145 : {
146 4 : const struct TALER_EXCHANGE_TransferData *ta
147 : = &tgr->details.ok.td;
148 :
149 4 : if (NULL == tts->expected_total_amount)
150 : {
151 0 : GNUNET_break (0);
152 0 : TALER_TESTING_interpreter_fail (is);
153 0 : return;
154 : }
155 4 : if (NULL == tts->expected_wire_fee)
156 : {
157 0 : GNUNET_break (0);
158 0 : TALER_TESTING_interpreter_fail (is);
159 0 : return;
160 : }
161 :
162 4 : if (GNUNET_OK !=
163 4 : TALER_string_to_amount (tts->expected_total_amount,
164 : &expected_amount))
165 : {
166 0 : GNUNET_break (0);
167 0 : TALER_TESTING_interpreter_fail (is);
168 0 : return;
169 : }
170 4 : if (0 != TALER_amount_cmp (&ta->total_amount,
171 : &expected_amount))
172 : {
173 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
174 : "Total amount mismatch to command %s - "
175 : "%s vs %s\n",
176 : tts->cmd->label,
177 : TALER_amount_to_string (&ta->total_amount),
178 : TALER_amount_to_string (&expected_amount));
179 0 : json_dumpf (hr->reply,
180 : stderr,
181 : 0);
182 0 : fprintf (stderr, "\n");
183 0 : TALER_TESTING_interpreter_fail (is);
184 0 : return;
185 : }
186 :
187 4 : if (GNUNET_OK !=
188 4 : TALER_string_to_amount (tts->expected_wire_fee,
189 : &expected_amount))
190 : {
191 0 : GNUNET_break (0);
192 0 : TALER_TESTING_interpreter_fail (is);
193 0 : return;
194 : }
195 :
196 4 : if (0 != TALER_amount_cmp (&ta->wire_fee,
197 : &expected_amount))
198 : {
199 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
200 : "Wire fee mismatch to command %s\n",
201 : tts->cmd->label);
202 0 : json_dumpf (hr->reply,
203 : stderr,
204 : 0);
205 0 : TALER_TESTING_interpreter_fail (is);
206 0 : return;
207 : }
208 :
209 : /**
210 : * Optionally checking: (1) wire-details for this transfer
211 : * match the ones from a referenced "deposit" operation -
212 : * or any operation that could provide wire-details. (2)
213 : * Total amount for this transfer matches the one from any
214 : * referenced command that could provide one.
215 : */
216 4 : if (NULL != tts->wire_details_reference)
217 : {
218 : const struct TALER_TESTING_Command *wire_details_cmd;
219 : const struct TALER_FullPayto *payto_uri;
220 : struct TALER_FullPaytoHashP h_payto;
221 :
222 : wire_details_cmd
223 0 : = TALER_TESTING_interpreter_lookup_command (
224 : is,
225 : tts->wire_details_reference);
226 0 : if (NULL == wire_details_cmd)
227 : {
228 0 : GNUNET_break (0);
229 0 : TALER_TESTING_interpreter_fail (is);
230 0 : return;
231 : }
232 0 : if (GNUNET_OK !=
233 0 : TALER_TESTING_get_trait_full_payto_uri (wire_details_cmd,
234 : &payto_uri))
235 : {
236 0 : GNUNET_break (0);
237 0 : TALER_TESTING_interpreter_fail (is);
238 0 : return;
239 : }
240 0 : TALER_full_payto_hash (*payto_uri,
241 : &h_payto);
242 0 : if (0 != GNUNET_memcmp (&h_payto,
243 : &ta->h_payto))
244 : {
245 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
246 : "Wire hash missmath to command %s\n",
247 : tts->cmd->label);
248 0 : json_dumpf (hr->reply,
249 : stderr,
250 : 0);
251 0 : TALER_TESTING_interpreter_fail (is);
252 0 : return;
253 : }
254 : }
255 4 : if (NULL != tts->total_amount_reference)
256 : {
257 : const struct TALER_TESTING_Command *total_amount_cmd;
258 : const struct TALER_Amount *total_amount_from_reference;
259 :
260 : total_amount_cmd
261 0 : = TALER_TESTING_interpreter_lookup_command (is,
262 : tts->
263 : total_amount_reference);
264 0 : if (NULL == total_amount_cmd)
265 : {
266 0 : GNUNET_break (0);
267 0 : TALER_TESTING_interpreter_fail (is);
268 0 : return;
269 : }
270 0 : if (GNUNET_OK !=
271 0 : TALER_TESTING_get_trait_amount (total_amount_cmd,
272 : &total_amount_from_reference))
273 : {
274 0 : GNUNET_break (0);
275 0 : TALER_TESTING_interpreter_fail (is);
276 0 : return;
277 : }
278 0 : if (0 != TALER_amount_cmp (&ta->total_amount,
279 : total_amount_from_reference))
280 : {
281 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
282 : "Amount mismatch in command %s\n",
283 : tts->cmd->label);
284 0 : json_dumpf (hr->reply,
285 : stderr,
286 : 0);
287 0 : TALER_TESTING_interpreter_fail (is);
288 0 : return;
289 : }
290 : }
291 4 : break;
292 : } /* case OK */
293 : } /* switch on status */
294 6 : TALER_TESTING_interpreter_next (is);
295 : }
296 :
297 :
298 : /**
299 : * Run the command.
300 : *
301 : * @param cls closure.
302 : * @param cmd the command under execution.
303 : * @param is the interpreter state.
304 : */
305 : static void
306 6 : track_transfer_run (
307 : void *cls,
308 : const struct TALER_TESTING_Command *cmd,
309 : struct TALER_TESTING_Interpreter *is)
310 : {
311 : /* looking for a wtid to track .. */
312 6 : struct TrackTransferState *tts = cls;
313 : struct TALER_WireTransferIdentifierRawP wtid;
314 : const struct TALER_WireTransferIdentifierRawP *wtid_ptr;
315 :
316 6 : tts->cmd = cmd;
317 : /* If no reference is given, we'll use a all-zeros
318 : * WTID */
319 6 : memset (&wtid,
320 : 0,
321 : sizeof (wtid));
322 6 : wtid_ptr = &wtid;
323 6 : tts->is = is;
324 6 : if (NULL != tts->wtid_reference)
325 : {
326 : const struct TALER_TESTING_Command *wtid_cmd;
327 :
328 4 : wtid_cmd = TALER_TESTING_interpreter_lookup_command (tts->is,
329 : tts->wtid_reference);
330 4 : if (NULL == wtid_cmd)
331 : {
332 0 : GNUNET_break (0);
333 0 : TALER_TESTING_interpreter_fail (tts->is);
334 0 : return;
335 : }
336 :
337 4 : if (GNUNET_OK !=
338 4 : TALER_TESTING_get_trait_wtid (wtid_cmd,
339 : &wtid_ptr))
340 : {
341 0 : GNUNET_break (0);
342 0 : TALER_TESTING_interpreter_fail (tts->is);
343 0 : return;
344 : }
345 4 : GNUNET_assert (NULL != wtid_ptr);
346 : }
347 6 : tts->tth = TALER_EXCHANGE_transfers_get (
348 : TALER_TESTING_interpreter_get_context (is),
349 : TALER_TESTING_get_exchange_url (is),
350 : TALER_TESTING_get_keys (is),
351 : wtid_ptr,
352 : &track_transfer_cb,
353 : tts);
354 6 : GNUNET_assert (NULL != tts->tth);
355 : }
356 :
357 :
358 : struct TALER_TESTING_Command
359 2 : TALER_TESTING_cmd_track_transfer_empty (
360 : const char *label,
361 : const char *wtid_reference,
362 : unsigned int expected_response_code)
363 : {
364 : struct TrackTransferState *tts;
365 :
366 2 : tts = GNUNET_new (struct TrackTransferState);
367 2 : tts->wtid_reference = wtid_reference;
368 2 : tts->expected_response_code = expected_response_code;
369 : {
370 2 : struct TALER_TESTING_Command cmd = {
371 : .cls = tts,
372 : .label = label,
373 : .run = &track_transfer_run,
374 : .cleanup = &track_transfer_cleanup
375 : };
376 :
377 2 : return cmd;
378 : }
379 : }
380 :
381 :
382 : struct TALER_TESTING_Command
383 4 : TALER_TESTING_cmd_track_transfer (
384 : const char *label,
385 : const char *wtid_reference,
386 : unsigned int expected_response_code,
387 : const char *expected_total_amount,
388 : const char *expected_wire_fee)
389 : {
390 : struct TrackTransferState *tts;
391 :
392 4 : tts = GNUNET_new (struct TrackTransferState);
393 4 : tts->wtid_reference = wtid_reference;
394 4 : tts->expected_response_code = expected_response_code;
395 4 : tts->expected_total_amount = expected_total_amount;
396 4 : tts->expected_wire_fee = expected_wire_fee;
397 : {
398 4 : struct TALER_TESTING_Command cmd = {
399 : .cls = tts,
400 : .label = label,
401 : .run = &track_transfer_run,
402 : .cleanup = &track_transfer_cleanup
403 : };
404 :
405 4 : return cmd;
406 : }
407 : }
408 :
409 :
410 : /* end of testing_api_cmd_gransfer_get.c */
|