device-mapper-multipath/0069-multipath-tools-tests-...

533 lines
15 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 21 Oct 2020 16:39:24 -0500
Subject: [PATCH] multipath-tools tests: and unit tests for libmpathvalid
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
Makefile.inc | 1 +
tests/Makefile | 5 +-
tests/mpathvalid.c | 467 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 472 insertions(+), 1 deletion(-)
create mode 100644 tests/mpathvalid.c
diff --git a/Makefile.inc b/Makefile.inc
index e05f3a91..13587a9f 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -66,6 +66,7 @@ libdir = $(prefix)/$(LIB)/multipath
unitdir = $(prefix)/$(SYSTEMDPATH)/systemd/system
mpathpersistdir = $(TOPDIR)/libmpathpersist
mpathcmddir = $(TOPDIR)/libmpathcmd
+mpathvaliddir = $(TOPDIR)/libmpathvalid
thirdpartydir = $(TOPDIR)/third-party
libdmmpdir = $(TOPDIR)/libdmmp
nvmedir = $(TOPDIR)/libmultipath/nvme
diff --git a/tests/Makefile b/tests/Makefile
index 908407ea..54da774e 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -13,7 +13,7 @@ CFLAGS += $(BIN_CFLAGS) -I$(multipathdir) -I$(mpathcmddir) \
LIBDEPS += -L. -L$(mpathcmddir) -lmultipath -lmpathcmd -lcmocka
TESTS := uevent parser util dmevents hwtable blacklist unaligned vpd pgpolicy \
- alias directio valid devt
+ alias directio valid devt mpathvalid
HELPERS := test-lib.o test-log.o
.SILENT: $(TESTS:%=%.o)
@@ -31,6 +31,7 @@ endif
ifneq ($(DIO_TEST_DEV),)
directio-test_FLAGS := -DDIO_TEST_DEV=\"$(DIO_TEST_DEV)\"
endif
+mpathvalid-test_FLAGS := -I$(mpathvaliddir)
# test-specific linker flags
# XYZ-test_TESTDEPS: test libraries containing __wrap_xyz functions
@@ -56,6 +57,8 @@ alias-test_LIBDEPS := -lpthread -ldl
valid-test_OBJDEPS := ../libmultipath/valid.o
valid-test_LIBDEPS := -ludev -lpthread -ldl
devt-test_LIBDEPS := -ludev
+mpathvalid-test_LIBDEPS := -ludev -lpthread -ldl
+mpathvalid-test_OBJDEPS := ../libmpathvalid/mpath_valid.o
ifneq ($(DIO_TEST_DEV),)
directio-test_LIBDEPS := -laio
endif
diff --git a/tests/mpathvalid.c b/tests/mpathvalid.c
new file mode 100644
index 00000000..5ffabb9d
--- /dev/null
+++ b/tests/mpathvalid.c
@@ -0,0 +1,467 @@
+/*
+ * Copyright (c) 2020 Benjamin Marzinski, Red Hat
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include <stdbool.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <libudev.h>
+#include <cmocka.h>
+#include "structs.h"
+#include "config.h"
+#include "mpath_valid.h"
+#include "util.h"
+#include "debug.h"
+
+const char *test_dev = "test_name";
+#define TEST_WWID "WWID_123"
+#define CONF_TEMPLATE "mpathvalid-testconf-XXXXXXXX"
+char conf_name[] = CONF_TEMPLATE;
+bool initialized;
+
+#if 0
+static int mode_to_findmp(unsigned int mode)
+{
+ switch (mode) {
+ case MPATH_SMART:
+ return FIND_MULTIPATHS_SMART;
+ case MPATH_GREEDY:
+ return FIND_MULTIPATHS_GREEDY;
+ case MPATH_STRICT:
+ return FIND_MULTIPATHS_STRICT;
+ }
+ fail_msg("invalid mode: %u", mode);
+ return FIND_MULTIPATHS_UNDEF;
+}
+#endif
+
+static unsigned int findmp_to_mode(int findmp)
+{
+ switch (findmp) {
+ case FIND_MULTIPATHS_SMART:
+ return MPATH_SMART;
+ case FIND_MULTIPATHS_GREEDY:
+ return MPATH_GREEDY;
+ case FIND_MULTIPATHS_STRICT:
+ case FIND_MULTIPATHS_OFF:
+ case FIND_MULTIPATHS_ON:
+ return MPATH_STRICT;
+ }
+ fail_msg("invalid find_multipaths value: %d", findmp);
+ return MPATH_DEFAULT;
+}
+
+int __wrap_is_path_valid(const char *name, struct config *conf, struct path *pp,
+ bool check_multipathd)
+{
+ int r = mock_type(int);
+ int findmp = mock_type(int);
+
+ assert_ptr_equal(name, test_dev);
+ assert_ptr_not_equal(conf, NULL);
+ assert_ptr_not_equal(pp, NULL);
+ assert_true(check_multipathd);
+
+ assert_int_equal(findmp, conf->find_multipaths);
+ if (r == MPATH_IS_ERROR || r == MPATH_IS_NOT_VALID)
+ return r;
+
+ strlcpy(pp->wwid, mock_ptr_type(char *), WWID_SIZE);
+ return r;
+}
+
+int __wrap_libmultipath_init(void)
+{
+ int r = mock_type(int);
+
+ assert_false(initialized);
+ if (r != 0)
+ return r;
+ initialized = true;
+ return 0;
+}
+
+void __wrap_libmultipath_exit(void)
+{
+ assert_true(initialized);
+ initialized = false;
+}
+
+int __wrap_dm_prereq(unsigned int *v)
+{
+ assert_ptr_not_equal(v, NULL);
+ return mock_type(int);
+}
+
+int __real_init_config(const char *file);
+
+int __wrap_init_config(const char *file)
+{
+ int r = mock_type(int);
+ struct config *conf;
+
+ assert_ptr_equal(file, DEFAULT_CONFIGFILE);
+ if (r != 0)
+ return r;
+
+ assert_string_not_equal(conf_name, CONF_TEMPLATE);
+ r = __real_init_config(conf_name);
+ conf = get_multipath_config();
+ assert_ptr_not_equal(conf, NULL);
+ assert_int_equal(conf->find_multipaths, mock_type(int));
+ return 0;
+}
+
+static const char * const find_multipaths_optvals[] = {
+ [FIND_MULTIPATHS_OFF] = "off",
+ [FIND_MULTIPATHS_ON] = "on",
+ [FIND_MULTIPATHS_STRICT] = "strict",
+ [FIND_MULTIPATHS_GREEDY] = "greedy",
+ [FIND_MULTIPATHS_SMART] = "smart",
+};
+
+void make_config_file(int findmp)
+{
+ int r, fd;
+ char buf[64];
+
+ assert_true(findmp > FIND_MULTIPATHS_UNDEF &&
+ findmp < __FIND_MULTIPATHS_LAST);
+
+ r = snprintf(buf, sizeof(buf), "defaults {\nfind_multipaths %s\n}\n",
+ find_multipaths_optvals[findmp]);
+ assert_true(r > 0 && (long unsigned int)r < sizeof(buf));
+
+ memcpy(conf_name, CONF_TEMPLATE, sizeof(conf_name));
+ fd = mkstemp(conf_name);
+ assert_true(fd >= 0);
+ assert_int_equal(safe_write(fd, buf, r), 0);
+ assert_int_equal(close(fd), 0);
+}
+
+int setup(void **state)
+{
+ initialized = false;
+ udev = udev_new();
+ if (udev == NULL)
+ return -1;
+ return 0;
+}
+
+int teardown(void **state)
+{
+ struct config *conf;
+ conf = get_multipath_config();
+ put_multipath_config(conf);
+ if (conf)
+ uninit_config();
+ if (strcmp(conf_name, CONF_TEMPLATE) != 0)
+ unlink(conf_name);
+ udev_unref(udev);
+ udev = NULL;
+ return 0;
+}
+
+static void check_config(bool valid_config)
+{
+ struct config *conf;
+
+ conf = get_multipath_config();
+ put_multipath_config(conf);
+ if (valid_config)
+ assert_ptr_not_equal(conf, NULL);
+}
+
+/* libmultipath_init fails */
+static void test_mpathvalid_init_bad1(void **state)
+{
+ will_return(__wrap_libmultipath_init, 1);
+ assert_int_equal(mpathvalid_init(MPATH_LOG_PRIO_DEBUG,
+ MPATH_LOG_STDERR), -1);
+ assert_false(initialized);
+ check_config(false);
+}
+
+/* init_config fails */
+static void test_mpathvalid_init_bad2(void **state)
+{
+ will_return(__wrap_libmultipath_init, 0);
+ will_return(__wrap_init_config, 1);
+ assert_int_equal(mpathvalid_init(MPATH_LOG_PRIO_ERR,
+ MPATH_LOG_STDERR_TIMESTAMP), -1);
+ assert_false(initialized);
+ check_config(false);
+}
+
+/* dm_prereq fails */
+static void test_mpathvalid_init_bad3(void **state)
+{
+ make_config_file(FIND_MULTIPATHS_STRICT);
+ will_return(__wrap_libmultipath_init, 0);
+ will_return(__wrap_init_config, 0);
+ will_return(__wrap_init_config, FIND_MULTIPATHS_STRICT);
+ will_return(__wrap_dm_prereq, 1);
+ assert_int_equal(mpathvalid_init(MPATH_LOG_STDERR, MPATH_LOG_PRIO_ERR),
+ -1);
+ assert_false(initialized);
+ check_config(false);
+}
+
+static void check_mpathvalid_init(int findmp, int prio, int log_style)
+{
+ make_config_file(findmp);
+ will_return(__wrap_libmultipath_init, 0);
+ will_return(__wrap_init_config, 0);
+ will_return(__wrap_init_config, findmp);
+ will_return(__wrap_dm_prereq, 0);
+ assert_int_equal(mpathvalid_init(prio, log_style), 0);
+ assert_true(initialized);
+ check_config(true);
+ assert_int_equal(logsink, log_style);
+ assert_int_equal(libmp_verbosity, prio);
+ assert_int_equal(findmp_to_mode(findmp), mpathvalid_get_mode());
+}
+
+static void check_mpathvalid_exit(void)
+{
+ assert_int_equal(mpathvalid_exit(), 0);
+ assert_false(initialized);
+ check_config(false);
+}
+
+static void test_mpathvalid_init_good1(void **state)
+{
+ check_mpathvalid_init(FIND_MULTIPATHS_OFF, MPATH_LOG_PRIO_ERR,
+ MPATH_LOG_STDERR_TIMESTAMP);
+}
+
+static void test_mpathvalid_init_good2(void **state)
+{
+ check_mpathvalid_init(FIND_MULTIPATHS_STRICT, MPATH_LOG_PRIO_DEBUG,
+ MPATH_LOG_STDERR);
+}
+
+static void test_mpathvalid_init_good3(void **state)
+{
+ check_mpathvalid_init(FIND_MULTIPATHS_ON, MPATH_LOG_PRIO_NOLOG,
+ MPATH_LOG_SYSLOG);
+}
+
+static void test_mpathvalid_exit(void **state)
+{
+ check_mpathvalid_init(FIND_MULTIPATHS_ON, MPATH_LOG_PRIO_ERR,
+ MPATH_LOG_STDERR);
+ check_mpathvalid_exit();
+}
+
+/* fails if config hasn't been set */
+static void test_mpathvalid_get_mode_bad(void **state)
+{
+#if 1
+ assert_int_equal(mpathvalid_get_mode(), MPATH_MODE_ERROR);
+#else
+ assert_int_equal(mpathvalid_get_mode(), 1);
+#endif
+}
+
+/*fails if config hasn't been set */
+static void test_mpathvalid_reload_config_bad1(void **state)
+{
+#if 1
+ will_return(__wrap_init_config, 1);
+#endif
+ assert_int_equal(mpathvalid_reload_config(), -1);
+ check_config(false);
+}
+
+/* init_config fails */
+static void test_mpathvalid_reload_config_bad2(void **state)
+{
+ check_mpathvalid_init(FIND_MULTIPATHS_ON, MPATH_LOG_PRIO_ERR,
+ MPATH_LOG_STDERR);
+ will_return(__wrap_init_config, 1);
+ assert_int_equal(mpathvalid_reload_config(), -1);
+ check_config(false);
+ check_mpathvalid_exit();
+}
+
+static void check_mpathvalid_reload_config(int findmp)
+{
+ assert_string_not_equal(conf_name, CONF_TEMPLATE);
+ unlink(conf_name);
+ make_config_file(findmp);
+ will_return(__wrap_init_config, 0);
+ will_return(__wrap_init_config, findmp);
+ assert_int_equal(mpathvalid_reload_config(), 0);
+ check_config(true);
+ assert_int_equal(findmp_to_mode(findmp), mpathvalid_get_mode());
+}
+
+static void test_mpathvalid_reload_config_good(void **state)
+{
+ check_mpathvalid_init(FIND_MULTIPATHS_OFF, MPATH_LOG_PRIO_ERR,
+ MPATH_LOG_STDERR);
+ check_mpathvalid_reload_config(FIND_MULTIPATHS_ON);
+ check_mpathvalid_reload_config(FIND_MULTIPATHS_GREEDY);
+ check_mpathvalid_reload_config(FIND_MULTIPATHS_SMART);
+ check_mpathvalid_reload_config(FIND_MULTIPATHS_STRICT);
+ check_mpathvalid_exit();
+}
+
+/* NULL name */
+static void test_mpathvalid_is_path_bad1(void **state)
+{
+ assert_int_equal(mpathvalid_is_path(NULL, MPATH_STRICT, NULL, NULL, 0),
+ MPATH_IS_ERROR);
+}
+
+/* bad mode */
+static void test_mpathvalid_is_path_bad2(void **state)
+{
+ assert_int_equal(mpathvalid_is_path(test_dev, MPATH_MODE_ERROR, NULL,
+ NULL, 0), MPATH_IS_ERROR);
+}
+
+/* NULL path_wwids and non-zero nr_paths */
+static void test_mpathvalid_is_path_bad3(void **state)
+{
+ assert_int_equal(mpathvalid_is_path(test_dev, MPATH_MODE_ERROR, NULL,
+ NULL, 1), MPATH_IS_ERROR);
+}
+
+/*fails if config hasn't been set */
+static void test_mpathvalid_is_path_bad4(void **state)
+{
+#if 0
+ will_return(__wrap_is_path_valid, MPATH_IS_ERROR);
+ will_return(__wrap_is_path_valid, FIND_MULTIPATHS_STRICT);
+#endif
+ assert_int_equal(mpathvalid_is_path(test_dev, MPATH_STRICT, NULL,
+ NULL, 0), MPATH_IS_ERROR);
+}
+
+/* is_path_valid fails */
+static void test_mpathvalid_is_path_bad5(void **state)
+{
+ check_mpathvalid_init(FIND_MULTIPATHS_OFF, MPATH_LOG_PRIO_ERR,
+ MPATH_LOG_STDERR);
+ will_return(__wrap_is_path_valid, MPATH_IS_ERROR);
+ will_return(__wrap_is_path_valid, FIND_MULTIPATHS_GREEDY);
+ assert_int_equal(mpathvalid_is_path(test_dev, MPATH_GREEDY, NULL,
+ NULL, 0), MPATH_IS_ERROR);
+ check_mpathvalid_exit();
+}
+
+static void test_mpathvalid_is_path_good1(void **state)
+{
+ char *wwid;
+ check_mpathvalid_init(FIND_MULTIPATHS_STRICT, MPATH_LOG_PRIO_ERR,
+ MPATH_LOG_STDERR);
+ will_return(__wrap_is_path_valid, MPATH_IS_NOT_VALID);
+ will_return(__wrap_is_path_valid, FIND_MULTIPATHS_STRICT);
+ assert_int_equal(mpathvalid_is_path(test_dev, MPATH_DEFAULT, &wwid,
+ NULL, 0), MPATH_IS_NOT_VALID);
+ assert_ptr_equal(wwid, NULL);
+ check_mpathvalid_exit();
+}
+
+static void test_mpathvalid_is_path_good2(void **state)
+{
+ const char *wwids[] = { "WWID_A", "WWID_B", "WWID_C", "WWID_D" };
+ char *wwid;
+ check_mpathvalid_init(FIND_MULTIPATHS_ON, MPATH_LOG_PRIO_ERR,
+ MPATH_LOG_STDERR);
+ will_return(__wrap_is_path_valid, MPATH_IS_VALID);
+ will_return(__wrap_is_path_valid, FIND_MULTIPATHS_ON);
+ will_return(__wrap_is_path_valid, TEST_WWID);
+ assert_int_equal(mpathvalid_is_path(test_dev, MPATH_DEFAULT, &wwid,
+ wwids, 4), MPATH_IS_VALID);
+ assert_string_equal(wwid, TEST_WWID);
+}
+
+static void test_mpathvalid_is_path_good3(void **state)
+{
+ const char *wwids[] = { "WWID_A", "WWID_B", "WWID_C", "WWID_D" };
+ char *wwid;
+ check_mpathvalid_init(FIND_MULTIPATHS_OFF, MPATH_LOG_PRIO_ERR,
+ MPATH_LOG_STDERR);
+ will_return(__wrap_is_path_valid, MPATH_IS_VALID);
+ will_return(__wrap_is_path_valid, FIND_MULTIPATHS_SMART);
+ will_return(__wrap_is_path_valid, TEST_WWID);
+ assert_int_equal(mpathvalid_is_path(test_dev, MPATH_SMART, &wwid,
+ wwids, 4), MPATH_IS_VALID);
+ assert_string_equal(wwid, TEST_WWID);
+}
+
+/* mabybe valid with no matching paths */
+static void test_mpathvalid_is_path_good4(void **state)
+{
+ const char *wwids[] = { "WWID_A", "WWID_B", "WWID_C", "WWID_D" };
+ char *wwid;
+ check_mpathvalid_init(FIND_MULTIPATHS_SMART, MPATH_LOG_PRIO_ERR,
+ MPATH_LOG_STDERR);
+ will_return(__wrap_is_path_valid, MPATH_IS_MAYBE_VALID);
+ will_return(__wrap_is_path_valid, FIND_MULTIPATHS_SMART);
+ will_return(__wrap_is_path_valid, TEST_WWID);
+ assert_int_equal(mpathvalid_is_path(test_dev, MPATH_DEFAULT, &wwid,
+ wwids, 4), MPATH_IS_MAYBE_VALID);
+ assert_string_equal(wwid, TEST_WWID);
+}
+
+/* maybe valid with matching paths */
+static void test_mpathvalid_is_path_good5(void **state)
+{
+ const char *wwids[] = { "WWID_A", "WWID_B", TEST_WWID, "WWID_D" };
+ char *wwid;
+ check_mpathvalid_init(FIND_MULTIPATHS_SMART, MPATH_LOG_PRIO_ERR,
+ MPATH_LOG_STDERR);
+ will_return(__wrap_is_path_valid, MPATH_IS_MAYBE_VALID);
+ will_return(__wrap_is_path_valid, FIND_MULTIPATHS_SMART);
+ will_return(__wrap_is_path_valid, TEST_WWID);
+ assert_int_equal(mpathvalid_is_path(test_dev, MPATH_DEFAULT, &wwid,
+ wwids, 4), MPATH_IS_VALID);
+ assert_string_equal(wwid, TEST_WWID);
+}
+
+#define setup_test(name) \
+ cmocka_unit_test_setup_teardown(name, setup, teardown)
+
+int test_mpathvalid(void)
+{
+ const struct CMUnitTest tests[] = {
+ setup_test(test_mpathvalid_init_bad1),
+ setup_test(test_mpathvalid_init_bad2),
+ setup_test(test_mpathvalid_init_bad3),
+ setup_test(test_mpathvalid_init_good1),
+ setup_test(test_mpathvalid_init_good2),
+ setup_test(test_mpathvalid_init_good3),
+ setup_test(test_mpathvalid_exit),
+ setup_test(test_mpathvalid_get_mode_bad),
+ setup_test(test_mpathvalid_reload_config_bad1),
+ setup_test(test_mpathvalid_reload_config_bad2),
+ setup_test(test_mpathvalid_reload_config_good),
+ setup_test(test_mpathvalid_is_path_bad1),
+ setup_test(test_mpathvalid_is_path_bad2),
+ setup_test(test_mpathvalid_is_path_bad3),
+ setup_test(test_mpathvalid_is_path_bad4),
+ setup_test(test_mpathvalid_is_path_bad5),
+ setup_test(test_mpathvalid_is_path_good1),
+ setup_test(test_mpathvalid_is_path_good2),
+ setup_test(test_mpathvalid_is_path_good3),
+ setup_test(test_mpathvalid_is_path_good4),
+ setup_test(test_mpathvalid_is_path_good5),
+ };
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
+
+int main(void)
+{
+ int r = 0;
+
+ r += test_mpathvalid();
+ return r;
+}
--
2.17.2