xref: /spdk/test/unit/lib/sock/posix.c/posix_ut.c (revision 588dfe314bb83d86effdf67ec42837b11c2620bf)
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_cunit.h"
12 
13 #include "common/lib/test_env.c"
14 #include "sock/posix/posix.c"
15 
16 DEFINE_STUB(spdk_sock_map_insert, int, (struct spdk_sock_map *map, int placement_id,
17 					struct spdk_sock_group_impl *group), 0);
18 DEFINE_STUB_V(spdk_sock_map_release, (struct spdk_sock_map *map, int placement_id));
19 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 DEFINE_STUB(spdk_sock_map_find_free, int, (struct spdk_sock_map *map), -1);
22 DEFINE_STUB_V(spdk_sock_map_cleanup, (struct spdk_sock_map *map));
23 
24 DEFINE_STUB_V(spdk_net_impl_register, (struct spdk_net_impl *impl, int priority));
25 DEFINE_STUB(spdk_sock_close, int, (struct spdk_sock **s), 0);
26 
27 static void
28 _req_cb(void *cb_arg, int len)
29 {
30 	*(bool *)cb_arg = true;
31 	CU_ASSERT(len == 0);
32 }
33 
34 static void
35 flush(void)
36 {
37 	struct spdk_posix_sock_group_impl group = {};
38 	struct spdk_posix_sock psock = {};
39 	struct spdk_sock *sock = &psock.base;
40 	struct spdk_sock_request *req1, *req2;
41 	bool cb_arg1, cb_arg2;
42 	int rc;
43 
44 	/* Set up data structures */
45 	TAILQ_INIT(&sock->queued_reqs);
46 	TAILQ_INIT(&sock->pending_reqs);
47 	sock->group_impl = &group.base;
48 
49 	req1 = calloc(1, sizeof(struct spdk_sock_request) + 2 * sizeof(struct iovec));
50 	SPDK_CU_ASSERT_FATAL(req1 != NULL);
51 	SPDK_SOCK_REQUEST_IOV(req1, 0)->iov_base = (void *)100;
52 	SPDK_SOCK_REQUEST_IOV(req1, 0)->iov_len = 32;
53 	SPDK_SOCK_REQUEST_IOV(req1, 1)->iov_base = (void *)200;
54 	SPDK_SOCK_REQUEST_IOV(req1, 1)->iov_len = 32;
55 	req1->iovcnt = 2;
56 	req1->cb_fn = _req_cb;
57 	req1->cb_arg = &cb_arg1;
58 
59 	req2 = calloc(1, sizeof(struct spdk_sock_request) + 2 * sizeof(struct iovec));
60 	SPDK_CU_ASSERT_FATAL(req2 != NULL);
61 	SPDK_SOCK_REQUEST_IOV(req2, 0)->iov_base = (void *)100;
62 	SPDK_SOCK_REQUEST_IOV(req2, 0)->iov_len = 32;
63 	SPDK_SOCK_REQUEST_IOV(req2, 1)->iov_base = (void *)200;
64 	SPDK_SOCK_REQUEST_IOV(req2, 1)->iov_len = 32;
65 	req2->iovcnt = 2;
66 	req2->cb_fn = _req_cb;
67 	req2->cb_arg = &cb_arg2;
68 
69 	/* Simple test - a request with a 2 element iovec
70 	 * that gets submitted in a single sendmsg. */
71 	spdk_sock_request_queue(sock, req1);
72 	MOCK_SET(sendmsg, 64);
73 	cb_arg1 = false;
74 	rc = _sock_flush(sock);
75 	CU_ASSERT(rc == 0);
76 	CU_ASSERT(cb_arg1 == true);
77 	CU_ASSERT(TAILQ_EMPTY(&sock->queued_reqs));
78 
79 	/* Two requests, where both can fully send. */
80 	spdk_sock_request_queue(sock, req1);
81 	spdk_sock_request_queue(sock, req2);
82 	MOCK_SET(sendmsg, 128);
83 	cb_arg1 = false;
84 	cb_arg2 = false;
85 	rc = _sock_flush(sock);
86 	CU_ASSERT(rc == 0);
87 	CU_ASSERT(cb_arg1 == true);
88 	CU_ASSERT(cb_arg2 == true);
89 	CU_ASSERT(TAILQ_EMPTY(&sock->queued_reqs));
90 
91 	/* Two requests. Only first one can send */
92 	spdk_sock_request_queue(sock, req1);
93 	spdk_sock_request_queue(sock, req2);
94 	MOCK_SET(sendmsg, 64);
95 	cb_arg1 = false;
96 	cb_arg2 = false;
97 	rc = _sock_flush(sock);
98 	CU_ASSERT(rc == 0);
99 	CU_ASSERT(cb_arg1 == true);
100 	CU_ASSERT(cb_arg2 == false);
101 	CU_ASSERT(TAILQ_FIRST(&sock->queued_reqs) == req2);
102 	TAILQ_REMOVE(&sock->queued_reqs, req2, internal.link);
103 	CU_ASSERT(TAILQ_EMPTY(&sock->queued_reqs));
104 
105 	/* One request. Partial send. */
106 	spdk_sock_request_queue(sock, req1);
107 	MOCK_SET(sendmsg, 10);
108 	cb_arg1 = false;
109 	rc = _sock_flush(sock);
110 	CU_ASSERT(rc == 0);
111 	CU_ASSERT(cb_arg1 == false);
112 	CU_ASSERT(TAILQ_FIRST(&sock->queued_reqs) == req1);
113 
114 	/* Do a second flush that partial sends again. */
115 	MOCK_SET(sendmsg, 24);
116 	cb_arg1 = false;
117 	rc = _sock_flush(sock);
118 	CU_ASSERT(rc == 0);
119 	CU_ASSERT(cb_arg1 == false);
120 	CU_ASSERT(TAILQ_FIRST(&sock->queued_reqs) == req1);
121 
122 	/* Flush the rest of the data */
123 	MOCK_SET(sendmsg, 30);
124 	cb_arg1 = false;
125 	rc = _sock_flush(sock);
126 	CU_ASSERT(rc == 0);
127 	CU_ASSERT(cb_arg1 == true);
128 	CU_ASSERT(TAILQ_EMPTY(&sock->queued_reqs));
129 
130 	free(req1);
131 	free(req2);
132 }
133 
134 int
135 main(int argc, char **argv)
136 {
137 	CU_pSuite	suite = NULL;
138 	unsigned int	num_failures;
139 
140 	CU_set_error_action(CUEA_ABORT);
141 	CU_initialize_registry();
142 
143 	suite = CU_add_suite("posix", NULL, NULL);
144 
145 	CU_ADD_TEST(suite, flush);
146 
147 	CU_basic_set_mode(CU_BRM_VERBOSE);
148 
149 	CU_basic_run_tests();
150 
151 	num_failures = CU_get_number_of_failures();
152 	CU_cleanup_registry();
153 
154 	return num_failures;
155 }
156