4 Copyright (C) Christof Schmitt 2019
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/>.
21 #include "system/filesys.h"
25 #include "common/ctdb_io.c"
27 void ctdb_set_error(struct ctdb_context *ctdb, const char *fmt, ...)
36 static void test_setup(ctdb_queue_cb_fn_t cb,
38 struct ctdb_context **pctdb,
39 struct ctdb_queue **pqueue)
42 struct ctdb_context *ctdb;
43 struct ctdb_queue *queue;
48 ctdb = talloc_zero(NULL, struct ctdb_context);
51 ctdb->ev = tevent_context_init(NULL);
53 queue = ctdb_queue_setup(ctdb, ctdb, pipefd[0], 0, cb,
55 assert(queue != NULL);
64 static const size_t test1_req_len = 8;
65 static const char *test1_req = "abcdefgh";
67 static void test1_callback(uint8_t *data, size_t length, void *private_data)
71 len = *(uint32_t *)data;
72 assert(len == sizeof(uint32_t) + test1_req_len);
74 assert(length == sizeof(uint32_t) + test1_req_len);
75 assert(memcmp(data + sizeof(len), test1_req, test1_req_len) == 0);
78 static void test1(void)
80 struct ctdb_context *ctdb;
84 test_setup(test1_callback, &fd, &ctdb, NULL);
86 pkt_size = sizeof(uint32_t) + test1_req_len;
87 ret = write(fd, &pkt_size, sizeof(pkt_size));
88 assert(ret == sizeof(pkt_size));
90 ret = write(fd, test1_req, test1_req_len);
91 assert(ret == test1_req_len);
93 tevent_loop_once(ctdb->ev);
98 static const size_t test2_req_len[] = { 900, 24, 600 };
100 static int test2_cb_num = 0;
102 static void test2_callback(uint8_t *data, size_t length, void *private_data)
106 len = *(uint32_t *)data;
107 assert(len == sizeof(uint32_t) + test2_req_len[test2_cb_num]);
108 assert(length == sizeof(uint32_t) + test2_req_len[test2_cb_num]);
113 static void test2(void)
115 struct ctdb_context *ctdb;
118 char req[1024] = { 0 };
120 for (i = 0; i < sizeof(req); i++) {
121 req[i] = i % CHAR_MAX;
124 test_setup(test2_callback, &fd, &ctdb, NULL);
130 pkt_size = sizeof(uint32_t) + test2_req_len[0];
131 ret = write(fd, &pkt_size, sizeof(pkt_size));
132 assert(ret == sizeof(pkt_size));
134 ret = write(fd, req, test2_req_len[0]);
135 assert(ret == test2_req_len[0]);
140 pkt_size = sizeof(uint32_t) + test2_req_len[1];
141 ret = write(fd, &pkt_size, sizeof(pkt_size));
142 assert(ret == sizeof(pkt_size));
145 * Omit the last byte to avoid buffer processing.
147 ret = write(fd, req, test2_req_len[1] - 1);
148 assert(ret == test2_req_len[1] - 1);
150 tevent_loop_once(ctdb->ev);
153 * Write the missing byte now.
155 ret = write(fd, &req[test2_req_len[1] - 1], 1);
161 pkt_size = sizeof(uint32_t) + test2_req_len[2];
162 ret = write(fd, &pkt_size, sizeof(pkt_size));
163 assert(ret == sizeof(pkt_size));
165 ret = write(fd, req, test2_req_len[2]);
166 assert(ret == test2_req_len[2]);
168 tevent_loop_once(ctdb->ev);
169 tevent_loop_once(ctdb->ev);
171 assert(test2_cb_num == 2);
176 static void test_cb(uint8_t *data, size_t length, void *private_data)
178 /* dummy handler, not verifying anything */
182 static void test3(void)
184 struct ctdb_context *ctdb;
185 struct ctdb_queue *queue;
192 test_setup(test_cb, &fd, &ctdb, &queue);
193 request = talloc_zero_size(queue, queue->buffer_size);
196 * calculate a request length which will fit into the buffer
197 * but not twice. Because we need to write the size integer
198 * as well (4-bytes) we're guaranteed that no 2 packets will fit.
200 req_len = queue->buffer_size >> 1;
202 /* writing first packet */
203 pkt_size = sizeof(uint32_t) + req_len;
205 ret = write(fd, &pkt_size, sizeof(pkt_size));
206 assert(ret == sizeof(pkt_size));
208 ret = write(fd, request, req_len);
209 assert(ret == req_len);
211 /* writing second, incomplete packet */
212 pkt_size = sizeof(uint32_t) + req_len;
214 ret = write(fd, &pkt_size, sizeof(pkt_size));
215 assert(ret == sizeof(pkt_size));
217 ret = write(fd, request, req_len >> 1);
218 assert(ret == req_len >> 1);
220 /* process...only 1st packet can be processed */
221 tevent_loop_once(ctdb->ev);
223 /* we should see a progressed offset of req_len + sizeof(pkt_size) */
224 assert(queue->buffer.offset == req_len + sizeof(pkt_size));
226 /* writing another few bytes of the still incomplete packet */
227 ret = write(fd, request, (req_len >> 1) - 1);
228 assert(ret == (req_len >> 1) - 1);
231 * the packet is still incomplete and connot be processed
232 * but the packet data had to be moved in the buffer in order
233 * to fetch the new 199 bytes -> offset must be 0 now.
235 tevent_loop_once(ctdb->ev);
237 * needs to be called twice as an incomplete packet
238 * does not trigger a schedule_immediate
240 tevent_loop_once(ctdb->ev);
242 assert(queue->buffer.offset == 0);
247 static void test4(void)
249 struct ctdb_context *ctdb;
250 struct ctdb_queue *queue;
257 test_setup(test_cb, &fd, &ctdb, &queue);
259 req_len = queue->buffer_size << 1; /* double the buffer size */
260 request = talloc_zero_size(queue, req_len);
262 /* writing first part of packet exceeding standard buffer size */
263 pkt_size = sizeof(uint32_t) + req_len;
265 ret = write(fd, &pkt_size, sizeof(pkt_size));
266 assert(ret == sizeof(pkt_size));
268 ret = write(fd, request, req_len - (queue->buffer_size >> 1));
269 assert(ret == req_len - (queue->buffer_size >> 1));
273 * this needs to be done to have things changed
275 tevent_loop_once(ctdb->ev);
277 * needs to be called twice as an initial incomplete packet
278 * does not trigger a schedule_immediate
280 tevent_loop_once(ctdb->ev);
282 /* the buffer should be resized to packet size now */
283 assert(queue->buffer.size == pkt_size);
285 /* writing remaining data */
286 ret = write(fd, request, queue->buffer_size >> 1);
287 assert(ret == (queue->buffer_size >> 1));
290 tevent_loop_once(ctdb->ev);
293 * the buffer was increased beyond its standard size.
294 * once packet got processed, the buffer has to be free'd
295 * and will be re-allocated with standard size on new request arrival.
298 assert(queue->buffer.size == 0);
300 /* writing new packet to verify standard buffer size */
301 pkt_size = sizeof(uint32_t) + (queue->buffer_size >> 1);
303 ret = write(fd, &pkt_size, sizeof(pkt_size));
304 assert(ret == sizeof(pkt_size));
306 ret = write(fd, request, (queue->buffer_size >> 1));
307 assert(ret == (queue->buffer_size >> 1));
310 tevent_loop_once(ctdb->ev);
312 /* back to standard buffer size */
313 assert(queue->buffer.size == queue->buffer_size);
318 int main(int argc, const char **argv)
323 fprintf(stderr, "%s <testnum>\n", argv[0]);
347 fprintf(stderr, "Unknown test number %s\n", argv[1]);