Il 29/01/2013 05:51, Wenchao Xia ha scritto:
>   In this example, first it will create some qcow2 images, then try get
> information including backing file relationship, then it will do sync IO on
> the image.
> 
> Signed-off-by: Wenchao Xia <xiaw...@linux.vnet.ibm.com>

Patch 8 alone won't compile.  This line:

+check-libqblock-$(CONFIG_LIBQBLOCK) = tests/check-libqblock-qcow2$(EXESUF)

has to be moved to this patch.

Please do this instead:

# in patch 9
check-libqblock-y = tests/check-libqblock-qcow2$(EXESUF)
...
# in patch 8
check-unit-$(CONFIG_LIBQBLOCK) += $(check-libqblock-y)

Paolo

> ---
>  tests/check-libqblock-qcow2.c |  392 
> +++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 392 insertions(+), 0 deletions(-)
>  create mode 100644 tests/check-libqblock-qcow2.c
> 
> diff --git a/tests/check-libqblock-qcow2.c b/tests/check-libqblock-qcow2.c
> new file mode 100644
> index 0000000..0cbe8da
> --- /dev/null
> +++ b/tests/check-libqblock-qcow2.c
> @@ -0,0 +1,392 @@
> +/*
> + * QEMU block layer library test
> + *
> + * Copyright IBM, Corp. 2013
> + *
> + * Authors:
> + *  Wenchao Xia   <xiaw...@linux.vnet.ibm.com>
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2 or later.
> + * See the COPYING.LIB file in the top-level directory.
> + *
> + * Limitation:
> + *    1 filename do not support relative path, to save trouble in creating
> + * backing files.
> + */
> +
> +#include <glib.h>
> +#include <stdarg.h>
> +#include <stdio.h>
> +#include <unistd.h>
> +#include <inttypes.h>
> +#include <string.h>
> +#include <stdlib.h>
> +#include <sys/stat.h>
> +#include <sys/types.h>
> +
> +
> +#include "libqblock.h"
> +#include "libqtest.h"
> +
> +#define LIBQB_TEST_ENV_DIR "LIBQBLOCK_TEST_DIR"
> +#define LIBQB_TEST_DEFAULT_DIR "/tmp"
> +#define LIBQB_TEST_DEFAULT_FILENAME "libqblock_qcow2_test_img"
> +
> +typedef struct LibqbTestSettings {
> +    const char *image_filename;
> +    uint64_t image_size;
> +    unsigned int num_backings;
> +    unsigned int io_buf_size;
> +    uint64_t io_offset;
> +    int print_flag;
> +} LibqbTestSettings;
> +
> +LibqbTestSettings libqb_test_settings;
> +
> +static void print_loc(const QBlockLocationInfo *loc)
> +{
> +    if (loc == NULL) {
> +        printf("loc is NULL.");
> +        return;
> +    }
> +    switch (loc->prot_type) {
> +    case QB_PROTO_NONE:
> +        printf("protocol type [none].");
> +        break;
> +    case QB_PROTO_FILE:
> +        printf("protocol type [file], filename [%s].",
> +               loc->o_file.filename);
> +        break;
> +    default:
> +        printf("protocol type not supported.");
> +        break;
> +    }
> +}
> +
> +static void print_info_image_static(QBlockStaticInfo *info)
> +{
> +    const uint64_t *virt_size = qb_get_virt_size(info);
> +    const QBlockLocationInfo *backing_loc = qb_get_backing_loc(info);
> +    g_assert(virt_size != NULL);
> +
> +    printf("=======image location:\n");
> +    print_loc(&info->loc);
> +    printf("\nvirtual_size %" PRId64 ", format type %d [%s]",
> +           *(virt_size),
> +           info->fmt.fmt_type, qb_fmttype2str(info->fmt.fmt_type));
> +    printf("\nbacking image location:\n");
> +    print_loc(backing_loc);
> +    printf("\n");
> +}
> +
> +static char *generate_backing_filename(const char *filename, int index)
> +{
> +    char *backing_filename = NULL;
> +
> +    backing_filename = g_strdup_printf("%s_backing_%d", filename, index);
> +    return backing_filename;
> +}
> +
> +/* get filename in a full path */
> +static const char *get_filename(const char *path)
> +{
> +    const char *filename;
> +    filename = strrchr(path, '/');
> +    if (filename == NULL) {
> +        filename = path;
> +    } else {
> +        filename++;
> +    }
> +    return filename;
> +}
> +
> +/* create a chain of files, num_backings must >= 0. */
> +static void files_create_qcow2(const char *filename,
> +                               int num_backings,
> +                               uint64_t virt_size)
> +{
> +    QBlockContext *context = NULL;
> +    QBlockImage *qbi = NULL;
> +    QBlockLocationInfo *loc_info = NULL;
> +    QBlockFormatInfo *fmt_info = NULL;
> +    int ret;
> +    int index;
> +    int flag;
> +    char *backing_filename = NULL, *new_filename = NULL;
> +    const char *relative_filename = NULL;
> +
> +    ret = qb_context_new(&context);
> +    g_assert(ret == 0);
> +
> +    ret = qb_image_new(context, &qbi);
> +    g_assert(ret == 0);
> +
> +    ret = qb_loc_info_new(context, &loc_info);
> +    g_assert(ret == 0);
> +
> +    ret = qb_fmt_info_new(context, &fmt_info);
> +    g_assert(ret == 0);
> +
> +    loc_info->prot_type = QB_PROTO_FILE;
> +    fmt_info->fmt_type = QB_FMT_QCOW2;
> +    fmt_info->virt_size = virt_size;
> +    flag = 0;
> +
> +    index = 0;
> +    while (index < num_backings) {
> +        new_filename = generate_backing_filename(filename, index);
> +        loc_info->o_file.filename = new_filename;
> +        if (backing_filename != NULL) {
> +            fmt_info->o_qcow2.backing_loc.prot_type = QB_PROTO_FILE;
> +            relative_filename = get_filename(backing_filename);
> +            fmt_info->o_qcow2.backing_loc.o_file.filename =
> +                                                             
> relative_filename;
> +        }
> +        ret = qb_create(context, qbi, loc_info, fmt_info, flag);
> +        g_assert(ret == 0);
> +        free(backing_filename);
> +        backing_filename = new_filename;
> +        new_filename = NULL;
> +        index++;
> +    }
> +
> +    loc_info->o_file.filename = filename;
> +    if (backing_filename != NULL) {
> +        fmt_info->o_qcow2.backing_loc.prot_type = QB_PROTO_FILE;
> +        relative_filename = get_filename(backing_filename);
> +        fmt_info->o_qcow2.backing_loc.o_file.filename =
> +                                                         relative_filename;
> +    }
> +    ret = qb_create(context, qbi, loc_info, fmt_info, flag);
> +    g_assert(ret == 0);
> +    free(backing_filename);
> +
> +    qb_fmt_info_delete(context, &fmt_info);
> +    qb_loc_info_delete(context, &loc_info);
> +    qb_image_unref(context, &qbi);
> +    qb_context_delete(&context);
> +    return;
> +}
> +
> +static void files_delete(const char *filename,
> +                         int num_backings,
> +                         uint64_t virt_size)
> +{
> +    char *new_filename = NULL;
> +    int index = 0;
> +    while (index < num_backings) {
> +        new_filename = generate_backing_filename(filename, index);
> +        unlink(new_filename);
> +        free(new_filename);
> +        index++;
> +    }
> +    unlink(filename);
> +}
> +
> +static void testcase_info_image_static(void)
> +{
> +    const char *filename = libqb_test_settings.image_filename;
> +    uint64_t image_size = libqb_test_settings.image_size;
> +    int num_backings = libqb_test_settings.num_backings;
> +    QBlockContext *context = NULL;
> +    QBlockImage *qbi = NULL;
> +    QBlockLocationInfo *loc_info = NULL;
> +    int ret, flag;
> +    QBlockStaticInfo *info_st = NULL;
> +    int i;
> +    char *backing_filename = NULL;
> +    const uint64_t *virt_size = NULL;
> +    const QBlockLocationInfo *backing_loc = NULL;
> +
> +    ret = qb_context_new(&context);
> +    g_assert(ret == 0);
> +
> +    ret = qb_image_new(context, &qbi);
> +    g_assert(ret == 0);
> +
> +    ret = qb_loc_info_new(context, &loc_info);
> +    g_assert(ret == 0);
> +
> +    loc_info->prot_type = QB_PROTO_FILE;
> +    loc_info->o_file.filename = filename;
> +    flag = LIBQBLOCK_O_NO_BACKING;
> +    ret = qb_open(context, qbi, loc_info, NULL, flag);
> +    g_assert(ret == 0);
> +
> +    i = num_backings - 1;
> +    while (1) {
> +        ret = qb_info_image_static_get(context, qbi, &info_st);
> +        g_assert(ret == 0);
> +        if (libqb_test_settings.print_flag > 0) {
> +            print_info_image_static(info_st);
> +        }
> +        qb_close(context, qbi);
> +
> +        /* checking the information */
> +        g_assert(info_st->loc.prot_type == loc_info->prot_type);
> +        ret = strcmp(info_st->loc.o_file.filename,
> +                     loc_info->o_file.filename);
> +
> +        g_assert(ret == 0);
> +        g_assert(info_st->fmt.fmt_type == QB_FMT_QCOW2);
> +        virt_size = qb_get_virt_size(info_st);
> +        g_assert(virt_size != NULL);
> +        g_assert(*virt_size == image_size);
> +        backing_loc = qb_get_backing_loc(info_st);
> +        /* qcow2 have always backing file property */
> +        g_assert(backing_loc != NULL);
> +        if (i >= 0) {
> +            /* it should have backing file */
> +            g_assert(backing_loc->prot_type == QB_PROTO_FILE);
> +            backing_filename = generate_backing_filename(filename, i);
> +            ret = strcmp(backing_filename, backing_loc->o_file.filename);
> +            g_assert(ret == 0);
> +            g_free(backing_filename);
> +        } else {
> +            g_assert(backing_loc->prot_type == QB_FMT_NONE);
> +        }
> +        i--;
> +        /* see if there is backing file need to check. */
> +        if (backing_loc->prot_type == QB_FMT_NONE) {
> +            g_assert(i < 0);
> +            break;
> +        }
> +        qb_loc_info_delete(context, &loc_info);
> +        loc_info = qb_loc_info_dup(backing_loc);
> +        ret = qb_open(context, qbi, loc_info, NULL, flag);
> +        g_assert(ret == 0);
> +        qb_info_image_static_delete(context, &info_st);
> +    }
> +    qb_info_image_static_delete(context, &info_st);
> +
> +    qb_loc_info_delete(context, &loc_info);
> +    qb_image_unref(context, &qbi);
> +    qb_context_delete(&context);
> +    return;
> +}
> +
> +/* assuming the image is new created */
> +static void testcase_sync_io(void)
> +{
> +    const char *filename = libqb_test_settings.image_filename;
> +    uint64_t io_buf_size = libqb_test_settings.io_buf_size;
> +    uint64_t io_offset = libqb_test_settings.io_offset;;
> +    unsigned char *buf_r, *buf_w;
> +    uint64_t i;
> +    unsigned int rand_value;
> +
> +    buf_r = g_malloc0(io_buf_size);
> +    buf_w = g_malloc0(io_buf_size);
> +    for (i = 0; i < io_buf_size; i++) {
> +        rand_value = g_test_rand_int_range(0, 255);
> +        buf_w[i] = (unsigned char)rand_value;
> +    }
> +
> +    QBlockContext *context = NULL;
> +    QBlockImage *qbi = NULL;
> +    QBlockLocationInfo *loc_info = NULL;
> +    int ret, flag;
> +
> +    ret = qb_context_new(&context);
> +    g_assert(ret == 0);
> +
> +    ret = qb_image_new(context, &qbi);
> +    g_assert(ret == 0);
> +
> +    ret = qb_loc_info_new(context, &loc_info);
> +    g_assert(ret == 0);
> +
> +
> +    loc_info->prot_type = QB_PROTO_FILE;
> +    loc_info->o_file.filename = filename;
> +    flag = LIBQBLOCK_O_RDWR;
> +    ret = qb_open(context, qbi, loc_info, NULL, flag);
> +    g_assert(ret == 0);
> +
> +    int status;
> +    int64_t len;
> +    ret = qb_check_allocation(context, qbi, io_offset, io_buf_size,
> +                                       &status, &len);
> +    g_assert(ret == 0);
> +    g_assert(status == 0);
> +    g_assert(len == io_buf_size);
> +
> +    ret = qb_write(context, qbi, buf_w, io_buf_size, io_offset);
> +    g_assert(ret == io_buf_size);
> +
> +    ret = qb_read(context, qbi, buf_r, io_buf_size, io_offset);
> +    g_assert(ret == io_buf_size);
> +
> +    int cmp = memcmp(buf_r, buf_w, io_buf_size);
> +    g_assert(cmp == 0);
> +
> +    ret = qb_check_allocation(context, qbi, io_offset, io_buf_size,
> +                                       &status, &len);
> +    g_assert(ret == 0);
> +    g_assert(status == 1);
> +    g_assert(len == io_buf_size);
> +
> +    qb_close(context, qbi);
> +
> +    qb_loc_info_delete(context, &loc_info);
> +    qb_image_unref(context, &qbi);
> +    qb_context_delete(&context);
> +    g_free(buf_r);
> +    g_free(buf_w);
> +    return;
> +}
> +
> +int main(int argc, char **argv)
> +{
> +    const char *root_dir;
> +    const char *name = LIBQB_TEST_DEFAULT_FILENAME;
> +    int ret;
> +    int dir_created = 0;
> +    char *filename;
> +
> +    root_dir = getenv(LIBQB_TEST_ENV_DIR);
> +    if (root_dir == NULL) {
> +        root_dir = LIBQB_TEST_DEFAULT_DIR;
> +    }
> +
> +    ret = access(root_dir, F_OK);
> +    if (ret != 0) {
> +        /* try mkdir */
> +        ret = mkdir(root_dir, 0755);
> +        g_assert(ret == 0);
> +        dir_created = 1;
> +    }
> +
> +    filename = g_strdup_printf("%s/%s", root_dir, name);
> +
> +    g_test_init(&argc, &argv, NULL);
> +    g_test_rand_int();
> +
> +    libqb_test_settings.image_filename = filename;
> +    libqb_test_settings.image_size =
> +                            1024 * 1024 * g_test_rand_int_range(1, 1024);
> +    libqb_test_settings.num_backings = g_test_rand_int_range(0, 10);
> +    libqb_test_settings.io_buf_size = g_test_rand_int_range(1, 1024 * 1024);
> +    libqb_test_settings.io_offset = g_test_rand_int_range(0,
> +            libqb_test_settings.image_size - 
> libqb_test_settings.io_buf_size);
> +
> +    files_create_qcow2(libqb_test_settings.image_filename,
> +                       libqb_test_settings.num_backings,
> +                       libqb_test_settings.image_size);
> +
> +    g_test_add_func("/libqblock/sync_info_image_static",
> +                      testcase_info_image_static);
> +    g_test_add_func("/libqblock/sync_io", testcase_sync_io);
> +
> +    ret = g_test_run();
> +    files_delete(libqb_test_settings.image_filename,
> +                 libqb_test_settings.num_backings,
> +                 libqb_test_settings.image_size);
> +
> +    g_free(filename);
> +    if (dir_created) {
> +        ret = rmdir(root_dir);
> +        g_assert(ret == 0);
> +    }
> +    return ret;
> +}
> 


Reply via email to