Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2020-2023 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 : * @file testing_api_cmd_get_product.c
21 : * @brief command to test GET /product/$ID
22 : * @author Christian Grothoff
23 : */
24 : #include "platform.h"
25 : #include <taler/taler_exchange_service.h>
26 : #include <taler/taler_testing_lib.h>
27 : #include "taler_merchant_service.h"
28 : #include "taler_merchant_testing_lib.h"
29 :
30 :
31 : /**
32 : * State of a "GET product" CMD.
33 : */
34 : struct GetProductState
35 : {
36 :
37 : /**
38 : * Handle for a "GET product" request.
39 : */
40 : struct TALER_MERCHANT_ProductGetHandle *igh;
41 :
42 : /**
43 : * The interpreter state.
44 : */
45 : struct TALER_TESTING_Interpreter *is;
46 :
47 : /**
48 : * Base URL of the merchant serving the request.
49 : */
50 : const char *merchant_url;
51 :
52 : /**
53 : * ID of the product to run GET for.
54 : */
55 : const char *product_id;
56 :
57 : /**
58 : * Reference for a POST or PATCH /products CMD (optional).
59 : */
60 : const char *product_reference;
61 :
62 : /**
63 : * Expected HTTP response code.
64 : */
65 : unsigned int http_status;
66 :
67 : };
68 :
69 :
70 : /**
71 : * Callback for a /get/product/$ID operation.
72 : *
73 : * @param cls closure for this function
74 : * @param pgr response details
75 : */
76 : static void
77 16 : get_product_cb (void *cls,
78 : const struct TALER_MERCHANT_ProductGetResponse *pgr)
79 : {
80 16 : struct GetProductState *gis = cls;
81 : const struct TALER_TESTING_Command *product_cmd;
82 :
83 16 : gis->igh = NULL;
84 16 : if (gis->http_status != pgr->hr.http_status)
85 : {
86 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
87 : "Unexpected response code %u (%d) to command %s\n",
88 : pgr->hr.http_status,
89 : (int) pgr->hr.ec,
90 : TALER_TESTING_interpreter_get_current_label (gis->is));
91 0 : TALER_TESTING_interpreter_fail (gis->is);
92 0 : return;
93 : }
94 16 : switch (pgr->hr.http_status)
95 : {
96 4 : case MHD_HTTP_OK:
97 : {
98 : const char *expected_description;
99 :
100 4 : product_cmd = TALER_TESTING_interpreter_lookup_command (
101 : gis->is,
102 : gis->product_reference);
103 4 : if (GNUNET_OK !=
104 4 : TALER_TESTING_get_trait_product_description (product_cmd,
105 : &expected_description))
106 0 : TALER_TESTING_interpreter_fail (gis->is);
107 4 : if (0 != strcmp (pgr->details.ok.description,
108 : expected_description))
109 : {
110 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
111 : "Product description does not match\n");
112 0 : TALER_TESTING_interpreter_fail (gis->is);
113 0 : return;
114 : }
115 : }
116 : {
117 : const json_t *expected_description_i18n;
118 :
119 4 : if (GNUNET_OK !=
120 4 : TALER_TESTING_get_trait_i18n_description (product_cmd,
121 : &expected_description_i18n))
122 0 : TALER_TESTING_interpreter_fail (gis->is);
123 4 : if (1 != json_equal (pgr->details.ok.description_i18n,
124 : expected_description_i18n))
125 : {
126 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
127 : "Product description i18n does not match\n");
128 0 : TALER_TESTING_interpreter_fail (gis->is);
129 0 : return;
130 : }
131 : }
132 : {
133 : const struct TALER_Amount *expected_price;
134 :
135 4 : if (GNUNET_OK !=
136 4 : TALER_TESTING_get_trait_amount (product_cmd,
137 : &expected_price))
138 0 : TALER_TESTING_interpreter_fail (gis->is);
139 4 : if ((GNUNET_OK !=
140 4 : TALER_amount_cmp_currency (&pgr->details.ok.price,
141 4 : expected_price)) ||
142 4 : (0 != TALER_amount_cmp (&pgr->details.ok.price,
143 : expected_price)))
144 : {
145 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
146 : "Product price does not match\n");
147 0 : TALER_TESTING_interpreter_fail (gis->is);
148 0 : return;
149 : }
150 : }
151 : {
152 : const char *expected_image;
153 :
154 4 : if (GNUNET_OK !=
155 4 : TALER_TESTING_get_trait_product_image (product_cmd,
156 : &expected_image))
157 0 : TALER_TESTING_interpreter_fail (gis->is);
158 4 : if (0 != strcmp (pgr->details.ok.image,
159 : expected_image))
160 : {
161 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
162 : "Product image does not match\n");
163 0 : TALER_TESTING_interpreter_fail (gis->is);
164 0 : return;
165 : }
166 : }
167 : {
168 : const json_t *expected_taxes;
169 :
170 4 : if (GNUNET_OK !=
171 4 : TALER_TESTING_get_trait_taxes (product_cmd,
172 : &expected_taxes))
173 0 : TALER_TESTING_interpreter_fail (gis->is);
174 4 : if (1 != json_equal (pgr->details.ok.taxes,
175 : expected_taxes))
176 : {
177 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
178 : "Product taxes do not match\n");
179 0 : TALER_TESTING_interpreter_fail (gis->is);
180 0 : return;
181 : }
182 : }
183 : {
184 : const char *expected_unit;
185 :
186 4 : if (GNUNET_OK !=
187 4 : TALER_TESTING_get_trait_product_unit (product_cmd,
188 : &expected_unit))
189 0 : TALER_TESTING_interpreter_fail (gis->is);
190 4 : if (0 != strcmp (pgr->details.ok.unit,
191 : expected_unit))
192 : {
193 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
194 : "Product unit does not match\n");
195 0 : TALER_TESTING_interpreter_fail (gis->is);
196 0 : return;
197 : }
198 : }
199 : {
200 : const json_t *expected_location;
201 :
202 4 : if (GNUNET_OK !=
203 4 : TALER_TESTING_get_trait_address (product_cmd,
204 : &expected_location))
205 0 : TALER_TESTING_interpreter_fail (gis->is);
206 4 : if (1 != json_equal (pgr->details.ok.location,
207 : expected_location))
208 : {
209 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
210 : "Product location does not match\n");
211 0 : TALER_TESTING_interpreter_fail (gis->is);
212 0 : return;
213 : }
214 : }
215 : {
216 : const int64_t *expected_total_stock;
217 :
218 4 : if (GNUNET_OK !=
219 4 : TALER_TESTING_get_trait_product_stock (product_cmd,
220 : &expected_total_stock))
221 0 : TALER_TESTING_interpreter_fail (gis->is);
222 4 : if (pgr->details.ok.total_stock != *expected_total_stock)
223 : {
224 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
225 : "Product total stock does not match\n");
226 0 : TALER_TESTING_interpreter_fail (gis->is);
227 0 : return;
228 : }
229 : }
230 : {
231 : const struct GNUNET_TIME_Timestamp *expected_next_restock;
232 :
233 4 : if (GNUNET_OK !=
234 4 : TALER_TESTING_get_trait_timestamp (product_cmd,
235 : 0,
236 : &expected_next_restock))
237 0 : TALER_TESTING_interpreter_fail (gis->is);
238 4 : if (GNUNET_TIME_timestamp_cmp (pgr->details.ok.next_restock,
239 : !=,
240 : *expected_next_restock))
241 : {
242 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
243 : "Product next restock does not match\n");
244 0 : TALER_TESTING_interpreter_fail (gis->is);
245 0 : return;
246 : }
247 : }
248 4 : break;
249 4 : case MHD_HTTP_UNAUTHORIZED:
250 4 : break;
251 8 : case MHD_HTTP_NOT_FOUND:
252 8 : break;
253 0 : default:
254 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
255 : "Unhandled HTTP status.\n");
256 : }
257 16 : TALER_TESTING_interpreter_next (gis->is);
258 : }
259 :
260 :
261 : /**
262 : * Run the "GET product" CMD.
263 : *
264 : *
265 : * @param cls closure.
266 : * @param cmd command being run now.
267 : * @param is interpreter state.
268 : */
269 : static void
270 16 : get_product_run (void *cls,
271 : const struct TALER_TESTING_Command *cmd,
272 : struct TALER_TESTING_Interpreter *is)
273 : {
274 16 : struct GetProductState *gis = cls;
275 :
276 16 : gis->is = is;
277 16 : gis->igh = TALER_MERCHANT_product_get (TALER_TESTING_interpreter_get_context (
278 : is),
279 : gis->merchant_url,
280 : gis->product_id,
281 : &get_product_cb,
282 : gis);
283 16 : GNUNET_assert (NULL != gis->igh);
284 16 : }
285 :
286 :
287 : /**
288 : * Free the state of a "GET product" CMD, and possibly
289 : * cancel a pending operation thereof.
290 : *
291 : * @param cls closure.
292 : * @param cmd command being run.
293 : */
294 : static void
295 16 : get_product_cleanup (void *cls,
296 : const struct TALER_TESTING_Command *cmd)
297 : {
298 16 : struct GetProductState *gis = cls;
299 :
300 16 : if (NULL != gis->igh)
301 : {
302 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
303 : "GET /products/$ID operation did not complete\n");
304 0 : TALER_MERCHANT_product_get_cancel (gis->igh);
305 : }
306 16 : GNUNET_free (gis);
307 16 : }
308 :
309 :
310 : struct TALER_TESTING_Command
311 16 : TALER_TESTING_cmd_merchant_get_product (const char *label,
312 : const char *merchant_url,
313 : const char *product_id,
314 : unsigned int http_status,
315 : const char *product_reference)
316 : {
317 : struct GetProductState *gis;
318 :
319 16 : gis = GNUNET_new (struct GetProductState);
320 16 : gis->merchant_url = merchant_url;
321 16 : gis->product_id = product_id;
322 16 : gis->http_status = http_status;
323 16 : gis->product_reference = product_reference;
324 : {
325 16 : struct TALER_TESTING_Command cmd = {
326 : .cls = gis,
327 : .label = label,
328 : .run = &get_product_run,
329 : .cleanup = &get_product_cleanup
330 : };
331 :
332 16 : return cmd;
333 : }
334 : }
335 :
336 :
337 : /* end of testing_api_cmd_get_product.c */
|