donau

Donation authority for GNU Taler (experimental)
Log | Files | Refs | Submodules | README | LICENSE

test_pq.c (8201B)


      1 /*
      2   This file is part of TALER
      3   (C) 2024 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 <donau_config.h>
     22 #include <taler/taler_util.h>
     23 #include <taler/taler_pq_lib.h>
     24 
     25 
     26 /**
     27  * Setup prepared statements.
     28  *
     29  * @param db database handle to initialize
     30  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
     31  */
     32 static enum GNUNET_GenericReturnValue
     33 postgres_prepare (struct GNUNET_PQ_Context *db)
     34 {
     35   struct GNUNET_PQ_PreparedStatement ps[] = {
     36     GNUNET_PQ_make_prepare ("test_insert",
     37                             "INSERT INTO test_pq ("
     38                             " tamount"
     39                             ",json"
     40                             ",aamount"
     41                             ",tamountc"
     42                             ") VALUES "
     43                             "($1, $2, $3, $4);"),
     44     GNUNET_PQ_make_prepare ("test_select",
     45                             "SELECT"
     46                             " tamount"
     47                             ",json"
     48                             ",aamount"
     49                             ",tamountc"
     50                             " FROM test_pq;"),
     51     GNUNET_PQ_PREPARED_STATEMENT_END
     52   };
     53 
     54   return GNUNET_PQ_prepare_statements (db,
     55                                        ps);
     56 }
     57 
     58 
     59 /**
     60  * Run actual test queries.
     61  *
     62  * @return 0 on success
     63  */
     64 static int
     65 run_queries (struct GNUNET_PQ_Context *conn)
     66 {
     67   struct TALER_Amount tamount;
     68   struct TALER_Amount aamount[3];
     69   struct TALER_Amount tamountc;
     70   json_t *json;
     71 
     72   GNUNET_assert (GNUNET_OK ==
     73                  TALER_string_to_amount ("EUR:5.3",
     74                                          &aamount[0]));
     75   GNUNET_assert (GNUNET_OK ==
     76                  TALER_string_to_amount ("EUR:6.4",
     77                                          &aamount[1]));
     78   GNUNET_assert (GNUNET_OK ==
     79                  TALER_string_to_amount ("EUR:7.5",
     80                                          &aamount[2]));
     81   GNUNET_assert (GNUNET_OK ==
     82                  TALER_string_to_amount ("EUR:7.7",
     83                                          &tamount));
     84   GNUNET_assert (GNUNET_OK ==
     85                  TALER_string_to_amount ("FOO:8.7",
     86                                          &tamountc));
     87   json = json_object ();
     88   GNUNET_assert (NULL != json);
     89   GNUNET_assert (0 ==
     90                  json_object_set_new (json,
     91                                       "foo",
     92                                       json_integer (42)));
     93   {
     94     struct GNUNET_PQ_QueryParam params_insert[] = {
     95       TALER_PQ_query_param_amount (conn,
     96                                    &tamount),
     97       TALER_PQ_query_param_json (json),
     98       TALER_PQ_query_param_array_amount (3,
     99                                          aamount,
    100                                          conn),
    101       TALER_PQ_query_param_amount_with_currency (conn,
    102                                                  &tamountc),
    103       GNUNET_PQ_query_param_end
    104     };
    105     PGresult *result;
    106 
    107     result = GNUNET_PQ_exec_prepared (conn,
    108                                       "test_insert",
    109                                       params_insert);
    110     GNUNET_PQ_cleanup_query_params_closures (params_insert);
    111     if (PGRES_COMMAND_OK != PQresultStatus (result))
    112     {
    113       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    114                   "Database failure: %s\n",
    115                   PQresultErrorMessage (result));
    116       PQclear (result);
    117       return 1;
    118     }
    119     PQclear (result);
    120     json_decref (json);
    121   }
    122   {
    123     struct TALER_Amount tamount2;
    124     struct TALER_Amount tamountc2;
    125     struct TALER_Amount *pamount;
    126     size_t npamount;
    127     json_t *json2;
    128     struct GNUNET_PQ_QueryParam params_select[] = {
    129       GNUNET_PQ_query_param_end
    130     };
    131     struct GNUNET_PQ_ResultSpec results_select[] = {
    132       TALER_PQ_result_spec_amount ("tamount",
    133                                    "EUR",
    134                                    &tamount2),
    135       TALER_PQ_result_spec_json ("json",
    136                                  &json2),
    137       TALER_PQ_result_spec_array_amount (conn,
    138                                          "aamount",
    139                                          "EUR",
    140                                          &npamount,
    141                                          &pamount),
    142       TALER_PQ_result_spec_amount_with_currency ("tamountc",
    143                                                  &tamountc2),
    144       GNUNET_PQ_result_spec_end
    145     };
    146 
    147     if (1 !=
    148         GNUNET_PQ_eval_prepared_singleton_select (conn,
    149                                                   "test_select",
    150                                                   params_select,
    151                                                   results_select))
    152     {
    153       GNUNET_break (0);
    154       return 1;
    155     }
    156     GNUNET_break (0 ==
    157                   TALER_amount_cmp (&tamount,
    158                                     &tamount2));
    159     GNUNET_break (42 ==
    160                   json_integer_value (json_object_get (json2,
    161                                                        "foo")));
    162     GNUNET_break (3 == npamount);
    163     for (size_t i = 0; i < 3; i++)
    164     {
    165       GNUNET_break (0 ==
    166                     TALER_amount_cmp (&aamount[i],
    167                                       &pamount[i]));
    168     }
    169     GNUNET_break (0 ==
    170                   TALER_amount_cmp (&tamountc,
    171                                     &tamountc2));
    172     GNUNET_PQ_cleanup_result (results_select);
    173   }
    174   return 0;
    175 }
    176 
    177 
    178 int
    179 main (int argc,
    180       const char *const argv[])
    181 {
    182   struct GNUNET_PQ_ExecuteStatement es[] = {
    183     GNUNET_PQ_make_execute ("DO $$ "
    184                             " BEGIN"
    185                             " CREATE TYPE taler_amount AS"
    186                             "   (val INT8, frac INT4);"
    187                             " EXCEPTION"
    188                             "   WHEN duplicate_object THEN null;"
    189                             " END "
    190                             "$$;"),
    191     GNUNET_PQ_make_execute ("DO $$ "
    192                             " BEGIN"
    193                             " CREATE TYPE taler_amount_currency AS"
    194                             "   (val INT8, frac INT4, curr VARCHAR(12));"
    195                             " EXCEPTION"
    196                             "   WHEN duplicate_object THEN null;"
    197                             " END "
    198                             "$$;"),
    199     GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS test_pq ("
    200                             " tamount taler_amount NOT NULL"
    201                             ",json VARCHAR NOT NULL"
    202                             ",aamount taler_amount[]"
    203                             ",tamountc taler_amount_currency"
    204                             ")"),
    205     GNUNET_PQ_EXECUTE_STATEMENT_END
    206   };
    207   struct GNUNET_PQ_Context *conn;
    208   int ret;
    209 
    210   (void) argc;
    211   (void) argv;
    212   GNUNET_log_setup ("test-pq",
    213                     "WARNING",
    214                     NULL);
    215   conn = GNUNET_PQ_connect ("postgres:///donaucheck",
    216                             NULL,
    217                             es,
    218                             NULL);
    219   if (NULL == conn)
    220     return 77;
    221   if (GNUNET_OK !=
    222       postgres_prepare (conn))
    223   {
    224     GNUNET_break (0);
    225     GNUNET_PQ_disconnect (conn);
    226     return 1;
    227   }
    228 
    229   ret = run_queries (conn);
    230   {
    231     struct GNUNET_PQ_ExecuteStatement ds[] = {
    232       GNUNET_PQ_make_execute ("DROP TABLE test_pq"),
    233       GNUNET_PQ_EXECUTE_STATEMENT_END
    234     };
    235 
    236     if (GNUNET_OK !=
    237         GNUNET_PQ_exec_statements (conn,
    238                                    ds))
    239     {
    240       fprintf (stderr,
    241                "Failed to drop table\n");
    242       GNUNET_PQ_disconnect (conn);
    243       return 1;
    244     }
    245   }
    246   GNUNET_PQ_disconnect (conn);
    247   return ret;
    248 }
    249 
    250 
    251 /* end of test_pq.c */