LCOV - code coverage report
Current view: top level - pq - test_pq.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 88.5 % 104 92
Test Date: 2026-06-14 14:19:22 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              :                                                        "merchant",
     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              :                                                        "merchant",
     211              :                                                        "aamountc",
     212              :                                                        &npamountc,
     213              :                                                        &pamountc),
     214            1 :       TALER_PQ_result_spec_array_amount (conn,
     215              :                                          "aamountn",
     216              :                                          "EUR",
     217              :                                          &npamountn,
     218              :                                          &pamountn),
     219            1 :       TALER_PQ_result_spec_array_amount_with_currency (conn,
     220              :                                                        "merchant",
     221              :                                                        "aamountnc",
     222              :                                                        &npamountnc,
     223              :                                                        &pamountnc),
     224            1 :       TALER_PQ_result_spec_amount_with_currency ("tamountc",
     225              :                                                  &tamountc2),
     226            1 :       GNUNET_PQ_result_spec_auto_from_type ("hash",
     227              :                                             &hc2),
     228            1 :       TALER_PQ_result_spec_array_hash_code (conn,
     229              :                                             "hashes",
     230              :                                             &nhcs,
     231              :                                             &hcs2),
     232            1 :       TALER_PQ_result_spec_array_cs_r_pub (conn,
     233              :                                            "cs_r_pubs",
     234              :                                            &n_rpubs,
     235              :                                            &out_cs_r_pubs),
     236              :       GNUNET_PQ_result_spec_end
     237              :     };
     238              : 
     239            1 :     if (1 !=
     240            1 :         GNUNET_PQ_eval_prepared_singleton_select (conn,
     241              :                                                   "test_select",
     242              :                                                   params_select,
     243              :                                                   results_select))
     244              :     {
     245            0 :       GNUNET_break (0);
     246            0 :       return 1;
     247              :     }
     248            1 :     GNUNET_break (0 ==
     249              :                   TALER_amount_cmp (&tamount,
     250              :                                     &tamount2));
     251            1 :     GNUNET_break (42 ==
     252              :                   json_integer_value (json_object_get (json2,
     253              :                                                        "foo")));
     254            1 :     GNUNET_break (3 == npamount);
     255            4 :     for (size_t i = 0; i < 3; i++)
     256              :     {
     257            3 :       GNUNET_break (0 ==
     258              :                     TALER_amount_cmp (&aamount[i],
     259              :                                       &pamount[i]));
     260              :     }
     261            1 :     GNUNET_break (2 == npamountc);
     262            3 :     for (size_t i = 0; i < npamountc; i++)
     263              :     {
     264            2 :       GNUNET_break (0 ==
     265              :                     TALER_amount_cmp (&aamountc[i],
     266              :                                       &pamountc[i]));
     267              :     }
     268            1 :     GNUNET_break (0 ==
     269              :                   TALER_amount_cmp (&tamountc,
     270              :                                     &tamountc2));
     271            1 :     GNUNET_break (0 == GNUNET_memcmp (&hc,&hc2));
     272            3 :     for (size_t i = 0; i < 2; i++)
     273              :     {
     274            2 :       GNUNET_break (0 ==
     275              :                     GNUNET_memcmp (&hcs[i],
     276              :                                    &hcs2[i]));
     277              :     }
     278            1 :     GNUNET_break (5 == n_rpubs);
     279            6 :     for (uint8_t i = 0; i < 5; i++)
     280              :     {
     281            5 :       GNUNET_break (0 ==
     282              :                     GNUNET_memcmp (&in_cs_r_pubs[i],
     283              :                                    &out_cs_r_pubs[i]));
     284            5 :       printf ("out_cs_r_pubs[%d]=%s\n",
     285              :               i,
     286              :               GNUNET_STRINGS_data_to_string_alloc (
     287            5 :                 &out_cs_r_pubs[i],
     288              :                 sizeof(out_cs_r_pubs[i])));
     289              :     }
     290            1 :     GNUNET_PQ_cleanup_result (results_select);
     291              :   }
     292            1 :   return 0;
     293              : }
     294              : 
     295              : 
     296              : int
     297            1 : main (int argc,
     298              :       const char *const argv[])
     299              : {
     300            1 :   struct GNUNET_PQ_ExecuteStatement es[] = {
     301            1 :     GNUNET_PQ_make_execute ("DO $$ "
     302              :                             " BEGIN"
     303              :                             " CREATE SCHEMA IF NOT EXISTS merchant;"
     304              :                             " END "
     305              :                             "$$;"),
     306            1 :     GNUNET_PQ_make_execute ("DO $$ "
     307              :                             " BEGIN"
     308              :                             " CREATE DOMAIN gnunet_hashcode AS BYTEA"
     309              :                             "   CHECK(length(VALUE)=64);"
     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 AS"
     317              :                             "   (val INT8, frac INT4);"
     318              :                             " EXCEPTION"
     319              :                             "   WHEN duplicate_object THEN null;"
     320              :                             " END "
     321              :                             "$$;"),
     322            1 :     GNUNET_PQ_make_execute ("DO $$ "
     323              :                             " BEGIN"
     324              :                             " CREATE TYPE merchant.taler_amount_currency AS"
     325              :                             "   (val INT8, frac INT4, curr VARCHAR(12));"
     326              :                             " EXCEPTION"
     327              :                             "   WHEN duplicate_object THEN null;"
     328              :                             " END "
     329              :                             "$$;"),
     330            1 :     GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS test_pq ("
     331              :                             "tamount taler_amount NOT NULL"
     332              :                             ",json VARCHAR NOT NULL"
     333              :                             ",aamount taler_amount[]"
     334              :                             ",aamountc merchant.taler_amount_currency[]"
     335              :                             ",aamountn taler_amount[] NOT NULL DEFAULT ARRAY[]::taler_amount[]"
     336              :                             ",aamountnc merchant.taler_amount_currency[] NOT NULL DEFAULT ARRAY[]::merchant.taler_amount_currency[]"
     337              :                             ",tamountc merchant.taler_amount_currency"
     338              :                             ",hash gnunet_hashcode"
     339              :                             ",hashes gnunet_hashcode[]"
     340              :                             ",cs_r_pubs BYTEA[]"
     341              :                             ")"),
     342              :     GNUNET_PQ_EXECUTE_STATEMENT_END
     343              :   };
     344              :   struct GNUNET_PQ_Context *conn;
     345              :   int ret;
     346              :   struct GNUNET_CONFIGURATION_Handle *cfg;
     347              : 
     348              :   (void) argc;
     349              :   (void) argv;
     350            1 :   GNUNET_log_setup ("test-pq",
     351              :                     "WARNING",
     352              :                     NULL);
     353            1 :   cfg = GNUNET_CONFIGURATION_create (
     354              :     TALER_EXCHANGE_project_data ());
     355            1 :   GNUNET_CONFIGURATION_set_value_string (cfg,
     356              :                                          "test-pq",
     357              :                                          "CONFIG",
     358              :                                          "postgres:///talercheck");
     359              :   /* just to squash warning */
     360            1 :   GNUNET_CONFIGURATION_set_value_string (cfg,
     361              :                                          "test-pq",
     362              :                                          "SQL_DIR",
     363              :                                          "none");
     364            1 :   conn = GNUNET_PQ_init (cfg,
     365              :                          "test-pq",
     366              :                          NULL,
     367              :                          NULL);
     368            1 :   GNUNET_CONFIGURATION_destroy (cfg);
     369            1 :   if (NULL == conn)
     370            0 :     return 77;
     371            1 :   GNUNET_assert (GNUNET_OK ==
     372              :                  GNUNET_PQ_exec_statements (conn,
     373              :                                             es));
     374            1 :   if (GNUNET_OK !=
     375            1 :       postgres_prepare (conn))
     376              :   {
     377            0 :     GNUNET_break (0);
     378            0 :     GNUNET_PQ_disconnect (conn);
     379            0 :     return 1;
     380              :   }
     381            1 :   ret = run_queries (conn);
     382              :   {
     383            1 :     struct GNUNET_PQ_ExecuteStatement ds[] = {
     384            1 :       GNUNET_PQ_make_execute ("DROP TABLE test_pq"),
     385              :       GNUNET_PQ_EXECUTE_STATEMENT_END
     386              :     };
     387              : 
     388            1 :     if (GNUNET_OK !=
     389            1 :         GNUNET_PQ_exec_statements (conn,
     390              :                                    ds))
     391              :     {
     392            0 :       fprintf (stderr,
     393              :                "Failed to drop table\n");
     394            0 :       GNUNET_PQ_disconnect (conn);
     395            0 :       return 1;
     396              :     }
     397              :   }
     398            1 :   GNUNET_PQ_disconnect (conn);
     399            1 :   return ret;
     400              : }
     401              : 
     402              : 
     403              : /* end of test_pq.c */
        

Generated by: LCOV version 2.0-1