tdb/test: add mutex related tests
[samba.git] / lib / tdb / test / run-mutex-openflags2.c
1 #include "../common/tdb_private.h"
2 #include "../common/io.c"
3 #include "../common/tdb.c"
4 #include "../common/lock.c"
5 #include "../common/freelist.c"
6 #include "../common/traverse.c"
7 #include "../common/transaction.c"
8 #include "../common/error.c"
9 #include "../common/open.c"
10 #include "../common/check.c"
11 #include "../common/hash.c"
12 #include "../common/mutex.c"
13 #include "tap-interface.h"
14 #include <stdlib.h>
15 #include <sys/types.h>
16 #include <sys/wait.h>
17 #include <poll.h>
18 #include <stdarg.h>
19
20 static TDB_DATA key, data;
21
22 static void log_void(struct tdb_context *tdb, enum tdb_debug_level level,
23                      const char *fmt, ...)
24 {
25 }
26
27 static void log_fn(struct tdb_context *tdb, enum tdb_debug_level level,
28                    const char *fmt, ...)
29 {
30         va_list ap;
31         va_start(ap, fmt);
32         vfprintf(stderr, fmt, ap);
33         va_end(ap);
34 }
35
36 static int do_child(int fd)
37 {
38         struct tdb_context *tdb;
39         unsigned int log_count;
40         struct tdb_logging_context log_ctx = { log_fn, &log_count };
41         struct tdb_logging_context nolog_ctx = { log_void, NULL };
42         char c;
43
44         read(fd, &c, 1);
45
46         tdb = tdb_open_ex("mutex-openflags2.tdb", 0,
47                           TDB_DEFAULT,
48                           O_RDWR|O_CREAT, 0755, &nolog_ctx, NULL);
49         ok((tdb == NULL) && (errno == EINVAL), "TDB_DEFAULT without "
50            "TDB_MUTEX_LOCKING should fail with EINVAL - %d", errno);
51
52         tdb = tdb_open_ex("mutex-openflags2.tdb", 0,
53                           TDB_CLEAR_IF_FIRST,
54                           O_RDWR|O_CREAT, 0755, &nolog_ctx, NULL);
55         ok((tdb == NULL) && (errno == EINVAL), "TDB_CLEAR_IF_FIRST without "
56            "TDB_MUTEX_LOCKING should fail with EINVAL - %d", errno);
57
58         tdb = tdb_open_ex("mutex-openflags2.tdb", 0,
59                           TDB_CLEAR_IF_FIRST |
60                           TDB_MUTEX_LOCKING |
61                           TDB_INTERNAL,
62                           O_RDWR|O_CREAT, 0755, &nolog_ctx, NULL);
63         ok((tdb == NULL) && (errno == EINVAL), "TDB_MUTEX_LOCKING with "
64            "TDB_INTERNAL should fail with EINVAL - %d", errno);
65
66         tdb = tdb_open_ex("mutex-openflags2.tdb", 0,
67                           TDB_CLEAR_IF_FIRST |
68                           TDB_MUTEX_LOCKING |
69                           TDB_NOMMAP,
70                           O_RDWR|O_CREAT, 0755, &nolog_ctx, NULL);
71         ok((tdb == NULL) && (errno == EINVAL), "TDB_MUTEX_LOCKING with "
72            "TDB_NOMMAP should fail with EINVAL - %d", errno);
73
74         tdb = tdb_open_ex("mutex-openflags2.tdb", 0,
75                           TDB_CLEAR_IF_FIRST |
76                           TDB_MUTEX_LOCKING,
77                           O_RDONLY, 0755, &nolog_ctx, NULL);
78         ok((tdb == NULL) && (errno == EINVAL), "TDB_MUTEX_LOCKING with "
79            "O_RDONLY should fail with EINVAL - %d", errno);
80
81         tdb = tdb_open_ex("mutex-openflags2.tdb", 0,
82                           TDB_CLEAR_IF_FIRST |
83                           TDB_MUTEX_LOCKING,
84                           O_RDWR|O_CREAT, 0755, &log_ctx, NULL);
85         ok((tdb != NULL), "TDB_MUTEX_LOCKING with TDB_CLEAR_IF_FIRST"
86            "TDB_NOMMAP should work - %d", errno);
87
88         return 0;
89 }
90
91 /* The code should barf on TDBs created with rwlocks. */
92 int main(int argc, char *argv[])
93 {
94         struct tdb_context *tdb;
95         unsigned int log_count;
96         struct tdb_logging_context log_ctx = { log_fn, &log_count };
97         struct tdb_logging_context nolog_ctx = { log_void, NULL };
98         int ret, status;
99         pid_t child, wait_ret;
100         int pipefd[2];
101         char c = 0;
102         bool runtime_support;
103
104         runtime_support = tdb_runtime_check_for_robust_mutexes();
105
106         ret = pipe(pipefd);
107         ok1(ret == 0);
108
109         key.dsize = strlen("hi");
110         key.dptr = discard_const_p(uint8_t, "hi");
111         data.dsize = strlen("world");
112         data.dptr = discard_const_p(uint8_t, "world");
113
114         tdb = tdb_open_ex("mutex-openflags2.tdb", 0,
115                           TDB_INCOMPATIBLE_HASH|
116                           TDB_MUTEX_LOCKING,
117                           O_RDWR|O_CREAT, 0755, &nolog_ctx, NULL);
118         ok((tdb == NULL) && (errno == EINVAL), "TDB_MUTEX_LOCKING without "
119            "TDB_CLEAR_IF_FIRST should fail with EINVAL - %d", errno);
120
121         if (!runtime_support) {
122                 tdb = tdb_open_ex("mutex-openflags2.tdb", 0,
123                                   TDB_CLEAR_IF_FIRST|
124                                   TDB_MUTEX_LOCKING,
125                                   O_RDWR|O_CREAT, 0755, &nolog_ctx, NULL);
126                 ok((tdb == NULL) && (errno == ENOSYS), "TDB_MUTEX_LOCKING without "
127                    "runtime support should fail with ENOSYS - %d", errno);
128
129                 skip(1, "No robust mutex support");
130                 return exit_status();
131         }
132
133         child = fork();
134         if (child == 0) {
135                 return do_child(pipefd[0]);
136         }
137
138         tdb = tdb_open_ex("mutex-openflags2.tdb", 0,
139                           TDB_CLEAR_IF_FIRST|
140                           TDB_MUTEX_LOCKING,
141                           O_RDWR|O_CREAT, 0755, &log_ctx, NULL);
142         ok((tdb != NULL), "tdb_open_ex with mutexes should succeed");
143
144         write(pipefd[1], &c, 1);
145
146         wait_ret = wait(&status);
147         ok((wait_ret == child) && (status == 0),
148            "child should have exited correctly");
149
150         diag("done");
151         return exit_status();
152 }