test_auditordb_checkpoints.c (11675B)
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 (GNUNET_CRYPTO_QUALITY_WEAK, 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 true))) 104 { 105 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 106 "Failed to connect to database\n"); 107 result = 77; 108 return; 109 } 110 111 (void) TALER_AUDITORDB_drop_tables (pg, 112 GNUNET_YES); 113 if (GNUNET_OK != 114 TALER_AUDITORDB_create_tables (cfg, 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 135 /* Test inserting a blank value, should tell us one result */ 136 GNUNET_assert ( 137 GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 138 TALER_AUDITORDB_insert_auditor_progress (pg, 139 "Test", 140 69, 141 NULL) 142 ); 143 /* Test re-inserting the same value; should yield no results */ 144 GNUNET_assert ( 145 GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == 146 TALER_AUDITORDB_insert_auditor_progress (pg, 147 "Test", 148 69, 149 NULL) 150 ); 151 /* Test inserting multiple values, with one already existing */ 152 GNUNET_assert ( 153 2 == TALER_AUDITORDB_insert_auditor_progress (pg, 154 "Test", 155 69, 156 "Test2", 157 123, 158 "Test3", 159 245, 160 NULL) 161 ); 162 /* Test re-re-inserting the same key with a different value; should also yield no results */ 163 GNUNET_assert ( 164 GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == 165 TALER_AUDITORDB_insert_auditor_progress (pg, 166 "Test", 167 42, 168 NULL) 169 ); 170 /* Test updating the same key (again) with a different value; should yield a result */ 171 GNUNET_assert ( 172 GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 173 TALER_AUDITORDB_update_auditor_progress (pg, 174 "Test", 175 42, 176 NULL) 177 ); 178 /* Test updating a key that doesn't exist; should yield 0 */ 179 GNUNET_assert ( 180 GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == 181 TALER_AUDITORDB_update_auditor_progress (pg, 182 "NonexistentTest", 183 1, 184 NULL) 185 ); 186 187 /* Right now, the state should look like this: 188 * Test = 42 189 * Test2 = 123 190 * Test3 = 245 191 * Let's make sure that's the case! */ 192 { 193 uint64_t value; 194 uint64_t valueNX; 195 uint64_t value3; 196 197 GNUNET_assert ( 198 3 == 199 TALER_AUDITORDB_get_auditor_progress ( 200 pg, 201 "Test", 202 &value, 203 "TestNX", 204 &valueNX, 205 "Test3", 206 &value3, 207 NULL) 208 ); 209 GNUNET_assert (value == 42); 210 GNUNET_assert (valueNX == 0); 211 GNUNET_assert (value3 == 245); 212 } 213 /* Ensure the rest are also at their expected values */ 214 { 215 uint64_t value; 216 217 GNUNET_assert ( 218 GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 219 TALER_AUDITORDB_get_auditor_progress ( 220 pg, 221 "Test2", 222 &value, 223 NULL) 224 ); 225 GNUNET_assert (value == 123); 226 } 227 { 228 uint64_t value; 229 230 GNUNET_assert ( 231 GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 232 TALER_AUDITORDB_get_auditor_progress ( 233 pg, 234 "Test3", 235 &value, 236 NULL) 237 ); 238 GNUNET_assert (value == 245); 239 } 240 { 241 uint64_t value; 242 243 /* Try fetching value that does not exist */ 244 GNUNET_assert ( 245 GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 246 TALER_AUDITORDB_get_auditor_progress ( 247 pg, 248 "TestNX", 249 &value, 250 NULL) 251 ); 252 GNUNET_assert (0 == value); 253 } 254 255 /* Test inserting a blank value, should tell us one result */ 256 GNUNET_assert ( 257 GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 258 TALER_AUDITORDB_insert_balance (pg, 259 "Test", 260 &a1, 261 NULL) 262 ); 263 /* Test re-inserting the same value; should yield no results */ 264 GNUNET_assert ( 265 GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == 266 TALER_AUDITORDB_insert_balance (pg, 267 "Test", 268 &a1, 269 NULL) 270 ); 271 /* Test inserting multiple values, with one already existing */ 272 GNUNET_assert ( 273 2 == TALER_AUDITORDB_insert_balance (pg, 274 "Test", 275 &a1, 276 "Test2", 277 &a2, 278 "Test3", 279 &a3, 280 NULL) 281 ); 282 /* Test re-re-inserting the same key with a different value; should also yield no results */ 283 GNUNET_assert ( 284 GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == 285 TALER_AUDITORDB_insert_balance (pg, 286 "Test", 287 &a2, 288 NULL) 289 ); 290 /* Test updating the same key (again) with a different value; should yield a result */ 291 GNUNET_assert ( 292 GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 293 TALER_AUDITORDB_update_balance (pg, 294 "Test", 295 &a2, 296 NULL) 297 ); 298 /* Test updating a key that doesn't exist; should yield 0 */ 299 GNUNET_assert ( 300 GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == 301 TALER_AUDITORDB_update_balance (pg, 302 "NonexistentTest", 303 &a2, 304 NULL) 305 ); 306 307 /* Right now, the state should look like this: 308 * Test = a2 309 * Test2 = a2 310 * Test3 = a3 311 * Let's make sure that's the case! */ 312 GNUNET_assert ( 313 GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 314 TALER_AUDITORDB_get_balance ( 315 pg, 316 "Test", 317 &a1, 318 NULL) 319 ); 320 GNUNET_assert (0 == 321 TALER_amount_cmp (&a1, 322 &a2)); 323 324 /* Ensure the rest are also at their expected values */ 325 GNUNET_assert ( 326 GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 327 TALER_AUDITORDB_get_balance ( 328 pg, 329 "Test2", 330 &a1, 331 NULL) 332 ); 333 GNUNET_assert (0 == 334 TALER_amount_cmp (&a1, 335 &a2)); 336 GNUNET_assert ( 337 GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 338 TALER_AUDITORDB_get_balance ( 339 pg, 340 "Test3", 341 &a1, 342 NULL) 343 ); 344 GNUNET_assert (0 == 345 TALER_amount_cmp (&a1, 346 &a3)); 347 348 /* Try fetching value that does not exist */ 349 GNUNET_assert ( 350 GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == 351 TALER_AUDITORDB_get_balance ( 352 pg, 353 "TestNX", 354 &a1, 355 NULL) 356 ); 357 GNUNET_assert (TALER_amount_is_zero (&a1)); 358 359 result = 0; 360 GNUNET_break (0 <= 361 TALER_AUDITORDB_commit (pg)); 362 drop: 363 GNUNET_break (GNUNET_OK == 364 TALER_AUDITORDB_drop_tables (pg, 365 GNUNET_YES)); 366 unload: 367 TALER_AUDITORDB_disconnect (pg); 368 pg = NULL; 369 } 370 371 372 int 373 main (int argc, 374 char *const argv[]) 375 { 376 struct GNUNET_CONFIGURATION_Handle *cfg; 377 378 (void) argc; 379 result = -1; 380 GNUNET_log_setup (argv[0], 381 "INFO", 382 NULL); 383 cfg = GNUNET_CONFIGURATION_create (TALER_AUDITOR_project_data ()); 384 if (GNUNET_OK != 385 GNUNET_CONFIGURATION_parse (cfg, 386 "test-auditor-db-postgres.conf")) 387 { 388 GNUNET_break (0); 389 return 2; 390 } 391 GNUNET_SCHEDULER_run (&run, cfg); 392 GNUNET_CONFIGURATION_destroy (cfg); 393 return result; 394 }