Line data Source code
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 "taler/taler_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 1 : run (void *cls)
83 : {
84 1 : struct GNUNET_CONFIGURATION_Handle *cfg = cls;
85 : struct TALER_Amount a1;
86 : struct TALER_Amount a2;
87 : struct TALER_Amount a3;
88 :
89 1 : GNUNET_assert (GNUNET_OK ==
90 : TALER_string_to_amount (CURRENCY ":11.245678",
91 : &a1));
92 1 : GNUNET_assert (GNUNET_OK ==
93 : TALER_string_to_amount (CURRENCY ":2",
94 : &a2));
95 1 : GNUNET_assert (GNUNET_OK ==
96 : TALER_string_to_amount (CURRENCY ":3",
97 : &a3));
98 :
99 1 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
100 : "Connecting to database\n");
101 1 : if (NULL ==
102 1 : (pg = TALER_AUDITORDB_connect (cfg,
103 : true)))
104 : {
105 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
106 : "Failed to connect to database\n");
107 0 : result = 77;
108 0 : return;
109 : }
110 :
111 1 : (void) TALER_AUDITORDB_drop_tables (pg,
112 : GNUNET_YES);
113 1 : if (GNUNET_OK !=
114 1 : TALER_AUDITORDB_create_tables (cfg,
115 : false,
116 : 0))
117 : {
118 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
119 : "Failed to 'create_tables'\n");
120 0 : result = 77;
121 0 : goto unload;
122 : }
123 1 : if (GNUNET_SYSERR ==
124 1 : TALER_AUDITORDB_preflight (pg))
125 : {
126 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
127 : "Failed preflight check\n");
128 0 : result = 77;
129 0 : goto drop;
130 : }
131 :
132 1 : FAILIF (GNUNET_OK !=
133 : TALER_AUDITORDB_start (pg));
134 :
135 : /* Test inserting a blank value, should tell us one result */
136 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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 1 : GNUNET_assert (value == 42);
210 1 : GNUNET_assert (valueNX == 0);
211 1 : GNUNET_assert (value3 == 245);
212 : }
213 : /* Ensure the rest are also at their expected values */
214 : {
215 : uint64_t value;
216 :
217 1 : 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 1 : GNUNET_assert (value == 123);
226 : }
227 : {
228 : uint64_t value;
229 :
230 1 : 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 1 : GNUNET_assert (value == 245);
239 : }
240 : {
241 : uint64_t value;
242 :
243 : /* Try fetching value that does not exist */
244 1 : 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 1 : GNUNET_assert (0 == value);
253 : }
254 :
255 : /* Test inserting a blank value, should tell us one result */
256 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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 1 : GNUNET_assert (
313 : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
314 : TALER_AUDITORDB_get_balance (
315 : pg,
316 : "Test",
317 : &a1,
318 : NULL)
319 : );
320 1 : GNUNET_assert (0 ==
321 : TALER_amount_cmp (&a1,
322 : &a2));
323 :
324 : /* Ensure the rest are also at their expected values */
325 1 : GNUNET_assert (
326 : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
327 : TALER_AUDITORDB_get_balance (
328 : pg,
329 : "Test2",
330 : &a1,
331 : NULL)
332 : );
333 1 : GNUNET_assert (0 ==
334 : TALER_amount_cmp (&a1,
335 : &a2));
336 1 : GNUNET_assert (
337 : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
338 : TALER_AUDITORDB_get_balance (
339 : pg,
340 : "Test3",
341 : &a1,
342 : NULL)
343 : );
344 1 : GNUNET_assert (0 ==
345 : TALER_amount_cmp (&a1,
346 : &a3));
347 :
348 : /* Try fetching value that does not exist */
349 1 : GNUNET_assert (
350 : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
351 : TALER_AUDITORDB_get_balance (
352 : pg,
353 : "TestNX",
354 : &a1,
355 : NULL)
356 : );
357 1 : GNUNET_assert (TALER_amount_is_zero (&a1));
358 :
359 1 : result = 0;
360 1 : GNUNET_break (0 <=
361 : TALER_AUDITORDB_commit (pg));
362 1 : drop:
363 1 : GNUNET_break (GNUNET_OK ==
364 : TALER_AUDITORDB_drop_tables (pg,
365 : GNUNET_YES));
366 1 : unload:
367 1 : TALER_AUDITORDB_disconnect (pg);
368 1 : pg = NULL;
369 : }
370 :
371 :
372 : int
373 1 : main (int argc,
374 : char *const argv[])
375 : {
376 : struct GNUNET_CONFIGURATION_Handle *cfg;
377 :
378 : (void) argc;
379 1 : result = -1;
380 1 : GNUNET_log_setup (argv[0],
381 : "INFO",
382 : NULL);
383 1 : cfg = GNUNET_CONFIGURATION_create (TALER_AUDITOR_project_data ());
384 1 : if (GNUNET_OK !=
385 1 : GNUNET_CONFIGURATION_parse (cfg,
386 : "test-auditor-db-postgres.conf"))
387 : {
388 0 : GNUNET_break (0);
389 0 : return 2;
390 : }
391 1 : GNUNET_SCHEDULER_run (&run, cfg);
392 1 : GNUNET_CONFIGURATION_destroy (cfg);
393 1 : return result;
394 : }
|