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 } 48 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 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 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 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 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 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 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 142 static void count_each_test(QOSGraphNode *path, int len) 143 { 144 npath++; 145 } 146 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 156 static void init_nop(void) 157 { 158 qos_graph_init(); 159 qos_graph_destroy(); 160 } 161 162 static void test_machine(void) 163 { 164 qos_graph_init(); 165 check_machine(MACHINE_PC); 166 qos_graph_destroy(); 167 } 168 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 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 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 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 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 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 226 static void test_driver(void) 227 { 228 qos_graph_init(); 229 check_driver(I440FX); 230 qos_graph_destroy(); 231 } 232 233 static void test_test(void) 234 { 235 qos_graph_init(); 236 check_test(REGISTER_TEST, SDHCI); 237 qos_graph_destroy(); 238 } 239 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 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 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 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 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 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 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 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 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 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 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 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 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 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