failtest: internally eliminate duplicate calls.
[ccan] / ccan / failtest / test / run-locking.c
1 #include <stdlib.h>
2 #include <setjmp.h>
3 #include <stdio.h>
4 #include <stdarg.h>
5 #include <assert.h>
6 #include <ccan/tap/tap.h>
7 /* Include the C files directly. */
8 #include <ccan/failtest/failtest.c>
9
10 #define SIZE 8
11
12 /* We don't want to fork and fail; we're just testing lock recording. */
13 static enum failtest_result dont_fail(struct tlist_calls *history)
14 {
15         return FAIL_DONT_FAIL;
16 }
17
18 static bool place_lock(int fd, char lockarr[], unsigned pos, unsigned size,
19                        int type)
20 {
21         struct flock fl;
22
23         /* Update record keeping. */
24         if (type == F_RDLCK)
25                 memset(lockarr+pos, 1, size);
26         else if (type == F_WRLCK)
27                 memset(lockarr+pos, 2, size);
28         else
29                 memset(lockarr+pos, 0, size);
30
31         fl.l_whence = SEEK_SET;
32         fl.l_type = type;
33         fl.l_start = pos;
34         fl.l_len = size;
35         return failtest_fcntl(fd, "run-locking.c", 1, F_SETLK, &fl) == 0;
36 }
37
38 static char lock_lookup(int fd, unsigned pos)
39 {
40         char ret = 0;
41         unsigned int i;
42         struct lock_info *l;
43
44         for (i = 0; i < lock_num; i++) {
45                 l = &locks[i];
46
47                 if (l->fd != fd)
48                         continue;
49
50                 if (pos >= l->start && pos <= l->end) {
51                         if (ret)
52                                 ret = 3;
53                         else if (l->type == F_RDLCK)
54                                 ret = 1;
55                         else
56                                 ret = 2;
57                 }
58         }
59         return ret;
60 }
61
62 static bool test(int fd,
63                  unsigned p1, unsigned s1,
64                  unsigned p2, unsigned s2,
65                  unsigned p3, unsigned s3)
66 {
67         unsigned int i;
68         char lockarr[SIZE];
69
70         memset(lockarr, 0, sizeof(lockarr));
71
72         if (!place_lock(fd, lockarr, p1, s1, F_WRLCK))
73                 return false;
74
75         if (!place_lock(fd, lockarr, p2, s2, F_RDLCK))
76                 return false;
77
78         if (!place_lock(fd, lockarr, p3, s3, F_UNLCK))
79                 return false;
80
81         for (i = 0; i < SIZE; i++) {
82                 if (lock_lookup(fd, i) != lockarr[i])
83                         return false;
84         }
85
86         /* Reset lock info. */
87         lock_num = 0;
88         return true;
89 }
90
91 int main(void)
92 {
93         int fd;
94         long flags;
95         unsigned int isize;
96
97         plan_tests(5835);
98         failtest_init(0, NULL);
99         failtest_hook = dont_fail;
100
101         fd = open("run-locking-scratch", O_RDWR|O_CREAT, 0600);
102         /* GETFL and SETFL wrappers should pass through. */
103         flags = fcntl(fd, F_GETFL);
104         ok1(failtest_fcntl(fd, "run-locking.c", 1, F_GETFL) == flags);
105         flags |= O_NONBLOCK;
106         ok1(failtest_fcntl(fd, "run-locking.c", 1, F_SETFL, flags) == 0);
107         ok1(failtest_fcntl(fd, "run-locking.c", 1, F_GETFL) == flags);
108
109         for (isize = 1; isize < 4; isize++) {
110                 unsigned int ipos;
111                 for (ipos = 0; ipos + isize < SIZE; ipos++) {
112                         unsigned int jsize;
113                         for (jsize = 1; jsize < 4; jsize++) {
114                                 unsigned int jpos;
115                                 for (jpos = 0; jpos + jsize < SIZE; jpos++) {
116                                         unsigned int ksize;
117                                         for (ksize = 1; ksize < 4; ksize++) {
118                                                 unsigned int kpos;
119                                                 for (kpos = 0;
120                                                      kpos + ksize < SIZE;
121                                                      kpos++) {
122                                                         ok1(test(fd,
123                                                                  ipos, isize,
124                                                                  jpos, jsize,
125                                                                  kpos, ksize));
126                                                 }
127                                         }
128                                 }
129                         }
130                 }
131         }
132
133         return exit_status();
134 }