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 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_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\": \"\",\n" // TODO
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 : " \"max_fee\": \"KUDOS:0.2\"\n"
78 : "}";
79 :
80 : const char *contract_v1 = "{\n"
81 : " \"version\": 1,\n"
82 : " \"choices\": [\n"
83 : " {\n"
84 : " \"amount\": \"KUDOS:1\",\n"
85 : " \"max_fee\": \"KUDOS:0.5\",\n"
86 : " \"inputs\": [\n"
87 : " {\n"
88 : " \"type\": \"token\",\n"
89 : " \"token_family_slug\": \"test-subscription\",\n"
90 : " \"count\": 1\n"
91 : " }\n"
92 : " ],\n"
93 : " \"outputs\": [\n"
94 : " {\n"
95 : " \"type\": \"token\",\n"
96 : " \"token_family_slug\": \"test-discount\",\n"
97 : " \"count\": 2,\n"
98 : " \"key_index\": 0\n" // TODO
99 : " },\n"
100 : " {\n"
101 : " \"type\": \"tax-receipt\",\n"
102 : " \"donau_urls\": [\"a\", \"b\", \"c\"],\n"
103 : " \"amount\": \"KUDOS:10\"\n"
104 : " }\n"
105 : " ]\n"
106 : " }\n"
107 : " ],\n"
108 : " \"token_families\": {\n"
109 : " \"test-subscription\": {\n"
110 : " \"name\": \"Test subscription\",\n"
111 : " \"description\": \"This is a test subscription\",\n"
112 : " \"description_i18n\": {\n"
113 : " \"en\": \"This is a test subscription\",\n"
114 : " \"es\": \"Esta es una subscripción de prueba\"\n"
115 : " },\n"
116 : " \"keys\": [\n"
117 : " {\n"
118 : " \"cipher\": \"CS\",\n"
119 : " \"cs_pub\": \"AMGKHAWCF3Y32E64G6JV7TPP7KHE2C3QFMNZ8N66Q744FV3TH1D0\",\n"
120 : " \"signature_validity_start\": {\"t_s\": 1736174497},\n"
121 : " \"signature_validity_end\": {\"t_s\": 1736174497}\n"
122 : " }\n"
123 : " ],\n"
124 : " \"details\": {\n"
125 : " \"class\": \"subscription\",\n"
126 : " \"trusted_domains\": [\"a\", \"b\", \"c\"]\n"
127 : " },\n"
128 : " \"critical\": true\n"
129 : " },\n"
130 : " \"test-discount\": {\n"
131 : " \"name\": \"Test discount\",\n"
132 : " \"description\": \"This is a test discount\",\n"
133 : " \"description_i18n\": {\n"
134 : " \"en\": \"This is a test discount\",\n"
135 : " \"es\": \"Este es un descuento de prueba\"\n"
136 : " },\n"
137 : " \"keys\": [\n"
138 : " {\n"
139 : " \"cipher\": \"RSA\",\n"
140 : " \"rsa_pub\": \"040000YGF5DK0PKCN99J0V814C20Q54C82S3RE3GBVC2T4QXEP7N05ABAN5DG8BC3FTN33BSG15VFX2N9X95HE7GBDAHSYHG4G00VHDCV4E0W4HVYTZGN6SGPBMTAE1XMYBH5DFWT4TXPSEQB96AG3G65X6BPQ0WXSARD5NP2YR1CQB6GB0W2BSKZK1AXZN67GHB3HHAPFV8V584QF1DGDXEWN875RN4HYNH3AW4XZ9SP5A7J5MED56P0TXX5D8C1HPWHFD89GE6Q7J0Q3QKM18WAVAZJTF6PR3Q5T2C71ST0VTP42F16ZZRWS4CHSXHM5RW0BGH383VX4100AD61X6QQ99K12Q17EQZK5MSE6AGNK24SCAH06XTXA7WFC78V0ARJKFDX1M483GE9SX20XXFKSTQ6B8104002\",\n"
141 : " \"signature_validity_start\": {\"t_s\": 1736174497},\n"
142 : " \"signature_validity_end\": {\"t_s\": 1736174497}\n"
143 : " }\n"
144 : " ],\n"
145 : " \"details\": {\n"
146 : " \"class\": \"discount\",\n"
147 : " \"expected_domains\": [\"a\", \"b\", \"c\"]\n"
148 : " },\n"
149 : " \"critical\": true\n"
150 : " }\n"
151 : " }\n"
152 : "}";
153 :
154 :
155 : int
156 1 : main (int argc,
157 : const char *const argv[])
158 : {
159 : (void) argc;
160 : (void) argv;
161 1 : GNUNET_log_setup ("test-contract",
162 : "WARNING",
163 : NULL);
164 :
165 : { // Contract v0
166 : json_t *common;
167 : json_t *v0;
168 : struct TALER_MERCHANT_Contract *v0_parsed;
169 : json_t *v0_serialized;
170 :
171 1 : common = json_loads (contract_common, 0, NULL);
172 1 : GNUNET_assert (NULL != common);
173 :
174 1 : v0 = json_loads (contract_v0, 0, NULL);
175 1 : GNUNET_assert (NULL != v0);
176 :
177 1 : GNUNET_assert (0 == json_object_update_new (v0, common));
178 :
179 1 : v0_parsed = TALER_MERCHANT_contract_parse (v0, false);
180 1 : GNUNET_assert (NULL != v0_parsed);
181 :
182 1 : v0_serialized = TALER_MERCHANT_contract_serialize (v0_parsed, false);
183 1 : GNUNET_assert (NULL != v0_serialized);
184 :
185 1 : GNUNET_assert (1 == json_equal (v0, v0_serialized));
186 :
187 1 : json_decref (v0_serialized);
188 1 : TALER_MERCHANT_contract_free (v0_parsed);
189 1 : json_decref (v0);
190 : }
191 :
192 : { // Contract v1
193 : json_t *common;
194 : json_t *v1;
195 : struct TALER_MERCHANT_Contract *v1_parsed;
196 : json_t *v1_serialized;
197 :
198 1 : common = json_loads (contract_common, 0, NULL);
199 1 : GNUNET_assert (NULL != common);
200 :
201 1 : v1 = json_loads (contract_v1, 0, NULL);
202 1 : GNUNET_assert (NULL != v1);
203 :
204 1 : GNUNET_assert (0 == json_object_update_new (v1, common));
205 :
206 1 : v1_parsed = TALER_MERCHANT_contract_parse (v1, false);
207 1 : GNUNET_assert (NULL != v1_parsed);
208 :
209 1 : v1_serialized = TALER_MERCHANT_contract_serialize (v1_parsed, false);
210 1 : GNUNET_assert (NULL != v1_serialized);
211 :
212 1 : GNUNET_assert (1 == json_equal (v1, v1_serialized));
213 :
214 1 : for (unsigned int i = 0;
215 3 : i < v1_parsed->details.v1.token_authorities_len;
216 2 : i++)
217 : {
218 2 : struct TALER_MERCHANT_ContractTokenFamily *in =
219 2 : &v1_parsed->details.v1.token_authorities[i];
220 4 : for (unsigned int j = 0; j < in->keys_len; j++)
221 : {
222 2 : struct TALER_MERCHANT_ContractTokenFamilyKey *inkey = &in->keys[j];
223 : struct TALER_MERCHANT_ContractTokenFamily out;
224 : struct TALER_MERCHANT_ContractTokenFamilyKey outkey;
225 2 : GNUNET_assert (GNUNET_OK == TALER_MERCHANT_find_token_family_key (
226 : in->slug,
227 : inkey->valid_after,
228 : v1_parsed->details.v1.token_authorities,
229 : v1_parsed->details.v1.token_authorities_len,
230 : &out,
231 : &outkey));
232 2 : GNUNET_assert (0 == GNUNET_memcmp (in, &out));
233 2 : GNUNET_assert (0 == GNUNET_memcmp (inkey, &outkey));
234 : }
235 : }
236 :
237 1 : json_decref (v1_serialized);
238 1 : TALER_MERCHANT_contract_free (v1_parsed);
239 1 : json_decref (v1);
240 : }
241 :
242 1 : return 0;
243 : }
|