xref: /spdk/test/unit/lib/init/subsystem.c/subsystem_ut.c (revision 95d6c9fac17572b107042103439aafd696d60b0e)
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 	short 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