1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * * Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * * Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * * Neither the name of Intel Corporation nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include "spdk/stdinc.h" 36 37 #include "spdk_cunit.h" 38 39 #include "unit/lib/json_mock.c" 40 #include "init/subsystem.c" 41 #include "common/lib/test_env.c" 42 43 static struct spdk_subsystem g_ut_subsystems[8]; 44 static struct spdk_subsystem_depend g_ut_subsystem_deps[8]; 45 static int global_rc; 46 47 static void 48 ut_event_fn(int rc, void *arg1) 49 { 50 global_rc = rc; 51 } 52 53 static void 54 set_up_subsystem(struct spdk_subsystem *subsystem, const char *name) 55 { 56 subsystem->init = NULL; 57 subsystem->fini = NULL; 58 subsystem->name = name; 59 } 60 61 static void 62 set_up_depends(struct spdk_subsystem_depend *depend, const char *subsystem_name, 63 const char *dpends_on_name) 64 { 65 depend->name = subsystem_name; 66 depend->depends_on = dpends_on_name; 67 } 68 69 static void 70 subsystem_clear(void) 71 { 72 struct spdk_subsystem *subsystem, *subsystem_tmp; 73 struct spdk_subsystem_depend *subsystem_dep, *subsystem_dep_tmp; 74 75 TAILQ_FOREACH_SAFE(subsystem, &g_subsystems, tailq, subsystem_tmp) { 76 TAILQ_REMOVE(&g_subsystems, subsystem, tailq); 77 } 78 79 TAILQ_FOREACH_SAFE(subsystem_dep, &g_subsystems_deps, tailq, subsystem_dep_tmp) { 80 TAILQ_REMOVE(&g_subsystems_deps, subsystem_dep, tailq); 81 } 82 } 83 84 static void 85 subsystem_sort_test_depends_on_single(void) 86 { 87 struct spdk_subsystem *subsystem; 88 int i; 89 char subsystem_name[16]; 90 91 global_rc = -1; 92 spdk_subsystem_init(ut_event_fn, NULL); 93 CU_ASSERT(global_rc == 0); 94 95 i = 4; 96 TAILQ_FOREACH(subsystem, &g_subsystems, tailq) { 97 snprintf(subsystem_name, sizeof(subsystem_name), "subsystem%d", i); 98 SPDK_CU_ASSERT_FATAL(i > 0); 99 i--; 100 CU_ASSERT(strcmp(subsystem_name, subsystem->name) == 0); 101 } 102 } 103 104 static void 105 subsystem_sort_test_depends_on_multiple(void) 106 { 107 int i; 108 struct spdk_subsystem *subsystem; 109 110 subsystem_clear(); 111 set_up_subsystem(&g_ut_subsystems[0], "iscsi"); 112 set_up_subsystem(&g_ut_subsystems[1], "nvmf"); 113 set_up_subsystem(&g_ut_subsystems[2], "sock"); 114 set_up_subsystem(&g_ut_subsystems[3], "bdev"); 115 set_up_subsystem(&g_ut_subsystems[4], "rpc"); 116 set_up_subsystem(&g_ut_subsystems[5], "scsi"); 117 set_up_subsystem(&g_ut_subsystems[6], "interface"); 118 set_up_subsystem(&g_ut_subsystems[7], "accel"); 119 120 for (i = 0; i < 8; i++) { 121 spdk_add_subsystem(&g_ut_subsystems[i]); 122 } 123 124 set_up_depends(&g_ut_subsystem_deps[0], "bdev", "accel"); 125 set_up_depends(&g_ut_subsystem_deps[1], "scsi", "bdev"); 126 set_up_depends(&g_ut_subsystem_deps[2], "rpc", "interface"); 127 set_up_depends(&g_ut_subsystem_deps[3], "sock", "interface"); 128 set_up_depends(&g_ut_subsystem_deps[4], "nvmf", "interface"); 129 set_up_depends(&g_ut_subsystem_deps[5], "iscsi", "scsi"); 130 set_up_depends(&g_ut_subsystem_deps[6], "iscsi", "sock"); 131 set_up_depends(&g_ut_subsystem_deps[7], "iscsi", "rpc"); 132 133 for (i = 0; i < 8; i++) { 134 spdk_add_subsystem_depend(&g_ut_subsystem_deps[i]); 135 } 136 137 global_rc = -1; 138 spdk_subsystem_init(ut_event_fn, NULL); 139 CU_ASSERT(global_rc == 0); 140 141 subsystem = TAILQ_FIRST(&g_subsystems); 142 CU_ASSERT(strcmp(subsystem->name, "interface") == 0); 143 TAILQ_REMOVE(&g_subsystems, subsystem, tailq); 144 145 subsystem = TAILQ_FIRST(&g_subsystems); 146 CU_ASSERT(strcmp(subsystem->name, "accel") == 0); 147 TAILQ_REMOVE(&g_subsystems, subsystem, tailq); 148 149 subsystem = TAILQ_FIRST(&g_subsystems); 150 CU_ASSERT(strcmp(subsystem->name, "nvmf") == 0); 151 TAILQ_REMOVE(&g_subsystems, subsystem, tailq); 152 153 subsystem = TAILQ_FIRST(&g_subsystems); 154 CU_ASSERT(strcmp(subsystem->name, "sock") == 0); 155 TAILQ_REMOVE(&g_subsystems, subsystem, tailq); 156 157 subsystem = TAILQ_FIRST(&g_subsystems); 158 CU_ASSERT(strcmp(subsystem->name, "bdev") == 0); 159 TAILQ_REMOVE(&g_subsystems, subsystem, tailq); 160 161 subsystem = TAILQ_FIRST(&g_subsystems); 162 CU_ASSERT(strcmp(subsystem->name, "rpc") == 0); 163 TAILQ_REMOVE(&g_subsystems, subsystem, tailq); 164 165 subsystem = TAILQ_FIRST(&g_subsystems); 166 CU_ASSERT(strcmp(subsystem->name, "scsi") == 0); 167 TAILQ_REMOVE(&g_subsystems, subsystem, tailq); 168 169 subsystem = TAILQ_FIRST(&g_subsystems); 170 CU_ASSERT(strcmp(subsystem->name, "iscsi") == 0); 171 TAILQ_REMOVE(&g_subsystems, subsystem, tailq); 172 } 173 174 struct spdk_subsystem subsystem1 = { 175 .name = "subsystem1", 176 }; 177 178 struct spdk_subsystem subsystem2 = { 179 .name = "subsystem2", 180 }; 181 struct spdk_subsystem subsystem3 = { 182 .name = "subsystem3", 183 }; 184 185 struct spdk_subsystem subsystem4 = { 186 .name = "subsystem4", 187 }; 188 189 SPDK_SUBSYSTEM_REGISTER(subsystem1); 190 SPDK_SUBSYSTEM_REGISTER(subsystem2); 191 SPDK_SUBSYSTEM_REGISTER(subsystem3); 192 SPDK_SUBSYSTEM_REGISTER(subsystem4); 193 194 SPDK_SUBSYSTEM_DEPEND(subsystem1, subsystem2) 195 SPDK_SUBSYSTEM_DEPEND(subsystem2, subsystem3) 196 SPDK_SUBSYSTEM_DEPEND(subsystem3, subsystem4) 197 198 199 static void 200 subsystem_sort_test_missing_dependency(void) 201 { 202 /* 203 * A depends on B, but B is missing 204 */ 205 206 subsystem_clear(); 207 set_up_subsystem(&g_ut_subsystems[0], "A"); 208 spdk_add_subsystem(&g_ut_subsystems[0]); 209 210 set_up_depends(&g_ut_subsystem_deps[0], "A", "B"); 211 spdk_add_subsystem_depend(&g_ut_subsystem_deps[0]); 212 213 global_rc = -1; 214 spdk_subsystem_init(ut_event_fn, NULL); 215 CU_ASSERT(global_rc != 0); 216 217 /* 218 * Dependency from C to A is defined, but C is missing 219 */ 220 221 subsystem_clear(); 222 set_up_subsystem(&g_ut_subsystems[0], "A"); 223 spdk_add_subsystem(&g_ut_subsystems[0]); 224 225 set_up_depends(&g_ut_subsystem_deps[0], "C", "A"); 226 spdk_add_subsystem_depend(&g_ut_subsystem_deps[0]); 227 228 global_rc = -1; 229 spdk_subsystem_init(ut_event_fn, NULL); 230 CU_ASSERT(global_rc != 0); 231 232 } 233 234 int 235 main(int argc, char **argv) 236 { 237 CU_pSuite suite = NULL; 238 unsigned int num_failures; 239 240 CU_set_error_action(CUEA_ABORT); 241 CU_initialize_registry(); 242 243 suite = CU_add_suite("subsystem_suite", NULL, NULL); 244 245 CU_ADD_TEST(suite, subsystem_sort_test_depends_on_single); 246 CU_ADD_TEST(suite, subsystem_sort_test_depends_on_multiple); 247 CU_ADD_TEST(suite, subsystem_sort_test_missing_dependency); 248 249 CU_basic_set_mode(CU_BRM_VERBOSE); 250 CU_basic_run_tests(); 251 num_failures = CU_get_number_of_failures(); 252 CU_cleanup_registry(); 253 254 return num_failures; 255 } 256