* Add some missing gitlab-CI job dependencies

* Re-enable "make check SPEED=slow"
 * Improve the gitlab-pipeline-status script
 * Clean up inclusing of qtest.h headers
 * Improve libqos/qgraph documentation
 * Fix downloading problem in the acceptance tests
 * Remove deprecated target tilegx
 * Add new bsd-user maintainers
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCAAvFiEEJ7iIR+7gJQEY8+q5LtnXdP5wLbUFAmBHTZERHHRodXRoQHJl
 ZGhhdC5jb20ACgkQLtnXdP5wLbW1bA//Xkqv1MXiTllIp9/MaayzrCXE4QI1yosA
 onaEQWBuchw2oO/riyayskD516J5q0dyMlQAWx2tv9N1wFC+F8gUcP/q0zpckqhu
 79DyRj9upDYrCgmGUi+0O9qelv3f7VHB6B1bBZlJzA+W7WskrXYk97dXkezvGDQa
 a+D95upQiOLu2cxvEWTx+Z4Gz1R4NMM/JaudnMkNy/WECLOrEQr/bEgk60dwomO2
 Vdb2t1DLwmjFXXQgBvP5olVk/4vHGcDCMOD3gy8TTt7sNv3VR7re18rUdWnOQcB8
 hm3IRGLYZ/JYTqKutJ4QYpOFA1hUyKOLysi3Wj/jhuzV/n028izpPbeCsuWGZ1Ck
 QmdOdP/g8XZzPWekEEG+pL8gZgVM/HdJAm+Ameiwq2F6ybDXS75EgBzCjFC3p1kF
 KA6UFUD9tw2ZGIjy5vzJToTn4wtku6n9B9sP3nHeVQYbQtSFQhfQwP02NVM66dua
 PLSlIPP09jtmGS/LO9j+aw72bNhMJzpEORQvnoAOsbH8cgTpu6auzvKDg2+cMqGb
 pXBihfvhRvfk3RV8dn2nk929FS6hxybjW3aU9iZAG+Dg0YIPwFOk/w/awgbAjhYe
 bwywmRZSE1mkqm6brE8J1y6SORlcvontv6PLy5NYLe6gGHJex4j8U0zWKW0qDjNr
 hot+/3Mstsw=
 =8JHZ
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/thuth-gitlab/tags/pull-request-2021-03-09' into staging

* Add some missing gitlab-CI job dependencies
* Re-enable "make check SPEED=slow"
* Improve the gitlab-pipeline-status script
* Clean up inclusing of qtest.h headers
* Improve libqos/qgraph documentation
* Fix downloading problem in the acceptance tests
* Remove deprecated target tilegx
* Add new bsd-user maintainers

# gpg: Signature made Tue 09 Mar 2021 10:27:29 GMT
# gpg:                using RSA key 27B88847EEE0250118F3EAB92ED9D774FE702DB5
# gpg:                issuer "thuth@redhat.com"
# gpg: Good signature from "Thomas Huth <th.huth@gmx.de>" [full]
# gpg:                 aka "Thomas Huth <thuth@redhat.com>" [full]
# gpg:                 aka "Thomas Huth <huth@tuxfamily.org>" [full]
# gpg:                 aka "Thomas Huth <th.huth@posteo.de>" [unknown]
# Primary key fingerprint: 27B8 8847 EEE0 2501 18F3  EAB9 2ED9 D774 FE70 2DB5

* remotes/thuth-gitlab/tags/pull-request-2021-03-09:
  bsd-user: Add new maintainers
  Remove deprecated target tilegx
  Acceptance Tests: restore filtering of tests by target arch
  Acceptance Tests: restore downloading of VM images
  docs/devel/qgraph: improve qgraph documentation
  libqos/qgraph: format qgraph comments for sphinx documentation
  scripts/ci/gitlab-pipeline-status: give more info when pipeline not found
  scripts/ci/gitlab-pipeline-status: give more information on failures
  scripts/ci/gitlab-pipeline-status: split utlity function for HTTP GET
  meson: Re-enable the possibility to run "make check SPEED=slow"
  docker: OpenSBI build job depends on OpenSBI container
  docker: EDK2 build job depends on EDK2 container
  docker: Alpine build job depends on Alpine container
  qtest: delete superfluous inclusions of qtest.h

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2021-03-10 17:22:45 +00:00
commit 821e7ed167
64 changed files with 741 additions and 6154 deletions

View file

