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