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


      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                                                        NULL,
    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                                                        NULL,
    220                                                        "aamountnc",
    221                                                        &npamountnc,
    222                                                        &pamountnc),
    223       TALER_PQ_result_spec_amount_with_currency ("tamountc",
    224                                                  &tamountc2),
    225       GNUNET_PQ_result_spec_auto_from_type ("hash",
    226                                             &hc2),
    227       TALER_PQ_result_spec_array_hash_code (conn,
    228                                             "hashes",
    229                                             &nhcs,
    230                                             &hcs2),
    231       TALER_PQ_result_spec_array_cs_r_pub (conn,
    232                                            "cs_r_pubs",
    233                                            &n_rpubs,
    234                                            &out_cs_r_pubs),
    235       GNUNET_PQ_result_spec_end
    236     };
    237 
    238     if (1 !=
    239         GNUNET_PQ_eval_prepared_singleton_select (conn,
    240                                                   "test_select",
    241                                                   params_select,
    242                                                   results_select))
    243     {
    244       GNUNET_break (0);
    245       return 1;
    246     }
    247     GNUNET_break (0 ==
    248                   TALER_amount_cmp (&tamount,
    249                                     &tamount2));
    250     GNUNET_break (42 ==
    251                   json_integer_value (json_object_get (json2,
    252                                                        "foo")));
    253     GNUNET_break (3 == npamount);
    254     for (size_t i = 0; i < 3; i++)
    255     {
    256       GNUNET_break (0 ==
    257                     TALER_amount_cmp (&aamount[i],
    258                                       &pamount[i]));
    259     }
    260     GNUNET_break (2 == npamountc);
    261     for (size_t i = 0; i < npamountc; i++)
    262     {
    263       GNUNET_break (0 ==
    264                     TALER_amount_cmp (&aamountc[i],
    265                                       &pamountc[i]));
    266     }
    267     GNUNET_break (0 ==
    268                   TALER_amount_cmp (&tamountc,
    269                                     &tamountc2));
    270     GNUNET_break (0 == GNUNET_memcmp (&hc,&hc2));
    271     for (size_t i = 0; i < 2; i++)
    272     {
    273       GNUNET_break (0 ==
    274                     GNUNET_memcmp (&hcs[i],
    275                                    &hcs2[i]));
    276     }
    277     GNUNET_break (5 == n_rpubs);
    278     for (uint8_t i = 0; i < 5; i++)
    279     {
    280       GNUNET_break (0 ==
    281                     GNUNET_memcmp (&in_cs_r_pubs[i],
    282                                    &out_cs_r_pubs[i]));
    283       printf ("out_cs_r_pubs[%d]=%s\n",
    284               i,
    285               GNUNET_STRINGS_data_to_string_alloc (
    286                 &out_cs_r_pubs[i],
    287                 sizeof(out_cs_r_pubs[i])));
    288     }
    289     GNUNET_PQ_cleanup_result (results_select);
    290   }
    291   return 0;
    292 }
    293 
    294 
    295 int
    296 main (int argc,
    297       const char *const argv[])
    298 {
    299   struct GNUNET_PQ_ExecuteStatement es[] = {
    300     GNUNET_PQ_make_execute ("DO $$ "
    301                             " BEGIN"
    302                             " CREATE DOMAIN gnunet_hashcode AS BYTEA"
    303                             "   CHECK(length(VALUE)=64);"
    304                             " EXCEPTION"
    305                             "   WHEN duplicate_object THEN null;"
    306                             " END "
    307                             "$$;"),
    308     GNUNET_PQ_make_execute ("DO $$ "
    309                             " BEGIN"
    310                             " CREATE TYPE taler_amount AS"
    311                             "   (val INT8, frac INT4);"
    312                             " EXCEPTION"
    313                             "   WHEN duplicate_object THEN null;"
    314                             " END "
    315                             "$$;"),
    316     GNUNET_PQ_make_execute ("DO $$ "
    317                             " BEGIN"
    318                             " CREATE TYPE taler_amount_currency AS"
    319                             "   (val INT8, frac INT4, curr VARCHAR(12));"
    320                             " EXCEPTION"
    321                             "   WHEN duplicate_object THEN null;"
    322                             " END "
    323                             "$$;"),
    324     GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS test_pq ("
    325                             "tamount taler_amount NOT NULL"
    326                             ",json VARCHAR NOT NULL"
    327                             ",aamount taler_amount[]"
    328                             ",aamountc taler_amount_currency[]"
    329                             ",aamountn taler_amount[] NOT NULL DEFAULT ARRAY[]::taler_amount[]"
    330                             ",aamountnc taler_amount_currency[] NOT NULL DEFAULT ARRAY[]::taler_amount_currency[]"
    331                             ",tamountc taler_amount_currency"
    332                             ",hash gnunet_hashcode"
    333                             ",hashes gnunet_hashcode[]"
    334                             ",cs_r_pubs BYTEA[]"
    335                             ")"),
    336     GNUNET_PQ_EXECUTE_STATEMENT_END
    337   };
    338   struct GNUNET_PQ_Context *conn;
    339   int ret;
    340 
    341   (void) argc;
    342   (void) argv;
    343   GNUNET_log_setup ("test-pq",
    344                     "WARNING",
    345                     NULL);
    346   conn = GNUNET_PQ_connect ("postgres:///talercheck",
    347                             NULL,
    348                             es,
    349                             NULL);
    350   if (NULL == conn)
    351     return 77;
    352   if (GNUNET_OK !=
    353       postgres_prepare (conn))
    354   {
    355     GNUNET_break (0);
    356     GNUNET_PQ_disconnect (conn);
    357     return 1;
    358   }
    359 
    360   ret = run_queries (conn);
    361   {
    362     struct GNUNET_PQ_ExecuteStatement ds[] = {
    363       GNUNET_PQ_make_execute ("DROP TABLE test_pq"),
    364       GNUNET_PQ_EXECUTE_STATEMENT_END
    365     };
    366 
    367     if (GNUNET_OK !=
    368         GNUNET_PQ_exec_statements (conn,
    369                                    ds))
    370     {
    371       fprintf (stderr,
    372                "Failed to drop table\n");
    373       GNUNET_PQ_disconnect (conn);
    374       return 1;
    375     }
    376   }
    377   GNUNET_PQ_disconnect (conn);
    378   return ret;
    379 }
    380 
    381 
    382 /* end of test_pq.c */