1 #include "../common/tdb_private.h"
2 #include "lock-tracking.h"
3 static ssize_t pwrite_check(int fd, const void *buf, size_t count, off_t offset);
4 static ssize_t write_check(int fd, const void *buf, size_t count);
5 static int ftruncate_check(int fd, off_t length);
7 #define pwrite pwrite_check
8 #define write write_check
9 #define fcntl fcntl_with_lockcheck
10 #define ftruncate ftruncate_check
12 #include "../common/io.c"
13 #include "../common/tdb.c"
14 #include "../common/lock.c"
15 #include "../common/freelist.c"
16 #include "../common/traverse.c"
17 #include "../common/transaction.c"
18 #include "../common/error.c"
19 #include "../common/open.c"
20 #include "../common/check.c"
21 #include "../common/hash.c"
22 #include "../common/mutex.c"
23 #include "tap-interface.h"
27 #include "external-agent.h"
35 static int target, current;
36 #define TEST_DBNAME "run-mutex-die.tdb"
37 #define KEY_STRING "helloworld"
39 static void maybe_die(int fd)
45 if (current == target) {
50 static ssize_t pwrite_check(int fd,
51 const void *buf, size_t count, off_t offset)
57 ret = pwrite(fd, buf, count, offset);
65 static ssize_t write_check(int fd, const void *buf, size_t count)
71 ret = write(fd, buf, count);
79 static int ftruncate_check(int fd, off_t length)
85 ret = ftruncate(fd, length);
91 static enum agent_return flakey_ops(struct agent *a)
93 enum agent_return ret;
96 * Run in the external agent child
99 ret = external_agent_operation(a, OPEN_WITH_CLEAR_IF_FIRST, TEST_DBNAME);
100 if (ret != SUCCESS) {
101 fprintf(stderr, "Agent failed to open: %s\n",
102 agent_return_name(ret));
105 ret = external_agent_operation(a, UNMAP, "");
106 if (ret != SUCCESS) {
107 fprintf(stderr, "Agent failed to unmap: %s\n",
108 agent_return_name(ret));
111 ret = external_agent_operation(a, STORE, "xyz");
112 if (ret != SUCCESS) {
113 fprintf(stderr, "Agent failed to store: %s\n",
114 agent_return_name(ret));
117 ret = external_agent_operation(a, STORE, KEY_STRING);
118 if (ret != SUCCESS) {
119 fprintf(stderr, "Agent failed store: %s\n",
120 agent_return_name(ret));
123 ret = external_agent_operation(a, FETCH, KEY_STRING);
124 if (ret != SUCCESS) {
125 fprintf(stderr, "Agent failed find key: %s\n",
126 agent_return_name(ret));
129 ret = external_agent_operation(a, PING, "");
130 if (ret != SUCCESS) {
131 fprintf(stderr, "Agent failed ping: %s\n",
132 agent_return_name(ret));
138 static bool prep_db(void) {
139 struct tdb_context *tdb;
143 key.dptr = discard_const_p(uint8_t, KEY_STRING);
144 key.dsize = strlen((char *)key.dptr);
145 data.dptr = discard_const_p(uint8_t, "foo");
146 data.dsize = strlen((char *)data.dptr);
152 TDB_INCOMPATIBLE_HASH|TDB_MUTEX_LOCKING|TDB_CLEAR_IF_FIRST,
153 O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL);
158 if (tdb_store(tdb, key, data, TDB_INSERT) != 0) {
170 static bool test_db(void) {
171 struct tdb_context *tdb;
175 TEST_DBNAME, 1024, TDB_INCOMPATIBLE_HASH,
176 O_RDWR, 0600, &taplogctx, NULL);
179 perror("tdb_open_ex failed");
183 ret = tdb_traverse(tdb, NULL, NULL);
185 perror("traverse failed");
200 static bool test_one(void)
202 enum agent_return ret;
207 while (ret != SUCCESS) {
211 int child_target = target;
216 target = child_target;
219 agent = prepare_external_agent();
221 ret = flakey_ops(agent);
223 diag("Agent (target=%d) returns %s",
224 target, agent_return_name(ret));
226 if (ret == SUCCESS) {
227 ok((target > 19), "At least one AGENT_DIED expected");
229 ok(ret == AGENT_DIED, "AGENT_DIED expected");
232 shutdown_agent(agent);
235 int child_target = target;
240 target = child_target;
249 int main(int argc, char *argv[])
252 bool runtime_support;
254 runtime_support = tdb_runtime_check_for_robust_mutexes();
256 if (!runtime_support) {
257 skip(1, "No robust mutex support");
258 return exit_status();
262 unlock_callback = maybe_die;
268 return exit_status();