waf: Do not recurse into ntdb
[Samba.git] / lib / ntdb / test / api-fork-test.c
blob4b114d6f60b7ea9a495a54256256123b44aff482
1 /* Test forking while holding lock.
3 * There are only five ways to do this currently:
4 * (1) grab a ntdb_chainlock, then fork.
5 * (2) grab a ntdb_lockall, then fork.
6 * (3) grab a ntdb_lockall_read, then fork.
7 * (4) start a transaction, then fork.
8 * (5) fork from inside a ntdb_parse() callback.
10 * Note that we don't hold a lock across ntdb_traverse callbacks, so
11 * that doesn't matter.
13 #include "config.h"
14 #include "ntdb.h"
15 #include "private.h"
16 #include "tap-interface.h"
17 #include "logging.h"
19 static bool am_child = false;
21 static enum NTDB_ERROR fork_in_parse(NTDB_DATA key, NTDB_DATA data,
22 struct ntdb_context *ntdb)
24 int status;
26 if (fork() == 0) {
27 am_child = true;
29 /* We expect this to fail. */
30 if (ntdb_store(ntdb, key, data, NTDB_REPLACE) != NTDB_ERR_LOCK)
31 exit(1);
33 if (ntdb_fetch(ntdb, key, &data) != NTDB_ERR_LOCK)
34 exit(1);
36 if (tap_log_messages != 2)
37 exit(2);
39 return NTDB_SUCCESS;
41 wait(&status);
42 ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
43 return NTDB_SUCCESS;
46 int main(int argc, char *argv[])
48 unsigned int i;
49 struct ntdb_context *ntdb;
50 int flags[] = { NTDB_DEFAULT, NTDB_NOMMAP,
51 NTDB_CONVERT, NTDB_NOMMAP|NTDB_CONVERT };
52 NTDB_DATA key = ntdb_mkdata("key", 3);
53 NTDB_DATA data = ntdb_mkdata("data", 4);
55 plan_tests(sizeof(flags) / sizeof(flags[0]) * 14);
56 for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
57 int status;
59 tap_log_messages = 0;
61 ntdb = ntdb_open("run-fork-test.ntdb",
62 flags[i]|MAYBE_NOSYNC,
63 O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
64 if (!ok1(ntdb))
65 continue;
67 /* Put a record in here. */
68 ok1(ntdb_store(ntdb, key, data, NTDB_REPLACE) == NTDB_SUCCESS);
70 ok1(ntdb_chainlock(ntdb, key) == NTDB_SUCCESS);
71 if (fork() == 0) {
72 /* We expect this to fail. */
73 if (ntdb_store(ntdb, key, data, NTDB_REPLACE) != NTDB_ERR_LOCK)
74 return 1;
76 if (ntdb_fetch(ntdb, key, &data) != NTDB_ERR_LOCK)
77 return 1;
79 if (tap_log_messages != 2)
80 return 2;
82 /* Child can do this without any complaints. */
83 ntdb_chainunlock(ntdb, key);
84 if (tap_log_messages != 2)
85 return 3;
86 ntdb_close(ntdb);
87 if (tap_log_messages != 2)
88 return 4;
89 return 0;
91 wait(&status);
92 ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
93 ntdb_chainunlock(ntdb, key);
95 ok1(ntdb_lockall(ntdb) == NTDB_SUCCESS);
96 if (fork() == 0) {
97 /* We expect this to fail. */
98 if (ntdb_store(ntdb, key, data, NTDB_REPLACE) != NTDB_ERR_LOCK)
99 return 1;
101 if (ntdb_fetch(ntdb, key, &data) != NTDB_ERR_LOCK)
102 return 1;
104 if (tap_log_messages != 2)
105 return 2;
107 /* Child can do this without any complaints. */
108 ntdb_unlockall(ntdb);
109 if (tap_log_messages != 2)
110 return 3;
111 ntdb_close(ntdb);
112 if (tap_log_messages != 2)
113 return 4;
114 return 0;
116 wait(&status);
117 ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
118 ntdb_unlockall(ntdb);
120 ok1(ntdb_lockall_read(ntdb) == NTDB_SUCCESS);
121 if (fork() == 0) {
122 /* We expect this to fail. */
123 /* This would always fail anyway... */
124 if (ntdb_store(ntdb, key, data, NTDB_REPLACE) != NTDB_ERR_LOCK)
125 return 1;
127 if (ntdb_fetch(ntdb, key, &data) != NTDB_ERR_LOCK)
128 return 1;
130 if (tap_log_messages != 2)
131 return 2;
133 /* Child can do this without any complaints. */
134 ntdb_unlockall_read(ntdb);
135 if (tap_log_messages != 2)
136 return 3;
137 ntdb_close(ntdb);
138 if (tap_log_messages != 2)
139 return 4;
140 return 0;
142 wait(&status);
143 ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
144 ntdb_unlockall_read(ntdb);
146 ok1(ntdb_transaction_start(ntdb) == NTDB_SUCCESS);
147 /* If transactions is empty, noop "commit" succeeds. */
148 ok1(ntdb_delete(ntdb, key) == NTDB_SUCCESS);
149 if (fork() == 0) {
150 int last_log_messages;
152 /* We expect this to fail. */
153 if (ntdb_store(ntdb, key, data, NTDB_REPLACE) != NTDB_ERR_LOCK)
154 return 1;
156 if (ntdb_fetch(ntdb, key, &data) != NTDB_ERR_LOCK)
157 return 1;
159 if (tap_log_messages != 2)
160 return 2;
162 if (ntdb_transaction_prepare_commit(ntdb)
163 != NTDB_ERR_LOCK)
164 return 3;
165 if (tap_log_messages == 2)
166 return 4;
168 last_log_messages = tap_log_messages;
169 /* Child can do this without any complaints. */
170 ntdb_transaction_cancel(ntdb);
171 if (tap_log_messages != last_log_messages)
172 return 4;
173 ntdb_close(ntdb);
174 if (tap_log_messages != last_log_messages)
175 return 4;
176 return 0;
178 wait(&status);
179 ok1(WIFEXITED(status) && WEXITSTATUS(status) == 0);
180 ntdb_transaction_cancel(ntdb);
182 ok1(ntdb_parse_record(ntdb, key, fork_in_parse, ntdb)
183 == NTDB_SUCCESS);
184 ntdb_close(ntdb);
185 if (am_child) {
186 /* Child can return from parse without complaints. */
187 if (tap_log_messages != 2)
188 exit(3);
189 exit(0);
191 ok1(tap_log_messages == 0);
193 return exit_status();