virstoragetest.c 38.3 KB
Newer Older
1
/*
2
 * Copyright (C) 2013-2014 Red Hat, Inc.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * Author: Eric Blake <eblake@redhat.com>
 */

#include <config.h>

#include <stdlib.h>

#include "testutils.h"
#include "vircommand.h"
#include "virerror.h"
28
#include "virfile.h"
29 30
#include "virlog.h"
#include "virstoragefile.h"
31
#include "virstring.h"
32
#include "dirname.h"
33

34 35
#include "storage/storage_driver.h"

36 37
#define VIR_FROM_THIS VIR_FROM_NONE

38 39
VIR_LOG_INIT("tests.storagetest");

40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
#define datadir abs_builddir "/virstoragedata"

/* This test creates the following files, all in datadir:

 * raw: 1024-byte raw file
 * qcow2: qcow2 file with 'raw' as backing
 * wrap: qcow2 file with 'qcow2' as backing
 * qed: qed file with 'raw' as backing
 * sub/link1: symlink to qcow2
 * sub/link2: symlink to wrap
 *
 * Relative names to these files are known at compile time, but absolute
 * and canonical names depend on where the test is run; for convenience,
 * we pre-populate the computation of these names for use during the test.
*/

static char *qemuimg;
static char *absraw;
static char *canonraw;
static char *absqcow2;
static char *canonqcow2;
static char *abswrap;
E
Eric Blake 已提交
62
static char *canonwrap;
63
static char *absqed;
E
Eric Blake 已提交
64
static char *canonqed;
E
Eric Blake 已提交
65
static char *absdir;
E
Eric Blake 已提交
66
static char *canondir;
67 68 69 70 71 72 73 74 75 76 77
static char *abslink2;

static void
testCleanupImages(void)
{
    VIR_FREE(qemuimg);
    VIR_FREE(absraw);
    VIR_FREE(canonraw);
    VIR_FREE(absqcow2);
    VIR_FREE(canonqcow2);
    VIR_FREE(abswrap);
E
Eric Blake 已提交
78
    VIR_FREE(canonwrap);
79
    VIR_FREE(absqed);
E
Eric Blake 已提交
80
    VIR_FREE(canonqed);
E
Eric Blake 已提交
81
    VIR_FREE(absdir);
E
Eric Blake 已提交
82
    VIR_FREE(canondir);
83 84 85 86 87 88 89 90
    VIR_FREE(abslink2);

    if (chdir(abs_builddir) < 0) {
        fprintf(stderr, "unable to return to correct directory, refusing to "
                "clean up %s\n", datadir);
        return;
    }

91
    virFileDeleteTree(datadir);
92 93
}

94 95 96 97 98 99 100

static virStorageSourcePtr
testStorageFileGetMetadata(const char *path,
                           int format,
                           uid_t uid, gid_t gid,
                           bool allow_probe)
{
101
    struct stat st;
102 103 104 105 106 107 108 109
    virStorageSourcePtr ret = NULL;

    if (VIR_ALLOC(ret) < 0)
        return NULL;

    ret->type = VIR_STORAGE_TYPE_FILE;
    ret->format = format;

110 111 112 113 114 115 116 117 118
    if (stat(path, &st) == 0) {
        if (S_ISDIR(st.st_mode)) {
            ret->type = VIR_STORAGE_TYPE_DIR;
            ret->format = VIR_STORAGE_FILE_DIR;
        } else if (S_ISBLK(st.st_mode)) {
            ret->type = VIR_STORAGE_TYPE_BLOCK;
        }
    }

119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
    if (VIR_STRDUP(ret->relPath, path) < 0)
        goto error;

    if (!(ret->relDir = mdir_name(path))) {
        virReportOOMError();
        goto error;
    }

    if (!(ret->path = canonicalize_file_name(path))) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "failed to resolve '%s'", path);
        goto error;
    }

    if (virStorageFileGetMetadata(ret, uid, gid, allow_probe) < 0)
        goto error;

    return ret;

 error:
    virStorageSourceFree(ret);
    return NULL;
}

142 143 144 145 146
static int
testPrepImages(void)
{
    int ret = EXIT_FAILURE;
    virCommandPtr cmd = NULL;
147 148
    char *buf = NULL;
    bool compat = false;
149 150 151 152

    qemuimg = virFindFileInPath("kvm-img");
    if (!qemuimg)
        qemuimg = virFindFileInPath("qemu-img");
153 154
    if (!qemuimg)
        goto skip;
155

156 157 158
    /* Clean up from any earlier failed tests */
    virFileDeleteTree(datadir);

159 160 161 162 163 164 165 166 167 168 169 170
    /* See if qemu-img supports '-o compat=xxx'.  If so, we force the
     * use of both v2 and v3 files; if not, it is v2 only but the test
     * still works. */
    cmd = virCommandNewArgList(qemuimg, "create", "-f", "qcow2",
                               "-o?", "/dev/null", NULL);
    virCommandSetOutputBuffer(cmd, &buf);
    if (virCommandRun(cmd, NULL) < 0)
        goto skip;
    if (strstr(buf, "compat "))
        compat = true;
    VIR_FREE(buf);

171 172 173 174
    if (virAsprintf(&absraw, "%s/raw", datadir) < 0 ||
        virAsprintf(&absqcow2, "%s/qcow2", datadir) < 0 ||
        virAsprintf(&abswrap, "%s/wrap", datadir) < 0 ||
        virAsprintf(&absqed, "%s/qed", datadir) < 0 ||
E
Eric Blake 已提交
175
        virAsprintf(&absdir, "%s/dir", datadir) < 0 ||
176
        virAsprintf(&abslink2, "%s/sub/link2", datadir) < 0)
177 178 179 180 181 182
        goto cleanup;

    if (virFileMakePath(datadir "/sub") < 0) {
        fprintf(stderr, "unable to create directory %s\n", datadir "/sub");
        goto cleanup;
    }
E
Eric Blake 已提交
183 184 185 186
    if (virFileMakePath(datadir "/dir") < 0) {
        fprintf(stderr, "unable to create directory %s\n", datadir "/dir");
        goto cleanup;
    }
E
Eric Blake 已提交
187 188 189 190
    if (!(canondir = canonicalize_file_name(absdir))) {
        virReportOOMError();
        goto cleanup;
    }
191 192 193 194 195 196

    if (chdir(datadir) < 0) {
        fprintf(stderr, "unable to test relative backing chains\n");
        goto cleanup;
    }

197 198
    if (virAsprintf(&buf, "%1024d", 0) < 0 ||
        virFileWriteStr("raw", buf, 0600) < 0) {
199
        fprintf(stderr, "unable to create raw file\n");
200
        goto cleanup;
201
    }
202 203 204 205 206 207 208 209
    if (!(canonraw = canonicalize_file_name(absraw))) {
        virReportOOMError();
        goto cleanup;
    }

    /* Create a qcow2 wrapping relative raw; later on, we modify its
     * metadata to test other configurations */
    virCommandFree(cmd);
210 211 212 213
    cmd = virCommandNewArgList(qemuimg, "create", "-f", "qcow2", NULL);
    virCommandAddArgFormat(cmd, "-obacking_file=raw,backing_fmt=raw%s",
                           compat ? ",compat=0.10" : "");
    virCommandAddArg(cmd, "qcow2");
214
    if (virCommandRun(cmd, NULL) < 0)
215
        goto skip;
216 217
    /* Make sure our later uses of 'qemu-img rebase' will work */
    virCommandFree(cmd);
218
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
219
                               "-F", "raw", "-b", "raw", "qcow2", NULL);
