Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2019 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/stdinc.h"
7 : : #include "spdk/util.h"
8 : :
9 : : #include "spdk_internal/mock.h"
10 : :
11 : : #include "spdk_internal/cunit.h"
12 : :
13 : : #include "common/lib/test_env.c"
14 : : #include "sock/uring/uring.c"
15 : :
16 : 0 : DEFINE_STUB(spdk_sock_map_insert, int, (struct spdk_sock_map *map, int placement_id,
17 : : struct spdk_sock_group_impl *group), 0);
18 : 0 : DEFINE_STUB_V(spdk_sock_map_release, (struct spdk_sock_map *map, int placement_id));
19 : 0 : DEFINE_STUB(spdk_sock_map_lookup, int, (struct spdk_sock_map *map, int placement_id,
20 : : struct spdk_sock_group_impl **group, struct spdk_sock_group_impl *hint), 0);
21 : 0 : DEFINE_STUB(spdk_sock_map_find_free, int, (struct spdk_sock_map *map), -1);
22 : 3 : DEFINE_STUB_V(spdk_sock_map_cleanup, (struct spdk_sock_map *map));
23 : :
24 : 3 : DEFINE_STUB_V(spdk_net_impl_register, (struct spdk_net_impl *impl, int priority));
25 : 0 : DEFINE_STUB(spdk_sock_close, int, (struct spdk_sock **s), 0);
26 : 0 : DEFINE_STUB(io_uring_submit, int, (struct io_uring *ring), 0);
27 : 0 : DEFINE_STUB(io_uring_queue_init, int, (unsigned entries, struct io_uring *ring, unsigned flags), 0);
28 : 0 : DEFINE_STUB_V(io_uring_queue_exit, (struct io_uring *ring));
29 : 0 : DEFINE_STUB(spdk_sock_group_provide_buf, int, (struct spdk_sock_group *group, void *buf,
30 : : size_t len, void *ctx), 0);
31 : 0 : DEFINE_STUB(spdk_sock_group_get_buf, size_t, (struct spdk_sock_group *group, void **buf,
32 : : void **ctx), 0);
33 : :
34 : : static void
35 : 27 : _req_cb(void *cb_arg, int len)
36 : : {
37 [ + - ]: 27 : *(bool *)cb_arg = true;
38 : 27 : CU_ASSERT(len == 0);
39 : 27 : }
40 : :
41 : : static void
42 : 3 : flush_client(void)
43 : : {
44 : 3 : struct spdk_uring_sock_group_impl group = {};
45 : 3 : struct spdk_uring_sock usock = {};
46 : 3 : struct spdk_sock *sock = &usock.base;
47 : 1 : struct spdk_sock_request *req1, *req2;
48 : 2 : bool cb_arg1, cb_arg2;
49 : 1 : int rc;
50 : :
51 : : /* Set up data structures */
52 [ + - + - : 3 : TAILQ_INIT(&sock->queued_reqs);
+ - + - +
- + - + -
+ - ]
53 [ + - + - : 3 : TAILQ_INIT(&sock->pending_reqs);
+ - + - +
- + - + -
+ - ]
54 [ + - + - ]: 3 : sock->group_impl = &group.base;
55 : :
56 : 3 : req1 = calloc(1, sizeof(struct spdk_sock_request) + 3 * sizeof(struct iovec));
57 [ + + # # ]: 3 : SPDK_CU_ASSERT_FATAL(req1 != NULL);
58 [ + - + - : 3 : SPDK_SOCK_REQUEST_IOV(req1, 0)->iov_base = (void *)100;
+ - + - ]
59 [ + - + - : 3 : SPDK_SOCK_REQUEST_IOV(req1, 0)->iov_len = 64;
+ - + - ]
60 [ + - + - : 3 : SPDK_SOCK_REQUEST_IOV(req1, 1)->iov_base = (void *)200;
+ - + - ]
61 [ + - + - : 3 : SPDK_SOCK_REQUEST_IOV(req1, 1)->iov_len = 64;
+ - + - ]
62 [ + - + - : 3 : SPDK_SOCK_REQUEST_IOV(req1, 2)->iov_base = (void *)300;
+ - + - ]
63 [ + - + - : 3 : SPDK_SOCK_REQUEST_IOV(req1, 2)->iov_len = 64;
+ - + - ]
64 [ + - + - ]: 3 : req1->iovcnt = 3;
65 [ + - + - ]: 3 : req1->cb_fn = _req_cb;
66 [ + - + - ]: 3 : req1->cb_arg = &cb_arg1;
67 : :
68 : 3 : req2 = calloc(1, sizeof(struct spdk_sock_request) + 2 * sizeof(struct iovec));
69 [ + + # # ]: 3 : SPDK_CU_ASSERT_FATAL(req2 != NULL);
70 [ + - + - : 3 : SPDK_SOCK_REQUEST_IOV(req2, 0)->iov_base = (void *)100;
+ - + - ]
71 [ + - + - : 3 : SPDK_SOCK_REQUEST_IOV(req2, 0)->iov_len = 32;
+ - + - ]
72 [ + - + - : 3 : SPDK_SOCK_REQUEST_IOV(req2, 1)->iov_base = (void *)200;
+ - + - ]
73 [ + - + - : 3 : SPDK_SOCK_REQUEST_IOV(req2, 1)->iov_len = 32;
+ - + - ]
74 [ + - + - ]: 3 : req2->iovcnt = 2;
75 [ + - + - ]: 3 : req2->cb_fn = _req_cb;
76 [ + - + - ]: 3 : req2->cb_arg = &cb_arg2;
77 : :
78 : : /* Simple test - a request with a 3 element iovec
79 : : * that gets submitted in a single sendmsg. */
80 : 3 : spdk_sock_request_queue(sock, req1);
81 : 3 : MOCK_SET(sendmsg, 192);
82 : 3 : cb_arg1 = false;
83 : 3 : rc = uring_sock_flush(sock);
84 : 3 : CU_ASSERT(rc == 192);
85 [ + + ]: 3 : CU_ASSERT(cb_arg1 == true);
86 [ + - + - : 3 : CU_ASSERT(TAILQ_EMPTY(&sock->queued_reqs));
+ - ]
87 : :
88 : : /* Two requests, where both can fully send. */
89 : 3 : spdk_sock_request_queue(sock, req1);
90 : 3 : spdk_sock_request_queue(sock, req2);
91 : 3 : MOCK_SET(sendmsg, 256);
92 : 3 : cb_arg1 = false;
93 : 3 : cb_arg2 = false;
94 : 3 : rc = uring_sock_flush(sock);
95 : 3 : CU_ASSERT(rc == 256);
96 [ + + ]: 3 : CU_ASSERT(cb_arg1 == true);
97 [ + + ]: 3 : CU_ASSERT(cb_arg2 == true);
98 [ + - + - : 3 : CU_ASSERT(TAILQ_EMPTY(&sock->queued_reqs));
+ - ]
99 : :
100 : : /* Two requests. Only first one can send */
101 : 3 : spdk_sock_request_queue(sock, req1);
102 : 3 : spdk_sock_request_queue(sock, req2);
103 : 3 : MOCK_SET(sendmsg, 192);
104 : 3 : cb_arg1 = false;
105 : 3 : cb_arg2 = false;
106 : 3 : rc = uring_sock_flush(sock);
107 : 3 : CU_ASSERT(rc == 192);
108 [ + + ]: 3 : CU_ASSERT(cb_arg1 == true);
109 [ + + ]: 3 : CU_ASSERT(cb_arg2 == false);
110 [ + - + - : 3 : CU_ASSERT(TAILQ_FIRST(&sock->queued_reqs) == req2);
+ - ]
111 [ + + + - : 3 : TAILQ_REMOVE(&sock->queued_reqs, req2, internal.link);
+ - + - -
+ # # # #
# # # # #
# # # # #
# # # # #
# # # # #
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - ]
112 [ + - + - : 3 : CU_ASSERT(TAILQ_EMPTY(&sock->queued_reqs));
+ - ]
113 : :
114 : : /* One request. Partial send. */
115 : 3 : spdk_sock_request_queue(sock, req1);
116 : 3 : MOCK_SET(sendmsg, 10);
117 : 3 : cb_arg1 = false;
118 : 3 : rc = uring_sock_flush(sock);
119 : 3 : CU_ASSERT(rc == 10);
120 [ + + ]: 3 : CU_ASSERT(cb_arg1 == false);
121 [ + - + - : 3 : CU_ASSERT(TAILQ_FIRST(&sock->queued_reqs) == req1);
+ - ]
122 : :
123 : : /* Do a second flush that partial sends again. */
124 : 3 : MOCK_SET(sendmsg, 52);
125 : 3 : cb_arg1 = false;
126 : 3 : rc = uring_sock_flush(sock);
127 : 3 : CU_ASSERT(rc == 52);
128 [ + + ]: 3 : CU_ASSERT(cb_arg1 == false);
129 [ + - + - : 3 : CU_ASSERT(TAILQ_FIRST(&sock->queued_reqs) == req1);
+ - ]
130 : :
131 : : /* Flush the rest of the data */
132 : 3 : MOCK_SET(sendmsg, 130);
133 : 3 : cb_arg1 = false;
134 : 3 : rc = uring_sock_flush(sock);
135 : 3 : CU_ASSERT(rc == 130);
136 [ + + ]: 3 : CU_ASSERT(cb_arg1 == true);
137 [ + - + - : 3 : CU_ASSERT(TAILQ_EMPTY(&sock->queued_reqs));
+ - ]
138 : :
139 : 3 : free(req1);
140 : 3 : free(req2);
141 : 3 : }
142 : :
143 : : static void
144 : 3 : flush_server(void)
145 : : {
146 : 3 : struct spdk_uring_sock_group_impl group = {};
147 : 3 : struct spdk_uring_sock usock = {};
148 : 3 : struct spdk_sock *sock = &usock.base;
149 : 1 : struct spdk_sock_request *req1, *req2;
150 : 2 : bool cb_arg1, cb_arg2;
151 : 1 : int rc;
152 : :
153 : : /* Set up data structures */
154 [ + - + - : 3 : TAILQ_INIT(&sock->queued_reqs);
+ - + - +
- + - + -
+ - ]
155 [ + - + - : 3 : TAILQ_INIT(&sock->pending_reqs);
+ - + - +
- + - + -
+ - ]
156 [ + - + - ]: 3 : sock->group_impl = &group.base;
157 [ + - + - ]: 3 : usock.write_task.sock = &usock;
158 [ + - ]: 3 : usock.group = &group;
159 : :
160 : 3 : req1 = calloc(1, sizeof(struct spdk_sock_request) + 2 * sizeof(struct iovec));
161 [ + + # # ]: 3 : SPDK_CU_ASSERT_FATAL(req1 != NULL);
162 [ + - + - : 3 : SPDK_SOCK_REQUEST_IOV(req1, 0)->iov_base = (void *)100;
+ - + - ]
163 [ + - + - : 3 : SPDK_SOCK_REQUEST_IOV(req1, 0)->iov_len = 64;
+ - + - ]
164 [ + - + - : 3 : SPDK_SOCK_REQUEST_IOV(req1, 1)->iov_base = (void *)200;
+ - + - ]
165 [ + - + - : 3 : SPDK_SOCK_REQUEST_IOV(req1, 1)->iov_len = 64;
+ - + - ]
166 [ + - + - ]: 3 : req1->iovcnt = 2;
167 [ + - + - ]: 3 : req1->cb_fn = _req_cb;
168 [ + - + - ]: 3 : req1->cb_arg = &cb_arg1;
169 : :
170 : 3 : req2 = calloc(1, sizeof(struct spdk_sock_request) + 2 * sizeof(struct iovec));
171 [ + + # # ]: 3 : SPDK_CU_ASSERT_FATAL(req2 != NULL);
172 [ + - + - : 3 : SPDK_SOCK_REQUEST_IOV(req2, 0)->iov_base = (void *)100;
+ - + - ]
173 [ + - + - : 3 : SPDK_SOCK_REQUEST_IOV(req2, 0)->iov_len = 32;
+ - + - ]
174 [ + - + - : 3 : SPDK_SOCK_REQUEST_IOV(req2, 1)->iov_base = (void *)200;
+ - + - ]
175 [ + - + - : 3 : SPDK_SOCK_REQUEST_IOV(req2, 1)->iov_len = 32;
+ - + - ]
176 [ + - + - ]: 3 : req2->iovcnt = 2;
177 [ + - + - ]: 3 : req2->cb_fn = _req_cb;
178 [ + - + - ]: 3 : req2->cb_arg = &cb_arg2;
179 : :
180 : : /* we should not call _sock_flush directly, since it will finally
181 : : * call liburing related functions */
182 : :
183 : : /* Simple test - a request with a 2 element iovec
184 : : * that is fully completed. */
185 : 3 : spdk_sock_request_queue(sock, req1);
186 : 3 : cb_arg1 = false;
187 [ + - ]: 3 : rc = spdk_sock_prep_reqs(sock, usock.write_task.iovs, 0, NULL, NULL);
188 : 3 : CU_ASSERT(rc == 2);
189 : 3 : sock_complete_write_reqs(sock, 128, 0);
190 [ + + ]: 3 : CU_ASSERT(cb_arg1 == true);
191 [ + - + - : 3 : CU_ASSERT(TAILQ_EMPTY(&sock->queued_reqs));
+ - ]
192 : :
193 : : /* Two requests, where both can be fully completed. */
194 : 3 : spdk_sock_request_queue(sock, req1);
195 : 3 : spdk_sock_request_queue(sock, req2);
196 : 3 : cb_arg1 = false;
197 : 3 : cb_arg2 = false;
198 [ + - ]: 3 : rc = spdk_sock_prep_reqs(sock, usock.write_task.iovs, 0, NULL, NULL);
199 : 3 : CU_ASSERT(rc == 4);
200 : 3 : sock_complete_write_reqs(sock, 192, 0);
201 [ + + ]: 3 : CU_ASSERT(cb_arg1 == true);
202 [ + + ]: 3 : CU_ASSERT(cb_arg2 == true);
203 [ + - + - : 3 : CU_ASSERT(TAILQ_EMPTY(&sock->queued_reqs));
+ - ]
204 : :
205 : :
206 : : /* One request that is partially sent. */
207 : 3 : spdk_sock_request_queue(sock, req1);
208 : 3 : cb_arg1 = false;
209 [ + - ]: 3 : rc = spdk_sock_prep_reqs(sock, usock.write_task.iovs, 0, NULL, NULL);
210 : 3 : CU_ASSERT(rc == 2);
211 : 3 : sock_complete_write_reqs(sock, 92, 0);
212 : 3 : CU_ASSERT(rc == 2);
213 [ + + ]: 3 : CU_ASSERT(cb_arg1 == false);
214 [ + - + - : 3 : CU_ASSERT(TAILQ_FIRST(&sock->queued_reqs) == req1);
+ - ]
215 : :
216 : : /* Get the second time partial sent result. */
217 : 3 : sock_complete_write_reqs(sock, 10, 0);
218 [ + + ]: 3 : CU_ASSERT(cb_arg1 == false);
219 [ + - + - : 3 : CU_ASSERT(TAILQ_FIRST(&sock->queued_reqs) == req1);
+ - ]
220 : :
221 : : /* Data is finally sent. */
222 : 3 : sock_complete_write_reqs(sock, 26, 0);
223 [ + + ]: 3 : CU_ASSERT(cb_arg1 == true);
224 [ + - + - : 3 : CU_ASSERT(TAILQ_EMPTY(&sock->queued_reqs));
+ - ]
225 : :
226 : 3 : free(req1);
227 : 3 : free(req2);
228 : 3 : }
229 : :
230 : : int
231 : 3 : main(int argc, char **argv)
232 : : {
233 : 3 : CU_pSuite suite = NULL;
234 : 1 : unsigned int num_failures;
235 : :
236 : 3 : CU_initialize_registry();
237 : :
238 : 3 : suite = CU_add_suite("uring", NULL, NULL);
239 : :
240 : :
241 : 3 : CU_ADD_TEST(suite, flush_client);
242 : 3 : CU_ADD_TEST(suite, flush_server);
243 : :
244 : :
245 : 3 : num_failures = spdk_ut_run_tests(argc, argv, NULL);
246 : :
247 : 3 : CU_cleanup_registry();
248 : :
249 : 4 : return num_failures;
250 : 1 : }
|