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 (15479B)


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