220 221
    if (virCommandRun(cmd, NULL) < 0)
        goto skip;
222 223 224 225 226 227 228 229
    if (!(canonqcow2 = canonicalize_file_name(absqcow2))) {
        virReportOOMError();
        goto cleanup;
    }

    /* Create a second qcow2 wrapping the first, to be sure that we
     * can correctly avoid insecure probing.  */
    virCommandFree(cmd);
230
    cmd = virCommandNewArgList(qemuimg, "create", "-f", "qcow2", NULL);
231 232
    virCommandAddArgFormat(cmd, "-obacking_file=%s,backing_fmt=qcow2%s",
                           absqcow2, compat ? ",compat=1.1" : "");
233 234
    virCommandAddArg(cmd, "wrap");
    if (virCommandRun(cmd, NULL) < 0)
235
        goto skip;
E
Eric Blake 已提交
236 237 238 239
    if (!(canonwrap = canonicalize_file_name(abswrap))) {
        virReportOOMError();
        goto cleanup;
    }
240 241 242

    /* Create a qed file. */
    virCommandFree(cmd);
243
    cmd = virCommandNewArgList(qemuimg, "create", "-f", "qed", NULL);
244 245 246 247
    virCommandAddArgFormat(cmd, "-obacking_file=%s,backing_fmt=raw",
                           absraw);
    virCommandAddArg(cmd, "qed");
    if (virCommandRun(cmd, NULL) < 0)
248
        goto skip;
E
Eric Blake 已提交
249 250 251 252
    if (!(canonqed = canonicalize_file_name(absqed))) {
        virReportOOMError();
        goto cleanup;
    }
253

254
#ifdef HAVE_SYMLINK
255 256 257 258 259 260
    /* Create some symlinks in a sub-directory. */
    if (symlink("../qcow2", datadir "/sub/link1") < 0 ||
        symlink("../wrap", datadir "/sub/link2") < 0) {
        fprintf(stderr, "unable to create symlink");
        goto cleanup;
    }
261
#endif
262 263

    ret = 0;
264
 cleanup:
265
    VIR_FREE(buf);
266 267 268 269
    virCommandFree(cmd);
    if (ret)
        testCleanupImages();
    return ret;
270

271
 skip:
272 273 274
    fputs("qemu-img is too old; skipping this test\n", stderr);
    ret = EXIT_AM_SKIP;
    goto cleanup;
275 276
}

277 278 279 280 281
/* Many fields of virStorageFileMetadata have the same content whether
 * we access the file relatively or absolutely; but file names differ
 * depending on how the chain was opened.  For ease of testing, we
 * test both relative and absolute starts, and use a flag to say which
 * of the two variations to compare against.  */
282 283 284 285 286 287 288
typedef struct _testFileData testFileData;
struct _testFileData
{
    const char *expBackingStore;
    const char *expBackingStoreRaw;
    unsigned long long expCapacity;
    bool expEncrypted;
289 290
    const char *pathRel;
    const char *pathAbs;
291
    const char *path;
E
Eric Blake 已提交
292 293 294 295
    const char *relDirRel;
    const char *relDirAbs;
    int type;
    int format;
296 297 298 299 300 301 302
};

enum {
    EXP_PASS = 0,
    EXP_FAIL = 1,
    EXP_WARN = 2,
    ALLOW_PROBE = 4,
303
    ABS_START = 8,
304 305 306 307 308
};

struct testChainData
{
    const char *start;
309
    virStorageFileFormat format;
310
    const testFileData *files[4];
311 312 313 314
    int nfiles;
    unsigned int flags;
};

315 316

static const char testStorageChainFormat[] =
317
    "chain member: %zu\n"
318 319 320 321 322 323 324 325 326 327
    "store: %s\n"
    "backingStoreRaw: %s\n"
    "capacity: %lld\n"
    "encryption: %d\n"
    "relPath:%s\n"
    "path:%s\n"
    "relDir:%s\n"
    "type:%d\n"
    "format:%d\n";

