test_auditordb_checkpoints.c (11745B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2016--2024 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 auditordb/test_auditordb_checkpoints.c 18 * @brief test cases for DB interaction functions 19 * @author Christian Grothoff 20 */ 21 #include <gnunet/gnunet_common.h> 22 #include <gnunet/gnunet_db_lib.h> 23 #include "auditordb_lib.h" 24 #include "auditor-database/create_tables.h" 25 #include "auditor-database/drop_tables.h" 26 #include "auditor-database/get_auditor_progress.h" 27 #include "auditor-database/get_balance.h" 28 #include "auditor-database/insert_auditor_progress.h" 29 #include "auditor-database/insert_balance.h" 30 #include "auditor-database/preflight.h" 31 #include "auditor-database/start.h" 32 #include "auditor-database/update_auditor_progress.h" 33 #include "auditor-database/update_balance.h" 34 35 36 /** 37 * Currency we use, must match CURRENCY in "test-auditor-db-postgres.conf". 38 */ 39 #define CURRENCY "EUR" 40 41 /** 42 * Report line of error if @a cond is true, and jump to label "drop". 43 */ 44 #define FAILIF(cond) \ 45 do { \ 46 if (! (cond)) { break;} \ 47 GNUNET_break (0); \ 48 goto drop; \ 49 } while (0) 50 51 /** 52 * Initializes @a ptr with random data. 53 */ 54 #define RND_BLK(ptr) \ 55 GNUNET_CRYPTO_random_block (ptr, \ 56 sizeof (*ptr)) 57 58 /** 59 * Initializes @a ptr with zeros. 60 */ 61 #define ZR_BLK(ptr) \ 62 memset (ptr, 0, sizeof (*ptr)) 63 64 65 /** 66 * Global result from the testcase. 67 */ 68 static int result = -1; 69 70 /** 71 * Database connection under test. 72 */ 73 static struct TALER_AUDITORDB_PostgresContext *pg; 74 75 76 /** 77 * Main function that will be run by the scheduler. 78 * 79 * @param cls closure with config 80 */ 81 static void 82 run (void *cls) 83 { 84 struct GNUNET_CONFIGURATION_Handle *cfg = cls; 85 struct TALER_Amount a1; 86 struct TALER_Amount a2; 87 struct TALER_Amount a3; 88 89 GNUNET_assert (GNUNET_OK == 90 TALER_string_to_amount (CURRENCY ":11.245678", 91 &a1)); 92 GNUNET_assert (GNUNET_OK == 93 TALER_string_to_amount (CURRENCY ":2", 94 &a2)); 95 GNUNET_assert (GNUNET_OK == 96 TALER_string_to_amount (CURRENCY ":3", 97 &a3)); 98 99 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 100 "Connecting to database\n"); 101 if (NULL == 102 (pg = TALER_AUDITORDB_connect (cfg))) 103 { 104 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 105 "Failed to connect to database\n"); 106 result = 77; 107 return; 108 } 109 GNUNET_assert (GNUNET_OK == 110 TALER_AUDITORDB_preflight (pg)); 111 (void) TALER_AUDITORDB_drop_tables (pg, 112 GNUNET_YES); 113 if (GNUNET_OK != 114 TALER_AUDITORDB_create_tables (pg, 115 false, 116 0)) 117 { 118 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 119 "Failed to 'create_tables'\n"); 120 result = 77; 121 goto unload; 122 } 123 if (GNUNET_SYSERR == 124 TALER_AUDITORDB_preflight (pg)) 125 { 126 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 127 "Failed preflight check\n"); 128 result = 77; 129 goto drop; 130 } 131 132 FAILIF (GNUNET_OK != 133 TALER_AUDITORDB_start (pg, 134 "test-auditordb-checkpoints")); 135 136 /* Test inserting a blank value, should tell us one result */ 137 GNUNET_assert ( 138 GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 139 TALER_AUDITORDB_insert_auditor_progress (pg, 140 "Test", 141 69, 142 NULL) 143 ); 144 /* Test re-inserting the same value; should yield no results */ 145 GNUNET_assert ( 146 GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == 147 TALER_AUDITORDB_insert_auditor_progress (pg, 148 "Test", 149 69, 150 NULL) 151 ); 152 /* Test inserting multiple values, with one already existing */ 153 GNUNET_assert ( 154 2 == TALER_AUDITORDB_insert_auditor_progress (pg, 155 "Test", 156 69, 157 "Test2", 158 123, 159 "Test3", 160 245, 161 NULL) 162 ); 163 /* Test re-re-inserting the same key with a different value; should also yield no results */ 164 GNUNET_assert ( 165 GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == 166 TALER_AUDITORDB_insert_auditor_progress (pg, 167 "Test", 168 42, 169 NULL) 170 ); 171 /* Test updating the same key (again) with a different value; should yield a result */ 172 GNUNET_assert ( 173 GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 174 TALER_AUDITORDB_update_auditor_progress (pg, 175 "Test", 176 42, 177 NULL) 178 ); 179 /* Test updating a key that doesn't exist; should yield 0 */ 180 GNUNET_assert ( 181 GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == 182 TALER_AUDITORDB_update_auditor_progress (pg, 183 "NonexistentTest", 184 1, 185 NULL) 186 ); 187 188 /* Right now, the state should look like this: 189 * Test = 42 190 * Test2 = 123 191 * Test3 = 245 192 * Let's make sure that's the case! */ 193 { 194 uint64_t value; 195 uint64_t valueNX; 196 uint64_t value3; 197 198 GNUNET_assert ( 199 3 == 200 TALER_AUDITORDB_get_auditor_progress ( 201 pg, 202 "Test", 203 &value, 204 "TestNX", 205 &valueNX, 206 "Test3", 207 &value3, 208 NULL) 209 ); 210 GNUNET_assert (value == 42); 211 GNUNET_assert (valueNX == 0); 212 GNUNET_assert (value3 == 245); 213 } 214 /* Ensure the rest are also at their expected values */ 215 { 216 uint64_t value; 217 218 GNUNET_assert ( 219 GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 220 TALER_AUDITORDB_get_auditor_progress ( 221 pg, 222 "Test2", 223 &value, 224 NULL) 225 ); 226 GNUNET_assert (value == 123); 227 } 228 { 229 uint64_t value; 230 231 GNUNET_assert ( 232 GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 233 TALER_AUDITORDB_get_auditor_progress ( 234 pg, 235 "Test3", 236 &value, 237 NULL) 238 ); 239 GNUNET_assert (value == 245); 240 } 241 { 242 uint64_t value; 243 244 /* Try fetching value that does not exist */ 245 GNUNET_assert ( 246 GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 247 TALER_AUDITORDB_get_auditor_progress ( 248 pg, 249 "TestNX", 250 &value, 251 NULL) 252 ); 253 GNUNET_assert (0 == value); 254 } 255 256 /* Test inserting a blank value, should tell us one result */ 257 GNUNET_assert ( 258 GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 259 TALER_AUDITORDB_insert_balance (pg, 260 "Test", 261 &a1, 262 NULL) 263 ); 264 /* Test re-inserting the same value; should yield no results */ 265 GNUNET_assert ( 266 GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == 267 TALER_AUDITORDB_insert_balance (pg, 268 "Test", 269 &a1, 270 NULL) 271 ); 272 /* Test inserting multiple values, with one already existing */ 273 GNUNET_assert ( 274 2 == TALER_AUDITORDB_insert_balance (pg, 275 "Test", 276 &a1, 277 "Test2", 278 &a2, 279 "Test3", 280 &a3, 281 NULL) 282 ); 283 /* Test re-re-inserting the same key with a different value; should also yield no results */ 284 GNUNET_assert ( 285 GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == 286 TALER_AUDITORDB_insert_balance (pg, 287 "Test", 288 &a2, 289 NULL) 290 ); 291 /* Test updating the same key (again) with a different value; should yield a result */ 292 GNUNET_assert ( 293 GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 294 TALER_AUDITORDB_update_balance (pg, 295 "Test", 296 &a2, 297 NULL) 298 ); 299 /* Test updating a key that doesn't exist; should yield 0 */ 300 GNUNET_assert ( 301 GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == 302 TALER_AUDITORDB_update_balance (pg, 303 "NonexistentTest", 304 &a2, 305 NULL) 306 ); 307 308 /* Right now, the state should look like this: 309 * Test = a2 310 * Test2 = a2 311 * Test3 = a3 312 * Let's make sure that's the case! */ 313 GNUNET_assert ( 314 GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 315 TALER_AUDITORDB_get_balance ( 316 pg, 317 "Test", 318 &a1, 319 NULL) 320 ); 321 GNUNET_assert (0 == 322 TALER_amount_cmp (&a1, 323 &a2)); 324 325 /* Ensure the rest are also at their expected values */ 326 GNUNET_assert ( 327 GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 328 TALER_AUDITORDB_get_balance ( 329 pg, 330 "Test2", 331 &a1, 332 NULL) 333 ); 334 GNUNET_assert (0 == 335 TALER_amount_cmp (&a1, 336 &a2)); 337 GNUNET_assert ( 338 GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 339 TALER_AUDITORDB_get_balance ( 340 pg, 341 "Test3", 342 &a1, 343 NULL) 344 ); 345 GNUNET_assert (0 == 346 TALER_amount_cmp (&a1, 347 &a3)); 348 349 /* Try fetching value that does not exist */ 350 GNUNET_assert ( 351 GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 352 TALER_AUDITORDB_get_balance ( 353 pg, 354 "TestNX", 355 &a1, 356 NULL) 357 ); 358 GNUNET_assert (TALER_amount_is_zero (&a1)); 359 360 result = 0; 361 GNUNET_break (0 <= 362 TALER_AUDITORDB_commit (pg)); 363 drop: 364 GNUNET_break (GNUNET_OK == 365 TALER_AUDITORDB_drop_tables (pg, 366 GNUNET_YES)); 367 unload: 368 TALER_AUDITORDB_disconnect (pg); 369 pg = NULL; 370 } 371 372 373 int 374 main (int argc, 375 char *const argv[]) 376 { 377 struct GNUNET_CONFIGURATION_Handle *cfg; 378 379 (void) argc; 380 result = -1; 381 GNUNET_log_setup (argv[0], 382 "INFO", 383 NULL); 384 cfg = GNUNET_CONFIGURATION_create (TALER_AUDITOR_project_data ()); 385 if (GNUNET_OK != 386 GNUNET_CONFIGURATION_parse (cfg, 387 "test-auditor-db-postgres.conf")) 388 { 389 GNUNET_break (0); 390 return 2; 391 } 392 GNUNET_SCHEDULER_run (&run, cfg); 393 GNUNET_CONFIGURATION_destroy (cfg); 394 return result; 395 }