libmultipath: cleanup old issues with directio checker
[multipath-tools/.git] / tests / directio.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 #define _GNU_SOURCE
20 #include <stdint.h>
21 #include <stdbool.h>
22 #include <stdarg.h>
23 #include <stddef.h>
24 #include <setjmp.h>
25 #include <stdlib.h>
26 #include <cmocka.h>
27 #include "globals.c"
28 #include "../libmultipath/checkers/directio.c"
29
30 int test_fd = 111;
31 int ioctx_count = 0;
32 struct io_event mock_events[AIO_GROUP_SIZE]; /* same as the checker max */
33 int ev_off = 0;
34 struct timespec zero_timeout = {0};
35 struct timespec full_timeout = { .tv_sec = -1 };
36
37 int __real_ioctl(int fd, unsigned long request, void *argp);
38
39 int __wrap_ioctl(int fd, unsigned long request, void *argp)
40 {
41 #ifdef DIO_TEST_DEV
42         mock_type(int);
43         return __real_ioctl(fd, request, argp);
44 #else
45         int *blocksize = (int *)argp;
46
47         assert_int_equal(fd, test_fd);
48         assert_int_equal(request, BLKBSZGET);
49         assert_non_null(blocksize);
50         *blocksize = mock_type(int);
51         return 0;
52 #endif
53 }
54
55 int __real_fcntl(int fd, int cmd, long arg);
56
57 int __wrap_fcntl(int fd, int cmd, long arg)
58 {
59 #ifdef DIO_TEST_DEV
60         return __real_fcntl(fd, cmd, arg);
61 #else
62         assert_int_equal(fd, test_fd);
63         assert_int_equal(cmd, F_GETFL);
64         return O_DIRECT;
65 #endif
66 }
67
68 int __real___fxstat(int ver, int fd, struct stat *statbuf);
69
70 int __wrap___fxstat(int ver, int fd, struct stat *statbuf)
71 {
72 #ifdef DIO_TEST_DEV
73         return __real___fxstat(ver, fd, statbuf);
74 #else
75         assert_int_equal(fd, test_fd);
76         assert_non_null(statbuf);
77         memset(statbuf, 0, sizeof(struct stat));
78         return 0;
79 #endif
80 }
81
82 int __real_io_setup(int maxevents, io_context_t *ctxp);
83
84 int __wrap_io_setup(int maxevents, io_context_t *ctxp)
85 {
86         ioctx_count++;
87 #ifdef DIO_TEST_DEV
88         int ret = mock_type(int);
89         assert_int_equal(ret, __real_io_setup(maxevents, ctxp));
90         return ret;
91 #else
92         return mock_type(int);
93 #endif
94 }
95
96 int __real_io_destroy(io_context_t ctx);
97
98 int __wrap_io_destroy(io_context_t ctx)
99 {
100         ioctx_count--;
101 #ifdef DIO_TEST_DEV
102         int ret = mock_type(int);
103         assert_int_equal(ret, __real_io_destroy(ctx));
104         return ret;
105 #else
106         return mock_type(int);
107 #endif
108 }
109
110 int __real_io_submit(io_context_t ctx, long nr, struct iocb *ios[]);
111
112 int __wrap_io_submit(io_context_t ctx, long nr, struct iocb *ios[])
113 {
114 #ifdef DIO_TEST_DEV
115         struct timespec dev_delay = { .tv_nsec = 100000 };
116         int ret = mock_type(int);
117         assert_int_equal(ret, __real_io_submit(ctx, nr, ios));
118         nanosleep(&dev_delay, NULL);
119         return ret;
120 #else
121         return mock_type(int);
122 #endif
123 }
124
125 int __real_io_cancel(io_context_t ctx, struct iocb *iocb, struct io_event *evt);
126
127 int __wrap_io_cancel(io_context_t ctx, struct iocb *iocb, struct io_event *evt)
128 {
129 #ifdef DIO_TEST_DEV
130         mock_type(int);
131         return __real_io_cancel(ctx, iocb, evt);
132 #else
133         return mock_type(int);
134 #endif
135 }
136
137 int __real_io_getevents(io_context_t ctx, long min_nr, long nr,
138                         struct io_event *events, struct timespec *timeout);
139
140 int __wrap_io_getevents(io_context_t ctx, long min_nr, long nr,
141                         struct io_event *events, struct timespec *timeout)
142 {
143         int nr_evs;
144 #ifndef DIO_TEST_DEV
145         struct timespec *sleep_tmo;
146         int i;
147         struct io_event *evs;
148 #endif
149
150         assert_non_null(timeout);
151         nr_evs = mock_type(int);
152         assert_true(nr_evs <= nr);
153         if (!nr_evs)
154                 return 0;
155 #ifdef DIO_TEST_DEV
156         mock_ptr_type(struct timespec *);
157         mock_ptr_type(struct io_event *);
158         assert_int_equal(nr_evs, __real_io_getevents(ctx, min_nr, nr_evs,
159                                                      events, timeout));
160 #else
161         sleep_tmo = mock_ptr_type(struct timespec *);
162         if (sleep_tmo) {
163                 if (sleep_tmo->tv_sec < 0)
164                         nanosleep(timeout, NULL);
165                 else
166                         nanosleep(sleep_tmo, NULL);
167         }
168         if (nr_evs < 0) {
169                 errno = -nr_evs;
170                 return -1;
171         }
172         evs = mock_ptr_type(struct io_event *);
173         for (i = 0; i < nr_evs; i++)
174                 events[i] = evs[i];
175 #endif
176         ev_off -= nr_evs;
177         return nr_evs;
178 }
179
180 static void return_io_getevents_none(void)
181 {
182         will_return(__wrap_io_getevents, 0);
183 }
184
185 static void return_io_getevents_nr(struct timespec *ts, int nr,
186                                    struct async_req **reqs, int *res)
187 {
188         int i, off = 0;
189
190         for(i = 0; i < nr; i++) {
191                 mock_events[i + ev_off].obj = &reqs[i]->io;
192                 if (res[i] == 0)
193                         mock_events[i + ev_off].res = reqs[i]->blksize;
194         }
195         while (nr > 0) {
196                 will_return(__wrap_io_getevents, (nr > 128)? 128 : nr);
197                 will_return(__wrap_io_getevents, ts);
198                 will_return(__wrap_io_getevents, &mock_events[off + ev_off]);
199                 ts = NULL;
200                 off += 128;
201                 nr -= 128;
202         }
203         if (nr == 0)
204                 will_return(__wrap_io_getevents, 0);
205         ev_off += i;
206 }
207
208 void do_check_state(struct checker *c, int sync, int timeout, int chk_state)
209 {
210         struct directio_context * ct = (struct directio_context *)c->context;
211
212         if (!ct->running)
213                 will_return(__wrap_io_submit, 1);
214         assert_int_equal(check_state(test_fd, ct, sync, timeout), chk_state);
215         assert_int_equal(ev_off, 0);
216         memset(mock_events, 0, sizeof(mock_events));
217 }
218
219 void do_libcheck_reset(int nr_aio_grps)
220 {
221         int count = 0;
222         struct aio_group *aio_grp;
223
224         list_for_each_entry(aio_grp, &aio_grp_list, node)
225                 count++;
226         assert_int_equal(count, nr_aio_grps);
227         for (count = 0; count < nr_aio_grps; count++)
228                 will_return(__wrap_io_destroy, 0);
229         libcheck_reset();
230         assert_true(list_empty(&aio_grp_list));
231         assert_int_equal(ioctx_count, 0);
232 }
233
234 static void do_libcheck_init(struct checker *c, int blocksize,
235                              struct async_req **req)
236 {
237         struct directio_context * ct;
238
239         c->fd = test_fd;
240         will_return(__wrap_ioctl, blocksize);
241         assert_int_equal(libcheck_init(c), 0);
242         ct = (struct directio_context *)c->context;
243         assert_non_null(ct);
244         assert_non_null(ct->aio_grp);
245         assert_non_null(ct->req);
246         if (req)
247                 *req = ct->req;
248 #ifndef DIO_TEST_DEV
249         /* don't check fake blocksize on real devices */
250         assert_int_equal(ct->req->blksize, blocksize);
251 #endif
252 }
253
254 static int is_checker_running(struct checker *c)
255 {
256         struct directio_context * ct = (struct directio_context *)c->context;
257         return ct->running;
258 }
259
260 static struct aio_group *get_aio_grp(struct checker *c)
261 {
262         struct directio_context * ct = (struct directio_context *)c->context;
263
264         assert_non_null(ct);
265         return ct->aio_grp;
266 }
267
268 static void check_aio_grp(struct aio_group *aio_grp, int holders,
269                           int orphans)
270 {
271         int count = 0;
272         struct list_head *item;
273
274         list_for_each(item, &aio_grp->orphans)
275                 count++;
276         assert_int_equal(holders, aio_grp->holders);
277         assert_int_equal(orphans, count);
278 }
279
280 /* simple resetting test */
281 static void test_reset(void **state)
282 {
283         assert_true(list_empty(&aio_grp_list));
284         do_libcheck_reset(0);
285 }
286
287 /* tests initializing, then resetting, and then initializing again */
288 static void test_init_reset_init(void **state)
289 {
290         struct checker c = {0};
291         struct aio_group *aio_grp, *tmp_grp;
292
293         assert_true(list_empty(&aio_grp_list));
294         will_return(__wrap_io_setup, 0);
295         do_libcheck_init(&c, 4096, NULL);
296         aio_grp = get_aio_grp(&c);
297         check_aio_grp(aio_grp, 1, 0);
298         list_for_each_entry(tmp_grp, &aio_grp_list, node)
299                 assert_ptr_equal(aio_grp, tmp_grp);
300         libcheck_free(&c);
301         check_aio_grp(aio_grp, 0, 0);
302         do_libcheck_reset(1);
303         will_return(__wrap_io_setup, 0);
304         do_libcheck_init(&c, 4096, NULL);
305         aio_grp = get_aio_grp(&c);
306         check_aio_grp(aio_grp, 1, 0);
307         list_for_each_entry(tmp_grp, &aio_grp_list, node)
308                 assert_ptr_equal(aio_grp, tmp_grp);
309         libcheck_free(&c);
310         check_aio_grp(aio_grp, 0, 0);
311         do_libcheck_reset(1);
312 }
313
314 /* test initializing and then freeing 4096 checkers */
315 static void test_init_free(void **state)
316 {
317         int i, count = 0;
318         struct checker c[4096] = {0};
319         struct aio_group *aio_grp;
320
321         assert_true(list_empty(&aio_grp_list));
322         will_return(__wrap_io_setup, 0);
323         will_return(__wrap_io_setup, 0);
324         will_return(__wrap_io_setup, 0);
325         will_return(__wrap_io_setup, 0);
326         for (i = 0; i < 4096; i++) {
327                 struct directio_context * ct;
328
329                 if (i % 3 == 0)
330                         do_libcheck_init(&c[i], 512, NULL);
331                 else if (i % 3 == 1)
332                         do_libcheck_init(&c[i], 1024, NULL);
333                 else
334                         do_libcheck_init(&c[i], 4096, NULL);
335                 ct = (struct directio_context *)c[i].context;
336                 assert_non_null(ct->aio_grp);
337                 if ((i & 1023) == 0)
338                         aio_grp = ct->aio_grp;
339                 else {
340                         assert_ptr_equal(ct->aio_grp, aio_grp);
341                         assert_int_equal(aio_grp->holders, (i & 1023) + 1);
342                 }
343         }
344         count = 0;
345         list_for_each_entry(aio_grp, &aio_grp_list, node)
346                 count++;
347         assert_int_equal(count, 4);
348         for (i = 0; i < 4096; i++) {
349                 struct directio_context * ct = (struct directio_context *)c[i].context;
350
351                 aio_grp = ct->aio_grp;
352                 libcheck_free(&c[i]);
353                 assert_int_equal(aio_grp->holders, 1023 - (i & 1023));
354         }
355         list_for_each_entry(aio_grp, &aio_grp_list, node)
356                 assert_int_equal(aio_grp->holders, 0);
357         do_libcheck_reset(4);
358 }
359
360 /* check mixed initializing and freeing 4096 checkers */
361 static void test_multi_init_free(void **state)
362 {
363         int i, count;
364         struct checker c[4096] = {0};
365         struct aio_group *aio_grp;
366
367         assert_true(list_empty(&aio_grp_list));
368         will_return(__wrap_io_setup, 0);
369         will_return(__wrap_io_setup, 0);
370         will_return(__wrap_io_setup, 0);
371         will_return(__wrap_io_setup, 0);
372         for (count = 0, i = 0; i < 4096; count++) {
373                 /* usually init, but occasionally free checkers */
374                 if (count == 0 || (count % 5 != 0 && count % 7 != 0)) {
375                         do_libcheck_init(&c[i], 4096, NULL);
376                         i++;
377                 } else {
378                         i--;
379                         libcheck_free(&c[i]);
380                 }
381         }
382         count = 0;
383         list_for_each_entry(aio_grp, &aio_grp_list, node) {
384                 assert_int_equal(aio_grp->holders, 1024);
385                 count++;
386         }
387         assert_int_equal(count, 4);
388         for (count = 0, i = 4096; i > 0; count++) {
389                 /* usually free, but occasionally init checkers */
390                 if (count == 0 || (count % 5 != 0 && count % 7 != 0)) {
391                         i--;
392                         libcheck_free(&c[i]);
393                 } else {
394                         do_libcheck_init(&c[i], 4096, NULL);
395                         i++;
396                 }
397         }
398         do_libcheck_reset(4);
399 }
400
401 /* simple single checker sync test */
402 static void test_check_state_simple(void **state)
403 {
404         struct checker c = {0};
405         struct async_req *req;
406         int res = 0;
407
408         assert_true(list_empty(&aio_grp_list));
409         will_return(__wrap_io_setup, 0);
410         do_libcheck_init(&c, 4096, &req);
411         return_io_getevents_nr(NULL, 1, &req, &res);
412         do_check_state(&c, 1, 30, PATH_UP);
413         libcheck_free(&c);
414         do_libcheck_reset(1);
415 }
416
417 /* test sync timeout */
418 static void test_check_state_timeout(void **state)
419 {
420         struct checker c = {0};
421         struct aio_group *aio_grp;
422
423         assert_true(list_empty(&aio_grp_list));
424         will_return(__wrap_io_setup, 0);
425         do_libcheck_init(&c, 4096, NULL);
426         aio_grp = get_aio_grp(&c);
427         return_io_getevents_none();
428         will_return(__wrap_io_cancel, 0);
429         do_check_state(&c, 1, 30, PATH_DOWN);
430         check_aio_grp(aio_grp, 1, 0);
431 #ifdef DIO_TEST_DEV
432         /* io_cancel will return negative value on timeout, so it happens again
433          * when freeing the checker */
434         will_return(__wrap_io_cancel, 0);
435 #endif
436         libcheck_free(&c);
437         do_libcheck_reset(1);
438 }
439
440 /* test async timeout */
441 static void test_check_state_async_timeout(void **state)
442 {
443         struct checker c = {0};
444         struct aio_group *aio_grp;
445
446         assert_true(list_empty(&aio_grp_list));
447         will_return(__wrap_io_setup, 0);
448         do_libcheck_init(&c, 4096, NULL);
449         aio_grp = get_aio_grp(&c);
450         return_io_getevents_none();
451         do_check_state(&c, 0, 3, PATH_PENDING);
452         return_io_getevents_none();
453         do_check_state(&c, 0, 3, PATH_PENDING);
454         return_io_getevents_none();
455         do_check_state(&c, 0, 3, PATH_PENDING);
456         return_io_getevents_none();
457         will_return(__wrap_io_cancel, 0);
458         do_check_state(&c, 0, 3, PATH_DOWN);
459         check_aio_grp(aio_grp, 1, 0);
460 #ifdef DIO_TEST_DEV
461         will_return(__wrap_io_cancel, 0);
462 #endif
463         libcheck_free(&c);
464         do_libcheck_reset(1);
465 }
466
467 /* test freeing checkers with outstanding requests */
468 static void test_free_with_pending(void **state)
469 {
470         struct checker c[2] = {0};
471         struct aio_group *aio_grp;
472         struct async_req *req;
473         int res = 0;
474
475         assert_true(list_empty(&aio_grp_list));
476         will_return(__wrap_io_setup, 0);
477         do_libcheck_init(&c[0], 4096, &req);
478         do_libcheck_init(&c[1], 4096, NULL);
479         aio_grp = get_aio_grp(c);
480         return_io_getevents_none();
481         do_check_state(&c[0], 0, 30, PATH_PENDING);
482         return_io_getevents_nr(NULL, 1, &req, &res);
483         return_io_getevents_none();
484         do_check_state(&c[1], 0, 30, PATH_PENDING);
485         assert_true(is_checker_running(&c[0]));
486         assert_true(is_checker_running(&c[1]));
487         check_aio_grp(aio_grp, 2, 0);
488         libcheck_free(&c[0]);
489         check_aio_grp(aio_grp, 1, 0);
490         will_return(__wrap_io_cancel, 0);
491         libcheck_free(&c[1]);
492 #ifdef DIO_TEST_DEV
493         check_aio_grp(aio_grp, 1, 1); /* real cancel doesn't remove request */
494 #else
495         check_aio_grp(aio_grp, 0, 0);
496 #endif
497         do_libcheck_reset(1);
498 }
499
500 /* test removing orpahed aio_group on free */
501 static void test_orphaned_aio_group(void **state)
502 {
503         struct checker c[AIO_GROUP_SIZE] = {0};
504         struct aio_group *aio_grp, *tmp_grp;
505         int i;
506
507         assert_true(list_empty(&aio_grp_list));
508         will_return(__wrap_io_setup, 0);
509         for (i = 0; i < AIO_GROUP_SIZE; i++) {
510                 do_libcheck_init(&c[i], 4096, NULL);
511                 return_io_getevents_none();
512                 do_check_state(&c[i], 0, 30, PATH_PENDING);
513         }
514         aio_grp = get_aio_grp(c);
515         check_aio_grp(aio_grp, AIO_GROUP_SIZE, 0);
516         i = 0;
517         list_for_each_entry(tmp_grp, &aio_grp_list, node)
518                 i++;
519         assert_int_equal(i, 1);
520         for (i = 0; i < AIO_GROUP_SIZE; i++) {
521                 assert_true(is_checker_running(&c[i]));
522                 will_return(__wrap_io_cancel, -1);
523                 if (i == AIO_GROUP_SIZE - 1) {
524                         /* remove the orphaned group and create a new one */
525                         will_return(__wrap_io_destroy, 0);
526                 }
527                 libcheck_free(&c[i]);
528         }
529         do_libcheck_reset(0);
530 }
531
532 /* test sync timeout with failed cancel and cleanup by another
533  * checker */
534 static void test_timeout_cancel_failed(void **state)
535 {
536         struct checker c[2] = {0};
537         struct aio_group *aio_grp;
538         struct async_req *reqs[2];
539         int res[] = {0,0};
540         int i;
541
542         assert_true(list_empty(&aio_grp_list));
543         will_return(__wrap_io_setup, 0);
544         for (i = 0; i < 2; i++)
545                 do_libcheck_init(&c[i], 4096, &reqs[i]);
546         aio_grp = get_aio_grp(c);
547         return_io_getevents_none();
548         will_return(__wrap_io_cancel, -1);
549         do_check_state(&c[0], 1, 30, PATH_DOWN);
550         assert_true(is_checker_running(&c[0]));
551         check_aio_grp(aio_grp, 2, 0);
552         return_io_getevents_none();
553         will_return(__wrap_io_cancel, -1);
554         do_check_state(&c[0], 1, 30, PATH_DOWN);
555         assert_true(is_checker_running(&c[0]));
556         return_io_getevents_nr(NULL, 1, &reqs[0], &res[0]);
557         return_io_getevents_nr(NULL, 1, &reqs[1], &res[1]);
558         do_check_state(&c[1], 1, 30, PATH_UP);
559         do_check_state(&c[0], 1, 30, PATH_UP);
560         for (i = 0; i < 2; i++) {
561                 assert_false(is_checker_running(&c[i]));
562                 libcheck_free(&c[i]);
563         }
564         do_libcheck_reset(1);
565 }
566
567 /* test async timeout with failed cancel and cleanup by another
568  * checker */
569 static void test_async_timeout_cancel_failed(void **state)
570 {
571         struct checker c[2] = {0};
572         struct async_req *reqs[2];
573         int res[] = {0,0};
574         int i;
575
576         assert_true(list_empty(&aio_grp_list));
577         will_return(__wrap_io_setup, 0);
578         for (i = 0; i < 2; i++)
579                 do_libcheck_init(&c[i], 4096, &reqs[i]);
580         return_io_getevents_none();
581         do_check_state(&c[0], 0, 2, PATH_PENDING);
582         return_io_getevents_none();
583         do_check_state(&c[1], 0, 2, PATH_PENDING);
584         return_io_getevents_none();
585         do_check_state(&c[0], 0, 2, PATH_PENDING);
586         return_io_getevents_none();
587         do_check_state(&c[1], 0, 2, PATH_PENDING);
588         return_io_getevents_none();
589         will_return(__wrap_io_cancel, -1);
590         do_check_state(&c[0], 0, 2, PATH_DOWN);
591 #ifndef DIO_TEST_DEV
592         /* can't pick which even gets returned on real devices */
593         return_io_getevents_nr(NULL, 1, &reqs[1], &res[1]);
594         do_check_state(&c[1], 0, 2, PATH_UP);
595 #endif
596         return_io_getevents_none();
597         will_return(__wrap_io_cancel, -1);
598         do_check_state(&c[0], 0, 2, PATH_DOWN);
599         assert_true(is_checker_running(&c[0]));
600         return_io_getevents_nr(NULL, 2, reqs, res);
601         do_check_state(&c[1], 0, 2, PATH_UP);
602         do_check_state(&c[0], 0, 2, PATH_UP);
603         for (i = 0; i < 2; i++) {
604                 assert_false(is_checker_running(&c[i]));
605                 libcheck_free(&c[i]);
606         }
607         do_libcheck_reset(1);
608 }
609
610 /* test orphaning a request, and having another checker clean it up */
611 static void test_orphan_checker_cleanup(void **state)
612 {
613         struct checker c[2] = {0};
614         struct async_req *reqs[2];
615         int res[] = {0,0};
616         struct aio_group *aio_grp;
617         int i;
618
619         assert_true(list_empty(&aio_grp_list));
620         will_return(__wrap_io_setup, 0);
621         for (i = 0; i < 2; i++)
622                 do_libcheck_init(&c[i], 4096, &reqs[i]);
623         aio_grp = get_aio_grp(c);
624         return_io_getevents_none();
625         do_check_state(&c[0], 0, 30, PATH_PENDING);
626         will_return(__wrap_io_cancel, -1);
627         check_aio_grp(aio_grp, 2, 0);
628         libcheck_free(&c[0]);
629         check_aio_grp(aio_grp, 2, 1);
630         return_io_getevents_nr(NULL, 2, reqs, res);
631         do_check_state(&c[1], 0, 2, PATH_UP);
632         check_aio_grp(aio_grp, 1, 0);
633         libcheck_free(&c[1]);
634         check_aio_grp(aio_grp, 0, 0);
635         do_libcheck_reset(1);
636 }
637
638 /* test orphaning a request, and having reset clean it up */
639 static void test_orphan_reset_cleanup(void **state)
640 {
641         struct checker c;
642         struct aio_group *orphan_aio_grp, *tmp_aio_grp;
643         int found, count;
644
645         assert_true(list_empty(&aio_grp_list));
646         will_return(__wrap_io_setup, 0);
647         do_libcheck_init(&c, 4096, NULL);
648         orphan_aio_grp = get_aio_grp(&c);
649         return_io_getevents_none();
650         do_check_state(&c, 0, 30, PATH_PENDING);
651         will_return(__wrap_io_cancel, -1);
652         check_aio_grp(orphan_aio_grp, 1, 0);
653         libcheck_free(&c);
654         check_aio_grp(orphan_aio_grp, 1, 1);
655         found = count = 0;
656         list_for_each_entry(tmp_aio_grp, &aio_grp_list, node) {
657                 count++;
658                 if (tmp_aio_grp == orphan_aio_grp)
659                         found = 1;
660         }
661         assert_int_equal(count, 1);
662         assert_int_equal(found, 1);
663         do_libcheck_reset(1);
664 }
665
666 /* test checkers with different blocksizes */
667 static void test_check_state_blksize(void **state)
668 {
669         int i;
670         struct checker c[3] = {0};
671         int blksize[] = {4096, 1024, 512};
672         struct async_req *reqs[3];
673         int res[] = {0,1,0};
674 #ifdef DIO_TEST_DEV
675         /* can't pick event return state on real devices */
676         int chk_state[] = {PATH_UP, PATH_UP, PATH_UP};
677 #else
678         int chk_state[] = {PATH_UP, PATH_DOWN, PATH_UP};
679 #endif
680
681         assert_true(list_empty(&aio_grp_list));
682         will_return(__wrap_io_setup, 0);
683         for (i = 0; i < 3; i++)
684                 do_libcheck_init(&c[i], blksize[i], &reqs[i]);
685         for (i = 0; i < 3; i++) {
686                 return_io_getevents_nr(NULL, 1, &reqs[i], &res[i]);
687                 do_check_state(&c[i], 1, 30, chk_state[i]);
688         }
689         for (i = 0; i < 3; i++) {
690                 assert_false(is_checker_running(&c[i]));
691                 libcheck_free(&c[i]);
692         }
693         do_libcheck_reset(1);
694 }
695
696 /* test async checkers pending and getting resovled by another checker
697  * as well as the loops for getting multiple events */
698 static void test_check_state_async(void **state)
699 {
700         int i;
701         struct checker c[257] = {0};
702         struct async_req *reqs[257];
703         int res[257] = {0};
704
705         assert_true(list_empty(&aio_grp_list));
706         will_return(__wrap_io_setup, 0);
707         for (i = 0; i < 257; i++)
708                 do_libcheck_init(&c[i], 4096, &reqs[i]);
709         for (i = 0; i < 256; i++) {
710                 return_io_getevents_none();
711                 do_check_state(&c[i], 0, 30, PATH_PENDING);
712                 assert_true(is_checker_running(&c[i]));
713         }
714         return_io_getevents_nr(&full_timeout, 256, reqs, res);
715         return_io_getevents_nr(NULL, 1, &reqs[256], &res[256]);
716         do_check_state(&c[256], 0, 30, PATH_UP);
717         assert_false(is_checker_running(&c[256]));
718         libcheck_free(&c[256]);
719         for (i = 0; i < 256; i++) {
720                 do_check_state(&c[i], 0, 30, PATH_UP);
721                 assert_false(is_checker_running(&c[i]));
722                 libcheck_free(&c[i]);
723         }
724         do_libcheck_reset(1);
725 }
726
727 static int setup(void **state)
728 {
729 #ifdef DIO_TEST_DEV
730         test_fd = open(DIO_TEST_DEV, O_RDONLY);
731         if (test_fd < 0)
732                 fail_msg("cannot open %s: %m", DIO_TEST_DEV);
733 #endif
734         return 0;
735 }
736
737 static int teardown(void **state)
738 {
739 #ifdef DIO_TEST_DEV
740         assert_true(test_fd > 0);
741         assert_int_equal(close(test_fd), 0);
742 #endif
743         return 0;
744 }
745
746 int test_directio(void)
747 {
748         const struct CMUnitTest tests[] = {
749                 cmocka_unit_test(test_reset),
750                 cmocka_unit_test(test_init_reset_init),
751                 cmocka_unit_test(test_init_free),
752                 cmocka_unit_test(test_multi_init_free),
753                 cmocka_unit_test(test_check_state_simple),
754                 cmocka_unit_test(test_check_state_timeout),
755                 cmocka_unit_test(test_check_state_async_timeout),
756                 cmocka_unit_test(test_free_with_pending),
757                 cmocka_unit_test(test_timeout_cancel_failed),
758                 cmocka_unit_test(test_async_timeout_cancel_failed),
759                 cmocka_unit_test(test_orphan_checker_cleanup),
760                 cmocka_unit_test(test_orphan_reset_cleanup),
761                 cmocka_unit_test(test_check_state_blksize),
762                 cmocka_unit_test(test_check_state_async),
763                 cmocka_unit_test(test_orphaned_aio_group),
764         };
765
766         return cmocka_run_group_tests(tests, setup, teardown);
767 }
768
769 int main(void)
770 {
771         int ret = 0;
772
773         conf.verbosity = 2;
774         ret += test_directio();
775         return ret;
776 }