328 329 330 331 332
static int
testStorageChain(const void *args)
{
    const struct testChainData *data = args;
    int ret = -1;
333 334
    virStorageSourcePtr meta;
    virStorageSourcePtr elt;
335
    size_t i = 0;
E
Eric Blake 已提交
336
    char *broken = NULL;
337
    bool isAbs = !!(data->flags & ABS_START);
338

339 340
    meta = testStorageFileGetMetadata(data->start, data->format, -1, -1,
                                      (data->flags & ALLOW_PROBE) != 0);
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
    if (!meta) {
        if (data->flags & EXP_FAIL) {
            virResetLastError();
            ret = 0;
        }
        goto cleanup;
    } else if (data->flags & EXP_FAIL) {
        fprintf(stderr, "call should have failed\n");
        goto cleanup;
    }
    if (data->flags & EXP_WARN) {
        if (!virGetLastError()) {
            fprintf(stderr, "call should have warned\n");
            goto cleanup;
        }
        virResetLastError();
E
Eric Blake 已提交
357 358 359 360 361 362 363 364 365 366 367 368 369
        if (virStorageFileChainGetBroken(meta, &broken) || !broken) {
            fprintf(stderr, "call should identify broken part of chain\n");
            goto cleanup;
        }
    } else {
        if (virGetLastError()) {
            fprintf(stderr, "call should not have warned\n");
            goto cleanup;
        }
        if (virStorageFileChainGetBroken(meta, &broken) || broken) {
            fprintf(stderr, "chain should not be identified as broken\n");
            goto cleanup;
        }
370 371 372 373 374 375
    }

    elt = meta;
    while (elt) {
        char *expect = NULL;
        char *actual = NULL;
376
        const char *expPath;
E
Eric Blake 已提交
377
        const char *expRelDir;
378 379 380 381 382 383

        if (i == data->nfiles) {
            fprintf(stderr, "probed chain was too long\n");
            goto cleanup;
        }

384 385
        expPath = isAbs ? data->files[i]->pathAbs
            : data->files[i]->pathRel;
E
Eric Blake 已提交
386 387
        expRelDir = isAbs ? data->files[i]->relDirAbs
            : data->files[i]->relDirRel;
388
        if (virAsprintf(&expect,
389
                        testStorageChainFormat, i,
390 391 392
                        NULLSTR(data->files[i]->expBackingStore),
                        NULLSTR(data->files[i]->expBackingStoreRaw),
                        data->files[i]->expCapacity,
393
                        data->files[i]->expEncrypted,
E
Eric Blake 已提交
394
                        NULLSTR(expPath),
395
                        NULLSTR(data->files[i]->path),
E
Eric Blake 已提交
396 397 398
                        NULLSTR(expRelDir),
                        data->files[i]->type,
                        data->files[i]->format) < 0 ||
399
            virAsprintf(&actual,
400
                        testStorageChainFormat, i,
401
                        NULLSTR(elt->backingStore ? elt->backingStore->path : NULL),
402
                        NULLSTR(elt->backingStoreRaw),
403 404
                        elt->capacity,
                        !!elt->encryption,
405
                        NULLSTR(elt->relPath),
406
                        NULLSTR(elt->path),
E
Eric Blake 已提交
407
                        NULLSTR(elt->relDir),
408 409
                        elt->type,
                        elt->format) < 0) {
410 411 412 413 414 415 416 417 418 419 420 421
            VIR_FREE(expect);
            VIR_FREE(actual);
            goto cleanup;
        }
        if (STRNEQ(expect, actual)) {
            virtTestDifference(stderr, expect, actual);
            VIR_FREE(expect);
            VIR_FREE(actual);
            goto cleanup;
        }
        VIR_FREE(expect);
        VIR_FREE(actual);
422
        elt = elt->backingStore;
423 424 425 426 427 428 429 430
        i++;
    }
    if (i != data->nfiles) {
        fprintf(stderr, "probed chain was too short\n");
        goto cleanup;
    }

    ret = 0;
431
 cleanup:
E
Eric Blake 已提交
432
    VIR_FREE(broken);
433
    virStorageSourceFree(meta);
434 435 436
    return ret;
}

E
Eric Blake 已提交
437 438
struct testLookupData
{
439
    virStorageSourcePtr chain;
440
    const char *target;
E
Eric Blake 已提交
441
    virStorageSourcePtr from;
E
Eric Blake 已提交
442
    const char *name;
443
    unsigned int expIndex;
E
Eric Blake 已提交
444
    const char *expResult;
445
    virStorageSourcePtr expMeta;
E
Eric Blake 已提交
446 447 448 449 450 451 452 453
    const char *expParent;
};

static int
testStorageLookup(const void *args)
{
    const struct testLookupData *data = args;
    int ret = 0;
454
    virStorageSourcePtr result;
E
Eric Blake 已提交
455
    const char *actualParent;
456 457 458 459 460 461 462 463 464 465 466
    unsigned int idx;

    if (virStorageFileParseChainIndex(data->target, data->name, &idx) < 0 &&
        data->expIndex) {
        fprintf(stderr, "call should not have failed\n");
        ret = -1;
    }
    if (idx != data->expIndex) {
        fprintf(stderr, "index: expected %u, got %u\n", data->expIndex, idx);
        ret = -1;
    }
E
Eric Blake 已提交
467

468
     /* Test twice to ensure optional parameter doesn't cause NULL deref. */
E
Eric Blake 已提交
469
    result = virStorageFileChainLookup(data->chain, data->from,
470 471
                                       idx ? NULL : data->name,
                                       idx, NULL);
E
Eric Blake 已提交
472 473 474 475 476 477 478 479 480 481 482 483 484 485

    if (!data->expResult) {
        if (!virGetLastError()) {
            fprintf(stderr, "call should have failed\n");
            ret = -1;
        }
        virResetLastError();
    } else {
        if (virGetLastError()) {
            fprintf(stderr, "call should not have warned\n");
            ret = -1;
        }
    }

486 487 488 489 490 491 492
    if (!result) {
        if (data->expResult) {
            fprintf(stderr, "result 1: expected %s, got NULL\n",
                    data->expResult);
            ret = -1;
        }
    } else if (STRNEQ_NULLABLE(data->expResult, result->path)) {
E
Eric Blake 已提交
493
        fprintf(stderr, "result 1: expected %s, got %s\n",
494
                NULLSTR(data->expResult), NULLSTR(result->path));
E
Eric Blake 已提交
495 496 497
        ret = -1;
    }

E
Eric Blake 已提交
498
    result = virStorageFileChainLookup(data->chain, data->from,
499
                                       data->name, idx, &actualParent);
E
Eric Blake 已提交
500 501
    if (!data->expResult)
        virResetLastError();
502 503 504 505 506 507 508 509

    if (!result) {
        if (data->expResult) {
            fprintf(stderr, "result 2: expected %s, got NULL\n",
                    data->expResult);
            ret = -1;
        }
    } else if (STRNEQ_NULLABLE(data->expResult, result->path)) {
E
Eric Blake 已提交
510
        fprintf(stderr, "result 2: expected %s, got %s\n",
511
                NULLSTR(data->expResult), NULLSTR(result->path));
E
Eric Blake 已提交
512 513
        ret = -1;
    }
514
    if (data->expMeta != result) {
E
Eric Blake 已提交
515
        fprintf(stderr, "meta: expected %p, got %p\n",
516
                data->expMeta, result);
E
Eric Blake 已提交
517 518 519 520 521 522 523 524 525 526 527
        ret = -1;
    }
    if (STRNEQ_NULLABLE(data->expParent, actualParent)) {
        fprintf(stderr, "parent: expected %s, got %s\n",
                NULLSTR(data->expParent), NULLSTR(actualParent));
        ret = -1;
    }

    return ret;
}

