xref: /spdk/test/common/lib/test_env.c (revision c94020001adcc0d8fae89ff7902e2e0f2243e25d)
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_internal/mock.h"
37 
38 #include "spdk/env.h"
39 #include "spdk/queue.h"
40 
41 DEFINE_STUB(spdk_process_is_primary, bool, (void), true)
42 DEFINE_STUB(spdk_memzone_lookup, void *, (const char *name), NULL)
43 
44 /*
45  * These mocks don't use the DEFINE_STUB macros because
46  * their default implementation is more complex.
47  */
48 
49 DEFINE_RETURN_MOCK(spdk_memzone_reserve, void *);
50 void *
51 spdk_memzone_reserve(const char *name, size_t len, int socket_id, unsigned flags)
52 {
53 	HANDLE_RETURN_MOCK(spdk_memzone_reserve);
54 
55 	return malloc(len);
56 }
57 
58 DEFINE_RETURN_MOCK(spdk_memzone_reserve_aligned, void *);
59 void *
60 spdk_memzone_reserve_aligned(const char *name, size_t len, int socket_id,
61 			     unsigned flags, unsigned align)
62 {
63 	HANDLE_RETURN_MOCK(spdk_memzone_reserve_aligned);
64 
65 	return malloc(len);
66 }
67 
68 DEFINE_RETURN_MOCK(spdk_malloc, void *);
69 void *
70 spdk_malloc(size_t size, size_t align, uint64_t *phys_addr, int socket_id, uint32_t flags)
71 {
72 	HANDLE_RETURN_MOCK(spdk_malloc);
73 
74 	void *buf = NULL;
75 	if (posix_memalign(&buf, align, size)) {
76 		return NULL;
77 	}
78 	if (phys_addr) {
79 		*phys_addr = (uint64_t)buf;
80 	}
81 
82 	return buf;
83 }
84 
85 DEFINE_RETURN_MOCK(spdk_zmalloc, void *);
86 void *
87 spdk_zmalloc(size_t size, size_t align, uint64_t *phys_addr, int socket_id, uint32_t flags)
88 {
89 	HANDLE_RETURN_MOCK(spdk_zmalloc);
90 
91 	void *buf = spdk_malloc(size, align, phys_addr, -1, 1);
92 
93 	if (buf != NULL) {
94 		memset(buf, 0, size);
95 	}
96 	return buf;
97 }
98 
99 DEFINE_RETURN_MOCK(spdk_dma_malloc, void *);
100 void *
101 spdk_dma_malloc(size_t size, size_t align, uint64_t *phys_addr)
102 {
103 	HANDLE_RETURN_MOCK(spdk_dma_malloc);
104 
105 	return spdk_malloc(size, align, phys_addr, -1, 1);
106 }
107 
108 DEFINE_RETURN_MOCK(spdk_dma_zmalloc, void *);
109 void *
110 spdk_dma_zmalloc(size_t size, size_t align, uint64_t *phys_addr)
111 {
112 	HANDLE_RETURN_MOCK(spdk_dma_zmalloc);
113 
114 	return spdk_zmalloc(size, align, phys_addr, -1, 1);
115 }
116 
117 DEFINE_RETURN_MOCK(spdk_dma_malloc_socket, void *);
118 void *
119 spdk_dma_malloc_socket(size_t size, size_t align, uint64_t *phys_addr, int socket_id)
120 {
121 	HANDLE_RETURN_MOCK(spdk_dma_malloc_socket);
122 
123 	return spdk_dma_malloc(size, align, phys_addr);
124 }
125 
126 DEFINE_RETURN_MOCK(spdk_dma_zmalloc_socket, void *);
127 void *
128 spdk_dma_zmalloc_socket(size_t size, size_t align, uint64_t *phys_addr, int socket_id)
129 {
130 	HANDLE_RETURN_MOCK(spdk_dma_zmalloc_socket);
131 
132 	return spdk_dma_zmalloc(size, align, phys_addr);
133 }
134 
135 DEFINE_RETURN_MOCK(spdk_dma_realloc, void *);
136 void *
137 spdk_dma_realloc(void *buf, size_t size, size_t align, uint64_t *phys_addr)
138 {
139 	HANDLE_RETURN_MOCK(spdk_dma_realloc);
140 
141 	return realloc(buf, size);
142 }
143 
144 void
145 spdk_free(void *buf)
146 {
147 	free(buf);
148 }
149 
150 void
151 spdk_dma_free(void *buf)
152 {
153 	return spdk_free(buf);
154 }
155 
156 DEFINE_RETURN_MOCK(spdk_vtophys, uint64_t);
157 uint64_t
158 spdk_vtophys(void *buf)
159 {
160 	HANDLE_RETURN_MOCK(spdk_vtophys);
161 
162 	return (uintptr_t)buf;
163 }
164 
165 void
166 spdk_memzone_dump(FILE *f)
167 {
168 	return;
169 }
170 
171 DEFINE_RETURN_MOCK(spdk_memzone_free, int);
172 int
173 spdk_memzone_free(const char *name)
174 {
175 	HANDLE_RETURN_MOCK(spdk_memzone_free);
176 
177 	return 0;
178 }
179 
180 struct test_mempool {
181 	size_t	count;
182 };
183 
184 DEFINE_RETURN_MOCK(spdk_mempool_create, struct spdk_mempool *);
185 struct spdk_mempool *
186 spdk_mempool_create(const char *name, size_t count,
187 		    size_t ele_size, size_t cache_size, int socket_id)
188 {
189 	struct test_mempool *mp;
190 
191 	HANDLE_RETURN_MOCK(spdk_mempool_create);
192 
193 	mp = calloc(1, sizeof(*mp));
194 	if (mp == NULL) {
195 		return NULL;
196 	}
197 
198 	mp->count = count;
199 
200 	return (struct spdk_mempool *)mp;
201 }
202 
203 void
204 spdk_mempool_free(struct spdk_mempool *_mp)
205 {
206 	struct test_mempool *mp = (struct test_mempool *)_mp;
207 
208 	free(mp);
209 }
210 
211 DEFINE_RETURN_MOCK(spdk_mempool_get, void *);
212 void *
213 spdk_mempool_get(struct spdk_mempool *_mp)
214 {
215 	struct test_mempool *mp = (struct test_mempool *)_mp;
216 	void *buf;
217 
218 	HANDLE_RETURN_MOCK(spdk_mempool_get);
219 
220 	if (mp && mp->count == 0) {
221 		return NULL;
222 	}
223 
224 	if (posix_memalign(&buf, 64, 0x1000)) {
225 		return NULL;
226 	} else {
227 		if (mp) {
228 			mp->count--;
229 		}
230 		return buf;
231 	}
232 }
233 
234 int
235 spdk_mempool_get_bulk(struct spdk_mempool *mp, void **ele_arr, size_t count)
236 {
237 	for (size_t i = 0; i < count; i++) {
238 		ele_arr[i] = spdk_mempool_get(mp);
239 		if (ele_arr[i] == NULL) {
240 			return -1;
241 		}
242 	}
243 	return 0;
244 }
245 
246 void
247 spdk_mempool_put(struct spdk_mempool *_mp, void *ele)
248 {
249 	struct test_mempool *mp = (struct test_mempool *)_mp;
250 
251 	if (mp) {
252 		mp->count++;
253 	}
254 	free(ele);
255 }
256 
257 void
258 spdk_mempool_put_bulk(struct spdk_mempool *mp, void **ele_arr, size_t count)
259 {
260 	for (size_t i = 0; i < count; i++) {
261 		spdk_mempool_put(mp, ele_arr[i]);
262 	}
263 }
264 
265 DEFINE_RETURN_MOCK(spdk_mempool_count, size_t);
266 size_t
267 spdk_mempool_count(const struct spdk_mempool *_mp)
268 {
269 	struct test_mempool *mp = (struct test_mempool *)_mp;
270 
271 	HANDLE_RETURN_MOCK(spdk_mempool_count);
272 
273 	if (mp) {
274 		return mp->count;
275 	} else {
276 		return 1024;
277 	}
278 }
279 
280 struct spdk_ring_ele {
281 	void *ele;
282 	TAILQ_ENTRY(spdk_ring_ele) link;
283 };
284 
285 struct spdk_ring {
286 	TAILQ_HEAD(, spdk_ring_ele) elements;
287 };
288 
289 DEFINE_RETURN_MOCK(spdk_ring_create, struct spdk_ring *);
290 struct spdk_ring *
291 spdk_ring_create(enum spdk_ring_type type, size_t count, int socket_id)
292 {
293 	struct spdk_ring *ring;
294 
295 	HANDLE_RETURN_MOCK(spdk_ring_create);
296 
297 	ring = calloc(1, sizeof(*ring));
298 	if (ring) {
299 		TAILQ_INIT(&ring->elements);
300 	}
301 
302 	return ring;
303 }
304 
305 void
306 spdk_ring_free(struct spdk_ring *ring)
307 {
308 	free(ring);
309 }
310 
311 DEFINE_RETURN_MOCK(spdk_ring_enqueue, size_t);
312 size_t
313 spdk_ring_enqueue(struct spdk_ring *ring, void **objs, size_t count)
314 {
315 	struct spdk_ring_ele *ele;
316 	size_t i;
317 
318 	HANDLE_RETURN_MOCK(spdk_ring_enqueue);
319 
320 	for (i = 0; i < count; i++) {
321 		ele = calloc(1, sizeof(*ele));
322 		if (!ele) {
323 			break;
324 		}
325 
326 		ele->ele = objs[i];
327 		TAILQ_INSERT_TAIL(&ring->elements, ele, link);
328 	}
329 
330 	return i;
331 }
332 
333 DEFINE_RETURN_MOCK(spdk_ring_dequeue, size_t);
334 size_t
335 spdk_ring_dequeue(struct spdk_ring *ring, void **objs, size_t count)
336 {
337 	struct spdk_ring_ele *ele, *tmp;
338 	size_t i = 0;
339 
340 	HANDLE_RETURN_MOCK(spdk_ring_dequeue);
341 
342 	if (count == 0) {
343 		return 0;
344 	}
345 
346 	TAILQ_FOREACH_SAFE(ele, &ring->elements, link, tmp) {
347 		TAILQ_REMOVE(&ring->elements, ele, link);
348 		objs[i] = ele->ele;
349 		free(ele);
350 		i++;
351 		if (i >= count) {
352 			break;
353 		}
354 	}
355 
356 	return i;
357 
358 }
359 
360 DEFINE_RETURN_MOCK(spdk_get_ticks, uint64_t);
361 uint64_t
362 spdk_get_ticks(void)
363 {
364 	HANDLE_RETURN_MOCK(spdk_get_ticks);
365 
366 	return ut_spdk_get_ticks;
367 }
368 
369 DEFINE_RETURN_MOCK(spdk_get_ticks_hz, uint64_t);
370 uint64_t
371 spdk_get_ticks_hz(void)
372 {
373 	HANDLE_RETURN_MOCK(spdk_get_ticks_hz);
374 
375 	return 1000000;
376 }
377 
378 void
379 spdk_delay_us(unsigned int us)
380 {
381 	/* spdk_get_ticks_hz is 1000000, meaning 1 tick per us. */
382 	ut_spdk_get_ticks += us;
383 }
384 
385 DEFINE_RETURN_MOCK(spdk_pci_addr_parse, int);
386 int
387 spdk_pci_addr_parse(struct spdk_pci_addr *addr, const char *bdf)
388 {
389 	unsigned domain, bus, dev, func;
390 
391 	HANDLE_RETURN_MOCK(spdk_pci_addr_parse);
392 
393 	if (addr == NULL || bdf == NULL) {
394 		return -EINVAL;
395 	}
396 
397 	if ((sscanf(bdf, "%x:%x:%x.%x", &domain, &bus, &dev, &func) == 4) ||
398 	    (sscanf(bdf, "%x.%x.%x.%x", &domain, &bus, &dev, &func) == 4)) {
399 		/* Matched a full address - all variables are initialized */
400 	} else if (sscanf(bdf, "%x:%x:%x", &domain, &bus, &dev) == 3) {
401 		func = 0;
402 	} else if ((sscanf(bdf, "%x:%x.%x", &bus, &dev, &func) == 3) ||
403 		   (sscanf(bdf, "%x.%x.%x", &bus, &dev, &func) == 3)) {
404 		domain = 0;
405 	} else if ((sscanf(bdf, "%x:%x", &bus, &dev) == 2) ||
406 		   (sscanf(bdf, "%x.%x", &bus, &dev) == 2)) {
407 		domain = 0;
408 		func = 0;
409 	} else {
410 		return -EINVAL;
411 	}
412 
413 	if (bus > 0xFF || dev > 0x1F || func > 7) {
414 		return -EINVAL;
415 	}
416 
417 	addr->domain = domain;
418 	addr->bus = bus;
419 	addr->dev = dev;
420 	addr->func = func;
421 
422 	return 0;
423 }
424 
425 DEFINE_RETURN_MOCK(spdk_pci_addr_fmt, int);
426 int
427 spdk_pci_addr_fmt(char *bdf, size_t sz, const struct spdk_pci_addr *addr)
428 {
429 	int rc;
430 
431 	HANDLE_RETURN_MOCK(spdk_pci_addr_fmt);
432 
433 	rc = snprintf(bdf, sz, "%04x:%02x:%02x.%x",
434 		      addr->domain, addr->bus,
435 		      addr->dev, addr->func);
436 
437 	if (rc > 0 && (size_t)rc < sz) {
438 		return 0;
439 	}
440 
441 	return -1;
442 }
443 
444 DEFINE_RETURN_MOCK(spdk_pci_addr_compare, int);
445 int
446 spdk_pci_addr_compare(const struct spdk_pci_addr *a1, const struct spdk_pci_addr *a2)
447 {
448 	HANDLE_RETURN_MOCK(spdk_pci_addr_compare);
449 
450 	if (a1->domain > a2->domain) {
451 		return 1;
452 	} else if (a1->domain < a2->domain) {
453 		return -1;
454 	} else if (a1->bus > a2->bus) {
455 		return 1;
456 	} else if (a1->bus < a2->bus) {
457 		return -1;
458 	} else if (a1->dev > a2->dev) {
459 		return 1;
460 	} else if (a1->dev < a2->dev) {
461 		return -1;
462 	} else if (a1->func > a2->func) {
463 		return 1;
464 	} else if (a1->func < a2->func) {
465 		return -1;
466 	}
467 
468 	return 0;
469 }
470