kpartx: fix bad dm_devn return
[multipath-tools/.git] / tests / dmevents.c
1 /*
2  * Copyright (c) 2018 Benjamin Marzinski, Redhat
3  *
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.
8  *
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.
13  *
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/>.
16  *
17  */
18
19 #include <stdint.h>
20 #include <stdbool.h>
21 #include <stdarg.h>
22 #include <stddef.h>
23 #include <setjmp.h>
24 #include <stdlib.h>
25 #include <cmocka.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include "structs.h"
30 #include "structs_vec.h"
31
32 #include "globals.c"
33 /* I have to do this to get at the static variables */
34 #include "../multipathd/dmevents.c"
35
36 /* pretend dm device */
37 struct dm_device {
38         char name[WWID_SIZE];
39         /* is this a mpath device, or other dm device */
40         int is_mpath;
41         uint32_t evt_nr;
42         /* tracks the event number when the multipath device was updated */
43         uint32_t update_nr;
44 };
45
46 struct test_data {
47         struct vectors vecs;
48         vector dm_devices;
49         struct dm_names *names;
50 };
51
52 struct test_data data;
53
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)
58 {
59         struct dm_device *dev;
60         int i;
61
62         vector_foreach_slot(data.dm_devices, dev, i) {
63                 if (strcmp(name, dev->name) == 0) {
64                         dev->evt_nr = evt_nr;
65                         return 0;
66                 }
67         }
68         dev = (struct dm_device *)malloc(sizeof(struct dm_device));
69         if (!dev){
70                 condlog(0, "Testing error mallocing dm_device");
71                 return -1;
72         }
73         strncpy(dev->name, name, WWID_SIZE);
74         dev->name[WWID_SIZE - 1] = 0;
75         dev->is_mpath = is_mpath;
76         dev->evt_nr = evt_nr;
77         if (!vector_alloc_slot(data.dm_devices)) {
78                 condlog(0, "Testing error setting dm_devices slot");
79                 free(dev);
80                 return -1;
81         }
82         vector_set_slot(data.dm_devices, dev);
83         return 0;
84 }
85
86 /* helper function for pretend dm devices */
87 struct dm_device *find_dm_device(const char *name)
88 {
89         struct dm_device *dev;
90         int i;
91
92         vector_foreach_slot(data.dm_devices, dev, i)
93                 if (strcmp(name, dev->name) == 0)
94                         return dev;
95         return NULL;
96 }
97
98 /* helper function for pretend dm devices */
99 int remove_dm_device_event(const char *name)
100 {
101         struct dm_device *dev;
102         int i;
103
104         vector_foreach_slot(data.dm_devices, dev, i) {
105                 if (strcmp(name, dev->name) == 0) {
106                         vector_del_slot(data.dm_devices, i);
107                                 free(dev);
108                         return 0;
109                 }
110         }
111         return -1;
112 }
113
114 /* helper function for pretend dm devices */
115 void remove_all_dm_device_events(void)
116 {
117         struct dm_device *dev;
118         int i;
119
120         vector_foreach_slot(data.dm_devices, dev, i)
121                 free(dev);
122         vector_reset(data.dm_devices);
123 }
124
125 static inline size_t align_val(size_t val)
126 {
127         return (val + 7) & ~7;
128 }
129 static inline void *align_ptr(void *ptr)
130 {
131         return (void *)align_val((size_t)ptr);
132 }
133
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
136  * structure */
137 struct dm_names *build_dm_names(void)
138 {
139         struct dm_names *names, *np, *old_np = NULL;
140         uint32_t *event_nr;
141         struct dm_device *dev;
142         int i, size = 0;
143
144         if (VECTOR_SIZE(data.dm_devices) == 0) {
145                 names = (struct dm_names *)malloc(sizeof(struct dm_names));
146                 if (!names) {
147                         condlog(0, "Testing error allocating empty dm_names");
148                         return NULL;
149                 }
150                 names->dev = 0;
151                 names->next = 0;
152                 return names;
153         }
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));
158         }
159         names = (struct dm_names *)malloc(size);
160         if (!names) {
161                 condlog(0, "Testing error allocating dm_names");
162                 return NULL;
163         }
164         np = names;
165         vector_foreach_slot(data.dm_devices, dev, i) {
166                 if (old_np)
167                         old_np->next = (uint32_t) ((uintptr_t) np -
168                                                    (uintptr_t) old_np);
169                 np->dev = 1;
170                 np->next = 0;
171                 strcpy(np->name, dev->name);
172
173                 old_np = np;
174                 event_nr = align_ptr(np->name + strlen(dev->name) + 1);
175                 *event_nr = dev->evt_nr;
176                 np = align_ptr(event_nr + 1);
177         }
178         assert_int_equal((char *)np - (char *)names, size);
179         return names;
180 }
181
182 static int setup(void **state)
183 {
184         if (dmevent_poll_supported()) {
185                 data.dm_devices = vector_alloc();
186                 *state = &data;
187         } else
188                 *state = NULL;
189         return 0;
190 }
191
192 static int teardown(void **state)
193 {
194         struct dm_device *dev;
195         int i;
196         struct test_data *datap = (struct test_data *)(*state);
197         if (datap == NULL)
198                 return 0;
199         vector_foreach_slot(datap->dm_devices, dev, i)
200                 free(dev);
201         vector_free(datap->dm_devices);
202         datap = NULL;
203         return 0;
204 }
205
206 int __wrap_open(const char *pathname, int flags)
207 {
208         assert_ptr_equal(pathname, "/dev/mapper/control");
209         assert_int_equal(flags, O_RDWR);
210         return mock_type(int);
211 }
212
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)
216 {
217         assert_int_equal(fd, waiter->fd);
218         return 0;
219 }
220
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)
224 {
225         struct dm_device *dev;
226         int i;
227
228         vector_foreach_slot(data.dm_devices, dev, i)
229                 if (strcmp(name, dev->name) == 0)
230                         return dev->is_mpath;
231         return 0;
232 }
233
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)
237 {
238         struct dm_device *dev;
239         int fail = mock_type(int);
240
241         if (fail)
242                 return -1;
243         dev = find_dm_device(name);
244         if (dev) {
245                 /* simulate updating device state after adding it */
246                 dev->update_nr = dev->evt_nr;
247                 return dev->evt_nr;
248         }
249         return -1;
250 }
251
252 int __wrap_ioctl(int fd, unsigned long request, void *argp)
253 {
254         assert_int_equal(fd, waiter->fd);
255         assert_int_equal(request, DM_DEV_ARM_POLL);
256         return mock_type(int);
257 }
258
259 struct dm_task *__wrap_libmp_dm_task_create(int task)
260 {
261         assert_int_equal(task, DM_DEVICE_LIST);
262         return mock_type(struct dm_task *);
263 }
264
265 int __wrap_dm_task_no_open_count(struct dm_task *dmt)
266 {
267         assert_ptr_equal((struct test_data *)dmt, &data);
268         return mock_type(int);
269 }
270
271 int __wrap_dm_task_run(struct dm_task *dmt)
272 {
273         assert_ptr_equal((struct test_data *)dmt, &data);
274         return mock_type(int);
275 }
276
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)
280 {
281         int good = mock_type(int);
282         assert_ptr_equal((struct test_data *)dmt, &data);
283
284         if (data.names) {
285                 condlog(0, "Testing error. data.names already allocated");
286                 return NULL;
287         }
288         if (!good)
289                 return NULL;
290         data.names = build_dm_names();
291         return data.names;
292 }
293
294 void __wrap_dm_task_destroy(struct dm_task *dmt)
295 {
296         assert_ptr_equal((struct test_data *)dmt, &data);
297
298         if (data.names) {
299                 free(data.names);
300                 data.names = NULL;
301         }
302 }
303
304 int __wrap_poll(struct pollfd *fds, nfds_t nfds, int timeout)
305 {
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);
311 }
312
313 void __wrap_remove_map_by_alias(const char *alias, struct vectors * vecs,
314                                 int purge_vec)
315 {
316         check_expected(alias);
317         assert_ptr_equal(vecs, waiter->vecs);
318         assert_int_equal(purge_vec, 1);
319 }
320
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)
325 {
326         int fail;
327
328         check_expected(mapname);
329         assert_ptr_equal(vecs, waiter->vecs);
330         assert_int_equal(reset, 1);
331         fail = mock_type(int);
332         if (fail) {
333                 assert_int_equal(remove_dm_device_event(mapname), 0);
334                 return fail;
335         } else {
336                 struct dm_device *dev;
337                 int i;
338
339                 vector_foreach_slot(data.dm_devices, dev, i) {
340                         if (strcmp(mapname, dev->name) == 0) {
341                                 dev->update_nr = dev->evt_nr;
342                                 return 0;
343                         }
344                 }
345                 fail();
346         }
347         return fail;
348 }
349
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)
354 {
355         struct dev_event *dev_evt;
356         int i;
357
358         vector_foreach_slot(waiter->events, dev_evt, i)
359                 if (!strcmp(dev_evt->name, name))
360                         return dev_evt;
361         return NULL;
362 }
363
364 /* null vecs pointer when initialized dmevents */
365 static void test_init_waiter_bad0(void **state)
366 {
367         /* this boilerplate code just skips the test if
368          * dmevents polling is not supported */
369         struct test_data *datap = (struct test_data *)(*state);
370         if (datap == NULL)
371                 skip();
372
373         assert_int_equal(init_dmevent_waiter(NULL), -1);
374 }
375
376 /* fail to open /dev/mapper/control */
377 static void test_init_waiter_bad1(void **state)
378 {
379         struct test_data *datap = (struct test_data *)(*state);
380         if (datap == NULL)
381                 skip();
382         will_return(__wrap_open, -1);
383         assert_int_equal(init_dmevent_waiter(&datap->vecs), -1);
384         assert_ptr_equal(waiter, NULL);
385 }
386
387 /* waiter remains initialized after this test */
388 static void test_init_waiter_good0(void **state)
389 {
390         struct test_data *datap = (struct test_data *)(*state);
391         if (datap == NULL)
392                 skip();
393         will_return(__wrap_open, 2);
394         assert_int_equal(init_dmevent_waiter(&datap->vecs), 0);
395         assert_ptr_not_equal(waiter, NULL);
396 }
397
398 /* No dm device named foo */
399 static void test_watch_dmevents_bad0(void **state)
400 {
401         struct test_data *datap = (struct test_data *)(*state);
402         if (datap == NULL)
403                 skip();
404         assert_int_equal(watch_dmevents("foo"), -1);
405         assert_ptr_equal(find_dmevents("foo"), NULL);
406 }
407
408 /* foo is not a multipath device */
409 static void test_watch_dmevents_bad1(void **state)
410 {
411         struct test_data *datap = (struct test_data *)(*state);
412         if (datap == NULL)
413                 skip();
414
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);
418 }
419
420 /* failed getting the dmevent number */
421 static void test_watch_dmevents_bad2(void **state)
422 {
423         struct test_data *datap = (struct test_data *)(*state);
424         if (datap == NULL)
425                 skip();
426
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);
432 }
433
434 /* verify that you can watch and unwatch dm multipath device "foo" */
435 static void test_watch_dmevents_good0(void **state)
436 {
437         struct dev_event *dev_evt;
438         struct test_data *datap = (struct test_data *)(*state);
439         if (datap == NULL)
440                 skip();
441
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);
456 }
457
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)
461 {
462         struct dev_event *dev_evt;
463         struct test_data *datap = (struct test_data *)(*state);
464         if (datap == NULL)
465                 skip();
466
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);
486 }
487
488 /* watch and then unwatch multiple devices */
489 static void test_watch_dmevents_good2(void **state)
490 {
491         struct dev_event *dev_evt;
492         struct test_data *datap = (struct test_data *)(*state);
493         if (datap == NULL)
494                 skip();
495
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);
522 }
523
524 /* dm_task_create fails */
525 static void test_get_events_bad0(void **state)
526 {
527         struct test_data *datap = (struct test_data *)(*state);
528         if (datap == NULL)
529                 skip();
530
531         unwatch_all_dmevents();
532         remove_all_dm_device_events();
533
534         will_return(__wrap_libmp_dm_task_create, NULL);
535         assert_int_equal(dm_get_events(), -1);
536 }
537
538 /* dm_task_run fails */
539 static void test_get_events_bad1(void **state)
540 {
541         struct test_data *datap = (struct test_data *)(*state);
542         if (datap == NULL)
543                 skip();
544
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);
549 }
550
551 /* dm_task_get_names fails */
552 static void test_get_events_bad2(void **state)
553 {
554         struct test_data *datap = (struct test_data *)(*state);
555         if (datap == NULL)
556                 skip();
557
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);
563 }
564
565 /* If the device isn't being watched, dm_get_events returns NULL */
566 static void test_get_events_good0(void **state)
567 {
568         struct test_data *datap = (struct test_data *)(*state);
569         if (datap == NULL)
570                 skip();
571
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);
580 }
581
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)
588 {
589         struct dev_event *dev_evt;
590         struct test_data *datap = (struct test_data *)(*state);
591         if (datap == NULL)
592                 skip();
593
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);
628 }
629
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)
633 {
634         struct dm_device *dev;
635         struct dev_event *dev_evt;
636         struct test_data *datap = (struct test_data *)(*state);
637         if (datap == NULL)
638                 skip();
639
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);
656 }
657
658 /* arm_dm_event_poll's ioctl fails. Nothing happens */
659 static void test_dmevent_loop_bad1(void **state)
660 {
661         struct dm_device *dev;
662         struct dev_event *dev_evt;
663         struct test_data *datap = (struct test_data *)(*state);
664         if (datap == NULL)
665                 skip();
666
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);
678 }
679
680 /* dm_get_events fails. Nothing happens */
681 static void test_dmevent_loop_bad2(void **state)
682 {
683         struct dm_device *dev;
684         struct dev_event *dev_evt;
685         struct test_data *datap = (struct test_data *)(*state);
686         if (datap == NULL)
687                 skip();
688
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);
701 }
702
703 /* verify dmevent_loop runs successfully when no devices are being
704  * watched */
705 static void test_dmevent_loop_good0(void **state)
706 {
707         struct test_data *datap = (struct test_data *)(*state);
708         if (datap == NULL)
709                 skip();
710
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);
720 }
721
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)
728 {
729         struct dm_device *dev;
730         struct dev_event *dev_evt;
731         struct test_data *datap = (struct test_data *)(*state);
732         if (datap == NULL)
733                 skip();
734
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);
779 }
780
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)
786 {
787         struct dm_device *dev;
788         struct dev_event *dev_evt;
789         struct test_data *datap = (struct test_data *)(*state);
790         if (datap == NULL)
791                 skip();
792
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);
828 }
829
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)
833 {
834         struct dm_device *dev;
835         struct test_data *datap = (struct test_data *)(*state);
836         if (datap == NULL)
837                 skip();
838
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);
858 }
859
860
861 /* verify that rearming the dmevents polling works */
862 static void test_arm_poll(void **state)
863 {
864         struct test_data *datap = (struct test_data *)(*state);
865         if (datap == NULL)
866                 skip();
867         will_return(__wrap_ioctl, 0);
868         assert_int_equal(arm_dm_event_poll(waiter->fd), 0);
869 }
870
871 /* verify that the waiter is cleaned up */
872 static void test_cleanup_waiter(void **state)
873 {
874         struct test_data *datap = (struct test_data *)(*state);
875         if (datap == NULL)
876                 skip();
877         cleanup_dmevent_waiter();
878         assert_ptr_equal(waiter, NULL);
879 }
880
881 int test_dmevents(void)
882 {
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),
907         };
908         return cmocka_run_group_tests(tests, setup, teardown);
909 }
910
911 int main(void)
912 {
913         int ret = 0;
914
915         ret += test_dmevents();
916         return ret;
917 }