LCOV - code coverage report
Current view: top level - pq - test_pq.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 77 89 86.5 %
Date: 2025-06-05 21:03:14 Functions: 3 3 100.0 %

          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 */

Generated by: LCOV version 1.16