exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

test_pq.c (13949B)


      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 postgres_prepare (struct GNUNET_PQ_Context *db)
     35 {
     36   struct GNUNET_PQ_PreparedStatement ps[] = {
     37     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     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   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 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   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   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   GNUNET_assert (GNUNET_OK ==
    100                  TALER_string_to_amount ("EUR:5.3",
    101                                          &aamount[0]));
    102   GNUNET_assert (GNUNET_OK ==
    103                  TALER_string_to_amount ("EUR:6.4",
    104                                          &aamount[1]));
    105   GNUNET_assert (GNUNET_OK ==
    106                  TALER_string_to_amount ("EUR:7.5",
    107                                          &aamount[2]));
    108   GNUNET_assert (GNUNET_OK ==
    109                  TALER_string_to_amount ("EUR:7.7",
    110                                          &tamount));
    111   GNUNET_assert (GNUNET_OK ==
    112                  TALER_string_to_amount ("USD:3.2",
    113                                          &aamountc[0]));
    114   GNUNET_assert (GNUNET_OK ==
    115                  TALER_string_to_amount ("CHF:4.5",
    116                                          &aamountc[1]));
    117   GNUNET_assert (GNUNET_OK ==
    118                  TALER_string_to_amount ("FOO:8.7",
    119                                          &tamountc));
    120   json = json_object ();
    121   GNUNET_assert (NULL != json);
    122   GNUNET_assert (0 ==
    123                  json_object_set_new (json,
    124                                       "foo",
    125                                       json_integer (42)));
    126   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
    127                               in_cs_r_pubs,
    128                               sizeof(struct GNUNET_CRYPTO_CSPublicRPairP) * 5);
    129   {
    130     struct GNUNET_PQ_QueryParam params_insert[] = {
    131       TALER_PQ_query_param_amount (conn,
    132                                    &tamount),
    133       TALER_PQ_query_param_json (json),
    134       TALER_PQ_query_param_array_amount (3,
    135                                          aamount,
    136                                          conn),
    137       TALER_PQ_query_param_array_amount_with_currency (2,
    138                                                        aamountc,
    139                                                        conn),
    140       TALER_PQ_query_param_amount_with_currency (conn,
    141                                                  &tamountc),
    142       GNUNET_PQ_query_param_fixed_size (&hc,
    143                                         sizeof (hc)),
    144       TALER_PQ_query_param_array_hash_code (2,
    145                                             hcs,
    146                                             conn),
    147       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     result = GNUNET_PQ_exec_prepared (conn,
    155                                       "test_insert",
    156                                       params_insert);
    157     for (uint8_t i = 0; i < 5; i++)
    158     {
    159       printf (" in_cs_r_pubs[%d]=%s\n",
    160               i,
    161               GNUNET_STRINGS_data_to_string_alloc (
    162                 &in_cs_r_pubs[i],
    163                 sizeof(in_cs_r_pubs[i])));
    164     }
    165 
    166     if (PGRES_COMMAND_OK != PQresultStatus (result))
    167     {
    168       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    169                   "Database failure: %s\n",
    170                   PQresultErrorMessage (result));
    171       PQclear (result);
    172       return 1;
    173     }
    174     PQclear (result);
    175     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     struct GNUNET_PQ_QueryParam params_select[] = {
    195       GNUNET_PQ_query_param_end
    196     };
    197     struct GNUNET_PQ_ResultSpec results_select[] = {
    198       TALER_PQ_result_spec_amount ("tamount",
    199                                    "EUR",
    200                                    &tamount2),
    201       TALER_PQ_result_spec_json ("json",
    202                                  &json2),
    203       TALER_PQ_result_spec_array_amount (conn,
    204                                          "aamount",
    205                                          "EUR",
    206                                          &npamount,
    207                                          &pamount),
    208       TALER_PQ_result_spec_array_amount_with_currency (conn,
    209                                                        "aamountc",
    210                                                        &npamountc,
    211                                                        &pamountc),
    212       TALER_PQ_result_spec_array_amount (conn,
    213                                          "aamountn",
    214                                          "EUR",
    215                                          &npamountn,
    216                                          &pamountn),
    217       TALER_PQ_result_spec_array_amount_with_currency (conn,
    218                                                        "aamountnc",
    219                                                        &npamountnc,
    220                                                        &pamountnc),
    221       TALER_PQ_result_spec_amount_with_currency ("tamountc",
    222                                                  &tamountc2),
    223       GNUNET_PQ_result_spec_auto_from_type ("hash",
    224                                             &hc2),
    225       TALER_PQ_result_spec_array_hash_code (conn,
    226                                             "hashes",
    227                                             &nhcs,
    228                                             &hcs2),
    229       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     if (1 !=
    237         GNUNET_PQ_eval_prepared_singleton_select (conn,
    238                                                   "test_select",
    239                                                   params_select,
    240                                                   results_select))
    241     {
    242       GNUNET_break (0);
    243       return 1;
    244     }
    245     GNUNET_break (0 ==
    246                   TALER_amount_cmp (&tamount,
    247                                     &tamount2));
    248     GNUNET_break (42 ==
    249                   json_integer_value (json_object_get (json2,
    250                                                        "foo")));
    251     GNUNET_break (3 == npamount);
    252     for (size_t i = 0; i < 3; i++)
    253     {
    254       GNUNET_break (0 ==
    255                     TALER_amount_cmp (&aamount[i],
    256                                       &pamount[i]));
    257     }
    258     GNUNET_break (2 == npamountc);
    259     for (size_t i = 0; i < npamountc; i++)
    260     {
    261       GNUNET_break (0 ==
    262                     TALER_amount_cmp (&aamountc[i],
    263                                       &pamountc[i]));
    264     }
    265     GNUNET_break (0 ==
    266                   TALER_amount_cmp (&tamountc,
    267                                     &tamountc2));
    268     GNUNET_break (0 == GNUNET_memcmp (&hc,&hc2));
    269     for (size_t i = 0; i < 2; i++)
    270     {
    271       GNUNET_break (0 ==
    272                     GNUNET_memcmp (&hcs[i],
    273                                    &hcs2[i]));
    274     }
    275     GNUNET_break (5 == n_rpubs);
    276     for (uint8_t i = 0; i < 5; i++)
    277     {
    278       GNUNET_break (0 ==
    279                     GNUNET_memcmp (&in_cs_r_pubs[i],
    280                                    &out_cs_r_pubs[i]));
    281       printf ("out_cs_r_pubs[%d]=%s\n",
    282               i,
    283               GNUNET_STRINGS_data_to_string_alloc (
    284                 &out_cs_r_pubs[i],
    285                 sizeof(out_cs_r_pubs[i])));
    286     }
    287     GNUNET_PQ_cleanup_result (results_select);
    288   }
    289   return 0;
    290 }
    291 
    292 
    293 int
    294 main (int argc,
    295       const char *const argv[])
    296 {
    297   struct GNUNET_PQ_ExecuteStatement es[] = {
    298     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     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     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     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   GNUNET_log_setup ("test-pq",
    342                     "WARNING",
    343                     NULL);
    344   conn = GNUNET_PQ_connect ("postgres:///talercheck",
    345                             NULL,
    346                             es,
    347                             NULL);
    348   if (NULL == conn)
    349     return 77;
    350   if (GNUNET_OK !=
    351       postgres_prepare (conn))
    352   {
    353     GNUNET_break (0);
    354     GNUNET_PQ_disconnect (conn);
    355     return 1;
    356   }
    357 
    358   ret = run_queries (conn);
    359   {
    360     struct GNUNET_PQ_ExecuteStatement ds[] = {
    361       GNUNET_PQ_make_execute ("DROP TABLE test_pq"),
    362       GNUNET_PQ_EXECUTE_STATEMENT_END
    363     };
    364 
    365     if (GNUNET_OK !=
    366         GNUNET_PQ_exec_statements (conn,
    367                                    ds))
    368     {
    369       fprintf (stderr,
    370                "Failed to drop table\n");
    371       GNUNET_PQ_disconnect (conn);
    372       return 1;
    373     }
    374   }
    375   GNUNET_PQ_disconnect (conn);
    376   return ret;
    377 }
    378 
    379 
    380 /* end of test_pq.c */