1 /*
2    Bacula(R) - The Network Backup Solution
3 
4    Copyright (C) 2000-2020 Kern Sibbald
5 
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8 
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13 
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16 
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20  *  Program to test CATS DB routines
21  *
22  *
23  */
24 #define _BDB_PRIV_INTERFACE_
25 
26 #include "bacula.h"
27 #include "cats/cats.h"
28 #include "cats/bvfs.h"
29 #include "findlib/find.h"
30 
31 /* Local variables */
32 static BDB *db;
33 static const char *file = "COPYRIGHT";
34 //static DBId_t fnid=0;
35 static const char *db_name = "bacula";
36 static const char *db_user = "bacula";
37 static const char *db_password = "";
38 static const char *db_host = NULL;
39 static const char *db_address = NULL;
40 static int db_port = 0;
41 static int64_t pid = 0;
42 static JCR *jcr=NULL;
43 
44 #define PLINE "\n============================================================\n"
usage()45 static void usage()
46 {
47    fprintf(stderr, _(
48 PROG_COPYRIGHT
49 "\n%sVersion: %s (%s)\n"
50 "       -d <nn>           set debug level to <nn>\n"
51 "       -dt               print timestamp in debug output\n"
52 "       -n <name>         specify the database name (default bacula)\n"
53 "       -u <user>         specify database user name (default bacula)\n"
54 "       -P <password      specify database password (default none)\n"
55 "       -h <host>         specify database host (default NULL)\n"
56 "       -w <working>      specify working directory\n"
57 "       -p <path>         specify path\n"
58 "       -f <file>         specify file\n"
59 "       -l <limit>        maximum tuple to fetch\n"
60 "       -q                print only errors\n"
61 "       -v                verbose\n"
62 "       -?                print this message\n\n"), 2011, "", VERSION, BDATE);
63    exit(1);
64 }
65 
66 bool print_ok=true;
67 int _err=0;
68 int _wrn=0;
69 int _nb=0;
70 
_warn(const char * file,int l,const char * op,int value,const char * label)71 bool _warn(const char *file, int l, const char *op, int value, const char *label)
72 {
73    bool ret=false;
74    _nb++;
75    if (!value) {
76       _wrn++;
77       printf("WRN %.30s %s:%i on %s\n", label, file, l, op);
78    } else {
79       ret=true;
80       printf("OK  %.30s\n", label);
81    }
82    return ret;
83 }
84 
85 #define warn(x, label) _warn(__FILE__, __LINE__, #x, (x), label)
86 
_ok(const char * file,int l,const char * op,int value,const char * label)87 bool _ok(const char *file, int l, const char *op, int value, const char *label)
88 {
89    bool ret=false;
90    _nb++;
91    if (!value) {
92       _err++;
93       printf("ERR %.30s %s:%i on %s\n", label, file, l, op);
94    } else {
95       ret=true;
96       if (print_ok) {
97          printf("OK  %.30s\n", label);
98       }
99    }
100    return ret;
101 }
102 
103 #define ok(x, label) _ok(__FILE__, __LINE__, #x, (x), label)
104 
_nok(const char * file,int l,const char * op,int value,const char * label)105 bool _nok(const char *file, int l, const char *op, int value, const char *label)
106 {
107    bool ret=false;
108    _nb++;
109    if (value) {
110       _err++;
111       printf("ERR %.30s %s:%i on !%s\n", label, file, l, op);
112    } else {
113       ret = true;
114       if (print_ok) {
115          printf("OK  %.30s\n", label);
116       }
117    }
118    return ret;
119 }
120 
121 #define nok(x, label) _nok(__FILE__, __LINE__, #x, (x), label)
122 
report()123 int report()
124 {
125    printf("Result %i/%i OK\n", _nb - _err, _nb);
126    return _err>0;
127 }
128 
cmp_pool(POOL_DBR & pr,POOL_DBR & pr2)129 static void cmp_pool(POOL_DBR &pr, POOL_DBR &pr2)
130 {
131    ok(pr.MaxVols == pr2.MaxVols,                "  Check Pool MaxVols");
132    ok(pr.UseOnce == pr2.UseOnce,                "  Check Pool UseOnce");
133    ok(pr.UseCatalog == pr2.UseCatalog,          "  Check Pool UseCatalog");
134    ok(pr.AcceptAnyVolume == pr2.AcceptAnyVolume,"  Check Pool AcceptAnyVolume");
135    ok(pr.AutoPrune == pr2.AutoPrune,            "  Check Pool AutoPrune");
136    ok(pr.Recycle == pr2.Recycle,                "  Check Pool Recycle");
137    ok(pr.VolRetention == pr2.VolRetention ,     "  Check Pool VolRetention");
138    ok(pr.VolUseDuration == pr2.VolUseDuration,  "  Check Pool VolUseDuration");
139    ok(pr.MaxVolJobs == pr2.MaxVolJobs,          "  Check Pool MaxVolJobs");
140    ok(pr.MaxVolFiles == pr2.MaxVolFiles,        "  Check Pool MaxVolFiles");
141    ok(pr.MaxVolBytes == pr2.MaxVolBytes,        "  Check Pool MaxVolBytes");
142    ok(!strcmp(pr.PoolType, pr2.PoolType),       "  Check Pool PoolType");
143    ok(pr.LabelType == pr2.LabelType,            "  Check Pool LabelType");
144    ok(!strcmp(pr.LabelFormat, pr2.LabelFormat), "  Check Pool LabelFormat");
145    ok(pr.RecyclePoolId == pr2.RecyclePoolId,    "  Check Pool RecyclePoolId");
146    ok(pr.ScratchPoolId == pr2.ScratchPoolId,    "  Check Pool ScratchPoolId");
147    ok(pr.ActionOnPurge == pr2.ActionOnPurge,    "  Check Pool ActionOnPurge");
148 }
149 
cmp_client(CLIENT_DBR & cr,CLIENT_DBR & cr2)150 static void cmp_client(CLIENT_DBR &cr, CLIENT_DBR &cr2)
151 {
152    ok(!strcmp(cr2.Name, cr.Name),           "  Check Client Name");
153    ok(!strcmp(cr2.Uname, cr.Uname),         "  Check Client Uname");
154    ok(cr.AutoPrune == cr2.AutoPrune,        "  Check Client Autoprune");
155    ok(cr.JobRetention == cr2.JobRetention,  "  Check Client JobRetention");
156    ok(cr.FileRetention == cr2.FileRetention,"  Check Client FileRetention");
157 }
158 
cmp_job(JOB_DBR & jr,JOB_DBR & jr2)159 static void cmp_job(JOB_DBR &jr, JOB_DBR &jr2)
160 {
161    ok(jr.VolSessionId == jr2.VolSessionId,     "  Check VolSessionId");
162    ok(jr.VolSessionTime == jr2.VolSessionTime, "  Check VolSessionTime");
163    ok(jr.PoolId == jr2.PoolId,                 "  Check PoolId");
164    ok(jr.StartTime == jr2.StartTime,           "  Check StartTime");
165    ok(jr.EndTime == jr2.EndTime,               "  Check EndTime");
166    ok(jr.JobFiles == jr2.JobFiles,             "  Check JobFiles");
167    ok(jr.JobBytes == jr2.JobBytes,             "  Check JobBytes");
168    ok(jr.JobTDate == jr2.JobTDate,             "  Check JobTDate");
169    ok(!strcmp(jr.Job, jr2.Job),                "  Check Job");
170    ok(jr.JobStatus == jr2.JobStatus,           "  Check JobStatus");
171    ok(jr.JobType == jr2.JobType,               "  Check Type");
172    ok(jr.JobLevel == jr2.JobLevel,             "  Check Level");
173    ok(jr.ClientId == jr2.ClientId,             "  Check ClientId");
174    ok(!strcmp(jr.Name, jr2.Name),              "  Check Name");
175    ok(jr.PriorJobId == jr2.PriorJobId,         "  Check PriorJobId");
176    ok(jr.RealEndTime == jr2.RealEndTime,       "  Check RealEndTime");
177    ok(jr.JobId == jr2.JobId,                   "  Check JobId");
178    ok(jr.FileSetId == jr2.FileSetId,           "  Check FileSetId");
179    ok(jr.SchedTime == jr2.SchedTime,           "  Check SchedTime");
180    ok(jr.RealEndTime == jr2.RealEndTime,       "  Check RealEndTime");
181    ok(jr.ReadBytes == jr2.ReadBytes,           "  Check ReadBytes");
182    ok(jr.HasBase == jr2.HasBase,               "  Check HasBase");
183    ok(jr.PurgedFiles == jr2.PurgedFiles,       "  Check PurgedFiles");
184 }
185 
186 
187 #define aPATH "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
188 #define aFILE "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
189 
list_files(void * ctx,int nb_col,char ** row)190 static int list_files(void *ctx, int nb_col, char **row)
191 {
192    uint32_t *k = (uint32_t*) ctx;
193    (*k)++;
194    ok(nb_col > 4, "Check result columns");
195    ok(!strcmp(row[0], aPATH aPATH aPATH aPATH "/"), "Check path");
196    ok(!strcmp(row[1], aFILE aFILE ".txt"), "Check filename");
197    ok(str_to_int64(row[2]) == 10, "Check FileIndex");
198    ok(str_to_int64(row[3]) == jcr->JobId, "Check JobId");
199    return 1;
200 }
201 
count_col(void * ctx,int nb_col,char ** row)202 static int count_col(void *ctx, int nb_col, char **row)
203 {
204    *((int32_t*) ctx) = nb_col;
205    return 1;
206 }
207 
208 /* number of thread started */
209 
main(int argc,char * argv[])210 int main (int argc, char *argv[])
211 {
212    int ch;
213    char *path=NULL, *client=NULL;
214    uint64_t limit=0;
215    bool clean=false;
216    bool full_test=false;
217    int dbtype;
218    uint32_t j;
219    char temp[20];
220    POOLMEM *buf = get_pool_memory(PM_FNAME);
221    POOLMEM *buf2 = get_pool_memory(PM_FNAME);
222    POOLMEM *buf3 = get_pool_memory(PM_FNAME);
223 
224    setlocale(LC_ALL, "");
225    bindtextdomain("bacula", LOCALEDIR);
226    textdomain("bacula");
227    init_stack_dump();
228    pid = getpid();
229 
230    Pmsg0(0, "Starting cats_test tool" PLINE);
231 
232    my_name_is(argc, argv, "");
233    init_msg(NULL, NULL);
234 
235    OSDependentInit();
236 
237    while ((ch = getopt(argc, argv, "qh:c:l:d:n:P:Su:vFw:?p:f:T")) != -1) {
238       switch (ch) {
239       case 'q':
240          print_ok = false;
241          break;
242       case 'd':                    /* debug level */
243          if (*optarg == 't') {
244             dbg_timestamp = true;
245          } else {
246             debug_level = atoi(optarg);
247             if (debug_level <= 0) {
248                debug_level = 1;
249             }
250          }
251          break;
252       case 'l':
253          limit = str_to_int64(optarg);
254          break;
255 
256       case 'c':
257          client = optarg;
258          break;
259 
260       case 'h':
261          db_host = optarg;
262          break;
263 
264       case 'n':
265          db_name = optarg;
266          break;
267 
268       case 'w':
269          working_directory = optarg;
270          break;
271 
272       case 'u':
273          db_user = optarg;
274          break;
275 
276       case 'P':
277          db_password = optarg;
278          break;
279 
280       case 'v':
281          verbose++;
282          break;
283 
284       case 'p':
285          path = optarg;
286          break;
287 
288       case 'F':
289          full_test = true;
290          break;
291 
292       case 'f':
293          file = optarg;
294          break;
295 
296       case 'T':
297          clean = true;
298          break;
299 
300       case '?':
301       default:
302          usage();
303 
304       }
305    }
306    argc -= optind;
307    argv += optind;
308 
309    if (argc != 0) {
310       Pmsg0(0, _("Wrong number of arguments: \n"));
311       usage();
312    }
313 
314    /* TODO:
315     *  - Open DB
316     *    - With errors
317     *    - With good info
318     *    - With multiple thread in //
319     *  - Test cats.h
320     *  - Test all sql_cmds.c
321     *  - Test all sql.c (db_)
322     *  - Test all sql_create.c
323     *  - Test db_handler
324     */
325 
326    jcr = new_jcr(sizeof(JCR), NULL);
327    jcr->setJobType(JT_CONSOLE);
328    jcr->setJobLevel(L_NONE);
329    jcr->JobStatus = JS_Running;
330    bstrncpy(jcr->Job, "**dummy**", sizeof(jcr->Job));
331    jcr->JobId = pid;      /* this is JobId on tape */
332    jcr->start_time = jcr->sched_time = time(NULL);
333 
334    /* Test DB connexion */
335    Pmsg1(0, PLINE "Test DB connection \"%s\"" PLINE, db_name);
336 
337    if (full_test) {
338       db = db_init_database(jcr /* JCR */,
339                    NULL /* dbi driver */,
340                    db_name, db_user, db_password, db_address, db_port + 100,
341                    NULL /* db_socket */,
342                    db_ssl_mode, db_ssl_key, db_ssl_cert,
343                    db_ssl_ca, db_ssl_capath, db_ssl_cipher,
344                    0 /* mult_db_connections */, false);
345       ok(db != NULL, "Test bad connection");
346       if (!db) {
347          report();
348          exit (1);
349       }
350       nok(db_open_database(jcr, db), "Open bad Database");
351       db_close_database(jcr, db);
352    }
353 
354    db = db_init_database(jcr /* JCR */,
355                 NULL /* dbi driver */,
356                 db_name, db_user, db_password, db_address, db_port,
357                 NULL /* db_socket */,
358                 db_ssl_mode, db_ssl_key, db_ssl_cert,
359                 db_ssl_ca, db_ssl_capath, db_ssl_cipher,
360                 false /* mult_db_connections */, false);
361 
362    ok(db != NULL, "Test db connection");
363    if (!db) {
364       report();
365       exit (1);
366    }
367    if (!ok(db_open_database(jcr, db), "Open Database")) {
368       Pmsg1(000, _("Could not open database \"%s\".\n"), db_name);
369       Jmsg(jcr, M_FATAL, 0, _("Could not open, database \"%s\".\n"), db_name);
370       Jmsg(jcr, M_FATAL, 0, _("%s"), db_strerror(db));
371       Pmsg1(000, "%s", db_strerror(db));
372       db_close_database(jcr, db);
373       report();
374       exit (1);
375    }
376    dbtype = db_get_type_index(db);
377 
378 
379    /* Check if the SQL library is thread-safe */
380    ok(check_tables_version(jcr, db), "Check table version");
381    ok(db_sql_query(db, "SELECT VersionId FROM Version",
382                    db_int_handler, &j), "SELECT VersionId");
383 
384    ok(UPDATE_DB(jcr, db, (char*)"UPDATE Version SET VersionId = 1"),
385       "Update VersionId");
386    nok(check_tables_version(jcr, db), "Check table version");
387    Mmsg(buf, "UPDATE Version SET VersionId = %d", j);
388    ok(UPDATE_DB(jcr, db, buf), "Restore VersionId");
389 
390    if (dbtype != SQL_TYPE_SQLITE3) {
391       ok(db_check_max_connections(jcr, db, 1), "Test min Max Connexion");
392       nok(db_check_max_connections(jcr, db, 10000), "Test max Max Connexion");
393    }
394 
395    ok(db_open_batch_connexion(jcr, db), "Opening batch connection");
396    db_close_database(jcr, jcr->db_batch);
397    jcr->db_batch = NULL;
398 
399    /* ---------------------------------------------------------------- */
400 
401    uint32_t storageid=0;
402    ok(db_sql_query(db, "SELECT MIN(StorageId) FROM Storage",
403                    db_int_handler, &storageid), "Get StorageId");
404    ok(storageid > 0, "Check StorageId");
405    if (!storageid) {
406       Pmsg0(0, "Please, run REGRESS_DEBUG=1 tests/bacula-backup-test before this test");
407       exit (1);
408    }
409 
410    /* ---------------------------------------------------------------- */
411    Pmsg0(0, PLINE "Doing Basic SQL tests" PLINE);
412    ok(db_sql_query(db, "SELECT 1,2,3,4,5", count_col, &j), "Count 5 rows");
413    ok(j == 5, "Check number of columns");
414    ok(db_sql_query(db, "SELECT 1,2,3,4,5,'a','b','c','d','e'",
415                    count_col, &j), "Count 10 rows");
416    ok(j == 10, "Check number of columns");
417 
418    bsnprintf(temp, sizeof(temp), "t%lld", pid);
419    ok(db_sql_query(db, "SELECT 2", db_int_handler, &j), "Good SELECT query");
420    ok(db_sql_query(db, "SELECT 1 FROM Media WHERE VolumeName='missing'",
421                    db_int_handler, &j), "Good empty SELECT query");
422 
423    db_int64_ctx i64;
424    i64.value = 0; i64.count = 0;
425    ok(db_sql_query(db, "SELECT 1",db_int64_handler, &i64),"db_int64_handler");
426    ok(i64.value == 1, "Check db_int64_handler return");
427 
428    db_list_ctx lctx;
429    ok(db_sql_query(db, "SELECT FileId FROM File ORDER By FileId LIMIT 10",
430                    db_list_handler, &lctx), "db_list_ctx");
431    ok(lctx.count == 10, "Check db_list_ctx count ");
432    ok(!strcmp(lctx.list, "1,2,3,4,5,6,7,8,9,10"), "Check db_list_ctx list");
433 
434    nok(db_sql_query(db, "blabla", db_int_handler, &j), "Bad query");
435 
436    Mmsg(buf, "CREATE Table %s (a int)", temp);
437    ok(db_sql_query(db, buf, NULL, NULL), "CREATE query");
438 
439    Mmsg(buf, "INSERT INTO %s (a) VALUES (1)", temp);
440    ok(INSERT_DB(jcr, db, buf), "INSERT query");
441    ok(INSERT_DB(jcr, db, buf), "INSERT query");
442    ok(sql_affected_rows(db) == 1, "Check sql_affected_rows");
443 
444    Mmsg(buf, "INSERT INTO aaa%s (a) VALUES (1)", temp);
445    nok(INSERT_DB(jcr, db, buf), "Bad INSERT query");
446    ok(sql_affected_rows(db) == 0, "Check sql_affected_rows");
447 
448    Mmsg(buf, "UPDATE %s SET a = 2", temp);
449    ok(UPDATE_DB(jcr, db, buf), "UPDATE query");
450    ok(sql_affected_rows(db) == 2, "Check sql_affected_rows");
451 
452    Mmsg(buf, "UPDATE %s SET a = 2 WHERE a = 1", temp);
453    nok(UPDATE_DB(jcr, db, buf), "Empty UPDATE query");
454 
455    Mmsg(buf, "UPDATE aaa%s SET a = 2", temp);
456    nok(UPDATE_DB(jcr, db, buf), "Bad UPDATE query");
457 
458    Mmsg(buf, "DELETE FROM %s", temp);
459    ok(DELETE_DB(jcr, db, buf), "DELETE query");
460    nok(DELETE_DB(jcr, db, buf), "Empty DELETE query"); /* TODO bug ? */
461 
462    Mmsg(buf, "DELETE FROM aaa%s", temp);
463    ok(DELETE_DB(jcr, db, buf), "Bad DELETE query"); /* TODO bug ? */
464 
465    Mmsg(buf, "DROP TABLE %s", temp);
466    ok(QUERY_DB(jcr, db, buf), "DROP query");
467    nok(QUERY_DB(jcr, db, buf), "Empty DROP query");
468 
469    /* ---------------------------------------------------------------- */
470 
471    strcpy(buf, "This string should be 'escaped'");
472    db_escape_string(jcr, db, buf2, buf, strlen(buf));
473    ok((strlen(buf) + 2) == strlen(buf2),"Quoted string should be longer");
474    Mmsg(buf, "INSERT INTO Path (Path) VALUES ('%lld-%s')", pid, buf2);
475    ok(db_sql_query(db, buf, NULL, NULL), "Inserting quoted string");
476 
477    /* ---------------------------------------------------------------- */
478    Pmsg0(0, PLINE "Doing Job tests" PLINE);
479 
480    JOB_DBR jr, jr2;
481    memset(&jr, 0, sizeof(jr));
482    memset(&jr2, 0, sizeof(jr2));
483    jr.JobId = 1;
484    ok(db_get_job_record(jcr, db, &jr), "Get Job record for JobId=1");
485    ok(jr.JobFiles > 10, "Check number of files");
486 
487    jr.JobId = (JobId_t)pid;
488    Mmsg(buf, "%s-%lld", jr.Job, pid);
489    strcpy(jr.Job, buf);
490    ok(db_create_job_record(jcr, db, &jr), "Create Job record");
491    ok(db_update_job_start_record(jcr, db, &jr), "Update Start Record");
492    ok(db_update_job_end_record(jcr, db, &jr), "Update End Record");
493    jr2.JobId = jr.JobId;
494    ok(db_get_job_record(jcr, db, &jr2), "Get Job record by JobId");
495    cmp_job(jr, jr2);
496 
497    memset(&jr2, 0, sizeof(jr2));
498    strcpy(jr2.Job, jr.Job);
499    ok(db_get_job_record(jcr, db, &jr2), "Get Job record by Job name");
500    cmp_job(jr, jr2);
501 
502    memset(&jr2, 0, sizeof(jr2));
503    jr2.JobId = 99999;
504    nok(db_get_job_record(jcr, db, &jr2), "Get non existing Job record (JobId)");
505 
506    memset(&jr2, 0, sizeof(jr2));
507    strcpy(jr2.Job, "test");
508    nok(db_get_job_record(jcr, db, &jr2), "Get non existing Job record (Job)");
509 
510    /* ---------------------------------------------------------------- */
511 
512    ATTR_DBR ar;
513    memset(&ar, 0, sizeof(ar));
514    Mmsg(buf2, aPATH aPATH aPATH aPATH "/" aFILE aFILE ".txt");
515    ar.fname = buf2;
516    Mmsg(buf3, "gD ImIZ IGk B Po Po A A A JY BNNvf5 BNKzS7 BNNuwC A A C");
517    ar.attr = buf3;
518    ar.FileIndex = 10;
519    ar.Stream = STREAM_UNIX_ATTRIBUTES;
520    ar.FileType = FT_REG;
521    jcr->JobId = ar.JobId = jr.JobId;
522    jcr->JobStatus = JS_Running;
523    ok(db_create_attributes_record(jcr, db, &ar), "Inserting Filename");
524    ok(db_write_batch_file_records(jcr), "Commit batch session");
525    Mmsg(buf, "SELECT FileIndex FROM File WHERE JobId=%lld",(int64_t)jcr->JobId);
526    ok(db_sql_query(db, buf, db_int_handler, &j), "Get Inserted record");
527    ok(j == ar.FileIndex, "Check FileIndex");
528    Mmsg(buf, "SELECT COUNT(1) FROM File WHERE JobId=%lld",(int64_t)jcr->JobId);
529    ok(db_sql_query(db, buf, db_int_handler, &j), "List records");
530    ok(j == 1, "Check batch session records");
531    j = 0;
532    Mmsg(buf, "%lld", (uint64_t)jcr->JobId);
533    ok(db_get_file_list(jcr, jcr->db_batch, buf, DBL_NONE, list_files, &j),
534       "List files with db_get_file_list()");
535    ok(j == 1, "Check db_get_file_list results");
536    /* ---------------------------------------------------------------- */
537 
538    Pmsg0(0, PLINE "Doing Client tests" PLINE);
539    CLIENT_DBR cr, cr2;
540    memset(&cr, 0, sizeof(cr));
541    memset(&cr2, 0, sizeof(cr2));
542 
543    cr.AutoPrune = 1;
544    cr.FileRetention = 10;
545    cr.JobRetention = 15;
546    bsnprintf(cr.Name, sizeof(cr.Name), "client-%lld-fd", pid);
547    bsnprintf(cr.Uname, sizeof(cr.Uname), "uname-%lld", pid);
548 
549    ok(db_create_client_record(jcr, db, &cr), "db_create_client_record()");
550    ok(cr.ClientId > 0, "Check ClientId");
551 
552    cr2.ClientId = cr.ClientId; /* Save it */
553    cr.ClientId = 0;
554 
555    Pmsg0(0, "Search client by ClientId\n");
556    ok(db_create_client_record(jcr, db, &cr),"Should get the client record");
557    ok(cr.ClientId == cr2.ClientId,           "Check if ClientId is the same");
558 
559    ok(db_get_client_record(jcr, db, &cr2), "Search client by ClientId");
560    cmp_client(cr, cr2);
561 
562    Pmsg0(0, "Search client by Name\n");
563    memset(&cr2, 0, sizeof(cr2));
564    strcpy(cr2.Name, cr.Name);
565    ok(db_get_client_record(jcr, db, &cr2),"Search client by Name");
566    cmp_client(cr, cr2);
567 
568    Pmsg0(0, "Search non existing client by Name\n");
569    memset(&cr2, 0, sizeof(cr2));
570    bsnprintf(cr2.Name, sizeof(cr2.Name), "hollow-client-%lld-fd", pid);
571    nok(db_get_client_record(jcr, db, &cr2), "Search non existing client");
572    ok(cr2.ClientId == 0, "Check ClientId after failed search");
573 
574    cr.AutoPrune = 0;
575    strcpy(cr.Uname, "NewUname");
576    ok(db_update_client_record(jcr, db, &cr), "Update Client record");
577    memset(&cr2, 0, sizeof(cr2));
578    cr2.ClientId = cr.ClientId;
579    ok(db_get_client_record(jcr, db, &cr2),"Search client by ClientId");
580    cmp_client(cr, cr2);
581 
582    int nb, i;
583    uint32_t *ret_ids;
584    ok(db_get_client_ids(jcr, db, &nb, &ret_ids), "Get Client Ids");
585    ok(nb > 0, "Should find at least 1 Id");
586    for (i = 0; i < nb; i++) {
587       if (ret_ids[i] == cr2.ClientId) {
588          break;
589       }
590    }
591    ok(i < nb, "Check if ClientId was found");
592 
593    /* ---------------------------------------------------------------- */
594    Pmsg0(0, PLINE "Doing Pool tests" PLINE);
595    POOL_DBR pr, pr2;
596    memset(&pr, 0, sizeof(pr));
597    memset(&pr2, 0, sizeof(pr2));
598 
599    bsnprintf(pr.Name, sizeof(pr.Name), "pool-%lld", pid);
600    pr.MaxVols = 10;
601    pr.UseOnce = 0;
602    pr.UseCatalog = true;
603    pr.AcceptAnyVolume = true;
604    pr.AutoPrune = true;
605    pr.Recycle = true;
606    pr.VolRetention = 1000;
607    pr.VolUseDuration = 1000;
608    pr.MaxVolJobs = 100;
609    pr.MaxVolFiles = 1000;
610    pr.MaxVolBytes = 1000000;
611    strcpy(pr.PoolType, "Backup");
612    pr.LabelType = 0;
613    pr.LabelFormat[0] = 0;
614    pr.RecyclePoolId = 0;
615    pr.ScratchPoolId = 0;
616    pr.ActionOnPurge = 1;
617 
618    ok(db_create_pool_record(jcr, db, &pr), "db_create_pool_record()");
619    ok(pr.PoolId > 0, "Check PoolId");
620 
621    pr2.PoolId = pr.PoolId;
622    pr.PoolId = 0;
623 
624    Pmsg0(0, "Search pool by PoolId\n");
625    nok(db_create_pool_record(jcr, db, &pr),"Can't create pool twice");
626    ok(db_get_pool_numvols(jcr, db, &pr2), "Search pool by PoolId");
627    cmp_pool(pr, pr2);
628 
629    pr2.MaxVols++;
630    pr2.AutoPrune = false;
631    pr2.Recycle = false;
632    pr2.VolRetention++;
633    pr2.VolUseDuration++;
634    pr2.MaxVolJobs++;
635    pr2.MaxVolFiles++;
636    pr2.MaxVolBytes++;
637    strcpy(pr2.PoolType, "Restore");
638    strcpy(pr2.LabelFormat, "VolFormat");
639    pr2.RecyclePoolId = 0;
640    pr2.ScratchPoolId = 0;
641    pr2.ActionOnPurge = 2;
642 
643    ok(db_update_pool_record(jcr, db, &pr2), "Update Pool record");
644    memset(&pr, 0, sizeof(pr));
645    pr.PoolId = pr2.PoolId;
646    ok(db_get_pool_numvols(jcr, db, &pr), "Search pool by PoolId");
647    cmp_pool(pr, pr2);
648 
649    ok(db_delete_pool_record(jcr, db, &pr), "Delete Pool");
650    nok(db_delete_pool_record(jcr, db, &pr), "Delete non existing Pool");
651    nok(db_update_pool_record(jcr, db, &pr), "Update non existing Pool");
652    ok(db_create_pool_record(jcr, db, &pr), "Recreate Pool");
653 
654    /* ---------------------------------------------------------------- */
655    Pmsg0(0, PLINE "Doing Media tests" PLINE);
656 
657    MEDIA_DBR mr, mr2;
658    memset(&mr, 0, sizeof(mr));
659    memset(&mr2, 0, sizeof(mr2));
660 
661    bsnprintf(mr.VolumeName, sizeof(mr.VolumeName), "media-%lld", pid);
662    bsnprintf(mr.MediaType, sizeof(mr.MediaType), "type-%lld", pid);
663 
664    /* from set_pool_dbr_defaults_in_media_dbr(&mr, &pr);  */
665    mr.PoolId = pr.PoolId;
666    bstrncpy(mr.VolStatus, NT_("Append"), sizeof(mr.VolStatus));
667    mr.Recycle = pr.Recycle;
668    mr.VolRetention = pr.VolRetention;
669    mr.VolUseDuration = pr.VolUseDuration;
670    mr.ActionOnPurge = pr.ActionOnPurge;
671    mr.RecyclePoolId = pr.RecyclePoolId;
672    mr.MaxVolJobs = pr.MaxVolJobs;
673    mr.MaxVolFiles = pr.MaxVolFiles;
674    mr.MaxVolBytes = pr.MaxVolBytes;
675    mr.LabelType = pr.LabelType;
676    mr.Enabled = 1;
677 
678    mr.VolCapacityBytes = 1000;
679    mr.Slot = 1;
680    mr.VolBytes = 1000;
681    mr.InChanger = 1;
682    mr.VolReadTime = 10000;
683    mr.VolWriteTime = 99999;
684    mr.StorageId = 0;
685    mr.DeviceId = 0;
686    mr.LocationId = 0;
687    mr.ScratchPoolId = 0;
688    mr.RecyclePoolId = 0;
689 
690    ok(db_create_media_record(jcr, db, &mr), "Create Media");
691    nok(db_create_media_record(jcr, db, &mr), "Create Media twice");
692 
693    /* ---------------------------------------------------------------- */
694    Pmsg0(0, PLINE "Doing ... tests" PLINE);
695 
696    db_close_database(jcr, db);
697    report();
698    free_pool_memory(buf);
699    free_pool_memory(buf2);
700    free_pool_memory(buf3);
701    return 0;
702 }
703