[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH V4 5/5] libqblock test example
From: |
Wenchao Xia |
Subject: |
[Qemu-devel] [PATCH V4 5/5] libqblock test example |
Date: |
Thu, 27 Sep 2012 10:24:02 +0800 |
In this example, at first it will create some qcow2 images, then get
information including backing file relationship. Then it will do sync IO on
the image.
Signed-off-by: Wenchao Xia <address@hidden>
---
tests/libqblock/libqblock-qcow2.c | 366 ++++++++++++++++++++++++++++++++++++-
1 files changed, 365 insertions(+), 1 deletions(-)
diff --git a/tests/libqblock/libqblock-qcow2.c
b/tests/libqblock/libqblock-qcow2.c
index c05c0c4..7985cb6 100644
--- a/tests/libqblock/libqblock-qcow2.c
+++ b/tests/libqblock/libqblock-qcow2.c
@@ -1,4 +1,368 @@
+/*
+ * QEMU block layer library test
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * 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 "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(QBlockProtInfo *loc)
+{
+ if (loc == NULL) {
+ printf("backing file is NULL.");
+ return;
+ }
+ switch (loc->prot_type) {
+ case QB_PROT_NONE:
+ printf("protocol type [none].");
+ break;
+ case QB_PROT_FILE:
+ printf("protocol type [file], filename [%s].",
+ loc->prot_op.o_file.filename);
+ break;
+ default:
+ printf("protocol type not supported.");
+ break;
+ }
+}
+
+static void print_info_image_static(QBlockStaticInfo *info)
+{
+ printf("=======image location:\n");
+ print_loc(&info->loc);
+ printf("\nvirtual_size %" PRId64 ", format type %d [%s]",
+ *(info->member_addr->virt_size),
+ info->fmt.fmt_type, qb_fmttype2str(info->fmt.fmt_type));
+ printf("\nbacking image location:\n");
+ print_loc(info->member_addr->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;
+ QBlockState *qbs = NULL;
+ QBlockProtInfo *prot_info = NULL;
+ QBlockFmtInfo *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_state_new(context, &qbs);
+ g_assert(ret == 0);
+
+ ret = qb_prot_info_new(context, &prot_info);
+ g_assert(ret == 0);
+
+ ret = qb_fmt_info_new(context, &fmt_info);
+ g_assert(ret == 0);
+
+ prot_info->prot_type = QB_PROT_FILE;
+ fmt_info->fmt_type = QB_FMT_QCOW2;
+ fmt_info->fmt_op.o_qcow2.virt_size = virt_size;
+ flag = 0;
+
+ index = 0;
+ while (index < num_backings) {
+ new_filename = generate_backing_filename(filename, index);
+ prot_info->prot_op.o_file.filename = new_filename;
+ if (backing_filename != NULL) {
+ fmt_info->fmt_op.o_qcow2.backing_loc.prot_type = QB_PROT_FILE;
+ relative_filename = get_filename(backing_filename);
+ fmt_info->fmt_op.o_qcow2.backing_loc.prot_op.o_file.filename =
+ relative_filename;
+ }
+ ret = qb_create(context, qbs, prot_info, fmt_info, flag);
+ g_assert(ret == 0);
+ free(backing_filename);
+ backing_filename = new_filename;
+ new_filename = NULL;
+ index++;
+ }
+
+ prot_info->prot_op.o_file.filename = filename;
+ if (backing_filename != NULL) {
+ fmt_info->fmt_op.o_qcow2.backing_loc.prot_type = QB_PROT_FILE;
+ relative_filename = get_filename(backing_filename);
+ fmt_info->fmt_op.o_qcow2.backing_loc.prot_op.o_file.filename =
+ relative_filename;
+ }
+ ret = qb_create(context, qbs, prot_info, fmt_info, flag);
+ g_assert(ret == 0);
+ free(backing_filename);
+
+ qb_fmt_info_delete(context, &fmt_info);
+ qb_prot_info_delete(context, &prot_info);
+ qb_state_delete(context, &qbs);
+ 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;
+ QBlockState *qbs = NULL;
+ QBlockProtInfo *prot_info = NULL;
+ int ret, flag;
+ QBlockStaticInfo *info_st = NULL;
+ int i;
+ char *backing_filename = NULL;
+
+ ret = qb_context_new(&context);
+ g_assert(ret == 0);
+
+ ret = qb_state_new(context, &qbs);
+ g_assert(ret == 0);
+
+ ret = qb_prot_info_new(context, &prot_info);
+ g_assert(ret == 0);
+
+ prot_info->prot_type = QB_PROT_FILE;
+ prot_info->prot_op.o_file.filename = filename;
+ flag = LIBQBLOCK_O_NO_BACKING;
+ ret = qb_open(context, qbs, prot_info, NULL, flag);
+ g_assert(ret == 0);
+
+ i = num_backings - 1;
+ while (1) {
+ ret = qb_info_image_static_get(context, qbs, &info_st);
+ g_assert(ret == 0);
+ if (libqb_test_settings.print_flag > 0) {
+ print_info_image_static(info_st);
+ }
+ qb_close(context, qbs);
+
+ /* checking the information */
+ g_assert(info_st->loc.prot_type == prot_info->prot_type);
+ ret = strcmp(info_st->loc.prot_op.o_file.filename,
+ prot_info->prot_op.o_file.filename);
+
+ g_assert(ret == 0);
+ g_assert(info_st->fmt.fmt_type == QB_FMT_QCOW2);
+ g_assert(*(info_st->member_addr->virt_size) == image_size);
+ if (i >= 0) {
+ /* it should have backing file */
+ g_assert(info_st->member_addr->backing_loc->prot_type ==
+ QB_PROT_FILE);
+ backing_filename = generate_backing_filename(filename, i);
+ ret = strcmp(backing_filename,
+ info_st->member_addr->backing_loc->prot_op.o_file.filename);
+ g_assert(ret == 0);
+ g_free(backing_filename);
+ } else {
+ g_assert(info_st->member_addr->backing_loc->prot_type ==
+ QB_FMT_NONE);
+ }
+ i--;
+ /* see if there is backing file need to check. */
+ if ((info_st->member_addr->backing_loc == NULL) ||
+ (info_st->member_addr->backing_loc->prot_type == QB_FMT_NONE)) {
+ break;
+ }
+ qb_prot_info_delete(context, &prot_info);
+ prot_info = qb_prot_info_dup(info_st->member_addr->backing_loc);
+ ret = qb_open(context, qbs, prot_info, NULL, flag);
+ g_assert(ret == 0);
+ qb_info_image_static_delete(context, &info_st);
+ }
+ qb_info_image_static_delete(context, &info_st);
+
+ qb_prot_info_delete(context, &prot_info);
+ qb_state_delete(context, &qbs);
+ 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;
+ QBlockState *qbs = NULL;
+ QBlockProtInfo *prot_info = NULL;
+ int ret, flag;
+
+ ret = qb_context_new(&context);
+ g_assert(ret == 0);
+
+ ret = qb_state_new(context, &qbs);
+ g_assert(ret == 0);
+
+ ret = qb_prot_info_new(context, &prot_info);
+ g_assert(ret == 0);
+
+
+ prot_info->prot_type = QB_PROT_FILE;
+ prot_info->prot_op.o_file.filename = filename;
+ flag = LIBQBLOCK_O_RDWR;
+ ret = qb_open(context, qbs, prot_info, NULL, flag);
+ g_assert(ret == 0);
+
+ int status;
+ int64_t len;
+ ret = qb_check_allocation(context, qbs, 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, qbs, buf_w, io_buf_size, io_offset);
+ g_assert(ret == io_buf_size);
+
+ ret = qb_read(context, qbs, 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, qbs, io_offset, io_buf_size,
+ &status, &len);
+ g_assert(ret == 0);
+ g_assert(status == 1);
+ g_assert(len == io_buf_size);
+
+ qb_close(context, qbs);
+
+ qb_prot_info_delete(context, &prot_info);
+ qb_state_delete(context, &qbs);
+ qb_context_delete(&context);
+ g_free(buf_r);
+ g_free(buf_w);
+ return;
+}
+
int main(int argc, char **argv)
{
- return 0;
+ const char *root_dir;
+ const char *name = LIBQB_TEST_DEFAULT_FILENAME;
+ int ret;
+ char *filename;
+
+ root_dir = getenv(LIBQB_TEST_ENV_DIR);
+ if (root_dir == NULL) {
+ root_dir = LIBQB_TEST_DEFAULT_DIR;
+ }
+
+ 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);
+ return ret;
}
--
1.7.1
- Re: [Qemu-devel] [PATCH V4 2/5] libqblock type defines, (continued)
[Qemu-devel] [PATCH V4 4/5] libqblock test build system, Wenchao Xia, 2012/09/26
- Re: [Qemu-devel] [PATCH V4 4/5] libqblock test build system, Paolo Bonzini, 2012/09/27
- Re: [Qemu-devel] [PATCH V4 4/5] libqblock test build system, Wenchao Xia, 2012/09/27
- Re: [Qemu-devel] [PATCH V4 4/5] libqblock test build system, Paolo Bonzini, 2012/09/27
- Re: [Qemu-devel] [PATCH V4 4/5] libqblock test build system, Wenchao Xia, 2012/09/27
- Re: [Qemu-devel] [PATCH V4 4/5] libqblock test build system, Paolo Bonzini, 2012/09/28
- Re: [Qemu-devel] [PATCH V4 4/5] libqblock test build system, Wenchao Xia, 2012/09/28
[Qemu-devel] [PATCH V4 5/5] libqblock test example,
Wenchao Xia <=
[Qemu-devel] [PATCH V4 3/5] libqblock API, Wenchao Xia, 2012/09/26