From: Benjamin Marzinski <bmarzins@redhat.com>
To: Christophe Varoqui <christophe.varoqui@opensvc.com>
Cc: device-mapper development <dm-devel@redhat.com>,
Martin Wilck <Martin.Wilck@suse.com>
Subject: [dm-devel] [PATCH v3 2/4] multipath-tools tests: and unit tests for libmpathvalid
Date: Wed, 21 Oct 2020 16:39:24 -0500 [thread overview]
Message-ID: <1603316366-28735-3-git-send-email-bmarzins@redhat.com> (raw)
In-Reply-To: <1603316366-28735-1-git-send-email-bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.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 73ff0f5c..73ec0702 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
.SILENT: $(TESTS:%=%.o)
.PRECIOUS: $(TESTS:%=%-test)
@@ -30,6 +30,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
@@ -55,6 +56,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
--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
next prev parent reply other threads:[~2020-10-21 21:42 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-10-21 21:39 [dm-devel] [PATCH v3 0/4] add library to check if device is a valid path Benjamin Marzinski
2020-10-21 21:39 ` [dm-devel] [PATCH v3 1/4] multipath: add libmpathvalid library Benjamin Marzinski
2020-10-21 21:39 ` Benjamin Marzinski [this message]
2020-10-21 21:39 ` [dm-devel] [PATCH v3 3/4] libmultipath: add uid failback for dasd devices Benjamin Marzinski
2020-10-21 21:39 ` [dm-devel] [PATCH v3 4/4] libmultipath: change log level for null uid_attribute Benjamin Marzinski
2020-11-01 20:48 ` Martin Wilck
2020-11-01 21:33 ` [dm-devel] [PATCH v3 0/4] add library to check if device is a valid path Martin Wilck
2020-11-02 20:22 ` Benjamin Marzinski
2020-12-16 20:52 ` Martin Wilck
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1603316366-28735-3-git-send-email-bmarzins@redhat.com \
--to=bmarzins@redhat.com \
--cc=Martin.Wilck@suse.com \
--cc=christophe.varoqui@opensvc.com \
--cc=dm-devel@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.