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 35 static void *machinefunct(QTestState *qts) 36 { 37 return NULL; 38 } 39 40 static void *driverfunct(void *obj, QGuestAllocator *machine, void *arg) 41 { 42 return NULL; 43 } 44 45 static void testfunct(void *obj, void *arg, QGuestAllocator *alloc) 46 { 47 return; 48 } 49 50 static void check_interface(const char *interface) 51 { 52 g_assert_cmpint(qos_graph_has_machine(interface), ==, FALSE); 53 g_assert_nonnull(qos_graph_get_node(interface)); 54 g_assert_cmpint(qos_graph_has_node(interface), ==, TRUE); 55 g_assert_cmpint(qos_graph_get_node_type(interface), ==, QNODE_INTERFACE); 56 qos_graph_node_set_availability(interface, TRUE); 57 g_assert_cmpint(qos_graph_get_node_availability(interface), ==, TRUE); 58 } 59 60 static void check_machine(const char *machine) 61 { 62 qos_node_create_machine(machine, machinefunct); 63 g_assert_nonnull(qos_graph_get_machine(machine)); 64 g_assert_cmpint(qos_graph_has_machine(machine), ==, TRUE); 65 g_assert_nonnull(qos_graph_get_node(machine)); 66 g_assert_cmpint(qos_graph_get_node_availability(machine), ==, FALSE); 67 qos_graph_node_set_availability(machine, TRUE); 68 g_assert_cmpint(qos_graph_get_node_availability(machine), ==, TRUE); 69 g_assert_cmpint(qos_graph_has_node(machine), ==, TRUE); 70 g_assert_cmpint(qos_graph_get_node_type(machine), ==, QNODE_MACHINE); 71 } 72 73 static void check_contains(const char *machine, const char *driver) 74 { 75 QOSGraphEdge *edge; 76 qos_node_contains(machine, driver, NULL); 77 78 edge = qos_graph_get_edge(machine, driver); 79 g_assert_nonnull(edge); 80 g_assert_cmpint(qos_graph_edge_get_type(edge), ==, QEDGE_CONTAINS); 81 g_assert_cmpint(qos_graph_has_edge(machine, driver), ==, TRUE); 82 } 83 84 static void check_produces(const char *machine, const char *interface) 85 { 86 QOSGraphEdge *edge; 87 88 qos_node_produces(machine, interface); 89 check_interface(interface); 90 edge = qos_graph_get_edge(machine, interface); 91 g_assert_nonnull(edge); 92 g_assert_cmpint(qos_graph_edge_get_type(edge), ==, 93 QEDGE_PRODUCES); 94 g_assert_cmpint(qos_graph_has_edge(machine, interface), ==, TRUE); 95 } 96 97 static void check_consumes(const char *driver, const char *interface) 98 { 99 QOSGraphEdge *edge; 100 101 qos_node_consumes(driver, interface, NULL); 102 check_interface(interface); 103 edge = qos_graph_get_edge(interface, driver); 104 g_assert_nonnull(edge); 105 g_assert_cmpint(qos_graph_edge_get_type(edge), ==, QEDGE_CONSUMED_BY); 106 g_assert_cmpint(qos_graph_has_edge(interface, driver), ==, TRUE); 107 } 108 109 static void check_driver(const char *driver) 110 { 111 qos_node_create_driver(driver, driverfunct); 112 g_assert_cmpint(qos_graph_has_machine(driver), ==, FALSE); 113 g_assert_nonnull(qos_graph_get_node(driver)); 114 g_assert_cmpint(qos_graph_has_node(driver), ==, TRUE); 115 g_assert_cmpint(qos_graph_get_node_type(driver), ==, QNODE_DRIVER); 116 g_assert_cmpint(qos_graph_get_node_availability(driver), ==, FALSE); 117 qos_graph_node_set_availability(driver, TRUE); 118 g_assert_cmpint(qos_graph_get_node_availability(driver), ==, TRUE); 119 } 120 121 static void check_test(const char *test, const char *interface) 122 { 123 QOSGraphEdge *edge; 124 char *full_name = g_strdup_printf("%s-tests/%s", interface, test); 125 126 qos_add_test(test, interface, testfunct, NULL); 127 g_assert_cmpint(qos_graph_has_machine(test), ==, FALSE); 128 g_assert_cmpint(qos_graph_has_machine(full_name), ==, FALSE); 129 g_assert_nonnull(qos_graph_get_node(full_name)); 130 g_assert_cmpint(qos_graph_has_node(full_name), ==, TRUE); 131 g_assert_cmpint(qos_graph_get_node_type(full_name), ==, QNODE_TEST); 132 edge = qos_graph_get_edge(interface, full_name); 133 g_assert_nonnull(edge); 134 g_assert_cmpint(qos_graph_edge_get_type(edge), ==, 135 QEDGE_CONSUMED_BY); 136 g_assert_cmpint(qos_graph_has_edge(interface, full_name), ==, TRUE); 137 g_assert_cmpint(qos_graph_get_node_availability(full_name), ==, TRUE); 138 qos_graph_node_set_availability(full_name, FALSE); 139 g_assert_cmpint(qos_graph_get_node_availability(full_name), ==, FALSE); 140 g_free(full_name); 141 } 142 143 static void count_each_test(QOSGraphNode *path, int len) 144 { 145 npath++; 146 } 147 148 static void check_leaf_discovered(int n) 149 { 150 npath = 0; 151 qos_graph_foreach_test_path(count_each_test); 152 g_assert_cmpint(n, ==, npath); 153 } 154 155 /* G_Test functions */ 156 157 static void init_nop(void) 158 { 159 qos_graph_init(); 160 qos_graph_destroy(); 161 } 162 163 static void test_machine(void) 164 { 165 qos_graph_init(); 166 check_machine(MACHINE_PC); 167 qos_graph_destroy(); 168 } 169 170 static void test_contains(void) 171 { 172 qos_graph_init(); 173 check_contains(MACHINE_PC, I440FX); 174 g_assert_null(qos_graph_get_machine(MACHINE_PC)); 175 g_assert_null(qos_graph_get_machine(I440FX)); 176 g_assert_null(qos_graph_get_node(MACHINE_PC)); 177 g_assert_null(qos_graph_get_node(I440FX)); 178 qos_graph_destroy(); 179 } 180 181 static void test_multiple_contains(void) 182 { 183 qos_graph_init(); 184 check_contains(MACHINE_PC, I440FX); 185 check_contains(MACHINE_PC, PCIBUS_PC); 186 qos_graph_destroy(); 187 } 188 189 static void test_produces(void) 190 { 191 qos_graph_init(); 192 check_produces(MACHINE_PC, I440FX); 193 g_assert_null(qos_graph_get_machine(MACHINE_PC)); 194 g_assert_null(qos_graph_get_machine(I440FX)); 195 g_assert_null(qos_graph_get_node(MACHINE_PC)); 196 g_assert_nonnull(qos_graph_get_node(I440FX)); 197 qos_graph_destroy(); 198 } 199 200 static void test_multiple_produces(void) 201 { 202 qos_graph_init(); 203 check_produces(MACHINE_PC, I440FX); 204 check_produces(MACHINE_PC, PCIBUS_PC); 205 qos_graph_destroy(); 206 } 207 208 static void test_consumes(void) 209 { 210 qos_graph_init(); 211 check_consumes(I440FX, SDHCI); 212 g_assert_null(qos_graph_get_machine(I440FX)); 213 g_assert_null(qos_graph_get_machine(SDHCI)); 214 g_assert_null(qos_graph_get_node(I440FX)); 215 g_assert_nonnull(qos_graph_get_node(SDHCI)); 216 qos_graph_destroy(); 217 } 218 219 static void test_multiple_consumes(void) 220 { 221 qos_graph_init(); 222 check_consumes(I440FX, SDHCI); 223 check_consumes(PCIBUS_PC, SDHCI); 224 qos_graph_destroy(); 225 } 226 227 static void test_driver(void) 228 { 229 qos_graph_init(); 230 check_driver(I440FX); 231 qos_graph_destroy(); 232 } 233 234 static void test_test(void) 235 { 236 qos_graph_init(); 237 check_test(REGISTER_TEST, SDHCI); 238 qos_graph_destroy(); 239 } 240 241 static void test_machine_contains_driver(void) 242 { 243 qos_graph_init(); 244 check_machine(MACHINE_PC); 245 check_driver(I440FX); 246 check_contains(MACHINE_PC, I440FX); 247 qos_graph_destroy(); 248 } 249 250 static void test_driver_contains_driver(void) 251 { 252 qos_graph_init(); 253 check_driver(PCIBUS_PC); 254 check_driver(I440FX); 255 check_contains(PCIBUS_PC, I440FX); 256 qos_graph_destroy(); 257 } 258 259 static void test_machine_produces_interface(void) 260 { 261 qos_graph_init(); 262 check_machine(MACHINE_PC); 263 check_produces(MACHINE_PC, SDHCI); 264 qos_graph_destroy(); 265 } 266 267 static void test_driver_produces_interface(void) 268 { 269 qos_graph_init(); 270 check_driver(I440FX); 271 check_produces(I440FX, SDHCI); 272 qos_graph_destroy(); 273 } 274 275 static void test_machine_consumes_interface(void) 276 { 277 qos_graph_init(); 278 check_machine(MACHINE_PC); 279 check_consumes(MACHINE_PC, SDHCI); 280 qos_graph_destroy(); 281 } 282 283 static void test_driver_consumes_interface(void) 284 { 285 qos_graph_init(); 286 check_driver(I440FX); 287 check_consumes(I440FX, SDHCI); 288 qos_graph_destroy(); 289 } 290 291 static void test_test_consumes_interface(void) 292 { 293 qos_graph_init(); 294 check_test(REGISTER_TEST, SDHCI); 295 qos_graph_destroy(); 296 } 297 298 static void test_full_sample(void) 299 { 300 qos_graph_init(); 301 check_machine(MACHINE_PC); 302 check_contains(MACHINE_PC, I440FX); 303 check_driver(I440FX); 304 check_driver(PCIBUS_PC); 305 check_contains(I440FX, PCIBUS_PC); 306 check_produces(PCIBUS_PC, PCIBUS); 307 check_driver(SDHCI_PCI); 308 qos_node_consumes(SDHCI_PCI, PCIBUS, NULL); 309 check_produces(SDHCI_PCI, SDHCI); 310 check_driver(SDHCI_MM); 311 check_produces(SDHCI_MM, SDHCI); 312 qos_add_test(REGISTER_TEST, SDHCI, testfunct, NULL); 313 check_leaf_discovered(1); 314 qos_print_graph(); 315 qos_graph_destroy(); 316 } 317 318 static void test_full_sample_raspi(void) 319 { 320 qos_graph_init(); 321 check_machine(MACHINE_PC); 322 check_contains(MACHINE_PC, I440FX); 323 check_driver(I440FX); 324 check_driver(PCIBUS_PC); 325 check_contains(I440FX, PCIBUS_PC); 326 check_produces(PCIBUS_PC, PCIBUS); 327 check_driver(SDHCI_PCI); 328 qos_node_consumes(SDHCI_PCI, PCIBUS, NULL); 329 check_produces(SDHCI_PCI, SDHCI); 330 check_machine(MACHINE_RASPI2); 331 check_contains(MACHINE_RASPI2, SDHCI_MM); 332 check_driver(SDHCI_MM); 333 check_produces(SDHCI_MM, SDHCI); 334 qos_add_test(REGISTER_TEST, SDHCI, testfunct, NULL); 335 qos_print_graph(); 336 check_leaf_discovered(2); 337 qos_graph_destroy(); 338 } 339 340 static void test_cycle(void) 341 { 342 qos_graph_init(); 343 check_machine(MACHINE_RASPI2); 344 check_driver("B"); 345 check_driver("C"); 346 check_driver("D"); 347 check_contains(MACHINE_RASPI2, "B"); 348 check_contains("B", "C"); 349 check_contains("C", "D"); 350 check_contains("D", MACHINE_RASPI2); 351 check_leaf_discovered(0); 352 qos_print_graph(); 353 qos_graph_destroy(); 354 } 355 356 static void test_two_test_same_interface(void) 357 { 358 qos_graph_init(); 359 check_machine(MACHINE_RASPI2); 360 check_produces(MACHINE_RASPI2, "B"); 361 qos_add_test("C", "B", testfunct, NULL); 362 qos_add_test("D", "B", testfunct, NULL); 363 check_contains(MACHINE_RASPI2, "B"); 364 check_leaf_discovered(4); 365 qos_print_graph(); 366 qos_graph_destroy(); 367 } 368 369 static void test_test_in_path(void) 370 { 371 qos_graph_init(); 372 check_machine(MACHINE_RASPI2); 373 check_produces(MACHINE_RASPI2, "B"); 374 qos_add_test("C", "B", testfunct, NULL); 375 check_driver("D"); 376 check_consumes("D", "B"); 377 check_produces("D", "E"); 378 qos_add_test("F", "E", testfunct, NULL); 379 check_leaf_discovered(2); 380 qos_print_graph(); 381 qos_graph_destroy(); 382 } 383 384 static void test_double_edge(void) 385 { 386 qos_graph_init(); 387 check_machine(MACHINE_RASPI2); 388 check_produces("B", "C"); 389 qos_node_consumes("C", "B", NULL); 390 qos_add_test("D", "C", testfunct, NULL); 391 check_contains(MACHINE_RASPI2, "B"); 392 qos_print_graph(); 393 qos_graph_destroy(); 394 } 395 396 int main(int argc, char **argv) 397 { 398 g_test_init(&argc, &argv, NULL); 399 g_test_add_func("/qgraph/init_nop", init_nop); 400 g_test_add_func("/qgraph/test_machine", test_machine); 401 g_test_add_func("/qgraph/test_contains", test_contains); 402 g_test_add_func("/qgraph/test_multiple_contains", test_multiple_contains); 403 g_test_add_func("/qgraph/test_produces", test_produces); 404 g_test_add_func("/qgraph/test_multiple_produces", test_multiple_produces); 405 g_test_add_func("/qgraph/test_consumes", test_consumes); 406 g_test_add_func("/qgraph/test_multiple_consumes", 407 test_multiple_consumes); 408 g_test_add_func("/qgraph/test_driver", test_driver); 409 g_test_add_func("/qgraph/test_test", test_test); 410 g_test_add_func("/qgraph/test_machine_contains_driver", 411 test_machine_contains_driver); 412 g_test_add_func("/qgraph/test_driver_contains_driver", 413 test_driver_contains_driver); 414 g_test_add_func("/qgraph/test_machine_produces_interface", 415 test_machine_produces_interface); 416 g_test_add_func("/qgraph/test_driver_produces_interface", 417 test_driver_produces_interface); 418 g_test_add_func("/qgraph/test_machine_consumes_interface", 419 test_machine_consumes_interface); 420 g_test_add_func("/qgraph/test_driver_consumes_interface", 421 test_driver_consumes_interface); 422 g_test_add_func("/qgraph/test_test_consumes_interface", 423 test_test_consumes_interface); 424 g_test_add_func("/qgraph/test_full_sample", test_full_sample); 425 g_test_add_func("/qgraph/test_full_sample_raspi", test_full_sample_raspi); 426 g_test_add_func("/qgraph/test_cycle", test_cycle); 427 g_test_add_func("/qgraph/test_two_test_same_interface", 428 test_two_test_same_interface); 429 g_test_add_func("/qgraph/test_test_in_path", test_test_in_path); 430 g_test_add_func("/qgraph/test_double_edge", test_double_edge); 431 432 g_test_run(); 433 return 0; 434 } 435