]> git.ipfire.org Git - thirdparty/bacula.git/commitdiff
Update unittests for lockmgr.c and fix memory leak.
authorRadosław Korzeniewski <radekk@inteos.pl>
Mon, 27 Aug 2018 15:17:59 +0000 (17:17 +0200)
committerRadosław Korzeniewski <radekk@inteos.pl>
Mon, 27 Aug 2018 15:17:59 +0000 (17:17 +0200)
.gitignore
bacula/src/lib/Makefile.in
bacula/src/lib/lockmgr.c
bacula/src/lib/unittests.c
bacula/src/lib/unittests.h
regress/tests/lockmgr-unittests [new file with mode: 0755]

index 0deaae06d96f726bd08a16ccb45a68851a6069ec..480e26a2afafd2ea5c164da2a4998cd7cc5f2222 100644 (file)
@@ -325,3 +325,4 @@ bacula/src/lib/fnmatch_test
 bacula/src/lib/sha1_test
 bacula/src/lib/htable_test
 bacula/src/lib/ini_test
+bacula/src/lib/lockmgr_test
index c62f335100d4fe99a7cfafad89d79bead8821b4c..83d91ec4099a6d4c7ad4268c2e746c574077af16 100644 (file)
@@ -132,10 +132,10 @@ output_test: Makefile output.c unittests.o
        $(RMF) output.o
        $(CXX) $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) output.c
 
-lockmgr_test: Makefile lockmgr.c
+lockmgr_test: Makefile libbac.la lockmgr.c unittests.o
        $(RMF) lockmgr.o
-       $(CXX) -D _TEST_IT $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE)  $(CFLAGS) lockmgr.c
-       $(LIBTOOL_LINK) $(CXX) $(LDFLAGS) -L. -o $@ lockmgr.o $(DLIB) -lbac -lm $(LIBS) $(OPENSSL_LIBS)
+       $(CXX) -DTEST_PROGRAM $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE)  $(CFLAGS) lockmgr.c
+       $(LIBTOOL_LINK) $(CXX) $(LDFLAGS) -L. -o $@ lockmgr.o unittests.o $(DLIB) -lbac -lm $(LIBS) $(OPENSSL_LIBS)
        $(RMF) lockmgr.o
        $(CXX) $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) lockmgr.c
 
index d53aec863ecc61fb3b676d7185eb2726f7b145c0..53f466af825f98455d77c7e15350aafc5a2a815d 100644 (file)
@@ -11,7 +11,7 @@
    Public License, v3.0 ("AGPLv3") and some additional permissions and
    terms pursuant to its AGPLv3 Section 7.
 
-   This notice must be preserved when any source code is 
+   This notice must be preserved when any source code is
    conveyed and/or propagated.
 
    Bacula(R) is a registered trademark of Kern Sibbald.
    Pmsg4(000, _("ASSERT failed at %s:%i: %s (%s)\n"), f, l, #x, m);        \
    jcr[0] = 0; }
 
+/* for lockmgr unit tests we have to clean up developer flags and asserts which breaks our tests */
+#ifdef TEST_PROGRAM
+#ifdef DEVELOPER
+#undef DEVELOPER
+#endif
+#ifdef ASSERTD
+#undef ASSERTD
+#define ASSERTD(x, y)
+#endif
+#endif
+
 /*
   Inspired from
   http://www.cs.berkeley.edu/~kamil/teaching/sp03/041403.pdf
@@ -77,8 +88,8 @@
   rwlock object or the smartalloc lib. To disable LMGR, just add
   LOCKMGR_COMPLIANT before the inclusion of "bacula.h"
 
-  cd build/src/tools
-  g++ -g -c lockmgr.c -I.. -I../lib -DUSE_LOCKMGR -D_TEST_IT
+  cd build/src/lib
+  g++ -g -c lockmgr.c -I.. -I../lib -DUSE_LOCKMGR -DTEST_PROGRAM
   g++ -o lockmgr lockmgr.o -lbac -L../lib/.libs -lssl -lpthread
 
 */
@@ -276,7 +287,7 @@ static int32_t global_event_id=0;
 static int global_int_thread_id=0; /* Keep an integer for each thread */
 
 /* Keep this number of event per thread */