528 529 530 531 532
static int
mymain(void)
{
    int ret;
    virCommandPtr cmd = NULL;
533
    struct testChainData data;
E
Eric Blake 已提交
534
    struct testLookupData data2;
535
    virStorageSourcePtr chain = NULL;
E
Eric Blake 已提交
536 537
    virStorageSourcePtr chain2; /* short for chain->backingStore */
    virStorageSourcePtr chain3; /* short for chain2->backingStore */
538 539 540 541 542 543

    /* Prep some files with qemu-img; if that is not found on PATH, or
     * if it lacks support for qcow2 and qed, skip this test.  */
    if ((ret = testPrepImages()) != 0)
        return ret;

544
#define TEST_ONE_CHAIN(id, start, format, flags, ...)                \
545
    do {                                                             \
546 547 548 549
        size_t i;                                                    \
        memset(&data, 0, sizeof(data));                              \
        data = (struct testChainData){                               \
            start, format, { __VA_ARGS__ }, 0, flags,                \
550
        };                                                           \
551 552 553
        for (i = 0; i < ARRAY_CARDINALITY(data.files); i++)          \
            if (data.files[i])                                       \
                data.nfiles++;                                       \
554
        if (virtTestRun("Storage backing chain " id,                 \
555 556 557 558
                        testStorageChain, &data) < 0)                \
            ret = -1;                                                \
    } while (0)

559 560 561
#define VIR_FLATTEN_2(...) __VA_ARGS__
#define VIR_FLATTEN_1(_1) VIR_FLATTEN_2 _1

562 563 564
#define TEST_CHAIN(id, relstart, absstart, format, chain1, flags1,   \
                   chain2, flags2, chain3, flags3, chain4, flags4)   \
    do {                                                             \
565 566 567 568
        TEST_ONE_CHAIN(#id "a", relstart, format, flags1,            \
                       VIR_FLATTEN_1(chain1));                       \
        TEST_ONE_CHAIN(#id "b", relstart, format, flags2,            \
                       VIR_FLATTEN_1(chain2));                       \
569
        TEST_ONE_CHAIN(#id "c", absstart, format, flags3 | ABS_START,\
570
                       VIR_FLATTEN_1(chain3));                       \
571
        TEST_ONE_CHAIN(#id "d", absstart, format, flags4 | ABS_START,\
572
                       VIR_FLATTEN_1(chain4));                       \
573 574 575 576 577
    } while (0)

    /* The actual tests, in several groups. */

    /* Missing file */
578
    TEST_ONE_CHAIN("0", "bogus", VIR_STORAGE_FILE_RAW, EXP_FAIL);
579 580

    /* Raw image, whether with right format or no specified format */
581
    testFileData raw = {
582 583
        .pathRel = "raw",
        .pathAbs = canonraw,
584
        .path = canonraw,
E
Eric Blake 已提交
585 586 587 588
        .relDirRel = ".",
        .relDirAbs = datadir,
        .type = VIR_STORAGE_TYPE_FILE,
        .format = VIR_STORAGE_FILE_RAW,
589
    };
590
    TEST_CHAIN(1, "raw", absraw, VIR_STORAGE_FILE_RAW,
591 592 593 594
               (&raw), EXP_PASS,
               (&raw), ALLOW_PROBE | EXP_PASS,
               (&raw), EXP_PASS,
               (&raw), ALLOW_PROBE | EXP_PASS);
595
    TEST_CHAIN(2, "raw", absraw, VIR_STORAGE_FILE_AUTO,
596 597 598 599
               (&raw), EXP_PASS,
               (&raw), ALLOW_PROBE | EXP_PASS,
               (&raw), EXP_PASS,
               (&raw), ALLOW_PROBE | EXP_PASS);
600 601

    /* Qcow2 file with relative raw backing, format provided */
602
    raw.pathAbs = "raw";
603
    testFileData qcow2 = {
604 605 606
        .expBackingStore = canonraw,
        .expBackingStoreRaw = "raw",
        .expCapacity = 1024,
607 608
        .pathRel = "qcow2",
        .pathAbs = canonqcow2,
609
        .path = canonqcow2,
E
Eric Blake 已提交
610 611 612 613
        .relDirRel = ".",
        .relDirAbs = datadir,
        .type = VIR_STORAGE_TYPE_FILE,
        .format = VIR_STORAGE_FILE_QCOW2,
614 615 616 617
    };
    testFileData qcow2_as_raw = {
        .pathRel = "qcow2",
        .pathAbs = canonqcow2,
618
        .path = canonqcow2,
E
Eric Blake 已提交
619 620 621 622
        .relDirRel = ".",
        .relDirAbs = datadir,
        .type = VIR_STORAGE_TYPE_FILE,
        .format = VIR_STORAGE_FILE_RAW,
623
    };
624
    TEST_CHAIN(3, "qcow2", absqcow2, VIR_STORAGE_FILE_QCOW2,
625 626 627 628
               (&qcow2, &raw), EXP_PASS,
               (&qcow2, &raw), ALLOW_PROBE | EXP_PASS,
               (&qcow2, &raw), EXP_PASS,
               (&qcow2, &raw), ALLOW_PROBE | EXP_PASS);
629
    TEST_CHAIN(4, "qcow2", absqcow2, VIR_STORAGE_FILE_AUTO,
630
               (&qcow2_as_raw), EXP_PASS,
631
               (&qcow2, &raw), ALLOW_PROBE | EXP_PASS,
632
               (&qcow2_as_raw), EXP_PASS,
633
               (&qcow2, &raw), ALLOW_PROBE | EXP_PASS);
634 635 636 637 638 639 640

    /* Rewrite qcow2 file to use absolute backing name */
    virCommandFree(cmd);
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
                               "-F", "raw", "-b", absraw, "qcow2", NULL);
    if (virCommandRun(cmd, NULL) < 0)
        ret = -1;
641
    qcow2.expBackingStoreRaw = absraw;
642 643
    raw.pathRel = absraw;
    raw.pathAbs = absraw;
E
Eric Blake 已提交
644
    raw.relDirRel = datadir;
645 646 647

    /* Qcow2 file with raw as absolute backing, backing format provided */
    TEST_CHAIN(5, "qcow2", absqcow2, VIR_STORAGE_FILE_QCOW2,
648 649 650 651
               (&qcow2, &raw), EXP_PASS,
               (&qcow2, &raw), ALLOW_PROBE | EXP_PASS,
               (&qcow2, &raw), EXP_PASS,
               (&qcow2, &raw), ALLOW_PROBE | EXP_PASS);
652
    TEST_CHAIN(6, "qcow2", absqcow2, VIR_STORAGE_FILE_AUTO,
653
               (&qcow2_as_raw), EXP_PASS,
654
               (&qcow2, &raw), ALLOW_PROBE | EXP_PASS,
655
               (&qcow2_as_raw), EXP_PASS,
656
               (&qcow2, &raw), ALLOW_PROBE | EXP_PASS);
657 658

    /* Wrapped file access */
659 660 661 662
    testFileData wrap = {
        .expBackingStore = canonqcow2,
        .expBackingStoreRaw = absqcow2,
        .expCapacity = 1024,
663 664
        .pathRel = "wrap",
        .pathAbs = abswrap,
665
        .path = canonwrap,
E
Eric Blake 已提交
666 667 668 669
        .relDirRel = ".",
        .relDirAbs = datadir,
        .type = VIR_STORAGE_TYPE_FILE,
        .format = VIR_STORAGE_FILE_QCOW2,
670
    };
671
    qcow2.pathRel = absqcow2;
E
Eric Blake 已提交
672
    qcow2.relDirRel = datadir;
