2 * Copyright (c) 2018 Benjamin Marzinski, Redhat
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
26 #include <sys/types.h>
30 #include "structs_vec.h"
33 /* I have to do this to get at the static variables */
34 #include "../multipathd/dmevents.c"
36 /* pretend dm device */
39 /* is this a mpath device, or other dm device */
42 /* tracks the event number when the multipath device was updated */
49 struct dm_names *names;
52 struct test_data data;
54 /* Add a pretend dm device, or update its event number. This is used to build
55 * up the dm devices that the dmevents code queries with dm_task_get_names,
56 * dm_geteventnr, and dm_is_mpath */
57 int add_dm_device_event(char *name, int is_mpath, uint32_t evt_nr)
59 struct dm_device *dev;
62 vector_foreach_slot(data.dm_devices, dev, i) {
63 if (strcmp(name, dev->name) == 0) {
68 dev = (struct dm_device *)malloc(sizeof(struct dm_device));
70 condlog(0, "Testing error mallocing dm_device");
73 strncpy(dev->name, name, WWID_SIZE);
74 dev->name[WWID_SIZE - 1] = 0;
75 dev->is_mpath = is_mpath;
77 if (!vector_alloc_slot(data.dm_devices)) {
78 condlog(0, "Testing error setting dm_devices slot");
82 vector_set_slot(data.dm_devices, dev);
86 /* helper function for pretend dm devices */
87 struct dm_device *find_dm_device(const char *name)
89 struct dm_device *dev;
92 vector_foreach_slot(data.dm_devices, dev, i)
93 if (strcmp(name, dev->name) == 0)
98 /* helper function for pretend dm devices */
99 int remove_dm_device_event(const char *name)
101 struct dm_device *dev;
104 vector_foreach_slot(data.dm_devices, dev, i) {
105 if (strcmp(name, dev->name) == 0) {
106 vector_del_slot(data.dm_devices, i);
114 /* helper function for pretend dm devices */
115 void remove_all_dm_device_events(void)
117 struct dm_device *dev;
120 vector_foreach_slot(data.dm_devices, dev, i)
122 vector_reset(data.dm_devices);
125 static inline size_t align_val(size_t val)
127 return (val + 7) & ~7;
129 static inline void *align_ptr(void *ptr)
131 return (void *)align_val((size_t)ptr);
134 /* copied off of list_devices in dm-ioctl.c except that it uses
135 * the pretend dm devices, and saves the output to the test_data
137 struct dm_names *build_dm_names(void)
139 struct dm_names *names, *np, *old_np = NULL;
141 struct dm_device *dev;
144 if (VECTOR_SIZE(data.dm_devices) == 0) {
145 names = (struct dm_names *)malloc(sizeof(struct dm_names));
147 condlog(0, "Testing error allocating empty dm_names");
154 vector_foreach_slot(data.dm_devices, dev, i) {
155 size += align_val(offsetof(struct dm_names, name) +
156 strlen(dev->name) + 1);
157 size += align_val(sizeof(uint32_t));
159 names = (struct dm_names *)malloc(size);
161 condlog(0, "Testing error allocating dm_names");
165 vector_foreach_slot(data.dm_devices, dev, i) {
167 old_np->next = (uint32_t) ((uintptr_t) np -
171 strcpy(np->name, dev->name);
174 event_nr = align_ptr(np->name + strlen(dev->name) + 1);
175 *event_nr = dev->evt_nr;
176 np = align_ptr(event_nr + 1);
178 assert_int_equal((char *)np - (char *)names, size);
182 static int setup(void **state)
184 if (dmevent_poll_supported()) {
185 data.dm_devices = vector_alloc();
192 static int teardown(void **state)
194 struct dm_device *dev;
196 struct test_data *datap = (struct test_data *)(*state);
199 vector_foreach_slot(datap->dm_devices, dev, i)
201 vector_free(datap->dm_devices);
206 int __wrap_open(const char *pathname, int flags)
208 assert_ptr_equal(pathname, "/dev/mapper/control");
209 assert_int_equal(flags, O_RDWR);
210 return mock_type(int);
213 /* We never check the result of the close(), so there's no need to
214 * to mock a return value */
215 int __wrap_close(int fd)
217 assert_int_equal(fd, waiter->fd);
221 /* the pretend dm device code checks the input and supplies the
222 * return value, so there's no need to do that here */
223 int __wrap_dm_is_mpath(const char *name)
225 struct dm_device *dev;
228 vector_foreach_slot(data.dm_devices, dev, i)
229 if (strcmp(name, dev->name) == 0)
230 return dev->is_mpath;
234 /* either get return info from the pretend dm device, or
235 * override it to test -1 return */
236 int __wrap_dm_geteventnr(const char *name)
238 struct dm_device *dev;
239 int fail = mock_type(int);
243 dev = find_dm_device(name);
245 /* simulate updating device state after adding it */
246 dev->update_nr = dev->evt_nr;
252 int __wrap_ioctl(int fd, unsigned long request, void *argp)
254 assert_int_equal(fd, waiter->fd);
255 assert_int_equal(request, DM_DEV_ARM_POLL);
256 return mock_type(int);
259 struct dm_task *__wrap_libmp_dm_task_create(int task)
261 assert_int_equal(task, DM_DEVICE_LIST);
262 return mock_type(struct dm_task *);
265 int __wrap_dm_task_no_open_count(struct dm_task *dmt)
267 assert_ptr_equal((struct test_data *)dmt, &data);
268 return mock_type(int);
271 int __wrap_dm_task_run(struct dm_task *dmt)
273 assert_ptr_equal((struct test_data *)dmt, &data);
274 return mock_type(int);
277 /* either get return info from the pretend dm device, or
278 * override it to test NULL return */
279 struct dm_names * __wrap_dm_task_get_names(struct dm_task *dmt)
281 int good = mock_type(int);
282 assert_ptr_equal((struct test_data *)dmt, &data);
285 condlog(0, "Testing error. data.names already allocated");
290 data.names = build_dm_names();
294 void __wrap_dm_task_destroy(struct dm_task *dmt)
296 assert_ptr_equal((struct test_data *)dmt, &data);
304 int __wrap_poll(struct pollfd *fds, nfds_t nfds, int timeout)
306 assert_int_equal(nfds, 1);
307 assert_int_equal(timeout, -1);
308 assert_int_equal(fds->fd, waiter->fd);
309 assert_int_equal(fds->events, POLLIN);
310 return mock_type(int);
313 void __wrap_remove_map_by_alias(const char *alias, struct vectors * vecs,
316 check_expected(alias);
317 assert_ptr_equal(vecs, waiter->vecs);
318 assert_int_equal(purge_vec, 1);
321 /* pretend update the pretend dm devices. If fail is set, it
322 * simulates having the dm device removed. Otherwise it just sets
323 * update_nr to record when the update happened */
324 int __wrap_update_multipath(struct vectors *vecs, char *mapname, int reset)
328 check_expected(mapname);
329 assert_ptr_equal(vecs, waiter->vecs);
330 assert_int_equal(reset, 1);
331 fail = mock_type(int);
333 assert_int_equal(remove_dm_device_event(mapname), 0);
336 struct dm_device *dev;
339 vector_foreach_slot(data.dm_devices, dev, i) {
340 if (strcmp(mapname, dev->name) == 0) {
341 dev->update_nr = dev->evt_nr;
350 /* helper function used to check if the dmevents list of devices
351 * includes a specific device. To make sure that dmevents is
352 * in the correct state after running a function */
353 struct dev_event *find_dmevents(const char *name)
355 struct dev_event *dev_evt;
358 vector_foreach_slot(waiter->events, dev_evt, i)
359 if (!strcmp(dev_evt->name, name))
364 /* null vecs pointer when initialized dmevents */
365 static void test_init_waiter_bad0(void **state)
367 /* this boilerplate code just skips the test if
368 * dmevents polling is not supported */
369 struct test_data *datap = (struct test_data *)(*state);
373 assert_int_equal(init_dmevent_waiter(NULL), -1);
376 /* fail to open /dev/mapper/control */
377 static void test_init_waiter_bad1(void **state)
379 struct test_data *datap = (struct test_data *)(*state);
382 will_return(__wrap_open, -1);
383 assert_int_equal(init_dmevent_waiter(&datap->vecs), -1);
384 assert_ptr_equal(waiter, NULL);
387 /* waiter remains initialized after this test */
388 static void test_init_waiter_good0(void **state)
390 struct test_data *datap = (struct test_data *)(*state);
393 will_return(__wrap_open, 2);
394 assert_int_equal(init_dmevent_waiter(&datap->vecs), 0);
395 assert_ptr_not_equal(waiter, NULL);
398 /* No dm device named foo */
399 static void test_watch_dmevents_bad0(void **state)
401 struct test_data *datap = (struct test_data *)(*state);
404 assert_int_equal(watch_dmevents("foo"), -1);
405 assert_ptr_equal(find_dmevents("foo"), NULL);
408 /* foo is not a multipath device */
409 static void test_watch_dmevents_bad1(void **state)
411 struct test_data *datap = (struct test_data *)(*state);
415 assert_int_equal(add_dm_device_event("foo", 0, 5), 0);
416 assert_int_equal(watch_dmevents("foo"), -1);
417 assert_ptr_equal(find_dmevents("foo"), NULL);
420 /* failed getting the dmevent number */
421 static void test_watch_dmevents_bad2(void **state)
423 struct test_data *datap = (struct test_data *)(*state);
427 remove_all_dm_device_events();
428 assert_int_equal(add_dm_device_event("foo", 1, 5), 0);
429 will_return(__wrap_dm_geteventnr, -1);
430 assert_int_equal(watch_dmevents("foo"), -1);
431 assert_ptr_equal(find_dmevents("foo"), NULL);
434 /* verify that you can watch and unwatch dm multipath device "foo" */
435 static void test_watch_dmevents_good0(void **state)
437 struct dev_event *dev_evt;
438 struct test_data *datap = (struct test_data *)(*state);
442 remove_all_dm_device_events();
443 assert_int_equal(add_dm_device_event("foo", 1, 5), 0);
444 will_return(__wrap_dm_geteventnr, 0);
445 assert_int_equal(watch_dmevents("foo"), 0);
446 /* verify foo is being watched */
447 dev_evt = find_dmevents("foo");
448 assert_ptr_not_equal(dev_evt, NULL);
449 assert_int_equal(dev_evt->evt_nr, 5);
450 assert_int_equal(dev_evt->action, EVENT_NOTHING);
451 assert_int_equal(VECTOR_SIZE(waiter->events), 1);
452 unwatch_dmevents("foo");
453 /* verify foo is no longer being watched */
454 assert_int_equal(VECTOR_SIZE(waiter->events), 0);
455 assert_ptr_equal(find_dmevents("foo"), NULL);
458 /* verify that if you try to watch foo multiple times, it only
459 * is placed on the waiter list once */
460 static void test_watch_dmevents_good1(void **state)
462 struct dev_event *dev_evt;
463 struct test_data *datap = (struct test_data *)(*state);
467 remove_all_dm_device_events();
468 assert_int_equal(add_dm_device_event("foo", 1, 5), 0);
469 will_return(__wrap_dm_geteventnr, 0);
470 assert_int_equal(watch_dmevents("foo"), 0);
471 dev_evt = find_dmevents("foo");
472 assert_ptr_not_equal(dev_evt, NULL);
473 assert_int_equal(dev_evt->evt_nr, 5);
474 assert_int_equal(dev_evt->action, EVENT_NOTHING);
475 assert_int_equal(add_dm_device_event("foo", 1, 6), 0);
476 will_return(__wrap_dm_geteventnr, 0);
477 assert_int_equal(watch_dmevents("foo"), 0);
478 dev_evt = find_dmevents("foo");
479 assert_ptr_not_equal(dev_evt, NULL);
480 assert_int_equal(dev_evt->evt_nr, 6);
481 assert_int_equal(dev_evt->action, EVENT_NOTHING);
482 assert_int_equal(VECTOR_SIZE(waiter->events), 1);
483 unwatch_dmevents("foo");
484 assert_int_equal(VECTOR_SIZE(waiter->events), 0);
485 assert_ptr_equal(find_dmevents("foo"), NULL);
488 /* watch and then unwatch multiple devices */
489 static void test_watch_dmevents_good2(void **state)
491 struct dev_event *dev_evt;
492 struct test_data *datap = (struct test_data *)(*state);
496 unwatch_all_dmevents();
497 remove_all_dm_device_events();
498 assert_int_equal(add_dm_device_event("foo", 1, 5), 0);
499 assert_int_equal(add_dm_device_event("bar", 1, 7), 0);
500 will_return(__wrap_dm_geteventnr, 0);
501 assert_int_equal(watch_dmevents("foo"), 0);
502 dev_evt = find_dmevents("foo");
503 assert_ptr_not_equal(dev_evt, NULL);
504 assert_int_equal(dev_evt->evt_nr, 5);
505 assert_int_equal(dev_evt->action, EVENT_NOTHING);
506 assert_ptr_equal(find_dmevents("bar"), NULL);
507 will_return(__wrap_dm_geteventnr, 0);
508 assert_int_equal(watch_dmevents("bar"), 0);
509 dev_evt = find_dmevents("foo");
510 assert_ptr_not_equal(dev_evt, NULL);
511 assert_int_equal(dev_evt->evt_nr, 5);
512 assert_int_equal(dev_evt->action, EVENT_NOTHING);
513 dev_evt = find_dmevents("bar");
514 assert_ptr_not_equal(dev_evt, NULL);
515 assert_int_equal(dev_evt->evt_nr, 7);
516 assert_int_equal(dev_evt->action, EVENT_NOTHING);
517 assert_int_equal(VECTOR_SIZE(waiter->events), 2);
518 unwatch_all_dmevents();
519 assert_int_equal(VECTOR_SIZE(waiter->events), 0);
520 assert_ptr_equal(find_dmevents("foo"), NULL);
521 assert_ptr_equal(find_dmevents("bar"), NULL);
524 /* dm_task_create fails */
525 static void test_get_events_bad0(void **state)
527 struct test_data *datap = (struct test_data *)(*state);
531 unwatch_all_dmevents();
532 remove_all_dm_device_events();
534 will_return(__wrap_libmp_dm_task_create, NULL);
535 assert_int_equal(dm_get_events(), -1);
538 /* dm_task_run fails */
539 static void test_get_events_bad1(void **state)
541 struct test_data *datap = (struct test_data *)(*state);
545 will_return(__wrap_libmp_dm_task_create, &data);
546 will_return(__wrap_dm_task_no_open_count, 1);
547 will_return(__wrap_dm_task_run, 0);
548 assert_int_equal(dm_get_events(), -1);
551 /* dm_task_get_names fails */
552 static void test_get_events_bad2(void **state)
554 struct test_data *datap = (struct test_data *)(*state);
558 will_return(__wrap_libmp_dm_task_create, &data);
559 will_return(__wrap_dm_task_no_open_count, 1);
560 will_return(__wrap_dm_task_run, 1);
561 will_return(__wrap_dm_task_get_names, 0);
562 assert_int_equal(dm_get_events(), -1);
565 /* If the device isn't being watched, dm_get_events returns NULL */
566 static void test_get_events_good0(void **state)
568 struct test_data *datap = (struct test_data *)(*state);
572 assert_int_equal(add_dm_device_event("foo", 1, 5), 0);
573 will_return(__wrap_libmp_dm_task_create, &data);
574 will_return(__wrap_dm_task_no_open_count, 1);
575 will_return(__wrap_dm_task_run, 1);
576 will_return(__wrap_dm_task_get_names, 1);
577 assert_int_equal(dm_get_events(), 0);
578 assert_ptr_equal(find_dmevents("foo"), NULL);
579 assert_int_equal(VECTOR_SIZE(waiter->events), 0);
582 /* There are 5 dm devices. 4 of them are multipath devices.
583 * Only 3 of them are being watched. "foo" has a new event
584 * "xyzzy" gets removed. Nothing happens to bar. Verify
585 * that all the events are properly set, and that nothing
586 * happens with the two devices that aren't being watched */
587 static void test_get_events_good1(void **state)
589 struct dev_event *dev_evt;
590 struct test_data *datap = (struct test_data *)(*state);
594 remove_all_dm_device_events();
595 assert_int_equal(add_dm_device_event("foo", 1, 5), 0);
596 assert_int_equal(add_dm_device_event("bar", 1, 7), 0);
597 assert_int_equal(add_dm_device_event("baz", 1, 12), 0);
598 assert_int_equal(add_dm_device_event("qux", 0, 4), 0);
599 assert_int_equal(add_dm_device_event("xyzzy", 1, 8), 0);
600 will_return(__wrap_dm_geteventnr, 0);
601 assert_int_equal(watch_dmevents("foo"), 0);
602 will_return(__wrap_dm_geteventnr, 0);
603 assert_int_equal(watch_dmevents("bar"), 0);
604 will_return(__wrap_dm_geteventnr, 0);
605 assert_int_equal(watch_dmevents("xyzzy"), 0);
606 assert_int_equal(add_dm_device_event("foo", 1, 6), 0);
607 assert_int_equal(remove_dm_device_event("xyzzy"), 0);
608 will_return(__wrap_libmp_dm_task_create, &data);
609 will_return(__wrap_dm_task_no_open_count, 1);
610 will_return(__wrap_dm_task_run, 1);
611 will_return(__wrap_dm_task_get_names, 1);
612 assert_int_equal(dm_get_events(), 0);
613 dev_evt = find_dmevents("foo");
614 assert_ptr_not_equal(dev_evt, NULL);
615 assert_int_equal(dev_evt->evt_nr, 6);
616 assert_int_equal(dev_evt->action, EVENT_UPDATE);
617 dev_evt = find_dmevents("bar");
618 assert_ptr_not_equal(dev_evt, NULL);
619 assert_int_equal(dev_evt->evt_nr, 7);
620 assert_int_equal(dev_evt->action, EVENT_NOTHING);
621 dev_evt = find_dmevents("xyzzy");
622 assert_ptr_not_equal(dev_evt, NULL);
623 assert_int_equal(dev_evt->evt_nr, 8);
624 assert_int_equal(dev_evt->action, EVENT_REMOVE);
625 assert_ptr_equal(find_dmevents("baz"), NULL);
626 assert_ptr_equal(find_dmevents("qux"), NULL);
627 assert_int_equal(VECTOR_SIZE(waiter->events), 3);
630 /* poll does not return an event. nothing happens. The
631 * devices remain after this test */
632 static void test_dmevent_loop_bad0(void **state)
634 struct dm_device *dev;
635 struct dev_event *dev_evt;
636 struct test_data *datap = (struct test_data *)(*state);
640 remove_all_dm_device_events();
641 unwatch_all_dmevents();
642 assert_int_equal(add_dm_device_event("foo", 1, 5), 0);
643 will_return(__wrap_dm_geteventnr, 0);
644 assert_int_equal(watch_dmevents("foo"), 0);
645 assert_int_equal(add_dm_device_event("foo", 1, 6), 0);
646 will_return(__wrap_poll, 0);
647 assert_int_equal(dmevent_loop(), 1);
648 dev_evt = find_dmevents("foo");
649 assert_ptr_not_equal(dev_evt, NULL);
650 assert_int_equal(dev_evt->evt_nr, 5);
651 assert_int_equal(dev_evt->action, EVENT_NOTHING);
652 dev = find_dm_device("foo");
653 assert_ptr_not_equal(dev, NULL);
654 assert_int_equal(dev->evt_nr, 6);
655 assert_int_equal(dev->update_nr, 5);
658 /* arm_dm_event_poll's ioctl fails. Nothing happens */
659 static void test_dmevent_loop_bad1(void **state)
661 struct dm_device *dev;
662 struct dev_event *dev_evt;
663 struct test_data *datap = (struct test_data *)(*state);
667 will_return(__wrap_poll, 1);
668 will_return(__wrap_ioctl, -1);
669 assert_int_equal(dmevent_loop(), 1);
670 dev_evt = find_dmevents("foo");
671 assert_ptr_not_equal(dev_evt, NULL);
672 assert_int_equal(dev_evt->evt_nr, 5);
673 assert_int_equal(dev_evt->action, EVENT_NOTHING);
674 dev = find_dm_device("foo");
675 assert_ptr_not_equal(dev, NULL);
676 assert_int_equal(dev->evt_nr, 6);
677 assert_int_equal(dev->update_nr, 5);
680 /* dm_get_events fails. Nothing happens */
681 static void test_dmevent_loop_bad2(void **state)
683 struct dm_device *dev;
684 struct dev_event *dev_evt;
685 struct test_data *datap = (struct test_data *)(*state);
689 will_return(__wrap_poll, 1);
690 will_return(__wrap_ioctl, 0);
691 will_return(__wrap_libmp_dm_task_create, NULL);
692 assert_int_equal(dmevent_loop(), 1);
693 dev_evt = find_dmevents("foo");
694 assert_ptr_not_equal(dev_evt, NULL);
695 assert_int_equal(dev_evt->evt_nr, 5);
696 assert_int_equal(dev_evt->action, EVENT_NOTHING);
697 dev = find_dm_device("foo");
698 assert_ptr_not_equal(dev, NULL);
699 assert_int_equal(dev->evt_nr, 6);
700 assert_int_equal(dev->update_nr, 5);
703 /* verify dmevent_loop runs successfully when no devices are being
705 static void test_dmevent_loop_good0(void **state)
707 struct test_data *datap = (struct test_data *)(*state);
711 remove_all_dm_device_events();
712 unwatch_all_dmevents();
713 will_return(__wrap_poll, 1);
714 will_return(__wrap_ioctl, 0);
715 will_return(__wrap_libmp_dm_task_create, &data);
716 will_return(__wrap_dm_task_no_open_count, 1);
717 will_return(__wrap_dm_task_run, 1);
718 will_return(__wrap_dm_task_get_names, 1);
719 assert_int_equal(dmevent_loop(), 1);
722 /* Watch 3 devices, where one device has an event (foo), one device is
723 * removed (xyzzy), and one device does nothing (bar). Verify that
724 * the device with the event gets updated, the device that is removed
725 * gets unwatched, and the device with no events stays the same.
726 * The devices remain after this test */
727 static void test_dmevent_loop_good1(void **state)
729 struct dm_device *dev;
730 struct dev_event *dev_evt;
731 struct test_data *datap = (struct test_data *)(*state);
735 remove_all_dm_device_events();
736 unwatch_all_dmevents();
737 assert_int_equal(add_dm_device_event("foo", 1, 5), 0);
738 assert_int_equal(add_dm_device_event("bar", 1, 7), 0);
739 assert_int_equal(add_dm_device_event("baz", 1, 12), 0);
740 assert_int_equal(add_dm_device_event("xyzzy", 1, 8), 0);
741 will_return(__wrap_dm_geteventnr, 0);
742 assert_int_equal(watch_dmevents("foo"), 0);
743 will_return(__wrap_dm_geteventnr, 0);
744 assert_int_equal(watch_dmevents("bar"), 0);
745 will_return(__wrap_dm_geteventnr, 0);
746 assert_int_equal(watch_dmevents("xyzzy"), 0);
747 assert_int_equal(add_dm_device_event("foo", 1, 6), 0);
748 assert_int_equal(remove_dm_device_event("xyzzy"), 0);
749 will_return(__wrap_poll, 1);
750 will_return(__wrap_ioctl, 0);
751 will_return(__wrap_libmp_dm_task_create, &data);
752 will_return(__wrap_dm_task_no_open_count, 1);
753 will_return(__wrap_dm_task_run, 1);
754 will_return(__wrap_dm_task_get_names, 1);
755 expect_string(__wrap_update_multipath, mapname, "foo");
756 will_return(__wrap_update_multipath, 0);
757 expect_string(__wrap_remove_map_by_alias, alias, "xyzzy");
758 assert_int_equal(dmevent_loop(), 1);
759 assert_int_equal(VECTOR_SIZE(waiter->events), 2);
760 assert_int_equal(VECTOR_SIZE(data.dm_devices), 3);
761 dev_evt = find_dmevents("foo");
762 assert_ptr_not_equal(dev_evt, NULL);
763 assert_int_equal(dev_evt->evt_nr, 6);
764 assert_int_equal(dev_evt->action, EVENT_NOTHING);
765 dev = find_dm_device("foo");
766 assert_ptr_not_equal(dev, NULL);
767 assert_int_equal(dev->evt_nr, 6);
768 assert_int_equal(dev->update_nr, 6);
769 dev_evt = find_dmevents("bar");
770 assert_ptr_not_equal(dev_evt, NULL);
771 assert_int_equal(dev_evt->evt_nr, 7);
772 assert_int_equal(dev_evt->action, EVENT_NOTHING);
773 dev = find_dm_device("bar");
774 assert_ptr_not_equal(dev, NULL);
775 assert_int_equal(dev->evt_nr, 7);
776 assert_int_equal(dev->update_nr, 7);
777 assert_ptr_equal(find_dmevents("xyzzy"), NULL);
778 assert_ptr_equal(find_dm_device("xyzzy"), NULL);
781 /* watch another dm device and add events to two of them, so bar and
782 * baz have new events, and foo doesn't. Set update_multipath to
783 * fail for baz. Verify that baz is unwatched, bar is updated, and
784 * foo stays the same. */
785 static void test_dmevent_loop_good2(void **state)
787 struct dm_device *dev;
788 struct dev_event *dev_evt;
789 struct test_data *datap = (struct test_data *)(*state);
793 assert_int_equal(add_dm_device_event("bar", 1, 9), 0);
794 will_return(__wrap_dm_geteventnr, 0);
795 assert_int_equal(watch_dmevents("baz"), 0);
796 assert_int_equal(add_dm_device_event("baz", 1, 14), 0);
797 will_return(__wrap_poll, 1);
798 will_return(__wrap_ioctl, 0);
799 will_return(__wrap_libmp_dm_task_create, &data);
800 will_return(__wrap_dm_task_no_open_count, 1);
801 will_return(__wrap_dm_task_run, 1);
802 will_return(__wrap_dm_task_get_names, 1);
803 expect_string(__wrap_update_multipath, mapname, "bar");
804 will_return(__wrap_update_multipath, 0);
805 expect_string(__wrap_update_multipath, mapname, "baz");
806 will_return(__wrap_update_multipath, 1);
807 assert_int_equal(dmevent_loop(), 1);
808 assert_int_equal(VECTOR_SIZE(waiter->events), 2);
809 assert_int_equal(VECTOR_SIZE(data.dm_devices), 2);
810 dev_evt = find_dmevents("foo");
811 assert_ptr_not_equal(dev_evt, NULL);
812 assert_int_equal(dev_evt->evt_nr, 6);
813 assert_int_equal(dev_evt->action, EVENT_NOTHING);
814 dev = find_dm_device("foo");
815 assert_ptr_not_equal(dev, NULL);
816 assert_int_equal(dev->evt_nr, 6);
817 assert_int_equal(dev->update_nr, 6);
818 dev_evt = find_dmevents("bar");
819 assert_ptr_not_equal(dev_evt, NULL);
820 assert_int_equal(dev_evt->evt_nr, 9);
821 assert_int_equal(dev_evt->action, EVENT_NOTHING);
822 dev = find_dm_device("bar");
823 assert_ptr_not_equal(dev, NULL);
824 assert_int_equal(dev->evt_nr, 9);
825 assert_int_equal(dev->update_nr, 9);
826 assert_ptr_equal(find_dmevents("baz"), NULL);
827 assert_ptr_equal(find_dm_device("baz"), NULL);
830 /* remove dm device foo, and unwatch events on bar. Verify that
831 * foo is cleaned up and unwatched, and bar is no longer updated */
832 static void test_dmevent_loop_good3(void **state)
834 struct dm_device *dev;
835 struct test_data *datap = (struct test_data *)(*state);
839 assert_int_equal(remove_dm_device_event("foo"), 0);
840 unwatch_dmevents("bar");
841 will_return(__wrap_poll, 1);
842 will_return(__wrap_ioctl, 0);
843 will_return(__wrap_libmp_dm_task_create, &data);
844 will_return(__wrap_dm_task_no_open_count, 1);
845 will_return(__wrap_dm_task_run, 1);
846 will_return(__wrap_dm_task_get_names, 1);
847 expect_string(__wrap_remove_map_by_alias, alias, "foo");
848 assert_int_equal(dmevent_loop(), 1);
849 assert_int_equal(VECTOR_SIZE(waiter->events), 0);
850 assert_int_equal(VECTOR_SIZE(data.dm_devices), 1);
851 dev = find_dm_device("bar");
852 assert_ptr_not_equal(dev, NULL);
853 assert_int_equal(dev->evt_nr, 9);
854 assert_int_equal(dev->update_nr, 9);
855 assert_ptr_equal(find_dmevents("foo"), NULL);
856 assert_ptr_equal(find_dmevents("bar"), NULL);
857 assert_ptr_equal(find_dm_device("foo"), NULL);
861 /* verify that rearming the dmevents polling works */
862 static void test_arm_poll(void **state)
864 struct test_data *datap = (struct test_data *)(*state);
867 will_return(__wrap_ioctl, 0);
868 assert_int_equal(arm_dm_event_poll(waiter->fd), 0);
871 /* verify that the waiter is cleaned up */
872 static void test_cleanup_waiter(void **state)
874 struct test_data *datap = (struct test_data *)(*state);
877 cleanup_dmevent_waiter();
878 assert_ptr_equal(waiter, NULL);
881 int test_dmevents(void)
883 const struct CMUnitTest tests[] = {
884 cmocka_unit_test(test_init_waiter_bad0),
885 cmocka_unit_test(test_init_waiter_bad1),
886 cmocka_unit_test(test_init_waiter_good0),
887 cmocka_unit_test(test_watch_dmevents_bad0),
888 cmocka_unit_test(test_watch_dmevents_bad1),
889 cmocka_unit_test(test_watch_dmevents_bad2),
890 cmocka_unit_test(test_watch_dmevents_good0),
891 cmocka_unit_test(test_watch_dmevents_good1),
892 cmocka_unit_test(test_watch_dmevents_good2),
893 cmocka_unit_test(test_get_events_bad0),
894 cmocka_unit_test(test_get_events_bad1),
895 cmocka_unit_test(test_get_events_bad2),
896 cmocka_unit_test(test_get_events_good0),
897 cmocka_unit_test(test_get_events_good1),
898 cmocka_unit_test(test_arm_poll),
899 cmocka_unit_test(test_dmevent_loop_bad0),
900 cmocka_unit_test(test_dmevent_loop_bad1),
901 cmocka_unit_test(test_dmevent_loop_bad2),
902 cmocka_unit_test(test_dmevent_loop_good0),
903 cmocka_unit_test(test_dmevent_loop_good1),
904 cmocka_unit_test(test_dmevent_loop_good2),
905 cmocka_unit_test(test_dmevent_loop_good3),
906 cmocka_unit_test(test_cleanup_waiter),
908 return cmocka_run_group_tests(tests, setup, teardown);
915 ret += test_dmevents();