torture3: Test lock upgrade/downgrade
[Samba.git] / source3 / torture / test_g_lock.c
blob154b1c168c2412c08709462c066f03b3801243e2
1 /*
2 * Unix SMB/CIFS implementation.
3 * Test g_lock API
4 * Copyright (C) Volker Lendecke 2017
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "torture/proto.h"
22 #include "system/filesys.h"
23 #include "g_lock.h"
24 #include "messages.h"
25 #include "lib/util/server_id.h"
27 static bool get_g_lock_ctx(TALLOC_CTX *mem_ctx,
28 struct tevent_context **ev,
29 struct messaging_context **msg,
30 struct g_lock_ctx **ctx)
32 *ev = samba_tevent_context_init(mem_ctx);
33 if (*ev == NULL) {
34 fprintf(stderr, "tevent_context_init failed\n");
35 return false;
37 *msg = messaging_init(*ev, *ev);
38 if (*msg == NULL) {
39 fprintf(stderr, "messaging_init failed\n");
40 TALLOC_FREE(*ev);
41 return false;
43 *ctx = g_lock_ctx_init(*ev, *msg);
44 if (*ctx == NULL) {
45 fprintf(stderr, "g_lock_ctx_init failed\n");
46 TALLOC_FREE(*msg);
47 TALLOC_FREE(*ev);
48 return false;
51 return true;
54 bool run_g_lock1(int dummy)
56 struct tevent_context *ev = NULL;
57 struct messaging_context *msg = NULL;
58 struct g_lock_ctx *ctx = NULL;
59 const char *lockname = "lock1";
60 NTSTATUS status;
61 bool ret = false;
62 bool ok;
64 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
65 if (!ok) {
66 goto fail;
69 status = g_lock_lock(ctx, lockname, G_LOCK_READ,
70 (struct timeval) { .tv_sec = 1 });
71 if (!NT_STATUS_IS_OK(status)) {
72 fprintf(stderr, "g_lock_lock failed: %s\n",
73 nt_errstr(status));
74 goto fail;
77 status = g_lock_lock(ctx, lockname, G_LOCK_READ,
78 (struct timeval) { .tv_sec = 1 });
79 if (!NT_STATUS_EQUAL(status, NT_STATUS_WAS_LOCKED)) {
80 fprintf(stderr, "Double lock got %s\n",
81 nt_errstr(status));
82 goto fail;
85 status = g_lock_unlock(ctx, lockname);
86 if (!NT_STATUS_IS_OK(status)) {
87 fprintf(stderr, "g_lock_unlock failed: %s\n",
88 nt_errstr(status));
89 goto fail;
92 status = g_lock_unlock(ctx, lockname);
93 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
94 fprintf(stderr, "g_lock_unlock returned: %s\n",
95 nt_errstr(status));
96 goto fail;
99 ret = true;
100 fail:
101 TALLOC_FREE(ctx);
102 TALLOC_FREE(msg);
103 TALLOC_FREE(ev);
104 return ret;
107 struct lock2_parser_state {
108 uint8_t *rdata;
109 bool ok;
112 static void lock2_parser(const struct g_lock_rec *locks,
113 size_t num_locks,
114 const uint8_t *data,
115 size_t datalen,
116 void *private_data)
118 struct lock2_parser_state *state = private_data;
120 if (datalen != sizeof(uint8_t)) {
121 return;
123 *state->rdata = *data;
124 state->ok = true;
128 * Test g_lock_write_data
131 bool run_g_lock2(int dummy)
133 struct tevent_context *ev = NULL;
134 struct messaging_context *msg = NULL;
135 struct g_lock_ctx *ctx = NULL;
136 const char *lockname = "lock2";
137 uint8_t data = 42;
138 uint8_t rdata;
139 struct lock2_parser_state state = { .rdata = &rdata };
140 NTSTATUS status;
141 bool ret = false;
142 bool ok;
144 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
145 if (!ok) {
146 goto fail;
149 status = g_lock_write_data(ctx, lockname, &data, sizeof(data));
150 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_LOCKED)) {
151 fprintf(stderr, "unlocked g_lock_write_data returned %s\n",
152 nt_errstr(status));
153 goto fail;
156 status = g_lock_lock(ctx, lockname, G_LOCK_WRITE,
157 (struct timeval) { .tv_sec = 1 });
158 if (!NT_STATUS_IS_OK(status)) {
159 fprintf(stderr, "g_lock_lock returned %s\n",
160 nt_errstr(status));
161 goto fail;
164 status = g_lock_write_data(ctx, lockname, &data, sizeof(data));
165 if (!NT_STATUS_IS_OK(status)) {
166 fprintf(stderr, "g_lock_write_data failed: %s\n",
167 nt_errstr(status));
168 goto fail;
171 status = g_lock_unlock(ctx, lockname);
172 if (!NT_STATUS_IS_OK(status)) {
173 fprintf(stderr, "g_lock_unlock failed: %s\n",
174 nt_errstr(status));
175 goto fail;
178 status = g_lock_dump(ctx, lockname, lock2_parser, &state);
179 if (!NT_STATUS_IS_OK(status)) {
180 fprintf(stderr, "g_lock_dump failed: %s\n",
181 nt_errstr(status));
182 goto fail;
185 if (!state.ok) {
186 fprintf(stderr, "Could not parse data\n");
187 goto fail;
189 if (rdata != data) {
190 fprintf(stderr, "Returned %"PRIu8", expected %"PRIu8"\n",
191 rdata, data);
192 goto fail;
195 ret = true;
196 fail:
197 TALLOC_FREE(ctx);
198 TALLOC_FREE(msg);
199 TALLOC_FREE(ev);
200 return ret;
203 struct lock3_parser_state {
204 struct server_id self;
205 enum g_lock_type lock_type;
206 bool ok;
209 static void lock3_parser(const struct g_lock_rec *locks,
210 size_t num_locks,
211 const uint8_t *data,
212 size_t datalen,
213 void *private_data)
215 struct lock3_parser_state *state = private_data;
217 if (datalen != 0) {
218 fprintf(stderr, "datalen=%zu\n", datalen);
219 return;
221 if (num_locks != 1) {
222 fprintf(stderr, "num_locks=%zu\n", num_locks);
223 return;
225 if (locks[0].lock_type != state->lock_type) {
226 fprintf(stderr, "found type %d, expected %d\n",
227 (int)locks[0].lock_type, (int)state->lock_type);
228 return;
230 if (!server_id_equal(&locks[0].pid, &state->self)) {
231 struct server_id_buf tmp1, tmp2;
232 fprintf(stderr, "found pid %s, expected %s\n",
233 server_id_str_buf(locks[0].pid, &tmp1),
234 server_id_str_buf(state->self, &tmp2));
235 return;
238 state->ok = true;
242 * Test lock upgrade/downgrade
245 bool run_g_lock3(int dummy)
247 struct tevent_context *ev = NULL;
248 struct messaging_context *msg = NULL;
249 struct g_lock_ctx *ctx = NULL;
250 const char *lockname = "lock3";
251 struct lock3_parser_state state;
252 NTSTATUS status;
253 bool ret = false;
254 bool ok;
256 ok = get_g_lock_ctx(talloc_tos(), &ev, &msg, &ctx);
257 if (!ok) {
258 goto fail;
261 state.self = messaging_server_id(msg);
263 status = g_lock_lock(ctx, lockname, G_LOCK_READ,
264 (struct timeval) { .tv_sec = 1 });
265 if (!NT_STATUS_IS_OK(status)) {
266 fprintf(stderr, "g_lock_lock returned %s\n",
267 nt_errstr(status));
268 goto fail;
271 status = g_lock_lock(ctx, lockname, G_LOCK_READ,
272 (struct timeval) { .tv_sec = 1 });
273 if (!NT_STATUS_EQUAL(status, NT_STATUS_WAS_LOCKED)) {
274 fprintf(stderr, "g_lock_lock returned %s, expected %s\n",
275 nt_errstr(status), nt_errstr(NT_STATUS_WAS_LOCKED));
276 goto fail;
279 state.lock_type = G_LOCK_READ;
280 state.ok = false;
282 status = g_lock_dump(ctx, lockname, lock3_parser, &state);
283 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
284 fprintf(stderr, "g_lock_dump returned %s\n",
285 nt_errstr(status));
286 goto fail;
288 if (!state.ok) {
289 goto fail;
292 status = g_lock_lock(ctx, lockname, G_LOCK_WRITE,
293 (struct timeval) { .tv_sec = 1 });
294 if (!NT_STATUS_IS_OK(status)) {
295 fprintf(stderr, "g_lock_lock returned %s\n",
296 nt_errstr(status));
297 goto fail;
300 state.lock_type = G_LOCK_WRITE;
301 state.ok = false;
303 status = g_lock_dump(ctx, lockname, lock3_parser, &state);
304 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
305 fprintf(stderr, "g_lock_dump returned %s\n",
306 nt_errstr(status));
307 goto fail;
309 if (!state.ok) {
310 goto fail;
314 ret = true;
315 fail:
316 TALLOC_FREE(ctx);
317 TALLOC_FREE(msg);
318 TALLOC_FREE(ev);
319 return ret;