673
    TEST_CHAIN(7, "wrap", abswrap, VIR_STORAGE_FILE_QCOW2,
674 675 676 677
               (&wrap, &qcow2, &raw), EXP_PASS,
               (&wrap, &qcow2, &raw), ALLOW_PROBE | EXP_PASS,
               (&wrap, &qcow2, &raw), EXP_PASS,
               (&wrap, &qcow2, &raw), ALLOW_PROBE | EXP_PASS);
678 679 680 681 682 683 684 685 686 687 688 689 690

    /* Rewrite qcow2 and wrap file to omit backing file type */
    virCommandFree(cmd);
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
                               "-b", absraw, "qcow2", NULL);
    if (virCommandRun(cmd, NULL) < 0)
        ret = -1;

    virCommandFree(cmd);
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
                               "-b", absqcow2, "wrap", NULL);
    if (virCommandRun(cmd, NULL) < 0)
        ret = -1;
691
    qcow2_as_raw.pathRel = absqcow2;
E
Eric Blake 已提交
692
    qcow2_as_raw.relDirRel = datadir;
693 694

    /* Qcow2 file with raw as absolute backing, backing format omitted */
695 696 697 698
    testFileData wrap_as_raw = {
        .expBackingStore = canonqcow2,
        .expBackingStoreRaw = absqcow2,
        .expCapacity = 1024,
699 700
        .pathRel = "wrap",
        .pathAbs = abswrap,
701
        .path = canonwrap,
E
Eric Blake 已提交
702 703 704 705
        .relDirRel = ".",
        .relDirAbs = datadir,
        .type = VIR_STORAGE_TYPE_FILE,
        .format = VIR_STORAGE_FILE_QCOW2,
706
    };
707
    TEST_CHAIN(8, "wrap", abswrap, VIR_STORAGE_FILE_QCOW2,
708
               (&wrap_as_raw, &qcow2_as_raw), EXP_PASS,
709
               (&wrap, &qcow2, &raw), ALLOW_PROBE | EXP_PASS,
710
               (&wrap_as_raw, &qcow2_as_raw), EXP_PASS,
711
               (&wrap, &qcow2, &raw), ALLOW_PROBE | EXP_PASS);
712 713 714 715 716 717 718 719

    /* Rewrite qcow2 to a missing backing file, with backing type */
    virCommandFree(cmd);
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
                               "-F", "qcow2", "-b", datadir "/bogus",
                               "qcow2", NULL);
    if (virCommandRun(cmd, NULL) < 0)
        ret = -1;
720 721
    qcow2.expBackingStore = NULL;
    qcow2.expBackingStoreRaw = datadir "/bogus";
722
    qcow2.pathRel = "qcow2";
E
Eric Blake 已提交
723
    qcow2.relDirRel = ".";
724 725 726

    /* Qcow2 file with missing backing file but specified type */
    TEST_CHAIN(9, "qcow2", absqcow2, VIR_STORAGE_FILE_QCOW2,
727 728 729 730
               (&qcow2), EXP_WARN,
               (&qcow2), ALLOW_PROBE | EXP_WARN,
               (&qcow2), EXP_WARN,
               (&qcow2), ALLOW_PROBE | EXP_WARN);
731 732 733 734 735 736 737 738 739 740

    /* Rewrite qcow2 to a missing backing file, without backing type */
    virCommandFree(cmd);
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
                               "-b", datadir "/bogus", "qcow2", NULL);
    if (virCommandRun(cmd, NULL) < 0)
        ret = -1;

    /* Qcow2 file with missing backing file and no specified type */
    TEST_CHAIN(10, "qcow2", absqcow2, VIR_STORAGE_FILE_QCOW2,
741 742 743 744
               (&qcow2), EXP_WARN,
               (&qcow2), ALLOW_PROBE | EXP_WARN,
               (&qcow2), EXP_WARN,
               (&qcow2), ALLOW_PROBE | EXP_WARN);
745 746 747 748

    /* Rewrite qcow2 to use an nbd: protocol as backend */
    virCommandFree(cmd);
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
749
                               "-F", "raw", "-b", "nbd:example.org:6000:exportname=blah",
750 751 752
                               "qcow2", NULL);
    if (virCommandRun(cmd, NULL) < 0)
        ret = -1;
753 754
    qcow2.expBackingStore = "blah";
    qcow2.expBackingStoreRaw = "nbd:example.org:6000:exportname=blah";
755 756

    /* Qcow2 file with backing protocol instead of file */
757
    testFileData nbd = {
758 759 760
        .pathRel = "nbd:example.org:6000:exportname=blah",
        .pathAbs = "nbd:example.org:6000:exportname=blah",
        .path = "blah",
761 762
        .type = VIR_STORAGE_TYPE_NETWORK,
        .format = VIR_STORAGE_FILE_RAW,
763 764
        .relDirRel = ".",
        .relDirAbs = ".",
765
    };
766
    TEST_CHAIN(11, "qcow2", absqcow2, VIR_STORAGE_FILE_QCOW2,
767 768 769 770
               (&qcow2, &nbd), EXP_PASS,
               (&qcow2, &nbd), ALLOW_PROBE | EXP_PASS,
               (&qcow2, &nbd), EXP_PASS,
               (&qcow2, &nbd), ALLOW_PROBE | EXP_PASS);
771 772

    /* qed file */
773 774 775 776
    testFileData qed = {
        .expBackingStore = canonraw,
        .expBackingStoreRaw = absraw,
        .expCapacity = 1024,
777 778
        .pathRel = "qed",
        .pathAbs = absqed,
779
        .path = canonqed,
E
Eric Blake 已提交
780 781 782 783
        .relDirRel = ".",
        .relDirAbs = datadir,
        .type = VIR_STORAGE_TYPE_FILE,
        .format = VIR_STORAGE_FILE_QED,
784 785 786 787
    };
    testFileData qed_as_raw = {
        .pathRel = "qed",
        .pathAbs = absqed,
788
        .path = canonqed,
E
Eric Blake 已提交
789 790 791 792
        .relDirRel = ".",
        .relDirAbs = datadir,
        .type = VIR_STORAGE_TYPE_FILE,
        .format = VIR_STORAGE_FILE_RAW,
793
    };
794
    TEST_CHAIN(12, "qed", absqed, VIR_STORAGE_FILE_AUTO,
795
               (&qed_as_raw), EXP_PASS,
796
               (&qed, &raw), ALLOW_PROBE | EXP_PASS,
797
               (&qed_as_raw), EXP_PASS,
798
               (&qed, &raw), ALLOW_PROBE | EXP_PASS);
799

E
Eric Blake 已提交
800
    /* directory */
