qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org
Cc: kwolf@redhat.com, aliguori@us.ibm.com, stefanha@gmail.com,
	blauwirbel@gmail.com, pbonzini@redhat.com, eblake@redhat.com,
	Wenchao Xia <xiawenc@linux.vnet.ibm.com>
Subject: [Qemu-devel] [PATCH V4 5/5] libqblock test example
Date: Thu, 27 Sep 2012 10:24:02 +0800	[thread overview]
Message-ID: <1348712642-4427-6-git-send-email-xiawenc@linux.vnet.ibm.com> (raw)
In-Reply-To: <1348712642-4427-1-git-send-email-xiawenc@linux.vnet.ibm.com>

  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 <xiawenc@linux.vnet.ibm.com>
---
 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   <xiawenc@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 "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

      parent reply	other threads:[~2012-09-27  2:24 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-27  2:23 [Qemu-devel] [PATCH V4 0/5] libqblock qemu block layer library Wenchao Xia
2012-09-27  2:23 ` [Qemu-devel] [PATCH V4 1/5] libqblock build system Wenchao Xia
2012-09-27  8:06   ` Paolo Bonzini
2012-09-27  9:39     ` Wenchao Xia
2012-09-27  2:23 ` [Qemu-devel] [PATCH V4 2/5] libqblock type defines Wenchao Xia
2012-09-27  8:25   ` Paolo Bonzini
2012-09-27  9:52     ` Wenchao Xia
2012-09-27 10:16       ` Paolo Bonzini
2012-09-28  3:00         ` Wenchao Xia
2012-09-28  7:51           ` Paolo Bonzini
2012-09-28 10:52             ` Wenchao Xia
2012-09-28 10:58               ` Paolo Bonzini
2012-09-27  2:24 ` [Qemu-devel] [PATCH V4 3/5] libqblock API Wenchao Xia
2012-09-27  2:24 ` [Qemu-devel] [PATCH V4 4/5] libqblock test build system Wenchao Xia
2012-09-27  8:30   ` Paolo Bonzini
2012-09-27  9:56     ` Wenchao Xia
2012-09-27 10:17       ` Paolo Bonzini
2012-09-28  3:04         ` Wenchao Xia
2012-09-28  7:52           ` Paolo Bonzini
2012-09-28  9:46             ` Wenchao Xia
2012-09-27  2:24 ` Wenchao Xia [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1348712642-4427-6-git-send-email-xiawenc@linux.vnet.ibm.com \
    --to=xiawenc@linux.vnet.ibm.com \
    --cc=aliguori@us.ibm.com \
    --cc=blauwirbel@gmail.com \
    --cc=eblake@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).