xref: /qemu/tests/unit/test-blockjob.c (revision 9ef8112a24d13c9d054c26105b24a3e12e1cb430)
1*9ef8112aSAlberto Garcia /*
2*9ef8112aSAlberto Garcia  * Blockjob tests
3*9ef8112aSAlberto Garcia  *
4*9ef8112aSAlberto Garcia  * Copyright Igalia, S.L. 2016
5*9ef8112aSAlberto Garcia  *
6*9ef8112aSAlberto Garcia  * Authors:
7*9ef8112aSAlberto Garcia  *  Alberto Garcia   <berto@igalia.com>
8*9ef8112aSAlberto Garcia  *
9*9ef8112aSAlberto Garcia  * This work is licensed under the terms of the GNU LGPL, version 2 or later.
10*9ef8112aSAlberto Garcia  * See the COPYING.LIB file in the top-level directory.
11*9ef8112aSAlberto Garcia  */
12*9ef8112aSAlberto Garcia 
13*9ef8112aSAlberto Garcia #include "qemu/osdep.h"
14*9ef8112aSAlberto Garcia #include "qapi/error.h"
15*9ef8112aSAlberto Garcia #include "qemu/main-loop.h"
16*9ef8112aSAlberto Garcia #include "block/blockjob.h"
17*9ef8112aSAlberto Garcia #include "sysemu/block-backend.h"
18*9ef8112aSAlberto Garcia 
19*9ef8112aSAlberto Garcia static const BlockJobDriver test_block_job_driver = {
20*9ef8112aSAlberto Garcia     .instance_size = sizeof(BlockJob),
21*9ef8112aSAlberto Garcia };
22*9ef8112aSAlberto Garcia 
23*9ef8112aSAlberto Garcia static void block_job_cb(void *opaque, int ret)
24*9ef8112aSAlberto Garcia {
25*9ef8112aSAlberto Garcia }
26*9ef8112aSAlberto Garcia 
27*9ef8112aSAlberto Garcia static BlockJob *do_test_id(BlockBackend *blk, const char *id,
28*9ef8112aSAlberto Garcia                             bool should_succeed)
29*9ef8112aSAlberto Garcia {
30*9ef8112aSAlberto Garcia     BlockJob *job;
31*9ef8112aSAlberto Garcia     Error *errp = NULL;
32*9ef8112aSAlberto Garcia 
33*9ef8112aSAlberto Garcia     job = block_job_create(id, &test_block_job_driver, blk_bs(blk), 0,
34*9ef8112aSAlberto Garcia                            block_job_cb, NULL, &errp);
35*9ef8112aSAlberto Garcia     if (should_succeed) {
36*9ef8112aSAlberto Garcia         g_assert_null(errp);
37*9ef8112aSAlberto Garcia         g_assert_nonnull(job);
38*9ef8112aSAlberto Garcia         if (id) {
39*9ef8112aSAlberto Garcia             g_assert_cmpstr(job->id, ==, id);
40*9ef8112aSAlberto Garcia         } else {
41*9ef8112aSAlberto Garcia             g_assert_cmpstr(job->id, ==, blk_name(blk));
42*9ef8112aSAlberto Garcia         }
43*9ef8112aSAlberto Garcia     } else {
44*9ef8112aSAlberto Garcia         g_assert_nonnull(errp);
45*9ef8112aSAlberto Garcia         g_assert_null(job);
46*9ef8112aSAlberto Garcia         error_free(errp);
47*9ef8112aSAlberto Garcia     }
48*9ef8112aSAlberto Garcia 
49*9ef8112aSAlberto Garcia     return job;
50*9ef8112aSAlberto Garcia }
51*9ef8112aSAlberto Garcia 
52*9ef8112aSAlberto Garcia /* This creates a BlockBackend (optionally with a name) with a
53*9ef8112aSAlberto Garcia  * BlockDriverState inserted. */
54*9ef8112aSAlberto Garcia static BlockBackend *create_blk(const char *name)
55*9ef8112aSAlberto Garcia {
56*9ef8112aSAlberto Garcia     BlockBackend *blk = blk_new();
57*9ef8112aSAlberto Garcia     BlockDriverState *bs = bdrv_new();
58*9ef8112aSAlberto Garcia 
59*9ef8112aSAlberto Garcia     blk_insert_bs(blk, bs);
60*9ef8112aSAlberto Garcia     bdrv_unref(bs);
61*9ef8112aSAlberto Garcia 
62*9ef8112aSAlberto Garcia     if (name) {
63*9ef8112aSAlberto Garcia         Error *errp = NULL;
64*9ef8112aSAlberto Garcia         monitor_add_blk(blk, name, &errp);
65*9ef8112aSAlberto Garcia         g_assert_null(errp);
66*9ef8112aSAlberto Garcia     }
67*9ef8112aSAlberto Garcia 
68*9ef8112aSAlberto Garcia     return blk;
69*9ef8112aSAlberto Garcia }
70*9ef8112aSAlberto Garcia 
71*9ef8112aSAlberto Garcia /* This destroys the backend */
72*9ef8112aSAlberto Garcia static void destroy_blk(BlockBackend *blk)
73*9ef8112aSAlberto Garcia {
74*9ef8112aSAlberto Garcia     if (blk_name(blk)[0] != '\0') {
75*9ef8112aSAlberto Garcia         monitor_remove_blk(blk);
76*9ef8112aSAlberto Garcia     }
77*9ef8112aSAlberto Garcia 
78*9ef8112aSAlberto Garcia     blk_remove_bs(blk);
79*9ef8112aSAlberto Garcia     blk_unref(blk);
80*9ef8112aSAlberto Garcia }
81*9ef8112aSAlberto Garcia 
82*9ef8112aSAlberto Garcia static void test_job_ids(void)
83*9ef8112aSAlberto Garcia {
84*9ef8112aSAlberto Garcia     BlockBackend *blk[3];
85*9ef8112aSAlberto Garcia     BlockJob *job[3];
86*9ef8112aSAlberto Garcia 
87*9ef8112aSAlberto Garcia     blk[0] = create_blk(NULL);
88*9ef8112aSAlberto Garcia     blk[1] = create_blk("drive1");
89*9ef8112aSAlberto Garcia     blk[2] = create_blk("drive2");
90*9ef8112aSAlberto Garcia 
91*9ef8112aSAlberto Garcia     /* No job ID provided and the block backend has no name */
92*9ef8112aSAlberto Garcia     job[0] = do_test_id(blk[0], NULL, false);
93*9ef8112aSAlberto Garcia 
94*9ef8112aSAlberto Garcia     /* These are all invalid job IDs */
95*9ef8112aSAlberto Garcia     job[0] = do_test_id(blk[0], "0id", false);
96*9ef8112aSAlberto Garcia     job[0] = do_test_id(blk[0], "",    false);
97*9ef8112aSAlberto Garcia     job[0] = do_test_id(blk[0], "   ", false);
98*9ef8112aSAlberto Garcia     job[0] = do_test_id(blk[0], "123", false);
99*9ef8112aSAlberto Garcia     job[0] = do_test_id(blk[0], "_id", false);
100*9ef8112aSAlberto Garcia     job[0] = do_test_id(blk[0], "-id", false);
101*9ef8112aSAlberto Garcia     job[0] = do_test_id(blk[0], ".id", false);
102*9ef8112aSAlberto Garcia     job[0] = do_test_id(blk[0], "#id", false);
103*9ef8112aSAlberto Garcia 
104*9ef8112aSAlberto Garcia     /* This one is valid */
105*9ef8112aSAlberto Garcia     job[0] = do_test_id(blk[0], "id0", true);
106*9ef8112aSAlberto Garcia 
107*9ef8112aSAlberto Garcia     /* We cannot have two jobs in the same BDS */
108*9ef8112aSAlberto Garcia     do_test_id(blk[0], "id1", false);
109*9ef8112aSAlberto Garcia 
110*9ef8112aSAlberto Garcia     /* Duplicate job IDs are not allowed */
111*9ef8112aSAlberto Garcia     job[1] = do_test_id(blk[1], "id0", false);
112*9ef8112aSAlberto Garcia 
113*9ef8112aSAlberto Garcia     /* But once job[0] finishes we can reuse its ID */
114*9ef8112aSAlberto Garcia     block_job_unref(job[0]);
115*9ef8112aSAlberto Garcia     job[1] = do_test_id(blk[1], "id0", true);
116*9ef8112aSAlberto Garcia 
117*9ef8112aSAlberto Garcia     /* No job ID specified, defaults to the backend name ('drive1') */
118*9ef8112aSAlberto Garcia     block_job_unref(job[1]);
119*9ef8112aSAlberto Garcia     job[1] = do_test_id(blk[1], NULL, true);
120*9ef8112aSAlberto Garcia 
121*9ef8112aSAlberto Garcia     /* Duplicate job ID */
122*9ef8112aSAlberto Garcia     job[2] = do_test_id(blk[2], "drive1", false);
123*9ef8112aSAlberto Garcia 
124*9ef8112aSAlberto Garcia     /* The ID of job[2] would default to 'drive2' but it is already in use */
125*9ef8112aSAlberto Garcia     job[0] = do_test_id(blk[0], "drive2", true);
126*9ef8112aSAlberto Garcia     job[2] = do_test_id(blk[2], NULL, false);
127*9ef8112aSAlberto Garcia 
128*9ef8112aSAlberto Garcia     /* This one is valid */
129*9ef8112aSAlberto Garcia     job[2] = do_test_id(blk[2], "id_2", true);
130*9ef8112aSAlberto Garcia 
131*9ef8112aSAlberto Garcia     block_job_unref(job[0]);
132*9ef8112aSAlberto Garcia     block_job_unref(job[1]);
133*9ef8112aSAlberto Garcia     block_job_unref(job[2]);
134*9ef8112aSAlberto Garcia 
135*9ef8112aSAlberto Garcia     destroy_blk(blk[0]);
136*9ef8112aSAlberto Garcia     destroy_blk(blk[1]);
137*9ef8112aSAlberto Garcia     destroy_blk(blk[2]);
138*9ef8112aSAlberto Garcia }
139*9ef8112aSAlberto Garcia 
140*9ef8112aSAlberto Garcia int main(int argc, char **argv)
141*9ef8112aSAlberto Garcia {
142*9ef8112aSAlberto Garcia     qemu_init_main_loop(&error_abort);
143*9ef8112aSAlberto Garcia 
144*9ef8112aSAlberto Garcia     g_test_init(&argc, &argv, NULL);
145*9ef8112aSAlberto Garcia     g_test_add_func("/blockjob/ids", test_job_ids);
146*9ef8112aSAlberto Garcia     return g_test_run();
147*9ef8112aSAlberto Garcia }
148