801
    testFileData dir = {
802 803
        .pathRel = "dir",
        .pathAbs = absdir,
804 805 806
        .path = canondir,
        .relDirRel = ".",
        .relDirAbs = datadir,
E
Eric Blake 已提交
807 808
        .type = VIR_STORAGE_TYPE_DIR,
        .format = VIR_STORAGE_FILE_DIR,
809
    };
E
Eric Blake 已提交
810 811 812 813 814 815 816 817 818 819 820
    TEST_CHAIN(13, "dir", absdir, VIR_STORAGE_FILE_AUTO,
               (&dir), EXP_PASS,
               (&dir), ALLOW_PROBE | EXP_PASS,
               (&dir), EXP_PASS,
               (&dir), ALLOW_PROBE | EXP_PASS);
    TEST_CHAIN(14, "dir", absdir, VIR_STORAGE_FILE_DIR,
               (&dir), EXP_PASS,
               (&dir), ALLOW_PROBE | EXP_PASS,
               (&dir), EXP_PASS,
               (&dir), ALLOW_PROBE | EXP_PASS);

821
#ifdef HAVE_SYMLINK
822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837
    /* Rewrite qcow2 and wrap file to use backing names relative to a
     * symlink from a different directory */
    virCommandFree(cmd);
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
                               "-F", "raw", "-b", "../raw", "qcow2", NULL);
    if (virCommandRun(cmd, NULL) < 0)
        ret = -1;

    virCommandFree(cmd);
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
                               "-F", "qcow2", "-b", "../sub/link1", "wrap",
                               NULL);
    if (virCommandRun(cmd, NULL) < 0)
        ret = -1;

    /* Behavior of symlinks to qcow2 with relative backing files */
838
    testFileData link1 = {
839 840 841
        .expBackingStore = canonraw,
        .expBackingStoreRaw = "../raw",
        .expCapacity = 1024,
842 843
        .pathRel = "../sub/link1",
        .pathAbs = "../sub/link1",
844
        .path = canonqcow2,
E
Eric Blake 已提交
845 846 847 848
        .relDirRel = "sub/../sub",
        .relDirAbs = datadir "/sub/../sub",
        .type = VIR_STORAGE_TYPE_FILE,
        .format = VIR_STORAGE_FILE_QCOW2,
849
    };
850
    testFileData link2 = {
851 852 853
        .expBackingStore = canonqcow2,
        .expBackingStoreRaw = "../sub/link1",
        .expCapacity = 1024,
854 855
        .pathRel = "sub/link2",
        .pathAbs = abslink2,
856
        .path = canonwrap,
E
Eric Blake 已提交
857 858 859 860
        .relDirRel = "sub",
        .relDirAbs = datadir "/sub",
        .type = VIR_STORAGE_TYPE_FILE,
        .format = VIR_STORAGE_FILE_QCOW2,
861
    };
862 863
    raw.pathRel = "../raw";
    raw.pathAbs = "../raw";
E
Eric Blake 已提交
864 865
    raw.relDirRel = "sub/../sub/..";
    raw.relDirAbs = datadir "/sub/../sub/..";
E
Eric Blake 已提交
866
    TEST_CHAIN(15, "sub/link2", abslink2, VIR_STORAGE_FILE_QCOW2,
867 868 869 870
               (&link2, &link1, &raw), EXP_PASS,
               (&link2, &link1, &raw), ALLOW_PROBE | EXP_PASS,
               (&link2, &link1, &raw), EXP_PASS,
               (&link2, &link1, &raw), ALLOW_PROBE | EXP_PASS);
871
#endif
E
Eric Blake 已提交
872 873 874 875 876 877 878

    /* Rewrite qcow2 to be a self-referential loop */
    virCommandFree(cmd);
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
                               "-F", "qcow2", "-b", "qcow2", "qcow2", NULL);
    if (virCommandRun(cmd, NULL) < 0)
        ret = -1;
879 880
    qcow2.expBackingStore = NULL;
    qcow2.expBackingStoreRaw = "qcow2";
E
Eric Blake 已提交
881 882 883

    /* Behavior of an infinite loop chain */
    TEST_CHAIN(16, "qcow2", absqcow2, VIR_STORAGE_FILE_QCOW2,
884 885 886 887
               (&qcow2), EXP_WARN,
               (&qcow2), ALLOW_PROBE | EXP_WARN,
               (&qcow2), EXP_WARN,
               (&qcow2), ALLOW_PROBE | EXP_WARN);
E
Eric Blake 已提交
888 889 890 891 892 893 894 895 896 897 898 899 900

    /* Rewrite wrap and qcow2 to be mutually-referential loop */
    virCommandFree(cmd);
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
                               "-F", "qcow2", "-b", "wrap", "qcow2", NULL);
    if (virCommandRun(cmd, NULL) < 0)
        ret = -1;

    virCommandFree(cmd);
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
                               "-F", "qcow2", "-b", absqcow2, "wrap", NULL);
    if (virCommandRun(cmd, NULL) < 0)
        ret = -1;
901
    qcow2.expBackingStoreRaw = "wrap";
902
    qcow2.pathRel = absqcow2;
E
Eric Blake 已提交
903
    qcow2.relDirRel =  datadir;
E
Eric Blake 已提交
904 905 906

    /* Behavior of an infinite loop chain */
    TEST_CHAIN(17, "wrap", abswrap, VIR_STORAGE_FILE_QCOW2,
907 908 909 910
               (&wrap, &qcow2), EXP_WARN,
               (&wrap, &qcow2), ALLOW_PROBE | EXP_WARN,
               (&wrap, &qcow2), EXP_WARN,
               (&wrap, &qcow2), ALLOW_PROBE | EXP_WARN);
E
Eric Blake 已提交
911

E
Eric Blake 已提交
912 913 914 915 916 917 918
    /* Rewrite wrap and qcow2 back to 3-deep chain, absolute backing */
    virCommandFree(cmd);
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
                               "-F", "qcow2", "-b", absraw, "qcow2", NULL);
    if (virCommandRun(cmd, NULL) < 0)
        ret = -1;

919
    /* Test behavior of chain lookups, absolute backing from relative start */
920 921
    chain = testStorageFileGetMetadata("wrap", VIR_STORAGE_FILE_QCOW2,
                                       -1, -1, false);
E
Eric Blake 已提交
922 923 924 925
    if (!chain) {
        ret = -1;
        goto cleanup;
    }
E
Eric Blake 已提交
926 927
    chain2 = chain->backingStore;
    chain3 = chain2->backingStore;
E
Eric Blake 已提交
928

E
Eric Blake 已提交
929
#define TEST_LOOKUP_TARGET(id, target, from, name, index, result,       \
E
Eric Blake 已提交
930
                           meta, parent)                                \
