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 (13977B)


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