diff options
author | Thomas Huth | 2019-09-10 16:41:20 +0200 |
---|---|---|
committer | Thomas Huth | 2020-01-12 11:42:41 +0100 |
commit | 1cf4323ecd03235984e43a416a42f10c975cf785 (patch) | |
tree | 57ad5475a4cbbbe0088aecf86b682d8e11150b9f /tests/libqos/qgraph.h | |
parent | tests/Makefile: Move qtest-related settings to a separate Makefile.include (diff) | |
download | qemu-1cf4323ecd03235984e43a416a42f10c975cf785.tar.gz qemu-1cf4323ecd03235984e43a416a42f10c975cf785.tar.xz qemu-1cf4323ecd03235984e43a416a42f10c975cf785.zip |
tests/libqos: Move the libqos files under tests/qtest/
The qos stuff belongs to qtest, so move it into that directory, too.
Message-Id: <20191218103059.11729-8-thuth@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Diffstat (limited to 'tests/libqos/qgraph.h')
-rw-r--r-- | tests/libqos/qgraph.h | 574 |
1 files changed, 0 insertions, 574 deletions
diff --git a/tests/libqos/qgraph.h b/tests/libqos/qgraph.h deleted file mode 100644 index 3a25dda4b2..0000000000 --- a/tests/libqos/qgraph.h +++ /dev/null @@ -1,574 +0,0 @@ -/* - * libqos driver framework - * - * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see <http://www.gnu.org/licenses/> - */ - -#ifndef QGRAPH_H -#define QGRAPH_H - -#include <gmodule.h> -#include "qemu/module.h" -#include "malloc.h" - -/* maximum path length */ -#define QOS_PATH_MAX_ELEMENT_SIZE 50 - -typedef struct QOSGraphObject QOSGraphObject; -typedef struct QOSGraphNode QOSGraphNode; -typedef struct QOSGraphEdge QOSGraphEdge; -typedef struct QOSGraphNodeOptions QOSGraphNodeOptions; -typedef struct QOSGraphEdgeOptions QOSGraphEdgeOptions; -typedef struct QOSGraphTestOptions QOSGraphTestOptions; - -/* Constructor for drivers, machines and test */ -typedef void *(*QOSCreateDriverFunc) (void *parent, QGuestAllocator *alloc, - void *addr); -typedef void *(*QOSCreateMachineFunc) (QTestState *qts); -typedef void (*QOSTestFunc) (void *parent, void *arg, QGuestAllocator *alloc); - -/* QOSGraphObject functions */ -typedef void *(*QOSGetDriver) (void *object, const char *interface); -typedef QOSGraphObject *(*QOSGetDevice) (void *object, const char *name); -typedef void (*QOSDestructorFunc) (QOSGraphObject *object); -typedef void (*QOSStartFunct) (QOSGraphObject *object); - -/* Test options functions */ -typedef void *(*QOSBeforeTest) (GString *cmd_line, void *arg); - -/** - * SECTION: qgraph.h - * @title: Qtest Driver Framework - * @short_description: interfaces to organize drivers and tests - * as nodes in a graph - * - * This Qgraph API provides all basic functions to create a graph - * and instantiate nodes representing machines, drivers and tests - * representing their relations with CONSUMES, PRODUCES, and CONTAINS - * edges. - * - * The idea is to have a framework where each test asks for a specific - * driver, and the framework takes care of allocating the proper devices - * required and passing the correct command line arguments to QEMU. - * - * A node can be of four types: - * - QNODE_MACHINE: for example "arm/raspi2" - * - QNODE_DRIVER: for example "generic-sdhci" - * - QNODE_INTERFACE: for example "sdhci" (interface for all "-sdhci" drivers) - * an interface is not explicitly created, it will be auto- - * matically instantiated when a node consumes or produces - * it. - * - QNODE_TEST: for example "sdhci-test", consumes an interface and tests - * the functions provided - * - * Notes for the nodes: - * - QNODE_MACHINE: each machine struct must have a QGuestAllocator and - * implement get_driver to return the allocator passing - * "memory". The function can also return NULL if the - * allocator is not set. - * - QNODE_DRIVER: driver names must be unique, and machines and nodes - * planned to be "consumed" by other nodes must match QEMU - * drivers name, otherwise they won't be discovered - * - * An edge relation between two nodes (drivers or machines) X and Y can be: - * - X CONSUMES Y: Y can be plugged into X - * - X PRODUCES Y: X provides the interface Y - * - X CONTAINS Y: Y is part of X component - * - * Basic framework steps are the following: - * - All nodes and edges are created in their respective - * machine/driver/test files - * - The framework starts QEMU and asks for a list of available devices - * and machines (note that only machines and "consumed" nodes are mapped - * 1:1 with QEMU devices) - * - The framework walks the graph starting from the available machines and - * performs a Depth First Search for tests - * - Once a test is found, the path is walked again and all drivers are - * allocated accordingly and the final interface is passed to the test - * - The test is executed - * - Unused objects are cleaned and the path discovery is continued - * - * Depending on the QEMU binary used, only some drivers/machines will be - * available and only test that are reached by them will be executed. - * - * <example> - * <title>Creating new driver an its interface</title> - * <programlisting> - #include "libqos/qgraph.h" - - struct My_driver { - QOSGraphObject obj; - Node_produced prod; - Node_contained cont; - } - - static void my_destructor(QOSGraphObject *obj) - { - g_free(obj); - } - - static void my_get_driver(void *object, const char *interface) { - My_driver *dev = object; - if (!g_strcmp0(interface, "my_interface")) { - return &dev->prod; - } - abort(); - } - - static void my_get_device(void *object, const char *device) { - My_driver *dev = object; - if (!g_strcmp0(device, "my_driver_contained")) { - return &dev->cont; - } - abort(); - } - - static void *my_driver_constructor(void *node_consumed, - QOSGraphObject *alloc) - { - My_driver dev = g_new(My_driver, 1); - // get the node pointed by the produce edge - dev->obj.get_driver = my_get_driver; - // get the node pointed by the contains - dev->obj.get_device = my_get_device; - // free the object - dev->obj.destructor = my_destructor; - do_something_with_node_consumed(node_consumed); - // set all fields of contained device - init_contained_device(&dev->cont); - return &dev->obj; - } - - static void register_my_driver(void) - { - qos_node_create_driver("my_driver", my_driver_constructor); - // contained drivers don't need a constructor, - // they will be init by the parent. - qos_node_create_driver("my_driver_contained", NULL); - - // For the sake of this example, assume machine x86_64/pc contains - // "other_node". - // This relation, along with the machine and "other_node" creation, - // should be defined in the x86_64_pc-machine.c file. - // "my_driver" will then consume "other_node" - qos_node_contains("my_driver", "my_driver_contained"); - qos_node_produces("my_driver", "my_interface"); - qos_node_consumes("my_driver", "other_node"); - } - * </programlisting> - * </example> - * - * In the above example, all possible types of relations are created: - * node "my_driver" consumes, contains and produces other nodes. - * more specifically: - * x86_64/pc -->contains--> other_node <--consumes-- my_driver - * | - * my_driver_contained <--contains--+ - * | - * my_interface <--produces--+ - * - * or inverting the consumes edge in consumed_by: - * - * x86_64/pc -->contains--> other_node --consumed_by--> my_driver - * | - * my_driver_contained <--contains--+ - * | - * my_interface <--produces--+ - * - * <example> - * <title>Creating new test</title> - * <programlisting> - * #include "libqos/qgraph.h" - * - * static void my_test_function(void *obj, void *data) - * { - * Node_produced *interface_to_test = obj; - * // test interface_to_test - * } - * - * static void register_my_test(void) - * { - * qos_add_test("my_interface", "my_test", my_test_function); - * } - * - * libqos_init(register_my_test); - * - * </programlisting> - * </example> - * - * Here a new test is created, consuming "my_interface" node - * and creating a valid path from a machine to a test. - * Final graph will be like this: - * x86_64/pc -->contains--> other_node <--consumes-- my_driver - * | - * my_driver_contained <--contains--+ - * | - * my_test --consumes--> my_interface <--produces--+ - * - * or inverting the consumes edge in consumed_by: - * - * x86_64/pc -->contains--> other_node --consumed_by--> my_driver - * | - * my_driver_contained <--contains--+ - * | - * my_test <--consumed_by-- my_interface <--produces--+ - * - * Assuming there the binary is - * QTEST_QEMU_BINARY=x86_64-softmmu/qemu-system-x86_64 - * a valid test path will be: - * "/x86_64/pc/other_node/my_driver/my_interface/my_test". - * - * Additional examples are also in libqos/test-qgraph.c - * - * Command line: - * Command line is built by using node names and optional arguments - * passed by the user when building the edges. - * - * There are three types of command line arguments: - * - in node : created from the node name. For example, machines will - * have "-M <machine>" to its command line, while devices - * "-device <device>". It is automatically done by the - * framework. - * - after node : added as additional argument to the node name. - * This argument is added optionally when creating edges, - * by setting the parameter @after_cmd_line and - * @extra_edge_opts in #QOSGraphEdgeOptions. - * The framework automatically adds - * a comma before @extra_edge_opts, - * because it is going to add attributes - * after the destination node pointed by - * the edge containing these options, and automatically - * adds a space before @after_cmd_line, because it - * adds an additional device, not an attribute. - * - before node : added as additional argument to the node name. - * This argument is added optionally when creating edges, - * by setting the parameter @before_cmd_line in - * #QOSGraphEdgeOptions. This attribute - * is going to add attributes before the destination node - * pointed by the edge containing these options. It is - * helpful to commands that are not node-representable, - * such as "-fdsev" or "-netdev". - * - * While adding command line in edges is always used, not all nodes names are - * used in every path walk: this is because the contained or produced ones - * are already added by QEMU, so only nodes that "consumes" will be used to - * build the command line. Also, nodes that will have { "abstract" : true } - * as QMP attribute will loose their command line, since they are not proper - * devices to be added in QEMU. - * - * Example: - * - QOSGraphEdgeOptions opts = { - .arg = NULL, - .size_arg = 0, - .after_cmd_line = "-device other", - .before_cmd_line = "-netdev something", - .extra_edge_opts = "addr=04.0", - }; - QOSGraphNode * node = qos_node_create_driver("my_node", constructor); - qos_node_consumes_args("my_node", "interface", &opts); - * - * Will produce the following command line: - * "-netdev something -device my_node,addr=04.0 -device other" - */ - -/** - * Edge options to be passed to the contains/consumes *_args function. - */ -struct QOSGraphEdgeOptions { - void *arg; /* - * optional arg that will be used by - * dest edge - */ - uint32_t size_arg; /* - * optional arg size that will be used by - * dest edge - */ - const char *extra_device_opts;/* - *optional additional command line for dest - * edge, used to add additional attributes - * *after* the node command line, the - * framework automatically prepends "," - * to this argument. - */ - const char *before_cmd_line; /* - * optional additional command line for dest - * edge, used to add additional attributes - * *before* the node command line, usually - * other non-node represented commands, - * like "-fdsev synt" - */ - const char *after_cmd_line; /* - * optional extra command line to be added - * after the device command. This option - * is used to add other devices - * command line that depend on current node. - * Automatically prepends " " to this - * argument - */ - const char *edge_name; /* - * optional edge to differentiate multiple - * devices with same node name - */ -}; - -/** - * Test options to be passed to the test functions. - */ -struct QOSGraphTestOptions { - QOSGraphEdgeOptions edge; /* edge arguments that will be used by test. - * Note that test *does not* use edge_name, - * and uses instead arg and size_arg as - * data arg for its test function. - */ - void *arg; /* passed to the .before function, or to the - * test function if there is no .before - * function - */ - QOSBeforeTest before; /* executed before the test. Can add - * additional parameters to the command line - * and modify the argument to the test function. - */ - bool subprocess; /* run the test in a subprocess */ -}; - -/** - * Each driver, test or machine of this framework will have a - * QOSGraphObject as first field. - * - * This set of functions offered by QOSGraphObject are executed - * in different stages of the framework: - * - get_driver / get_device : Once a machine-to-test path has been - * found, the framework traverses it again and allocates all the - * nodes, using the provided constructor. To satisfy their relations, - * i.e. for produces or contains, where a struct constructor needs - * an external parameter represented by the previous node, - * the framework will call get_device (for contains) or - * get_driver (for produces), depending on the edge type, passing - * them the name of the next node to be taken and getting from them - * the corresponding pointer to the actual structure of the next node to - * be used in the path. - * - * - start_hw: This function is executed after all the path objects - * have been allocated, but before the test is run. It starts the hw, setting - * the initial configurations (*_device_enable) and making it ready for the - * test. - * - * - destructor: Opposite to the node constructor, destroys the object. - * This function is called after the test has been executed, and performs - * a complete cleanup of each node allocated field. In case no constructor - * is provided, no destructor will be called. - * - */ -struct QOSGraphObject { - /* for produces edges, returns void * */ - QOSGetDriver get_driver; - /* for contains edges, returns a QOSGraphObject * */ - QOSGetDevice get_device; - /* start the hw, get ready for the test */ - QOSStartFunct start_hw; - /* destroy this QOSGraphObject */ - QOSDestructorFunc destructor; - /* free the memory associated to the QOSGraphObject and its contained - * children */ - GDestroyNotify free; -}; - -/** - * qos_graph_init(): initialize the framework, creates two hash - * tables: one for the nodes and another for the edges. - */ -void qos_graph_init(void); - -/** - * qos_graph_destroy(): deallocates all the hash tables, - * freeing all nodes and edges. - */ -void qos_graph_destroy(void); - -/** - * qos_node_destroy(): removes and frees a node from the, - * nodes hash table. - */ -void qos_node_destroy(void *key); - -/** - * qos_edge_destroy(): removes and frees an edge from the, - * edges hash table. - */ -void qos_edge_destroy(void *key); - -/** - * qos_add_test(): adds a test node @name to the nodes hash table. - * - * The test will consume a @interface node, and once the - * graph walking algorithm has found it, the @test_func will be - * executed. It also has the possibility to - * add an optional @opts (see %QOSGraphNodeOptions). - * - * For tests, opts->edge.arg and size_arg represent the arg to pass - * to @test_func - */ -void qos_add_test(const char *name, const char *interface, - QOSTestFunc test_func, - QOSGraphTestOptions *opts); - -/** - * qos_node_create_machine(): creates the machine @name and - * adds it to the node hash table. - * - * This node will be of type QNODE_MACHINE and have @function - * as constructor - */ -void qos_node_create_machine(const char *name, QOSCreateMachineFunc function); - -/** - * qos_node_create_machine_args(): same as qos_node_create_machine, - * but with the possibility to add an optional ", @opts" after -M machine - * command line. - */ -void qos_node_create_machine_args(const char *name, - QOSCreateMachineFunc function, - const char *opts); - -/** - * qos_node_create_driver(): creates the driver @name and - * adds it to the node hash table. - * - * This node will be of type QNODE_DRIVER and have @function - * as constructor - */ -void qos_node_create_driver(const char *name, QOSCreateDriverFunc function); - -/** - * qos_node_contains(): creates one or more edges of type QEDGE_CONTAINS - * and adds them to the edge list mapped to @container in the - * edge hash table. - * - * The edges will have @container as source and @contained as destination. - * - * If @opts is NULL, a single edge will be added with no options. - * If @opts is non-NULL, the arguments after @contained represent a - * NULL-terminated list of %QOSGraphEdgeOptions structs, and an - * edge will be added for each of them. - * - * This function can be useful when there are multiple devices - * with the same node name contained in a machine/other node - * - * For example, if "arm/raspi2" contains 2 "generic-sdhci" - * devices, the right commands will be: - * qos_node_create_machine("arm/raspi2"); - * qos_node_create_driver("generic-sdhci", constructor); - * //assume rest of the fields are set NULL - * QOSGraphEdgeOptions op1 = { .edge_name = "emmc" }; - * QOSGraphEdgeOptions op2 = { .edge_name = "sdcard" }; - * qos_node_contains("arm/raspi2", "generic-sdhci", &op1, &op2, NULL); - * - * Of course this also requires that the @container's get_device function - * should implement a case for "emmc" and "sdcard". - * - * For contains, op1.arg and op1.size_arg represent the arg to pass - * to @contained constructor to properly initialize it. - */ -void qos_node_contains(const char *container, const char *contained, - QOSGraphEdgeOptions *opts, ...); - -/** - * qos_node_produces(): creates an edge of type QEDGE_PRODUCES and - * adds it to the edge list mapped to @producer in the - * edge hash table. - * - * This edge will have @producer as source and @interface as destination. - */ -void qos_node_produces(const char *producer, const char *interface); - -/** - * qos_node_consumes(): creates an edge of type QEDGE_CONSUMED_BY and - * adds it to the edge list mapped to @interface in the - * edge hash table. - * - * This edge will have @interface as source and @consumer as destination. - * It also has the possibility to add an optional @opts - * (see %QOSGraphEdgeOptions) - */ -void qos_node_consumes(const char *consumer, const char *interface, - QOSGraphEdgeOptions *opts); - -/** - * qos_invalidate_command_line(): invalidates current command line, so that - * qgraph framework cannot try to cache the current command line and - * forces QEMU to restart. - */ -void qos_invalidate_command_line(void); - -/** - * qos_get_current_command_line(): return the command line required by the - * machine and driver objects. This is the same string that was passed to - * the test's "before" callback, if any. - */ -const char *qos_get_current_command_line(void); - -/** - * qos_allocate_objects(): - * @qts: The #QTestState that will be referred to by the machine object. - * @alloc: Where to store the allocator for the machine object, or %NULL. - * - * Allocate driver objects for the current test - * path, but relative to the QTestState @qts. - * - * Returns a test object just like the one that was passed to - * the test function, but relative to @qts. - */ -void *qos_allocate_objects(QTestState *qts, QGuestAllocator **p_alloc); - -/** - * qos_object_destroy(): calls the destructor for @obj - */ -void qos_object_destroy(QOSGraphObject *obj); - -/** - * qos_object_queue_destroy(): queue the destructor for @obj so that it is - * called at the end of the test - */ -void qos_object_queue_destroy(QOSGraphObject *obj); - -/** - * qos_object_start_hw(): calls the start_hw function for @obj - */ -void qos_object_start_hw(QOSGraphObject *obj); - -/** - * qos_machine_new(): instantiate a new machine node - * @node: A machine node to be instantiated - * @qts: The #QTestState that will be referred to by the machine object. - * - * Returns a machine object. - */ -QOSGraphObject *qos_machine_new(QOSGraphNode *node, QTestState *qts); - -/** - * qos_machine_new(): instantiate a new driver node - * @node: A driver node to be instantiated - * @parent: A #QOSGraphObject to be consumed by the new driver node - * @alloc: An allocator to be used by the new driver node. - * @arg: The argument for the consumed-by edge to @node. - * - * Calls the constructor for the driver object. - */ -QOSGraphObject *qos_driver_new(QOSGraphNode *node, QOSGraphObject *parent, - QGuestAllocator *alloc, void *arg); - - -#endif |