Line data Source code
1 : /*
2 : This file is part of TALER
3 : (C) 2015, 2016, 2023 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 : * @file pq/test_pq.c
18 : * @brief Tests for Postgres convenience API
19 : * @author Christian Grothoff <christian@grothoff.org>
20 : */
21 : #include "platform.h"
22 : #include "taler_util.h"
23 : #include "taler_pq_lib.h"
24 : #include <gnunet/gnunet_pq_lib.h>
25 :
26 :
27 : /**
28 : * Setup prepared statements.
29 : *
30 : * @param db database handle to initialize
31 : * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
32 : */
33 : static enum GNUNET_GenericReturnValue
34 1 : postgres_prepare (struct GNUNET_PQ_Context *db)
35 : {
36 1 : struct GNUNET_PQ_PreparedStatement ps[] = {
37 1 : GNUNET_PQ_make_prepare ("test_insert",
38 : "INSERT INTO test_pq ("
39 : " tamount"
40 : ",json"
41 : ",aamount"
42 : ",tamountc"
43 : ",hash"
44 : ",hashes"
45 : ",cs_r_pubs"
46 : ") VALUES "
47 : "($1, $2, $3, $4, $5, $6, $7);"),
48 1 : GNUNET_PQ_make_prepare ("test_select",
49 : "SELECT"
50 : " tamount"
51 : ",json"
52 : ",aamount"
53 : ",tamountc"
54 : ",hash"
55 : ",hashes"
56 : ",cs_r_pubs"
57 : " FROM test_pq;"),
58 : GNUNET_PQ_PREPARED_STATEMENT_END
59 : };
60 :
61 1 : return GNUNET_PQ_prepare_statements (db,
62 : ps);
63 : }
64 :
65 :
66 : /**
67 : * Run actual test queries.
68 : *
69 : * @return 0 on success
70 : */
71 : static int
72 1 : run_queries (struct GNUNET_PQ_Context *conn)
73 : {
74 : struct TALER_Amount tamount;
75 : struct TALER_Amount aamount[3];
76 : struct TALER_Amount tamountc;
77 1 : struct GNUNET_HashCode hc =
78 : {{0xdeadbeef,0xdeadbeef,0xdeadbeef,0xdeadbeef,
79 : 0xdeadbeef,0xdeadbeef,0xdeadbeef,0xdeadbeef,
80 : 0xdeadbeef,0xdeadbeef,0xdeadbeef,0xdeadbeef,
81 : 0xdeadbeef,0xdeadbeef,0xdeadbeef,0xdeadbeef, }};
82 1 : struct GNUNET_HashCode hcs[2] =
83 : {{{0xc0feec0f,0xc0feec0f,0xc0feec0f,0xc0feec0f,
84 : 0xc0feec0f,0xc0feec0f,0xc0feec0f,0xc0feec0f,
85 : 0xc0feec0f,0xc0feec0f,0xc0feec0f,0xc0feec0f,
86 : 0xc0feec0f,0xc0feec0f,0xc0feec0f,0xc0feec0f,}},
87 : {{0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,
88 : 0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,
89 : 0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,
90 : 0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,}}};
91 : struct GNUNET_CRYPTO_CSPublicRPairP in_cs_r_pubs[5];
92 : json_t *json;
93 :
94 1 : GNUNET_assert (GNUNET_OK ==
95 : TALER_string_to_amount ("EUR:5.3",
96 : &aamount[0]));
97 1 : GNUNET_assert (GNUNET_OK ==
98 : TALER_string_to_amount ("EUR:6.4",
99 : &aamount[1]));
100 1 : GNUNET_assert (GNUNET_OK ==
101 : TALER_string_to_amount ("EUR:7.5",
102 : &aamount[2]));
103 1 : GNUNET_assert (GNUNET_OK ==
104 : TALER_string_to_amount ("EUR:7.7",
105 : &tamount));
106 1 : GNUNET_assert (GNUNET_OK ==
107 : TALER_string_to_amount ("FOO:8.7",
108 : &tamountc));
109 1 : json = json_object ();
110 1 : GNUNET_assert (NULL != json);
111 1 : GNUNET_assert (0 ==
112 : json_object_set_new (json,
113 : "foo",
114 : json_integer (42)));
115 1 : GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
116 : in_cs_r_pubs,
117 : sizeof(struct GNUNET_CRYPTO_CSPublicRPairP) * 5);
118 : {
119 1 : struct GNUNET_PQ_QueryParam params_insert[] = {
120 1 : TALER_PQ_query_param_amount (conn,
121 : &tamount),
122 1 : TALER_PQ_query_param_json (json),
123 1 : TALER_PQ_query_param_array_amount (3,
124 : aamount,
125 : conn),
126 1 : TALER_PQ_query_param_amount_with_currency (conn,
127 : &tamountc),
128 1 : GNUNET_PQ_query_param_fixed_size (&hc,
129 : sizeof (hc)),
130 1 : TALER_PQ_query_param_array_hash_code (2,
131 : hcs,
132 : conn),
133 1 : TALER_PQ_query_param_array_cs_r_pub (5,
134 : in_cs_r_pubs,
135 : conn),
136 : GNUNET_PQ_query_param_end
137 : };
138 : PGresult *result;
139 :
140 1 : result = GNUNET_PQ_exec_prepared (conn,
141 : "test_insert",
142 : params_insert);
143 6 : for (uint8_t i = 0; i < 5; i++)
144 : {
145 5 : printf (" in_cs_r_pubs[%d]=%s\n",
146 : i,
147 : GNUNET_STRINGS_data_to_string_alloc (
148 5 : &in_cs_r_pubs[i],
149 : sizeof(in_cs_r_pubs[i])));
150 : }
151 :
152 1 : if (PGRES_COMMAND_OK != PQresultStatus (result))
153 : {
154 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
155 : "Database failure: %s\n",
156 : PQresultErrorMessage (result));
157 0 : PQclear (result);
158 0 : return 1;
159 : }
160 1 : PQclear (result);
161 1 : json_decref (json);
162 : }
163 : {
164 : struct TALER_Amount tamount2;
165 : struct TALER_Amount tamountc2;
166 : struct TALER_Amount *pamount;
167 : struct GNUNET_HashCode hc2;
168 : struct GNUNET_HashCode *hcs2;
169 : struct GNUNET_CRYPTO_CSPublicRPairP *out_cs_r_pubs;
170 : size_t npamount;
171 : size_t nhcs;
172 : size_t n_rpubs;
173 : json_t *json2;
174 1 : struct GNUNET_PQ_QueryParam params_select[] = {
175 : GNUNET_PQ_query_param_end
176 : };
177 1 : struct GNUNET_PQ_ResultSpec results_select[] = {
178 1 : TALER_PQ_result_spec_amount ("tamount",
179 : "EUR",
180 : &tamount2),
181 1 : TALER_PQ_result_spec_json ("json",
182 : &json2),
183 1 : TALER_PQ_result_spec_array_amount (conn,
184 : "aamount",
185 : "EUR",
186 : &npamount,
187 : &pamount),
188 1 : TALER_PQ_result_spec_amount_with_currency ("tamountc",
189 : &tamountc2),
190 1 : GNUNET_PQ_result_spec_auto_from_type ("hash",
191 : &hc2),
192 1 : TALER_PQ_result_spec_array_hash_code (conn,
193 : "hashes",
194 : &nhcs,
195 : &hcs2),
196 1 : TALER_PQ_result_spec_array_cs_r_pub (conn,
197 : "cs_r_pubs",
198 : &n_rpubs,
199 : &out_cs_r_pubs),
200 : GNUNET_PQ_result_spec_end
201 : };
202 :
203 1 : if (1 !=
204 1 : GNUNET_PQ_eval_prepared_singleton_select (conn,
205 : "test_select",
206 : params_select,
207 : results_select))
208 : {
209 0 : GNUNET_break (0);
210 0 : return 1;
211 : }
212 1 : GNUNET_break (0 ==
213 : TALER_amount_cmp (&tamount,
214 : &tamount2));
215 1 : GNUNET_break (42 ==
216 : json_integer_value (json_object_get (json2,
217 : "foo")));
218 1 : GNUNET_break (3 == npamount);
219 4 : for (size_t i = 0; i < 3; i++)
220 : {
221 3 : GNUNET_break (0 ==
222 : TALER_amount_cmp (&aamount[i],
223 : &pamount[i]));
224 : }
225 1 : GNUNET_break (0 ==
226 : TALER_amount_cmp (&tamountc,
227 : &tamountc2));
228 1 : GNUNET_break (0 == GNUNET_memcmp (&hc,&hc2));
229 3 : for (size_t i = 0; i < 2; i++)
230 : {
231 2 : GNUNET_break (0 ==
232 : GNUNET_memcmp (&hcs[i],
233 : &hcs2[i]));
234 : }
235 1 : GNUNET_break (5 == n_rpubs);
236 6 : for (uint8_t i = 0; i < 5; i++)
237 : {
238 5 : GNUNET_break (0 ==
239 : GNUNET_memcmp (&in_cs_r_pubs[i],
240 : &out_cs_r_pubs[i]));
241 5 : printf ("out_cs_r_pubs[%d]=%s\n",
242 : i,
243 : GNUNET_STRINGS_data_to_string_alloc (
244 5 : &out_cs_r_pubs[i],
245 : sizeof(out_cs_r_pubs[i])));
246 : }
247 1 : GNUNET_PQ_cleanup_result (results_select);
248 : }
249 1 : return 0;
250 : }
251 :
252 :
253 : int
254 1 : main (int argc,
255 : const char *const argv[])
256 : {
257 1 : struct GNUNET_PQ_ExecuteStatement es[] = {
258 1 : GNUNET_PQ_make_execute ("DO $$ "
259 : " BEGIN"
260 : " CREATE DOMAIN gnunet_hashcode AS BYTEA"
261 : " CHECK(length(VALUE)=64);"
262 : " EXCEPTION"
263 : " WHEN duplicate_object THEN null;"
264 : " END "
265 : "$$;"),
266 1 : GNUNET_PQ_make_execute ("DO $$ "
267 : " BEGIN"
268 : " CREATE TYPE taler_amount AS"
269 : " (val INT8, frac INT4);"
270 : " EXCEPTION"
271 : " WHEN duplicate_object THEN null;"
272 : " END "
273 : "$$;"),
274 1 : GNUNET_PQ_make_execute ("DO $$ "
275 : " BEGIN"
276 : " CREATE TYPE taler_amount_currency AS"
277 : " (val INT8, frac INT4, curr VARCHAR(12));"
278 : " EXCEPTION"
279 : " WHEN duplicate_object THEN null;"
280 : " END "
281 : "$$;"),
282 1 : GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS test_pq ("
283 : " tamount taler_amount NOT NULL"
284 : ",json VARCHAR NOT NULL"
285 : ",aamount taler_amount[]"
286 : ",tamountc taler_amount_currency"
287 : ",hash gnunet_hashcode"
288 : ",hashes gnunet_hashcode[]"
289 : ",cs_r_pubs BYTEA[]"
290 : ")"),
291 : GNUNET_PQ_EXECUTE_STATEMENT_END
292 : };
293 : struct GNUNET_PQ_Context *conn;
294 : int ret;
295 :
296 : (void) argc;
297 : (void) argv;
298 1 : GNUNET_log_setup ("test-pq",
299 : "WARNING",
300 : NULL);
301 1 : conn = GNUNET_PQ_connect ("postgres:///talercheck",
302 : NULL,
303 : es,
304 : NULL);
305 1 : if (NULL == conn)
306 0 : return 77;
307 1 : if (GNUNET_OK !=
308 1 : postgres_prepare (conn))
309 : {
310 0 : GNUNET_break (0);
311 0 : GNUNET_PQ_disconnect (conn);
312 0 : return 1;
313 : }
314 :
315 1 : ret = run_queries (conn);
316 : {
317 1 : struct GNUNET_PQ_ExecuteStatement ds[] = {
318 1 : GNUNET_PQ_make_execute ("DROP TABLE test_pq"),
319 : GNUNET_PQ_EXECUTE_STATEMENT_END
320 : };
321 :
322 1 : if (GNUNET_OK !=
323 1 : GNUNET_PQ_exec_statements (conn,
324 : ds))
325 : {
326 0 : fprintf (stderr,
327 : "Failed to drop table\n");
328 0 : GNUNET_PQ_disconnect (conn);
329 0 : return 1;
330 : }
331 : }
332 1 : GNUNET_PQ_disconnect (conn);
333 1 : return ret;
334 : }
335 :
336 :
337 : /* end of test_pq.c */
|