Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2022 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include <sys/queue.h>
7 : :
8 : : #include "spdk/stdinc.h"
9 : :
10 : : #include "spdk_internal/cunit.h"
11 : : #include "common/lib/test_env.c"
12 : :
13 : : #include "ftl/mngt/ftl_mngt.c"
14 : :
15 : : #define CALLER_CB_RET_VALUE 999
16 : :
17 : : /* list for structure with results of tests from callbacks */
18 : : struct entry {
19 : : int data;
20 : : TAILQ_ENTRY(entry) entries;
21 : : };
22 : :
23 : : TAILQ_HEAD(listhead, entry) g_head;
24 : :
25 : : struct thread_send_msg_container {
26 : : spdk_msg_fn fn;
27 : : void *ctx;
28 : : } g_thread_send_msg_container;
29 : :
30 : : struct spdk_ftl_dev g_dev;
31 : :
32 : : int
33 : 516 : spdk_thread_send_msg(const struct spdk_thread *thread, spdk_msg_fn fn, void *ctx)
34 : : {
35 : 516 : g_thread_send_msg_container.fn = fn;
36 : 516 : g_thread_send_msg_container.ctx = ctx;
37 : 516 : return 0;
38 : : }
39 : :
40 : : struct spdk_thread *
41 : 114 : spdk_get_thread(void)
42 : : {
43 : 114 : struct spdk_thread *thd = (struct spdk_thread *)0x1;
44 : 114 : return thd;
45 : : }
46 : :
47 : : static int
48 : 6 : setup_test_list(void)
49 : : {
50 : 6 : TAILQ_INIT(&g_head);
51 : 6 : return 0;
52 : : }
53 : :
54 : : static void
55 : 48 : check_list_empty(void)
56 : : {
57 : 48 : CU_ASSERT_TRUE(TAILQ_EMPTY(&g_head));
58 : 48 : }
59 : :
60 : : static void
61 : 342 : add_elem_to_test_list(int data)
62 : : {
63 : 342 : struct entry *en = calloc(1, sizeof(*en));
64 [ - + ]: 342 : SPDK_CU_ASSERT_FATAL(en != NULL);
65 : 342 : en->data = data;
66 : 342 : TAILQ_INSERT_TAIL(&g_head, en, entries);
67 : 342 : }
68 : :
69 : : static void
70 : 342 : check_elem_on_list_and_remove(int compared_elem)
71 : : {
72 : 342 : struct entry *en = TAILQ_FIRST(&g_head);
73 [ + - ]: 342 : if (en != NULL) {
74 : 342 : CU_ASSERT_EQUAL(en->data, compared_elem);
75 [ + + ]: 342 : TAILQ_REMOVE(&g_head, en, entries);
76 : 342 : free(en);
77 : : } else {
78 : 0 : CU_FAIL("not null value was expected");
79 : : }
80 : 342 : }
81 : :
82 : : static void
83 : 72 : fn_finish(struct spdk_ftl_dev *dev, void *ctx, int status)
84 : : {
85 : 72 : add_elem_to_test_list(CALLER_CB_RET_VALUE);
86 : 72 : g_thread_send_msg_container.fn = NULL;
87 : 72 : g_thread_send_msg_container.ctx = NULL;
88 : 72 : }
89 : :
90 : : typedef int (*ftl_execute_fn)(struct spdk_ftl_dev *dev,
91 : : const struct ftl_mngt_process_desc *process,
92 : : ftl_mngt_completion cb, void *cb_cntx);
93 : :
94 : : static void
95 : 72 : run_ftl_mngt_with_cb_cntx(ftl_execute_fn exec_fn,
96 : : const struct ftl_mngt_process_desc *process, void *cb_cntx)
97 : : {
98 : 72 : int result = exec_fn(&g_dev, process, fn_finish, cb_cntx);
99 : 72 : CU_ASSERT_EQUAL(result, 0);
100 [ + + ]: 588 : while (g_thread_send_msg_container.fn != NULL) {
101 : 516 : g_thread_send_msg_container.fn(g_thread_send_msg_container.ctx);
102 : : }
103 : 72 : }
104 : :
105 : : static void
106 : 48 : run_ftl_mngt(ftl_execute_fn exec_fn,
107 : : const struct ftl_mngt_process_desc *process)
108 : : {
109 : 48 : run_ftl_mngt_with_cb_cntx(exec_fn, process, NULL);
110 : 48 : }
111 : :
112 : : /*-
113 : : * test 1
114 : : * tests simple invoking next steps
115 : : * it is shown if ftl_mngt_process_execute and ftl_mngt_process_rollback invoke functions in proper order
116 : : * (functions call only ftl_mngt_next_step)
117 : : */
118 : :
119 : : static void
120 : 6 : fn_1_1_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
121 : : {
122 : 6 : add_elem_to_test_list(1);
123 : 6 : ftl_mngt_next_step(mngt);
124 : 6 : }
125 : :
126 : : static void
127 : 6 : fn_1_1_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
128 : : {
129 : 6 : add_elem_to_test_list(-1);
130 : 6 : ftl_mngt_next_step(mngt);
131 : 6 : }
132 : :
133 : : static void
134 : 6 : fn_1_2_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
135 : : {
136 : 6 : add_elem_to_test_list(2);
137 : 6 : ftl_mngt_next_step(mngt);
138 : 6 : }
139 : :
140 : : static void
141 : 6 : fn_1_3_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
142 : : {
143 : 6 : add_elem_to_test_list(3);
144 : 6 : ftl_mngt_next_step(mngt);
145 : 6 : }
146 : :
147 : : static void
148 : 6 : fn_1_3_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
149 : : {
150 : 6 : add_elem_to_test_list(-3);
151 : 6 : ftl_mngt_next_step(mngt);
152 : 6 : }
153 : :
154 : : static struct ftl_mngt_process_desc pdesc_test_1 = {
155 : : .name = "process 1",
156 : : .steps = {
157 : : {
158 : : .name = "step 1",
159 : : .action = fn_1_1_action,
160 : : .cleanup = fn_1_1_cleanup
161 : : },
162 : : {
163 : : .name = "step 2",
164 : : .action = fn_1_2_action
165 : : },
166 : : {
167 : : .name = "step 3",
168 : : .action = fn_1_3_action,
169 : : .cleanup = fn_1_3_cleanup
170 : : },
171 : : {}
172 : : }
173 : : };
174 : :
175 : : static void
176 : 6 : test_next_step(void)
177 : : {
178 : 6 : run_ftl_mngt(ftl_mngt_process_execute, &pdesc_test_1);
179 : :
180 : : /* check proper order of action functions */
181 [ + + ]: 24 : for (int i = 1; i <= 3; i++) {
182 : 18 : check_elem_on_list_and_remove(i);
183 : : }
184 : :
185 : : /* check if caller callback was invoked */
186 : 6 : check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
187 : :
188 : 6 : run_ftl_mngt(ftl_mngt_process_rollback, &pdesc_test_1);
189 : :
190 : : /* Check proper order of cleanup functions.
191 : : * Cleanup functions add to list opposite values to action functions.
192 : : * Cleanup functions are invoked in reverse order,
193 : : * moreover action 2 does not have cleanup,
194 : : * so expected values are -3, then -1 */
195 : 6 : check_elem_on_list_and_remove(-3);
196 : 6 : check_elem_on_list_and_remove(-1);
197 : :
198 : : /* check if caller callback was invoked */
199 : 6 : check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
200 : :
201 : 6 : check_list_empty();
202 : 6 : }
203 : :
204 : : /*-
205 : : * test 2
206 : : * tests action and cleanup function which invoke
207 : : * ftl_mngt_continue_step function
208 : : */
209 : :
210 : : static void
211 : 48 : fn_2_common_part(struct ftl_mngt_process *mngt, int elem)
212 : : {
213 : 48 : struct entry *en = TAILQ_LAST(&g_head, listhead);
214 : :
215 [ + + + + ]: 48 : if (en == NULL || en->data != elem) {
216 : : /* if function was invoked 1st time, make it once again */
217 : 24 : add_elem_to_test_list(elem);
218 : 24 : ftl_mngt_continue_step(mngt);
219 : : } else {
220 : : /* otherwise go to the next function */
221 : 24 : add_elem_to_test_list(elem);
222 : 24 : ftl_mngt_next_step(mngt);
223 : : }
224 : 48 : }
225 : :
226 : : static void
227 : 12 : fn_2_1_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
228 : : {
229 : 12 : fn_2_common_part(mngt, 1);
230 : 12 : }
231 : :
232 : : static void
233 : 12 : fn_2_1_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
234 : : {
235 : 12 : fn_2_common_part(mngt, -1);
236 : 12 : }
237 : :
238 : : static void
239 : 12 : fn_2_2_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
240 : : {
241 : 12 : fn_2_common_part(mngt, 2);
242 : 12 : }
243 : :
244 : : static void
245 : 12 : fn_2_2_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
246 : : {
247 : 12 : fn_2_common_part(mngt, -2);
248 : 12 : }
249 : :
250 : : static struct ftl_mngt_process_desc pdesc_test_2 = {
251 : : .name = "process 2",
252 : : .steps = {
253 : : {
254 : : .name = "step 1",
255 : : .action = fn_2_1_action,
256 : : .cleanup = fn_2_1_cleanup
257 : : },
258 : : {
259 : : .name = "step 2",
260 : : .action = fn_2_2_action,
261 : : .cleanup = fn_2_2_cleanup
262 : : },
263 : : {}
264 : : }
265 : : };
266 : :
267 : : static void
268 : 6 : test_continue_step(void)
269 : : {
270 : 6 : run_ftl_mngt(ftl_mngt_process_execute, &pdesc_test_2);
271 : :
272 : : /* check proper order of action functions */
273 : 6 : check_elem_on_list_and_remove(1);
274 : 6 : check_elem_on_list_and_remove(1);
275 : 6 : check_elem_on_list_and_remove(2);
276 : 6 : check_elem_on_list_and_remove(2);
277 : :
278 : : /* check if caller callback was invoked */
279 : 6 : check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
280 : :
281 : 6 : run_ftl_mngt(ftl_mngt_process_rollback, &pdesc_test_2);
282 : :
283 : : /* check proper order of action functions */
284 : 6 : check_elem_on_list_and_remove(-2);
285 : 6 : check_elem_on_list_and_remove(-2);
286 : 6 : check_elem_on_list_and_remove(-1);
287 : 6 : check_elem_on_list_and_remove(-1);
288 : :
289 : : /* check if caller callback was invoked */
290 : 6 : check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
291 : :
292 : 6 : check_list_empty();
293 : 6 : }
294 : :
295 : : /*-
296 : : * test 3
297 : : * tests ftl_mngt_alloc_step_cntx and all ftl_mngt_get functions
298 : : */
299 : :
300 : : const int PROCESS_CNTX_TEST_VAL_0 = 21;
301 : : const int PROCESS_CNTX_TEST_VAL_1 = 37;
302 : : const int STEP_CNTX_TEST_VAL = 1;
303 : :
304 : : static void
305 : 24 : put_on_list(void)
306 : : {
307 : 24 : struct entry *en = calloc(1, sizeof(*en));
308 [ - + ]: 24 : SPDK_CU_ASSERT_FATAL(en != NULL);
309 : 24 : TAILQ_INSERT_TAIL(&g_head, en, entries);
310 : 24 : }
311 : :
312 : : static bool
313 : 48 : check_if_list_empty_and_clean(void)
314 : : {
315 : 48 : struct entry *en = TAILQ_FIRST(&g_head);
316 [ + + ]: 48 : if (en == NULL) {
317 : 24 : return true;
318 : : } else {
319 [ - + ]: 24 : TAILQ_REMOVE(&g_head, en, entries);
320 : 24 : free(en);
321 : 24 : return false;
322 : : }
323 : : }
324 : :
325 : : static void
326 : 12 : fn_3_1_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
327 : : {
328 : : int *step_cntx_ptr, *process_cntx_ptr;
329 : : char *caller_cntx_ptr;
330 : : int status;
331 : :
332 : 12 : step_cntx_ptr = ftl_mngt_get_step_ctx(mngt);
333 [ + + ]: 12 : if (check_if_list_empty_and_clean()) {
334 : : /* In 1st run of this function test list is empty
335 : : * and 'if' is true, this part of function is done.
336 : : * That 'if' part ends with ftl_mngt_continue_step,
337 : : * so function will be called once again.
338 : : * Element is added to the test list
339 : : * to invoke 'else' in second run */
340 : 6 : put_on_list();
341 : : /* this step descriptor does not locate any context
342 : : * at the beginning,
343 : : * so pointer should contain NULL */
344 : 6 : CU_ASSERT_PTR_NULL(step_cntx_ptr);
345 : :
346 : 6 : status = ftl_mngt_alloc_step_ctx(mngt, sizeof(*step_cntx_ptr));
347 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(status == 0);
348 : 6 : step_cntx_ptr = ftl_mngt_get_step_ctx(mngt);
349 : : /* now pointer should point to allocated context */
350 : 6 : CU_ASSERT_PTR_NOT_NULL(step_cntx_ptr);
351 : :
352 : : /* this value should be retrieved in second run of function
353 : : * (in 'else' part) */
354 : 6 : *step_cntx_ptr = STEP_CNTX_TEST_VAL;
355 : :
356 : 6 : ftl_mngt_continue_step(mngt);
357 : : } else {
358 : : /* In second run retrieved pointer is not empty.
359 : : * Moreover it should contain value allocated for this step
360 : : * in previous run of function */
361 : 6 : CU_ASSERT_PTR_NOT_NULL(step_cntx_ptr);
362 : 6 : CU_ASSERT_EQUAL(*step_cntx_ptr, STEP_CNTX_TEST_VAL);
363 : :
364 : : /* check getting device */
365 : 6 : CU_ASSERT_EQUAL(ftl_mngt_get_dev(mngt), dev);
366 : 6 : CU_ASSERT_EQUAL(ftl_mngt_get_dev(mngt), &g_dev);
367 : :
368 : : /* tests for process context */
369 : 6 : process_cntx_ptr = ftl_mngt_get_process_ctx(mngt);
370 : :
371 : : /* 1st get of process context, should be clear ('0' values) */
372 : 6 : CU_ASSERT_EQUAL(process_cntx_ptr[0], 0);
373 : 6 : CU_ASSERT_EQUAL(process_cntx_ptr[1], 0);
374 : :
375 : : /* Random values put in process context.
376 : : * Should be retrieved in the next function
377 : : * (it is common space for the entire process) */
378 : 6 : process_cntx_ptr[0] = PROCESS_CNTX_TEST_VAL_0;
379 : 6 : process_cntx_ptr[1] = PROCESS_CNTX_TEST_VAL_1;
380 : :
381 : : /* tests for caller context */
382 : 6 : caller_cntx_ptr = ftl_mngt_get_caller_ctx(mngt);
383 : :
384 : : /* check previously located values */
385 : 6 : CU_ASSERT_EQUAL(caller_cntx_ptr[0], 'd');
386 : 6 : CU_ASSERT_EQUAL(caller_cntx_ptr[1], 'a');
387 : 6 : CU_ASSERT_EQUAL(caller_cntx_ptr[2], 'j');
388 : :
389 : : /* insert new */
390 : 6 : caller_cntx_ptr[0] = ' ';
391 : 6 : caller_cntx_ptr[1] = 'k';
392 : 6 : caller_cntx_ptr[2] = 'a';
393 : :
394 : 6 : ftl_mngt_next_step(mngt);
395 : : }
396 : 12 : }
397 : :
398 : : static void
399 : 12 : fn_3_2_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
400 : : {
401 : : int *step_cntx_ptr, *process_cntx_ptr;
402 : : char *caller_cntx_ptr;
403 : : int status;
404 : :
405 : 12 : step_cntx_ptr = ftl_mngt_get_step_ctx(mngt);
406 : : /* context of this step descriptor is never empty
407 : : * so pointer cannot contain NULL */
408 : 12 : CU_ASSERT_PTR_NOT_NULL(step_cntx_ptr);
409 : :
410 [ + + ]: 12 : if (check_if_list_empty_and_clean()) {
411 : : /* In 1st run of this function test list is empty
412 : : * and 'if' is true, this part of function is done.
413 : : * That 'if' part ends with ftl_mngt_continue_step,
414 : : * so function will be called once again.
415 : : * Element is added to the test list
416 : : * to invoke 'else' in second run */
417 : 6 : put_on_list();
418 : :
419 : : /* check getting device */
420 : 6 : CU_ASSERT_EQUAL(ftl_mngt_get_dev(mngt), dev);
421 : 6 : CU_ASSERT_EQUAL(ftl_mngt_get_dev(mngt), &g_dev);
422 : :
423 : : /* tests for process context */
424 : 6 : process_cntx_ptr = ftl_mngt_get_process_ctx(mngt);
425 : :
426 : : /* check if it is possible to retrieve values located
427 : : * in process context by previous function */
428 : 6 : CU_ASSERT_EQUAL(process_cntx_ptr[0], PROCESS_CNTX_TEST_VAL_0);
429 : 6 : CU_ASSERT_EQUAL(process_cntx_ptr[1], PROCESS_CNTX_TEST_VAL_1);
430 : :
431 : : /* tests for caller context */
432 : 6 : caller_cntx_ptr = ftl_mngt_get_caller_ctx(mngt);
433 : :
434 : : /* check previously located values */
435 : 6 : CU_ASSERT_EQUAL(caller_cntx_ptr[0], ' ');
436 : 6 : CU_ASSERT_EQUAL(caller_cntx_ptr[1], 'k');
437 : 6 : CU_ASSERT_EQUAL(caller_cntx_ptr[2], 'a');
438 : :
439 : : /* insert new */
440 : 6 : caller_cntx_ptr[0] = 'm';
441 : 6 : caller_cntx_ptr[1] = 'i';
442 : 6 : caller_cntx_ptr[2] = 'e';
443 : :
444 : : /* first run of step so reserved step context
445 : : * was never used before and should contain 0 */
446 : 6 : CU_ASSERT_EQUAL(*step_cntx_ptr, 0);
447 : :
448 : : /* this value should be retrieved in second run of function
449 : : * (in 'else' part) */
450 : 6 : *step_cntx_ptr = STEP_CNTX_TEST_VAL;
451 : :
452 : 6 : ftl_mngt_continue_step(mngt);
453 : : } else {
454 : : /* In second run retrieved pointer should contain value
455 : : * allocated for this step in previous run of function */
456 : 6 : CU_ASSERT_EQUAL(*step_cntx_ptr, STEP_CNTX_TEST_VAL);
457 : :
458 : 6 : status = ftl_mngt_alloc_step_ctx(mngt, sizeof(*step_cntx_ptr));
459 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(status == 0);
460 : 6 : step_cntx_ptr = ftl_mngt_get_step_ctx(mngt);
461 : :
462 : : /* now pointer should point to newly allocated context
463 : : * and be cleaned up (should contain '0') */
464 : 6 : CU_ASSERT_PTR_NOT_NULL(step_cntx_ptr);
465 : 6 : CU_ASSERT_EQUAL(*step_cntx_ptr, 0);
466 : :
467 : 6 : ftl_mngt_next_step(mngt);
468 : : }
469 : 12 : }
470 : :
471 : : static void
472 : 12 : fn_3_2_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
473 : : {
474 : : int *step_cntx_ptr, *process_cntx_ptr;
475 : : char *caller_cntx_ptr;
476 : : int status;
477 : :
478 : 12 : step_cntx_ptr = ftl_mngt_get_step_ctx(mngt);
479 : : /* context of this step descriptor is never empty
480 : : * so pointer cannot contain NULL */
481 : 12 : CU_ASSERT_PTR_NOT_NULL(step_cntx_ptr);
482 : :
483 [ + + ]: 12 : if (check_if_list_empty_and_clean()) {
484 : : /* In 1st run of this function test list is empty
485 : : * and 'if' is true, this part of function is done.
486 : : * That 'if' part ends with ftl_mngt_continue_step,
487 : : * so function will be called once again.
488 : : * Element is added to the test list
489 : : * to invoke 'else' in second run */
490 : 6 : put_on_list();
491 : :
492 : : /* first run of step so reserved step context
493 : : * was never used before and should contain 0 */
494 : 6 : CU_ASSERT_EQUAL(*step_cntx_ptr, 0);
495 : :
496 : : /* this value should be retrieved in second run of function
497 : : * (in 'else' part) */
498 : 6 : *step_cntx_ptr = STEP_CNTX_TEST_VAL;
499 : :
500 : 6 : ftl_mngt_continue_step(mngt);
501 : : } else {
502 : : /* In second run retrieved pointer should contain value
503 : : * allocated for this step in previous run of function */
504 : 6 : CU_ASSERT_EQUAL(*step_cntx_ptr, STEP_CNTX_TEST_VAL);
505 : :
506 : 6 : status = ftl_mngt_alloc_step_ctx(mngt, sizeof(*step_cntx_ptr));
507 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(status == 0);
508 : 6 : step_cntx_ptr = ftl_mngt_get_step_ctx(mngt);
509 : :
510 : : /* now pointer should point to newly allocated context
511 : : * and be cleaned up (should contain '0') */
512 : 6 : CU_ASSERT_PTR_NOT_NULL(step_cntx_ptr);
513 : 6 : CU_ASSERT_EQUAL(*step_cntx_ptr, 0);
514 : :
515 : : /* check getting device */
516 : 6 : CU_ASSERT_EQUAL(ftl_mngt_get_dev(mngt), dev);
517 : 6 : CU_ASSERT_EQUAL(ftl_mngt_get_dev(mngt), &g_dev);
518 : :
519 : : /* tests for process context */
520 : 6 : process_cntx_ptr = ftl_mngt_get_process_ctx(mngt);
521 : :
522 : : /* 1st get of process context, should be clear ('0' values) */
523 : 6 : CU_ASSERT_EQUAL(process_cntx_ptr[0], 0);
524 : 6 : CU_ASSERT_EQUAL(process_cntx_ptr[1], 0);
525 : :
526 : : /* Random values put in process context.
527 : : * Should be retrieved in the next function
528 : : * (it is common space for the entire process) */
529 : 6 : process_cntx_ptr[0] = PROCESS_CNTX_TEST_VAL_0;
530 : 6 : process_cntx_ptr[1] = PROCESS_CNTX_TEST_VAL_1;
531 : :
532 : : /* tests for caller context */
533 : 6 : caller_cntx_ptr = ftl_mngt_get_caller_ctx(mngt);
534 : :
535 : : /* check previously located values */
536 : 6 : CU_ASSERT_EQUAL(caller_cntx_ptr[0], 'm');
537 : 6 : CU_ASSERT_EQUAL(caller_cntx_ptr[1], 'i');
538 : 6 : CU_ASSERT_EQUAL(caller_cntx_ptr[2], 'e');
539 : :
540 : : /* insert new */
541 : 6 : caller_cntx_ptr[0] = 'n';
542 : 6 : caller_cntx_ptr[1] = 'i';
543 : 6 : caller_cntx_ptr[2] = 'a';
544 : :
545 : 6 : ftl_mngt_next_step(mngt);
546 : : }
547 : 12 : }
548 : :
549 : : static void
550 : 12 : fn_3_1_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
551 : : {
552 : : int *step_cntx_ptr, *process_cntx_ptr;
553 : : char *caller_cntx_ptr;
554 : : int status;
555 : :
556 : 12 : step_cntx_ptr = ftl_mngt_get_step_ctx(mngt);
557 [ + + ]: 12 : if (check_if_list_empty_and_clean()) {
558 : : /* In 1st run of this function test list is empty
559 : : * and 'if' is true, this part of function is done.
560 : : * That 'if' part ends with ftl_mngt_continue_step,
561 : : * so function will be called once again.
562 : : * Element is added to the test list
563 : : * to invoke 'else' in second run */
564 : 6 : put_on_list();
565 : : /* this step descriptor does not locate any context
566 : : * at the beginning,
567 : : * so pointer should contain NULL */
568 : 6 : CU_ASSERT_PTR_NULL(step_cntx_ptr);
569 : :
570 : : /* check getting device */
571 : 6 : CU_ASSERT_EQUAL(ftl_mngt_get_dev(mngt), dev);
572 : 6 : CU_ASSERT_EQUAL(ftl_mngt_get_dev(mngt), &g_dev);
573 : :
574 : : /* tests for process context */
575 : 6 : process_cntx_ptr = ftl_mngt_get_process_ctx(mngt);
576 : :
577 : : /* check if it is possible to retrieve values located
578 : : * in process context by previous function */
579 : 6 : CU_ASSERT_EQUAL(process_cntx_ptr[0], PROCESS_CNTX_TEST_VAL_0);
580 : 6 : CU_ASSERT_EQUAL(process_cntx_ptr[1], PROCESS_CNTX_TEST_VAL_1);
581 : :
582 : : /* tests for caller context */
583 : 6 : caller_cntx_ptr = ftl_mngt_get_caller_ctx(mngt);
584 : :
585 : : /* check previously located values */
586 : 6 : CU_ASSERT_EQUAL(caller_cntx_ptr[0], 'n');
587 : 6 : CU_ASSERT_EQUAL(caller_cntx_ptr[1], 'i');
588 : 6 : CU_ASSERT_EQUAL(caller_cntx_ptr[2], 'a');
589 : :
590 : : /* insert new */
591 : 6 : caller_cntx_ptr[0] = '!';
592 : 6 : caller_cntx_ptr[1] = '!';
593 : 6 : caller_cntx_ptr[2] = '!';
594 : :
595 : 6 : status = ftl_mngt_alloc_step_ctx(mngt, sizeof(*step_cntx_ptr));
596 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(status == 0);
597 : 6 : step_cntx_ptr = ftl_mngt_get_step_ctx(mngt);
598 : : /* now pointer should point to allocated context */
599 : 6 : CU_ASSERT_PTR_NOT_NULL(step_cntx_ptr);
600 : :
601 : : /* this value should be retrieved in second run of function
602 : : * (in 'else' part) */
603 : 6 : *step_cntx_ptr = STEP_CNTX_TEST_VAL;
604 : :
605 : 6 : ftl_mngt_continue_step(mngt);
606 : : } else {
607 : : /* In second run retrieved pointer is not empty.
608 : : * Moreover it should contain value allocated for this step
609 : : * in previous run of function */
610 : 6 : CU_ASSERT_PTR_NOT_NULL(step_cntx_ptr);
611 : 6 : CU_ASSERT_EQUAL(*step_cntx_ptr, STEP_CNTX_TEST_VAL);
612 : :
613 : 6 : ftl_mngt_next_step(mngt);
614 : : }
615 : 12 : }
616 : :
617 : : static struct ftl_mngt_process_desc pdesc_test_3 = {
618 : : .name = "process 3",
619 : : .ctx_size = 2 * sizeof(int),
620 : : .steps = {
621 : : {
622 : : .name = "step 1",
623 : : .action = fn_3_1_action,
624 : : .cleanup = fn_3_1_cleanup
625 : : },
626 : : {
627 : : .name = "step 2",
628 : : .ctx_size = sizeof(int),
629 : : .action = fn_3_2_action,
630 : : .cleanup = fn_3_2_cleanup
631 : : },
632 : : {}
633 : : }
634 : : };
635 : :
636 : : static void
637 : 6 : test_get_func_and_step_cntx_alloc(void)
638 : : {
639 : 6 : char cb_cntx[4] = "daj";
640 : :
641 : 6 : run_ftl_mngt_with_cb_cntx(ftl_mngt_process_execute, &pdesc_test_3, cb_cntx);
642 : :
643 : : /* check if caller callback was invoked */
644 : 6 : check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
645 : :
646 : : /* check if steps changed cb_cntx correctly */
647 : 6 : CU_ASSERT_EQUAL(cb_cntx[0], 'm');
648 : 6 : CU_ASSERT_EQUAL(cb_cntx[1], 'i');
649 : 6 : CU_ASSERT_EQUAL(cb_cntx[2], 'e');
650 : :
651 : 6 : run_ftl_mngt_with_cb_cntx(ftl_mngt_process_rollback, &pdesc_test_3, cb_cntx);
652 : :
653 : : /* check if caller callback was invoked */
654 : 6 : check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
655 : :
656 : : /* check if steps changed cb_cntx correctly */
657 : 6 : CU_ASSERT_EQUAL(cb_cntx[0], '!');
658 : 6 : CU_ASSERT_EQUAL(cb_cntx[1], '!');
659 : 6 : CU_ASSERT_EQUAL(cb_cntx[2], '!');
660 : :
661 : 6 : check_list_empty();
662 : 6 : }
663 : :
664 : :
665 : :
666 : : /*-
667 : : * test 4
668 : : * tests ftl_mngt_fail_step function
669 : : *
670 : : * In that test one of the action functions fails (third one).
671 : : * Because of that expected result (saved on the test result list)
672 : : * are numbers of the next action function up to failing function.
673 : : * After that cleanup functions are invoked in reversed order.
674 : : */
675 : :
676 : : static void
677 : 6 : fn_4_1_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
678 : : {
679 : 6 : add_elem_to_test_list(1);
680 : 6 : ftl_mngt_next_step(mngt);
681 : 6 : }
682 : :
683 : : static void
684 : 6 : fn_4_1_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
685 : : {
686 : 6 : add_elem_to_test_list(-1);
687 : 6 : ftl_mngt_next_step(mngt);
688 : 6 : }
689 : :
690 : : static void
691 : 6 : fn_4_2_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
692 : : {
693 : 6 : add_elem_to_test_list(2);
694 : 6 : ftl_mngt_next_step(mngt);
695 : 6 : }
696 : :
697 : : static void
698 : 6 : fn_4_2_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
699 : : {
700 : 6 : add_elem_to_test_list(-2);
701 : 6 : ftl_mngt_next_step(mngt);
702 : 6 : }
703 : :
704 : : static void
705 : 6 : fn_4_3_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
706 : : {
707 : 6 : add_elem_to_test_list(3);
708 : : /* this action fails, so cleanup should begin now */
709 : 6 : ftl_mngt_fail_step(mngt);
710 : 6 : }
711 : :
712 : : static void
713 : 6 : fn_4_3_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
714 : : {
715 : 6 : add_elem_to_test_list(-3);
716 : 6 : ftl_mngt_next_step(mngt);
717 : 6 : }
718 : :
719 : : static void
720 : 0 : fn_4_4_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
721 : : {
722 : 0 : CU_FAIL("failure cannot start another action");
723 : 0 : ftl_mngt_next_step(mngt);
724 : 0 : }
725 : :
726 : : static struct ftl_mngt_process_desc pdesc_test_4 = {
727 : : .name = "process 4",
728 : : .steps = {
729 : : {
730 : : .name = "step 1",
731 : : .action = fn_4_1_action,
732 : : .cleanup = fn_4_1_cleanup
733 : : },
734 : : {
735 : : .name = "step 2",
736 : : .action = fn_4_2_action,
737 : : .cleanup = fn_4_2_cleanup
738 : : },
739 : : {
740 : : .name = "step 3",
741 : : .action = fn_4_3_action,
742 : : .cleanup = fn_4_3_cleanup
743 : : },
744 : : {
745 : : .name = "step 2",
746 : : .action = fn_4_4_action
747 : : },
748 : : {}
749 : : }
750 : : };
751 : :
752 : : static void
753 : 6 : test_fail_step(void)
754 : : {
755 : 6 : run_ftl_mngt(ftl_mngt_process_execute, &pdesc_test_4);
756 : :
757 : : /* check proper order of action functions */
758 [ + + ]: 24 : for (int i = 1; i <= 3; i++) {
759 : 18 : check_elem_on_list_and_remove(i);
760 : : }
761 : :
762 : : /* 3rd action function fails, so now should be
763 : : * cleanup functions in reverse order */
764 [ + + ]: 24 : for (int i = 3; i > 0; i--) {
765 : 18 : check_elem_on_list_and_remove(-i);
766 : : }
767 : :
768 : : /* check if caller callback was invoked */
769 : 6 : check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
770 : :
771 : 6 : check_list_empty();
772 : 6 : }
773 : :
774 : : /*-
775 : : * test 5
776 : : * tests ftl_mngt_call_process and ftl_mngt_call_process_rollback functions
777 : : * tests only proper flow without failures
778 : : */
779 : :
780 : : static void
781 : 6 : fn_5_2_1_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
782 : : {
783 : 6 : add_elem_to_test_list(21);
784 : 6 : ftl_mngt_next_step(mngt);
785 : 6 : }
786 : :
787 : : static void
788 : 6 : fn_5_2_1_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
789 : : {
790 : 6 : add_elem_to_test_list(-21);
791 : 6 : ftl_mngt_next_step(mngt);
792 : 6 : }
793 : :
794 : : static void
795 : 6 : fn_5_2_2_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
796 : : {
797 : 6 : add_elem_to_test_list(22);
798 : 6 : ftl_mngt_next_step(mngt);
799 : 6 : }
800 : :
801 : : static void
802 : 6 : fn_5_2_2_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
803 : : {
804 : 6 : add_elem_to_test_list(-22);
805 : 6 : ftl_mngt_next_step(mngt);
806 : 6 : }
807 : :
808 : : static struct ftl_mngt_process_desc pdesc_test_5_2 = {
809 : : .name = "process nested inside step 2 from process 5",
810 : : .steps = {
811 : : {
812 : : .name = "step 2_1",
813 : : .action = fn_5_2_1_action,
814 : : .cleanup = fn_5_2_1_cleanup
815 : : },
816 : : {
817 : : .name = "step 2_2",
818 : : .action = fn_5_2_2_action,
819 : : .cleanup = fn_5_2_2_cleanup
820 : : },
821 : : {}
822 : : }
823 : : };
824 : :
825 : : static void
826 : 6 : fn_5_3_1_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
827 : : {
828 : 6 : add_elem_to_test_list(31);
829 : 6 : ftl_mngt_next_step(mngt);
830 : 6 : }
831 : :
832 : : static void
833 : 6 : fn_5_3_1_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
834 : : {
835 : 6 : add_elem_to_test_list(-31);
836 : 6 : ftl_mngt_next_step(mngt);
837 : 6 : }
838 : :
839 : : static void
840 : 6 : fn_5_3_2_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
841 : : {
842 : 6 : add_elem_to_test_list(32);
843 : 6 : ftl_mngt_next_step(mngt);
844 : 6 : }
845 : :
846 : : static void
847 : 6 : fn_5_3_2_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
848 : : {
849 : 6 : add_elem_to_test_list(-32);
850 : 6 : ftl_mngt_next_step(mngt);
851 : 6 : }
852 : :
853 : : static struct ftl_mngt_process_desc pdesc_test_5_3 = {
854 : : .name = "process nested inside step 2 from process 5",
855 : : .steps = {
856 : : {
857 : : .name = "step 3_1",
858 : : .action = fn_5_3_1_action,
859 : : .cleanup = fn_5_3_1_cleanup
860 : : },
861 : : {
862 : : .name = "step 3_2",
863 : : .action = fn_5_3_2_action,
864 : : .cleanup = fn_5_3_2_cleanup
865 : : },
866 : : {}
867 : : }
868 : : };
869 : :
870 : : static void
871 : 6 : fn_5_1_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
872 : : {
873 : 6 : add_elem_to_test_list(1);
874 : 6 : ftl_mngt_next_step(mngt);
875 : 6 : }
876 : :
877 : : static void
878 : 6 : fn_5_1_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
879 : : {
880 : 6 : add_elem_to_test_list(-1);
881 : 6 : ftl_mngt_next_step(mngt);
882 : 6 : }
883 : :
884 : : static void
885 : 6 : fn_5_2_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
886 : : {
887 : 6 : add_elem_to_test_list(2);
888 : 6 : ftl_mngt_call_process(mngt, &pdesc_test_5_2, NULL);
889 : 6 : }
890 : :
891 : : static void
892 : 6 : fn_5_2_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
893 : : {
894 : 6 : add_elem_to_test_list(-2);
895 : 6 : ftl_mngt_call_process_rollback(mngt, &pdesc_test_5_2);
896 : 6 : }
897 : :
898 : : static void
899 : 6 : fn_5_3_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
900 : : {
901 : 6 : add_elem_to_test_list(3);
902 : 6 : ftl_mngt_call_process_rollback(mngt, &pdesc_test_5_3);
903 : 6 : }
904 : :
905 : : static void
906 : 6 : fn_5_3_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
907 : : {
908 : 6 : add_elem_to_test_list(-3);
909 : 6 : ftl_mngt_call_process(mngt, &pdesc_test_5_3, NULL);
910 : 6 : }
911 : :
912 : : static struct ftl_mngt_process_desc pdesc_test_5 = {
913 : : .name = "process 5 main",
914 : : .steps = {
915 : : {
916 : : .name = "step 1",
917 : : .action = fn_5_1_action,
918 : : .cleanup = fn_5_1_cleanup
919 : : },
920 : : {
921 : : .name = "step 2",
922 : : .action = fn_5_2_action,
923 : : .cleanup = fn_5_2_cleanup
924 : : },
925 : : {
926 : : .name = "step 3",
927 : : .action = fn_5_3_action,
928 : : .cleanup = fn_5_3_cleanup
929 : : },
930 : : {}
931 : : }
932 : : };
933 : :
934 : : static void
935 : 6 : test_mngt_call_and_call_rollback(void)
936 : : {
937 : 6 : run_ftl_mngt(ftl_mngt_process_execute, &pdesc_test_5);
938 : :
939 : 6 : check_elem_on_list_and_remove(1);
940 : 6 : check_elem_on_list_and_remove(2);
941 : 6 : check_elem_on_list_and_remove(21);
942 : 6 : check_elem_on_list_and_remove(22);
943 : 6 : check_elem_on_list_and_remove(3);
944 : 6 : check_elem_on_list_and_remove(-32);
945 : 6 : check_elem_on_list_and_remove(-31);
946 : :
947 : : /* check if caller callback was invoked */
948 : 6 : check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
949 : :
950 : 6 : run_ftl_mngt(ftl_mngt_process_rollback, &pdesc_test_5);
951 : :
952 : 6 : check_elem_on_list_and_remove(-3);
953 : 6 : check_elem_on_list_and_remove(31);
954 : 6 : check_elem_on_list_and_remove(32);
955 : 6 : check_elem_on_list_and_remove(-2);
956 : 6 : check_elem_on_list_and_remove(-22);
957 : 6 : check_elem_on_list_and_remove(-21);
958 : 6 : check_elem_on_list_and_remove(-1);
959 : :
960 : : /* check if caller callback was invoked */
961 : 6 : check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
962 : :
963 : 6 : check_list_empty();
964 : 6 : }
965 : :
966 : : /*
967 : : * test 6
968 : : * tests failure inside nested process
969 : : */
970 : :
971 : : static void
972 : 6 : fn_6_2_1_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
973 : : {
974 : 6 : add_elem_to_test_list(21);
975 : 6 : ftl_mngt_next_step(mngt);
976 : 6 : }
977 : :
978 : : static void
979 : 6 : fn_6_2_1_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
980 : : {
981 : 6 : add_elem_to_test_list(-21);
982 : 6 : ftl_mngt_next_step(mngt);
983 : 6 : }
984 : :
985 : : static void
986 : 6 : fn_6_2_2_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
987 : : {
988 : 6 : add_elem_to_test_list(22);
989 : : /* this action fails, so cleanup should begin now */
990 : 6 : ftl_mngt_fail_step(mngt);
991 : 6 : }
992 : :
993 : : static void
994 : 0 : fn_6_2_3_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
995 : : {
996 : 0 : CU_FAIL("failure cannot start another action");
997 : 0 : ftl_mngt_next_step(mngt);
998 : 0 : }
999 : :
1000 : : static struct ftl_mngt_process_desc pdesc_test_6_2 = {
1001 : : .name = "process nested inside step 2 from process 6",
1002 : : .steps = {
1003 : : {
1004 : : .name = "step 6_1",
1005 : : .action = fn_6_2_1_action,
1006 : : .cleanup = fn_6_2_1_cleanup
1007 : : },
1008 : : {
1009 : : .name = "step 6_2",
1010 : : .action = fn_6_2_2_action
1011 : : },
1012 : : {
1013 : : .name = "step 6_3",
1014 : : .action = fn_6_2_3_action
1015 : : },
1016 : : {}
1017 : : }
1018 : : };
1019 : :
1020 : : static void
1021 : 6 : fn_6_1_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
1022 : : {
1023 : 6 : add_elem_to_test_list(1);
1024 : 6 : ftl_mngt_next_step(mngt);
1025 : 6 : }
1026 : :
1027 : : static void
1028 : 6 : fn_6_2_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
1029 : : {
1030 : 6 : add_elem_to_test_list(2);
1031 : 6 : ftl_mngt_call_process(mngt, &pdesc_test_6_2, NULL);
1032 : 6 : }
1033 : :
1034 : : static void
1035 : 6 : fn_6_2_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
1036 : : {
1037 : 6 : add_elem_to_test_list(-2);
1038 : 6 : ftl_mngt_next_step(mngt);
1039 : 6 : }
1040 : :
1041 : : static void
1042 : 0 : fn_6_3_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
1043 : : {
1044 : 0 : CU_FAIL("failure cannot start another action");
1045 : 0 : ftl_mngt_next_step(mngt);
1046 : 0 : }
1047 : :
1048 : : static struct ftl_mngt_process_desc pdesc_test_6 = {
1049 : : .name = "process 6 main",
1050 : : .steps = {
1051 : : {
1052 : : .name = "step 1",
1053 : : .action = fn_6_1_action
1054 : : },
1055 : : {
1056 : : .name = "step 2",
1057 : : .action = fn_6_2_action,
1058 : : .cleanup = fn_6_2_cleanup
1059 : : },
1060 : : {
1061 : : .name = "step 3",
1062 : : .action = fn_6_3_action
1063 : : },
1064 : : {}
1065 : : }
1066 : : };
1067 : :
1068 : : static void
1069 : 6 : test_nested_process_failure(void)
1070 : : {
1071 : 6 : run_ftl_mngt(ftl_mngt_process_execute, &pdesc_test_6);
1072 : :
1073 : 6 : check_elem_on_list_and_remove(1);
1074 : 6 : check_elem_on_list_and_remove(2);
1075 : 6 : check_elem_on_list_and_remove(21);
1076 : 6 : check_elem_on_list_and_remove(22);
1077 : 6 : check_elem_on_list_and_remove(-21);
1078 : 6 : check_elem_on_list_and_remove(-2);
1079 : :
1080 : : /* check if caller callback was invoked */
1081 : 6 : check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
1082 : :
1083 : 6 : check_list_empty();
1084 : 6 : }
1085 : :
1086 : : struct test_call_init_ctx {
1087 : : int init_handler_result;
1088 : : };
1089 : :
1090 : : static int
1091 : 12 : test_call_init_child_init_hndlr(struct spdk_ftl_dev *dev,
1092 : : struct ftl_mngt_process *mngt, void *_init_ctx)
1093 : : {
1094 : 12 : struct test_call_init_ctx *init_ctx = _init_ctx;
1095 : :
1096 : 12 : add_elem_to_test_list(10);
1097 : 12 : return init_ctx->init_handler_result;
1098 : : }
1099 : :
1100 : : static void
1101 : 6 : test_call_init_child_deinit_hndlr(struct spdk_ftl_dev *dev,
1102 : : struct ftl_mngt_process *mngt)
1103 : : {
1104 : 6 : add_elem_to_test_list(1000);
1105 : 6 : }
1106 : :
1107 : : static void
1108 : 6 : test_call_init_child_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
1109 : : {
1110 : 6 : add_elem_to_test_list(100);
1111 : 6 : ftl_mngt_next_step(mngt);
1112 : 6 : }
1113 : :
1114 : : static struct ftl_mngt_process_desc pdesc_test_call_init_child = {
1115 : : .name = "Test call init, child",
1116 : : .init_handler = test_call_init_child_init_hndlr,
1117 : : .deinit_handler = test_call_init_child_deinit_hndlr,
1118 : : .steps = {
1119 : : {
1120 : : .name = "Test call init, child step",
1121 : : .action = test_call_init_child_action
1122 : : },
1123 : : {}
1124 : : }
1125 : : };
1126 : :
1127 : : static void
1128 : 12 : test_call_init_parent_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
1129 : : {
1130 : 12 : struct test_call_init_ctx *init_ctx = ftl_mngt_get_caller_ctx(mngt);
1131 : :
1132 : 12 : add_elem_to_test_list(1);
1133 : 12 : ftl_mngt_call_process(mngt, &pdesc_test_call_init_child, init_ctx);
1134 : 12 : }
1135 : :
1136 : : static struct ftl_mngt_process_desc pdesc_test_call_init_parent = {
1137 : : .name = "Test call init, parent",
1138 : : .steps = {
1139 : : {
1140 : : .name = "Test call init, parent step",
1141 : : .action = test_call_init_parent_action
1142 : : },
1143 : : {}
1144 : : }
1145 : : };
1146 : :
1147 : : static void
1148 : 6 : test_call_init_success(void)
1149 : : {
1150 : 6 : struct test_call_init_ctx init_ctx = {
1151 : : .init_handler_result = 0
1152 : : };
1153 : :
1154 : 6 : run_ftl_mngt_with_cb_cntx(ftl_mngt_process_execute, &pdesc_test_call_init_parent, &init_ctx);
1155 : :
1156 : 6 : check_elem_on_list_and_remove(1);
1157 : 6 : check_elem_on_list_and_remove(10);
1158 : 6 : check_elem_on_list_and_remove(100);
1159 : :
1160 : : /* check if caller deinit handler ws invoked */
1161 : 6 : check_elem_on_list_and_remove(1000);
1162 : :
1163 : : /* check if caller callback was invoked */
1164 : 6 : check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
1165 : :
1166 : 6 : check_list_empty();
1167 : 6 : }
1168 : :
1169 : : static void
1170 : 6 : test_call_init_failure(void)
1171 : : {
1172 : 6 : struct test_call_init_ctx init_ctx = {
1173 : : .init_handler_result = -1
1174 : : };
1175 : :
1176 : 6 : run_ftl_mngt_with_cb_cntx(ftl_mngt_process_execute, &pdesc_test_call_init_parent, &init_ctx);
1177 : :
1178 : 6 : check_elem_on_list_and_remove(1);
1179 : 6 : check_elem_on_list_and_remove(10);
1180 : :
1181 : : /* check if caller callback was invoked */
1182 : 6 : check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
1183 : :
1184 : 6 : check_list_empty();
1185 : 6 : }
1186 : :
1187 : : int
1188 : 6 : main(int argc, char **argv)
1189 : : {
1190 : 6 : CU_pSuite suite = NULL;
1191 : : unsigned int num_failures;
1192 : :
1193 : 6 : CU_initialize_registry();
1194 : :
1195 : 6 : suite = CU_add_suite("ftl_mngt", setup_test_list, NULL);
1196 : :
1197 : 6 : CU_ADD_TEST(suite, test_next_step);
1198 : 6 : CU_ADD_TEST(suite, test_continue_step);
1199 : 6 : CU_ADD_TEST(suite, test_get_func_and_step_cntx_alloc);
1200 : 6 : CU_ADD_TEST(suite, test_fail_step);
1201 : 6 : CU_ADD_TEST(suite, test_mngt_call_and_call_rollback);
1202 : 6 : CU_ADD_TEST(suite, test_nested_process_failure);
1203 : 6 : CU_ADD_TEST(suite, test_call_init_success);
1204 : 6 : CU_ADD_TEST(suite, test_call_init_failure);
1205 : :
1206 : 6 : num_failures = spdk_ut_run_tests(argc, argv, NULL);
1207 : 6 : CU_cleanup_registry();
1208 : :
1209 : 6 : return num_failures;
1210 : : }
|