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


      1 /*
      2   This file is part of TALER
      3   (C) 2015, 2016, 2023 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 "taler/platform.h"
     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                             ",tamountc"
     56                             ",hash"
     57                             ",hashes"
     58                             ",cs_r_pubs"
     59                             " FROM test_pq;"),
     60     GNUNET_PQ_PREPARED_STATEMENT_END
     61   };
     62 
     63   return GNUNET_PQ_prepare_statements (db,
     64                                        ps);
     65 }
     66 
     67 
     68 /**
     69  * Run actual test queries.
     70  *
     71  * @return 0 on success
     72  */
     73 static int
     74 run_queries (struct GNUNET_PQ_Context *conn)
     75 {
     76   struct TALER_Amount tamount;
     77   struct TALER_Amount aamount[3];
     78   struct TALER_Amount aamountc[2];
     79   struct TALER_Amount tamountc;
     80   struct GNUNET_HashCode hc =
     81   {{0xdeadbeef,0xdeadbeef,0xdeadbeef,0xdeadbeef,
     82     0xdeadbeef,0xdeadbeef,0xdeadbeef,0xdeadbeef,
     83     0xdeadbeef,0xdeadbeef,0xdeadbeef,0xdeadbeef,
     84     0xdeadbeef,0xdeadbeef,0xdeadbeef,0xdeadbeef, }};
     85   struct GNUNET_HashCode hcs[2] =
     86   {{{0xc0feec0f,0xc0feec0f,0xc0feec0f,0xc0feec0f,
     87      0xc0feec0f,0xc0feec0f,0xc0feec0f,0xc0feec0f,
     88      0xc0feec0f,0xc0feec0f,0xc0feec0f,0xc0feec0f,
     89      0xc0feec0f,0xc0feec0f,0xc0feec0f,0xc0feec0f,}},
     90    {{0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,
     91      0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,
     92      0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,
     93      0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,}}};
     94   struct GNUNET_CRYPTO_CSPublicRPairP in_cs_r_pubs[5];
     95   json_t *json;
     96 
     97   GNUNET_assert (GNUNET_OK ==
     98                  TALER_string_to_amount ("EUR:5.3",
     99                                          &aamount[0]));
    100   GNUNET_assert (GNUNET_OK ==
    101                  TALER_string_to_amount ("EUR:6.4",
    102                                          &aamount[1]));
    103   GNUNET_assert (GNUNET_OK ==
    104                  TALER_string_to_amount ("EUR:7.5",
    105                                          &aamount[2]));
    106   GNUNET_assert (GNUNET_OK ==
    107                  TALER_string_to_amount ("EUR:7.7",
    108                                          &tamount));
    109   GNUNET_assert (GNUNET_OK ==
    110                  TALER_string_to_amount ("USD:3.2",
    111                                          &aamountc[0]));
    112   GNUNET_assert (GNUNET_OK ==
    113                  TALER_string_to_amount ("CHF:4.5",
    114                                          &aamountc[1]));
    115   GNUNET_assert (GNUNET_OK ==
    116                  TALER_string_to_amount ("FOO:8.7",
    117                                          &tamountc));
    118   json = json_object ();
    119   GNUNET_assert (NULL != json);
    120   GNUNET_assert (0 ==
    121                  json_object_set_new (json,
    122                                       "foo",
    123                                       json_integer (42)));
    124   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
    125                               in_cs_r_pubs,
    126                               sizeof(struct GNUNET_CRYPTO_CSPublicRPairP) * 5);
    127   {
    128     struct GNUNET_PQ_QueryParam params_insert[] = {
    129       TALER_PQ_query_param_amount (conn,
    130                                    &tamount),
    131       TALER_PQ_query_param_json (json),
    132       TALER_PQ_query_param_array_amount (3,
    133                                          aamount,
    134                                          conn),
    135       TALER_PQ_query_param_array_amount_with_currency (2,
    136                                                        aamountc,
    137                                                        conn),
    138       TALER_PQ_query_param_amount_with_currency (conn,
    139                                                  &tamountc),
    140       GNUNET_PQ_query_param_fixed_size (&hc,
    141                                         sizeof (hc)),
    142       TALER_PQ_query_param_array_hash_code (2,
    143                                             hcs,
    144                                             conn),
    145       TALER_PQ_query_param_array_cs_r_pub (5,
    146                                            in_cs_r_pubs,
    147                                            conn),
    148       GNUNET_PQ_query_param_end
    149     };
    150     PGresult *result;
    151 
    152     result = GNUNET_PQ_exec_prepared (conn,
    153                                       "test_insert",
    154                                       params_insert);
    155     for (uint8_t i = 0; i < 5; i++)
    156     {
    157       printf (" in_cs_r_pubs[%d]=%s\n",
    158               i,
    159               GNUNET_STRINGS_data_to_string_alloc (
    160                 &in_cs_r_pubs[i],
    161                 sizeof(in_cs_r_pubs[i])));
    162     }
    163 
    164     if (PGRES_COMMAND_OK != PQresultStatus (result))
    165     {
    166       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    167                   "Database failure: %s\n",
    168                   PQresultErrorMessage (result));
    169       PQclear (result);
    170       return 1;
    171     }
    172     PQclear (result);
    173     json_decref (json);
    174   }
    175   {
    176     struct TALER_Amount tamount2;
    177     struct TALER_Amount tamountc2;
    178     struct TALER_Amount *pamount;
    179     struct TALER_Amount *pamountc;
    180     struct GNUNET_HashCode hc2;
    181     struct GNUNET_HashCode *hcs2;
    182     struct GNUNET_CRYPTO_CSPublicRPairP *out_cs_r_pubs;
    183     size_t npamount;
    184     size_t npamountc;
    185     size_t nhcs;
    186     size_t n_rpubs;
    187     json_t *json2;
    188     struct GNUNET_PQ_QueryParam params_select[] = {
    189       GNUNET_PQ_query_param_end
    190     };
    191     struct GNUNET_PQ_ResultSpec results_select[] = {
    192       TALER_PQ_result_spec_amount ("tamount",
    193                                    "EUR",
    194                                    &tamount2),
    195       TALER_PQ_result_spec_json ("json",
    196                                  &json2),
    197       TALER_PQ_result_spec_array_amount (conn,
    198                                          "aamount",
    199                                          "EUR",
    200                                          &npamount,
    201                                          &pamount),
    202       TALER_PQ_result_spec_array_amount_with_currency (conn,
    203                                                        "aamountc",
    204                                                        &npamountc,
    205                                                        &pamountc),
    206       TALER_PQ_result_spec_amount_with_currency ("tamountc",
    207                                                  &tamountc2),
    208       GNUNET_PQ_result_spec_auto_from_type ("hash",
    209                                             &hc2),
    210       TALER_PQ_result_spec_array_hash_code (conn,
    211                                             "hashes",
    212                                             &nhcs,
    213                                             &hcs2),
    214       TALER_PQ_result_spec_array_cs_r_pub (conn,
    215                                            "cs_r_pubs",
    216                                            &n_rpubs,
    217                                            &out_cs_r_pubs),
    218       GNUNET_PQ_result_spec_end
    219     };
    220 
    221     if (1 !=
    222         GNUNET_PQ_eval_prepared_singleton_select (conn,
    223                                                   "test_select",
    224                                                   params_select,
    225                                                   results_select))
    226     {
    227       GNUNET_break (0);
    228       return 1;
    229     }
    230     GNUNET_break (0 ==
    231                   TALER_amount_cmp (&tamount,
    232                                     &tamount2));
    233     GNUNET_break (42 ==
    234                   json_integer_value (json_object_get (json2,
    235                                                        "foo")));
    236     GNUNET_break (3 == npamount);
    237     for (size_t i = 0; i < 3; i++)
    238     {
    239       GNUNET_break (0 ==
    240                     TALER_amount_cmp (&aamount[i],
    241                                       &pamount[i]));
    242     }
    243     GNUNET_break (2 == npamountc);
    244     for (size_t i = 0; i < npamountc; i++)
    245     {
    246       GNUNET_break (0 ==
    247                     TALER_amount_cmp (&aamountc[i],
    248                                       &pamountc[i]));
    249     }
    250     GNUNET_break (0 ==
    251                   TALER_amount_cmp (&tamountc,
    252                                     &tamountc2));
    253     GNUNET_break (0 == GNUNET_memcmp (&hc,&hc2));
    254     for (size_t i = 0; i < 2; i++)
    255     {
    256       GNUNET_break (0 ==
    257                     GNUNET_memcmp (&hcs[i],
    258                                    &hcs2[i]));
    259     }
    260     GNUNET_break (5 == n_rpubs);
    261     for (uint8_t i = 0; i < 5; i++)
    262     {
    263       GNUNET_break (0 ==
    264                     GNUNET_memcmp (&in_cs_r_pubs[i],
    265                                    &out_cs_r_pubs[i]));
    266       printf ("out_cs_r_pubs[%d]=%s\n",
    267               i,
    268               GNUNET_STRINGS_data_to_string_alloc (
    269                 &out_cs_r_pubs[i],
    270                 sizeof(out_cs_r_pubs[i])));
    271     }
    272     GNUNET_PQ_cleanup_result (results_select);
    273   }
    274   return 0;
    275 }
    276 
    277 
    278 int
    279 main (int argc,
    280       const char *const argv[])
    281 {
    282   struct GNUNET_PQ_ExecuteStatement es[] = {
    283     GNUNET_PQ_make_execute ("DO $$ "
    284                             " BEGIN"
    285                             " CREATE DOMAIN gnunet_hashcode AS BYTEA"
    286                             "   CHECK(length(VALUE)=64);"
    287                             " EXCEPTION"
    288                             "   WHEN duplicate_object THEN null;"
    289                             " END "
    290                             "$$;"),
    291     GNUNET_PQ_make_execute ("DO $$ "
    292                             " BEGIN"
    293                             " CREATE TYPE taler_amount AS"
    294                             "   (val INT8, frac INT4);"
    295                             " EXCEPTION"
    296                             "   WHEN duplicate_object THEN null;"
    297                             " END "
    298                             "$$;"),
    299     GNUNET_PQ_make_execute ("DO $$ "
    300                             " BEGIN"
    301                             " CREATE TYPE taler_amount_currency AS"
    302                             "   (val INT8, frac INT4, curr VARCHAR(12));"
    303                             " EXCEPTION"
    304                             "   WHEN duplicate_object THEN null;"
    305                             " END "
    306                             "$$;"),
    307     GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS test_pq ("
    308                             " tamount taler_amount NOT NULL"
    309                             ",json VARCHAR NOT NULL"
    310                             ",aamount taler_amount[]"
    311                             ",aamountc taler_amount_currency[]"
    312                             ",tamountc taler_amount_currency"
    313                             ",hash gnunet_hashcode"
    314                             ",hashes gnunet_hashcode[]"
    315                             ",cs_r_pubs BYTEA[]"
    316                             ")"),
    317     GNUNET_PQ_EXECUTE_STATEMENT_END
    318   };
    319   struct GNUNET_PQ_Context *conn;
    320   int ret;
    321 
    322   (void) argc;
    323   (void) argv;
    324   GNUNET_log_setup ("test-pq",
    325                     "WARNING",
    326                     NULL);
    327   conn = GNUNET_PQ_connect ("postgres:///talercheck",
    328                             NULL,
    329                             es,
    330                             NULL);
    331   if (NULL == conn)
    332     return 77;
    333   if (GNUNET_OK !=
    334       postgres_prepare (conn))
    335   {
    336     GNUNET_break (0);
    337     GNUNET_PQ_disconnect (conn);
    338     return 1;
    339   }
    340 
    341   ret = run_queries (conn);
    342   {
    343     struct GNUNET_PQ_ExecuteStatement ds[] = {
    344       GNUNET_PQ_make_execute ("DROP TABLE test_pq"),
    345       GNUNET_PQ_EXECUTE_STATEMENT_END
    346     };
    347 
    348     if (GNUNET_OK !=
    349         GNUNET_PQ_exec_statements (conn,
    350                                    ds))
    351     {
    352       fprintf (stderr,
    353                "Failed to drop table\n");
    354       GNUNET_PQ_disconnect (conn);
    355       return 1;
    356     }
    357   }
    358   GNUNET_PQ_disconnect (conn);
    359   return ret;
    360 }
    361 
    362 
    363 /* end of test_pq.c */