LCOV - code coverage report
Current view: top level - pq - test_pq.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 87.8 % 98 86
Test Date: 2026-01-09 13:26:54 Functions: 100.0 % 3 3

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

Generated by: LCOV version 2.0-1