E
Eric Blake 已提交
931 932 933 934 935 936 937
    do {                                                                \
        data2 = (struct testLookupData){                                \
            chain, target, from, name, index,                           \
            result, meta, parent, };                                    \
        if (virtTestRun("Chain lookup " #id,                            \
                        testStorageLookup, &data2) < 0)                 \
            ret = -1;                                                   \
E
Eric Blake 已提交
938
    } while (0)
E
Eric Blake 已提交
939 940 941 942
#define TEST_LOOKUP(id, from, name, result, meta, parent)               \
    TEST_LOOKUP_TARGET(id, NULL, from, name, 0, result, meta, parent)

    TEST_LOOKUP(0, NULL, "bogus", NULL, NULL, NULL);
E
Eric Blake 已提交
943
    TEST_LOOKUP(1, chain, "bogus", NULL, NULL, NULL);
E
Eric Blake 已提交
944
    TEST_LOOKUP(2, NULL, "wrap", chain->path, chain, NULL);
E
Eric Blake 已提交
945
    TEST_LOOKUP(3, chain, "wrap", NULL, NULL, NULL);
E
Eric Blake 已提交
946
    TEST_LOOKUP(4, chain2, "wrap", NULL, NULL, NULL);
E
Eric Blake 已提交
947
    TEST_LOOKUP(5, NULL, abswrap, chain->path, chain, NULL);
E
Eric Blake 已提交
948
    TEST_LOOKUP(6, chain, abswrap, NULL, NULL, NULL);
E
Eric Blake 已提交
949
    TEST_LOOKUP(7, chain2, abswrap, NULL, NULL, NULL);
E
Eric Blake 已提交
950
    TEST_LOOKUP(8, NULL, "qcow2", chain2->path, chain2, chain->path);
E
Eric Blake 已提交
951
    TEST_LOOKUP(9, chain, "qcow2", chain2->path, chain2, chain->path);
E
Eric Blake 已提交
952
    TEST_LOOKUP(10, chain2, "qcow2", NULL, NULL, NULL);
E
Eric Blake 已提交
953
    TEST_LOOKUP(11, chain3, "qcow2", NULL, NULL, NULL);
E
Eric Blake 已提交
954
    TEST_LOOKUP(12, NULL, absqcow2, chain2->path, chain2, chain->path);
E
Eric Blake 已提交
955
    TEST_LOOKUP(13, chain, absqcow2, chain2->path, chain2, chain->path);
E
Eric Blake 已提交
956
    TEST_LOOKUP(14, chain2, absqcow2, NULL, NULL, NULL);
E
Eric Blake 已提交
957
    TEST_LOOKUP(15, chain3, absqcow2, NULL, NULL, NULL);
E
Eric Blake 已提交
958
    TEST_LOOKUP(16, NULL, "raw", chain3->path, chain3, chain2->path);
E
Eric Blake 已提交
959 960
    TEST_LOOKUP(17, chain, "raw", chain3->path, chain3, chain2->path);
    TEST_LOOKUP(18, chain2, "raw", chain3->path, chain3, chain2->path);
E
Eric Blake 已提交
961
    TEST_LOOKUP(19, chain3, "raw", NULL, NULL, NULL);
E
Eric Blake 已提交
962
    TEST_LOOKUP(20, NULL, absraw, chain3->path, chain3, chain2->path);
E
Eric Blake 已提交
963 964
    TEST_LOOKUP(21, chain, absraw, chain3->path, chain3, chain2->path);
    TEST_LOOKUP(22, chain2, absraw, chain3->path, chain3, chain2->path);
E
Eric Blake 已提交
965
    TEST_LOOKUP(23, chain3, absraw, NULL, NULL, NULL);
E
Eric Blake 已提交
966
    TEST_LOOKUP(24, NULL, NULL, chain3->path, chain3, chain2->path);
E
Eric Blake 已提交
967 968
    TEST_LOOKUP(25, chain, NULL, chain3->path, chain3, chain2->path);
    TEST_LOOKUP(26, chain2, NULL, chain3->path, chain3, chain2->path);
E
Eric Blake 已提交
969
    TEST_LOOKUP(27, chain3, NULL, NULL, NULL, NULL);
E
Eric Blake 已提交
970 971 972 973 974 975 976 977 978 979 980 981 982 983

    /* Rewrite wrap and qcow2 back to 3-deep chain, relative backing */
    virCommandFree(cmd);
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
                               "-F", "raw", "-b", "raw", "qcow2", NULL);
    if (virCommandRun(cmd, NULL) < 0)
        ret = -1;

    virCommandFree(cmd);
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
                               "-F", "qcow2", "-b", "qcow2", "wrap", NULL);
    if (virCommandRun(cmd, NULL) < 0)
        ret = -1;

984
    /* Test behavior of chain lookups, relative backing from absolute start */
985
    virStorageSourceFree(chain);
986 987
    chain = testStorageFileGetMetadata(abswrap, VIR_STORAGE_FILE_QCOW2,
                                       -1, -1, false);
E
Eric Blake 已提交
988 989 990 991
    if (!chain) {
        ret = -1;
        goto cleanup;
    }
E
Eric Blake 已提交
992 993
    chain2 = chain->backingStore;
    chain3 = chain2->backingStore;
E
Eric Blake 已提交
994

E
Eric Blake 已提交
995
    TEST_LOOKUP(28, NULL, "bogus", NULL, NULL, NULL);
E
Eric Blake 已提交
996
    TEST_LOOKUP(29, chain, "bogus", NULL, NULL, NULL);
E
Eric Blake 已提交
997
    TEST_LOOKUP(30, NULL, "wrap", chain->path, chain, NULL);
E
Eric Blake 已提交
998
    TEST_LOOKUP(31, chain, "wrap", NULL, NULL, NULL);
E
Eric Blake 已提交
999
    TEST_LOOKUP(32, chain2, "wrap", NULL, NULL, NULL);
E
Eric Blake 已提交
1000
    TEST_LOOKUP(33, NULL, abswrap, chain->path, chain, NULL);
E
Eric Blake 已提交
1001
    TEST_LOOKUP(34, chain, abswrap, NULL, NULL, NULL);
E
Eric Blake 已提交
1002
    TEST_LOOKUP(35, chain2, abswrap, NULL, NULL, NULL);
E
Eric Blake 已提交
1003
    TEST_LOOKUP(36, NULL, "qcow2", chain2->path, chain2, chain->path);
E
Eric Blake 已提交
1004
    TEST_LOOKUP(37, chain, "qcow2", chain2->path, chain2, chain->path);
E
Eric Blake 已提交
1005
    TEST_LOOKUP(38, chain2, "qcow2", NULL, NULL, NULL);
E
Eric Blake 已提交
1006
    TEST_LOOKUP(39, chain3, "qcow2", NULL, NULL, NULL);
