Add a few tests (mostly meaningful with valgrind or ASAN) to test the
shared pointer code.

Signed-off-by: Martin Wilck <[email protected]>
---
 tests/Makefile     |   4 +-
 tests/shared_ptr.c | 111 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 114 insertions(+), 1 deletion(-)
 create mode 100644 tests/shared_ptr.c

diff --git a/tests/Makefile b/tests/Makefile
index f0e5dd3..fc2a7ed 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -9,7 +9,8 @@ CFLAGS += $(BIN_CFLAGS) -Wno-unused-parameter 
-Wno-unused-function $(W_MISSING_I
 LIBDEPS += -L. -L $(mpathutildir) -L$(mpathcmddir) -lmultipath -lmpathutil 
-lmpathcmd -lcmocka
 
 TESTS := uevent parser util dmevents hwtable blacklist unaligned vpd pgpolicy \
-        alias directio valid devt mpathvalid strbuf sysfs features cli mapinfo 
runner
+        alias directio valid devt mpathvalid strbuf sysfs features cli mapinfo 
runner \
+        shared_ptr
 HELPERS := test-lib.o test-log.o
 
 .PRECIOUS: $(TESTS:%=%-test)
@@ -66,6 +67,7 @@ features-test_OBJDEPS := $(mpathutildir)/mt-libudev.o
 cli-test_OBJDEPS := $(daemondir)/cli.o
 mapinfo-test_LIBDEPS = -lpthread -ldevmapper
 runner-test_LIBDEPS = -lpthread
+shared_ptr-test_LIBDEPS = -lpthread
 
 %.o: %.c
        @echo building $@ because of $?
diff --git a/tests/shared_ptr.c b/tests/shared_ptr.c
new file mode 100644
index 0000000..ca5aa1a
--- /dev/null
+++ b/tests/shared_ptr.c
@@ -0,0 +1,111 @@
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <pthread.h>
+#include "cmocka-compat.h"
+#include "util.h"
+
+#include "globals.c"
+
+struct s_8 {
+       uint64_t val;
+};
+
+struct s_4 {
+       uint32_t val;
+};
+
+struct s_2 {
+       uint16_t val;
+};
+
+// clang-format off
+#define make_destruct(n, size)      \
+static void destruct_ ## n ## _ ## size(void *ptr) \
+{                                                \
+       struct s_##size *s = ptr;                 \
+                                                 \
+       assert_ptr_not_equal(ptr, NULL);          \
+       assert_int_equal(s->val, n);              \
+}
+
+#define make_fn(size) \
+static void *thread_##size(void *arg)          \
+{                                              \
+       struct s_##size *s = arg;               \
+                                               \
+       get_shared_ptr(s);                      \
+       s->val++;                               \
+       put_shared_ptr(s);                      \
+       return NULL;                            \
+}
+
+make_fn(2)
+make_fn(4)
+make_fn(8)
+
+#define make_test(n, size)                                     \
+make_destruct(n, size)                                         \
+                                                               \
+static void test_ ## n ## _ ## size(void **state)              \
+{                                                              \
+       pthread_t threads[n];                                   \
+       struct s_##size *s;                                     \
+       int i, rc;                                              \
+                                                               \
+       s = alloc_shared_ptr(size, destruct_ ## n## _ ## size); \
+       assert_ptr_not_equal(s, NULL);                          \
+       s->val = 0;                                             \
+       for (i = 0; i < n; i++) {                               \
+               rc = pthread_create(&threads[i], NULL,          \
+                                   thread_##size, s);          \
+               assert_int_equal(rc, 0);                        \
+       }                                                       \
+       for (i = 0; i < n; i++) {                               \
+               rc = pthread_join(threads[i], NULL);            \
+               assert_int_equal(rc, 0);                        \
+       }                                                       \
+       assert_int_equal(s->val, n);                            \
+       put_shared_ptr(s);                                      \
+}
+
+make_test(0, 2)
+make_test(0, 4)
+make_test(0, 8)
+make_test(100, 2)
+make_test(100, 4)
+make_test(100, 8)
+make_test(1000, 2)
+make_test(1000, 4)
+make_test(1000, 8)
+       // clang-format on
+
+       int test_shared_ptr(void)
+{
+       // clang-format off
+       const struct CMUnitTest tests[] = {
+               cmocka_unit_test(test_0_2),
+               cmocka_unit_test(test_0_4),
+               cmocka_unit_test(test_0_8),
+               cmocka_unit_test(test_100_2),
+               cmocka_unit_test(test_100_4),
+               cmocka_unit_test(test_100_8),
+               cmocka_unit_test(test_1000_2),
+               cmocka_unit_test(test_1000_4),
+               cmocka_unit_test(test_1000_8),
+       };
+       // clang-format on
+       return cmocka_run_group_tests(tests, NULL, NULL);
+}
+
+int main(void)
+{
+       int ret = 0;
+
+       init_test_verbosity(-1);
+       ret += test_shared_ptr();
+       return ret;
+}
-- 
2.54.0


Reply via email to