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_lock_product.c
21 : * @brief command to test LOCK /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 "POST /products/$ID" CMD.
33 : */
34 : struct LockProductState
35 : {
36 :
37 : /**
38 : * Handle for a "GET product" request.
39 : */
40 : struct TALER_MERCHANT_ProductLockHandle *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 : * UUID that identifies the client holding the lock
59 : */
60 : char *uuid;
61 :
62 : /**
63 : * duration how long should the lock be held
64 : */
65 : struct GNUNET_TIME_Relative duration;
66 :
67 : /**
68 : * how much product should be locked
69 : */
70 : uint32_t quantity;
71 :
72 : /**
73 : * Fractional component of the quantity (units of 1/MERCHANT_UNIT_FRAC_BASE) when
74 : * @e use_fractional_quantity is true.
75 : */
76 : uint32_t quantity_frac;
77 :
78 : /**
79 : * Set to true if @e quantity_frac should be sent along with @e quantity.
80 : */
81 : bool use_fractional_quantity;
82 :
83 : /**
84 : * Expected HTTP response code.
85 : */
86 : unsigned int http_status;
87 :
88 : };
89 :
90 :
91 : /**
92 : * Callback for a POST /products/$ID/lock operation.
93 : *
94 : * @param cls closure for this function
95 : * @param hr response being processed
96 : */
97 : static void
98 12 : lock_product_cb (void *cls,
99 : const struct TALER_MERCHANT_HttpResponse *hr)
100 : {
101 12 : struct LockProductState *pis = cls;
102 :
103 12 : pis->iph = NULL;
104 12 : if (pis->http_status != hr->http_status)
105 : {
106 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
107 : "Unexpected response code %u (%d) to command %s\n",
108 : hr->http_status,
109 : (int) hr->ec,
110 : TALER_TESTING_interpreter_get_current_label (pis->is));
111 0 : TALER_TESTING_interpreter_fail (pis->is);
112 0 : return;
113 : }
114 12 : switch (hr->http_status)
115 : {
116 6 : case MHD_HTTP_NO_CONTENT:
117 6 : break;
118 0 : case MHD_HTTP_FORBIDDEN:
119 0 : break;
120 2 : case MHD_HTTP_NOT_FOUND:
121 2 : break;
122 2 : case MHD_HTTP_GONE:
123 2 : break;
124 2 : default:
125 2 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
126 : "Unhandled HTTP status %u for lock product.\n",
127 : hr->http_status);
128 : }
129 12 : TALER_TESTING_interpreter_next (pis->is);
130 : }
131 :
132 :
133 : /**
134 : * Run the "LOCK /products/$ID" CMD.
135 : *
136 : *
137 : * @param cls closure.
138 : * @param cmd command being run now.
139 : * @param is interpreter state.
140 : */
141 : static void
142 12 : lock_product_run (void *cls,
143 : const struct TALER_TESTING_Command *cmd,
144 : struct TALER_TESTING_Interpreter *is)
145 : {
146 12 : struct LockProductState *pis = cls;
147 :
148 12 : pis->is = is;
149 12 : if (pis->use_fractional_quantity)
150 : {
151 4 : pis->iph = TALER_MERCHANT_product_lock2 (
152 : TALER_TESTING_interpreter_get_context (is),
153 : pis->merchant_url,
154 : pis->product_id,
155 4 : pis->uuid,
156 : pis->duration,
157 4 : pis->quantity,
158 : pis->quantity_frac,
159 : true,
160 : &lock_product_cb,
161 : pis);
162 : }
163 : else
164 : {
165 8 : pis->iph = TALER_MERCHANT_product_lock (
166 : TALER_TESTING_interpreter_get_context (is),
167 : pis->merchant_url,
168 : pis->product_id,
169 8 : pis->uuid,
170 : pis->duration,
171 : pis->quantity,
172 : &lock_product_cb,
173 : pis);
174 : }
175 12 : GNUNET_assert (NULL != pis->iph);
176 12 : }
177 :
178 :
179 : /**
180 : * Free the state of a "GET product" CMD, and possibly
181 : * cancel a pending operation thereof.
182 : *
183 : * @param cls closure.
184 : * @param cmd command being run.
185 : */
186 : static void
187 12 : lock_product_cleanup (void *cls,
188 : const struct TALER_TESTING_Command *cmd)
189 : {
190 12 : struct LockProductState *pis = cls;
191 :
192 12 : if (NULL != pis->iph)
193 : {
194 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
195 : "POST /product/$ID/lock operation did not complete\n");
196 0 : TALER_MERCHANT_product_lock_cancel (pis->iph);
197 : }
198 12 : GNUNET_free (pis->uuid);
199 12 : GNUNET_free (pis);
200 12 : }
201 :
202 :
203 : /**
204 : * Offer internal data to other commands.
205 : *
206 : * @param cls closure
207 : * @param[out] ret result (could be anything)
208 : * @param trait name of the trait
209 : * @param index index number of the object to extract.
210 : * @return #GNUNET_OK on success
211 : */
212 : static enum GNUNET_GenericReturnValue
213 2 : lock_product_traits (void *cls,
214 : const void **ret,
215 : const char *trait,
216 : unsigned int index)
217 : {
218 2 : struct LockProductState *lps = cls;
219 : struct TALER_TESTING_Trait traits[] = {
220 2 : TALER_TESTING_make_trait_lock_uuid (lps->uuid),
221 2 : TALER_TESTING_trait_end ()
222 : };
223 :
224 2 : return TALER_TESTING_get_trait (traits,
225 : ret,
226 : trait,
227 : index);
228 : }
229 :
230 :
231 : struct TALER_TESTING_Command
232 12 : TALER_TESTING_cmd_merchant_lock_product (
233 : const char *label,
234 : const char *merchant_url,
235 : const char *product_id,
236 : struct GNUNET_TIME_Relative duration,
237 : uint32_t quantity,
238 : unsigned int http_status)
239 : {
240 : struct LockProductState *pis;
241 : struct GNUNET_Uuid uuid;
242 :
243 12 : pis = GNUNET_new (struct LockProductState);
244 12 : pis->merchant_url = merchant_url;
245 12 : pis->product_id = product_id;
246 12 : pis->http_status = http_status;
247 12 : GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
248 : &uuid,
249 : sizeof (struct GNUNET_Uuid));
250 12 : pis->uuid = GNUNET_STRINGS_data_to_string_alloc (&uuid,
251 : sizeof (uuid));
252 12 : pis->duration = duration;
253 12 : pis->quantity = quantity;
254 12 : pis->quantity_frac = 0;
255 12 : pis->use_fractional_quantity = false;
256 :
257 : {
258 12 : struct TALER_TESTING_Command cmd = {
259 : .cls = pis,
260 : .label = label,
261 : .run = &lock_product_run,
262 : .cleanup = &lock_product_cleanup,
263 : .traits = &lock_product_traits
264 : };
265 :
266 12 : return cmd;
267 : }
268 : }
269 :
270 :
271 : struct TALER_TESTING_Command
272 4 : TALER_TESTING_cmd_merchant_lock_product2 (
273 : const char *label,
274 : const char *merchant_url,
275 : const char *product_id,
276 : struct GNUNET_TIME_Relative duration,
277 : uint32_t quantity,
278 : uint32_t quantity_frac,
279 : bool use_fractional_quantity,
280 : unsigned int http_status)
281 : {
282 : struct LockProductState *pis;
283 : struct TALER_TESTING_Command cmd;
284 :
285 4 : cmd = TALER_TESTING_cmd_merchant_lock_product (label,
286 : merchant_url,
287 : product_id,
288 : duration,
289 : quantity,
290 : http_status);
291 4 : pis = cmd.cls;
292 4 : pis->quantity_frac = quantity_frac;
293 4 : pis->use_fractional_quantity = use_fractional_quantity;
294 4 : return cmd;
295 : }
296 :
297 :
298 : /* end of testing_api_cmd_lock_product.c */
|