exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

test_json.c (15507B)


      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 "taler/platform.h"
     23 #include "taler/taler_util.h"
     24 #include "taler/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 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     TALER_JSON_spec_amount ("amount",
     40                             "EUR",
     41                             &a2),
     42     GNUNET_JSON_spec_end ()
     43   };
     44 
     45   GNUNET_assert (GNUNET_OK ==
     46                  TALER_string_to_amount ("EUR:4.3",
     47                                          &a1));
     48   j = json_pack ("{s:o}", "amount", TALER_JSON_from_amount (&a1));
     49   GNUNET_assert (NULL != j);
     50   GNUNET_assert (GNUNET_OK ==
     51                  GNUNET_JSON_parse (j, spec,
     52                                     NULL, NULL));
     53   GNUNET_assert (0 ==
     54                  TALER_amount_cmp (&a1,
     55                                    &a2));
     56   json_decref (j);
     57   return 0;
     58 }
     59 
     60 
     61 /**
     62  * Verify JSON packing/parsing for amount arrays.
     63  *
     64  * @return 0 on success
     65  */
     66 static int
     67 test_amount_array (void)
     68 {
     69   struct TALER_Amount amounts[2];
     70   struct TALER_Amount *parsed = NULL;
     71   size_t parsed_len = 0;
     72   struct GNUNET_JSON_Specification spec[2];
     73   json_t *doc;
     74   const size_t num_amounts = sizeof (amounts) / sizeof (amounts[0]);
     75 
     76   GNUNET_assert (GNUNET_OK ==
     77                  TALER_string_to_amount ("EUR:1.2",
     78                                          &amounts[0]));
     79   GNUNET_assert (GNUNET_OK ==
     80                  TALER_string_to_amount ("EUR:3.4",
     81                                          &amounts[1]));
     82 
     83   spec[0] = TALER_JSON_spec_amount_any_array ("amounts",
     84                                               &parsed_len,
     85                                               &parsed);
     86   spec[1] = GNUNET_JSON_spec_end ();
     87 
     88   doc = GNUNET_JSON_PACK (
     89     TALER_JSON_pack_amount_array ("amounts",
     90                                   num_amounts,
     91                                   amounts));
     92   GNUNET_assert (NULL != doc);
     93   GNUNET_assert (GNUNET_OK ==
     94                  GNUNET_JSON_parse (doc,
     95                                     spec,
     96                                     NULL,
     97                                     NULL));
     98   GNUNET_assert (parsed_len == num_amounts);
     99   for (size_t i = 0; i<num_amounts; i++)
    100     GNUNET_assert (0 ==
    101                    TALER_amount_cmp (&amounts[i],
    102                                      &parsed[i]));
    103   GNUNET_JSON_parse_free (spec);
    104   json_decref (doc);
    105 
    106   return 0;
    107 }
    108 
    109 
    110 struct TestPath_Closure
    111 {
    112   const char **object_ids;
    113 
    114   const json_t **parents;
    115 
    116   unsigned int results_length;
    117 
    118   int cmp_result;
    119 };
    120 
    121 
    122 static void
    123 path_cb (void *cls,
    124          const char *object_id,
    125          json_t *parent)
    126 {
    127   struct TestPath_Closure *cmp = cls;
    128   unsigned int i;
    129 
    130   if (NULL == cmp)
    131     return;
    132   i = cmp->results_length;
    133   if ((0 != strcmp (cmp->object_ids[i],
    134                     object_id)) ||
    135       (1 != json_equal (cmp->parents[i],
    136                         parent)))
    137     cmp->cmp_result = 1;
    138   cmp->results_length += 1;
    139 }
    140 
    141 
    142 static int
    143 test_contract (void)
    144 {
    145   struct TALER_PrivateContractHashP h1;
    146   struct TALER_PrivateContractHashP h2;
    147   json_t *c1;
    148   json_t *c2;
    149   json_t *c3;
    150   json_t *c4;
    151 
    152   c1 = json_pack ("{s:s, s:{s:s, s:{s:b}}}",
    153                   "k1", "v1",
    154                   "k2", "n1", "n2",
    155                   /***/ "$forgettable", "n1", true);
    156   GNUNET_assert (GNUNET_OK ==
    157                  TALER_JSON_contract_seed_forgettable (c1,
    158                                                        c1));
    159   GNUNET_assert (GNUNET_OK ==
    160                  TALER_JSON_contract_hash (c1,
    161                                            &h1));
    162   json_decref (c1);
    163 
    164   c1 = json_pack ("{s:s, s:{s:s, s:{s:s}}}",
    165                   "k1", "v1",
    166                   "k2", "n1", "n2",
    167                   /***/ "$forgettable", "n1", "salt");
    168   GNUNET_assert (NULL != c1);
    169   GNUNET_assert (GNUNET_OK ==
    170                  TALER_JSON_contract_mark_forgettable (c1,
    171                                                        "k1"));
    172   GNUNET_assert (GNUNET_OK ==
    173                  TALER_JSON_contract_mark_forgettable (c1,
    174                                                        "k2"));
    175   GNUNET_assert (GNUNET_OK ==
    176                  TALER_JSON_contract_hash (c1,
    177                                            &h1));
    178   GNUNET_assert (GNUNET_OK ==
    179                  TALER_JSON_contract_part_forget (c1,
    180                                                   "k1"));
    181   /* check salt was forgotten */
    182   GNUNET_assert (NULL ==
    183                  json_object_get (json_object_get (c1,
    184                                                    "$forgettable"),
    185                                   "k1"));
    186   GNUNET_assert (GNUNET_OK ==
    187                  TALER_JSON_contract_hash (c1,
    188                                            &h2));
    189   if (0 !=
    190       GNUNET_memcmp (&h1,
    191                      &h2))
    192   {
    193     GNUNET_break (0);
    194     json_decref (c1);
    195     return 1;
    196   }
    197   GNUNET_assert (GNUNET_OK ==
    198                  TALER_JSON_contract_part_forget (json_object_get (c1,
    199                                                                    "k2"),
    200                                                   "n1"));
    201   GNUNET_assert (GNUNET_OK ==
    202                  TALER_JSON_contract_hash (c1,
    203                                            &h2));
    204   if (0 !=
    205       GNUNET_memcmp (&h1,
    206                      &h2))
    207   {
    208     GNUNET_break (0);
    209     json_decref (c1);
    210     return 1;
    211   }
    212   GNUNET_assert (GNUNET_OK ==
    213                  TALER_JSON_contract_part_forget (c1,
    214                                                   "k2"));
    215   // json_dumpf (c1, stderr, JSON_INDENT (2));
    216   GNUNET_assert (GNUNET_OK ==
    217                  TALER_JSON_contract_hash (c1,
    218                                            &h2));
    219   json_decref (c1);
    220   if (0 !=
    221       GNUNET_memcmp (&h1,
    222                      &h2))
    223   {
    224     GNUNET_break (0);
    225     return 1;
    226   }
    227 
    228   c1 = json_pack ("{s:I, s:{s:s}, s:{s:b, s:{s:s}}, s:{s:s}}",
    229                   "k1", 1,
    230                   "$forgettable", "k1", "SALT",
    231                   "k2", "n1", true,
    232                   /***/ "$forgettable", "n1", "salt",
    233                   "k3", "n1", "string");
    234   GNUNET_assert (GNUNET_OK ==
    235                  TALER_JSON_contract_hash (c1,
    236                                            &h1));
    237   // json_dumpf (c1, stderr, JSON_INDENT (2));
    238   json_decref (c1);
    239   {
    240     char *s;
    241 
    242     s = GNUNET_STRINGS_data_to_string_alloc (&h1,
    243                                              sizeof (h1));
    244     if (0 !=
    245         strcmp (s,
    246                 "VDE8JPX0AEEE3EX1K8E11RYEWSZQKGGZCV6BWTE4ST1C8711P7H850Z7F2Q2HSSYETX87ERC2JNHWB7GTDWTDWMM716VKPSRBXD7SRR"))
    247     {
    248       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    249                   "Invalid reference hash: %s\n",
    250                   s);
    251       GNUNET_free (s);
    252       return 1;
    253     }
    254     GNUNET_free (s);
    255   }
    256 
    257 
    258   c2 = json_pack ("{s:s}",
    259                   "n1", "n2");
    260   GNUNET_assert (NULL != c2);
    261   GNUNET_assert (GNUNET_OK ==
    262                  TALER_JSON_contract_mark_forgettable (c2,
    263                                                        "n1"));
    264   c3 = json_pack ("{s:s, s:o}",
    265                   "k1", "v1",
    266                   "k2", c2);
    267   GNUNET_assert (NULL != c3);
    268   GNUNET_assert (GNUNET_OK ==
    269                  TALER_JSON_contract_mark_forgettable (c3,
    270                                                        "k1"));
    271   GNUNET_assert (GNUNET_OK ==
    272                  TALER_JSON_contract_hash (c3,
    273                                            &h1));
    274   GNUNET_assert (GNUNET_OK ==
    275                  TALER_JSON_contract_part_forget (c2,
    276                                                   "n1"));
    277   GNUNET_assert (GNUNET_OK ==
    278                  TALER_JSON_contract_hash (c3,
    279                                            &h2));
    280   json_decref (c3);
    281   c4 = json_pack ("{s:{s:s}, s:[{s:s}, {s:s}, {s:s}]}",
    282                   "abc1",
    283                   "xyz", "value",
    284                   "fruit",
    285                   "name", "banana",
    286                   "name", "apple",
    287                   "name", "orange");
    288   GNUNET_assert (NULL != c4);
    289   GNUNET_assert (GNUNET_SYSERR ==
    290                  TALER_JSON_expand_path (c4,
    291                                          "%.xyz",
    292                                          &path_cb,
    293                                          NULL));
    294   GNUNET_assert (GNUNET_OK ==
    295                  TALER_JSON_expand_path (c4,
    296                                          "$.nonexistent_id",
    297                                          &path_cb,
    298                                          NULL));
    299   GNUNET_assert (GNUNET_SYSERR ==
    300                  TALER_JSON_expand_path (c4,
    301                                          "$.fruit[n]",
    302                                          &path_cb,
    303                                          NULL));
    304 
    305   {
    306     const char *object_ids[] = { "xyz" };
    307     const json_t *parents[] = {
    308       json_object_get (c4,
    309                        "abc1")
    310     };
    311     struct TestPath_Closure tp = {
    312       .object_ids = object_ids,
    313       .parents = parents,
    314       .results_length = 0,
    315       .cmp_result = 0
    316     };
    317     GNUNET_assert (GNUNET_OK ==
    318                    TALER_JSON_expand_path (c4,
    319                                            "$.abc1.xyz",
    320                                            &path_cb,
    321                                            &tp));
    322     GNUNET_assert (1 == tp.results_length);
    323     GNUNET_assert (0 == tp.cmp_result);
    324   }
    325   {
    326     const char *object_ids[] = { "name" };
    327     const json_t *parents[] = {
    328       json_array_get (json_object_get (c4,
    329                                        "fruit"),
    330                       0)
    331     };
    332     struct TestPath_Closure tp = {
    333       .object_ids = object_ids,
    334       .parents = parents,
    335       .results_length = 0,
    336       .cmp_result = 0
    337     };
    338     GNUNET_assert (GNUNET_OK ==
    339                    TALER_JSON_expand_path (c4,
    340                                            "$.fruit[0].name",
    341                                            &path_cb,
    342                                            &tp));
    343     GNUNET_assert (1 == tp.results_length);
    344     GNUNET_assert (0 == tp.cmp_result);
    345   }
    346   {
    347     const char *object_ids[] = { "name", "name", "name" };
    348     const json_t *parents[] = {
    349       json_array_get (json_object_get (c4,
    350                                        "fruit"),
    351                       0),
    352       json_array_get (json_object_get (c4,
    353                                        "fruit"),
    354                       1),
    355       json_array_get (json_object_get (c4,
    356                                        "fruit"),
    357                       2)
    358     };
    359     struct TestPath_Closure tp = {
    360       .object_ids = object_ids,
    361       .parents = parents,
    362       .results_length = 0,
    363       .cmp_result = 0
    364     };
    365     GNUNET_assert (GNUNET_OK ==
    366                    TALER_JSON_expand_path (c4,
    367                                            "$.fruit[*].name",
    368                                            &path_cb,
    369                                            &tp));
    370     GNUNET_assert (3 == tp.results_length);
    371     GNUNET_assert (0 == tp.cmp_result);
    372   }
    373   json_decref (c4);
    374   if (0 !=
    375       GNUNET_memcmp (&h1,
    376                      &h2))
    377   {
    378     GNUNET_break (0);
    379     return 1;
    380   }
    381   return 0;
    382 }
    383 
    384 
    385 static int
    386 test_json_canon (void)
    387 {
    388   {
    389     json_t *c1;
    390     char *canon;
    391     c1 = json_pack ("{s:s}",
    392                     "k1", "Hello\nWorld");
    393 
    394     canon = TALER_JSON_canonicalize (c1);
    395     GNUNET_assert (NULL != canon);
    396 
    397     printf ("canon: '%s'\n", canon);
    398 
    399     GNUNET_assert (0 == strcmp (canon,
    400                                 "{\"k1\":\"Hello\\nWorld\"}"));
    401   }
    402   {
    403     json_t *c1;
    404     char *canon;
    405     c1 = json_pack ("{s:s}",
    406                     "k1", "Testing “unicode” characters");
    407 
    408     canon = TALER_JSON_canonicalize (c1);
    409     GNUNET_assert (NULL != canon);
    410 
    411     printf ("canon: '%s'\n", canon);
    412 
    413     GNUNET_assert (0 == strcmp (canon,
    414                                 "{\"k1\":\"Testing “unicode” characters\"}"));
    415   }
    416   {
    417     json_t *c1;
    418     char *canon;
    419     c1 = json_pack ("{s:s}",
    420                     "k1", "low range \x05 chars");
    421 
    422     canon = TALER_JSON_canonicalize (c1);
    423     GNUNET_assert (NULL != canon);
    424 
    425     printf ("canon: '%s'\n", canon);
    426 
    427     GNUNET_assert (0 == strcmp (canon,
    428                                 "{\"k1\":\"low range \\u0005 chars\"}"));
    429   }
    430 
    431 
    432   return 0;
    433 }
    434 
    435 
    436 static int
    437 test_rfc8785 (void)
    438 {
    439   struct TALER_PrivateContractHashP h1;
    440   json_t *c1;
    441 
    442   c1 = json_pack ("{s:s}",
    443                   "k1", "\x08\x0B\t\1\\\x0d");
    444   GNUNET_assert (GNUNET_OK ==
    445                  TALER_JSON_contract_hash (c1,
    446                                            &h1));
    447   {
    448     char *s;
    449 
    450     s = GNUNET_STRINGS_data_to_string_alloc (&h1,
    451                                              sizeof (h1));
    452     if (0 !=
    453         strcmp (s,
    454                 "531S33T8ZRGW6548G7T67PMDNGS4Z1D8A2GMB87G3PNKYTW6KGF7Q99XVCGXBKVA2HX6PR5ENJ1PQ5ZTYMMXQB6RM7S82VP7ZG2X5G8"))
    455     {
    456       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    457                   "Invalid reference hash: %s\n",
    458                   s);
    459       GNUNET_free (s);
    460       json_decref (c1);
    461       return 1;
    462     }
    463     GNUNET_free (s);
    464   }
    465   json_decref (c1);
    466   return 0;
    467 }
    468 
    469 
    470 static int
    471 test_array (void)
    472 {
    473   struct _data
    474   {
    475     char chars[2];
    476   };
    477   struct _data *data;
    478   size_t num_data;
    479   struct GNUNET_JSON_Specification spec[] = {
    480     TALER_JSON_spec_array_of_data ("nums",
    481                                    sizeof(*data),
    482                                    &num_data,
    483                                    (void **) &data),
    484     GNUNET_JSON_spec_end ()
    485   };
    486   json_t *d;
    487   const char *buf[] = {
    488     "01", "02", "03", "04",
    489     "Aa", "Bb", "Cc", "Dd"
    490   };
    491 
    492   d = json_pack ("{s:[s:s:s:s:s:s:s:s]}",
    493                  "nums",
    494                  "60RG","60S0","60SG","60T0",
    495                  "85GG","89H0","8DHG","8HJ0");
    496   GNUNET_assert (NULL != d);
    497   printf ("sizeof(*data)=%ld\n", sizeof(*data));
    498   printf ("array:>>%s<<\n", json_dumps (d, JSON_INDENT (2)));
    499   GNUNET_assert (GNUNET_OK ==
    500                  GNUNET_JSON_parse (d, spec,
    501                                     NULL, NULL));
    502   GNUNET_assert (sizeof(buf) / sizeof(*buf) == num_data);
    503   for (uint8_t i = 0; i<num_data; i++)
    504   {
    505     printf ("buf[%d]=%s vs data[%d]=%c%c\n",
    506             i, buf[i],
    507             i, data[i].chars[0], data[i].chars[1]);
    508     if (0 != memcmp (buf[i],&data[i], sizeof(*data)))
    509       return 2;
    510   }
    511   return 0;
    512 }
    513 
    514 
    515 int
    516 main (int argc,
    517       const char *const argv[])
    518 {
    519   (void) argc;
    520   (void) argv;
    521   GNUNET_log_setup ("test-json",
    522                     "WARNING",
    523                     NULL);
    524   if (0 != test_amount ())
    525     return 1;
    526   if (0 != test_amount_array ())
    527     return 1;
    528   if (0 != test_contract ())
    529     return 2;
    530   if (0 != test_json_canon ())
    531     return 2;
    532   if (0 != test_rfc8785 ())
    533     return 2;
    534   if (0 != test_array ())
    535     return 2;
    536   return 0;
    537 }
    538 
    539 
    540 /* end of test_json.c */