LCOV - code coverage report
Current view: top level - spdk/test/unit/lib/ftl/ftl_mngt - ftl_mngt_ut.c (source / functions) Hit Total Coverage
Test: Combined Lines: 440 453 97.1 %
Date: 2024-07-15 14:51:33 Functions: 64 67 95.5 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 32 40 80.0 %

           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                 :        258 : spdk_thread_send_msg(const struct spdk_thread *thread, spdk_msg_fn fn, void *ctx)
      34                 :            : {
      35                 :        258 :         g_thread_send_msg_container.fn = fn;
      36                 :        258 :         g_thread_send_msg_container.ctx = ctx;
      37                 :        258 :         return 0;
      38                 :            : }
      39                 :            : 
      40                 :            : struct spdk_thread *
      41                 :         57 : spdk_get_thread(void)
      42                 :            : {
      43                 :         57 :         struct spdk_thread *thd = (struct spdk_thread *)0x1;
      44                 :         57 :         return thd;
      45                 :            : }
      46                 :            : 
      47                 :            : static int
      48                 :          3 : setup_test_list(void)
      49                 :            : {
      50                 :          3 :         TAILQ_INIT(&g_head);
      51                 :          3 :         return 0;
      52                 :            : }
      53                 :            : 
      54                 :            : static void
      55                 :         24 : check_list_empty(void)
      56                 :            : {
      57                 :         24 :         CU_ASSERT_TRUE(TAILQ_EMPTY(&g_head));
      58                 :         24 : }
      59                 :            : 
      60                 :            : static void
      61                 :        171 : add_elem_to_test_list(int data)
      62                 :            : {
      63                 :        171 :         struct entry *en = calloc(1, sizeof(*en));
      64         [ -  + ]:        171 :         SPDK_CU_ASSERT_FATAL(en != NULL);
      65                 :        171 :         en->data = data;
      66                 :        171 :         TAILQ_INSERT_TAIL(&g_head, en, entries);
      67                 :        171 : }
      68                 :            : 
      69                 :            : static void
      70                 :        171 : check_elem_on_list_and_remove(int compared_elem)
      71                 :            : {
      72                 :        171 :         struct entry *en = TAILQ_FIRST(&g_head);
      73         [ +  - ]:        171 :         if (en != NULL) {
      74                 :        171 :                 CU_ASSERT_EQUAL(en->data, compared_elem);
      75         [ +  + ]:        171 :                 TAILQ_REMOVE(&g_head, en, entries);
      76                 :        171 :                 free(en);
      77                 :            :         } else {
      78                 :          0 :                 CU_FAIL("not null value was expected");
      79                 :            :         }
      80                 :        171 : }
      81                 :            : 
      82                 :            : static void
      83                 :         36 : fn_finish(struct spdk_ftl_dev *dev, void *ctx, int status)
      84                 :            : {
      85                 :         36 :         add_elem_to_test_list(CALLER_CB_RET_VALUE);
      86                 :         36 :         g_thread_send_msg_container.fn = NULL;
      87                 :         36 :         g_thread_send_msg_container.ctx = NULL;
      88                 :         36 : }
      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                 :         36 : run_ftl_mngt_with_cb_cntx(ftl_execute_fn exec_fn,
      96                 :            :                           const struct ftl_mngt_process_desc *process, void *cb_cntx)
      97                 :            : {
      98                 :         36 :         int result = exec_fn(&g_dev, process, fn_finish, cb_cntx);
      99                 :         36 :         CU_ASSERT_EQUAL(result, 0);
     100         [ +  + ]:        294 :         while (g_thread_send_msg_container.fn != NULL) {
     101                 :        258 :                 g_thread_send_msg_container.fn(g_thread_send_msg_container.ctx);
     102                 :            :         }
     103                 :         36 : }
     104                 :            : 
     105                 :            : static void
     106                 :         24 : run_ftl_mngt(ftl_execute_fn exec_fn,
     107                 :            :              const struct ftl_mngt_process_desc *process)
     108                 :            : {
     109                 :         24 :         run_ftl_mngt_with_cb_cntx(exec_fn, process, NULL);
     110                 :         24 : }
     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                 :          3 : fn_1_1_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     121                 :            : {
     122                 :          3 :         add_elem_to_test_list(1);
     123                 :          3 :         ftl_mngt_next_step(mngt);
     124                 :          3 : }
     125                 :            : 
     126                 :            : static void
     127                 :          3 : fn_1_1_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     128                 :            : {
     129                 :          3 :         add_elem_to_test_list(-1);
     130                 :          3 :         ftl_mngt_next_step(mngt);
     131                 :          3 : }
     132                 :            : 
     133                 :            : static void
     134                 :          3 : fn_1_2_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     135                 :            : {
     136                 :          3 :         add_elem_to_test_list(2);
     137                 :          3 :         ftl_mngt_next_step(mngt);
     138                 :          3 : }
     139                 :            : 
     140                 :            : static void
     141                 :          3 : fn_1_3_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     142                 :            : {
     143                 :          3 :         add_elem_to_test_list(3);
     144                 :          3 :         ftl_mngt_next_step(mngt);
     145                 :          3 : }
     146                 :            : 
     147                 :            : static void
     148                 :          3 : fn_1_3_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     149                 :            : {
     150                 :          3 :         add_elem_to_test_list(-3);
     151                 :          3 :         ftl_mngt_next_step(mngt);
     152                 :          3 : }
     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                 :          3 : test_next_step(void)
     177                 :            : {
     178                 :          3 :         run_ftl_mngt(ftl_mngt_process_execute, &pdesc_test_1);
     179                 :            : 
     180                 :            :         /* check proper order of action functions */
     181         [ +  + ]:         12 :         for (int i = 1; i <= 3; i++) {
     182                 :          9 :                 check_elem_on_list_and_remove(i);
     183                 :            :         }
     184                 :            : 
     185                 :            :         /* check if caller callback was invoked */
     186                 :          3 :         check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
     187                 :            : 
     188                 :          3 :         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                 :          3 :         check_elem_on_list_and_remove(-3);
     196                 :          3 :         check_elem_on_list_and_remove(-1);
     197                 :            : 
     198                 :            :         /* check if caller callback was invoked */
     199                 :          3 :         check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
     200                 :            : 
     201                 :          3 :         check_list_empty();
     202                 :          3 : }
     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                 :         24 : fn_2_common_part(struct ftl_mngt_process *mngt, int elem)
     212                 :            : {
     213                 :         24 :         struct entry *en = TAILQ_LAST(&g_head, listhead);
     214                 :            : 
     215   [ +  +  +  + ]:         24 :         if (en == NULL || en->data != elem) {
     216                 :            :                 /* if function was invoked 1st time, make it once again */
     217                 :         12 :                 add_elem_to_test_list(elem);
     218                 :         12 :                 ftl_mngt_continue_step(mngt);
     219                 :            :         } else {
     220                 :            :                 /* otherwise go to the next function */
     221                 :         12 :                 add_elem_to_test_list(elem);
     222                 :         12 :                 ftl_mngt_next_step(mngt);
     223                 :            :         }
     224                 :         24 : }
     225                 :            : 
     226                 :            : static void
     227                 :          6 : fn_2_1_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     228                 :            : {
     229                 :          6 :         fn_2_common_part(mngt, 1);
     230                 :          6 : }
     231                 :            : 
     232                 :            : static void
     233                 :          6 : fn_2_1_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     234                 :            : {
     235                 :          6 :         fn_2_common_part(mngt, -1);
     236                 :          6 : }
     237                 :            : 
     238                 :            : static void
     239                 :          6 : fn_2_2_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     240                 :            : {
     241                 :          6 :         fn_2_common_part(mngt, 2);
     242                 :          6 : }
     243                 :            : 
     244                 :            : static void
     245                 :          6 : fn_2_2_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     246                 :            : {
     247                 :          6 :         fn_2_common_part(mngt, -2);
     248                 :          6 : }
     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                 :          3 : test_continue_step(void)
     269                 :            : {
     270                 :          3 :         run_ftl_mngt(ftl_mngt_process_execute, &pdesc_test_2);
     271                 :            : 
     272                 :            :         /* check proper order of action functions */
     273                 :          3 :         check_elem_on_list_and_remove(1);
     274                 :          3 :         check_elem_on_list_and_remove(1);
     275                 :          3 :         check_elem_on_list_and_remove(2);
     276                 :          3 :         check_elem_on_list_and_remove(2);
     277                 :            : 
     278                 :            :         /* check if caller callback was invoked */
     279                 :          3 :         check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
     280                 :            : 
     281                 :          3 :         run_ftl_mngt(ftl_mngt_process_rollback, &pdesc_test_2);
     282                 :            : 
     283                 :            :         /* check proper order of action functions */
     284                 :          3 :         check_elem_on_list_and_remove(-2);
     285                 :          3 :         check_elem_on_list_and_remove(-2);
     286                 :          3 :         check_elem_on_list_and_remove(-1);
     287                 :          3 :         check_elem_on_list_and_remove(-1);
     288                 :            : 
     289                 :            :         /* check if caller callback was invoked */
     290                 :          3 :         check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
     291                 :            : 
     292                 :          3 :         check_list_empty();
     293                 :          3 : }
     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                 :         12 : put_on_list(void)
     306                 :            : {
     307                 :         12 :         struct entry *en = calloc(1, sizeof(*en));
     308         [ -  + ]:         12 :         SPDK_CU_ASSERT_FATAL(en != NULL);
     309                 :         12 :         TAILQ_INSERT_TAIL(&g_head, en, entries);
     310                 :         12 : }
     311                 :            : 
     312                 :            : static bool
     313                 :         24 : check_if_list_empty_and_clean(void)
     314                 :            : {
     315                 :         24 :         struct entry *en = TAILQ_FIRST(&g_head);
     316         [ +  + ]:         24 :         if (en == NULL) {
     317                 :         12 :                 return true;
     318                 :            :         } else {
     319         [ -  + ]:         12 :                 TAILQ_REMOVE(&g_head, en, entries);
     320                 :         12 :                 free(en);
     321                 :         12 :                 return false;
     322                 :            :         }
     323                 :            : }
     324                 :            : 
     325                 :            : static void
     326                 :          6 : 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                 :          6 :         step_cntx_ptr = ftl_mngt_get_step_ctx(mngt);
     333         [ +  + ]:          6 :         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                 :          3 :                 put_on_list();
     341                 :            :                 /* this step descriptor does not locate any context
     342                 :            :                  * at the beginning,
     343                 :            :                  * so pointer should contain NULL */
     344                 :          3 :                 CU_ASSERT_PTR_NULL(step_cntx_ptr);
     345                 :            : 
     346                 :          3 :                 status = ftl_mngt_alloc_step_ctx(mngt, sizeof(*step_cntx_ptr));
     347         [ -  + ]:          3 :                 SPDK_CU_ASSERT_FATAL(status == 0);
     348                 :          3 :                 step_cntx_ptr = ftl_mngt_get_step_ctx(mngt);
     349                 :            :                 /* now pointer should point to allocated context */
     350                 :          3 :                 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                 :          3 :                 *step_cntx_ptr = STEP_CNTX_TEST_VAL;
     355                 :            : 
     356                 :          3 :                 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                 :          3 :                 CU_ASSERT_PTR_NOT_NULL(step_cntx_ptr);
     362                 :          3 :                 CU_ASSERT_EQUAL(*step_cntx_ptr, STEP_CNTX_TEST_VAL);
     363                 :            : 
     364                 :            :                 /* check getting device */
     365                 :          3 :                 CU_ASSERT_EQUAL(ftl_mngt_get_dev(mngt), dev);
     366                 :          3 :                 CU_ASSERT_EQUAL(ftl_mngt_get_dev(mngt), &g_dev);
     367                 :            : 
     368                 :            :                 /* tests for process context */
     369                 :          3 :                 process_cntx_ptr = ftl_mngt_get_process_ctx(mngt);
     370                 :            : 
     371                 :            :                 /* 1st get of process context, should be clear ('0' values) */
     372                 :          3 :                 CU_ASSERT_EQUAL(process_cntx_ptr[0], 0);
     373                 :          3 :                 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                 :          3 :                 process_cntx_ptr[0] = PROCESS_CNTX_TEST_VAL_0;
     379                 :          3 :                 process_cntx_ptr[1] = PROCESS_CNTX_TEST_VAL_1;
     380                 :            : 
     381                 :            :                 /* tests for caller context */
     382                 :          3 :                 caller_cntx_ptr = ftl_mngt_get_caller_ctx(mngt);
     383                 :            : 
     384                 :            :                 /* check previously located values */
     385                 :          3 :                 CU_ASSERT_EQUAL(caller_cntx_ptr[0], 'd');
     386                 :          3 :                 CU_ASSERT_EQUAL(caller_cntx_ptr[1], 'a');
     387                 :          3 :                 CU_ASSERT_EQUAL(caller_cntx_ptr[2], 'j');
     388                 :            : 
     389                 :            :                 /* insert new */
     390                 :          3 :                 caller_cntx_ptr[0] = ' ';
     391                 :          3 :                 caller_cntx_ptr[1] = 'k';
     392                 :          3 :                 caller_cntx_ptr[2] = 'a';
     393                 :            : 
     394                 :          3 :                 ftl_mngt_next_step(mngt);
     395                 :            :         }
     396                 :          6 : }
     397                 :            : 
     398                 :            : static void
     399                 :          6 : 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                 :          6 :         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                 :          6 :         CU_ASSERT_PTR_NOT_NULL(step_cntx_ptr);
     409                 :            : 
     410         [ +  + ]:          6 :         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                 :          3 :                 put_on_list();
     418                 :            : 
     419                 :            :                 /* check getting device */
     420                 :          3 :                 CU_ASSERT_EQUAL(ftl_mngt_get_dev(mngt), dev);
     421                 :          3 :                 CU_ASSERT_EQUAL(ftl_mngt_get_dev(mngt), &g_dev);
     422                 :            : 
     423                 :            :                 /* tests for process context */
     424                 :          3 :                 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                 :          3 :                 CU_ASSERT_EQUAL(process_cntx_ptr[0], PROCESS_CNTX_TEST_VAL_0);
     429                 :          3 :                 CU_ASSERT_EQUAL(process_cntx_ptr[1], PROCESS_CNTX_TEST_VAL_1);
     430                 :            : 
     431                 :            :                 /* tests for caller context */
     432                 :          3 :                 caller_cntx_ptr = ftl_mngt_get_caller_ctx(mngt);
     433                 :            : 
     434                 :            :                 /* check previously located values */
     435                 :          3 :                 CU_ASSERT_EQUAL(caller_cntx_ptr[0], ' ');
     436                 :          3 :                 CU_ASSERT_EQUAL(caller_cntx_ptr[1], 'k');
     437                 :          3 :                 CU_ASSERT_EQUAL(caller_cntx_ptr[2], 'a');
     438                 :            : 
     439                 :            :                 /* insert new */
     440                 :          3 :                 caller_cntx_ptr[0] = 'm';
     441                 :          3 :                 caller_cntx_ptr[1] = 'i';
     442                 :          3 :                 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                 :          3 :                 CU_ASSERT_EQUAL(*step_cntx_ptr, 0);
     447                 :            : 
     448                 :            :                 /* this value should be retrieved in second run of function
     449                 :            :                  * (in 'else' part) */
     450                 :          3 :                 *step_cntx_ptr = STEP_CNTX_TEST_VAL;
     451                 :            : 
     452                 :          3 :                 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                 :          3 :                 CU_ASSERT_EQUAL(*step_cntx_ptr, STEP_CNTX_TEST_VAL);
     457                 :            : 
     458                 :          3 :                 status = ftl_mngt_alloc_step_ctx(mngt, sizeof(*step_cntx_ptr));
     459         [ -  + ]:          3 :                 SPDK_CU_ASSERT_FATAL(status == 0);
     460                 :          3 :                 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                 :          3 :                 CU_ASSERT_PTR_NOT_NULL(step_cntx_ptr);
     465                 :          3 :                 CU_ASSERT_EQUAL(*step_cntx_ptr, 0);
     466                 :            : 
     467                 :          3 :                 ftl_mngt_next_step(mngt);
     468                 :            :         }
     469                 :          6 : }
     470                 :            : 
     471                 :            : static void
     472                 :          6 : 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                 :          6 :         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                 :          6 :         CU_ASSERT_PTR_NOT_NULL(step_cntx_ptr);
     482                 :            : 
     483         [ +  + ]:          6 :         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                 :          3 :                 put_on_list();
     491                 :            : 
     492                 :            :                 /* first run of step so reserved step context
     493                 :            :                  * was never used before and should contain 0 */
     494                 :          3 :                 CU_ASSERT_EQUAL(*step_cntx_ptr, 0);
     495                 :            : 
     496                 :            :                 /* this value should be retrieved in second run of function
     497                 :            :                  * (in 'else' part) */
     498                 :          3 :                 *step_cntx_ptr = STEP_CNTX_TEST_VAL;
     499                 :            : 
     500                 :          3 :                 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                 :          3 :                 CU_ASSERT_EQUAL(*step_cntx_ptr, STEP_CNTX_TEST_VAL);
     505                 :            : 
     506                 :          3 :                 status = ftl_mngt_alloc_step_ctx(mngt, sizeof(*step_cntx_ptr));
     507         [ -  + ]:          3 :                 SPDK_CU_ASSERT_FATAL(status == 0);
     508                 :          3 :                 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                 :          3 :                 CU_ASSERT_PTR_NOT_NULL(step_cntx_ptr);
     513                 :          3 :                 CU_ASSERT_EQUAL(*step_cntx_ptr, 0);
     514                 :            : 
     515                 :            :                 /* check getting device */
     516                 :          3 :                 CU_ASSERT_EQUAL(ftl_mngt_get_dev(mngt), dev);
     517                 :          3 :                 CU_ASSERT_EQUAL(ftl_mngt_get_dev(mngt), &g_dev);
     518                 :            : 
     519                 :            :                 /* tests for process context */
     520                 :          3 :                 process_cntx_ptr = ftl_mngt_get_process_ctx(mngt);
     521                 :            : 
     522                 :            :                 /* 1st get of process context, should be clear ('0' values) */
     523                 :          3 :                 CU_ASSERT_EQUAL(process_cntx_ptr[0], 0);
     524                 :          3 :                 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                 :          3 :                 process_cntx_ptr[0] = PROCESS_CNTX_TEST_VAL_0;
     530                 :          3 :                 process_cntx_ptr[1] = PROCESS_CNTX_TEST_VAL_1;
     531                 :            : 
     532                 :            :                 /* tests for caller context */
     533                 :          3 :                 caller_cntx_ptr = ftl_mngt_get_caller_ctx(mngt);
     534                 :            : 
     535                 :            :                 /* check previously located values */
     536                 :          3 :                 CU_ASSERT_EQUAL(caller_cntx_ptr[0], 'm');
     537                 :          3 :                 CU_ASSERT_EQUAL(caller_cntx_ptr[1], 'i');
     538                 :          3 :                 CU_ASSERT_EQUAL(caller_cntx_ptr[2], 'e');
     539                 :            : 
     540                 :            :                 /* insert new */
     541                 :          3 :                 caller_cntx_ptr[0] = 'n';
     542                 :          3 :                 caller_cntx_ptr[1] = 'i';
     543                 :          3 :                 caller_cntx_ptr[2] = 'a';
     544                 :            : 
     545                 :          3 :                 ftl_mngt_next_step(mngt);
     546                 :            :         }
     547                 :          6 : }
     548                 :            : 
     549                 :            : static void
     550                 :          6 : 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                 :          6 :         step_cntx_ptr = ftl_mngt_get_step_ctx(mngt);
     557         [ +  + ]:          6 :         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                 :          3 :                 put_on_list();
     565                 :            :                 /* this step descriptor does not locate any context
     566                 :            :                  * at the beginning,
     567                 :            :                  * so pointer should contain NULL */
     568                 :          3 :                 CU_ASSERT_PTR_NULL(step_cntx_ptr);
     569                 :            : 
     570                 :            :                 /* check getting device */
     571                 :          3 :                 CU_ASSERT_EQUAL(ftl_mngt_get_dev(mngt), dev);
     572                 :          3 :                 CU_ASSERT_EQUAL(ftl_mngt_get_dev(mngt), &g_dev);
     573                 :            : 
     574                 :            :                 /* tests for process context */
     575                 :          3 :                 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                 :          3 :                 CU_ASSERT_EQUAL(process_cntx_ptr[0], PROCESS_CNTX_TEST_VAL_0);
     580                 :          3 :                 CU_ASSERT_EQUAL(process_cntx_ptr[1], PROCESS_CNTX_TEST_VAL_1);
     581                 :            : 
     582                 :            :                 /* tests for caller context */
     583                 :          3 :                 caller_cntx_ptr = ftl_mngt_get_caller_ctx(mngt);
     584                 :            : 
     585                 :            :                 /* check previously located values */
     586                 :          3 :                 CU_ASSERT_EQUAL(caller_cntx_ptr[0], 'n');
     587                 :          3 :                 CU_ASSERT_EQUAL(caller_cntx_ptr[1], 'i');
     588                 :          3 :                 CU_ASSERT_EQUAL(caller_cntx_ptr[2], 'a');
     589                 :            : 
     590                 :            :                 /* insert new */
     591                 :          3 :                 caller_cntx_ptr[0] = '!';
     592                 :          3 :                 caller_cntx_ptr[1] = '!';
     593                 :          3 :                 caller_cntx_ptr[2] = '!';
     594                 :            : 
     595                 :          3 :                 status = ftl_mngt_alloc_step_ctx(mngt, sizeof(*step_cntx_ptr));
     596         [ -  + ]:          3 :                 SPDK_CU_ASSERT_FATAL(status == 0);
     597                 :          3 :                 step_cntx_ptr = ftl_mngt_get_step_ctx(mngt);
     598                 :            :                 /* now pointer should point to allocated context */
     599                 :          3 :                 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                 :          3 :                 *step_cntx_ptr = STEP_CNTX_TEST_VAL;
     604                 :            : 
     605                 :          3 :                 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                 :          3 :                 CU_ASSERT_PTR_NOT_NULL(step_cntx_ptr);
     611                 :          3 :                 CU_ASSERT_EQUAL(*step_cntx_ptr, STEP_CNTX_TEST_VAL);
     612                 :            : 
     613                 :          3 :                 ftl_mngt_next_step(mngt);
     614                 :            :         }
     615                 :          6 : }
     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                 :          3 : test_get_func_and_step_cntx_alloc(void)
     638                 :            : {
     639                 :          3 :         char cb_cntx[4] = "daj";
     640                 :            : 
     641                 :          3 :         run_ftl_mngt_with_cb_cntx(ftl_mngt_process_execute, &pdesc_test_3, cb_cntx);
     642                 :            : 
     643                 :            :         /* check if caller callback was invoked */
     644                 :          3 :         check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
     645                 :            : 
     646                 :            :         /* check if steps changed cb_cntx correctly */
     647                 :          3 :         CU_ASSERT_EQUAL(cb_cntx[0], 'm');
     648                 :          3 :         CU_ASSERT_EQUAL(cb_cntx[1], 'i');
     649                 :          3 :         CU_ASSERT_EQUAL(cb_cntx[2], 'e');
     650                 :            : 
     651                 :          3 :         run_ftl_mngt_with_cb_cntx(ftl_mngt_process_rollback, &pdesc_test_3, cb_cntx);
     652                 :            : 
     653                 :            :         /* check if caller callback was invoked */
     654                 :          3 :         check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
     655                 :            : 
     656                 :            :         /* check if steps changed cb_cntx correctly */
     657                 :          3 :         CU_ASSERT_EQUAL(cb_cntx[0], '!');
     658                 :          3 :         CU_ASSERT_EQUAL(cb_cntx[1], '!');
     659                 :          3 :         CU_ASSERT_EQUAL(cb_cntx[2], '!');
     660                 :            : 
     661                 :          3 :         check_list_empty();
     662                 :          3 : }
     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                 :          3 : fn_4_1_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     678                 :            : {
     679                 :          3 :         add_elem_to_test_list(1);
     680                 :          3 :         ftl_mngt_next_step(mngt);
     681                 :          3 : }
     682                 :            : 
     683                 :            : static void
     684                 :          3 : fn_4_1_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     685                 :            : {
     686                 :          3 :         add_elem_to_test_list(-1);
     687                 :          3 :         ftl_mngt_next_step(mngt);
     688                 :          3 : }
     689                 :            : 
     690                 :            : static void
     691                 :          3 : fn_4_2_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     692                 :            : {
     693                 :          3 :         add_elem_to_test_list(2);
     694                 :          3 :         ftl_mngt_next_step(mngt);
     695                 :          3 : }
     696                 :            : 
     697                 :            : static void
     698                 :          3 : fn_4_2_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     699                 :            : {
     700                 :          3 :         add_elem_to_test_list(-2);
     701                 :          3 :         ftl_mngt_next_step(mngt);
     702                 :          3 : }
     703                 :            : 
     704                 :            : static void
     705                 :          3 : fn_4_3_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     706                 :            : {
     707                 :          3 :         add_elem_to_test_list(3);
     708                 :            :         /* this action fails, so cleanup should begin now */
     709                 :          3 :         ftl_mngt_fail_step(mngt);
     710                 :          3 : }
     711                 :            : 
     712                 :            : static void
     713                 :          3 : fn_4_3_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     714                 :            : {
     715                 :          3 :         add_elem_to_test_list(-3);
     716                 :          3 :         ftl_mngt_next_step(mngt);
     717                 :          3 : }
     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                 :          3 : test_fail_step(void)
     754                 :            : {
     755                 :          3 :         run_ftl_mngt(ftl_mngt_process_execute, &pdesc_test_4);
     756                 :            : 
     757                 :            :         /* check proper order of action functions */
     758         [ +  + ]:         12 :         for (int i = 1; i <= 3; i++) {
     759                 :          9 :                 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         [ +  + ]:         12 :         for (int i = 3; i > 0; i--) {
     765                 :          9 :                 check_elem_on_list_and_remove(-i);
     766                 :            :         }
     767                 :            : 
     768                 :            :         /* check if caller callback was invoked */
     769                 :          3 :         check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
     770                 :            : 
     771                 :          3 :         check_list_empty();
     772                 :          3 : }
     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                 :          3 : fn_5_2_1_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     782                 :            : {
     783                 :          3 :         add_elem_to_test_list(21);
     784                 :          3 :         ftl_mngt_next_step(mngt);
     785                 :          3 : }
     786                 :            : 
     787                 :            : static void
     788                 :          3 : fn_5_2_1_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     789                 :            : {
     790                 :          3 :         add_elem_to_test_list(-21);
     791                 :          3 :         ftl_mngt_next_step(mngt);
     792                 :          3 : }
     793                 :            : 
     794                 :            : static void
     795                 :          3 : fn_5_2_2_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     796                 :            : {
     797                 :          3 :         add_elem_to_test_list(22);
     798                 :          3 :         ftl_mngt_next_step(mngt);
     799                 :          3 : }
     800                 :            : 
     801                 :            : static void
     802                 :          3 : fn_5_2_2_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     803                 :            : {
     804                 :          3 :         add_elem_to_test_list(-22);
     805                 :          3 :         ftl_mngt_next_step(mngt);
     806                 :          3 : }
     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                 :          3 : fn_5_3_1_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     827                 :            : {
     828                 :          3 :         add_elem_to_test_list(31);
     829                 :          3 :         ftl_mngt_next_step(mngt);
     830                 :          3 : }
     831                 :            : 
     832                 :            : static void
     833                 :          3 : fn_5_3_1_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     834                 :            : {
     835                 :          3 :         add_elem_to_test_list(-31);
     836                 :          3 :         ftl_mngt_next_step(mngt);
     837                 :          3 : }
     838                 :            : 
     839                 :            : static void
     840                 :          3 : fn_5_3_2_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     841                 :            : {
     842                 :          3 :         add_elem_to_test_list(32);
     843                 :          3 :         ftl_mngt_next_step(mngt);
     844                 :          3 : }
     845                 :            : 
     846                 :            : static void
     847                 :          3 : fn_5_3_2_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     848                 :            : {
     849                 :          3 :         add_elem_to_test_list(-32);
     850                 :          3 :         ftl_mngt_next_step(mngt);
     851                 :          3 : }
     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                 :          3 : fn_5_1_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     872                 :            : {
     873                 :          3 :         add_elem_to_test_list(1);
     874                 :          3 :         ftl_mngt_next_step(mngt);
     875                 :          3 : }
     876                 :            : 
     877                 :            : static void
     878                 :          3 : fn_5_1_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     879                 :            : {
     880                 :          3 :         add_elem_to_test_list(-1);
     881                 :          3 :         ftl_mngt_next_step(mngt);
     882                 :          3 : }
     883                 :            : 
     884                 :            : static void
     885                 :          3 : fn_5_2_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     886                 :            : {
     887                 :          3 :         add_elem_to_test_list(2);
     888                 :          3 :         ftl_mngt_call_process(mngt, &pdesc_test_5_2, NULL);
     889                 :          3 : }
     890                 :            : 
     891                 :            : static void
     892                 :          3 : fn_5_2_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     893                 :            : {
     894                 :          3 :         add_elem_to_test_list(-2);
     895                 :          3 :         ftl_mngt_call_process_rollback(mngt, &pdesc_test_5_2);
     896                 :          3 : }
     897                 :            : 
     898                 :            : static void
     899                 :          3 : fn_5_3_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     900                 :            : {
     901                 :          3 :         add_elem_to_test_list(3);
     902                 :          3 :         ftl_mngt_call_process_rollback(mngt, &pdesc_test_5_3);
     903                 :          3 : }
     904                 :            : 
     905                 :            : static void
     906                 :          3 : fn_5_3_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     907                 :            : {
     908                 :          3 :         add_elem_to_test_list(-3);
     909                 :          3 :         ftl_mngt_call_process(mngt, &pdesc_test_5_3, NULL);
     910                 :          3 : }
     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                 :          3 : test_mngt_call_and_call_rollback(void)
     936                 :            : {
     937                 :          3 :         run_ftl_mngt(ftl_mngt_process_execute, &pdesc_test_5);
     938                 :            : 
     939                 :          3 :         check_elem_on_list_and_remove(1);
     940                 :          3 :         check_elem_on_list_and_remove(2);
     941                 :          3 :         check_elem_on_list_and_remove(21);
     942                 :          3 :         check_elem_on_list_and_remove(22);
     943                 :          3 :         check_elem_on_list_and_remove(3);
     944                 :          3 :         check_elem_on_list_and_remove(-32);
     945                 :          3 :         check_elem_on_list_and_remove(-31);
     946                 :            : 
     947                 :            :         /* check if caller callback was invoked */
     948                 :          3 :         check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
     949                 :            : 
     950                 :          3 :         run_ftl_mngt(ftl_mngt_process_rollback, &pdesc_test_5);
     951                 :            : 
     952                 :          3 :         check_elem_on_list_and_remove(-3);
     953                 :          3 :         check_elem_on_list_and_remove(31);
     954                 :          3 :         check_elem_on_list_and_remove(32);
     955                 :          3 :         check_elem_on_list_and_remove(-2);
     956                 :          3 :         check_elem_on_list_and_remove(-22);
     957                 :          3 :         check_elem_on_list_and_remove(-21);
     958                 :          3 :         check_elem_on_list_and_remove(-1);
     959                 :            : 
     960                 :            :         /* check if caller callback was invoked */
     961                 :          3 :         check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
     962                 :            : 
     963                 :          3 :         check_list_empty();
     964                 :          3 : }
     965                 :            : 
     966                 :            : /*
     967                 :            :  * test 6
     968                 :            :  * tests failure inside nested process
     969                 :            :  */
     970                 :            : 
     971                 :            : static void
     972                 :          3 : fn_6_2_1_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     973                 :            : {
     974                 :          3 :         add_elem_to_test_list(21);
     975                 :          3 :         ftl_mngt_next_step(mngt);
     976                 :          3 : }
     977                 :            : 
     978                 :            : static void
     979                 :          3 : fn_6_2_1_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     980                 :            : {
     981                 :          3 :         add_elem_to_test_list(-21);
     982                 :          3 :         ftl_mngt_next_step(mngt);
     983                 :          3 : }
     984                 :            : 
     985                 :            : static void
     986                 :          3 : fn_6_2_2_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     987                 :            : {
     988                 :          3 :         add_elem_to_test_list(22);
     989                 :            :         /* this action fails, so cleanup should begin now */
     990                 :          3 :         ftl_mngt_fail_step(mngt);
     991                 :          3 : }
     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                 :          3 : fn_6_1_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
    1022                 :            : {
    1023                 :          3 :         add_elem_to_test_list(1);
    1024                 :          3 :         ftl_mngt_next_step(mngt);
    1025                 :          3 : }
    1026                 :            : 
    1027                 :            : static void
    1028                 :          3 : fn_6_2_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
    1029                 :            : {
    1030                 :          3 :         add_elem_to_test_list(2);
    1031                 :          3 :         ftl_mngt_call_process(mngt, &pdesc_test_6_2, NULL);
    1032                 :          3 : }
    1033                 :            : 
    1034                 :            : static void
    1035                 :          3 : fn_6_2_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
    1036                 :            : {
    1037                 :          3 :         add_elem_to_test_list(-2);
    1038                 :          3 :         ftl_mngt_next_step(mngt);
    1039                 :          3 : }
    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                 :          3 : test_nested_process_failure(void)
    1070                 :            : {
    1071                 :          3 :         run_ftl_mngt(ftl_mngt_process_execute, &pdesc_test_6);
    1072                 :            : 
    1073                 :          3 :         check_elem_on_list_and_remove(1);
    1074                 :          3 :         check_elem_on_list_and_remove(2);
    1075                 :          3 :         check_elem_on_list_and_remove(21);
    1076                 :          3 :         check_elem_on_list_and_remove(22);
    1077                 :          3 :         check_elem_on_list_and_remove(-21);
    1078                 :          3 :         check_elem_on_list_and_remove(-2);
    1079                 :            : 
    1080                 :            :         /* check if caller callback was invoked */
    1081                 :          3 :         check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
    1082                 :            : 
    1083                 :          3 :         check_list_empty();
    1084                 :          3 : }
    1085                 :            : 
    1086                 :            : struct test_call_init_ctx {
    1087                 :            :         int init_handler_result;
    1088                 :            : };
    1089                 :            : 
    1090                 :            : static int
    1091                 :          6 : test_call_init_child_init_hndlr(struct spdk_ftl_dev *dev,
    1092                 :            :                                 struct ftl_mngt_process *mngt, void *_init_ctx)
    1093                 :            : {
    1094                 :          6 :         struct test_call_init_ctx *init_ctx = _init_ctx;
    1095                 :            : 
    1096                 :          6 :         add_elem_to_test_list(10);
    1097                 :          6 :         return init_ctx->init_handler_result;
    1098                 :            : }
    1099                 :            : 
    1100                 :            : static void
    1101                 :          3 : test_call_init_child_deinit_hndlr(struct spdk_ftl_dev *dev,
    1102                 :            :                                   struct ftl_mngt_process *mngt)
    1103                 :            : {
    1104                 :          3 :         add_elem_to_test_list(1000);
    1105                 :          3 : }
    1106                 :            : 
    1107                 :            : static void
    1108                 :          3 : test_call_init_child_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
    1109                 :            : {
    1110                 :          3 :         add_elem_to_test_list(100);
    1111                 :          3 :         ftl_mngt_next_step(mngt);
    1112                 :          3 : }
    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                 :          6 : test_call_init_parent_action(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
    1129                 :            : {
    1130                 :          6 :         struct test_call_init_ctx *init_ctx = ftl_mngt_get_caller_ctx(mngt);
    1131                 :            : 
    1132                 :          6 :         add_elem_to_test_list(1);
    1133                 :          6 :         ftl_mngt_call_process(mngt, &pdesc_test_call_init_child, init_ctx);
    1134                 :          6 : }
    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                 :          3 : test_call_init_success(void)
    1149                 :            : {
    1150                 :          3 :         struct test_call_init_ctx init_ctx = {
    1151                 :            :                 .init_handler_result = 0
    1152                 :            :         };
    1153                 :            : 
    1154                 :          3 :         run_ftl_mngt_with_cb_cntx(ftl_mngt_process_execute, &pdesc_test_call_init_parent, &init_ctx);
    1155                 :            : 
    1156                 :          3 :         check_elem_on_list_and_remove(1);
    1157                 :          3 :         check_elem_on_list_and_remove(10);
    1158                 :          3 :         check_elem_on_list_and_remove(100);
    1159                 :            : 
    1160                 :            :         /* check if caller deinit handler ws invoked */
    1161                 :          3 :         check_elem_on_list_and_remove(1000);
    1162                 :            : 
    1163                 :            :         /* check if caller callback was invoked */
    1164                 :          3 :         check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
    1165                 :            : 
    1166                 :          3 :         check_list_empty();
    1167                 :          3 : }
    1168                 :            : 
    1169                 :            : static void
    1170                 :          3 : test_call_init_failure(void)
    1171                 :            : {
    1172                 :          3 :         struct test_call_init_ctx init_ctx = {
    1173                 :            :                 .init_handler_result = -1
    1174                 :            :         };
    1175                 :            : 
    1176                 :          3 :         run_ftl_mngt_with_cb_cntx(ftl_mngt_process_execute, &pdesc_test_call_init_parent, &init_ctx);
    1177                 :            : 
    1178                 :          3 :         check_elem_on_list_and_remove(1);
    1179                 :          3 :         check_elem_on_list_and_remove(10);
    1180                 :            : 
    1181                 :            :         /* check if caller callback was invoked */
    1182                 :          3 :         check_elem_on_list_and_remove(CALLER_CB_RET_VALUE);
    1183                 :            : 
    1184                 :          3 :         check_list_empty();
    1185                 :          3 : }
    1186                 :            : 
    1187                 :            : int
    1188                 :          3 : main(int argc, char **argv)
    1189                 :            : {
    1190                 :          3 :         CU_pSuite suite = NULL;
    1191                 :            :         unsigned int num_failures;
    1192                 :            : 
    1193                 :          3 :         CU_initialize_registry();
    1194                 :            : 
    1195                 :          3 :         suite = CU_add_suite("ftl_mngt", setup_test_list, NULL);
    1196                 :            : 
    1197                 :          3 :         CU_ADD_TEST(suite, test_next_step);
    1198                 :          3 :         CU_ADD_TEST(suite, test_continue_step);
    1199                 :          3 :         CU_ADD_TEST(suite, test_get_func_and_step_cntx_alloc);
    1200                 :          3 :         CU_ADD_TEST(suite, test_fail_step);
    1201                 :          3 :         CU_ADD_TEST(suite, test_mngt_call_and_call_rollback);
    1202                 :          3 :         CU_ADD_TEST(suite, test_nested_process_failure);
    1203                 :          3 :         CU_ADD_TEST(suite, test_call_init_success);
    1204                 :          3 :         CU_ADD_TEST(suite, test_call_init_failure);
    1205                 :            : 
    1206                 :          3 :         num_failures = spdk_ut_run_tests(argc, argv, NULL);
    1207                 :          3 :         CU_cleanup_registry();
    1208                 :            : 
    1209                 :          3 :         return num_failures;
    1210                 :            : }

Generated by: LCOV version 1.14