All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Benjamin Marzinski" <bmarzins@redhat.com>
To: dm-devel@redhat.com
Cc: Martin Wilck <mwilck@suse.com>, christophe.varoqui@free.fr
Subject: [PATCH 12/12] multipath: add unit tests for dmevents code
Date: Wed, 14 Mar 2018 12:46:45 -0500	[thread overview]
Message-ID: <1521049605-22050-13-git-send-email-bmarzins@redhat.com> (raw)
In-Reply-To: <1521049605-22050-1-git-send-email-bmarzins@redhat.com>

These unit tests do not get complete code coverage. Also, they don't
check for memory errors. To do this through unit tests, instead of
using valgrid, would require adding unit test specific compilation
defines to the code, and compiling a seperate unit-test version.

Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
 tests/Makefile   |   9 +-
 tests/dmevents.c | 847 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 853 insertions(+), 3 deletions(-)
 create mode 100644 tests/dmevents.c

diff --git a/tests/Makefile b/tests/Makefile
index 3450b14..1f36411 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -3,11 +3,16 @@ include ../Makefile.inc
 CFLAGS += $(BIN_CFLAGS) -I$(multipathdir) -I$(mpathcmddir)
 LIBDEPS += -L$(multipathdir) -lmultipath -lcmocka
 
-TESTS := uevent parser util
+TESTS := uevent parser util dmevents
 
 .SILENT: $(TESTS:%=%.o)
 .PRECIOUS: $(TESTS:%=%-test)
 
+all:	$(TESTS:%=%.out)
+
+dmevents-test: dmevents.o ../multipathd/dmevents.c globals.c $(multipathdir)/libmultipath.so
+	@$(CC) -o $@ $< $(LDFLAGS) $(LIBDEPS) -lpthread -ldevmapper -lurcu -Wl,--wrap=open -Wl,--wrap=close -Wl,--wrap=dm_is_mpath -Wl,--wrap=dm_geteventnr -Wl,--wrap=ioctl -Wl,--wrap=libmp_dm_task_create -Wl,--wrap=dm_task_no_open_count -Wl,--wrap=dm_task_run -Wl,--wrap=dm_task_get_names -Wl,--wrap=dm_task_destroy -Wl,--wrap=poll -Wl,--wrap=remove_map_by_alias -Wl,--wrap=update_multipath
+
 %-test:	%.o globals.c $(multipathdir)/libmultipath.so
 	@$(CC) -o $@ $< $(LDFLAGS) $(LIBDEPS)
 
@@ -15,8 +20,6 @@ TESTS := uevent parser util
 	@echo == running $< ==
 	@LD_LIBRARY_PATH=$(multipathdir):$(mpathcmddir) ./$< >$@
 
-all:	$(TESTS:%=%.out)
-
 clean: dep_clean
 	rm -f $(TESTS:%=%-test) $(TESTS:%=%.out) $(TESTS:%=%.o)
 
