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

Generated by: LCOV version 2.0-1