@ -29,7 +29,6 @@
typedef struct QOSGraphObject QOSGraphObject;
typedef struct QOSGraphNode QOSGraphNode;
typedef struct QOSGraphEdge QOSGraphEdge;
typedef struct QOSGraphNodeOptions QOSGraphNodeOptions;
typedef struct QOSGraphEdgeOptions QOSGraphEdgeOptions;
typedef struct QOSGraphTestOptions QOSGraphTestOptions;
@ -49,340 +48,94 @@ typedef void (*QOSStartFunct) (QOSGraphObject *object);
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 "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 "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=./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 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:
* Edge options to be passed to the contains/consumes \*_args function.
* @arg: optional arg that will be used by dest edge
* @size_arg: @arg size that will be used by dest edge
* @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.
* @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"
* @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
* @edge_name: optional edge to differentiate multiple
* devices with same node name
*/
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
*/
void *arg;
uint32_t size_arg;
const char *extra_device_opts;
const char *before_cmd_line;
const char *after_cmd_line;
const char *edge_name;
};
/**
* struct QOSGraphTestOptions:
* Test options to be passed to the test functions.
* @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.
* @arg: if @before is non-NULL, pass @arg there.
* Otherwise pass it to the test function.
* @before: executed before the test. Used to add
* additional parameters to the command line
* and modify the argument to the test function.
* @subprocess: run the test in a subprocess.
*/
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 */
QOSGraphEdgeOptions edge;
void *arg;
QOSBeforeTest before;
bool subprocess;
};
/**
* struct QOSGraphObject:
* 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.
*
* @get_driver: see @get_device
* @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.
* @free: free the memory associated to the QOSGraphObject and its contained
* children
*/
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;
};
@ -399,24 +152,30 @@ void qos_graph_init(void);
void qos_graph_destroy(void);
/**
* qos_node_destroy(): removes and frees a node from the,
* qos_node_destroy(): removes and frees a node from the
* nodes hash table.
* @key: Name of the node
*/
void qos_node_destroy(void *key);
/**
* qos_edge_destroy(): removes and frees an edge from the,
* qos_edge_destroy(): removes and frees an edge from the
* edges hash table.
* @key: Name of the node
*/
void qos_edge_destroy(void *key);
/**
* qos_add_test(): adds a test node @name to the nodes hash table.
* @name: Name of the test
* @interface: Name of the interface node it consumes
* @test_func: Actual test to perform
* @opts: Facultative options (see %QOSGraphTestOptions)
*
* 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).
* add an optional @opts (see %QOSGraphTestOptions).
*
* For tests, opts->edge.arg and size_arg represent the arg to pass
* to @test_func
@ -428,6 +187,8 @@ void qos_add_test(const char *name, const char *interface,
/**
* qos_node_create_machine(): creates the machine @name and
* adds it to the node hash table.
* @name: Name of the machine
* @function: Machine constructor
*
* This node will be of type QNODE_MACHINE and have @function
* as constructor
@ -438,6 +199,9 @@ 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.
* @name: Name of the machine
* @function: Machine constructor
* @opts: Optional additional command line
*/
void qos_node_create_machine_args(const char *name,
QOSCreateMachineFunc function,
@ -446,6 +210,8 @@ void qos_node_create_machine_args(const char *name,
/**
* qos_node_create_driver(): creates the driver @name and
* adds it to the node hash table.
* @name: Name of the driver
* @function: Driver constructor
*
* This node will be of type QNODE_DRIVER and have @function
* as constructor
@ -453,17 +219,17 @@ void qos_node_create_machine_args(const char *name,
void qos_node_create_driver(const char *name, QOSCreateDriverFunc function);
/**
* Behaves as qos_node_create_driver() with the extension of allowing to
* specify a different node name vs. associated QEMU device name.
* qos_node_create_driver_named(): behaves as qos_node_create_driver() with the
* extension of allowing to specify a different node name vs. associated QEMU
* device name.
* @name: Custom, unique name of the node to be created
* @qemu_name: Actual (official) QEMU driver name the node shall be
* associated with
* @function: Driver constructor
*
* Use this function instead of qos_node_create_driver() if you need to create
* several instances of the same QEMU device. You are free to choose a custom
* node name, however the chosen node name must always be unique.
*
* @param name: custom, unique name of the node to be created
* @param qemu_name: actual (official) QEMU driver name the node shall be
* associated with
* @param function: driver constructor
*/
void qos_node_create_driver_named(const char *name, const char *qemu_name,
QOSCreateDriverFunc function);
@ -472,6 +238,9 @@ void qos_node_create_driver_named(const char *name, const char *qemu_name,
* 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.
* @container: Source node that "contains"
* @contained: Destination node that "is contained"
* @opts: Facultative options (see %QOSGraphEdgeOptions)
*
* The edges will have @container as source and @contained as destination.
*
@ -483,14 +252,17 @@ void qos_node_create_driver_named(const char *name, const char *qemu_name,
* 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"
* 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);
*
* .. code::
*
* 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".
@ -505,6 +277,8 @@ void qos_node_contains(const char *container, const char *contained,
* 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.
* @producer: Source node that "produces"
* @interface: Interface node that "is produced"
*
* This edge will have @producer as source and @interface as destination.
*/
@ -514,6 +288,9 @@ 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.
* @consumer: Node that "consumes"
* @interface: Interface node that "is consumed by"
* @opts: Facultative options (see %QOSGraphEdgeOptions)
*
* This edge will have @interface as source and @consumer as destination.
* It also has the possibility to add an optional @opts
@ -539,7 +316,7 @@ 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.
* @p_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.
@ -551,24 +328,27 @@ void *qos_allocate_objects(QTestState *qts, QGuestAllocator **p_alloc);
/**
* qos_object_destroy(): calls the destructor for @obj
* @obj: A #QOSGraphObject to destroy
*/
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
* @obj: A #QOSGraphObject to destroy
*/
void qos_object_queue_destroy(QOSGraphObject *obj);
/**
* qos_object_start_hw(): calls the start_hw function for @obj
* @obj: A #QOSGraphObject containing the start_hw function
*/
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.
* @node: Machine node to be instantiated
* @qts: A #QTestState that will be referred to by the machine object.
*
* Returns a machine object.
*/
@ -587,8 +367,8 @@ QOSGraphObject *qos_driver_new(QOSGraphNode *node, QOSGraphObject *parent,
QGuestAllocator *alloc, void *arg);
/**
* Just for debugging purpose: prints all currently existing nodes and
* edges to stdout.
* qos_dump_graph(): prints all currently existing nodes and
* edges to stdout. Just for debugging purposes.
*
* All qtests add themselves to the overall qos graph by calling qgraph
* functions that add device nodes and edges between the individual graph