E
Eric Blake 已提交
1007
    TEST_LOOKUP(40, NULL, absqcow2, chain2->path, chain2, chain->path);
E
Eric Blake 已提交
1008
    TEST_LOOKUP(41, chain, absqcow2, chain2->path, chain2, chain->path);
E
Eric Blake 已提交
1009
    TEST_LOOKUP(42, chain2, absqcow2, NULL, NULL, NULL);
E
Eric Blake 已提交
1010
    TEST_LOOKUP(43, chain3, absqcow2, NULL, NULL, NULL);
E
Eric Blake 已提交
1011
    TEST_LOOKUP(44, NULL, "raw", chain3->path, chain3, chain2->path);
E
Eric Blake 已提交
1012 1013
    TEST_LOOKUP(45, chain, "raw", chain3->path, chain3, chain2->path);
    TEST_LOOKUP(46, chain2, "raw", chain3->path, chain3, chain2->path);
E
Eric Blake 已提交
1014
    TEST_LOOKUP(47, chain3, "raw", NULL, NULL, NULL);
E
Eric Blake 已提交
1015
    TEST_LOOKUP(48, NULL, absraw, chain3->path, chain3, chain2->path);
E
Eric Blake 已提交
1016 1017
    TEST_LOOKUP(49, chain, absraw, chain3->path, chain3, chain2->path);
    TEST_LOOKUP(50, chain2, absraw, chain3->path, chain3, chain2->path);
E
Eric Blake 已提交
1018
    TEST_LOOKUP(51, chain3, absraw, NULL, NULL, NULL);
E
Eric Blake 已提交
1019
    TEST_LOOKUP(52, NULL, NULL, chain3->path, chain3, chain2->path);
E
Eric Blake 已提交
1020 1021
    TEST_LOOKUP(53, chain, NULL, chain3->path, chain3, chain2->path);
    TEST_LOOKUP(54, chain2, NULL, chain3->path, chain3, chain2->path);
E
Eric Blake 已提交
1022
    TEST_LOOKUP(55, chain3, NULL, NULL, NULL, NULL);
E
Eric Blake 已提交
1023 1024 1025 1026 1027 1028 1029 1030 1031

    /* Use link to wrap with cross-directory relative backing */
    virCommandFree(cmd);
    cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2",
                               "-F", "qcow2", "-b", "../qcow2", "wrap", NULL);
    if (virCommandRun(cmd, NULL) < 0)
        ret = -1;

    /* Test behavior of chain lookups, relative backing */
1032
    virStorageSourceFree(chain);
1033 1034
    chain = testStorageFileGetMetadata("sub/link2", VIR_STORAGE_FILE_QCOW2,
                                       -1, -1, false);
E
Eric Blake 已提交
1035 1036 1037 1038
    if (!chain) {
        ret = -1;
        goto cleanup;
    }
E
Eric Blake 已提交
1039 1040
    chain2 = chain->backingStore;
    chain3 = chain2->backingStore;
E
Eric Blake 已提交
1041

E
Eric Blake 已提交
1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056
    TEST_LOOKUP(56, NULL, "bogus", NULL, NULL, NULL);
    TEST_LOOKUP(57, NULL, "sub/link2", chain->path, chain, NULL);
    TEST_LOOKUP(58, NULL, "wrap", chain->path, chain, NULL);
    TEST_LOOKUP(59, NULL, abswrap, chain->path, chain, NULL);
    TEST_LOOKUP(60, NULL, "../qcow2", chain2->path, chain2, chain->path);
    TEST_LOOKUP(61, NULL, "qcow2", NULL, NULL, NULL);
    TEST_LOOKUP(62, NULL, absqcow2, chain2->path, chain2, chain->path);
    TEST_LOOKUP(63, NULL, "raw", chain3->path, chain3, chain2->path);
    TEST_LOOKUP(64, NULL, absraw, chain3->path, chain3, chain2->path);
    TEST_LOOKUP(65, NULL, NULL, chain3->path, chain3, chain2->path);

    TEST_LOOKUP_TARGET(66, "vda", NULL, "bogus[1]", 0, NULL, NULL, NULL);
    TEST_LOOKUP_TARGET(67, "vda", NULL, "vda[-1]", 0, NULL, NULL, NULL);
    TEST_LOOKUP_TARGET(68, "vda", NULL, "vda[1][1]", 0, NULL, NULL, NULL);
    TEST_LOOKUP_TARGET(69, "vda", NULL, "wrap", 0, chain->path, chain, NULL);
E
Eric Blake 已提交
1057
    TEST_LOOKUP_TARGET(70, "vda", chain, "wrap", 0, NULL, NULL, NULL);
E
Eric Blake 已提交
1058
    TEST_LOOKUP_TARGET(71, "vda", chain2, "wrap", 0, NULL, NULL, NULL);
E
Eric Blake 已提交
1059 1060
    TEST_LOOKUP_TARGET(72, "vda", NULL, "vda[0]", 0, NULL, NULL, NULL);
    TEST_LOOKUP_TARGET(73, "vda", NULL, "vda[1]", 1, chain2->path, chain2,
1061
                       chain->path);
E
Eric Blake 已提交
1062 1063
    TEST_LOOKUP_TARGET(74, "vda", chain, "vda[1]", 1, chain2->path, chain2,
                       chain->path);
E
Eric Blake 已提交
1064
    TEST_LOOKUP_TARGET(75, "vda", chain2, "vda[1]", 1, NULL, NULL, NULL);
E
Eric Blake 已提交
1065
    TEST_LOOKUP_TARGET(76, "vda", chain3, "vda[1]", 1, NULL, NULL, NULL);
E
Eric Blake 已提交
1066
    TEST_LOOKUP_TARGET(77, "vda", NULL, "vda[2]", 2, chain3->path, chain3,
E
Eric Blake 已提交
1067
                       chain2->path);
E
Eric Blake 已提交
1068 1069 1070 1071
    TEST_LOOKUP_TARGET(78, "vda", chain, "vda[2]", 2, chain3->path, chain3,
                       chain2->path);
    TEST_LOOKUP_TARGET(79, "vda", chain2, "vda[2]", 2, chain3->path, chain3,
                       chain2->path);
E
Eric Blake 已提交
1072
    TEST_LOOKUP_TARGET(80, "vda", chain3, "vda[2]", 2, NULL, NULL, NULL);
E
Eric Blake 已提交
1073
    TEST_LOOKUP_TARGET(81, "vda", NULL, "vda[3]", 3, NULL, NULL, NULL);
1074

E
Eric Blake 已提交
1075
 cleanup:
1076
    /* Final cleanup */
1077
    virStorageSourceFree(chain);
1078 1079 1080 1081 1082 1083 1084
    testCleanupImages();
    virCommandFree(cmd);

    return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}

VIRT_TEST_MAIN(mymain)