xref: /openbmc/qemu/tests/unit/test-blockjob.c (revision 6370d13c62c300826f8eb80e4ed9d2e67bad3fa7)
1da668aa1SThomas Huth /*
2da668aa1SThomas Huth  * Blockjob tests
3da668aa1SThomas Huth  *
4da668aa1SThomas Huth  * Copyright Igalia, S.L. 2016
5da668aa1SThomas Huth  *
6da668aa1SThomas Huth  * Authors:
7da668aa1SThomas Huth  *  Alberto Garcia   <berto@igalia.com>
8da668aa1SThomas Huth  *
9da668aa1SThomas Huth  * This work is licensed under the terms of the GNU LGPL, version 2 or later.
10da668aa1SThomas Huth  * See the COPYING.LIB file in the top-level directory.
11da668aa1SThomas Huth  */
12da668aa1SThomas Huth 
13da668aa1SThomas Huth #include "qemu/osdep.h"
14da668aa1SThomas Huth #include "qapi/error.h"
15da668aa1SThomas Huth #include "qemu/main-loop.h"
16da668aa1SThomas Huth #include "block/blockjob_int.h"
17da668aa1SThomas Huth #include "sysemu/block-backend.h"
18da668aa1SThomas Huth #include "qapi/qmp/qdict.h"
19c2c731a4SMax Reitz #include "iothread.h"
20da668aa1SThomas Huth 
21da668aa1SThomas Huth static const BlockJobDriver test_block_job_driver = {
22da668aa1SThomas Huth     .job_driver = {
23da668aa1SThomas Huth         .instance_size = sizeof(BlockJob),
24da668aa1SThomas Huth         .free          = block_job_free,
25da668aa1SThomas Huth         .user_resume   = block_job_user_resume,
26da668aa1SThomas Huth     },
27da668aa1SThomas Huth };
28da668aa1SThomas Huth 
block_job_cb(void * opaque,int ret)29da668aa1SThomas Huth static void block_job_cb(void *opaque, int ret)
30da668aa1SThomas Huth {
31da668aa1SThomas Huth }
32da668aa1SThomas Huth 
mk_job(BlockBackend * blk,const char * id,const BlockJobDriver * drv,bool should_succeed,int flags)33da668aa1SThomas Huth static BlockJob *mk_job(BlockBackend *blk, const char *id,
34da668aa1SThomas Huth                         const BlockJobDriver *drv, bool should_succeed,
35da668aa1SThomas Huth                         int flags)
36da668aa1SThomas Huth {
37da668aa1SThomas Huth     BlockJob *job;
38da668aa1SThomas Huth     Error *err = NULL;
39da668aa1SThomas Huth 
40da668aa1SThomas Huth     job = block_job_create(id, drv, NULL, blk_bs(blk),
41da668aa1SThomas Huth                            0, BLK_PERM_ALL, 0, flags, block_job_cb,
42da668aa1SThomas Huth                            NULL, &err);
43da668aa1SThomas Huth     if (should_succeed) {
44da668aa1SThomas Huth         g_assert_null(err);
45da668aa1SThomas Huth         g_assert_nonnull(job);
46da668aa1SThomas Huth         if (id) {
47da668aa1SThomas Huth             g_assert_cmpstr(job->job.id, ==, id);
48da668aa1SThomas Huth         } else {
49da668aa1SThomas Huth             g_assert_cmpstr(job->job.id, ==, blk_name(blk));
50da668aa1SThomas Huth         }
51da668aa1SThomas Huth     } else {
52da668aa1SThomas Huth         error_free_or_abort(&err);
53da668aa1SThomas Huth         g_assert_null(job);
54da668aa1SThomas Huth     }
55da668aa1SThomas Huth 
56da668aa1SThomas Huth     return job;
57da668aa1SThomas Huth }
58da668aa1SThomas Huth 
do_test_id(BlockBackend * blk,const char * id,bool should_succeed)59da668aa1SThomas Huth static BlockJob *do_test_id(BlockBackend *blk, const char *id,
60da668aa1SThomas Huth                             bool should_succeed)
61da668aa1SThomas Huth {
62da668aa1SThomas Huth     return mk_job(blk, id, &test_block_job_driver,
63da668aa1SThomas Huth                   should_succeed, JOB_DEFAULT);
64da668aa1SThomas Huth }
65da668aa1SThomas Huth 
66da668aa1SThomas Huth /* This creates a BlockBackend (optionally with a name) with a
67da668aa1SThomas Huth  * BlockDriverState inserted. */
create_blk(const char * name)68da668aa1SThomas Huth static BlockBackend *create_blk(const char *name)
69da668aa1SThomas Huth {
70da668aa1SThomas Huth     /* No I/O is performed on this device */
71da668aa1SThomas Huth     BlockBackend *blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
72da668aa1SThomas Huth     BlockDriverState *bs;
73da668aa1SThomas Huth 
74da668aa1SThomas Huth     QDict *opt = qdict_new();
75da668aa1SThomas Huth     qdict_put_str(opt, "file.read-zeroes", "on");
76da668aa1SThomas Huth     bs = bdrv_open("null-co://", NULL, opt, 0, &error_abort);
77da668aa1SThomas Huth     g_assert_nonnull(bs);
78da668aa1SThomas Huth 
79da668aa1SThomas Huth     blk_insert_bs(blk, bs, &error_abort);
80da668aa1SThomas Huth     bdrv_unref(bs);
81da668aa1SThomas Huth 
82da668aa1SThomas Huth     if (name) {
83da668aa1SThomas Huth         Error *err = NULL;
84da668aa1SThomas Huth         monitor_add_blk(blk, name, &err);
85da668aa1SThomas Huth         g_assert_null(err);
86da668aa1SThomas Huth     }
87da668aa1SThomas Huth 
88da668aa1SThomas Huth     return blk;
89da668aa1SThomas Huth }
90da668aa1SThomas Huth 
91da668aa1SThomas Huth /* This destroys the backend */
destroy_blk(BlockBackend * blk)92da668aa1SThomas Huth static void destroy_blk(BlockBackend *blk)
93da668aa1SThomas Huth {
94da668aa1SThomas Huth     if (blk_name(blk)[0] != '\0') {
95da668aa1SThomas Huth         monitor_remove_blk(blk);
96da668aa1SThomas Huth     }
97da668aa1SThomas Huth 
98da668aa1SThomas Huth     blk_remove_bs(blk);
99da668aa1SThomas Huth     blk_unref(blk);
100da668aa1SThomas Huth }
101da668aa1SThomas Huth 
test_job_ids(void)102da668aa1SThomas Huth static void test_job_ids(void)
103da668aa1SThomas Huth {
104da668aa1SThomas Huth     BlockBackend *blk[3];
105da668aa1SThomas Huth     BlockJob *job[3];
106da668aa1SThomas Huth 
107da668aa1SThomas Huth     blk[0] = create_blk(NULL);
108da668aa1SThomas Huth     blk[1] = create_blk("drive1");
109da668aa1SThomas Huth     blk[2] = create_blk("drive2");
110da668aa1SThomas Huth 
111da668aa1SThomas Huth     /* No job ID provided and the block backend has no name */
112da668aa1SThomas Huth     job[0] = do_test_id(blk[0], NULL, false);
113da668aa1SThomas Huth 
114da668aa1SThomas Huth     /* These are all invalid job IDs */
115da668aa1SThomas Huth     job[0] = do_test_id(blk[0], "0id", false);
116da668aa1SThomas Huth     job[0] = do_test_id(blk[0], "",    false);
117da668aa1SThomas Huth     job[0] = do_test_id(blk[0], "   ", false);
118da668aa1SThomas Huth     job[0] = do_test_id(blk[0], "123", false);
119da668aa1SThomas Huth     job[0] = do_test_id(blk[0], "_id", false);
120da668aa1SThomas Huth     job[0] = do_test_id(blk[0], "-id", false);
121da668aa1SThomas Huth     job[0] = do_test_id(blk[0], ".id", false);
122da668aa1SThomas Huth     job[0] = do_test_id(blk[0], "#id", false);
123da668aa1SThomas Huth 
124da668aa1SThomas Huth     /* This one is valid */
125da668aa1SThomas Huth     job[0] = do_test_id(blk[0], "id0", true);
126da668aa1SThomas Huth 
127da668aa1SThomas Huth     /* We can have two jobs in the same BDS */
128da668aa1SThomas Huth     job[1] = do_test_id(blk[0], "id1", true);
129da668aa1SThomas Huth     job_early_fail(&job[1]->job);
130da668aa1SThomas Huth 
131da668aa1SThomas Huth     /* Duplicate job IDs are not allowed */
132da668aa1SThomas Huth     job[1] = do_test_id(blk[1], "id0", false);
133da668aa1SThomas Huth 
134da668aa1SThomas Huth     /* But once job[0] finishes we can reuse its ID */
135da668aa1SThomas Huth     job_early_fail(&job[0]->job);
136da668aa1SThomas Huth     job[1] = do_test_id(blk[1], "id0", true);
137da668aa1SThomas Huth 
138da668aa1SThomas Huth     /* No job ID specified, defaults to the backend name ('drive1') */
139da668aa1SThomas Huth     job_early_fail(&job[1]->job);
140da668aa1SThomas Huth     job[1] = do_test_id(blk[1], NULL, true);
141da668aa1SThomas Huth 
142da668aa1SThomas Huth     /* Duplicate job ID */
143da668aa1SThomas Huth     job[2] = do_test_id(blk[2], "drive1", false);
144da668aa1SThomas Huth 
145da668aa1SThomas Huth     /* The ID of job[2] would default to 'drive2' but it is already in use */
146da668aa1SThomas Huth     job[0] = do_test_id(blk[0], "drive2", true);
147da668aa1SThomas Huth     job[2] = do_test_id(blk[2], NULL, false);
148da668aa1SThomas Huth 
149da668aa1SThomas Huth     /* This one is valid */
150da668aa1SThomas Huth     job[2] = do_test_id(blk[2], "id_2", true);
151da668aa1SThomas Huth 
152da668aa1SThomas Huth     job_early_fail(&job[0]->job);
153da668aa1SThomas Huth     job_early_fail(&job[1]->job);
154da668aa1SThomas Huth     job_early_fail(&job[2]->job);
155da668aa1SThomas Huth 
156da668aa1SThomas Huth     destroy_blk(blk[0]);
157da668aa1SThomas Huth     destroy_blk(blk[1]);
158da668aa1SThomas Huth     destroy_blk(blk[2]);
159da668aa1SThomas Huth }
160da668aa1SThomas Huth 
161da668aa1SThomas Huth typedef struct CancelJob {
162da668aa1SThomas Huth     BlockJob common;
163da668aa1SThomas Huth     BlockBackend *blk;
164da668aa1SThomas Huth     bool should_converge;
165da668aa1SThomas Huth     bool should_complete;
166da668aa1SThomas Huth } CancelJob;
167da668aa1SThomas Huth 
cancel_job_complete(Job * job,Error ** errp)168da668aa1SThomas Huth static void cancel_job_complete(Job *job, Error **errp)
169da668aa1SThomas Huth {
170da668aa1SThomas Huth     CancelJob *s = container_of(job, CancelJob, common.job);
171da668aa1SThomas Huth     s->should_complete = true;
172da668aa1SThomas Huth }
173da668aa1SThomas Huth 
cancel_job_run(Job * job,Error ** errp)174da668aa1SThomas Huth static int coroutine_fn cancel_job_run(Job *job, Error **errp)
175da668aa1SThomas Huth {
176da668aa1SThomas Huth     CancelJob *s = container_of(job, CancelJob, common.job);
177da668aa1SThomas Huth 
178da668aa1SThomas Huth     while (!s->should_complete) {
179da668aa1SThomas Huth         if (job_is_cancelled(&s->common.job)) {
180da668aa1SThomas Huth             return 0;
181da668aa1SThomas Huth         }
182da668aa1SThomas Huth 
183da668aa1SThomas Huth         if (!job_is_ready(&s->common.job) && s->should_converge) {
184da668aa1SThomas Huth             job_transition_to_ready(&s->common.job);
185da668aa1SThomas Huth         }
186da668aa1SThomas Huth 
187da668aa1SThomas Huth         job_sleep_ns(&s->common.job, 100000);
188da668aa1SThomas Huth     }
189da668aa1SThomas Huth 
190da668aa1SThomas Huth     return 0;
191da668aa1SThomas Huth }
192da668aa1SThomas Huth 
193da668aa1SThomas Huth static const BlockJobDriver test_cancel_driver = {
194da668aa1SThomas Huth     .job_driver = {
195da668aa1SThomas Huth         .instance_size = sizeof(CancelJob),
196da668aa1SThomas Huth         .free          = block_job_free,
197da668aa1SThomas Huth         .user_resume   = block_job_user_resume,
198da668aa1SThomas Huth         .run           = cancel_job_run,
199da668aa1SThomas Huth         .complete      = cancel_job_complete,
200da668aa1SThomas Huth     },
201da668aa1SThomas Huth };
202da668aa1SThomas Huth 
create_common(Job ** pjob)203da668aa1SThomas Huth static CancelJob *create_common(Job **pjob)
204da668aa1SThomas Huth {
205da668aa1SThomas Huth     BlockBackend *blk;
206da668aa1SThomas Huth     Job *job;
207da668aa1SThomas Huth     BlockJob *bjob;
208da668aa1SThomas Huth     CancelJob *s;
209da668aa1SThomas Huth 
210da668aa1SThomas Huth     blk = create_blk(NULL);
211da668aa1SThomas Huth     bjob = mk_job(blk, "Steve", &test_cancel_driver, true,
212da668aa1SThomas Huth                   JOB_MANUAL_FINALIZE | JOB_MANUAL_DISMISS);
213da668aa1SThomas Huth     job = &bjob->job;
214191e7af3SEmanuele Giuseppe Esposito     WITH_JOB_LOCK_GUARD() {
215191e7af3SEmanuele Giuseppe Esposito         job_ref_locked(job);
216da668aa1SThomas Huth         assert(job->status == JOB_STATUS_CREATED);
217191e7af3SEmanuele Giuseppe Esposito     }
218191e7af3SEmanuele Giuseppe Esposito 
219da668aa1SThomas Huth     s = container_of(bjob, CancelJob, common);
220da668aa1SThomas Huth     s->blk = blk;
221da668aa1SThomas Huth 
222da668aa1SThomas Huth     *pjob = job;
223da668aa1SThomas Huth     return s;
224da668aa1SThomas Huth }
225da668aa1SThomas Huth 
cancel_common(CancelJob * s)226da668aa1SThomas Huth static void cancel_common(CancelJob *s)
227da668aa1SThomas Huth {
228da668aa1SThomas Huth     BlockJob *job = &s->common;
229da668aa1SThomas Huth     BlockBackend *blk = s->blk;
230da668aa1SThomas Huth     JobStatus sts = job->job.status;
231da668aa1SThomas Huth 
2324cfb3f05SHanna Reitz     job_cancel_sync(&job->job, true);
233191e7af3SEmanuele Giuseppe Esposito     WITH_JOB_LOCK_GUARD() {
234da668aa1SThomas Huth         if (sts != JOB_STATUS_CREATED && sts != JOB_STATUS_CONCLUDED) {
235da668aa1SThomas Huth             Job *dummy = &job->job;
236191e7af3SEmanuele Giuseppe Esposito             job_dismiss_locked(&dummy, &error_abort);
237da668aa1SThomas Huth         }
238da668aa1SThomas Huth         assert(job->job.status == JOB_STATUS_NULL);
239191e7af3SEmanuele Giuseppe Esposito         job_unref_locked(&job->job);
240191e7af3SEmanuele Giuseppe Esposito     }
241da668aa1SThomas Huth 
242*6f592e5aSEmanuele Giuseppe Esposito     destroy_blk(blk);
243*6f592e5aSEmanuele Giuseppe Esposito 
244da668aa1SThomas Huth }
245da668aa1SThomas Huth 
test_cancel_created(void)246da668aa1SThomas Huth static void test_cancel_created(void)
247da668aa1SThomas Huth {
248da668aa1SThomas Huth     Job *job;
249da668aa1SThomas Huth     CancelJob *s;
250da668aa1SThomas Huth 
251da668aa1SThomas Huth     s = create_common(&job);
252da668aa1SThomas Huth     cancel_common(s);
253da668aa1SThomas Huth }
254da668aa1SThomas Huth 
assert_job_status_is(Job * job,int status)255191e7af3SEmanuele Giuseppe Esposito static void assert_job_status_is(Job *job, int status)
256191e7af3SEmanuele Giuseppe Esposito {
257191e7af3SEmanuele Giuseppe Esposito     WITH_JOB_LOCK_GUARD() {
258191e7af3SEmanuele Giuseppe Esposito         assert(job->status == status);
259191e7af3SEmanuele Giuseppe Esposito     }
260191e7af3SEmanuele Giuseppe Esposito }
261191e7af3SEmanuele Giuseppe Esposito 
test_cancel_running(void)262da668aa1SThomas Huth static void test_cancel_running(void)
263da668aa1SThomas Huth {
264da668aa1SThomas Huth     Job *job;
265da668aa1SThomas Huth     CancelJob *s;
266da668aa1SThomas Huth 
267da668aa1SThomas Huth     s = create_common(&job);
268da668aa1SThomas Huth 
269da668aa1SThomas Huth     job_start(job);
270191e7af3SEmanuele Giuseppe Esposito     assert_job_status_is(job, JOB_STATUS_RUNNING);
271da668aa1SThomas Huth 
272da668aa1SThomas Huth     cancel_common(s);
273da668aa1SThomas Huth }
274da668aa1SThomas Huth 
test_cancel_paused(void)275da668aa1SThomas Huth static void test_cancel_paused(void)
276da668aa1SThomas Huth {
277da668aa1SThomas Huth     Job *job;
278da668aa1SThomas Huth     CancelJob *s;
279da668aa1SThomas Huth 
280da668aa1SThomas Huth     s = create_common(&job);
281da668aa1SThomas Huth 
282da668aa1SThomas Huth     job_start(job);
283191e7af3SEmanuele Giuseppe Esposito     WITH_JOB_LOCK_GUARD() {
284da668aa1SThomas Huth         assert(job->status == JOB_STATUS_RUNNING);
285191e7af3SEmanuele Giuseppe Esposito         job_user_pause_locked(job, &error_abort);
286191e7af3SEmanuele Giuseppe Esposito     }
287da668aa1SThomas Huth     job_enter(job);
288191e7af3SEmanuele Giuseppe Esposito     assert_job_status_is(job, JOB_STATUS_PAUSED);
289da668aa1SThomas Huth 
290da668aa1SThomas Huth     cancel_common(s);
291da668aa1SThomas Huth }
292da668aa1SThomas Huth 
test_cancel_ready(void)293da668aa1SThomas Huth static void test_cancel_ready(void)
294da668aa1SThomas Huth {
295da668aa1SThomas Huth     Job *job;
296da668aa1SThomas Huth     CancelJob *s;
297da668aa1SThomas Huth 
298da668aa1SThomas Huth     s = create_common(&job);
299da668aa1SThomas Huth 
300da668aa1SThomas Huth     job_start(job);
301191e7af3SEmanuele Giuseppe Esposito     assert_job_status_is(job, JOB_STATUS_RUNNING);
302da668aa1SThomas Huth 
303da668aa1SThomas Huth     s->should_converge = true;
304da668aa1SThomas Huth     job_enter(job);
305191e7af3SEmanuele Giuseppe Esposito     assert_job_status_is(job, JOB_STATUS_READY);
306da668aa1SThomas Huth 
307da668aa1SThomas Huth     cancel_common(s);
308da668aa1SThomas Huth }
309da668aa1SThomas Huth 
test_cancel_standby(void)310da668aa1SThomas Huth static void test_cancel_standby(void)
311da668aa1SThomas Huth {
312da668aa1SThomas Huth     Job *job;
313da668aa1SThomas Huth     CancelJob *s;
314da668aa1SThomas Huth 
315da668aa1SThomas Huth     s = create_common(&job);
316da668aa1SThomas Huth 
317da668aa1SThomas Huth     job_start(job);
318191e7af3SEmanuele Giuseppe Esposito     assert_job_status_is(job, JOB_STATUS_RUNNING);
319da668aa1SThomas Huth 
320da668aa1SThomas Huth     s->should_converge = true;
321da668aa1SThomas Huth     job_enter(job);
322191e7af3SEmanuele Giuseppe Esposito     WITH_JOB_LOCK_GUARD() {
323da668aa1SThomas Huth         assert(job->status == JOB_STATUS_READY);
324191e7af3SEmanuele Giuseppe Esposito         job_user_pause_locked(job, &error_abort);
325191e7af3SEmanuele Giuseppe Esposito     }
326da668aa1SThomas Huth     job_enter(job);
327191e7af3SEmanuele Giuseppe Esposito     assert_job_status_is(job, JOB_STATUS_STANDBY);
328da668aa1SThomas Huth 
329da668aa1SThomas Huth     cancel_common(s);
330da668aa1SThomas Huth }
331da668aa1SThomas Huth 
test_cancel_pending(void)332da668aa1SThomas Huth static void test_cancel_pending(void)
333da668aa1SThomas Huth {
334da668aa1SThomas Huth     Job *job;
335da668aa1SThomas Huth     CancelJob *s;
336da668aa1SThomas Huth 
337da668aa1SThomas Huth     s = create_common(&job);
338da668aa1SThomas Huth 
339da668aa1SThomas Huth     job_start(job);
340191e7af3SEmanuele Giuseppe Esposito     assert_job_status_is(job, JOB_STATUS_RUNNING);
341da668aa1SThomas Huth 
342da668aa1SThomas Huth     s->should_converge = true;
343da668aa1SThomas Huth     job_enter(job);
344191e7af3SEmanuele Giuseppe Esposito     WITH_JOB_LOCK_GUARD() {
345da668aa1SThomas Huth         assert(job->status == JOB_STATUS_READY);
346191e7af3SEmanuele Giuseppe Esposito         job_complete_locked(job, &error_abort);
347191e7af3SEmanuele Giuseppe Esposito     }
348da668aa1SThomas Huth     job_enter(job);
349da668aa1SThomas Huth     while (!job->deferred_to_main_loop) {
350da668aa1SThomas Huth         aio_poll(qemu_get_aio_context(), true);
351da668aa1SThomas Huth     }
352191e7af3SEmanuele Giuseppe Esposito     assert_job_status_is(job, JOB_STATUS_READY);
353da668aa1SThomas Huth     aio_poll(qemu_get_aio_context(), true);
354191e7af3SEmanuele Giuseppe Esposito     assert_job_status_is(job, JOB_STATUS_PENDING);
355da668aa1SThomas Huth 
356da668aa1SThomas Huth     cancel_common(s);
357da668aa1SThomas Huth }
358da668aa1SThomas Huth 
test_cancel_concluded(void)359da668aa1SThomas Huth static void test_cancel_concluded(void)
360da668aa1SThomas Huth {
361da668aa1SThomas Huth     Job *job;
362da668aa1SThomas Huth     CancelJob *s;
363da668aa1SThomas Huth 
364da668aa1SThomas Huth     s = create_common(&job);
365da668aa1SThomas Huth 
366da668aa1SThomas Huth     job_start(job);
367191e7af3SEmanuele Giuseppe Esposito     assert_job_status_is(job, JOB_STATUS_RUNNING);
368da668aa1SThomas Huth 
369da668aa1SThomas Huth     s->should_converge = true;
370da668aa1SThomas Huth     job_enter(job);
371191e7af3SEmanuele Giuseppe Esposito     WITH_JOB_LOCK_GUARD() {
372da668aa1SThomas Huth         assert(job->status == JOB_STATUS_READY);
373191e7af3SEmanuele Giuseppe Esposito         job_complete_locked(job, &error_abort);
374191e7af3SEmanuele Giuseppe Esposito     }
375da668aa1SThomas Huth     job_enter(job);
376da668aa1SThomas Huth     while (!job->deferred_to_main_loop) {
377da668aa1SThomas Huth         aio_poll(qemu_get_aio_context(), true);
378da668aa1SThomas Huth     }
379191e7af3SEmanuele Giuseppe Esposito     assert_job_status_is(job, JOB_STATUS_READY);
380da668aa1SThomas Huth     aio_poll(qemu_get_aio_context(), true);
381191e7af3SEmanuele Giuseppe Esposito     assert_job_status_is(job, JOB_STATUS_PENDING);
382da668aa1SThomas Huth 
383191e7af3SEmanuele Giuseppe Esposito     WITH_JOB_LOCK_GUARD() {
384191e7af3SEmanuele Giuseppe Esposito         job_finalize_locked(job, &error_abort);
385*6f592e5aSEmanuele Giuseppe Esposito         assert(job->status == JOB_STATUS_CONCLUDED);
386191e7af3SEmanuele Giuseppe Esposito     }
387da668aa1SThomas Huth 
388da668aa1SThomas Huth     cancel_common(s);
389da668aa1SThomas Huth }
390da668aa1SThomas Huth 
main(int argc,char ** argv)391da668aa1SThomas Huth int main(int argc, char **argv)
392da668aa1SThomas Huth {
393da668aa1SThomas Huth     qemu_init_main_loop(&error_abort);
394da668aa1SThomas Huth     bdrv_init();
395da668aa1SThomas Huth 
396da668aa1SThomas Huth     g_test_init(&argc, &argv, NULL);
397da668aa1SThomas Huth     g_test_add_func("/blockjob/ids", test_job_ids);
398da668aa1SThomas Huth     g_test_add_func("/blockjob/cancel/created", test_cancel_created);
399da668aa1SThomas Huth     g_test_add_func("/blockjob/cancel/running", test_cancel_running);
400da668aa1SThomas Huth     g_test_add_func("/blockjob/cancel/paused", test_cancel_paused);
401da668aa1SThomas Huth     g_test_add_func("/blockjob/cancel/ready", test_cancel_ready);
402da668aa1SThomas Huth     g_test_add_func("/blockjob/cancel/standby", test_cancel_standby);
403da668aa1SThomas Huth     g_test_add_func("/blockjob/cancel/pending", test_cancel_pending);
404da668aa1SThomas Huth     g_test_add_func("/blockjob/cancel/concluded", test_cancel_concluded);
405da668aa1SThomas Huth     return g_test_run();
406da668aa1SThomas Huth }
407