1 /*
2 * libqos driver framework
3 *
4 * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License version 2.1 as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, see <http://www.gnu.org/licenses/>
17 */
18
19 #include "qemu/osdep.h"
20 #include "../qtest/libqos/qgraph.h"
21 #include "../qtest/libqos/qgraph_internal.h"
22
23 #define MACHINE_PC "x86_64/pc"
24 #define MACHINE_RASPI2 "arm/raspi2b"
25 #define I440FX "i440FX-pcihost"
26 #define PCIBUS_PC "pcibus-pc"
27 #define SDHCI "sdhci"
28 #define PCIBUS "pci-bus"
29 #define SDHCI_PCI "sdhci-pci"
30 #define SDHCI_MM "generic-sdhci"
31 #define REGISTER_TEST "register-test"
32
33 int npath;
34
machinefunct(QTestState * qts)35 static void *machinefunct(QTestState *qts)
36 {
37 return NULL;
38 }
39
driverfunct(void * obj,QGuestAllocator * machine,void * arg)40 static void *driverfunct(void *obj, QGuestAllocator *machine, void *arg)
41 {
42 return NULL;
43 }
44
testfunct(void * obj,void * arg,QGuestAllocator * alloc)45 static void testfunct(void *obj, void *arg, QGuestAllocator *alloc)
46 {
47 }
48
check_interface(const char * interface)49 static void check_interface(const char *interface)
50 {
51 g_assert_cmpint(qos_graph_has_machine(interface), ==, FALSE);
52 g_assert_nonnull(qos_graph_get_node(interface));
53 g_assert_cmpint(qos_graph_has_node(interface), ==, TRUE);
54 g_assert_cmpint(qos_graph_get_node_type(interface), ==, QNODE_INTERFACE);
55 qos_graph_node_set_availability(interface, TRUE);
56 g_assert_cmpint(qos_graph_get_node_availability(interface), ==, TRUE);
57 }
58
check_machine(const char * machine)59 static void check_machine(const char *machine)
60 {
61 qos_node_create_machine(machine, machinefunct);
62 g_assert_nonnull(qos_graph_get_machine(machine));
63 g_assert_cmpint(qos_graph_has_machine(machine), ==, TRUE);
64 g_assert_nonnull(qos_graph_get_node(machine));
65 g_assert_cmpint(qos_graph_get_node_availability(machine), ==, FALSE);
66 qos_graph_node_set_availability(machine, TRUE);
67 g_assert_cmpint(qos_graph_get_node_availability(machine), ==, TRUE);
68 g_assert_cmpint(qos_graph_has_node(machine), ==, TRUE);
69 g_assert_cmpint(qos_graph_get_node_type(machine), ==, QNODE_MACHINE);
70 }
71
check_contains(const char * machine,const char * driver)72 static void check_contains(const char *machine, const char *driver)
73 {
74 QOSGraphEdge *edge;
75 qos_node_contains(machine, driver, NULL);
76
77 edge = qos_graph_get_edge(machine, driver);
78 g_assert_nonnull(edge);
79 g_assert_cmpint(qos_graph_edge_get_type(edge), ==, QEDGE_CONTAINS);
80 g_assert_cmpint(qos_graph_has_edge(machine, driver), ==, TRUE);
81 }
82
check_produces(const char * machine,const char * interface)83 static void check_produces(const char *machine, const char *interface)
84 {
85 QOSGraphEdge *edge;
86
87 qos_node_produces(machine, interface);
88 check_interface(interface);
89 edge = qos_graph_get_edge(machine, interface);
90 g_assert_nonnull(edge);
91 g_assert_cmpint(qos_graph_edge_get_type(edge), ==,
92 QEDGE_PRODUCES);
93 g_assert_cmpint(qos_graph_has_edge(machine, interface), ==, TRUE);
94 }
95
check_consumes(const char * driver,const char * interface)96 static void check_consumes(const char *driver, const char *interface)
97 {
98 QOSGraphEdge *edge;
99
100 qos_node_consumes(driver, interface, NULL);
101 check_interface(interface);
102 edge = qos_graph_get_edge(interface, driver);
103 g_assert_nonnull(edge);
104 g_assert_cmpint(qos_graph_edge_get_type(edge), ==, QEDGE_CONSUMED_BY);
105 g_assert_cmpint(qos_graph_has_edge(interface, driver), ==, TRUE);
106 }
107
check_driver(const char * driver)108 static void check_driver(const char *driver)
109 {
110 qos_node_create_driver(driver, driverfunct);
111 g_assert_cmpint(qos_graph_has_machine(driver), ==, FALSE);
112 g_assert_nonnull(qos_graph_get_node(driver));
113 g_assert_cmpint(qos_graph_has_node(driver), ==, TRUE);
114 g_assert_cmpint(qos_graph_get_node_type(driver), ==, QNODE_DRIVER);
115 g_assert_cmpint(qos_graph_get_node_availability(driver), ==, FALSE);
116 qos_graph_node_set_availability(driver, TRUE);
117 g_assert_cmpint(qos_graph_get_node_availability(driver), ==, TRUE);
118 }
119
check_test(const char * test,const char * interface)120 static void check_test(const char *test, const char *interface)
121 {
122 QOSGraphEdge *edge;
123 char *full_name = g_strdup_printf("%s-tests/%s", interface, test);
124
125 qos_add_test(test, interface, testfunct, NULL);
126 g_assert_cmpint(qos_graph_has_machine(test), ==, FALSE);
127 g_assert_cmpint(qos_graph_has_machine(full_name), ==, FALSE);
128 g_assert_nonnull(qos_graph_get_node(full_name));
129 g_assert_cmpint(qos_graph_has_node(full_name), ==, TRUE);
130 g_assert_cmpint(qos_graph_get_node_type(full_name), ==, QNODE_TEST);
131 edge = qos_graph_get_edge(interface, full_name);
132 g_assert_nonnull(edge);
133 g_assert_cmpint(qos_graph_edge_get_type(edge), ==,
134 QEDGE_CONSUMED_BY);
135 g_assert_cmpint(qos_graph_has_edge(interface, full_name), ==, TRUE);
136 g_assert_cmpint(qos_graph_get_node_availability(full_name), ==, TRUE);
137 qos_graph_node_set_availability(full_name, FALSE);
138 g_assert_cmpint(qos_graph_get_node_availability(full_name), ==, FALSE);
139 g_free(full_name);
140 }
141
count_each_test(QOSGraphNode * path,int len)142 static void count_each_test(QOSGraphNode *path, int len)
143 {
144 npath++;
145 }
146
check_leaf_discovered(int n)147 static void check_leaf_discovered(int n)
148 {
149 npath = 0;
150 qos_graph_foreach_test_path(count_each_test);
151 g_assert_cmpint(n, ==, npath);
152 }
153
154 /* G_Test functions */
155
init_nop(void)156 static void init_nop(void)
157 {
158 qos_graph_init();
159 qos_graph_destroy();
160 }
161
test_machine(void)162 static void test_machine(void)
163 {
164 qos_graph_init();
165 check_machine(MACHINE_PC);
166 qos_graph_destroy();
167 }
168
test_contains(void)169 static void test_contains(void)
170 {
171 qos_graph_init();
172 check_contains(MACHINE_PC, I440FX);
173 g_assert_null(qos_graph_get_machine(MACHINE_PC));
174 g_assert_null(qos_graph_get_machine(I440FX));
175 g_assert_null(qos_graph_get_node(MACHINE_PC));
176 g_assert_null(qos_graph_get_node(I440FX));
177 qos_graph_destroy();
178 }
179
test_multiple_contains(void)180 static void test_multiple_contains(void)
181 {
182 qos_graph_init();
183 check_contains(MACHINE_PC, I440FX);
184 check_contains(MACHINE_PC, PCIBUS_PC);
185 qos_graph_destroy();
186 }
187
test_produces(void)188 static void test_produces(void)
189 {
190 qos_graph_init();
191 check_produces(MACHINE_PC, I440FX);
192 g_assert_null(qos_graph_get_machine(MACHINE_PC));
193 g_assert_null(qos_graph_get_machine(I440FX));
194 g_assert_null(qos_graph_get_node(MACHINE_PC));
195 g_assert_nonnull(qos_graph_get_node(I440FX));
196 qos_graph_destroy();
197 }
198
test_multiple_produces(void)199 static void test_multiple_produces(void)
200 {
201 qos_graph_init();
202 check_produces(MACHINE_PC, I440FX);
203 check_produces(MACHINE_PC, PCIBUS_PC);
204 qos_graph_destroy();
205 }
206
test_consumes(void)207 static void test_consumes(void)
208 {
209 qos_graph_init();
210 check_consumes(I440FX, SDHCI);
211 g_assert_null(qos_graph_get_machine(I440FX));
212 g_assert_null(qos_graph_get_machine(SDHCI));
213 g_assert_null(qos_graph_get_node(I440FX));
214 g_assert_nonnull(qos_graph_get_node(SDHCI));
215 qos_graph_destroy();
216 }
217
test_multiple_consumes(void)218 static void test_multiple_consumes(void)
219 {
220 qos_graph_init();
221 check_consumes(I440FX, SDHCI);
222 check_consumes(PCIBUS_PC, SDHCI);
223 qos_graph_destroy();
224 }
225
test_driver(void)226 static void test_driver(void)
227 {
228 qos_graph_init();
229 check_driver(I440FX);
230 qos_graph_destroy();
231 }
232
test_test(void)233 static void test_test(void)
234 {
235 qos_graph_init();
236 check_test(REGISTER_TEST, SDHCI);
237 qos_graph_destroy();
238 }
239
test_machine_contains_driver(void)240 static void test_machine_contains_driver(void)
241 {
242 qos_graph_init();
243 check_machine(MACHINE_PC);
244 check_driver(I440FX);
245 check_contains(MACHINE_PC, I440FX);
246 qos_graph_destroy();
247 }
248
test_driver_contains_driver(void)249 static void test_driver_contains_driver(void)
250 {
251 qos_graph_init();
252 check_driver(PCIBUS_PC);
253 check_driver(I440FX);
254 check_contains(PCIBUS_PC, I440FX);
255 qos_graph_destroy();
256 }
257
test_machine_produces_interface(void)258 static void test_machine_produces_interface(void)
259 {
260 qos_graph_init();
261 check_machine(MACHINE_PC);
262 check_produces(MACHINE_PC, SDHCI);
263 qos_graph_destroy();
264 }
265
test_driver_produces_interface(void)266 static void test_driver_produces_interface(void)
267 {
268 qos_graph_init();
269 check_driver(I440FX);
270 check_produces(I440FX, SDHCI);
271 qos_graph_destroy();
272 }
273
test_machine_consumes_interface(void)274 static void test_machine_consumes_interface(void)
275 {
276 qos_graph_init();
277 check_machine(MACHINE_PC);
278 check_consumes(MACHINE_PC, SDHCI);
279 qos_graph_destroy();
280 }
281
test_driver_consumes_interface(void)282 static void test_driver_consumes_interface(void)
283 {
284 qos_graph_init();
285 check_driver(I440FX);
286 check_consumes(I440FX, SDHCI);
287 qos_graph_destroy();
288 }
289
test_test_consumes_interface(void)290 static void test_test_consumes_interface(void)
291 {
292 qos_graph_init();
293 check_test(REGISTER_TEST, SDHCI);
294 qos_graph_destroy();
295 }
296
test_full_sample(void)297 static void test_full_sample(void)
298 {
299 qos_graph_init();
300 check_machine(MACHINE_PC);
301 check_contains(MACHINE_PC, I440FX);
302 check_driver(I440FX);
303 check_driver(PCIBUS_PC);
304 check_contains(I440FX, PCIBUS_PC);
305 check_produces(PCIBUS_PC, PCIBUS);
306 check_driver(SDHCI_PCI);
307 qos_node_consumes(SDHCI_PCI, PCIBUS, NULL);
308 check_produces(SDHCI_PCI, SDHCI);
309 check_driver(SDHCI_MM);
310 check_produces(SDHCI_MM, SDHCI);
311 qos_add_test(REGISTER_TEST, SDHCI, testfunct, NULL);
312 check_leaf_discovered(1);
313 qos_print_graph();
314 qos_graph_destroy();
315 }
316
test_full_sample_raspi(void)317 static void test_full_sample_raspi(void)
318 {
319 qos_graph_init();
320 check_machine(MACHINE_PC);
321 check_contains(MACHINE_PC, I440FX);
322 check_driver(I440FX);
323 check_driver(PCIBUS_PC);
324 check_contains(I440FX, PCIBUS_PC);
325 check_produces(PCIBUS_PC, PCIBUS);
326 check_driver(SDHCI_PCI);
327 qos_node_consumes(SDHCI_PCI, PCIBUS, NULL);
328 check_produces(SDHCI_PCI, SDHCI);
329 check_machine(MACHINE_RASPI2);
330 check_contains(MACHINE_RASPI2, SDHCI_MM);
331 check_driver(SDHCI_MM);
332 check_produces(SDHCI_MM, SDHCI);
333 qos_add_test(REGISTER_TEST, SDHCI, testfunct, NULL);
334 qos_print_graph();
335 check_leaf_discovered(2);
336 qos_graph_destroy();
337 }
338
test_cycle(void)339 static void test_cycle(void)
340 {
341 qos_graph_init();
342 check_machine(MACHINE_RASPI2);
343 check_driver("B");
344 check_driver("C");
345 check_driver("D");
346 check_contains(MACHINE_RASPI2, "B");
347 check_contains("B", "C");
348 check_contains("C", "D");
349 check_contains("D", MACHINE_RASPI2);
350 check_leaf_discovered(0);
351 qos_print_graph();
352 qos_graph_destroy();
353 }
354
test_two_test_same_interface(void)355 static void test_two_test_same_interface(void)
356 {
357 qos_graph_init();
358 check_machine(MACHINE_RASPI2);
359 check_produces(MACHINE_RASPI2, "B");
360 qos_add_test("C", "B", testfunct, NULL);
361 qos_add_test("D", "B", testfunct, NULL);
362 check_contains(MACHINE_RASPI2, "B");
363 check_leaf_discovered(4);
364 qos_print_graph();
365 qos_graph_destroy();
366 }
367
test_test_in_path(void)368 static void test_test_in_path(void)
369 {
370 qos_graph_init();
371 check_machine(MACHINE_RASPI2);
372 check_produces(MACHINE_RASPI2, "B");
373 qos_add_test("C", "B", testfunct, NULL);
374 check_driver("D");
375 check_consumes("D", "B");
376 check_produces("D", "E");
377 qos_add_test("F", "E", testfunct, NULL);
378 check_leaf_discovered(2);
379 qos_print_graph();
380 qos_graph_destroy();
381 }
382
test_double_edge(void)383 static void test_double_edge(void)
384 {
385 qos_graph_init();
386 check_machine(MACHINE_RASPI2);
387 check_produces("B", "C");
388 qos_node_consumes("C", "B", NULL);
389 qos_add_test("D", "C", testfunct, NULL);
390 check_contains(MACHINE_RASPI2, "B");
391 qos_print_graph();
392 qos_graph_destroy();
393 }
394
main(int argc,char ** argv)395 int main(int argc, char **argv)
396 {
397 g_test_init(&argc, &argv, NULL);
398 g_test_add_func("/qgraph/init_nop", init_nop);
399 g_test_add_func("/qgraph/test_machine", test_machine);
400 g_test_add_func("/qgraph/test_contains", test_contains);
401 g_test_add_func("/qgraph/test_multiple_contains", test_multiple_contains);
402 g_test_add_func("/qgraph/test_produces", test_produces);
403 g_test_add_func("/qgraph/test_multiple_produces", test_multiple_produces);
404 g_test_add_func("/qgraph/test_consumes", test_consumes);
405 g_test_add_func("/qgraph/test_multiple_consumes",
406 test_multiple_consumes);
407 g_test_add_func("/qgraph/test_driver", test_driver);
408 g_test_add_func("/qgraph/test_test", test_test);
409 g_test_add_func("/qgraph/test_machine_contains_driver",
410 test_machine_contains_driver);
411 g_test_add_func("/qgraph/test_driver_contains_driver",
412 test_driver_contains_driver);
413 g_test_add_func("/qgraph/test_machine_produces_interface",
414 test_machine_produces_interface);
415 g_test_add_func("/qgraph/test_driver_produces_interface",
416 test_driver_produces_interface);
417 g_test_add_func("/qgraph/test_machine_consumes_interface",
418 test_machine_consumes_interface);
419 g_test_add_func("/qgraph/test_driver_consumes_interface",
420 test_driver_consumes_interface);
421 g_test_add_func("/qgraph/test_test_consumes_interface",
422 test_test_consumes_interface);
423 g_test_add_func("/qgraph/test_full_sample", test_full_sample);
424 g_test_add_func("/qgraph/test_full_sample_raspi", test_full_sample_raspi);
425 g_test_add_func("/qgraph/test_cycle", test_cycle);
426 g_test_add_func("/qgraph/test_two_test_same_interface",
427 test_two_test_same_interface);
428 g_test_add_func("/qgraph/test_test_in_path", test_test_in_path);
429 g_test_add_func("/qgraph/test_double_edge", test_double_edge);
430
431 g_test_run();
432 return 0;
433 }
434