qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

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 
     30 typedef struct DummyObject DummyObject;
     31 typedef struct DummyObjectClass DummyObjectClass;
     32 
     33 struct DummyObject {
     34     Object parent;
     35 };
     36 
     37 struct DummyObjectClass {
     38     ObjectClass parent;
     39 };
     40 
     41 static const TypeInfo dummy_info = {
     42     .parent = TYPE_OBJECT,
     43     .name = TYPE_DUMMY,
     44     .instance_size = sizeof(DummyObject),
     45     .class_size = sizeof(DummyObjectClass),
     46 };
     47 
     48 struct TestTaskData {
     49     Object *source;
     50     Error *err;
     51     bool freed;
     52 };
     53 
     54 
     55 static 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 
     65 static 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 
     87 static void task_data_free(gpointer opaque)
     88 {
     89     struct TestTaskData *data = opaque;
     90 
     91     data->freed = true;
     92 }
     93 
     94 
     95 static 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 
    113 static 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 
    136 struct TestThreadWorkerData {
    137     Object *source;
    138     Error *err;
    139     bool fail;
    140     GThread *worker;
    141     GThread *complete;
    142     GMainLoop *loop;
    143 };
    144 
    145 static 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 
    160 static 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 
    174 static 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 
    215 static 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 
    257 int 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 }