Line data Source code
1 : /*
2 : This file is part of TALER
3 : (C) 2015, 2016, 2020 Taler Systems SA
4 :
5 : TALER is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 3, or (at your option) any later version.
8 :
9 : TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 : WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 : A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 :
13 : You should have received a copy of the GNU General Public License along with
14 : TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
15 : */
16 :
17 : /**
18 : * @file json/test_json.c
19 : * @brief Tests for Taler-specific crypto logic
20 : * @author Christian Grothoff <christian@grothoff.org>
21 : */
22 : #include "platform.h"
23 : #include "taler_util.h"
24 : #include "taler_json_lib.h"
25 :
26 :
27 : /**
28 : * Test amount conversion from/to JSON.
29 : *
30 : * @return 0 on success
31 : */
32 : static int
33 1 : test_amount (void)
34 : {
35 : json_t *j;
36 : struct TALER_Amount a1;
37 : struct TALER_Amount a2;
38 : struct GNUNET_JSON_Specification spec[] = {
39 1 : TALER_JSON_spec_amount ("amount",
40 : "EUR",
41 : &a2),
42 1 : GNUNET_JSON_spec_end ()
43 : };
44 :
45 1 : GNUNET_assert (GNUNET_OK ==
46 : TALER_string_to_amount ("EUR:4.3",
47 : &a1));
48 1 : j = json_pack ("{s:o}", "amount", TALER_JSON_from_amount (&a1));
49 1 : GNUNET_assert (NULL != j);
50 1 : GNUNET_assert (GNUNET_OK ==
51 : GNUNET_JSON_parse (j, spec,
52 : NULL, NULL));
53 1 : GNUNET_assert (0 ==
54 : TALER_amount_cmp (&a1,
55 : &a2));
56 1 : json_decref (j);
57 1 : return 0;
58 : }
59 :
60 :
61 : struct TestPath_Closure
62 : {
63 : const char **object_ids;
64 :
65 : const json_t **parents;
66 :
67 : unsigned int results_length;
68 :
69 : int cmp_result;
70 : };
71 :
72 :
73 : static void
74 5 : path_cb (void *cls,
75 : const char *object_id,
76 : json_t *parent)
77 : {
78 5 : struct TestPath_Closure *cmp = cls;
79 : unsigned int i;
80 :
81 5 : if (NULL == cmp)
82 0 : return;
83 5 : i = cmp->results_length;
84 5 : if ((0 != strcmp (cmp->object_ids[i],
85 5 : object_id)) ||
86 5 : (1 != json_equal (cmp->parents[i],
87 : parent)))
88 0 : cmp->cmp_result = 1;
89 5 : cmp->results_length += 1;
90 : }
91 :
92 :
93 : static int
94 1 : test_contract (void)
95 : {
96 : struct TALER_PrivateContractHashP h1;
97 : struct TALER_PrivateContractHashP h2;
98 : json_t *c1;
99 : json_t *c2;
100 : json_t *c3;
101 : json_t *c4;
102 :
103 1 : c1 = json_pack ("{s:s, s:{s:s, s:{s:b}}}",
104 : "k1", "v1",
105 : "k2", "n1", "n2",
106 : /***/ "$forgettable", "n1", true);
107 1 : GNUNET_assert (GNUNET_OK ==
108 : TALER_JSON_contract_seed_forgettable (c1,
109 : c1));
110 1 : GNUNET_assert (GNUNET_OK ==
111 : TALER_JSON_contract_hash (c1,
112 : &h1));
113 1 : json_decref (c1);
114 :
115 1 : c1 = json_pack ("{s:s, s:{s:s, s:{s:s}}}",
116 : "k1", "v1",
117 : "k2", "n1", "n2",
118 : /***/ "$forgettable", "n1", "salt");
119 1 : GNUNET_assert (NULL != c1);
120 1 : GNUNET_assert (GNUNET_OK ==
121 : TALER_JSON_contract_mark_forgettable (c1,
122 : "k1"));
123 1 : GNUNET_assert (GNUNET_OK ==
124 : TALER_JSON_contract_mark_forgettable (c1,
125 : "k2"));
126 1 : GNUNET_assert (GNUNET_OK ==
127 : TALER_JSON_contract_hash (c1,
128 : &h1));
129 1 : GNUNET_assert (GNUNET_OK ==
130 : TALER_JSON_contract_part_forget (c1,
131 : "k1"));
132 : /* check salt was forgotten */
133 1 : GNUNET_assert (NULL ==
134 : json_object_get (json_object_get (c1,
135 : "$forgettable"),
136 : "k1"));
137 1 : GNUNET_assert (GNUNET_OK ==
138 : TALER_JSON_contract_hash (c1,
139 : &h2));
140 1 : if (0 !=
141 1 : GNUNET_memcmp (&h1,
142 : &h2))
143 : {
144 0 : GNUNET_break (0);
145 0 : json_decref (c1);
146 0 : return 1;
147 : }
148 1 : GNUNET_assert (GNUNET_OK ==
149 : TALER_JSON_contract_part_forget (json_object_get (c1,
150 : "k2"),
151 : "n1"));
152 1 : GNUNET_assert (GNUNET_OK ==
153 : TALER_JSON_contract_hash (c1,
154 : &h2));
155 1 : if (0 !=
156 1 : GNUNET_memcmp (&h1,
157 : &h2))
158 : {
159 0 : GNUNET_break (0);
160 0 : json_decref (c1);
161 0 : return 1;
162 : }
163 1 : GNUNET_assert (GNUNET_OK ==
164 : TALER_JSON_contract_part_forget (c1,
165 : "k2"));
166 : // json_dumpf (c1, stderr, JSON_INDENT (2));
167 1 : GNUNET_assert (GNUNET_OK ==
168 : TALER_JSON_contract_hash (c1,
169 : &h2));
170 1 : json_decref (c1);
171 1 : if (0 !=
172 1 : GNUNET_memcmp (&h1,
173 : &h2))
174 : {
175 0 : GNUNET_break (0);
176 0 : return 1;
177 : }
178 :
179 1 : c1 = json_pack ("{s:I, s:{s:s}, s:{s:b, s:{s:s}}, s:{s:s}}",
180 : "k1", 1,
181 : "$forgettable", "k1", "SALT",
182 : "k2", "n1", true,
183 : /***/ "$forgettable", "n1", "salt",
184 : "k3", "n1", "string");
185 1 : GNUNET_assert (GNUNET_OK ==
186 : TALER_JSON_contract_hash (c1,
187 : &h1));
188 : // json_dumpf (c1, stderr, JSON_INDENT (2));
189 1 : json_decref (c1);
190 : {
191 : char *s;
192 :
193 1 : s = GNUNET_STRINGS_data_to_string_alloc (&h1,
194 : sizeof (h1));
195 1 : if (0 !=
196 1 : strcmp (s,
197 : "VDE8JPX0AEEE3EX1K8E11RYEWSZQKGGZCV6BWTE4ST1C8711P7H850Z7F2Q2HSSYETX87ERC2JNHWB7GTDWTDWMM716VKPSRBXD7SRR"))
198 : {
199 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
200 : "Invalid reference hash: %s\n",
201 : s);
202 0 : GNUNET_free (s);
203 0 : return 1;
204 : }
205 1 : GNUNET_free (s);
206 : }
207 :
208 :
209 1 : c2 = json_pack ("{s:s}",
210 : "n1", "n2");
211 1 : GNUNET_assert (NULL != c2);
212 1 : GNUNET_assert (GNUNET_OK ==
213 : TALER_JSON_contract_mark_forgettable (c2,
214 : "n1"));
215 1 : c3 = json_pack ("{s:s, s:o}",
216 : "k1", "v1",
217 : "k2", c2);
218 1 : GNUNET_assert (NULL != c3);
219 1 : GNUNET_assert (GNUNET_OK ==
220 : TALER_JSON_contract_mark_forgettable (c3,
221 : "k1"));
222 1 : GNUNET_assert (GNUNET_OK ==
223 : TALER_JSON_contract_hash (c3,
224 : &h1));
225 1 : GNUNET_assert (GNUNET_OK ==
226 : TALER_JSON_contract_part_forget (c2,
227 : "n1"));
228 1 : GNUNET_assert (GNUNET_OK ==
229 : TALER_JSON_contract_hash (c3,
230 : &h2));
231 1 : json_decref (c3);
232 1 : c4 = json_pack ("{s:{s:s}, s:[{s:s}, {s:s}, {s:s}]}",
233 : "abc1",
234 : "xyz", "value",
235 : "fruit",
236 : "name", "banana",
237 : "name", "apple",
238 : "name", "orange");
239 1 : GNUNET_assert (NULL != c4);
240 1 : GNUNET_assert (GNUNET_SYSERR ==
241 : TALER_JSON_expand_path (c4,
242 : "%.xyz",
243 : &path_cb,
244 : NULL));
245 1 : GNUNET_assert (GNUNET_OK ==
246 : TALER_JSON_expand_path (c4,
247 : "$.nonexistent_id",
248 : &path_cb,
249 : NULL));
250 1 : GNUNET_assert (GNUNET_SYSERR ==
251 : TALER_JSON_expand_path (c4,
252 : "$.fruit[n]",
253 : &path_cb,
254 : NULL));
255 :
256 : {
257 1 : const char *object_ids[] = { "xyz" };
258 1 : const json_t *parents[] = {
259 1 : json_object_get (c4,
260 : "abc1")
261 : };
262 1 : struct TestPath_Closure tp = {
263 : .object_ids = object_ids,
264 : .parents = parents,
265 : .results_length = 0,
266 : .cmp_result = 0
267 : };
268 1 : GNUNET_assert (GNUNET_OK ==
269 : TALER_JSON_expand_path (c4,
270 : "$.abc1.xyz",
271 : &path_cb,
272 : &tp));
273 1 : GNUNET_assert (1 == tp.results_length);
274 1 : GNUNET_assert (0 == tp.cmp_result);
275 : }
276 : {
277 1 : const char *object_ids[] = { "name" };
278 1 : const json_t *parents[] = {
279 1 : json_array_get (json_object_get (c4,
280 : "fruit"),
281 : 0)
282 : };
283 1 : struct TestPath_Closure tp = {
284 : .object_ids = object_ids,
285 : .parents = parents,
286 : .results_length = 0,
287 : .cmp_result = 0
288 : };
289 1 : GNUNET_assert (GNUNET_OK ==
290 : TALER_JSON_expand_path (c4,
291 : "$.fruit[0].name",
292 : &path_cb,
293 : &tp));
294 1 : GNUNET_assert (1 == tp.results_length);
295 1 : GNUNET_assert (0 == tp.cmp_result);
296 : }
297 : {
298 1 : const char *object_ids[] = { "name", "name", "name" };
299 3 : const json_t *parents[] = {
300 1 : json_array_get (json_object_get (c4,
301 : "fruit"),
302 : 0),
303 1 : json_array_get (json_object_get (c4,
304 : "fruit"),
305 : 1),
306 1 : json_array_get (json_object_get (c4,
307 : "fruit"),
308 : 2)
309 : };
310 1 : struct TestPath_Closure tp = {
311 : .object_ids = object_ids,
312 : .parents = parents,
313 : .results_length = 0,
314 : .cmp_result = 0
315 : };
316 1 : GNUNET_assert (GNUNET_OK ==
317 : TALER_JSON_expand_path (c4,
318 : "$.fruit[*].name",
319 : &path_cb,
320 : &tp));
321 1 : GNUNET_assert (3 == tp.results_length);
322 1 : GNUNET_assert (0 == tp.cmp_result);
323 : }
324 1 : json_decref (c4);
325 1 : if (0 !=
326 1 : GNUNET_memcmp (&h1,
327 : &h2))
328 : {
329 0 : GNUNET_break (0);
330 0 : return 1;
331 : }
332 1 : return 0;
333 : }
334 :
335 :
336 : static int
337 1 : test_json_canon (void)
338 : {
339 : {
340 : json_t *c1;
341 : char *canon;
342 1 : c1 = json_pack ("{s:s}",
343 : "k1", "Hello\nWorld");
344 :
345 1 : canon = TALER_JSON_canonicalize (c1);
346 1 : GNUNET_assert (NULL != canon);
347 :
348 1 : printf ("canon: '%s'\n", canon);
349 :
350 1 : GNUNET_assert (0 == strcmp (canon,
351 : "{\"k1\":\"Hello\\nWorld\"}"));
352 : }
353 : {
354 : json_t *c1;
355 : char *canon;
356 1 : c1 = json_pack ("{s:s}",
357 : "k1", "Testing “unicode” characters");
358 :
359 1 : canon = TALER_JSON_canonicalize (c1);
360 1 : GNUNET_assert (NULL != canon);
361 :
362 1 : printf ("canon: '%s'\n", canon);
363 :
364 1 : GNUNET_assert (0 == strcmp (canon,
365 : "{\"k1\":\"Testing “unicode” characters\"}"));
366 : }
367 : {
368 : json_t *c1;
369 : char *canon;
370 1 : c1 = json_pack ("{s:s}",
371 : "k1", "low range \x05 chars");
372 :
373 1 : canon = TALER_JSON_canonicalize (c1);
374 1 : GNUNET_assert (NULL != canon);
375 :
376 1 : printf ("canon: '%s'\n", canon);
377 :
378 1 : GNUNET_assert (0 == strcmp (canon,
379 : "{\"k1\":\"low range \\u0005 chars\"}"));
380 : }
381 :
382 :
383 1 : return 0;
384 : }
385 :
386 :
387 : static int
388 1 : test_rfc8785 (void)
389 : {
390 : struct TALER_PrivateContractHashP h1;
391 : json_t *c1;
392 :
393 1 : c1 = json_pack ("{s:s}",
394 : "k1", "\x08\x0B\t\1\\\x0d");
395 1 : GNUNET_assert (GNUNET_OK ==
396 : TALER_JSON_contract_hash (c1,
397 : &h1));
398 : {
399 : char *s;
400 :
401 1 : s = GNUNET_STRINGS_data_to_string_alloc (&h1,
402 : sizeof (h1));
403 1 : if (0 !=
404 1 : strcmp (s,
405 : "531S33T8ZRGW6548G7T67PMDNGS4Z1D8A2GMB87G3PNKYTW6KGF7Q99XVCGXBKVA2HX6PR5ENJ1PQ5ZTYMMXQB6RM7S82VP7ZG2X5G8"))
406 : {
407 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
408 : "Invalid reference hash: %s\n",
409 : s);
410 0 : GNUNET_free (s);
411 0 : json_decref (c1);
412 0 : return 1;
413 : }
414 1 : GNUNET_free (s);
415 : }
416 1 : json_decref (c1);
417 1 : return 0;
418 : }
419 :
420 :
421 : static int
422 1 : test_array (void)
423 : {
424 : struct _data
425 : {
426 : char chars[2];
427 : };
428 : struct _data *data;
429 : size_t num_data;
430 : struct GNUNET_JSON_Specification spec[] = {
431 1 : TALER_JSON_spec_array_of_data ("nums",
432 : sizeof(*data),
433 : &num_data,
434 : (void **) &data),
435 1 : GNUNET_JSON_spec_end ()
436 : };
437 : json_t *d;
438 1 : char *buf[] = {"01","02","03","04",
439 : "Aa","Bb","Cc","Dd"};
440 :
441 1 : d = json_pack ("{s:[s:s:s:s:s:s:s:s]}",
442 : "nums",
443 : "60RG","60S0","60SG","60T0",
444 : "85GG","89H0","8DHG","8HJ0");
445 1 : GNUNET_assert (NULL != d);
446 1 : printf ("sizeof(*data)=%ld\n", sizeof(*data));
447 1 : printf ("array:>>%s<<\n", json_dumps (d, JSON_INDENT (2)));
448 1 : GNUNET_assert (GNUNET_OK ==
449 : GNUNET_JSON_parse (d, spec,
450 : NULL, NULL));
451 1 : GNUNET_assert (sizeof(buf) / sizeof(*buf) == num_data);
452 9 : for (uint8_t i = 0; i<num_data; i++)
453 : {
454 8 : printf ("buf[%d]=%s vs data[%d]=%c%c\n",
455 : i, buf[i],
456 8 : i, data[i].chars[0], data[i].chars[1]);
457 8 : if (0 != memcmp (buf[i],&data[i], sizeof(*data)))
458 0 : return 2;
459 : }
460 1 : return 0;
461 : }
462 :
463 :
464 : int
465 1 : main (int argc,
466 : const char *const argv[])
467 : {
468 : (void) argc;
469 : (void) argv;
470 1 : GNUNET_log_setup ("test-json",
471 : "WARNING",
472 : NULL);
473 1 : if (0 != test_amount ())
474 0 : return 1;
475 1 : if (0 != test_contract ())
476 0 : return 2;
477 1 : if (0 != test_json_canon ())
478 0 : return 2;
479 1 : if (0 != test_rfc8785 ())
480 0 : return 2;
481 1 : if (0 != test_array ())
482 0 : return 2;
483 1 : return 0;
484 : }
485 :
486 :
487 : /* end of test_json.c */
|