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 */