LCOV - code coverage report
Current view: top level - json - test_json.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 140 165 84.8 %
Date: 2025-06-05 21:03:14 Functions: 7 7 100.0 %

          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 */

Generated by: LCOV version 1.16