unix_msg: Lift sockaddr_un handling from unix_msg_send
[Samba.git] / source3 / lib / unix_msg / tests.c
blob37ff3040a4e6866543d18bc7db833523804035f2
1 #include "replace.h"
2 #include "unix_msg.h"
3 #include "poll_funcs/poll_funcs_tevent.h"
4 #include "tevent.h"
6 struct cb_state {
7 unsigned num_received;
8 uint8_t *buf;
9 size_t buflen;
12 static void recv_cb(struct unix_msg_ctx *ctx,
13 uint8_t *msg, size_t msg_len,
14 void *private_data);
16 static void expect_messages(struct tevent_context *ev, struct cb_state *state,
17 unsigned num_msgs)
19 state->num_received = 0;
21 while (state->num_received < num_msgs) {
22 int ret;
24 ret = tevent_loop_once(ev);
25 if (ret == -1) {
26 fprintf(stderr, "tevent_loop_once failed: %s\n",
27 strerror(errno));
28 exit(1);
33 int main(void)
35 struct poll_funcs *funcs;
36 void *tevent_handle;
37 struct sockaddr_un addr1, addr2;
38 struct unix_msg_ctx *ctx1, *ctx2;
39 struct tevent_context *ev;
40 struct iovec iov;
41 uint8_t msg;
42 int i, ret;
43 static uint8_t buf[1755];
45 struct cb_state state;
47 addr1 = (struct sockaddr_un) { .sun_family = AF_UNIX };
48 strlcpy(addr1.sun_path, "sock1", sizeof(addr1.sun_path));
49 unlink(addr1.sun_path);
51 addr2 = (struct sockaddr_un) { .sun_family = AF_UNIX };
52 strlcpy(addr2.sun_path, "sock2", sizeof(addr2.sun_path));
53 unlink(addr2.sun_path);
55 ev = tevent_context_init(NULL);
56 if (ev == NULL) {
57 perror("tevent_context_init failed");
58 return 1;
61 funcs = poll_funcs_init_tevent(ev);
62 if (funcs == NULL) {
63 fprintf(stderr, "poll_funcs_init_tevent failed\n");
64 return 1;
66 tevent_handle = poll_funcs_tevent_register(ev, funcs, ev);
67 if (tevent_handle == NULL) {
68 fprintf(stderr, "poll_funcs_register_tevent failed\n");
69 return 1;
72 ret = unix_msg_init(&addr1, funcs, 256, 1,
73 recv_cb, &state, &ctx1);
74 if (ret != 0) {
75 fprintf(stderr, "unix_msg_init failed: %s\n",
76 strerror(ret));
77 return 1;
80 ret = unix_msg_init(&addr1, funcs, 256, 1,
81 recv_cb, &state, &ctx1);
82 if (ret == 0) {
83 fprintf(stderr, "unix_msg_init succeeded unexpectedly\n");
84 return 1;
86 if (ret != EADDRINUSE) {
87 fprintf(stderr, "unix_msg_init returned %s, expected "
88 "EADDRINUSE\n", strerror(ret));
89 return 1;
92 ret = unix_msg_init(&addr2, funcs, 256, 1,
93 recv_cb, &state, &ctx2);
94 if (ret != 0) {
95 fprintf(stderr, "unix_msg_init failed: %s\n",
96 strerror(ret));
97 return 1;
100 printf("sending a 0-length message\n");
102 state.buf = NULL;
103 state.buflen = 0;
105 ret = unix_msg_send(ctx1, &addr2, NULL, 0);
106 if (ret != 0) {
107 fprintf(stderr, "unix_msg_send failed: %s\n",
108 strerror(ret));
109 return 1;
112 expect_messages(ev, &state, 1);
114 printf("sending a small message\n");
116 msg = random();
117 iov.iov_base = &msg;
118 iov.iov_len = sizeof(msg);
119 state.buf = &msg;
120 state.buflen = sizeof(msg);
122 ret = unix_msg_send(ctx1, &addr2, &iov, 1);
123 if (ret != 0) {
124 fprintf(stderr, "unix_msg_send failed: %s\n",
125 strerror(ret));
126 return 1;
129 expect_messages(ev, &state, 1);
131 printf("sending six large, interleaved messages\n");
133 for (i=0; i<sizeof(buf); i++) {
134 buf[i] = random();
137 iov.iov_base = buf;
138 iov.iov_len = sizeof(buf);
139 state.buf = buf;
140 state.buflen = sizeof(buf);
142 for (i=0; i<3; i++) {
143 ret = unix_msg_send(ctx1, &addr2, &iov, 1);
144 if (ret != 0) {
145 fprintf(stderr, "unix_msg_send failed: %s\n",
146 strerror(ret));
147 return 1;
149 ret = unix_msg_send(ctx2, &addr2, &iov, 1);
150 if (ret != 0) {
151 fprintf(stderr, "unix_msg_send failed: %s\n",
152 strerror(ret));
153 return 1;
157 expect_messages(ev, &state, 6);
159 printf("sending a few messages in small pieces\n");
161 for (i = 0; i<5; i++) {
162 struct iovec iovs[20];
163 const size_t num_iovs = ARRAY_SIZE(iovs);
164 uint8_t *p = buf;
165 size_t j;
167 for (j=0; j<num_iovs-1; j++) {
168 size_t chunk = (random() % ((sizeof(buf) * 2) / num_iovs));
169 size_t space = (sizeof(buf) - (p - buf));
171 if (space == 0) {
172 break;
175 chunk = MIN(chunk, space);
177 iovs[j].iov_base = p;
178 iovs[j].iov_len = chunk;
179 p += chunk;
182 if (p < (buf + sizeof(buf))) {
183 iovs[j].iov_base = p;
184 iovs[j].iov_len = (sizeof(buf) - (p - buf));
185 j++;
188 ret = unix_msg_send(ctx1, &addr1, iovs, j);
189 if (ret != 0) {
190 fprintf(stderr, "unix_msg_send failed: %s\n",
191 strerror(ret));
192 return 1;
196 expect_messages(ev, &state, 5);
198 printf("Filling send queues before freeing\n");
200 for (i=0; i<5; i++) {
201 ret = unix_msg_send(ctx1, &addr2, &iov, 1);
202 if (ret != 0) {
203 fprintf(stderr, "unix_msg_send failed: %s\n",
204 strerror(ret));
205 return 1;
207 ret = unix_msg_send(ctx1, &addr1, &iov, 1);
208 if (ret != 0) {
209 fprintf(stderr, "unix_msg_send failed: %s\n",
210 strerror(ret));
211 return 1;
215 expect_messages(ev, &state, 1); /* Read just one msg */
217 unix_msg_free(ctx1);
218 unix_msg_free(ctx2);
219 talloc_free(tevent_handle);
220 talloc_free(funcs);
221 talloc_free(ev);
223 return 0;
226 static void recv_cb(struct unix_msg_ctx *ctx,
227 uint8_t *msg, size_t msg_len,
228 void *private_data)
230 struct cb_state *state = (struct cb_state *)private_data;
232 if (msg_len != state->buflen) {
233 fprintf(stderr, "expected %u bytes, got %u\n",
234 (unsigned)state->buflen, (unsigned)msg_len);
235 exit(1);
237 if ((msg_len != 0) && (memcmp(msg, state->buf, msg_len) != 0)) {
238 fprintf(stderr, "message content differs\n");
239 exit(1);
241 state->num_received += 1;