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