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