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