xref: /qemu/tests/unit/test-qgraph.c (revision 8a2b516ba2855c4530388051de2b8d17bc780ea8)
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