LCOV - code coverage report
Current view: top level - util - test_contract.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 91 91
Test Date: 2026-09-11 17:45:24 Functions: 100.0 % 1 1

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   (C) 2015, 2021 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 src/util/test_contract.c
      19              :  * @brief Tests for contract parsing/serializing
      20              :  * @author Iván Ávalos (ivan@avalos.me)
      21              :  */
      22              : 
      23              : #include "platform.h"
      24              : #include <gnunet/gnunet_util_lib.h>
      25              : #include <gnunet/gnunet_common.h>
      26              : #include <gnunet/gnunet_json_lib.h>
      27              : #include "taler/taler_merchant_util.h"
      28              : #include <jansson.h>
      29              : 
      30              : const char *contract_common = "{\n"
      31              :                               "  \"summary\": \"Test order\",\n"
      32              :                               "  \"summary_i18n\": {\n"
      33              :                               "    \"en\": \"Test order\",\n"
      34              :                               "    \"es\": \"Orden de prueba\"\n"
      35              :                               "  },\n"
      36              :                               "  \"order_id\": \"test\",\n"
      37              :                               "  \"public_reorder_url\": \"https://test.org/reorder\",\n"
      38              :                               "  \"fulfillment_url\": \"https://test.org/fulfillment\",\n"
      39              :                               "  \"fulfillment_message\": \"Thank you for your purchase!\",\n"
      40              :                               "  \"fulfillment_message_i18n\": {\n"
      41              :                               "    \"en\": \"Thank you for your purchase!\",\n"
      42              :                               "    \"es\": \"¡Gracias por su compra!\"\n"
      43              :                               "  },\n"
      44              :                               "  \"products\": [],\n"
      45              :                               "  \"timestamp\": {\"t_s\": 1736174497},\n"
      46              :                               "  \"refund_deadline\": {\"t_s\": 1736174497},\n"
      47              :                               "  \"pay_deadline\": {\"t_s\": 1736174497},\n"
      48              :                               "  \"wire_transfer_deadline\": {\"t_s\": 1736174497},\n"
      49              :                               "  \"merchant_pub\": \"F80MFRG8HVH6R9CQ47KRFQSJP3T6DBJ4K1D9B703RJY3Z39TBMJ0\",\n"
      50              :                               "  \"merchant_base_url\": \"https://test.org/merchant\",\n"
      51              :                               "  \"merchant\": {\n"
      52              :                               "    \"name\": \"Test merchant\",\n"
      53              :                               "    \"email\": \"test@test.org\",\n"
      54              :                               "    \"website\": \"https://test.org/merchant\",\n"
      55              :                               "    \"logo\": \"data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAA7EAAAOxAGVKw4bAAADRUlEQVRYhe2WXUgUURiG39l1Vt021C2piJAQyhXEXVNKysoSd8nywgLNn1CIMCLposCLxOii8KasC2+CFB1WRVASMpMUKiyIaLXyBwmhoh9Kzc1W929murAZ9+znZl2EXey5OvOc93zfO+ec+eZwZmuLjFVsmtVMHjYQNvBfGIhYSSAD6LcXYJ1RrzLO1AhzAg9oNHD0FGPBLSJ2bwuSjRE4U2rCydIdmJpxIae4C9wK8blQdUCWgaH7pepzZXUf3rx34eqFXcgwbwIANLUP40bjKzzuLIRBzwMATFY7ojgJL3pL1eRmqwAuhJNlDSiTTQebEcUv7pKjd9GMxSaouj9hHp+M0f4yeH0Sdh6xEwPkDOTu2QzuV4CVkltsAkYnptTxQI3CInkOFpsAHa9Byjbj7w2Ikoy6i9lMIh+nDfmWAFBS1UuYonX6OIY13zwEOWi9GQMv+8pwS3Awgtf3jjPJg5ME9wPZZH8Jw7r7JphzRQwAQIMwovZHZ/wkcF11Jj5/cRHumvfjVFES4Z/mRLVfe+0ZGVcNLHglMjg3eALff3gZlrs/ETnFnUSbdtiO0+XpDHN7RIz1FBKtKC3tg2rAtDUG35xuRqjjNdhd2EUC8BH0m9LraE2rrO5DXEwU4ZJ2qfyos6adXqw1RBKx0bBirQrZJj/MEyaKQKxeu4yBWTcitOybuT0i7t7OJ0G8flq7PD7KepryMb/AniOtFph1eqgB3TLLGpPVAsManmF3escx0HqUaB92HENH9wjDDHoeG7PpFxK4hWTjqspT1H6ykS7/pfrn2BCvJzzeGI0rDQ7CE2OXYtScTSfjjIFUq4CKolRGkJrXxhQZpQWyUOPbc9nSW5CXBLOVXRHGgIYDzl8eYAJqRD9JohSe+toswgK1eo3EsPJzPeSnRLag/8lHdYJy2ILru8L2ZSao/4Tg5ApzeaTFWD4Jw+MzwemWvw9YbAJkGRh5UAZg8ddssQmIitapCeZcXlhsAmqq0lX26Ok7bDlgR17Gesas2SaEvBeEvA8oTZaBgbYCGOP0aG534HrjCIam/XAPliFSp0VaXitkUcTQWx/ksQp13tdpF3JLaBH7awP/uq36nTBsIGxg1Q38BGj1Qe2GKmj3AAAAAElFTkSuQmCC\",\n"
      56              :                               "    \"address\": {},\n" // TODO
      57              :                               "    \"jurisdiction\": {}\n" // TODO
      58              :                               "  },\n"
      59              :                               "  \"h_wire\": \"WYEMPXPRA87Y1QBJAJSR5SMB8V3QN2MMHAKDAEN04XC8TQ6TBEJF5KAKT3Y8KKP9W0TW3A2PH1YB22EZJ9TA7HX1P5BFTJQ660GS1TG\",\n"
      60              :                               "  \"wire_method\": \"iban\",\n"
      61              :                               "  \"exchanges\": [],\n"
      62              :                               "  \"delivery_location\": {},\n" // TODO
      63              :                               "  \"delivery_date\": {\"t_s\": 1736174497},\n"
      64              :                               "  \"nonce\": \"test-nonce\",\n"
      65              :                               "  \"auto_refund\": {\"d_us\": \"forever\"},\n"
      66              :                               "  \"extra\": {\n"
      67              :                               "    \"key0\": \"value0\",\n"
      68              :                               "    \"key1\": \"value1\",\n"
      69              :                               "    \"key2\": 2\n"
      70              :                               "  },\n"
      71              :                               "  \"minimum_age\": 100\n"
      72              :                               "}";
      73              : 
      74              : const char *contract_v0 = "{\n"
      75              :                           "  \"version\": 0,\n"
      76              :                           "  \"amount\": \"KUDOS:10\",\n"
      77              :                           "  \"amount_external\": [\n"
      78              :                           "    {\n"
      79              :                           "      \"method\": \"cash\",\n"
      80              :                           "      \"id\": \"cash1\",\n"
      81              :                           "      \"amount\": \"KUDOS:30\",\n"
      82              :                           "      \"cashier_number\": \"7\"\n"
      83              :                           "    },\n"
      84              :                           "    {\n"
      85              :                           "      \"method\": \"card\",\n"
      86              :                           "      \"id\": \"sumup1\",\n"
      87              :                           "      \"amount\": \"KUDOS:5\",\n"
      88              :                           "      \"terminal_id\": 42,\n"
      89              :                           "      \"contactless\": true\n"
      90              :                           "    }\n"
      91              :                           "  ],\n"
      92              :                           "  \"max_fee\": \"KUDOS:0.2\"\n"
      93              :                           "}";
      94              : 
      95              : const char *contract_v1 = "{\n"
      96              :                           "  \"version\": 1,\n"
      97              :                           "  \"amount_external\": [\n"
      98              :                           "    {\n"
      99              :                           "      \"method\": \"cash\",\n"
     100              :                           "      \"id\": \"cash1\",\n"
     101              :                           "      \"amount\": \"KUDOS:3\"\n"
     102              :                           "    }\n"
     103              :                           "  ],\n"
     104              :                           "  \"choices\": [\n"
     105              :                           "    {\n"
     106              :                           "      \"amount\": \"KUDOS:1\",\n"
     107              :                           "      \"max_fee\": \"KUDOS:0.5\",\n"
     108              :                           "      \"description\": \"Subscription in, discount out\",\n"
     109              :                           "      \"description_i18n\": {\n"
     110              :                           "        \"en\": \"This is a test choice\",\n"
     111              :                           "        \"es\": \"Esta es una opción de prueba\"\n"
     112              :                           "      },\n"
     113              :                           "      \"inputs\": [\n"
     114              :                           "        {\n"
     115              :                           "          \"type\": \"token\",\n"
     116              :                           "          \"token_family_slug\": \"test-subscription\",\n"
     117              :                           "          \"count\": 1\n"
     118              :                           "        }\n"
     119              :                           "      ],\n"
     120              :                           "      \"outputs\": [\n"
     121              :                           "        {\n"
     122              :                           "          \"type\": \"token\",\n"
     123              :                           "          \"token_family_slug\": \"test-discount\",\n"
     124              :                           "          \"count\": 2,\n"
     125              :                           "          \"key_index\": 0\n" // TODO
     126              :                           "        },\n"
     127              :                           "        {\n"
     128              :                           "          \"type\": \"tax-receipt\",\n"
     129              :                           "          \"donau_urls\": [\"a\", \"b\", \"c\"],\n"
     130              :                           "          \"amount\": \"KUDOS:10\"\n"
     131              :                           "        }\n"
     132              :                           "      ]\n"
     133              :                           "    }\n"
     134              :                           "  ],\n"
     135              :                           "  \"token_families\": {\n"
     136              :                           "    \"test-subscription\": {\n"
     137              :                           "      \"name\": \"Test subscription\",\n"
     138              :                           "      \"description\": \"This is a test subscription\",\n"
     139              :                           "      \"description_i18n\": {\n"
     140              :                           "        \"en\": \"This is a test subscription\",\n"
     141              :                           "        \"es\": \"Esta es una subscripción de prueba\"\n"
     142              :                           "      },\n"
     143              :                           "      \"keys\": [\n"
     144              :                           "        {\n"
     145              :                           "          \"cipher\": \"CS\",\n"
     146              :                           "          \"cs_pub\": \"AMGKHAWCF3Y32E64G6JV7TPP7KHE2C3QFMNZ8N66Q744FV3TH1D0\",\n"
     147              :                           "          \"signature_validity_start\": {\"t_s\": 1736174497},\n"
     148              :                           "          \"signature_validity_end\": {\"t_s\": 1736174497}\n"
     149              :                           "        }\n"
     150              :                           "      ],\n"
     151              :                           "      \"details\": {\n"
     152              :                           "        \"class\": \"subscription\",\n"
     153              :                           "        \"trusted_domains\": [\"a\", \"b\", \"c\"]\n"
     154              :                           "      },\n"
     155              :                           "      \"critical\": true\n"
     156              :                           "    },\n"
     157              :                           "    \"test-discount\": {\n"
     158              :                           "      \"name\": \"Test discount\",\n"
     159              :                           "      \"description\": \"This is a test discount\",\n"
     160              :                           "      \"description_i18n\": {\n"
     161              :                           "        \"en\": \"This is a test discount\",\n"
     162              :                           "        \"es\": \"Este es un descuento de prueba\"\n"
     163              :                           "      },\n"
     164              :                           "      \"keys\": [\n"
     165              :                           "        {\n"
     166              :                           "          \"cipher\": \"RSA\",\n"
     167              :                           "          \"rsa_pub\": \"040000YGF5DK0PKCN99J0V814C20Q54C82S3RE3GBVC2T4QXEP7N05ABAN5DG8BC3FTN33BSG15VFX2N9X95HE7GBDAHSYHG4G00VHDCV4E0W4HVYTZGN6SGPBMTAE1XMYBH5DFWT4TXPSEQB96AG3G65X6BPQ0WXSARD5NP2YR1CQB6GB0W2BSKZK1AXZN67GHB3HHAPFV8V584QF1DGDXEWN875RN4HYNH3AW4XZ9SP5A7J5MED56P0TXX5D8C1HPWHFD89GE6Q7J0Q3QKM18WAVAZJTF6PR3Q5T2C71ST0VTP42F16ZZRWS4CHSXHM5RW0BGH383VX4100AD61X6QQ99K12Q17EQZK5MSE6AGNK24SCAH06XTXA7WFC78V0ARJKFDX1M483GE9SX20XXFKSTQ6B8104002\",\n"
     168              :                           "          \"signature_validity_start\": {\"t_s\": 1736174497},\n"
     169              :                           "          \"signature_validity_end\": {\"t_s\": 1736174497}\n"
     170              :                           "        }\n"
     171              :                           "      ],\n"
     172              :                           "      \"details\": {\n"
     173              :                           "        \"class\": \"discount\",\n"
     174              :                           "        \"expected_domains\": [\"a\", \"b\", \"c\"]\n"
     175              :                           "      },\n"
     176              :                           "      \"critical\": true\n"
     177              :                           "    }\n"
     178              :                           "  }\n"
     179              :                           "}";
     180              : 
     181              : 
     182              : int
     183            1 : main (int argc,
     184              :       const char *const argv[])
     185              : {
     186              :   (void) argc;
     187              :   (void) argv;
     188            1 :   GNUNET_log_setup ("test-contract",
     189              :                     "WARNING",
     190              :                     NULL);
     191              : 
     192              :   { // Contract v0
     193              :     json_t *common;
     194              :     json_t *v0;
     195              :     struct TALER_MERCHANT_Contract *v0_parsed;
     196              :     json_t *v0_serialized;
     197              : 
     198            1 :     common = json_loads (contract_common, 0, NULL);
     199            1 :     GNUNET_assert (NULL != common);
     200              : 
     201            1 :     v0 = json_loads (contract_v0, 0, NULL);
     202            1 :     GNUNET_assert (NULL != v0);
     203              : 
     204            1 :     GNUNET_assert (0 == json_object_update_new (v0, common));
     205              : 
     206            1 :     v0_parsed = TALER_MERCHANT_contract_parse (v0);
     207            1 :     GNUNET_assert (NULL != v0_parsed);
     208              : 
     209            1 :     v0_serialized = TALER_MERCHANT_contract_serialize (v0_parsed);
     210            1 :     GNUNET_assert (NULL != v0_serialized);
     211            1 :     GNUNET_assert (1 == json_equal (v0, v0_serialized));
     212              : 
     213            1 :     json_decref (v0_serialized);
     214            1 :     TALER_MERCHANT_contract_free (v0_parsed);
     215            1 :     json_decref (v0);
     216              :   }
     217              : 
     218              :   { // Contract v1
     219              :     json_t *common;
     220              :     json_t *v1;
     221              :     struct TALER_MERCHANT_Contract *v1_parsed;
     222              :     json_t *v1_serialized;
     223              : 
     224            1 :     common = json_loads (contract_common, 0, NULL);
     225            1 :     GNUNET_assert (NULL != common);
     226              : 
     227            1 :     v1 = json_loads (contract_v1, 0, NULL);
     228            1 :     GNUNET_assert (NULL != v1);
     229              : 
     230            1 :     GNUNET_assert (0 == json_object_update_new (v1, common));
     231              : 
     232            1 :     v1_parsed = TALER_MERCHANT_contract_parse (v1);
     233            1 :     GNUNET_assert (NULL != v1_parsed);
     234              : 
     235            1 :     v1_serialized = TALER_MERCHANT_contract_serialize (v1_parsed);
     236            1 :     GNUNET_assert (NULL != v1_serialized);
     237              : 
     238            1 :     GNUNET_assert (1 == json_equal (v1, v1_serialized));
     239              : 
     240            1 :     for (unsigned int i = 0;
     241            3 :          i < v1_parsed->pc->details.v1.token_authorities_len;
     242            2 :          i++)
     243              :     {
     244            2 :       struct TALER_MERCHANT_ContractTokenFamily *in =
     245            2 :         &v1_parsed->pc->details.v1.token_authorities[i];
     246            4 :       for (unsigned int j = 0; j < in->keys_len; j++)
     247              :       {
     248            2 :         struct TALER_MERCHANT_ContractTokenFamilyKey *inkey = &in->keys[j];
     249              :         struct TALER_MERCHANT_ContractTokenFamily out;
     250              :         struct TALER_MERCHANT_ContractTokenFamilyKey outkey;
     251            2 :         GNUNET_assert (GNUNET_OK == TALER_MERCHANT_find_token_family_key (
     252              :                          in->slug,
     253              :                          inkey->valid_after,
     254              :                          v1_parsed->pc->details.v1.token_authorities,
     255              :                          v1_parsed->pc->details.v1.token_authorities_len,
     256              :                          &out,
     257              :                          &outkey));
     258            2 :         GNUNET_assert (0 == GNUNET_memcmp (in, &out));
     259            2 :         GNUNET_assert (0 == GNUNET_memcmp (inkey, &outkey));
     260              :       }
     261              :     }
     262              : 
     263            1 :     json_decref (v1_serialized);
     264            1 :     TALER_MERCHANT_contract_free (v1_parsed);
     265            1 :     json_decref (v1);
     266              :   }
     267              : 
     268              :   { // Template pay duration validation
     269              :     json_t *finite;
     270              :     json_t *zero;
     271              :     json_t *omitted;
     272              :     json_t *forever;
     273            1 :     struct TALER_MERCHANT_TemplateContract parsed = { 0 };
     274              : 
     275            1 :     finite = json_pack ("{s:{s:I}}",
     276              :                         "pay_duration",
     277              :                         "d_us",
     278            1 :                         (json_int_t) GNUNET_TIME_UNIT_MINUTES.rel_value_us);
     279            1 :     zero = json_pack ("{s:{s:I}}",
     280              :                       "pay_duration",
     281              :                       "d_us",
     282              :                       (json_int_t) 0);
     283            1 :     omitted = json_object ();
     284            1 :     forever = json_pack ("{s:{s:s}}",
     285              :                          "pay_duration",
     286              :                          "d_us",
     287              :                          "forever");
     288            1 :     GNUNET_assert (TALER_MERCHANT_template_contract_valid (finite));
     289            1 :     GNUNET_assert (TALER_MERCHANT_template_contract_valid (zero));
     290            1 :     GNUNET_assert (TALER_MERCHANT_template_contract_valid (omitted));
     291            1 :     GNUNET_assert (! TALER_MERCHANT_template_contract_valid (forever));
     292              :     /* Legacy templates must remain parseable so they can fall back to the
     293              :        instance default when instantiated. */
     294            1 :     GNUNET_assert (
     295              :       GNUNET_OK ==
     296              :       TALER_MERCHANT_template_contract_parse (forever,
     297              :                                               &parsed,
     298              :                                               NULL));
     299            1 :     GNUNET_assert (GNUNET_TIME_relative_is_forever (parsed.pay_duration));
     300            1 :     TALER_MERCHANT_template_contract_free (&parsed);
     301            1 :     json_decref (finite);
     302            1 :     json_decref (zero);
     303            1 :     json_decref (omitted);
     304            1 :     json_decref (forever);
     305              :   }
     306              : 
     307              :   { // amount_external currency must match all v1 choices
     308              :     json_t *common;
     309              :     json_t *v1;
     310              :     json_t *bad_external;
     311              : 
     312            1 :     common = json_loads (contract_common, 0, NULL);
     313            1 :     GNUNET_assert (NULL != common);
     314            1 :     v1 = json_loads (contract_v1, 0, NULL);
     315            1 :     GNUNET_assert (NULL != v1);
     316            1 :     GNUNET_assert (0 == json_object_update_new (v1, common));
     317            1 :     bad_external = json_loads (
     318              :       "[{\"method\":\"cash\",\"id\":\"cash1\",\"amount\":\"EUR:3\"}]",
     319              :       0,
     320              :       NULL);
     321            1 :     GNUNET_assert (NULL != bad_external);
     322            1 :     GNUNET_assert (0 == json_object_set_new (v1,
     323              :                                              "amount_external",
     324              :                                              bad_external));
     325            1 :     GNUNET_assert (NULL == TALER_MERCHANT_contract_parse (v1));
     326            1 :     json_decref (v1);
     327              :   }
     328              : 
     329              :   { // amount_external validation
     330              :     struct TALER_Amount amount;
     331              :     static const char *invalid[] = {
     332              :       /* method "taler" is reserved */
     333              :       "[{\"method\":\"taler\",\"id\":\"t1\",\"amount\":\"KUDOS:1\"}]",
     334              :       /* entries disagreeing on a currency among themselves */
     335              :       "[{\"method\":\"cash\",\"id\":\"cash1\",\"amount\":\"KUDOS:1\"},"
     336              :       " {\"method\":\"card\",\"id\":\"card1\",\"amount\":\"EUR:1\"}]",
     337              :       /* missing id */
     338              :       "[{\"method\":\"cash\",\"amount\":\"KUDOS:1\"}]",
     339              :       /* missing amount */
     340              :       "[{\"method\":\"cash\",\"id\":\"cash1\"}]",
     341              :       /* empty method name */
     342              :       "[{\"method\":\"\",\"id\":\"cash1\",\"amount\":\"KUDOS:1\"}]",
     343              :       /* method name with blank */
     344              :       "[{\"method\":\"ca sh\",\"id\":\"cash1\",\"amount\":\"KUDOS:1\"}]",
     345              :       /* duplicate id */
     346              :       "[{\"method\":\"cash\",\"id\":\"cash1\",\"amount\":\"KUDOS:1\"},"
     347              :       " {\"method\":\"card\",\"id\":\"cash1\",\"amount\":\"KUDOS:1\"}]",
     348              :       /* nested method-specific field */
     349              :       "[{\"method\":\"cash\",\"id\":\"cash1\",\"amount\":\"KUDOS:1\","
     350              :       "  \"details\":{\"register\":1}}]",
     351              :       NULL
     352              :     };
     353              : 
     354            1 :     GNUNET_assert (GNUNET_OK ==
     355              :                    TALER_string_to_amount ("KUDOS:10",
     356              :                                            &amount));
     357              :     {
     358              :       json_t *valid;
     359              : 
     360            1 :       valid = json_loads (
     361              :         "[{\"method\":\"cash\",\"id\":\"cash1\",\"amount\":\"KUDOS:30\","
     362              :         "  \"cashier_number\":\"7\"}]",
     363              :         0,
     364              :         NULL);
     365            1 :       GNUNET_assert (NULL != valid);
     366            1 :       GNUNET_assert (TALER_MERCHANT_amount_external_valid (valid));
     367              :       /* valid entries in the currency of the order, and not in another */
     368            1 :       GNUNET_assert (TALER_MERCHANT_amount_external_currency_valid (valid,
     369              :                                                                     &amount));
     370              :       {
     371              :         struct TALER_Amount other;
     372              : 
     373            1 :         GNUNET_assert (GNUNET_OK ==
     374              :                        TALER_string_to_amount ("EUR:10",
     375              :                                                &other));
     376            1 :         GNUNET_assert (! TALER_MERCHANT_amount_external_currency_valid (valid,
     377              :                                                                         &other));
     378              :       }
     379            1 :       GNUNET_assert (TALER_MERCHANT_amount_external_total_valid (valid,
     380              :                                                                  &amount));
     381            1 :       json_decref (valid);
     382              :     }
     383              :     { // the order total must stay representable
     384              :       json_t *huge;
     385              :       struct TALER_Amount big;
     386              : 
     387              :       /* Two entries just below the largest representable amount:
     388              :          each is fine on its own, their sum is not. */
     389            1 :       huge = json_loads (
     390              :         "[{\"method\":\"cash\",\"id\":\"cash1\","
     391              :         "  \"amount\":\"KUDOS:4503599627370495\"},"
     392              :         " {\"method\":\"card\",\"id\":\"card1\","
     393              :         "  \"amount\":\"KUDOS:4503599627370495\"}]",
     394              :         0,
     395              :         NULL);
     396            1 :       GNUNET_assert (NULL != huge);
     397              :       /* the entries themselves are perfectly valid */
     398            1 :       GNUNET_assert (TALER_MERCHANT_amount_external_valid (huge));
     399            1 :       GNUNET_assert (TALER_MERCHANT_amount_external_currency_valid (huge,
     400              :                                                                     &amount));
     401              :       /* ... but adding them up overflows */
     402            1 :       GNUNET_assert (! TALER_MERCHANT_amount_external_total_valid (huge,
     403              :                                                                    &amount));
     404            1 :       json_decref (huge);
     405              : 
     406              :       /* A single entry that overflows only once the Taler amount of
     407              :          the order is added to it. */
     408            1 :       huge = json_loads (
     409              :         "[{\"method\":\"cash\",\"id\":\"cash1\","
     410              :         "  \"amount\":\"KUDOS:4503599627370495\"}]",
     411              :         0,
     412              :         NULL);
     413            1 :       GNUNET_assert (NULL != huge);
     414            1 :       GNUNET_assert (GNUNET_OK ==
     415              :                      TALER_string_to_amount ("KUDOS:10",
     416              :                                              &big));
     417            1 :       GNUNET_assert (! TALER_MERCHANT_amount_external_total_valid (huge,
     418              :                                                                    &big));
     419            1 :       json_decref (huge);
     420              :     }
     421            9 :     for (unsigned int i = 0; NULL != invalid[i]; i++)
     422              :     {
     423              :       json_t *j;
     424              : 
     425            8 :       j = json_loads (invalid[i], 0, NULL);
     426            8 :       GNUNET_assert (NULL != j);
     427            8 :       GNUNET_assert (! TALER_MERCHANT_amount_external_valid (j));
     428            8 :       json_decref (j);
     429              :     }
     430              :   }
     431              : 
     432            1 :   return 0;
     433              : }
        

Generated by: LCOV version 2.0-1