2 Bacula® - The Network Backup Solution
4 Copyright (C) 2011-2011 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version three of the GNU Affero General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU Affero General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Program to test CATS DB routines
37 #include "cats/cats.h"
38 #include "cats/bvfs.h"
39 #include "findlib/find.h"
43 static const char *file = "COPYRIGHT";
44 //static DBId_t fnid=0;
45 static const char *db_name = "bacula";
46 static const char *db_user = "bacula";
47 static const char *db_password = "";
48 static const char *db_host = NULL;
49 static const char *db_address = NULL;
50 static int db_port = 0;
51 static int64_t pid = 0;
54 #define PLINE "\n============================================================\n"
59 "\nVersion: %s (%s)\n"
60 " -d <nn> set debug level to <nn>\n"
61 " -dt print timestamp in debug output\n"
62 " -n <name> specify the database name (default bacula)\n"
63 " -u <user> specify database user name (default bacula)\n"
64 " -P <password specify database password (default none)\n"
65 " -h <host> specify database host (default NULL)\n"
66 " -w <working> specify working directory\n"
67 " -p <path> specify path\n"
68 " -f <file> specify file\n"
69 " -l <limit> maximum tuple to fetch\n"
70 " -q print only errors\n"
72 " -? print this message\n\n"), 2011, VERSION, BDATE);
81 bool _warn(const char *file, int l, const char *op, int value, const char *label)
87 printf("WRN %.30s %s:%i on %s\n", label, file, l, op);
90 printf("OK %.30s\n", label);
95 #define warn(x, label) _warn(__FILE__, __LINE__, #x, (x), label)
97 bool _ok(const char *file, int l, const char *op, int value, const char *label)
103 printf("ERR %.30s %s:%i on %s\n", label, file, l, op);
107 printf("OK %.30s\n", label);
113 #define ok(x, label) _ok(__FILE__, __LINE__, #x, (x), label)
115 bool _nok(const char *file, int l, const char *op, int value, const char *label)
121 printf("ERR %.30s %s:%i on !%s\n", label, file, l, op);
125 printf("OK %.30s\n", label);
131 #define nok(x, label) _nok(__FILE__, __LINE__, #x, (x), label)
135 printf("Result %i/%i OK\n", _nb - _err, _nb);
139 static void cmp_pool(POOL_DBR &pr, POOL_DBR &pr2)
141 ok(pr.MaxVols == pr2.MaxVols, " Check Pool MaxVols");
142 ok(pr.UseOnce == pr2.UseOnce, " Check Pool UseOnce");
143 ok(pr.UseCatalog == pr2.UseCatalog," Check Pool UseCatalog");
144 ok(pr.AcceptAnyVolume == pr2.AcceptAnyVolume," Check Pool AcceptAnyVolume");
145 ok(pr.AutoPrune == pr2.AutoPrune, " Check Pool AutoPrune");
146 ok(pr.Recycle == pr2.Recycle, " Check Pool Recycle");
147 ok(pr.VolRetention == pr2.VolRetention, " Check Pool VolRetention");
148 ok(pr.VolUseDuration == pr2.VolUseDuration," Check Pool VolUseDuration");
149 ok(pr.MaxVolJobs == pr2.MaxVolJobs, " Check Pool MaxVolJobs");
150 ok(pr.MaxVolFiles == pr2.MaxVolFiles, " Check Pool MaxVolFiles");
151 ok(pr.MaxVolBytes == pr2.MaxVolBytes, " Check Pool MaxVolBytes");
152 ok(!strcmp(pr.PoolType, pr2.PoolType), " Check Pool PoolType");
153 ok(pr.LabelType == pr2.LabelType, " Check Pool LabelType");
154 ok(!strcmp(pr.LabelFormat, pr2.LabelFormat), " Check Pool LabelFormat");
155 ok(pr.RecyclePoolId == pr2.RecyclePoolId, " Check Pool RecyclePoolId");
156 ok(pr.ScratchPoolId == pr2.ScratchPoolId, " Check Pool ScratchPoolId");
157 ok(pr.ActionOnPurge == pr2.ActionOnPurge, " Check Pool ActionOnPurge");
160 static void cmp_client(CLIENT_DBR &cr, CLIENT_DBR &cr2)
162 ok(!strcmp(cr2.Name, cr.Name), " Check Client Name");
163 ok(!strcmp(cr2.Uname, cr.Uname), " Check Client Uname");
164 ok(cr.AutoPrune == cr2.AutoPrune, " Check Client Autoprune");
165 ok(cr.JobRetention == cr2.JobRetention, " Check Client JobRetention");
166 ok(cr.FileRetention == cr2.FileRetention," Check Client FileRetention");
169 #define aPATH "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
170 #define aFILE "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
172 int list_files(void *ctx, int nb_col, char **row)
174 uint32_t *k = (uint32_t*) ctx;
176 ok(!strcmp(row[0], aPATH aPATH aPATH aPATH "/"), "Check path");
177 ok(!strcmp(row[1], aFILE aFILE ".txt"), "Check filename");
178 ok(str_to_int64(row[2]) == 10, "Check FileIndex");
179 ok(str_to_int64(row[3]) == jcr->JobId, "Check JobId");
183 /* number of thread started */
185 int main (int argc, char *argv[])
188 char *path=NULL, *client=NULL;
191 bool full_test=false;
195 POOLMEM *buf = get_pool_memory(PM_FNAME);
196 POOLMEM *buf2 = get_pool_memory(PM_FNAME);
197 POOLMEM *buf3 = get_pool_memory(PM_FNAME);
199 setlocale(LC_ALL, "");
200 bindtextdomain("bacula", LOCALEDIR);
201 textdomain("bacula");
205 Pmsg0(0, "Starting cats_test tool" PLINE);
207 my_name_is(argc, argv, "");
208 init_msg(NULL, NULL);
212 while ((ch = getopt(argc, argv, "qh:c:l:d:n:P:Su:vFw:?p:f:T")) != -1) {
217 case 'd': /* debug level */
218 if (*optarg == 't') {
219 dbg_timestamp = true;
221 debug_level = atoi(optarg);
222 if (debug_level <= 0) {
228 limit = str_to_int64(optarg);
244 working_directory = optarg;
252 db_password = optarg;
285 Pmsg0(0, _("Wrong number of arguments: \n"));
293 * - With multiple thread in //
295 * - Test all sql_cmds.c
296 * - Test all sql.c (db_)
297 * - Test all sql_create.c
301 jcr = new_jcr(sizeof(JCR), NULL);
302 jcr->set_JobType(JT_CONSOLE);
303 jcr->set_JobLevel(L_NONE);
304 jcr->JobStatus = JS_Running;
305 bstrncpy(jcr->Job, "**dummy**", sizeof(jcr->Job));
306 jcr->JobId = pid; /* this is JobId on tape */
307 jcr->start_time = jcr->sched_time = time(NULL);
309 /* Test DB connexion */
310 Pmsg1(0, PLINE "Test DB connection \"%s\"" PLINE, db_name);
313 db = db_init(jcr /* JCR */,
314 NULL /* dbi driver */,
315 db_name, db_user, db_password, db_address, db_port + 100,
316 NULL /* db_socket */,
317 0 /* mult_db_connections */);
318 ok(db != NULL, "Test bad connection");
323 nok(db_open_database(jcr, db), "Open bad Database");
324 db_close_database(jcr, db);
327 db = db_init(jcr /* JCR */,
328 NULL /* dbi driver */,
329 db_name, db_user, db_password, db_address, db_port,
330 NULL /* db_socket */,
331 0 /* mult_db_connections */);
333 ok(db != NULL, "Test db connection");
338 if (!ok(db_open_database(jcr, db), "Open Database")) {
339 Pmsg1(000, _("Could not open database \"%s\".\n"), db_name);
340 Jmsg(jcr, M_FATAL, 0, _("Could not open, database \"%s\".\n"), db_name);
341 Jmsg(jcr, M_FATAL, 0, _("%s"), db_strerror(db));
342 Pmsg1(000, "%s", db_strerror(db));
343 db_close_database(jcr, db);
349 /* Check if the SQL library is thread-safe */
350 db_check_backend_thread_safe();
351 ok(check_tables_version(jcr, db), "Check table version");
352 ok(db_sql_query(db, "SELECT VersionId FROM Version",
353 db_int_handler, &j), "SELECT VersionId");
355 ok(UPDATE_DB(jcr, db, (char*)"UPDATE Version SET VersionId = 1"),
357 nok(check_tables_version(jcr, db), "Check table version");
358 Mmsg(buf, "UPDATE Version SET VersionId = %d", j);
359 ok(UPDATE_DB(jcr, db, buf), "Restore VersionId");
361 if (dbtype != SQL_TYPE_SQLITE3) {
362 ok(db_check_max_connections(jcr, db, 1), "Test min Max Connexion");
363 nok(db_check_max_connections(jcr, db, 10000), "Test max Max Connexion");
366 ok(db_open_batch_connexion(jcr, db), "Opening batch connection");
367 db_close_database(jcr, jcr->db_batch);
368 jcr->db_batch = NULL;
370 /* ---------------------------------------------------------------- */
372 uint32_t storageid=0;
373 ok(db_sql_query(db, "SELECT MIN(StorageId) FROM Storage",
374 db_int_handler, &storageid), "Get StorageId");
375 ok(storageid > 0, "Check StorageId");
377 Pmsg0(0, "Please, run REGRESS_DEBUG=1 tests/bacula-backup-test before this test");
381 /* ---------------------------------------------------------------- */
382 Pmsg0(0, PLINE "Doing Basic SQL tests" PLINE);
384 bsnprintf(temp, sizeof(temp), "t%lld", pid);
385 ok(db_sql_query(db, "SELECT 2", db_int_handler, &j), "Good SELECT query");
386 ok(db_sql_query(db, "SELECT 1 FROM Media WHERE VolumeName='missing'",
387 db_int_handler, &j), "Good empty SELECT query");
390 i64.value = 0; i64.count = 0;
391 ok(db_sql_query(db, "SELECT 1",db_int64_handler, &i64),"db_int64_handler");
392 ok(i64.value == 1, "Check db_int64_handler return");
395 ok(db_sql_query(db, "SELECT FileId FROM File ORDER By FileId LIMIT 10",
396 db_list_handler, &lctx), "db_list_ctx");
397 ok(lctx.count == 10, "Check db_list_ctx count ");
398 ok(!strcmp(lctx.list, "1,2,3,4,5,6,7,8,9,10"), "Check db_list_ctx list");
400 nok(db_sql_query(db, "blabla", db_int_handler, &j), "Bad query");
402 Mmsg(buf, "CREATE Table %s (a int)", temp);
403 ok(db_sql_query(db, buf, NULL, NULL), "CREATE query");
405 Mmsg(buf, "INSERT INTO %s (a) VALUES (1)", temp);
406 ok(INSERT_DB(jcr, db, buf), "INSERT query");
407 ok(INSERT_DB(jcr, db, buf), "INSERT query");
408 ok(sql_affected_rows(db) == 1, "Check sql_affected_rows");
410 Mmsg(buf, "INSERT INTO aaa%s (a) VALUES (1)", temp);
411 nok(INSERT_DB(jcr, db, buf), "Bad INSERT query");
412 ok(sql_affected_rows(db) == 0, "Check sql_affected_rows");
414 Mmsg(buf, "UPDATE %s SET a = 2", temp);
415 ok(UPDATE_DB(jcr, db, buf), "UPDATE query");
416 ok(sql_affected_rows(db) == 2, "Check sql_affected_rows");
418 Mmsg(buf, "UPDATE %s SET a = 2 WHERE a = 1", temp);
419 nok(UPDATE_DB(jcr, db, buf), "Empty UPDATE query");
421 Mmsg(buf, "UPDATE aaa%s SET a = 2", temp);
422 nok(UPDATE_DB(jcr, db, buf), "Bad UPDATE query");
424 Mmsg(buf, "DELETE FROM %s", temp);
425 ok(DELETE_DB(jcr, db, buf), "DELETE query");
426 nok(DELETE_DB(jcr, db, buf), "Empty DELETE query"); /* TODO bug ? */
428 Mmsg(buf, "DELETE FROM aaa%s", temp);
429 ok(DELETE_DB(jcr, db, buf), "Bad DELETE query"); /* TODO bug ? */
431 Mmsg(buf, "DROP TABLE %s", temp);
432 ok(QUERY_DB(jcr, db, buf), "DROP query");
433 nok(QUERY_DB(jcr, db, buf), "Empty DROP query");
435 /* ---------------------------------------------------------------- */
437 strcpy(buf, "This string should be 'escaped'");
438 db_escape_string(jcr, db, buf2, buf, strlen(buf));
439 ok((strlen(buf) + 2) == strlen(buf2),"Quoted string should be longer");
440 Mmsg(buf, "INSERT INTO Path (Path) VALUES ('%lld-%s')", pid, buf2);
441 ok(db_sql_query(db, buf, NULL, NULL), "Inserting quoted string");
443 /* ---------------------------------------------------------------- */
446 memset(&jr, 0, sizeof(jr));
447 memset(&jr2, 0, sizeof(jr2));
449 ok(db_get_job_record(jcr, db, &jr), "Get Job record for JobId=1");
450 ok(jr.JobFiles > 10, "Check number of files");
452 jr.JobId = (JobId_t)pid;
453 Mmsg(buf, "%s-%lld", jr.Job, pid);
455 ok(db_create_job_record(jcr, db, &jr), "Create Job record");
457 /* ---------------------------------------------------------------- */
461 memset(&ar, 0, sizeof(ar));
462 Mmsg(buf2, aPATH aPATH aPATH aPATH "/" aFILE aFILE ".txt");
464 Mmsg(buf3, "gD ImIZ IGk B Po Po A A A JY BNNvf5 BNKzS7 BNNuwC A A C");
467 ar.Stream = STREAM_UNIX_ATTRIBUTES;
468 ar.FileType = FT_REG;
469 jcr->JobId = ar.JobId = jr.JobId;
470 jcr->JobStatus = JS_Running;
471 ok(db_create_file_attributes_record(jcr, db, &ar), "Inserting Filename");
472 ok(db_write_batch_file_records(jcr), "Commit batch session");
473 Mmsg(buf, "SELECT FileIndex FROM File WHERE JobId=%lld",(int64_t)jcr->JobId);
474 ok(db_sql_query(db, buf, db_int_handler, &j), "Get Inserted record");
475 ok(j == ar.FileIndex, "Check FileIndex");
476 Mmsg(buf, "SELECT COUNT(1) FROM File WHERE JobId=%lld",(int64_t)jcr->JobId);
477 ok(db_sql_query(db, buf, db_int_handler, &j), "List records");
478 ok(j == 1, "Check batch session records");
480 Mmsg(buf, "%lld", (uint64_t)jcr->JobId);
481 ok(db_get_file_list(jcr, jcr->db_batch, buf, false, false, list_files, &j),
482 "List files with db_get_file_list()");
483 ok(j == 1, "Check db_get_file_list results");
484 /* ---------------------------------------------------------------- */
486 Pmsg0(0, PLINE "Doing Client tests" PLINE);
488 memset(&cr, 0, sizeof(cr));
489 memset(&cr2, 0, sizeof(cr2));
492 cr.FileRetention = 10;
493 cr.JobRetention = 15;
494 bsnprintf(cr.Name, sizeof(cr.Name), "client-%lld-fd", pid);
495 bsnprintf(cr.Uname, sizeof(cr.Uname), "uname-%lld", pid);
497 ok(db_create_client_record(jcr, db, &cr), "db_create_client_record()");
498 ok(cr.ClientId > 0, "Check ClientId");
500 cr2.ClientId = cr.ClientId; /* Save it */
503 Pmsg0(0, "Search client by ClientId\n");
504 ok(db_create_client_record(jcr, db, &cr),"Should get the client record");
505 ok(cr.ClientId == cr2.ClientId, "Check if ClientId is the same");
507 ok(db_get_client_record(jcr, db, &cr2), "Search client by ClientId");
510 Pmsg0(0, "Search client by Name\n");
511 memset(&cr2, 0, sizeof(cr2));
512 strcpy(cr2.Name, cr.Name);
513 ok(db_get_client_record(jcr, db, &cr2),"Search client by Name");
516 Pmsg0(0, "Search non existing client by Name\n");
517 memset(&cr2, 0, sizeof(cr2));
518 bsnprintf(cr2.Name, sizeof(cr2.Name), "hollow-client-%lld-fd", pid);
519 nok(db_get_client_record(jcr, db, &cr2), "Search non existing client");
520 ok(cr2.ClientId == 0, "Check ClientId after failed search");
523 strcpy(cr.Uname, "NewUname");
524 ok(db_update_client_record(jcr, db, &cr), "Update Client record");
525 memset(&cr2, 0, sizeof(cr2));
526 cr2.ClientId = cr.ClientId;
527 ok(db_get_client_record(jcr, db, &cr2),"Search client by ClientId");
532 ok(db_get_client_ids(jcr, db, &nb, &ret_ids), "Get Client Ids");
533 ok(nb > 0, "Should find at least 1 Id");
534 for (i = 0; i < nb; i++) {
535 if (ret_ids[i] == cr2.ClientId) {
539 ok(i < nb, "Check if ClientId was found");
541 /* ---------------------------------------------------------------- */
542 Pmsg0(0, PLINE "Doing Pool tests" PLINE);
544 memset(&pr, 0, sizeof(pr));
545 memset(&pr2, 0, sizeof(pr2));
547 bsnprintf(pr.Name, sizeof(pr.Name), "pool-%lld", pid);
550 pr.UseCatalog = true;
551 pr.AcceptAnyVolume = true;
554 pr.VolRetention = 1000;
555 pr.VolUseDuration = 1000;
557 pr.MaxVolFiles = 1000;
558 pr.MaxVolBytes = 1000000;
559 strcpy(pr.PoolType, "Backup");
561 pr.LabelFormat[0] = 0;
562 pr.RecyclePoolId = 0;
563 pr.ScratchPoolId = 0;
564 pr.ActionOnPurge = 1;
566 ok(db_create_pool_record(jcr, db, &pr), "db_create_pool_record()");
567 ok(pr.PoolId > 0, "Check PoolId");
569 pr2.PoolId = pr.PoolId;
572 Pmsg0(0, "Search pool by PoolId\n");
573 nok(db_create_pool_record(jcr, db, &pr),"Can't create pool twice");
574 ok(db_get_pool_record(jcr, db, &pr2), "Search pool by PoolId");
578 pr2.AutoPrune = false;
581 pr2.VolUseDuration++;
585 strcpy(pr2.PoolType, "Restore");
586 strcpy(pr2.LabelFormat, "VolFormat");
587 pr2.RecyclePoolId = 0;
588 pr2.ScratchPoolId = 0;
589 pr2.ActionOnPurge = 2;
591 ok(db_update_pool_record(jcr, db, &pr2), "Update Pool record");
592 memset(&pr, 0, sizeof(pr));
593 pr.PoolId = pr2.PoolId;
594 ok(db_get_pool_record(jcr, db, &pr), "Search pool by PoolId");
597 ok(db_delete_pool_record(jcr, db, &pr), "Delete Pool");
598 nok(db_delete_pool_record(jcr, db, &pr), "Delete non existing Pool");
599 nok(db_update_pool_record(jcr, db, &pr), "Update non existing Pool");
600 ok(db_create_pool_record(jcr, db, &pr), "Recreate Pool");
602 /* ---------------------------------------------------------------- */
603 Pmsg0(0, PLINE "Doing Media tests" PLINE);
606 memset(&mr, 0, sizeof(mr));
607 memset(&mr2, 0, sizeof(mr2));
609 bsnprintf(mr.VolumeName, sizeof(mr.VolumeName), "media-%lld", pid);
610 bsnprintf(mr.MediaType, sizeof(mr.MediaType), "type-%lld", pid);
612 /* from set_pool_dbr_defaults_in_media_dbr(&mr, &pr); */
613 mr.PoolId = pr.PoolId;
614 bstrncpy(mr.VolStatus, NT_("Append"), sizeof(mr.VolStatus));
615 mr.Recycle = pr.Recycle;
616 mr.VolRetention = pr.VolRetention;
617 mr.VolUseDuration = pr.VolUseDuration;
618 mr.ActionOnPurge = pr.ActionOnPurge;
619 mr.RecyclePoolId = pr.RecyclePoolId;
620 mr.MaxVolJobs = pr.MaxVolJobs;
621 mr.MaxVolFiles = pr.MaxVolFiles;
622 mr.MaxVolBytes = pr.MaxVolBytes;
623 mr.LabelType = pr.LabelType;
626 mr.VolCapacityBytes = 1000;
630 mr.VolReadTime = 10000;
631 mr.VolWriteTime = 99999;
635 mr.ScratchPoolId = 0;
636 mr.RecyclePoolId = 0;
638 ok(db_create_media_record(jcr, db, &mr), "Create Media");
639 nok(db_create_media_record(jcr, db, &mr), "Create Media twice");
641 /* ---------------------------------------------------------------- */
642 Pmsg0(0, PLINE "Doing Job tests" PLINE);
644 /* ---------------------------------------------------------------- */
645 Pmsg0(0, PLINE "Doing ... tests" PLINE);
647 db_close_database(jcr, db);
649 free_pool_memory(buf);
650 free_pool_memory(buf2);
651 free_pool_memory(buf3);