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