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


      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 (in_cs_r_pubs,
    127                               sizeof(struct GNUNET_CRYPTO_CSPublicRPairP) * 5);
    128   {
    129     struct GNUNET_PQ_QueryParam params_insert[] = {
    130       TALER_PQ_query_param_amount (conn,
    131                                    &tamount),
    132       TALER_PQ_query_param_json (json),
    133       TALER_PQ_query_param_array_amount (3,
    134                                          aamount,
    135                                          conn),
    136       TALER_PQ_query_param_array_amount_with_currency (2,
    137                                                        aamountc,
    138                                                        "merchant",
    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                                                        "merchant",
    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                                                        "merchant",
    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 SCHEMA IF NOT EXISTS merchant;"
    303                             " END "
    304                             "$$;"),
    305     GNUNET_PQ_make_execute ("DO $$ "
    306                             " BEGIN"
    307                             " CREATE DOMAIN gnunet_hashcode AS BYTEA"
    308                             "   CHECK(length(VALUE)=64);"
    309                             " EXCEPTION"
    310                             "   WHEN duplicate_object THEN null;"
    311                             " END "
    312                             "$$;"),
    313     GNUNET_PQ_make_execute ("DO $$ "
    314                             " BEGIN"
    315                             " CREATE TYPE taler_amount AS"
    316                             "   (val INT8, frac INT4);"
    317                             " EXCEPTION"
    318                             "   WHEN duplicate_object THEN null;"
    319                             " END "
    320                             "$$;"),
    321     GNUNET_PQ_make_execute ("DO $$ "
    322                             " BEGIN"
    323                             " CREATE TYPE merchant.taler_amount_currency AS"
    324                             "   (val INT8, frac INT4, curr VARCHAR(12));"
    325                             " EXCEPTION"
    326                             "   WHEN duplicate_object THEN null;"
    327                             " END "
    328                             "$$;"),
    329     GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS test_pq ("
    330                             "tamount taler_amount NOT NULL"
    331                             ",json VARCHAR NOT NULL"
    332                             ",aamount taler_amount[]"
    333                             ",aamountc merchant.taler_amount_currency[]"
    334                             ",aamountn taler_amount[] NOT NULL DEFAULT ARRAY[]::taler_amount[]"
    335                             ",aamountnc merchant.taler_amount_currency[] NOT NULL DEFAULT ARRAY[]::merchant.taler_amount_currency[]"
    336                             ",tamountc merchant.taler_amount_currency"
    337                             ",hash gnunet_hashcode"
    338                             ",hashes gnunet_hashcode[]"
    339                             ",cs_r_pubs BYTEA[]"
    340                             ")"),
    341     GNUNET_PQ_EXECUTE_STATEMENT_END
    342   };
    343   struct GNUNET_PQ_Context *conn;
    344   int ret;
    345   struct GNUNET_CONFIGURATION_Handle *cfg;
    346 
    347   (void) argc;
    348   (void) argv;
    349   GNUNET_log_setup ("test-pq",
    350                     "WARNING",
    351                     NULL);
    352   cfg = GNUNET_CONFIGURATION_create (
    353     TALER_EXCHANGE_project_data ());
    354   GNUNET_CONFIGURATION_set_value_string (cfg,
    355                                          "test-pq",
    356                                          "CONFIG",
    357                                          "postgres:///talercheck");
    358   /* just to squash warning */
    359   GNUNET_CONFIGURATION_set_value_string (cfg,
    360                                          "test-pq",
    361                                          "SQL_DIR",
    362                                          "none");
    363   conn = GNUNET_PQ_init (cfg,
    364                          "test-pq",
    365                          NULL,
    366                          NULL);
    367   GNUNET_CONFIGURATION_destroy (cfg);
    368   if (NULL == conn)
    369     return 77;
    370   GNUNET_assert (GNUNET_OK ==
    371                  GNUNET_PQ_exec_statements (conn,
    372                                             es));
    373   if (GNUNET_OK !=
    374       postgres_prepare (conn))
    375   {
    376     GNUNET_break (0);
    377     GNUNET_PQ_disconnect (conn);
    378     return 1;
    379   }
    380   ret = run_queries (conn);
    381   {
    382     struct GNUNET_PQ_ExecuteStatement ds[] = {
    383       GNUNET_PQ_make_execute ("DROP TABLE test_pq"),
    384       GNUNET_PQ_EXECUTE_STATEMENT_END
    385     };
    386 
    387     if (GNUNET_OK !=
    388         GNUNET_PQ_exec_statements (conn,
    389                                    ds))
    390     {
    391       fprintf (stderr,
    392                "Failed to drop table\n");
    393       GNUNET_PQ_disconnect (conn);
    394       return 1;
    395     }
    396   }
    397   GNUNET_PQ_disconnect (conn);
    398   return ret;
    399 }
    400 
    401 
    402 /* end of test_pq.c */