xref: /spdk/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c (revision 2bdec64fbfb636f60c0fc6deb704f43a24c3a1eb)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/stdinc.h"
35 
36 #include "spdk_cunit.h"
37 #include "subsystem.h"
38 
39 const struct spdk_nvmf_ctrlr_ops spdk_nvmf_direct_ctrlr_ops;
40 const struct spdk_nvmf_ctrlr_ops spdk_nvmf_virtual_ctrlr_ops;
41 const struct spdk_nvmf_ctrlr_ops spdk_nvmf_discovery_ctrlr_ops;
42 
43 #include "subsystem.c"
44 
45 SPDK_LOG_REGISTER_TRACE_FLAG("nvmf", SPDK_TRACE_NVMF)
46 
47 struct spdk_nvmf_tgt g_nvmf_tgt;
48 
49 struct spdk_nvmf_listen_addr *
50 spdk_nvmf_listen_addr_create(const char *trname, enum spdk_nvmf_adrfam adrfam, const char *traddr,
51 			     const char *trsvcid)
52 {
53 	struct spdk_nvmf_listen_addr *listen_addr;
54 
55 	listen_addr = calloc(1, sizeof(*listen_addr));
56 	if (!listen_addr) {
57 		return NULL;
58 	}
59 
60 	listen_addr->traddr = strdup(traddr);
61 	if (!listen_addr->traddr) {
62 		free(listen_addr);
63 		return NULL;
64 	}
65 
66 	listen_addr->trsvcid = strdup(trsvcid);
67 	if (!listen_addr->trsvcid) {
68 		free(listen_addr->traddr);
69 		free(listen_addr);
70 		return NULL;
71 	}
72 
73 	listen_addr->trname = strdup(trname);
74 	if (!listen_addr->trname) {
75 		free(listen_addr->traddr);
76 		free(listen_addr->trsvcid);
77 		free(listen_addr);
78 		return NULL;
79 	}
80 
81 	listen_addr->adrfam = adrfam;
82 
83 	return listen_addr;
84 }
85 
86 void
87 spdk_nvmf_listen_addr_destroy(struct spdk_nvmf_listen_addr *addr)
88 {
89 	free(addr->trname);
90 	free(addr->trsvcid);
91 	free(addr->traddr);
92 	free(addr);
93 }
94 
95 void
96 spdk_nvmf_listen_addr_cleanup(struct spdk_nvmf_listen_addr *addr)
97 {
98 	return;
99 }
100 
101 static int
102 test_transport1_listen_addr_add(struct spdk_nvmf_listen_addr *listen_addr)
103 {
104 	return 0;
105 }
106 
107 static void
108 test_transport1_listen_addr_discover(struct spdk_nvmf_listen_addr *listen_addr,
109 				     struct spdk_nvmf_discovery_log_page_entry *entry)
110 {
111 	entry->trtype = 42;
112 }
113 
114 static const struct spdk_nvmf_transport test_transport1 = {
115 	.listen_addr_add = test_transport1_listen_addr_add,
116 	.listen_addr_discover = test_transport1_listen_addr_discover,
117 };
118 
119 const struct spdk_nvmf_transport *
120 spdk_nvmf_transport_get(const char *trname)
121 {
122 	if (!strcasecmp(trname, "test_transport1")) {
123 		return &test_transport1;
124 	}
125 
126 	return NULL;
127 }
128 
129 int32_t
130 spdk_nvme_ctrlr_process_admin_completions(struct spdk_nvme_ctrlr *ctrlr)
131 {
132 	return -1;
133 }
134 
135 int32_t
136 spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_completions)
137 {
138 	return -1;
139 }
140 
141 int
142 spdk_nvme_detach(struct spdk_nvme_ctrlr *ctrlr)
143 {
144 	return -1;
145 }
146 
147 void
148 spdk_nvmf_session_destruct(struct spdk_nvmf_session *session)
149 {
150 }
151 
152 int
153 spdk_nvmf_session_poll(struct spdk_nvmf_session *session)
154 {
155 	return -1;
156 }
157 
158 int
159 spdk_bdev_open(struct spdk_bdev *bdev, bool write, spdk_bdev_remove_cb_t remove_cb,
160 	       void *remove_ctx, struct spdk_bdev_desc **desc)
161 {
162 	return 0;
163 }
164 
165 const char *
166 spdk_bdev_get_name(const struct spdk_bdev *bdev)
167 {
168 	return "test";
169 }
170 
171 static void
172 test_spdk_nvmf_tgt_listen(void)
173 {
174 	struct spdk_nvmf_listen_addr *listen_addr;
175 
176 	/* Invalid trname */
177 	const char *trname  = "test_invalid_trname";
178 	enum spdk_nvmf_adrfam adrfam = SPDK_NVMF_ADRFAM_IPV4;
179 	const char *traddr  = "192.168.100.1";
180 	const char *trsvcid = "4420";
181 	CU_ASSERT(spdk_nvmf_tgt_listen(trname, adrfam, traddr, trsvcid) == NULL);
182 
183 	/* Listen addr is not create and create valid listen addr */
184 	trname  = "test_transport1";
185 	adrfam = SPDK_NVMF_ADRFAM_IPV4;
186 	traddr  = "192.168.3.11";
187 	trsvcid = "3320";
188 	listen_addr = spdk_nvmf_tgt_listen(trname, adrfam, traddr, trsvcid);
189 	SPDK_CU_ASSERT_FATAL(listen_addr != NULL);
190 	CU_ASSERT(listen_addr->traddr != NULL);
191 	CU_ASSERT(listen_addr->trsvcid != NULL);
192 	spdk_nvmf_listen_addr_destroy(listen_addr);
193 
194 }
195 
196 static void
197 test_spdk_nvmf_subsystem_add_ns(void)
198 {
199 	struct spdk_nvmf_subsystem subsystem = {
200 		.mode = NVMF_SUBSYSTEM_MODE_VIRTUAL,
201 		.dev.virt.max_nsid = 0,
202 		.dev.virt.ns_list = {},
203 	};
204 	struct spdk_bdev bdev1 = {}, bdev2 = {};
205 	uint32_t nsid;
206 
207 	/* Allow NSID to be assigned automatically */
208 	nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev1, 0);
209 	/* NSID 1 is the first unused ID */
210 	CU_ASSERT(nsid == 1);
211 	CU_ASSERT(subsystem.dev.virt.max_nsid == 1);
212 	CU_ASSERT(subsystem.dev.virt.ns_list[nsid - 1] == &bdev1);
213 
214 	/* Request a specific NSID */
215 	nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev2, 5);
216 	CU_ASSERT(nsid == 5);
217 	CU_ASSERT(subsystem.dev.virt.max_nsid == 5);
218 	CU_ASSERT(subsystem.dev.virt.ns_list[nsid - 1] == &bdev2);
219 
220 	/* Request an NSID that is already in use */
221 	nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev2, 5);
222 	CU_ASSERT(nsid == 0);
223 	CU_ASSERT(subsystem.dev.virt.max_nsid == 5);
224 }
225 
226 static void
227 nvmf_test_create_subsystem(void)
228 {
229 	char nqn[256];
230 	struct spdk_nvmf_subsystem *subsystem;
231 	TAILQ_INIT(&g_nvmf_tgt.subsystems);
232 
233 	strncpy(nqn, "nqn.2016-06.io.spdk:subsystem1", sizeof(nqn));
234 	subsystem = spdk_nvmf_create_subsystem(nqn, SPDK_NVMF_SUBTYPE_NVME,
235 					       NVMF_SUBSYSTEM_MODE_DIRECT, NULL, NULL, NULL);
236 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
237 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
238 	spdk_nvmf_delete_subsystem(subsystem);
239 
240 	/* Longest valid name */
241 	strncpy(nqn, "nqn.2016-06.io.spdk:", sizeof(nqn));
242 	memset(nqn + strlen(nqn), 'a', 223 - strlen(nqn));
243 	nqn[223] = '\0';
244 	CU_ASSERT(strlen(nqn) == 223);
245 	subsystem = spdk_nvmf_create_subsystem(nqn, SPDK_NVMF_SUBTYPE_NVME,
246 					       NVMF_SUBSYSTEM_MODE_DIRECT, NULL, NULL, NULL);
247 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
248 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
249 	spdk_nvmf_delete_subsystem(subsystem);
250 
251 	/* Name that is one byte longer than allowed */
252 	strncpy(nqn, "nqn.2016-06.io.spdk:", sizeof(nqn));
253 	memset(nqn + strlen(nqn), 'a', 224 - strlen(nqn));
254 	nqn[224] = '\0';
255 	CU_ASSERT(strlen(nqn) == 224);
256 	subsystem = spdk_nvmf_create_subsystem(nqn, SPDK_NVMF_SUBTYPE_NVME,
257 					       NVMF_SUBSYSTEM_MODE_DIRECT, NULL, NULL, NULL);
258 	CU_ASSERT(subsystem == NULL);
259 }
260 
261 static void
262 nvmf_test_find_subsystem(void)
263 {
264 	CU_ASSERT_PTR_NULL(spdk_nvmf_find_subsystem(NULL));
265 	CU_ASSERT_PTR_NULL(spdk_nvmf_find_subsystem("fake"));
266 }
267 
268 int main(int argc, char **argv)
269 {
270 	CU_pSuite	suite = NULL;
271 	unsigned int	num_failures;
272 
273 	if (CU_initialize_registry() != CUE_SUCCESS) {
274 		return CU_get_error();
275 	}
276 
277 	suite = CU_add_suite("nvmf", NULL, NULL);
278 	if (suite == NULL) {
279 		CU_cleanup_registry();
280 		return CU_get_error();
281 	}
282 
283 	if (
284 		CU_add_test(suite, "create_subsystem", nvmf_test_create_subsystem) == NULL ||
285 		CU_add_test(suite, "nvmf_tgt_listen", test_spdk_nvmf_tgt_listen) == NULL ||
286 		CU_add_test(suite, "nvmf_subsystem_add_ns", test_spdk_nvmf_subsystem_add_ns) == NULL ||
287 		CU_add_test(suite, "find_subsystem", nvmf_test_find_subsystem) == NULL) {
288 		CU_cleanup_registry();
289 		return CU_get_error();
290 	}
291 
292 	CU_basic_set_mode(CU_BRM_VERBOSE);
293 	CU_basic_run_tests();
294 	num_failures = CU_get_number_of_failures();
295 	CU_cleanup_registry();
296 	return num_failures;
297 }
298