aboutsummaryrefslogtreecommitdiff
path: root/src/pq/test_pq.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pq/test_pq.c')
-rw-r--r--src/pq/test_pq.c629
1 files changed, 0 insertions, 629 deletions
diff --git a/src/pq/test_pq.c b/src/pq/test_pq.c
deleted file mode 100644
index d70e18e6d..000000000
--- a/src/pq/test_pq.c
+++ /dev/null
@@ -1,629 +0,0 @@
1/*
2 This file is part of GNUnet
3 (C) 2015, 2016, 2019, 2020 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file pq/test_pq.c
22 * @brief Tests for Postgres convenience API
23 * @author Christian Grothoff <christian@grothoff.org>
24 */
25#include "platform.h"
26#include "gnunet_common.h"
27#include "gnunet_pq_lib.h"
28#include "gnunet_time_lib.h"
29#include "pq.h"
30
31/**
32 * Database handle.
33 */
34static struct GNUNET_PQ_Context *db;
35
36/**
37 * Global return value, 0 on success.
38 */
39static int ret;
40
41/**
42 * An event handler.
43 */
44static struct GNUNET_DB_EventHandler *eh;
45
46/**
47 * Timeout task.
48 */
49static struct GNUNET_SCHEDULER_Task *tt;
50
51
52/**
53 * Setup prepared statements.
54 *
55 * @param db database handle to initialize
56 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
57 */
58static int
59postgres_prepare (struct GNUNET_PQ_Context *db)
60{
61 struct GNUNET_PQ_PreparedStatement ps[] = {
62 GNUNET_PQ_make_prepare ("test_insert",
63 "INSERT INTO test_pq ("
64 " pub"
65 ",sig"
66 ",abs_time"
67 ",forever"
68 ",hash"
69 ",vsize"
70 ",u16"
71 ",u32"
72 ",u64"
73 ",unn"
74 ",arr_bool"
75 ",arr_int2"
76 ",arr_int4"
77 ",arr_int8"
78 ",arr_bytea"
79 ",arr_text"
80 ",arr_abs_time"
81 ",arr_rel_time"
82 ",arr_timestamp"
83 ") VALUES "
84 "($1, $2, $3, $4, $5, $6,"
85 "$7, $8, $9, $10,"
86 "$11, $12, $13, $14, $15, $16,"
87 "$17, $18, $19);"),
88 GNUNET_PQ_make_prepare ("test_select",
89 "SELECT"
90 " pub"
91 ",sig"
92 ",abs_time"
93 ",forever"
94 ",hash"
95 ",vsize"
96 ",u16"
97 ",u32"
98 ",u64"
99 ",unn"
100 ",arr_bool"
101 ",arr_int2"
102 ",arr_int4"
103 ",arr_int8"
104 ",arr_bytea"
105 ",arr_text"
106 ",arr_abs_time"
107 ",arr_rel_time"
108 ",arr_timestamp"
109 " FROM test_pq"
110 " ORDER BY abs_time DESC "
111 " LIMIT 1;"),
112 GNUNET_PQ_PREPARED_STATEMENT_END
113 };
114
115 return GNUNET_PQ_prepare_statements (db,
116 ps);
117}
118
119
120/**
121 * Run actual test queries.
122 *
123 * @param db database handle
124 * @return 0 on success
125 */
126static int
127run_queries (struct GNUNET_PQ_Context *db)
128{
129 struct GNUNET_CRYPTO_RsaPublicKey *pub;
130 struct GNUNET_CRYPTO_RsaPublicKey *pub2 = NULL;
131 struct GNUNET_CRYPTO_RsaSignature *sig;
132 struct GNUNET_CRYPTO_RsaSignature *sig2 = NULL;
133 struct GNUNET_TIME_Absolute abs_time = GNUNET_TIME_absolute_get ();
134 struct GNUNET_TIME_Absolute abs_time2;
135 struct GNUNET_TIME_Absolute forever = GNUNET_TIME_UNIT_FOREVER_ABS;
136 struct GNUNET_TIME_Absolute forever2;
137 struct GNUNET_HashCode hc;
138 struct GNUNET_HashCode hc2;
139 PGresult *result;
140 int ret;
141 struct GNUNET_CRYPTO_RsaPrivateKey *priv;
142 const char msg[] = "hello";
143 void *msg2;
144 struct GNUNET_HashCode hmsg;
145 size_t msg2_len;
146 uint16_t u16;
147 uint16_t u162;
148 uint32_t u32;
149 uint32_t u322;
150 uint64_t u64;
151 uint64_t u642;
152 uint64_t uzzz = 42;
153 struct GNUNET_HashCode ahc[3] = {};
154 bool ab[5] = {true, false, false, true, false};
155 uint16_t ai2[3] = {42, 0x0001, 0xFFFF};
156 uint32_t ai4[3] = {42, 0x00010000, 0xFFFFFFFF};
157 uint64_t ai8[3] = {42, 0x0001000000000000, 0xFFFFFFFFFFFFFFFF};
158 const char *as[] = {"foo", "bar", "buzz"};
159 const struct GNUNET_TIME_Absolute ata[2] = {GNUNET_TIME_absolute_get (),
160 GNUNET_TIME_absolute_get ()};
161 const struct GNUNET_TIME_Relative atr[2] = {GNUNET_TIME_relative_get_hour_ (),
162 GNUNET_TIME_relative_get_minute_ ()};
163 const struct GNUNET_TIME_Timestamp ats[2] = {GNUNET_TIME_timestamp_get (),
164 GNUNET_TIME_timestamp_get ()};
165
166
167 priv = GNUNET_CRYPTO_rsa_private_key_create (1024);
168 pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
169 memset (&hmsg, 42, sizeof(hmsg));
170 sig = GNUNET_CRYPTO_rsa_sign_fdh (priv,
171 &hmsg);
172 u16 = 16;
173 u32 = 32;
174 u64 = 64;
175 for (int i = 0; i < 3; i++)
176 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
177 &ahc[i],
178 sizeof(ahc[i]));
179
180 /* FIXME: test GNUNET_PQ_result_spec_variable_size */
181 {
182 struct GNUNET_PQ_QueryParam params_insert[] = {
183 GNUNET_PQ_query_param_rsa_public_key (pub),
184 GNUNET_PQ_query_param_rsa_signature (sig),
185 GNUNET_PQ_query_param_absolute_time (&abs_time),
186 GNUNET_PQ_query_param_absolute_time (&forever),
187 GNUNET_PQ_query_param_auto_from_type (&hc),
188 GNUNET_PQ_query_param_string (msg),
189 GNUNET_PQ_query_param_uint16 (&u16),
190 GNUNET_PQ_query_param_uint32 (&u32),
191 GNUNET_PQ_query_param_uint64 (&u64),
192 GNUNET_PQ_query_param_null (),
193 GNUNET_PQ_query_param_array_bool (5, ab, db),
194 GNUNET_PQ_query_param_array_uint16 (3, ai2, db),
195 GNUNET_PQ_query_param_array_uint32 (3, ai4, db),
196 GNUNET_PQ_query_param_array_uint64 (3, ai8, db),
197 GNUNET_PQ_query_param_array_bytes_same_size (3,
198 ahc,
199 sizeof(ahc[0]),
200 db),
201 GNUNET_PQ_query_param_array_ptrs_string (3, as, db),
202 GNUNET_PQ_query_param_array_abs_time (2, ata, db),
203 GNUNET_PQ_query_param_array_rel_time (2, atr, db),
204 GNUNET_PQ_query_param_array_timestamp (2, ats, db),
205 GNUNET_PQ_query_param_end
206 };
207 struct GNUNET_PQ_QueryParam params_select[] = {
208 GNUNET_PQ_query_param_end
209 };
210 bool got_null = false;
211 size_t num_bool;
212 bool *arr_bools;
213 size_t num_u16;
214 uint16_t *arr_u16;
215 size_t num_u32;
216 uint32_t *arr_u32;
217 size_t num_u64;
218 uint64_t *arr_u64;
219 size_t num_abs;
220 struct GNUNET_TIME_Absolute *arr_abs;
221 size_t num_rel;
222 struct GNUNET_TIME_Relative *arr_rel;
223 size_t num_tstmp;
224 struct GNUNET_TIME_Timestamp *arr_tstmp;
225 size_t num_str;
226 char *arr_str;
227 size_t num_hash;
228 struct GNUNET_HashCode *arr_hash;
229 size_t num_buf;
230 void *arr_buf;
231 size_t *sz_buf;
232 struct GNUNET_PQ_ResultSpec results_select[] = {
233 GNUNET_PQ_result_spec_rsa_public_key ("pub", &pub2),
234 GNUNET_PQ_result_spec_rsa_signature ("sig", &sig2),
235 GNUNET_PQ_result_spec_absolute_time ("abs_time", &abs_time2),
236 GNUNET_PQ_result_spec_absolute_time ("forever", &forever2),
237 GNUNET_PQ_result_spec_auto_from_type ("hash", &hc2),
238 GNUNET_PQ_result_spec_variable_size ("vsize", &msg2, &msg2_len),
239 GNUNET_PQ_result_spec_uint16 ("u16", &u162),
240 GNUNET_PQ_result_spec_uint32 ("u32", &u322),
241 GNUNET_PQ_result_spec_uint64 ("u64", &u642),
242 GNUNET_PQ_result_spec_allow_null (
243 GNUNET_PQ_result_spec_uint64 ("unn", &uzzz),
244 &got_null),
245 GNUNET_PQ_result_spec_array_bool (db,
246 "arr_bool",
247 &num_bool,
248 &arr_bools),
249 GNUNET_PQ_result_spec_array_uint16 (db,
250 "arr_int2",
251 &num_u16,
252 &arr_u16),
253 GNUNET_PQ_result_spec_array_uint32 (db,
254 "arr_int4",
255 &num_u32,
256 &arr_u32),
257 GNUNET_PQ_result_spec_array_uint64 (db,
258 "arr_int8",
259 &num_u64,
260 &arr_u64),
261 GNUNET_PQ_result_spec_array_abs_time (db,
262 "arr_abs_time",
263 &num_abs,
264 &arr_abs),
265 GNUNET_PQ_result_spec_array_rel_time (db,
266 "arr_rel_time",
267 &num_rel,
268 &arr_rel),
269 GNUNET_PQ_result_spec_array_timestamp (db,
270 "arr_timestamp",
271 &num_tstmp,
272 &arr_tstmp),
273 GNUNET_PQ_result_spec_auto_array_from_type (db,
274 "arr_bytea",
275 &num_hash,
276 arr_hash),
277 GNUNET_PQ_result_spec_array_variable_size (db,
278 "arr_bytea",
279 &num_buf,
280 &sz_buf,
281 &arr_buf),
282 GNUNET_PQ_result_spec_array_string (db,
283 "arr_text",
284 &num_str,
285 &arr_str),
286 GNUNET_PQ_result_spec_end
287 };
288
289 result = GNUNET_PQ_exec_prepared (db,
290 "test_insert",
291 params_insert);
292 if (PGRES_COMMAND_OK != PQresultStatus (result))
293 {
294 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
295 "Database failure: %s\n",
296 PQresultErrorMessage (result));
297 PQclear (result);
298 GNUNET_CRYPTO_rsa_signature_free (sig);
299 GNUNET_CRYPTO_rsa_private_key_free (priv);
300 GNUNET_CRYPTO_rsa_public_key_free (pub);
301 return 1;
302 }
303
304 PQclear (result);
305 result = GNUNET_PQ_exec_prepared (db,
306 "test_select",
307 params_select);
308 if (1 !=
309 PQntuples (result))
310 {
311 GNUNET_break (0);
312 PQclear (result);
313 GNUNET_CRYPTO_rsa_signature_free (sig);
314 GNUNET_CRYPTO_rsa_private_key_free (priv);
315 GNUNET_CRYPTO_rsa_public_key_free (pub);
316 return 1;
317 }
318 ret = GNUNET_PQ_extract_result (result,
319 results_select,
320 0);
321 GNUNET_break (GNUNET_YES == ret);
322 GNUNET_break (abs_time.abs_value_us == abs_time2.abs_value_us);
323 GNUNET_break (forever.abs_value_us == forever2.abs_value_us);
324 GNUNET_break (0 ==
325 GNUNET_memcmp (&hc,
326 &hc2));
327 GNUNET_break (0 ==
328 GNUNET_CRYPTO_rsa_signature_cmp (sig,
329 sig2));
330 GNUNET_break (0 ==
331 GNUNET_CRYPTO_rsa_public_key_cmp (pub,
332 pub2));
333 GNUNET_break (strlen (msg) == msg2_len);
334 GNUNET_break (0 ==
335 strncmp (msg,
336 msg2,
337 msg2_len));
338 GNUNET_break (16 == u162);
339 GNUNET_break (32 == u322);
340 GNUNET_break (64 == u642);
341 GNUNET_break (42 == uzzz);
342 GNUNET_break (got_null);
343
344 /* Check arrays */
345 GNUNET_break (num_bool == 5);
346 for (size_t i = 0; i < num_bool; i++)
347 GNUNET_break (arr_bools[i] == ab[i]);
348
349 GNUNET_break (num_u16 == 3);
350 for (size_t i = 0; i < num_u16; i++)
351 GNUNET_break (arr_u16[i] == ai2[i]);
352
353 GNUNET_break (num_u32 == 3);
354 for (size_t i = 0; i < num_u32; i++)
355 GNUNET_break (arr_u32[i] == ai4[i]);
356
357 GNUNET_break (num_u64 == 3);
358 for (size_t i = 0; i < num_u64; i++)
359 GNUNET_break (arr_u64[i] == ai8[i]);
360
361 GNUNET_break (num_abs == 2);
362 for (size_t i = 0; i < num_abs; i++)
363 GNUNET_break (arr_abs[i].abs_value_us == ata[i].abs_value_us);
364
365 GNUNET_break (num_rel == 2);
366 for (size_t i = 0; i < num_rel; i++)
367 GNUNET_break (arr_rel[i].rel_value_us == atr[i].rel_value_us);
368
369 GNUNET_break (num_tstmp == 2);
370 for (size_t i = 0; i < num_tstmp; i++)
371 GNUNET_break (arr_tstmp[i].abs_time.abs_value_us ==
372 ats[i].abs_time.abs_value_us);
373
374 GNUNET_break (num_str == 3);
375 GNUNET_break (0 == strcmp (arr_str, as[0]));
376 GNUNET_break (0 == strcmp (arr_str + 4, as[1]));
377 GNUNET_break (0 == strcmp (arr_str + 8, as[2]));
378
379 GNUNET_break (num_hash == 3);
380 for (size_t i = 0; i < num_hash; i++)
381 GNUNET_break (0 == GNUNET_memcmp (&arr_hash[i], &ahc[i]));
382
383 GNUNET_break (num_buf == 3);
384 for (size_t i = 0; i < num_buf; i++)
385 {
386 GNUNET_break (0 == memcmp (((char *) arr_buf) + i * sizeof(ahc[i]),
387 &ahc[i],
388 sizeof(ahc[i])));
389 }
390
391 GNUNET_PQ_cleanup_result (results_select);
392 PQclear (result);
393
394 GNUNET_PQ_cleanup_query_params_closures (params_insert);
395 }
396
397 GNUNET_CRYPTO_rsa_signature_free (sig);
398 GNUNET_CRYPTO_rsa_private_key_free (priv);
399 GNUNET_CRYPTO_rsa_public_key_free (pub);
400 if (GNUNET_OK != ret)
401 return 1;
402
403 return 0;
404}
405
406
407/**
408 * Task called on shutdown.
409 *
410 * @param cls NULL
411 */
412static void
413event_end (void *cls)
414{
415 GNUNET_PQ_event_listen_cancel (eh);
416 eh = NULL;
417 if (NULL != tt)
418 {
419 GNUNET_SCHEDULER_cancel (tt);
420 tt = NULL;
421 }
422}
423
424
425/**
426 * Task called on timeout. Should not happen, means
427 * we did not get the expected event.
428 *
429 * @param cls NULL
430 */
431static void
432timeout_cb (void *cls)
433{
434 ret = 2;
435 GNUNET_break (0);
436 tt = NULL;
437 GNUNET_SCHEDULER_shutdown ();
438}
439
440
441/**
442 * Task called on expected event
443 *
444 * @param cls NULL
445 */
446static void
447event_sched_cb (void *cls,
448 const void *extra,
449 size_t extra_size)
450{
451 GNUNET_assert (5 == extra_size);
452 GNUNET_assert (0 ==
453 memcmp ("hello",
454 extra,
455 5));
456 GNUNET_SCHEDULER_shutdown ();
457}
458
459
460/**
461 * Run tests that need a scheduler.
462 *
463 * @param cls NULL
464 */
465static void
466sched_tests (void *cls)
467{
468 struct GNUNET_DB_EventHeaderP es = {
469 .size = htons (sizeof (es)),
470 .type = htons (42)
471 };
472
473
474 tt = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
475 &timeout_cb,
476 NULL);
477 eh = GNUNET_PQ_event_listen (db,
478 &es,
479 GNUNET_TIME_UNIT_FOREVER_REL,
480 &event_sched_cb,
481 NULL);
482 GNUNET_PQ_reconnect (db);
483 GNUNET_SCHEDULER_add_shutdown (&event_end,
484 NULL);
485 GNUNET_PQ_event_notify (db,
486 &es,
487 "hello",
488 5);
489}
490
491
492int
493main (int argc,
494 const char *const argv[])
495{
496 struct GNUNET_PQ_ExecuteStatement es[] = {
497 GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS test_pq ("
498 " pub BYTEA NOT NULL"
499 ",sig BYTEA NOT NULL"
500 ",abs_time INT8 NOT NULL"
501 ",forever INT8 NOT NULL"
502 ",hash BYTEA NOT NULL CHECK(LENGTH(hash)=64)"
503 ",vsize VARCHAR NOT NULL"
504 ",u16 INT2 NOT NULL"
505 ",u32 INT4 NOT NULL"
506 ",u64 INT8 NOT NULL"
507 ",unn INT8"
508 ",arr_bool BOOL[]"
509 ",arr_int2 INT2[]"
510 ",arr_int4 INT4[]"
511 ",arr_int8 INT8[]"
512 ",arr_bytea BYTEA[]"
513 ",arr_text TEXT[]"
514 ",arr_abs_time INT8[]"
515 ",arr_rel_time INT8[]"
516 ",arr_timestamp INT8[]"
517 ")"),
518 GNUNET_PQ_EXECUTE_STATEMENT_END
519 };
520
521 GNUNET_log_setup ("test-pq",
522 "INFO",
523 NULL);
524 db = GNUNET_PQ_connect ("postgres:///gnunetcheck",
525 NULL,
526 es,
527 NULL);
528 if (NULL == db)
529 {
530 fprintf (stderr,
531 "Cannot run test, database connection failed\n");
532 return 77;
533 }
534 if (CONNECTION_OK != PQstatus (db->conn))
535 {
536 fprintf (stderr,
537 "Cannot run test, database connection failed: %s\n",
538 PQerrorMessage (db->conn));
539 GNUNET_break (0);
540 GNUNET_PQ_disconnect (db);
541 return 77; /* signal test was skipped */
542 }
543 if (GNUNET_OK !=
544 postgres_prepare (db))
545 {
546 GNUNET_break (0);
547 GNUNET_PQ_disconnect (db);
548 return 1;
549 }
550 ret = run_queries (db);
551 if (0 != ret)
552 {
553 GNUNET_break (0);
554 GNUNET_PQ_disconnect (db);
555 return ret;
556 }
557
558 /* ensure oid lookup works */
559 {
560 enum GNUNET_GenericReturnValue ret;
561 Oid oid;
562
563 ret = GNUNET_PQ_get_oid_by_name (db, "int8", &oid);
564
565 if (GNUNET_OK != ret)
566 {
567 fprintf (stderr,
568 "Cannot lookup oid for int8: %s\n",
569 PQerrorMessage (db->conn));
570 GNUNET_break (0);
571 GNUNET_PQ_disconnect (db);
572 return 77; /* signal test was skipped */
573 }
574
575 PQexec (db->conn, "CREATE TYPE foo AS (foo int, bar int);");
576
577 ret = GNUNET_PQ_get_oid_by_name (db, "foo", &oid);
578 if (GNUNET_OK != ret)
579 {
580 fprintf (stderr,
581 "Cannot lookup oid for foo: %s\n",
582 PQerrorMessage (db->conn));
583 GNUNET_break (0);
584 GNUNET_PQ_disconnect (db);
585 return 77; /* signal test was skipped */
586 }
587
588 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
589 "got oid %d for type foo\n", oid);
590 }
591
592 GNUNET_SCHEDULER_run (&sched_tests,
593 NULL);
594 if (0 != ret)
595 {
596 GNUNET_break (0);
597 GNUNET_PQ_disconnect (db);
598 return ret;
599 }
600#if TEST_RESTART
601 fprintf (stderr, "Please restart Postgres database now!\n");
602 sleep (60);
603 ret |= run_queries (db);
604 fprintf (stderr, "Result: %d (expect: 1 -- if you restarted the DB)\n", ret);
605 ret |= run_queries (db);
606 fprintf (stderr, "Result: %d (expect: 0)\n", ret);
607#endif
608 {
609 struct GNUNET_PQ_ExecuteStatement es[] = {
610 GNUNET_PQ_make_execute ("DROP TABLE test_pq"),
611 GNUNET_PQ_EXECUTE_STATEMENT_END
612 };
613
614 if (GNUNET_OK !=
615 GNUNET_PQ_exec_statements (db,
616 es))
617 {
618 fprintf (stderr,
619 "Failed to drop table\n");
620 GNUNET_PQ_disconnect (db);
621 return 1;
622 }
623 }
624 GNUNET_PQ_disconnect (db);
625 return ret;
626}
627
628
629/* end of test_pq.c */