cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

test-io-task.c (6503B)


      1/*
      2 * QEMU I/O task tests
      3 *
      4 * Copyright (c) 2015 Red Hat, Inc.
      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 as published by the Free Software Foundation; either
      9 * version 2.1 of the License, or (at your option) any later version.
     10 *
     11 * This library is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 * Lesser General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU Lesser General Public
     17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
     18 *
     19 */
     20
     21#include "qemu/osdep.h"
     22
     23#include "qom/object.h"
     24#include "io/task.h"
     25#include "qapi/error.h"
     26#include "qemu/module.h"
     27
     28#define TYPE_DUMMY "qemu:dummy"
     29
     30typedef struct DummyObject DummyObject;
     31typedef struct DummyObjectClass DummyObjectClass;
     32
     33struct DummyObject {
     34    Object parent;
     35};
     36
     37struct DummyObjectClass {
     38    ObjectClass parent;
     39};
     40
     41static const TypeInfo dummy_info = {
     42    .parent = TYPE_OBJECT,
     43    .name = TYPE_DUMMY,
     44    .instance_size = sizeof(DummyObject),
     45    .class_size = sizeof(DummyObjectClass),
     46};
     47
     48struct TestTaskData {
     49    Object *source;
     50    Error *err;
     51    bool freed;
     52};
     53
     54
     55static void task_callback(QIOTask *task,
     56                          gpointer opaque)
     57{
     58    struct TestTaskData *data = opaque;
     59
     60    data->source = qio_task_get_source(task);
     61    qio_task_propagate_error(task, &data->err);
     62}
     63
     64
     65static void test_task_complete(void)
     66{
     67    QIOTask *task;
     68    Object *obj = object_new(TYPE_DUMMY);
     69    Object *src;
     70    struct TestTaskData data = { NULL, NULL, false };
     71
     72    task = qio_task_new(obj, task_callback, &data, NULL);
     73    src = qio_task_get_source(task);
     74
     75    qio_task_complete(task);
     76
     77    g_assert(obj == src);
     78
     79    object_unref(obj);
     80
     81    g_assert(data.source == obj);
     82    g_assert(data.err == NULL);
     83    g_assert(data.freed == false);
     84}
     85
     86
     87static void task_data_free(gpointer opaque)
     88{
     89    struct TestTaskData *data = opaque;
     90
     91    data->freed = true;
     92}
     93
     94
     95static void test_task_data_free(void)
     96{
     97    QIOTask *task;
     98    Object *obj = object_new(TYPE_DUMMY);
     99    struct TestTaskData data = { NULL, NULL, false };
    100
    101    task = qio_task_new(obj, task_callback, &data, task_data_free);
    102
    103    qio_task_complete(task);
    104
    105    object_unref(obj);
    106
    107    g_assert(data.source == obj);
    108    g_assert(data.err == NULL);
    109    g_assert(data.freed == true);
    110}
    111
    112
    113static void test_task_failure(void)
    114{
    115    QIOTask *task;
    116    Object *obj = object_new(TYPE_DUMMY);
    117    struct TestTaskData data = { NULL, NULL, false };
    118    Error *err = NULL;
    119
    120    task = qio_task_new(obj, task_callback, &data, NULL);
    121
    122    error_setg(&err, "Some error");
    123
    124    qio_task_set_error(task, err);
    125    qio_task_complete(task);
    126
    127    object_unref(obj);
    128
    129    g_assert(data.source == obj);
    130    g_assert(data.err == err);
    131    g_assert(data.freed == false);
    132    error_free(data.err);
    133}
    134
    135
    136struct TestThreadWorkerData {
    137    Object *source;
    138    Error *err;
    139    bool fail;
    140    GThread *worker;
    141    GThread *complete;
    142    GMainLoop *loop;
    143};
    144
    145static void test_task_thread_worker(QIOTask *task,
    146                                    gpointer opaque)
    147{
    148    struct TestThreadWorkerData *data = opaque;
    149
    150    data->worker = g_thread_self();
    151
    152    if (data->fail) {
    153        Error *err = NULL;
    154        error_setg(&err, "Testing fail");
    155        qio_task_set_error(task, err);
    156    }
    157}
    158
    159
    160static void test_task_thread_callback(QIOTask *task,
    161                                      gpointer opaque)
    162{
    163    struct TestThreadWorkerData *data = opaque;
    164
    165    data->source = qio_task_get_source(task);
    166    qio_task_propagate_error(task, &data->err);
    167
    168    data->complete = g_thread_self();
    169
    170    g_main_loop_quit(data->loop);
    171}
    172
    173
    174static void test_task_thread_complete(void)
    175{
    176    QIOTask *task;
    177    Object *obj = object_new(TYPE_DUMMY);
    178    struct TestThreadWorkerData data = { 0 };
    179    GThread *self;
    180
    181    data.loop = g_main_loop_new(g_main_context_default(),
    182                                TRUE);
    183
    184    task = qio_task_new(obj,
    185                        test_task_thread_callback,
    186                        &data,
    187                        NULL);
    188
    189    qio_task_run_in_thread(task,
    190                           test_task_thread_worker,
    191                           &data,
    192                           NULL,
    193                           NULL);
    194
    195    g_main_loop_run(data.loop);
    196
    197    g_main_loop_unref(data.loop);
    198    object_unref(obj);
    199
    200    g_assert(data.source == obj);
    201    g_assert(data.err == NULL);
    202
    203    self = g_thread_self();
    204
    205    /* Make sure the test_task_thread_worker actually got
    206     * run in a different thread */
    207    g_assert(data.worker != self);
    208
    209    /* And that the test_task_thread_callback got rnu in
    210     * the main loop thread (ie this one) */
    211    g_assert(data.complete == self);
    212}
    213
    214
    215static void test_task_thread_failure(void)
    216{
    217    QIOTask *task;
    218    Object *obj = object_new(TYPE_DUMMY);
    219    struct TestThreadWorkerData data = { 0 };
    220    GThread *self;
    221
    222    data.loop = g_main_loop_new(g_main_context_default(),
    223                                TRUE);
    224    data.fail = true;
    225
    226    task = qio_task_new(obj,
    227                        test_task_thread_callback,
    228                        &data,
    229                        NULL);
    230
    231    qio_task_run_in_thread(task,
    232                           test_task_thread_worker,
    233                           &data,
    234                           NULL,
    235                           NULL);
    236
    237    g_main_loop_run(data.loop);
    238
    239    g_main_loop_unref(data.loop);
    240    object_unref(obj);
    241
    242    g_assert(data.source == obj);
    243    error_free_or_abort(&data.err);
    244
    245    self = g_thread_self();
    246
    247    /* Make sure the test_task_thread_worker actually got
    248     * run in a different thread */
    249    g_assert(data.worker != self);
    250
    251    /* And that the test_task_thread_callback got rnu in
    252     * the main loop thread (ie this one) */
    253    g_assert(data.complete == self);
    254}
    255
    256
    257int main(int argc, char **argv)
    258{
    259    g_test_init(&argc, &argv, NULL);
    260    module_call_init(MODULE_INIT_QOM);
    261    type_register_static(&dummy_info);
    262    g_test_add_func("/crypto/task/complete", test_task_complete);
    263    g_test_add_func("/crypto/task/datafree", test_task_data_free);
    264    g_test_add_func("/crypto/task/failure", test_task_failure);
    265    g_test_add_func("/crypto/task/thread_complete", test_task_thread_complete);
    266    g_test_add_func("/crypto/task/thread_failure", test_task_thread_failure);
    267    return g_test_run();
    268}