Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2020 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_patch_product.c
21 : * @brief command to test PATCH /product
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 "PATCH /product" CMD.
33 : */
34 : struct PatchProductState
35 : {
36 :
37 : /**
38 : * Handle for a "GET product" request.
39 : */
40 : struct TALER_MERCHANT_ProductPatchHandle *iph;
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 : * description of the product
59 : */
60 : const char *description;
61 :
62 : /**
63 : * Map from IETF BCP 47 language tags to localized descriptions
64 : */
65 : json_t *description_i18n;
66 :
67 : /**
68 : * unit in which the product is measured (liters, kilograms, packages, etc.)
69 : */
70 : const char *unit;
71 :
72 : /**
73 : * the price for one @a unit of the product
74 : */
75 : struct TALER_Amount price;
76 :
77 : /**
78 : * base64-encoded product image
79 : */
80 : char *image;
81 :
82 : /**
83 : * list of taxes paid by the merchant
84 : */
85 : json_t *taxes;
86 :
87 : /**
88 : * in @e units, -1 to indicate "infinite" (i.e. electronic books)
89 : */
90 : int64_t total_stock;
91 :
92 : /**
93 : * in @e units.
94 : */
95 : int64_t total_lost;
96 :
97 : /**
98 : * where the product is in stock
99 : */
100 : json_t *address;
101 :
102 : /**
103 : * when the next restocking is expected to happen, 0 for unknown,
104 : */
105 : struct GNUNET_TIME_Timestamp next_restock;
106 :
107 : /**
108 : * Expected HTTP response code.
109 : */
110 : unsigned int http_status;
111 :
112 : };
113 :
114 :
115 : /**
116 : * Callback for a PATCH /products/$ID operation.
117 : *
118 : * @param cls closure for this function
119 : * @param hr response being processed
120 : */
121 : static void
122 6 : patch_product_cb (void *cls,
123 : const struct TALER_MERCHANT_HttpResponse *hr)
124 : {
125 6 : struct PatchProductState *pis = cls;
126 :
127 6 : pis->iph = NULL;
128 6 : if (pis->http_status != hr->http_status)
129 : {
130 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
131 : "Unexpected response code %u (%d) to command %s\n",
132 : hr->http_status,
133 : (int) hr->ec,
134 : TALER_TESTING_interpreter_get_current_label (pis->is));
135 0 : TALER_TESTING_interpreter_fail (pis->is);
136 0 : return;
137 : }
138 6 : switch (hr->http_status)
139 : {
140 4 : case MHD_HTTP_NO_CONTENT:
141 4 : break;
142 0 : case MHD_HTTP_UNAUTHORIZED:
143 0 : break;
144 0 : case MHD_HTTP_FORBIDDEN:
145 0 : break;
146 2 : case MHD_HTTP_NOT_FOUND:
147 2 : break;
148 0 : case MHD_HTTP_CONFLICT:
149 0 : break;
150 0 : default:
151 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
152 : "Unhandled HTTP status %u for PATCH /products/ID.\n",
153 : hr->http_status);
154 : }
155 6 : TALER_TESTING_interpreter_next (pis->is);
156 : }
157 :
158 :
159 : /**
160 : * Run the "PATCH /products/$ID" CMD.
161 : *
162 : *
163 : * @param cls closure.
164 : * @param cmd command being run now.
165 : * @param is interpreter state.
166 : */
167 : static void
168 6 : patch_product_run (void *cls,
169 : const struct TALER_TESTING_Command *cmd,
170 : struct TALER_TESTING_Interpreter *is)
171 : {
172 6 : struct PatchProductState *pis = cls;
173 :
174 6 : pis->is = is;
175 6 : pis->iph = TALER_MERCHANT_product_patch (
176 : TALER_TESTING_interpreter_get_context (is),
177 : pis->merchant_url,
178 : pis->product_id,
179 : pis->description,
180 6 : pis->description_i18n,
181 : pis->unit,
182 6 : &pis->price,
183 6 : pis->image,
184 6 : pis->taxes,
185 : pis->total_stock,
186 6 : pis->total_lost,
187 6 : pis->address,
188 : pis->next_restock,
189 : &patch_product_cb,
190 : pis);
191 6 : GNUNET_assert (NULL != pis->iph);
192 6 : }
193 :
194 :
195 : /**
196 : * Offers information from the PATCH /products CMD state to other
197 : * commands.
198 : *
199 : * @param cls closure
200 : * @param[out] ret result (could be anything)
201 : * @param trait name of the trait
202 : * @param index index number of the object to extract.
203 : * @return #GNUNET_OK on success
204 : */
205 : static enum GNUNET_GenericReturnValue
206 18 : patch_product_traits (void *cls,
207 : const void **ret,
208 : const char *trait,
209 : unsigned int index)
210 : {
211 18 : struct PatchProductState *pps = cls;
212 : struct TALER_TESTING_Trait traits[] = {
213 18 : TALER_TESTING_make_trait_product_description (pps->description),
214 18 : TALER_TESTING_make_trait_i18n_description (pps->description_i18n),
215 18 : TALER_TESTING_make_trait_product_unit (pps->unit),
216 18 : TALER_TESTING_make_trait_amount (&pps->price),
217 18 : TALER_TESTING_make_trait_product_image (pps->image),
218 18 : TALER_TESTING_make_trait_taxes (pps->taxes),
219 18 : TALER_TESTING_make_trait_product_stock (&pps->total_stock),
220 18 : TALER_TESTING_make_trait_address (pps->address),
221 18 : TALER_TESTING_make_trait_timestamp (0,
222 18 : &pps->next_restock),
223 18 : TALER_TESTING_make_trait_product_id (pps->product_id),
224 18 : TALER_TESTING_trait_end (),
225 : };
226 :
227 18 : return TALER_TESTING_get_trait (traits,
228 : ret,
229 : trait,
230 : index);
231 : }
232 :
233 :
234 : /**
235 : * Free the state of a "GET product" CMD, and possibly
236 : * cancel a pending operation thereof.
237 : *
238 : * @param cls closure.
239 : * @param cmd command being run.
240 : */
241 : static void
242 6 : patch_product_cleanup (void *cls,
243 : const struct TALER_TESTING_Command *cmd)
244 : {
245 6 : struct PatchProductState *pis = cls;
246 :
247 6 : if (NULL != pis->iph)
248 : {
249 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
250 : "PATCH /products/$ID operation did not complete\n");
251 0 : TALER_MERCHANT_product_patch_cancel (pis->iph);
252 : }
253 6 : json_decref (pis->description_i18n);
254 6 : GNUNET_free (pis->image);
255 6 : json_decref (pis->taxes);
256 6 : json_decref (pis->address);
257 6 : GNUNET_free (pis);
258 6 : }
259 :
260 :
261 : struct TALER_TESTING_Command
262 6 : TALER_TESTING_cmd_merchant_patch_product (
263 : const char *label,
264 : const char *merchant_url,
265 : const char *product_id,
266 : const char *description,
267 : json_t *description_i18n,
268 : const char *unit,
269 : const char *price,
270 : const char *image,
271 : json_t *taxes,
272 : int64_t total_stock,
273 : uint64_t total_lost,
274 : json_t *address,
275 : struct GNUNET_TIME_Timestamp next_restock,
276 : unsigned int http_status)
277 : {
278 : struct PatchProductState *pis;
279 :
280 6 : GNUNET_assert ( (NULL == taxes) ||
281 : json_is_array (taxes));
282 6 : pis = GNUNET_new (struct PatchProductState);
283 6 : pis->merchant_url = merchant_url;
284 6 : pis->product_id = product_id;
285 6 : pis->http_status = http_status;
286 6 : pis->description = description;
287 6 : pis->description_i18n = description_i18n; /* ownership taken */
288 6 : pis->unit = unit;
289 6 : GNUNET_assert (GNUNET_OK ==
290 : TALER_string_to_amount (price,
291 : &pis->price));
292 6 : pis->image = GNUNET_strdup (image);
293 6 : pis->taxes = taxes; /* ownership taken */
294 6 : pis->total_stock = total_stock;
295 6 : pis->total_lost = total_lost;
296 6 : pis->address = address; /* ownership taken */
297 6 : pis->next_restock = next_restock;
298 : {
299 6 : struct TALER_TESTING_Command cmd = {
300 : .cls = pis,
301 : .label = label,
302 : .run = &patch_product_run,
303 : .cleanup = &patch_product_cleanup,
304 : .traits = &patch_product_traits
305 : };
306 :
307 6 : return cmd;
308 : }
309 : }
310 :
311 :
312 : /* end of testing_api_cmd_patch_product.c */
|