LCOV - code coverage report
Current view: top level - pq - test_pq.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 86.8 % 151 131
Test Date: 2026-10-10 21:00:14 Functions: 100.0 % 4 4

            Line data    Source code
       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            1 : postgres_prepare (struct GNUNET_PQ_Context *db)
      35              : {
      36            1 :   struct GNUNET_PQ_PreparedStatement ps[] = {
      37            1 :     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              :                             ",denom_sigs"
      48              :                             ") VALUES "
      49              :                             "($1, $2, $3, $4, $5, $6, $7, $8, $9);"),
      50            1 :     GNUNET_PQ_make_prepare ("test_select_denom_sigs",
      51              :                             "SELECT"
      52              :                             " ds.denom_sig"
      53              :                             " FROM test_pq"
      54              :                             " CROSS JOIN LATERAL"
      55              :                             "   UNNEST (denom_sigs) WITH ORDINALITY"
      56              :                             "     AS ds (denom_sig, idx)"
      57              :                             " ORDER BY ds.idx;"),
      58            1 :     GNUNET_PQ_make_prepare ("test_select",
      59              :                             "SELECT"
      60              :                             " tamount"
      61              :                             ",json"
      62              :                             ",aamount"
      63              :                             ",aamountc"
      64              :                             ",aamountn"
      65              :                             ",aamountnc"
      66              :                             ",tamountc"
      67              :                             ",hash"
      68              :                             ",hashes"
      69              :                             ",cs_r_pubs"
      70              :                             " FROM test_pq;"),
      71              :     GNUNET_PQ_PREPARED_STATEMENT_END
      72              :   };
      73              : 
      74            1 :   return GNUNET_PQ_prepare_statements (db,
      75              :                                        ps);
      76              : }
      77              : 
      78              : 
      79              : /**
      80              :  * Closure for #denom_sig_cb().
      81              :  */
      82              : struct DenomSigCheck
      83              : {
      84              :   /**
      85              :    * Signatures we inserted, in order.
      86              :    */
      87              :   const struct TALER_DenominationSignature *expected;
      88              : 
      89              :   /**
      90              :    * Number of entries in @e expected.
      91              :    */
      92              :   unsigned int num;
      93              : 
      94              :   /**
      95              :    * Rows seen so far.
      96              :    */
      97              :   unsigned int seen;
      98              : 
      99              :   /**
     100              :    * Set to true if a row did not match.
     101              :    */
     102              :   bool mismatch;
     103              : };
     104              : 
     105              : 
     106              : /**
     107              :  * Compare each unblinded signature read back from the array
     108              :  * with the one we inserted at the same position.
     109              :  *
     110              :  * @param cls a `struct DenomSigCheck *`
     111              :  * @param result the result
     112              :  * @param num_results number of rows
     113              :  */
     114              : static void
     115            1 : denom_sig_cb (void *cls,
     116              :               PGresult *result,
     117              :               unsigned int num_results)
     118              : {
     119            1 :   struct DenomSigCheck *dsc = cls;
     120              : 
     121            3 :   for (unsigned int i = 0; i < num_results; i++)
     122              :   {
     123            2 :     struct TALER_DenominationSignature got = { 0 };
     124            2 :     struct GNUNET_PQ_ResultSpec rs[] = {
     125            2 :       GNUNET_PQ_result_spec_unblinded_sig ("denom_sig",
     126              :                                            &got.unblinded_sig),
     127              :       GNUNET_PQ_result_spec_end
     128              :     };
     129              : 
     130            2 :     if (GNUNET_OK !=
     131            2 :         GNUNET_PQ_extract_result (result,
     132              :                                   rs,
     133              :                                   i))
     134              :     {
     135            0 :       GNUNET_break (0);
     136            0 :       dsc->mismatch = true;
     137            0 :       return;
     138              :     }
     139            4 :     if ( (dsc->seen >= dsc->num) ||
     140            2 :          (0 != TALER_denom_sig_cmp (&got,
     141            2 :                                     &dsc->expected[dsc->seen])) )
     142              :     {
     143            0 :       GNUNET_break (0);
     144            0 :       dsc->mismatch = true;
     145              :     }
     146            2 :     dsc->seen++;
     147            2 :     GNUNET_PQ_cleanup_result (rs);
     148              :   }
     149              : }
     150              : 
     151              : 
     152              : /**
     153              :  * Run actual test queries.
     154              :  *
     155              :  * @return 0 on success
     156              :  */
     157              : static int
     158            1 : run_queries (struct GNUNET_PQ_Context *conn)
     159              : {
     160              :   struct TALER_DenominationSignature denom_sigs[2];
     161              :   struct TALER_Amount tamount;
     162              :   struct TALER_Amount aamount[3];
     163              :   struct TALER_Amount aamountc[2];
     164              :   struct TALER_Amount tamountc;
     165            1 :   struct GNUNET_HashCode hc =
     166              :   {{0xdeadbeef,0xdeadbeef,0xdeadbeef,0xdeadbeef,
     167              :     0xdeadbeef,0xdeadbeef,0xdeadbeef,0xdeadbeef,
     168              :     0xdeadbeef,0xdeadbeef,0xdeadbeef,0xdeadbeef,
     169              :     0xdeadbeef,0xdeadbeef,0xdeadbeef,0xdeadbeef, }};
     170            1 :   struct GNUNET_HashCode hcs[2] =
     171              :   {{{0xc0feec0f,0xc0feec0f,0xc0feec0f,0xc0feec0f,
     172              :      0xc0feec0f,0xc0feec0f,0xc0feec0f,0xc0feec0f,
     173              :      0xc0feec0f,0xc0feec0f,0xc0feec0f,0xc0feec0f,
     174              :      0xc0feec0f,0xc0feec0f,0xc0feec0f,0xc0feec0f,}},
     175              :    {{0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,
     176              :      0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,
     177              :      0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,
     178              :      0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,}}};
     179              :   struct GNUNET_CRYPTO_CSPublicRPairP in_cs_r_pubs[5];
     180              :   json_t *json;
     181              : 
     182            1 :   GNUNET_assert (GNUNET_OK ==
     183              :                  TALER_string_to_amount ("EUR:5.3",
     184              :                                          &aamount[0]));
     185            1 :   GNUNET_assert (GNUNET_OK ==
     186              :                  TALER_string_to_amount ("EUR:6.4",
     187              :                                          &aamount[1]));
     188            1 :   GNUNET_assert (GNUNET_OK ==
     189              :                  TALER_string_to_amount ("EUR:7.5",
     190              :                                          &aamount[2]));
     191            1 :   GNUNET_assert (GNUNET_OK ==
     192              :                  TALER_string_to_amount ("EUR:7.7",
     193              :                                          &tamount));
     194            1 :   GNUNET_assert (GNUNET_OK ==
     195              :                  TALER_string_to_amount ("USD:3.2",
     196              :                                          &aamountc[0]));
     197            1 :   GNUNET_assert (GNUNET_OK ==
     198              :                  TALER_string_to_amount ("CHF:4.5",
     199              :                                          &aamountc[1]));
     200            1 :   GNUNET_assert (GNUNET_OK ==
     201              :                  TALER_string_to_amount ("FOO:8.7",
     202              :                                          &tamountc));
     203            1 :   json = json_object ();
     204            1 :   GNUNET_assert (NULL != json);
     205            1 :   GNUNET_assert (0 ==
     206              :                  json_object_set_new (json,
     207              :                                       "foo",
     208              :                                       json_integer (42)));
     209            1 :   GNUNET_CRYPTO_random_block (in_cs_r_pubs,
     210              :                               sizeof(struct GNUNET_CRYPTO_CSPublicRPairP) * 5);
     211              :   /* one CS and one RSA signature: the two encodings differ in size */
     212              :   {
     213              :     struct GNUNET_CRYPTO_UnblindedSignature *ubs;
     214              :     struct GNUNET_CRYPTO_RsaPrivateKey *rsa_priv;
     215              : 
     216            1 :     ubs = GNUNET_new (struct GNUNET_CRYPTO_UnblindedSignature);
     217            1 :     ubs->cipher = GNUNET_CRYPTO_BSA_CS;
     218            1 :     ubs->rc = 1;
     219            1 :     GNUNET_CRYPTO_random_block (&ubs->details.cs_signature,
     220              :                                 sizeof (ubs->details.cs_signature));
     221            1 :     denom_sigs[0].unblinded_sig = ubs;
     222              : 
     223            1 :     rsa_priv = GNUNET_CRYPTO_rsa_private_key_create (1024);
     224            1 :     GNUNET_assert (NULL != rsa_priv);
     225            1 :     ubs = GNUNET_new (struct GNUNET_CRYPTO_UnblindedSignature);
     226            1 :     ubs->cipher = GNUNET_CRYPTO_BSA_RSA;
     227            1 :     ubs->rc = 1;
     228              :     ubs->details.rsa_signature
     229            1 :       = GNUNET_CRYPTO_rsa_sign_fdh (rsa_priv,
     230              :                                     &hc,
     231              :                                     sizeof (hc));
     232            1 :     GNUNET_assert (NULL != ubs->details.rsa_signature);
     233            1 :     GNUNET_CRYPTO_rsa_private_key_free (rsa_priv);
     234            1 :     denom_sigs[1].unblinded_sig = ubs;
     235              :   }
     236              :   {
     237            1 :     struct GNUNET_PQ_QueryParam params_insert[] = {
     238            1 :       TALER_PQ_query_param_amount (conn,
     239              :                                    &tamount),
     240            1 :       TALER_PQ_query_param_json (json),
     241            1 :       TALER_PQ_query_param_array_amount (3,
     242              :                                          aamount,
     243              :                                          conn),
     244            1 :       TALER_PQ_query_param_array_amount_with_currency (2,
     245              :                                                        aamountc,
     246              :                                                        "merchant",
     247              :                                                        conn),
     248            1 :       TALER_PQ_query_param_amount_with_currency (conn,
     249              :                                                  &tamountc),
     250            1 :       GNUNET_PQ_query_param_fixed_size (&hc,
     251              :                                         sizeof (hc)),
     252            1 :       TALER_PQ_query_param_array_hash_code (2,
     253              :                                             hcs,
     254              :                                             conn),
     255            1 :       TALER_PQ_query_param_array_cs_r_pub (5,
     256              :                                            in_cs_r_pubs,
     257              :                                            conn),
     258            1 :       TALER_PQ_query_param_array_denom_sig (2,
     259              :                                             denom_sigs,
     260              :                                             conn),
     261              :       GNUNET_PQ_query_param_end
     262              :     };
     263              :     PGresult *result;
     264              : 
     265            1 :     result = GNUNET_PQ_exec_prepared (conn,
     266              :                                       "test_insert",
     267              :                                       params_insert);
     268            6 :     for (uint8_t i = 0; i < 5; i++)
     269              :     {
     270            5 :       printf (" in_cs_r_pubs[%d]=%s\n",
     271              :               i,
     272              :               GNUNET_STRINGS_data_to_string_alloc (
     273            5 :                 &in_cs_r_pubs[i],
     274              :                 sizeof(in_cs_r_pubs[i])));
     275              :     }
     276              : 
     277            1 :     if (PGRES_COMMAND_OK != PQresultStatus (result))
     278              :     {
     279            0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     280              :                   "Database failure: %s\n",
     281              :                   PQresultErrorMessage (result));
     282            0 :       PQclear (result);
     283            0 :       return 1;
     284              :     }
     285            1 :     PQclear (result);
     286            1 :     json_decref (json);
     287              :   }
     288              :   {
     289              :     struct TALER_Amount tamount2;
     290              :     struct TALER_Amount tamountc2;
     291              :     struct TALER_Amount *pamount;
     292              :     struct TALER_Amount *pamountc;
     293              :     struct TALER_Amount *pamountn;
     294              :     struct TALER_Amount *pamountnc;
     295              :     struct GNUNET_HashCode hc2;
     296              :     struct GNUNET_HashCode *hcs2;
     297              :     struct GNUNET_CRYPTO_CSPublicRPairP *out_cs_r_pubs;
     298              :     size_t npamount;
     299              :     size_t npamountc;
     300              :     size_t npamountn;
     301              :     size_t npamountnc;
     302              :     size_t nhcs;
     303              :     size_t n_rpubs;
     304              :     json_t *json2;
     305            1 :     struct GNUNET_PQ_QueryParam params_select[] = {
     306              :       GNUNET_PQ_query_param_end
     307              :     };
     308            1 :     struct GNUNET_PQ_ResultSpec results_select[] = {
     309            1 :       TALER_PQ_result_spec_amount ("tamount",
     310              :                                    "EUR",
     311              :                                    &tamount2),
     312            1 :       TALER_PQ_result_spec_json ("json",
     313              :                                  &json2),
     314            1 :       TALER_PQ_result_spec_array_amount (conn,
     315              :                                          "aamount",
     316              :                                          "EUR",
     317              :                                          &npamount,
     318              :                                          &pamount),
     319            1 :       TALER_PQ_result_spec_array_amount_with_currency (conn,
     320              :                                                        "merchant",
     321              :                                                        "aamountc",
     322              :                                                        &npamountc,
     323              :                                                        &pamountc),
     324            1 :       TALER_PQ_result_spec_array_amount (conn,
     325              :                                          "aamountn",
     326              :                                          "EUR",
     327              :                                          &npamountn,
     328              :                                          &pamountn),
     329            1 :       TALER_PQ_result_spec_array_amount_with_currency (conn,
     330              :                                                        "merchant",
     331              :                                                        "aamountnc",
     332              :                                                        &npamountnc,
     333              :                                                        &pamountnc),
     334            1 :       TALER_PQ_result_spec_amount_with_currency ("tamountc",
     335              :                                                  &tamountc2),
     336            1 :       GNUNET_PQ_result_spec_auto_from_type ("hash",
     337              :                                             &hc2),
     338            1 :       TALER_PQ_result_spec_array_hash_code (conn,
     339              :                                             "hashes",
     340              :                                             &nhcs,
     341              :                                             &hcs2),
     342            1 :       TALER_PQ_result_spec_array_cs_r_pub (conn,
     343              :                                            "cs_r_pubs",
     344              :                                            &n_rpubs,
     345              :                                            &out_cs_r_pubs),
     346              :       GNUNET_PQ_result_spec_end
     347              :     };
     348              : 
     349            1 :     if (1 !=
     350            1 :         GNUNET_PQ_eval_prepared_singleton_select (conn,
     351              :                                                   "test_select",
     352              :                                                   params_select,
     353              :                                                   results_select))
     354              :     {
     355            0 :       GNUNET_break (0);
     356            0 :       return 1;
     357              :     }
     358            1 :     GNUNET_break (0 ==
     359              :                   TALER_amount_cmp (&tamount,
     360              :                                     &tamount2));
     361            1 :     GNUNET_break (42 ==
     362              :                   json_integer_value (json_object_get (json2,
     363              :                                                        "foo")));
     364            1 :     GNUNET_break (3 == npamount);
     365            4 :     for (size_t i = 0; i < 3; i++)
     366              :     {
     367            3 :       GNUNET_break (0 ==
     368              :                     TALER_amount_cmp (&aamount[i],
     369              :                                       &pamount[i]));
     370              :     }
     371            1 :     GNUNET_break (2 == npamountc);
     372            3 :     for (size_t i = 0; i < npamountc; i++)
     373              :     {
     374            2 :       GNUNET_break (0 ==
     375              :                     TALER_amount_cmp (&aamountc[i],
     376              :                                       &pamountc[i]));
     377              :     }
     378            1 :     GNUNET_break (0 ==
     379              :                   TALER_amount_cmp (&tamountc,
     380              :                                     &tamountc2));
     381            1 :     GNUNET_break (0 == GNUNET_memcmp (&hc,&hc2));
     382            3 :     for (size_t i = 0; i < 2; i++)
     383              :     {
     384            2 :       GNUNET_break (0 ==
     385              :                     GNUNET_memcmp (&hcs[i],
     386              :                                    &hcs2[i]));
     387              :     }
     388            1 :     GNUNET_break (5 == n_rpubs);
     389            6 :     for (uint8_t i = 0; i < 5; i++)
     390              :     {
     391            5 :       GNUNET_break (0 ==
     392              :                     GNUNET_memcmp (&in_cs_r_pubs[i],
     393              :                                    &out_cs_r_pubs[i]));
     394            5 :       printf ("out_cs_r_pubs[%d]=%s\n",
     395              :               i,
     396              :               GNUNET_STRINGS_data_to_string_alloc (
     397            5 :                 &out_cs_r_pubs[i],
     398              :                 sizeof(out_cs_r_pubs[i])));
     399              :     }
     400            1 :     GNUNET_PQ_cleanup_result (results_select);
     401              :   }
     402              :   {
     403            1 :     struct DenomSigCheck dsc = {
     404              :       .expected = denom_sigs,
     405              :       .num = 2
     406              :     };
     407            1 :     struct GNUNET_PQ_QueryParam params_select[] = {
     408              :       GNUNET_PQ_query_param_end
     409              :     };
     410              : 
     411            1 :     if (2 !=
     412            1 :         GNUNET_PQ_eval_prepared_multi_select (conn,
     413              :                                               "test_select_denom_sigs",
     414              :                                               params_select,
     415              :                                               &denom_sig_cb,
     416              :                                               &dsc))
     417              :     {
     418            0 :       GNUNET_break (0);
     419            0 :       return 1;
     420              :     }
     421            1 :     GNUNET_break (2 == dsc.seen);
     422            1 :     GNUNET_break (! dsc.mismatch);
     423            1 :     if ( (2 != dsc.seen) ||
     424            1 :          (dsc.mismatch) )
     425            0 :       return 1;
     426              :   }
     427            1 :   TALER_denom_sig_free (&denom_sigs[0]);
     428            1 :   TALER_denom_sig_free (&denom_sigs[1]);
     429            1 :   return 0;
     430              : }
     431              : 
     432              : 
     433              : int
     434            1 : main (int argc,
     435              :       const char *const argv[])
     436              : {
     437            1 :   struct GNUNET_PQ_ExecuteStatement es[] = {
     438            1 :     GNUNET_PQ_make_execute ("DO $$ "
     439              :                             " BEGIN"
     440              :                             " CREATE SCHEMA IF NOT EXISTS merchant;"
     441              :                             " END "
     442              :                             "$$;"),
     443            1 :     GNUNET_PQ_make_execute ("DO $$ "
     444              :                             " BEGIN"
     445              :                             " CREATE DOMAIN gnunet_hashcode AS BYTEA"
     446              :                             "   CHECK(length(VALUE)=64);"
     447              :                             " EXCEPTION"
     448              :                             "   WHEN duplicate_object THEN null;"
     449              :                             " END "
     450              :                             "$$;"),
     451            1 :     GNUNET_PQ_make_execute ("DO $$ "
     452              :                             " BEGIN"
     453              :                             " CREATE TYPE taler_amount AS"
     454              :                             "   (val INT8, frac INT4);"
     455              :                             " EXCEPTION"
     456              :                             "   WHEN duplicate_object THEN null;"
     457              :                             " END "
     458              :                             "$$;"),
     459            1 :     GNUNET_PQ_make_execute ("DO $$ "
     460              :                             " BEGIN"
     461              :                             " CREATE TYPE merchant.taler_amount_currency AS"
     462              :                             "   (val INT8, frac INT4, curr VARCHAR(12));"
     463              :                             " EXCEPTION"
     464              :                             "   WHEN duplicate_object THEN null;"
     465              :                             " END "
     466              :                             "$$;"),
     467            1 :     GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS test_pq ("
     468              :                             "tamount taler_amount NOT NULL"
     469              :                             ",json VARCHAR NOT NULL"
     470              :                             ",aamount taler_amount[]"
     471              :                             ",aamountc merchant.taler_amount_currency[]"
     472              :                             ",aamountn taler_amount[] NOT NULL DEFAULT ARRAY[]::taler_amount[]"
     473              :                             ",aamountnc merchant.taler_amount_currency[] NOT NULL DEFAULT ARRAY[]::merchant.taler_amount_currency[]"
     474              :                             ",tamountc merchant.taler_amount_currency"
     475              :                             ",hash gnunet_hashcode"
     476              :                             ",hashes gnunet_hashcode[]"
     477              :                             ",cs_r_pubs BYTEA[]"
     478              :                             ",denom_sigs BYTEA[]"
     479              :                             ")"),
     480              :     GNUNET_PQ_EXECUTE_STATEMENT_END
     481              :   };
     482              :   struct GNUNET_PQ_Context *conn;
     483              :   int ret;
     484              :   struct GNUNET_CONFIGURATION_Handle *cfg;
     485              : 
     486              :   (void) argc;
     487              :   (void) argv;
     488            1 :   GNUNET_log_setup ("test-pq",
     489              :                     "WARNING",
     490              :                     NULL);
     491            1 :   cfg = GNUNET_CONFIGURATION_create (
     492              :     TALER_EXCHANGE_project_data ());
     493            1 :   GNUNET_CONFIGURATION_set_value_string (cfg,
     494              :                                          "test-pq",
     495              :                                          "CONFIG",
     496              :                                          "postgres:///talercheck");
     497              :   /* just to squash warning */
     498            1 :   GNUNET_CONFIGURATION_set_value_string (cfg,
     499              :                                          "test-pq",
     500              :                                          "SQL_DIR",
     501              :                                          "none");
     502            1 :   conn = GNUNET_PQ_init (cfg,
     503              :                          "test-pq",
     504              :                          NULL,
     505              :                          NULL);
     506            1 :   GNUNET_CONFIGURATION_destroy (cfg);
     507            1 :   if (NULL == conn)
     508            0 :     return 77;
     509            1 :   GNUNET_assert (GNUNET_OK ==
     510              :                  GNUNET_PQ_exec_statements (conn,
     511              :                                             es));
     512            1 :   if (GNUNET_OK !=
     513            1 :       postgres_prepare (conn))
     514              :   {
     515            0 :     GNUNET_break (0);
     516            0 :     GNUNET_PQ_disconnect (conn);
     517            0 :     return 1;
     518              :   }
     519            1 :   ret = run_queries (conn);
     520              :   {
     521            1 :     struct GNUNET_PQ_ExecuteStatement ds[] = {
     522            1 :       GNUNET_PQ_make_execute ("DROP TABLE test_pq"),
     523              :       GNUNET_PQ_EXECUTE_STATEMENT_END
     524              :     };
     525              : 
     526            1 :     if (GNUNET_OK !=
     527            1 :         GNUNET_PQ_exec_statements (conn,
     528              :                                    ds))
     529              :     {
     530            0 :       fprintf (stderr,
     531              :                "Failed to drop table\n");
     532            0 :       GNUNET_PQ_disconnect (conn);
     533            0 :       return 1;
     534              :     }
     535              :   }
     536            1 :   GNUNET_PQ_disconnect (conn);
     537            1 :   return ret;
     538              : }
     539              : 
     540              : 
     541              : /* end of test_pq.c */
        

Generated by: LCOV version 2.0-1