1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2016 Intel Corporation. 3 * All rights reserved. 4 * Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 5 */ 6 7 #include "spdk/stdinc.h" 8 9 #include "spdk_internal/cunit.h" 10 11 #include "unit/lib/json_mock.c" 12 #include "init/subsystem.c" 13 #include "common/lib/test_env.c" 14 15 static struct spdk_subsystem g_ut_subsystems[8]; 16 static struct spdk_subsystem_depend g_ut_subsystem_deps[8]; 17 static int global_rc; 18 19 static void 20 ut_event_fn(int rc, void *arg1) 21 { 22 global_rc = rc; 23 } 24 25 static void 26 set_up_subsystem(struct spdk_subsystem *subsystem, const char *name) 27 { 28 subsystem->init = NULL; 29 subsystem->fini = NULL; 30 subsystem->name = name; 31 } 32 33 static void 34 set_up_depends(struct spdk_subsystem_depend *depend, const char *subsystem_name, 35 const char *depends_on_name) 36 { 37 depend->name = subsystem_name; 38 depend->depends_on = depends_on_name; 39 } 40 41 static void 42 subsystem_clear(void) 43 { 44 struct spdk_subsystem *subsystem, *subsystem_tmp; 45 struct spdk_subsystem_depend *subsystem_dep, *subsystem_dep_tmp; 46 47 TAILQ_FOREACH_SAFE(subsystem, &g_subsystems, tailq, subsystem_tmp) { 48 TAILQ_REMOVE(&g_subsystems, subsystem, tailq); 49 } 50 51 TAILQ_FOREACH_SAFE(subsystem_dep, &g_subsystems_deps, tailq, subsystem_dep_tmp) { 52 TAILQ_REMOVE(&g_subsystems_deps, subsystem_dep, tailq); 53 } 54 } 55 56 static void 57 subsystem_sort_test_depends_on_single(void) 58 { 59 struct spdk_subsystem *subsystem; 60 int i; 61 char subsystem_name[16]; 62 63 global_rc = -1; 64 spdk_subsystem_init(ut_event_fn, NULL); 65 CU_ASSERT(global_rc == 0); 66 67 i = 4; 68 TAILQ_FOREACH(subsystem, &g_subsystems, tailq) { 69 snprintf(subsystem_name, sizeof(subsystem_name), "subsystem%d", i); 70 SPDK_CU_ASSERT_FATAL(i > 0); 71 i--; 72 CU_ASSERT(strcmp(subsystem_name, subsystem->name) == 0); 73 } 74 } 75 76 static void 77 subsystem_sort_test_depends_on_multiple(void) 78 { 79 int i; 80 struct spdk_subsystem *subsystem; 81 82 subsystem_clear(); 83 set_up_subsystem(&g_ut_subsystems[0], "iscsi"); 84 set_up_subsystem(&g_ut_subsystems[1], "nvmf"); 85 set_up_subsystem(&g_ut_subsystems[2], "sock"); 86 set_up_subsystem(&g_ut_subsystems[3], "bdev"); 87 set_up_subsystem(&g_ut_subsystems[4], "rpc"); 88 set_up_subsystem(&g_ut_subsystems[5], "scsi"); 89 set_up_subsystem(&g_ut_subsystems[6], "interface"); 90 set_up_subsystem(&g_ut_subsystems[7], "accel"); 91 92 for (i = 0; i < 8; i++) { 93 spdk_add_subsystem(&g_ut_subsystems[i]); 94 } 95 96 set_up_depends(&g_ut_subsystem_deps[0], "bdev", "accel"); 97 set_up_depends(&g_ut_subsystem_deps[1], "scsi", "bdev"); 98 set_up_depends(&g_ut_subsystem_deps[2], "rpc", "interface"); 99 set_up_depends(&g_ut_subsystem_deps[3], "sock", "interface"); 100 set_up_depends(&g_ut_subsystem_deps[4], "nvmf", "interface"); 101 set_up_depends(&g_ut_subsystem_deps[5], "iscsi", "scsi"); 102 set_up_depends(&g_ut_subsystem_deps[6], "iscsi", "sock"); 103 set_up_depends(&g_ut_subsystem_deps[7], "iscsi", "rpc"); 104 105 for (i = 0; i < 8; i++) { 106 spdk_add_subsystem_depend(&g_ut_subsystem_deps[i]); 107 } 108 109 global_rc = -1; 110 spdk_subsystem_init(ut_event_fn, NULL); 111 CU_ASSERT(global_rc == 0); 112 113 subsystem = TAILQ_FIRST(&g_subsystems); 114 CU_ASSERT(strcmp(subsystem->name, "interface") == 0); 115 TAILQ_REMOVE(&g_subsystems, subsystem, tailq); 116 117 subsystem = TAILQ_FIRST(&g_subsystems); 118 CU_ASSERT(strcmp(subsystem->name, "accel") == 0); 119 TAILQ_REMOVE(&g_subsystems, subsystem, tailq); 120 121 subsystem = TAILQ_FIRST(&g_subsystems); 122 CU_ASSERT(strcmp(subsystem->name, "nvmf") == 0); 123 TAILQ_REMOVE(&g_subsystems, subsystem, tailq); 124 125 subsystem = TAILQ_FIRST(&g_subsystems); 126 CU_ASSERT(strcmp(subsystem->name, "sock") == 0); 127 TAILQ_REMOVE(&g_subsystems, subsystem, tailq); 128 129 subsystem = TAILQ_FIRST(&g_subsystems); 130 CU_ASSERT(strcmp(subsystem->name, "bdev") == 0); 131 TAILQ_REMOVE(&g_subsystems, subsystem, tailq); 132 133 subsystem = TAILQ_FIRST(&g_subsystems); 134 CU_ASSERT(strcmp(subsystem->name, "rpc") == 0); 135 TAILQ_REMOVE(&g_subsystems, subsystem, tailq); 136 137 subsystem = TAILQ_FIRST(&g_subsystems); 138 CU_ASSERT(strcmp(subsystem->name, "scsi") == 0); 139 TAILQ_REMOVE(&g_subsystems, subsystem, tailq); 140 141 subsystem = TAILQ_FIRST(&g_subsystems); 142 CU_ASSERT(strcmp(subsystem->name, "iscsi") == 0); 143 TAILQ_REMOVE(&g_subsystems, subsystem, tailq); 144 } 145 146 struct spdk_subsystem subsystem1 = { 147 .name = "subsystem1", 148 }; 149 150 struct spdk_subsystem subsystem2 = { 151 .name = "subsystem2", 152 }; 153 struct spdk_subsystem subsystem3 = { 154 .name = "subsystem3", 155 }; 156 157 struct spdk_subsystem subsystem4 = { 158 .name = "subsystem4", 159 }; 160 161 SPDK_SUBSYSTEM_REGISTER(subsystem1); 162 SPDK_SUBSYSTEM_REGISTER(subsystem2); 163 SPDK_SUBSYSTEM_REGISTER(subsystem3); 164 SPDK_SUBSYSTEM_REGISTER(subsystem4); 165 166 SPDK_SUBSYSTEM_DEPEND(subsystem1, subsystem2) 167 SPDK_SUBSYSTEM_DEPEND(subsystem2, subsystem3) 168 SPDK_SUBSYSTEM_DEPEND(subsystem3, subsystem4) 169 170 171 static void 172 subsystem_sort_test_missing_dependency(void) 173 { 174 /* 175 * A depends on B, but B is missing 176 */ 177 178 subsystem_clear(); 179 set_up_subsystem(&g_ut_subsystems[0], "A"); 180 spdk_add_subsystem(&g_ut_subsystems[0]); 181 182 set_up_depends(&g_ut_subsystem_deps[0], "A", "B"); 183 spdk_add_subsystem_depend(&g_ut_subsystem_deps[0]); 184 185 global_rc = -1; 186 spdk_subsystem_init(ut_event_fn, NULL); 187 CU_ASSERT(global_rc != 0); 188 189 /* 190 * Dependency from C to A is defined, but C is missing 191 */ 192 193 subsystem_clear(); 194 set_up_subsystem(&g_ut_subsystems[0], "A"); 195 spdk_add_subsystem(&g_ut_subsystems[0]); 196 197 set_up_depends(&g_ut_subsystem_deps[0], "C", "A"); 198 spdk_add_subsystem_depend(&g_ut_subsystem_deps[0]); 199 200 global_rc = -1; 201 spdk_subsystem_init(ut_event_fn, NULL); 202 CU_ASSERT(global_rc != 0); 203 204 } 205 206 int 207 main(int argc, char **argv) 208 { 209 CU_pSuite suite = NULL; 210 unsigned int num_failures; 211 struct spdk_thread *thread; 212 213 CU_initialize_registry(); 214 215 suite = CU_add_suite("subsystem_suite", NULL, NULL); 216 217 spdk_thread_lib_init(NULL, 0); 218 thread = spdk_thread_create(NULL, NULL); 219 spdk_set_thread(thread); 220 221 CU_ADD_TEST(suite, subsystem_sort_test_depends_on_single); 222 CU_ADD_TEST(suite, subsystem_sort_test_depends_on_multiple); 223 CU_ADD_TEST(suite, subsystem_sort_test_missing_dependency); 224 225 num_failures = spdk_ut_run_tests(argc, argv, NULL); 226 CU_cleanup_registry(); 227 228 return num_failures; 229 } 230