-#ifdef _TEST_IT
+#ifdef TEST_PROGRAM
 # define LMGR_THREAD_EVENT_MAX  15
 #else
 # define LMGR_THREAD_EVENT_MAX  1024
@@ -319,10 +330,12 @@ public:
                   const char *from, int32_t line)
    {
       char *p;
+      int32_t oldflags;
       int   i = lmgr_thread_event_get_pos(event_id);
 
-      events[i].flags = LMGR_EVENT_INVALID;
+      oldflags = events[i].flags;
       p = events[i].comment;
+      events[i].flags = LMGR_EVENT_INVALID;
       events[i].comment = (char *)"*Freed*";
 
       /* Shared between thread, just an indication about timing */
@@ -335,7 +348,7 @@ public:
        * to check if the memory need to be freed
        */
       if (event_id >= LMGR_THREAD_EVENT_MAX) {
-         if (events[i].flags & LMGR_EVENT_FREE) {
+         if (oldflags & LMGR_EVENT_FREE) {
             free(p);
          }
       }
@@ -1215,9 +1228,13 @@ int bthread_change_uid(uid_t uid, gid_t gid)
    return -1;
 }
 
+#ifndef TEST_PROGRAM
+#define TEST_PROGRAM_A
+#endif
 
-#ifdef _TEST_IT
-
+#ifdef TEST_PROGRAM
+#include "bacula.h"
+#include "unittests.h"
 #include "lockmgr.h"
 #undef P
 #undef V
@@ -1235,6 +1252,8 @@ bthread_mutex_t mutex_p1 = BTHREAD_MUTEX_PRIORITY(1);
 bthread_mutex_t mutex_p2 = BTHREAD_MUTEX_PRIORITY(2);
 bthread_mutex_t mutex_p3 = BTHREAD_MUTEX_PRIORITY(3);
 static const char *my_prog;
+static bool thevent1ok = false;
+static bool thevent2ok = false;
 
 void *self_lock(void *temp)
 {
@@ -1282,10 +1301,9 @@ void *mix_rwl_mutex(void *temp)
    return NULL;
 }
 
-
 void *thuid(void *temp)
 {
-   char buf[512];
+//   char buf[512];
 //   if (restrict_job_permissions("eric", "users", buf, sizeof(buf)) < 0) {
    if (bthread_change_uid(2, 100) == -1) {
       berrno be;
@@ -1379,6 +1397,7 @@ void *th_prio(void *a) {
 }
 
 void *th_event1(void *a) {
+   lmgr_thread_t *self = lmgr_get_thread_info();
    for (int i=0; i < 10000; i++) {
       if ((i % 7) == 0) {
          lmgr_add_event_flag("strdup test", i, LMGR_EVENT_DUP);
@@ -1386,11 +1405,13 @@ void *th_event1(void *a) {
          lmgr_add_event("My comment", i);
       }
    }
+   thevent1ok = self->event_id == 10000;
    sleep(5);
    return NULL;
 }
 
 void *th_event2(void *a) {
+   lmgr_thread_t *self = lmgr_get_thread_info();
    for (int i=0; i < 10000; i++) {
       if ((i % 2) == 0) {
          lmgr_add_event_flag(bstrdup("free test"), i, LMGR_EVENT_FREE);
@@ -1398,48 +1419,11 @@ void *th_event2(void *a) {
          lmgr_add_event("My comment", i);
       }
    }
+   thevent2ok = self->event_id == 10000;
    sleep(5);
    return NULL;
 }
 
-int err=0;
-int nb=0;
-void _ok(const char *file, int l, const char *op, int value, const char *label)
-{
-   nb++;
-   if (!value) {
-      err++;
-      printf("ERR %.30s %s:%i on %s\n", label, file, l, op);
-   } else {
-      printf("OK  %.30s\n", label);
-   }
-}
-
-#define ok(x, label) _ok(__FILE__, __LINE__, #x, (x), label)
-
-void _nok(const char *file, int l, const char *op, int value, const char *label)
-{
-   nb++;
-   if (value) {
-      err++;
-      printf("ERR %.30s %s:%i on !%s\n", label, file, l, op);
-   } else {
-      printf("OK  %.30s\n", label);
-   }
-}
-
-#define nok(x, label) _nok(__FILE__, __LINE__, #x, (x), label)
-
-int report()
-{
-   printf("Result %i/%i OK\n", nb - err, nb);
-   return err>0;
-}
-
-void terminate(int sig)
-{
-}
-
 /*
  * TODO:
  *  - Must detect multiple lock
@@ -1448,18 +1432,18 @@ void terminate(int sig)
  */
 int main(int argc, char **argv)
 {
+   Unittests lmgr_test("lockmgr_test", true, argc != 2);
    void *ret=NULL;
    lmgr_thread_t *self;
    pthread_t id1, id2, id3, id4, id5, tab[200];
    bthread_mutex_t bmutex1;
    pthread_mutex_t pmutex2;
-   debug_level = 10;
-   my_prog = argv[0];
-   init_signals(terminate);
+
    use_undertaker = false;
-   lmgr_init_thread();
+   my_prog = argv[0];
    self = lmgr_get_thread_info();
 
+   /* below is used for checking forced SIGSEGV in separate process */
    if (argc == 2) {             /* do priority check */
       P(mutex_p2);                /* not permited */
       P(mutex_p1);
@@ -1468,10 +1452,17 @@ int main(int argc, char **argv)
       return 0;
    }
 
-   pthread_create(&id5, NULL, thuid, NULL);
-   pthread_join(id5, NULL);
-   fprintf(stderr, "UID %d:%d\n", (int)getuid(), (int)getgid());
-   exit(0);
+   /* workaround for bthread_change_uid() failure for non-root */
+   if (getuid() == 0){
+      /* we can change uid/git, so proceed the test */
+      pthread_create(&id5, NULL, thuid, NULL);
+      pthread_join(id5, NULL);
+      Pmsg2(0, "UID %d:%d\n", (int)getuid(), (int)getgid());
+   } else {
+      Pmsg0(0, "Skipped bthread_change_uid() for non-root\n");
+   }
+
+   Pmsg0(0, "Starting mutex priority test\n");
    pthread_mutex_init(&bmutex1, NULL);
    bthread_mutex_set_priority(&bmutex1, 10);
 
@@ -1484,12 +1475,14 @@ int main(int argc, char **argv)
    V(bmutex1);
    ok(self->max_priority == 0, "Check self max_priority");
 
+   Pmsg0(0, "Starting self deadlock tests\n");
    pthread_create(&id1, NULL, self_lock, NULL);
    sleep(2);
    ok(lmgr_detect_deadlock(), "Check self deadlock");
    lmgr_v(&mutex1.mutex);                /* a bit dirty */
    pthread_join(id1, NULL);
 
+   Pmsg0(0, "Starting thread kill tests\n");
    pthread_create(&id1, NULL, nolock, NULL);
    sleep(2);
    ok(bthread_kill(id1, SIGUSR2) == 0, "Kill existing thread");
@@ -1497,6 +1490,7 @@ int main(int argc, char **argv)
    ok(bthread_kill(id1, SIGUSR2) == -1, "Kill non-existing thread");
    ok(bthread_kill(pthread_self(), SIGUSR2) == -1, "Kill self");
 
+   Pmsg0(0, "Starting thread locks tests\n");
    pthread_create(&id1, NULL, nolock, NULL);
    sleep(2);
    nok(lmgr_detect_deadlock(), "Check for nolock");
@@ -1513,7 +1507,6 @@ int main(int argc, char **argv)
    pthread_join(id2, NULL);
    pthread_join(id3, NULL);
 
-
    brwlock_t wr;
    rwl_init(&wr);
    rwl_writelock(&wr);
@@ -1562,16 +1555,18 @@ int main(int argc, char **argv)
    P(mutex6);
    ok(lmgr_mutex_is_locked(&mutex6) == 1, "Check if mutex is locked");
    V(mutex6);
-   ok(lmgr_mutex_is_locked(&mutex6) == 0, "Check if mutex is locked");
+   ok(lmgr_mutex_is_locked(&mutex6) == 0, "Check if mutex is unlocked");
    V(mutex5);
    V(mutex4);
 
+   Pmsg0(0, "Starting threads deadlock tests\n");
    pthread_create(&id1, NULL, th1, NULL);
    sleep(1);
    pthread_create(&id2, NULL, th2, NULL);
    sleep(1);
    ok(lmgr_detect_deadlock(), "Check for deadlock");
 
+   Pmsg0(0, "Starting for max_priority locks tests\n");
    pthread_create(&id3, NULL, th_prio, NULL);
    pthread_join(id3, &ret);
    ok(ret != 0, "Check for priority segfault");
@@ -1613,6 +1608,7 @@ int main(int argc, char **argv)
    V(mutex_p1);
    V(mutex_p2);
 
+   Pmsg0(0, "Start lmgr_add_even tests\n");
    for (int i=0; i < 10000; i++) {
       if ((i % 7) == 0) {
          lmgr_add_event_flag("xxxxxxxxxxxxxxxx strdup test xxxxxxxxxxxxxxxx", i, LMGR_EVENT_DUP);
@@ -1620,24 +1616,19 @@ int main(int argc, char **argv)
          lmgr_add_event("My comment", i);
       }
    }
+   ok(self->event_id == 10000, "Checking registered events in self");
 
    pthread_create(&id4, NULL, th_event1, NULL);
    pthread_create(&id5, NULL, th_event2, NULL);
 
    sleep(2);
 
-   lmgr_dump();
-
    pthread_join(id4, NULL);
    pthread_join(id5, NULL);
-//
-//   pthread_create(&id3, NULL, th3, NULL);
-//
-//   pthread_join(id1, NULL);
-//   pthread_join(id2, NULL);
-   lmgr_cleanup_main();
-   sm_check(__FILE__, __LINE__, false);
+
+   ok(thevent1ok, "Checking registered events in thread1");
+   ok(thevent2ok, "Checking registered events in thread2");
+
    return report();
 }
-
-#endif
+#endif   /* TEST_PROGRAM */
index 9633928e2cbb9075eaf5ad000a4f30300c2a641a..be9d04f8f5e4c2b45662d686a5b65d23c42827f7 100644 (file)
@@ -99,9 +99,10 @@ void terminate(int sig) {};
 /*
  * Initializes the application env, including lockmanager.
  */
-void prolog(const char *name, bool lmgr=false)
+void prolog(const char *name, bool lmgr=false, bool motd=true)
 {
-   Pmsg1(-1, "==== Starting %s ... ====\n", name);
+   if (motd)
+      Pmsg1(-1, "==== Starting %s ... ====\n", name);
    my_name_is(0, NULL, name);
    init_signals(terminate);
    if (lmgr){
index 7da4f69b762de067ad3fe7e6dfca17853cde9fef..453822cefd89c2593ee13084cacb5dc6dafa0b9b 100644 (file)
@@ -45,14 +45,17 @@ void _ok(const char *file, int l, const char *op, int value, const char *label);
 void _nok(const char *file, int l, const char *op, int value, const char *label);
 int report();
 void terminate(int sig);
-void prolog(const char *name, bool lmgr=false);
+void prolog(const char *name, bool lmgr=false, bool motd=true);
 void epilog();
 
 /* The class based approach for C++ geeks */
 class Unittests
 {
 public:
-   Unittests(const char *name, bool lmgr=false) { prolog(name, lmgr); };
+   Unittests(const char *name, bool lmgr=false, bool motd=true)
+   {
+      prolog(name, lmgr, motd);
+   };
    ~Unittests() { epilog(); };
 };
 
diff --git a/regress/tests/lockmgr-unittests b/regress/tests/lockmgr-unittests
new file mode 100755 (executable)
index 0000000..042db7e
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Copyright (C) 2000-2015 Kern Sibbald
+# License: BSD 2-Clause; see file LICENSE-FOSS
+#
+# Copyright (c) 2018 by Inteos sp. z o.o.
+# All rights reserved. IP transfered to Bacula Systems according to agreement.
+#
+# This is a lockmgr unit test
+#
+TestName="lockmgr_test"
+. scripts/functions
+make -C $src/src/lib $TestName
+
+$src/src/lib/$TestName
+exit $?