[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH V16 9/9] libqblock: test: libqblock test example
From: |
Paolo Bonzini |
Subject: |
Re: [Qemu-devel] [PATCH V16 9/9] libqblock: test: libqblock test example |
Date: |
Tue, 29 Jan 2013 13:46:54 +0100 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130110 Thunderbird/17.0.2 |
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 <address@hidden>
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 <address@hidden>
> + *
> + * 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;
> +}
>
- [Qemu-devel] [PATCH V16 2/9] libqblock: build: add configure support, (continued)
- [Qemu-devel] [PATCH V16 2/9] libqblock: build: add configure support, Wenchao Xia, 2013/01/28
- [Qemu-devel] [PATCH V16 3/9] libqblock: build: add rule for libqblock.la, Wenchao Xia, 2013/01/28
- [Qemu-devel] [PATCH V16 4/9] libqblock: build: add packaging support, Wenchao Xia, 2013/01/28
- [Qemu-devel] [PATCH V16 5/9] block: export function path_has_protocol(), Wenchao Xia, 2013/01/28
- [Qemu-devel] [PATCH V16 7/9] libqblock: libqblock API implement, Wenchao Xia, 2013/01/28
- [Qemu-devel] [PATCH V16 8/9] libqblock: build: add rules for test case, Wenchao Xia, 2013/01/28
- [Qemu-devel] [PATCH V16 9/9] libqblock: test: libqblock test example, Wenchao Xia, 2013/01/28
- Re: [Qemu-devel] [PATCH V16 9/9] libqblock: test: libqblock test example,
Paolo Bonzini <=
- [Qemu-devel] [PATCH V16 6/9] libqblock: libqblock API design and type defines, Wenchao Xia, 2013/01/28
- Re: [Qemu-devel] [PATCH V16 0/9] libqblock qemu block layer library, Anthony Liguori, 2013/01/29