qemu/tests/qtest/libqos/qos_external.c
<<
>>
Prefs
   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 <getopt.h>
  21#include "libqtest.h"
  22#include "qapi/qmp/qdict.h"
  23#include "qapi/qmp/qbool.h"
  24#include "qapi/qmp/qstring.h"
  25#include "qemu/module.h"
  26#include "qapi/qmp/qlist.h"
  27#include "malloc.h"
  28#include "qgraph.h"
  29#include "qgraph_internal.h"
  30#include "qos_external.h"
  31
  32static void machine_apply_to_node(const char *name)
  33{
  34    char *machine_name = g_strconcat(qtest_get_arch(), "/", name, NULL);
  35
  36    qos_graph_node_set_availability(machine_name, true);
  37    g_free(machine_name);
  38}
  39
  40void machines_apply_to_node(MachineInfoList *mach_info)
  41{
  42    MachineInfoList *tail;
  43
  44    for (tail = mach_info; tail; tail = tail->next) {
  45        machine_apply_to_node(tail->value->name);
  46        if (tail->value->alias) {
  47            machine_apply_to_node(tail->value->alias);
  48        }
  49    }
  50}
  51
  52static void type_apply_to_node(const char *name, bool is_abstract)
  53{
  54    qos_graph_node_set_availability(name, true);
  55    if (is_abstract) {
  56        qos_delete_cmd_line(name);
  57    }
  58}
  59
  60void types_apply_to_node(ObjectTypeInfoList *type_info)
  61{
  62    ObjectTypeInfoList *tail;
  63
  64    for (tail = type_info; tail; tail = tail->next) {
  65        type_apply_to_node(tail->value->name, tail->value->abstract);
  66    }
  67}
  68
  69static QGuestAllocator *get_machine_allocator(QOSGraphObject *obj)
  70{
  71    return obj->get_driver(obj, "memory");
  72}
  73
  74/**
  75 * allocate_objects(): given an array of nodes @arg,
  76 * walks the path invoking all constructors and
  77 * passing the corresponding parameter in order to
  78 * continue the objects allocation.
  79 * Once the test is reached, return the object it consumes.
  80 *
  81 * Since the machine and QEDGE_CONSUMED_BY nodes allocate
  82 * memory in the constructor, g_test_queue_destroy is used so
  83 * that after execution they can be safely free'd.  (The test's
  84 * ->before callback is also welcome to use g_test_queue_destroy).
  85 *
  86 * Note: as specified in walk_path() too, @arg is an array of
  87 * char *, where arg[0] is a pointer to the command line
  88 * string that will be used to properly start QEMU when executing
  89 * the test, and the remaining elements represent the actual objects
  90 * that will be allocated.
  91 */
  92void *allocate_objects(QTestState *qts, char **path, QGuestAllocator **p_alloc)
  93{
  94    int current = 0;
  95    QGuestAllocator *alloc;
  96    QOSGraphObject *parent = NULL;
  97    QOSGraphEdge *edge;
  98    QOSGraphNode *node;
  99    void *edge_arg;
 100    void *obj;
 101
 102    node = qos_graph_get_node(path[current]);
 103    g_assert(node->type == QNODE_MACHINE);
 104
 105    obj = qos_machine_new(node, qts);
 106    qos_object_queue_destroy(obj);
 107
 108    alloc = get_machine_allocator(obj);
 109    if (p_alloc) {
 110        *p_alloc = alloc;
 111    }
 112
 113    for (;;) {
 114        if (node->type != QNODE_INTERFACE) {
 115            qos_object_start_hw(obj);
 116            parent = obj;
 117        }
 118
 119        /* follow edge and get object for next node constructor */
 120        current++;
 121        edge = qos_graph_get_edge(path[current - 1], path[current]);
 122        node = qos_graph_get_node(path[current]);
 123
 124        if (node->type == QNODE_TEST) {
 125            g_assert(qos_graph_edge_get_type(edge) == QEDGE_CONSUMED_BY);
 126            return obj;
 127        }
 128
 129        switch (qos_graph_edge_get_type(edge)) {
 130        case QEDGE_PRODUCES:
 131            obj = parent->get_driver(parent, path[current]);
 132            break;
 133
 134        case QEDGE_CONSUMED_BY:
 135            edge_arg = qos_graph_edge_get_arg(edge);
 136            obj = qos_driver_new(node, obj, alloc, edge_arg);
 137            qos_object_queue_destroy(obj);
 138            break;
 139
 140        case QEDGE_CONTAINS:
 141            obj = parent->get_device(parent, path[current]);
 142            break;
 143        }
 144    }
 145}
 146
 147