diff --git a/tests/dmevents.c b/tests/dmevents.c
new file mode 100644
index 0000000..4442fc2
--- /dev/null
+++ b/tests/dmevents.c
@@ -0,0 +1,847 @@
+/*
+ * Copyright (c) 2018 Benjamin Marzinski, Redhat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ *
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <cmocka.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "structs.h"
+#include "structs_vec.h"
+
+#include "globals.c"
+/* I have to do this to get at the static variables */
+#include "../multipathd/dmevents.c"
+
+struct dm_device {
+	char name[WWID_SIZE];
+	int is_mpath;
+	uint32_t evt_nr;
+	uint32_t update_nr;
+};
+
+struct test_data {
+	struct vectors vecs;
+	vector dm_devices;
+	struct dm_names *names;
+};
+
+struct test_data data;
+
+int add_dm_device_event(char *name, int is_mpath, uint32_t evt_nr)
+{
+	struct dm_device *dev;
+	int i;
+
+	vector_foreach_slot(data.dm_devices, dev, i) {
+		if (strcmp(name, dev->name) == 0) {
+			dev->evt_nr = evt_nr;
+			return 0;
+		}
+	}
+	dev = (struct dm_device *)malloc(sizeof(struct dm_device));
+	if (!dev){
+		condlog(0, "Testing error mallocing dm_device");
+		return -1;
+	}
+	strncpy(dev->name, name, WWID_SIZE);
+	dev->name[WWID_SIZE - 1] = 0;
+	dev->is_mpath = is_mpath;
+	dev->evt_nr = evt_nr;
+	if (!vector_alloc_slot(data.dm_devices)) {
+		condlog(0, "Testing error setting dm_devices slot");
+		free(dev);
+		return -1;
+	}
+	vector_set_slot(data.dm_devices, dev);
+	return 0;
+}
+
+struct dm_device *find_dm_device(const char *name)
+{
+	struct dm_device *dev;
+	int i;
+
+	vector_foreach_slot(data.dm_devices, dev, i)
+		if (strcmp(name, dev->name) == 0)
+			return dev;
+	return NULL;
+}
+
+int remove_dm_device_event(const char *name)
+{
+	struct dm_device *dev;
+	int i;
+
+	vector_foreach_slot(data.dm_devices, dev, i) {
+		if (strcmp(name, dev->name) == 0) {
+			vector_del_slot(data.dm_devices, i);
+				free(dev);
+			return 0;
+		}
+	}
+	return -1;
+}
+
+void remove_all_dm_device_events(void)
+{
+	struct dm_device *dev;
+	int i;
+
+	vector_foreach_slot(data.dm_devices, dev, i)
+		free(dev);
+	vector_reset(data.dm_devices);
+}
+
+static inline size_t align_val(size_t val)
+{
+        return (val + 7) & ~7;
+}
+static inline void *align_ptr(void *ptr)
+{
+	return (void *)align_val((size_t)ptr);
+}
+
+/* copied off of list_devices in dm-ioctl.c */
+struct dm_names *build_dm_names(void)
+{
+	struct dm_names *names, *np, *old_np = NULL;
+	uint32_t *event_nr;
+	struct dm_device *dev;
+	int i, size = 0;
+
+	if (VECTOR_SIZE(data.dm_devices) == 0) {
+		names = (struct dm_names *)malloc(sizeof(struct dm_names));
+		if (!names) {
+			condlog(0, "Testing error allocating empty dm_names");
+			return NULL;
+		}
+		names->dev = 0;
+		names->next = 0;
+		return names;
+	}
+	vector_foreach_slot(data.dm_devices, dev, i) {
+		size += align_val(offsetof(struct dm_names, name) +
+				  strlen(dev->name) + 1);
+		size += align_val(sizeof(uint32_t));
+	}
+	names = (struct dm_names *)malloc(size);
+	if (!names) {
+		condlog(0, "Testing error allocating dm_names");
+		return NULL;
+	}
+	np = names;
+	vector_foreach_slot(data.dm_devices, dev, i) {
+		if (old_np)
+			old_np->next = (uint32_t) ((uintptr_t) np -
+						   (uintptr_t) old_np);
+		np->dev = 1;
+		np->next = 0;
+		strcpy(np->name, dev->name);
+
+		old_np = np;
+		event_nr = align_ptr(np->name + strlen(dev->name) + 1);
+		*event_nr = dev->evt_nr;
+		np = align_ptr(event_nr + 1);
+	}
+	assert_int_equal((char *)np - (char *)names, size);
+	return names;
+}
+
+static int setup(void **state)
+{
+	if (dmevent_poll_supported()) {
+		data.dm_devices = vector_alloc();
+		*state = &data;
+	} else
+		*state = NULL;
+	return 0;
+}
+
+static int teardown(void **state)
+{
+	struct dm_device *dev;
+	int i;
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		return 0;
+	vector_foreach_slot(datap->dm_devices, dev, i)
+		free(dev);
+	vector_free(datap->dm_devices);
+	datap = NULL;
+	return 0;
+}
+
+int __wrap_open(const char *pathname, int flags)
+{
+	assert_ptr_equal(pathname, "/dev/mapper/control");
+	assert_int_equal(flags, O_RDWR);
+	return mock_type(int);
+}
+
+int __wrap_close(int fd)
+{
+	assert_int_equal(fd, waiter->fd);
+	return 0;
+}
+
+int __wrap_dm_is_mpath(const char *name)
+{
+	struct dm_device *dev;
+	int i;
+
+	vector_foreach_slot(data.dm_devices, dev, i)
+		if (strcmp(name, dev->name) == 0)
+			return dev->is_mpath;
+	return 0;
+}
+
+int __wrap_dm_geteventnr(const char *name)
+{
+	struct dm_device *dev;
+	int fail = mock_type(int);
+
+	if (fail)
+		return -1;
+	dev = find_dm_device(name);
+	if (dev) {
+		/* simulate updating device state after adding it */
+		dev->update_nr = dev->evt_nr;
+		return dev->evt_nr;
+	}
+	return -1;
+}
+
+int __wrap_ioctl(int fd, unsigned long request, void *argp)
+{
+	assert_int_equal(fd, waiter->fd);
+	assert_int_equal(request, DM_DEV_ARM_POLL);
+	return mock_type(int);
+}
+
+struct dm_task *__wrap_libmp_dm_task_create(int task)
+{
+	assert_int_equal(task, DM_DEVICE_LIST);
+	return mock_type(struct dm_task *);
+}
+
+int __wrap_dm_task_no_open_count(struct dm_task *dmt)
+{
+	assert_ptr_equal((struct test_data *)dmt, &data);
+	return mock_type(int);
+}
+
+int __wrap_dm_task_run(struct dm_task *dmt)
+{
+	assert_ptr_equal((struct test_data *)dmt, &data);
+	return mock_type(int);
+}
+
+struct dm_names * __wrap_dm_task_get_names(struct dm_task *dmt)
+{
+	int good = mock_type(int);
+	assert_ptr_equal((struct test_data *)dmt, &data);
+
+	if (data.names) {
+		condlog(0, "Testing error. data.names already allocated");
+		return NULL;
+	}
+	if (!good)
+		return NULL;
+	data.names = build_dm_names();
+	return data.names;
+}
+
+void __wrap_dm_task_destroy(struct dm_task *dmt)
+{
+	assert_ptr_equal((struct test_data *)dmt, &data);
+
+	if (data.names) {
+		free(data.names);
+		data.names = NULL;
+	}
+}
+
+int __wrap_poll(struct pollfd *fds, nfds_t nfds, int timeout)
+{
+	assert_int_equal(nfds, 1);
+	assert_int_equal(timeout, -1);
+	assert_int_equal(fds->fd, waiter->fd);
+	assert_int_equal(fds->events, POLLIN);
+	return mock_type(int);
+}
+
+void __wrap_remove_map_by_alias(const char *alias, struct vectors * vecs,
+				int purge_vec)
+{
+	check_expected(alias);
+	assert_ptr_equal(vecs, waiter->vecs);
+	assert_int_equal(purge_vec, 1);
+}
+
+int __wrap_update_multipath(struct vectors *vecs, char *mapname, int reset)
+{
+	int fail;
+
+	check_expected(mapname);
+	assert_ptr_equal(vecs, waiter->vecs);
+	assert_int_equal(reset, 1);
+	fail = mock_type(int);
+	if (fail) {
+		assert_int_equal(remove_dm_device_event(mapname), 0);
+		return fail;
+	} else {
+		struct dm_device *dev;
+		int i;
+
+		vector_foreach_slot(data.dm_devices, dev, i) {
+			if (strcmp(mapname, dev->name) == 0) {
+				dev->update_nr = dev->evt_nr;
+				return 0;
+			}
+		}
+		fail();
+	}
+	return fail;
+}
+
+struct dev_event *find_dmevents(const char *name)
+{
+	struct dev_event *dev_evt;
+	int i;
+
+	vector_foreach_slot(waiter->events, dev_evt, i)
+		if (!strcmp(dev_evt->name, name))
+			return dev_evt;
+	return NULL;
+}
+
+static void test_init_waiter_bad0(void **state)
+{
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		skip();
+	assert_int_equal(init_dmevent_waiter(NULL), -1);
+}
+
+static void test_init_waiter_bad1(void **state)
+{
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		skip();
+	will_return(__wrap_open, -1);
+	assert_int_equal(init_dmevent_waiter(&datap->vecs), -1);
+	assert_ptr_equal(waiter, NULL);
+}
+
+static void test_init_waiter_good0(void **state)
+{
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		skip();
+	will_return(__wrap_open, 2);
+	assert_int_equal(init_dmevent_waiter(&datap->vecs), 0);
+	assert_ptr_not_equal(waiter, NULL);
+}
+
+static void test_watch_dmevents_bad0(void **state)
+{
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		skip();
+	assert_int_equal(watch_dmevents("foo"), -1);
+	assert_ptr_equal(find_dmevents("foo"), NULL);
+}
+
+static void test_watch_dmevents_bad1(void **state)
+{
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		skip();
+
+	assert_int_equal(add_dm_device_event("foo", 0, 5), 0);
+	assert_int_equal(watch_dmevents("foo"), -1);
+	assert_ptr_equal(find_dmevents("foo"), NULL);
+}
+
+static void test_watch_dmevents_bad2(void **state)
+{
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		skip();
+
+	remove_all_dm_device_events();
+	assert_int_equal(add_dm_device_event("foo", 1, 5), 0);
+	will_return(__wrap_dm_geteventnr, -1);
+	assert_int_equal(watch_dmevents("foo"), -1);
+	assert_ptr_equal(find_dmevents("foo"), NULL);
+}
+static void test_watch_dmevents_good0(void **state)
+{
+	struct dev_event *dev_evt;
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		skip();
+
+	remove_all_dm_device_events();
+	assert_int_equal(add_dm_device_event("foo", 1, 5), 0);
+	will_return(__wrap_dm_geteventnr, 0);
+	assert_int_equal(watch_dmevents("foo"), 0);
+	dev_evt = find_dmevents("foo");
+	assert_ptr_not_equal(dev_evt, NULL);
+	assert_int_equal(dev_evt->evt_nr, 5);
+	assert_int_equal(dev_evt->action, EVENT_NOTHING);
+	assert_int_equal(VECTOR_SIZE(waiter->events), 1);
+	unwatch_dmevents("foo");
+	assert_int_equal(VECTOR_SIZE(waiter->events), 0);
+	assert_ptr_equal(find_dmevents("foo"), NULL);
+}
+
+static void test_watch_dmevents_good1(void **state)
+{
+	struct dev_event *dev_evt;
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		skip();
+
+	remove_all_dm_device_events();
+	assert_int_equal(add_dm_device_event("foo", 1, 5), 0);	
+	will_return(__wrap_dm_geteventnr, 0);
+	assert_int_equal(watch_dmevents("foo"), 0);
+	dev_evt = find_dmevents("foo");
+	assert_ptr_not_equal(dev_evt, NULL);
+	assert_int_equal(dev_evt->evt_nr, 5);
+	assert_int_equal(dev_evt->action, EVENT_NOTHING);
+	assert_int_equal(add_dm_device_event("foo", 1, 6), 0);
+	will_return(__wrap_dm_geteventnr, 0);
+	assert_int_equal(watch_dmevents("foo"), 0);
+	dev_evt = find_dmevents("foo");
+	assert_ptr_not_equal(dev_evt, NULL);
+	assert_int_equal(dev_evt->evt_nr, 6);
+	assert_int_equal(dev_evt->action, EVENT_NOTHING);
+	assert_int_equal(VECTOR_SIZE(waiter->events), 1);
+	unwatch_dmevents("foo");
+	assert_int_equal(VECTOR_SIZE(waiter->events), 0);
+	assert_ptr_equal(find_dmevents("foo"), NULL);
+}
+
+static void test_watch_dmevents_good2(void **state)
+{
+	struct dev_event *dev_evt;
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		skip();
+
+	unwatch_all_dmevents();
+	remove_all_dm_device_events();
+	assert_int_equal(add_dm_device_event("foo", 1, 5), 0);
+	assert_int_equal(add_dm_device_event("bar", 1, 7), 0);
+	will_return(__wrap_dm_geteventnr, 0);
+	assert_int_equal(watch_dmevents("foo"), 0);
+	dev_evt = find_dmevents("foo");
+	assert_ptr_not_equal(dev_evt, NULL);
+	assert_int_equal(dev_evt->evt_nr, 5);
+	assert_int_equal(dev_evt->action, EVENT_NOTHING);
+	assert_ptr_equal(find_dmevents("bar"), NULL);
+	will_return(__wrap_dm_geteventnr, 0);
+	assert_int_equal(watch_dmevents("bar"), 0);
+	dev_evt = find_dmevents("foo");
+	assert_ptr_not_equal(dev_evt, NULL);
+	assert_int_equal(dev_evt->evt_nr, 5);
+	assert_int_equal(dev_evt->action, EVENT_NOTHING);
+	dev_evt = find_dmevents("bar");
+	assert_ptr_not_equal(dev_evt, NULL);
+	assert_int_equal(dev_evt->evt_nr, 7);
+	assert_int_equal(dev_evt->action, EVENT_NOTHING);
+	assert_int_equal(VECTOR_SIZE(waiter->events), 2);
+	unwatch_all_dmevents();
+	assert_int_equal(VECTOR_SIZE(waiter->events), 0);
+	assert_ptr_equal(find_dmevents("foo"), NULL);
+	assert_ptr_equal(find_dmevents("bar"), NULL);
+}
+
+static void test_get_events_bad0(void **state)
+{
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		skip();
+
+	unwatch_all_dmevents();
+	remove_all_dm_device_events();
+
+	will_return(__wrap_libmp_dm_task_create, NULL);
+	assert_int_equal(dm_get_events(), -1);
+}
+
+static void test_get_events_bad1(void **state)
+{
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		skip();
+
+	will_return(__wrap_libmp_dm_task_create, &data);
+	will_return(__wrap_dm_task_no_open_count, 1);
+	will_return(__wrap_dm_task_run, 0);
+	assert_int_equal(dm_get_events(), -1);
+}
+
+static void test_get_events_bad2(void **state)
+{
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		skip();
+
+	will_return(__wrap_libmp_dm_task_create, &data);
+	will_return(__wrap_dm_task_no_open_count, 1);
+	will_return(__wrap_dm_task_run, 1);
+	will_return(__wrap_dm_task_get_names, 0);
+	assert_int_equal(dm_get_events(), -1);
+}
+
+static void test_get_events_good0(void **state)
+{
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		skip();
+
+	assert_int_equal(add_dm_device_event("foo", 1, 5), 0);
+	will_return(__wrap_libmp_dm_task_create, &data);
+	will_return(__wrap_dm_task_no_open_count, 1);
+	will_return(__wrap_dm_task_run, 1);
+	will_return(__wrap_dm_task_get_names, 1);
+	assert_int_equal(dm_get_events(), 0);
+	assert_ptr_equal(find_dmevents("foo"), NULL);
+	assert_int_equal(VECTOR_SIZE(waiter->events), 0);
+}
+
+static void test_get_events_good1(void **state)
+{
+	struct dev_event *dev_evt;
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		skip();
+
+	remove_all_dm_device_events();
+	assert_int_equal(add_dm_device_event("foo", 1, 5), 0);
+	assert_int_equal(add_dm_device_event("bar", 1, 7), 0);
+	assert_int_equal(add_dm_device_event("baz", 1, 12), 0);
+	assert_int_equal(add_dm_device_event("qux", 0, 4), 0);
+	assert_int_equal(add_dm_device_event("xyzzy", 1, 8), 0);
+	will_return(__wrap_dm_geteventnr, 0);
+	assert_int_equal(watch_dmevents("foo"), 0);
+	will_return(__wrap_dm_geteventnr, 0);
+	assert_int_equal(watch_dmevents("bar"), 0);
+	will_return(__wrap_dm_geteventnr, 0);
+	assert_int_equal(watch_dmevents("xyzzy"), 0);
+	assert_int_equal(add_dm_device_event("foo", 1, 6), 0);
+	assert_int_equal(remove_dm_device_event("xyzzy"), 0);
+	will_return(__wrap_libmp_dm_task_create, &data);
+	will_return(__wrap_dm_task_no_open_count, 1);
+	will_return(__wrap_dm_task_run, 1);
+	will_return(__wrap_dm_task_get_names, 1);
+	assert_int_equal(dm_get_events(), 0);
+	dev_evt = find_dmevents("foo");
+	assert_ptr_not_equal(dev_evt, NULL);
+	assert_int_equal(dev_evt->evt_nr, 6);
+	assert_int_equal(dev_evt->action, EVENT_UPDATE);
+	dev_evt = find_dmevents("bar");
+	assert_ptr_not_equal(dev_evt, NULL);
+	assert_int_equal(dev_evt->evt_nr, 7);
+	assert_int_equal(dev_evt->action, EVENT_NOTHING);
+	dev_evt = find_dmevents("xyzzy");
+	assert_ptr_not_equal(dev_evt, NULL);
+	assert_int_equal(dev_evt->evt_nr, 8);
+	assert_int_equal(dev_evt->action, EVENT_REMOVE);
+	assert_ptr_equal(find_dmevents("baz"), NULL);
+	assert_ptr_equal(find_dmevents("qux"), NULL);
+	assert_int_equal(VECTOR_SIZE(waiter->events), 3);
+}
+
+static void test_dmevent_loop_bad0(void **state)
+{
+	struct dm_device *dev;
+	struct dev_event *dev_evt;
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		skip();
+
+	remove_all_dm_device_events();
+	unwatch_all_dmevents();
+	assert_int_equal(add_dm_device_event("foo", 1, 5), 0);
+	will_return(__wrap_dm_geteventnr, 0);
+	assert_int_equal(watch_dmevents("foo"), 0);
+	assert_int_equal(add_dm_device_event("foo", 1, 6), 0);
+	will_return(__wrap_poll, 0);
+	assert_int_equal(dmevent_loop(), 1);
+	dev_evt = find_dmevents("foo");
+	assert_ptr_not_equal(dev_evt, NULL);
+	assert_int_equal(dev_evt->evt_nr, 5);
+	assert_int_equal(dev_evt->action, EVENT_NOTHING);
+	dev = find_dm_device("foo");
+	assert_ptr_not_equal(dev, NULL);
+	assert_int_equal(dev->evt_nr, 6);
+	assert_int_equal(dev->update_nr, 5);
+}
+
+static void test_dmevent_loop_bad1(void **state)
+{
+	struct dm_device *dev;
+	struct dev_event *dev_evt;
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		skip();
+
+	will_return(__wrap_poll, 1);
+	will_return(__wrap_ioctl, -1);
+	assert_int_equal(dmevent_loop(), 1);
+	dev_evt = find_dmevents("foo");
+	assert_ptr_not_equal(dev_evt, NULL);
+	assert_int_equal(dev_evt->evt_nr, 5);
+	assert_int_equal(dev_evt->action, EVENT_NOTHING);
+	dev = find_dm_device("foo");
+	assert_ptr_not_equal(dev, NULL);
+	assert_int_equal(dev->evt_nr, 6);
+	assert_int_equal(dev->update_nr, 5);
+}
+
+static void test_dmevent_loop_bad2(void **state)
+{
+	struct dm_device *dev;
+	struct dev_event *dev_evt;
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		skip();
+
+	will_return(__wrap_poll, 1);
+	will_return(__wrap_ioctl, 0);
+	will_return(__wrap_libmp_dm_task_create, NULL);
+	assert_int_equal(dmevent_loop(), 1);
+	dev_evt = find_dmevents("foo");
+	assert_ptr_not_equal(dev_evt, NULL);
+	assert_int_equal(dev_evt->evt_nr, 5);
+	assert_int_equal(dev_evt->action, EVENT_NOTHING);
+	dev = find_dm_device("foo");
+	assert_ptr_not_equal(dev, NULL);
+	assert_int_equal(dev->evt_nr, 6);
+	assert_int_equal(dev->update_nr, 5);
+}
+
+static void test_dmevent_loop_good0(void **state)
+{
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		skip();
+
+	remove_all_dm_device_events();
+	unwatch_all_dmevents();
+	will_return(__wrap_poll, 1);
+	will_return(__wrap_ioctl, 0);
+	will_return(__wrap_libmp_dm_task_create, &data);
+	will_return(__wrap_dm_task_no_open_count, 1);
+	will_return(__wrap_dm_task_run, 1);
+	will_return(__wrap_dm_task_get_names, 1);
+	assert_int_equal(dmevent_loop(), 1);
+}
+
+static void test_dmevent_loop_good1(void **state)
+{
+	struct dm_device *dev;
+	struct dev_event *dev_evt;
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		skip();
+
+	remove_all_dm_device_events();
+	unwatch_all_dmevents();
+	assert_int_equal(add_dm_device_event("foo", 1, 5), 0);
+	assert_int_equal(add_dm_device_event("bar", 1, 7), 0);
+	assert_int_equal(add_dm_device_event("baz", 1, 12), 0);
+	assert_int_equal(add_dm_device_event("xyzzy", 1, 8), 0);
+	will_return(__wrap_dm_geteventnr, 0);
+	assert_int_equal(watch_dmevents("foo"), 0);
+	will_return(__wrap_dm_geteventnr, 0);
+	assert_int_equal(watch_dmevents("bar"), 0);
+	will_return(__wrap_dm_geteventnr, 0);
+	assert_int_equal(watch_dmevents("xyzzy"), 0);
+	assert_int_equal(add_dm_device_event("foo", 1, 6), 0);
+	assert_int_equal(remove_dm_device_event("xyzzy"), 0);
+	will_return(__wrap_poll, 1);
+	will_return(__wrap_ioctl, 0);
+	will_return(__wrap_libmp_dm_task_create, &data);
+	will_return(__wrap_dm_task_no_open_count, 1);
+	will_return(__wrap_dm_task_run, 1);
+	will_return(__wrap_dm_task_get_names, 1);
+	expect_string(__wrap_update_multipath, mapname, "foo");
+	will_return(__wrap_update_multipath, 0);
+	expect_string(__wrap_remove_map_by_alias, alias, "xyzzy");
+	assert_int_equal(dmevent_loop(), 1);
+	assert_int_equal(VECTOR_SIZE(waiter->events), 2);
+	assert_int_equal(VECTOR_SIZE(data.dm_devices), 3);
+	dev_evt = find_dmevents("foo");
+	assert_ptr_not_equal(dev_evt, NULL);
+	assert_int_equal(dev_evt->evt_nr, 6);
+	assert_int_equal(dev_evt->action, EVENT_NOTHING);
+	dev = find_dm_device("foo");
+	assert_ptr_not_equal(dev, NULL);
+	assert_int_equal(dev->evt_nr, 6);
+	assert_int_equal(dev->update_nr, 6);
+	dev_evt = find_dmevents("bar");
+	assert_ptr_not_equal(dev_evt, NULL);
+	assert_int_equal(dev_evt->evt_nr, 7);
+	assert_int_equal(dev_evt->action, EVENT_NOTHING);
+	dev = find_dm_device("bar");
+	assert_ptr_not_equal(dev, NULL);
+	assert_int_equal(dev->evt_nr, 7);
+	assert_int_equal(dev->update_nr, 7);
+	assert_ptr_equal(find_dmevents("xyzzy"), NULL);
+	assert_ptr_equal(find_dm_device("xyzzy"), NULL);
+}
+
+static void test_dmevent_loop_good2(void **state)
+{
+	struct dm_device *dev;
+	struct dev_event *dev_evt;
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		skip();
+
+	assert_int_equal(add_dm_device_event("bar", 1, 9), 0);
+	will_return(__wrap_dm_geteventnr, 0);
+	assert_int_equal(watch_dmevents("baz"), 0);
+	assert_int_equal(add_dm_device_event("baz", 1, 14), 0);
+	will_return(__wrap_poll, 1);
+	will_return(__wrap_ioctl, 0);
+	will_return(__wrap_libmp_dm_task_create, &data);
+	will_return(__wrap_dm_task_no_open_count, 1);
+	will_return(__wrap_dm_task_run, 1);
+	will_return(__wrap_dm_task_get_names, 1);
+	expect_string(__wrap_update_multipath, mapname, "bar");
+	will_return(__wrap_update_multipath, 0);
+	expect_string(__wrap_update_multipath, mapname, "baz");
+	will_return(__wrap_update_multipath, 1);
+	assert_int_equal(dmevent_loop(), 1);
+	assert_int_equal(VECTOR_SIZE(waiter->events), 2);
+	assert_int_equal(VECTOR_SIZE(data.dm_devices), 2);
+	dev_evt = find_dmevents("foo");
+	assert_ptr_not_equal(dev_evt, NULL);
+	assert_int_equal(dev_evt->evt_nr, 6);
+	assert_int_equal(dev_evt->action, EVENT_NOTHING);
+	dev = find_dm_device("foo");
+	assert_ptr_not_equal(dev, NULL);
+	assert_int_equal(dev->evt_nr, 6);
+	assert_int_equal(dev->update_nr, 6);
+	dev_evt = find_dmevents("bar");
+	assert_ptr_not_equal(dev_evt, NULL);
+	assert_int_equal(dev_evt->evt_nr, 9);
+	assert_int_equal(dev_evt->action, EVENT_NOTHING);
+	dev = find_dm_device("bar");
+	assert_ptr_not_equal(dev, NULL);
+	assert_int_equal(dev->evt_nr, 9);
+	assert_int_equal(dev->update_nr, 9);
+	assert_ptr_equal(find_dmevents("baz"), NULL);
+	assert_ptr_equal(find_dm_device("baz"), NULL);
+}
+
+static void test_dmevent_loop_good3(void **state)
+{
+	struct dm_device *dev;
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		skip();
+
+	assert_int_equal(remove_dm_device_event("foo"), 0);
+	unwatch_dmevents("bar");
+	will_return(__wrap_poll, 1);
+	will_return(__wrap_ioctl, 0);
+	will_return(__wrap_libmp_dm_task_create, &data);
+	will_return(__wrap_dm_task_no_open_count, 1);
+	will_return(__wrap_dm_task_run, 1);
+	will_return(__wrap_dm_task_get_names, 1);
+	expect_string(__wrap_remove_map_by_alias, alias, "foo");
+	assert_int_equal(dmevent_loop(), 1);
+	assert_int_equal(VECTOR_SIZE(waiter->events), 0);
+	assert_int_equal(VECTOR_SIZE(data.dm_devices), 1);
+	dev = find_dm_device("bar");
+	assert_ptr_not_equal(dev, NULL);
+	assert_int_equal(dev->evt_nr, 9);
+	assert_int_equal(dev->update_nr, 9);
+	assert_ptr_equal(find_dmevents("foo"), NULL);
+	assert_ptr_equal(find_dmevents("bar"), NULL);
+	assert_ptr_equal(find_dm_device("foo"), NULL);
+}
+
+static void test_arm_poll(void **state)
+{
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		skip();
+	will_return(__wrap_ioctl, 0);
+	assert_int_equal(arm_dm_event_poll(waiter->fd), 0);
+}
+
+static void test_cleanup_waiter(void **state)
+{
+	struct test_data *datap = (struct test_data *)(*state);
+	if (datap == NULL)
+		skip();
+	cleanup_dmevent_waiter();
+	assert_ptr_equal(waiter, NULL);
+}
+
+int test_dmevents(void)
+{
+	const struct CMUnitTest tests[] = {
+		cmocka_unit_test(test_init_waiter_bad0),
+		cmocka_unit_test(test_init_waiter_bad1),
+		cmocka_unit_test(test_init_waiter_good0),
+		cmocka_unit_test(test_watch_dmevents_bad0),
+		cmocka_unit_test(test_watch_dmevents_bad1),
+		cmocka_unit_test(test_watch_dmevents_bad2),
+		cmocka_unit_test(test_watch_dmevents_good0),
+		cmocka_unit_test(test_watch_dmevents_good1),
+		cmocka_unit_test(test_watch_dmevents_good2),
+		cmocka_unit_test(test_get_events_bad0),
+		cmocka_unit_test(test_get_events_bad1),
+		cmocka_unit_test(test_get_events_bad2),
+		cmocka_unit_test(test_get_events_good0),
+		cmocka_unit_test(test_get_events_good1),
+		cmocka_unit_test(test_arm_poll),
+		cmocka_unit_test(test_dmevent_loop_bad0),
+		cmocka_unit_test(test_dmevent_loop_bad1),
+		cmocka_unit_test(test_dmevent_loop_bad2),
+		cmocka_unit_test(test_dmevent_loop_good0),
+		cmocka_unit_test(test_dmevent_loop_good1),
+		cmocka_unit_test(test_dmevent_loop_good2),
+		cmocka_unit_test(test_dmevent_loop_good3),
+		cmocka_unit_test(test_cleanup_waiter),
+	};
+	return cmocka_run_group_tests(tests, setup, teardown);
+}
+
+int main(void)
+{
+	int ret = 0;
+
+	ret += test_dmevents();
+	return ret;
+}
-- 
2.7.4

  parent reply	other threads:[~2018-03-14 17:46 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-03-14 17:46 [PATCH 00/12] multipath: new and rebased patches Benjamin Marzinski
2018-03-14 17:46 ` [PATCH 01/12] Unit tests for basenamecpy Benjamin Marzinski
2018-03-19  9:49   ` Martin Wilck
2018-03-19 10:05     ` Martin Wilck
2018-03-14 17:46 ` [PATCH 02/12] libmultipath: fix basenamecpy Benjamin Marzinski
2018-03-14 17:46 ` [PATCH 03/12] libmultipath: set dm_conf_verbosity Benjamin Marzinski
2018-03-19 10:18   ` Martin Wilck
2018-03-14 17:46 ` [PATCH 04/12] multipathd: log thread cleanup Benjamin Marzinski
2018-03-19 10:20   ` Martin Wilck
2018-03-14 17:46 ` [PATCH 05/12] libmultipath: fix log_pthread processing Benjamin Marzinski
2018-03-19 10:22   ` Martin Wilck
2018-03-14 17:46 ` [PATCH 06/12] multipathd: use nanosleep for strict timing Benjamin Marzinski
2018-03-19 10:50   ` Martin Wilck
2018-03-14 17:46 ` [PATCH 07/12] libmultipath: move remove_map waiter code to multipathd Benjamin Marzinski
2018-03-19 10:57   ` Martin Wilck
2018-03-14 17:46 ` [PATCH 08/12] move waiter code from libmultipath " Benjamin Marzinski
2018-03-14 17:46 ` [PATCH 09/12] call start_waiter_thread() before setup_multipath() Benjamin Marzinski
2018-03-14 17:46 ` [PATCH 10/12] libmultipath: add helper functions Benjamin Marzinski
2018-03-14 17:46 ` [PATCH 11/12] multipathd: add new polling dmevents waiter thread Benjamin Marzinski
2018-03-19 12:48   ` Martin Wilck
2018-03-14 17:46 ` Benjamin Marzinski [this message]
2018-03-19 12:01   ` [PATCH 12/12] multipath: add unit tests for dmevents code Martin Wilck
2018-03-15 14:30 ` [PATCH 00/12] multipath: new and rebased patches Benjamin Marzinski

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=1521049605-22050-13-git-send-email-bmarzins@redhat.com \
    --to=bmarzins@redhat.com \
    --cc=christophe.varoqui@free.fr \
    --cc=dm-devel@redhat.com \
    --cc=mwilck@suse.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.