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 0 : patch_product_cb (void *cls,
123 : const struct TALER_MERCHANT_HttpResponse *hr)
124 : {
125 0 : struct PatchProductState *pis = cls;
126 :
127 0 : pis->iph = NULL;
128 0 : 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 0 : switch (hr->http_status)
139 : {
140 0 : case MHD_HTTP_NO_CONTENT:
141 0 : break;
142 0 : case MHD_HTTP_UNAUTHORIZED:
143 0 : break;
144 0 : case MHD_HTTP_FORBIDDEN:
145 0 : break;
146 0 : case MHD_HTTP_NOT_FOUND:
147 0 : 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 0 : 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 0 : patch_product_run (void *cls,
169 : const struct TALER_TESTING_Command *cmd,
170 : struct TALER_TESTING_Interpreter *is)
171 : {
172 0 : struct PatchProductState *pis = cls;
173 :
174 0 : pis->is = is;
175 0 : pis->iph = TALER_MERCHANT_product_patch (is->ctx,
176 : pis->merchant_url,
177 : pis->product_id,
178 : pis->description,
179 0 : pis->description_i18n,
180 : pis->unit,
181 0 : &pis->price,
182 0 : pis->image,
183 0 : pis->taxes,
184 : pis->total_stock,
185 0 : pis->total_lost,
186 0 : pis->address,
187 : pis->next_restock,
188 : &patch_product_cb,
189 : pis);
190 0 : GNUNET_assert (NULL != pis->iph);
191 0 : }
192 :
193 :
194 : /**
195 : * Offers information from the PATCH /products CMD state to other
196 : * commands.
197 : *
198 : * @param cls closure
199 : * @param[out] ret result (could be anything)
200 : * @param trait name of the trait
201 : * @param index index number of the object to extract.
202 : * @return #GNUNET_OK on success
203 : */
204 : static enum GNUNET_GenericReturnValue
205 0 : patch_product_traits (void *cls,
206 : const void **ret,
207 : const char *trait,
208 : unsigned int index)
209 : {
210 0 : struct PatchProductState *pps = cls;
211 : struct TALER_TESTING_Trait traits[] = {
212 0 : TALER_TESTING_make_trait_product_description (&pps->description),
213 0 : TALER_TESTING_make_trait_i18n_description (pps->description_i18n),
214 0 : TALER_TESTING_make_trait_product_unit (&pps->unit),
215 0 : TALER_TESTING_make_trait_amount (&pps->price),
216 0 : TALER_TESTING_make_trait_product_image (
217 0 : (const char **) &pps->image),
218 0 : TALER_TESTING_make_trait_taxes (pps->taxes),
219 0 : TALER_TESTING_make_trait_product_stock (&pps->total_stock),
220 0 : TALER_TESTING_make_trait_address (pps->address),
221 0 : TALER_TESTING_make_trait_timestamp (0,
222 0 : &pps->next_restock),
223 0 : TALER_TESTING_make_trait_product_id (&pps->product_id),
224 0 : TALER_TESTING_trait_end (),
225 : };
226 :
227 0 : 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 0 : patch_product_cleanup (void *cls,
243 : const struct TALER_TESTING_Command *cmd)
244 : {
245 0 : struct PatchProductState *pis = cls;
246 :
247 0 : 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 0 : json_decref (pis->description_i18n);
254 0 : GNUNET_free (pis->image);
255 0 : json_decref (pis->taxes);
256 0 : json_decref (pis->address);
257 0 : GNUNET_free (pis);
258 0 : }
259 :
260 :
261 : struct TALER_TESTING_Command
262 0 : 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 0 : GNUNET_assert ( (NULL == taxes) ||
281 : json_is_array (taxes));
282 0 : pis = GNUNET_new (struct PatchProductState);
283 0 : pis->merchant_url = merchant_url;
284 0 : pis->product_id = product_id;
285 0 : pis->http_status = http_status;
286 0 : pis->description = description;
287 0 : pis->description_i18n = description_i18n; /* ownership taken */
288 0 : pis->unit = unit;
289 0 : GNUNET_assert (GNUNET_OK ==
290 : TALER_string_to_amount (price,
291 : &pis->price));
292 0 : pis->image = GNUNET_strdup (image);
293 0 : pis->taxes = taxes; /* ownership taken */
294 0 : pis->total_stock = total_stock;
295 0 : pis->total_lost = total_lost;
296 0 : pis->address = address; /* ownership taken */
297 0 : pis->next_restock = next_restock;
298 : {
299 0 : 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 0 : return cmd;
308 : }
309 : }
310 :
311 :
312 : /* end of testing_api_cmd_patch_product.c */
|