Re: [Qemu-devel] [PATCH 14/15] qapi: add test-libqmp

2011-03-12 Thread Anthony Liguori

On 03/12/2011 05:23 AM, Blue Swirl wrote:

On Sat, Mar 12, 2011 at 1:05 AM, Anthony Liguori  wrote:

This provides a glib-test based testing framework for QMP

Signed-off-by: Anthony Liguori

diff --git a/Makefile b/Makefile
index 5170675..1d363d7 100644
--- a/Makefile
+++ b/Makefile
@@ -72,6 +72,8 @@ defconfig:

  -include config-all-devices.mak

+TOOLS += test-libqmp
+
  build-all: $(DOCS) $(TOOLS) recurse-all

  config-host.h: config-host.h-timestamp
@@ -205,6 +207,15 @@ check-qlist: check-qlist.o qlist.o qint.o 
$(CHECK_PROG_DEPS)
  check-qfloat: check-qfloat.o qfloat.o $(CHECK_PROG_DEPS)
  check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o 
qjson.o json-streamer.o json-lexer.o json-parser.o $(CHECK_PROG_DEPS)

+LIBQMP_OBJS := qmp-types.o libqmp.o error.o libqmp-core.o
+LIBQMP_OBJS += qmp-marshal-types-core.o qmp-marshal-types.o
+LIBQMP_OBJS += qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o
+LIBQMP_OBJS += qerror.o
+LIBQMP_OBJS += json-streamer.o json-lexer.o json-parser.o
+LIBQMP_OBJS += $(oslib-obj-y) $(trace-obj-y) qemu-malloc.o
+
+test-libqmp: test-libqmp.o $(LIBQMP_OBJS) qemu-timer-common.o
+
  clean:
  # avoid old build problems by removing potentially incorrect old files
rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h 
gen-op-arm.h
diff --git a/test-libqmp.c b/test-libqmp.c
new file mode 100644

I'd put this to tests/.


tests/ lives outside of the QEMU build system today.  It's also very TCG 
specific.


How about taking the current contents of tests/ and moving it to 
tests/tcg and moving test-libqmp and check-*.c to tests/?



index 000..9b73987
--- /dev/null
+++ b/test-libqmp.c
@@ -0,0 +1,170 @@
+/*
+ * QAPI
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.  See
+ * the COPYING.LIB file in the top-level directory.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "config-host.h"
+#include "libqmp.h"
+#include "qerror.h"
+
+#define g_assert_noerr(err) g_assert(err == NULL);
+#define g_assert_anyerr(err) g_assert(err != NULL);
+#define g_assert_cmperr(err, op, type) do {   \
+g_assert_anyerr(err);\
+g_assert_cmpstr(error_get_field(err, "class"), op, type); \
+} while (0)
+
+static pid_t last_qemu_pid = -1;
+
+static QmpSession *qemu(const char *fmt, ...)
+{
+char buffer0[4096];
+char buffer1[4096];
+const char *pid_filename = "/tmp/test-libqmp-qemu.pid";
+const char *path = "/tmp/test-libqmp-qemu.sock";

Very insecure filenames.


This disappears in round 3 when I introduce discovery support in libqmp.

Even so, I don't think security is a major concern here.


+static void wait_for_pid_exit(pid_t pid)
+{
+FILE *f = NULL;
+
+/* This is ugly but I don't know of a better way */

man waitpid?


waitpid only works for child processes.  Since we launch with 
-daemonize, that the QEMU instance is no longer a child process.


We use -daemonize because it avoids the race condition where we try to 
connect to a QMP socket but QEMU hasn't created the socket yet.  It also 
means that we can just use system() to invoke QEMU which makes life a 
whole lot simpler.


Regards,

Anthony Liguori



Re: [Qemu-devel] [PATCH 14/15] qapi: add test-libqmp

2011-03-12 Thread Blue Swirl
On Sat, Mar 12, 2011 at 1:05 AM, Anthony Liguori  wrote:
> This provides a glib-test based testing framework for QMP
>
> Signed-off-by: Anthony Liguori 
>
> diff --git a/Makefile b/Makefile
> index 5170675..1d363d7 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -72,6 +72,8 @@ defconfig:
>
>  -include config-all-devices.mak
>
> +TOOLS += test-libqmp
> +
>  build-all: $(DOCS) $(TOOLS) recurse-all
>
>  config-host.h: config-host.h-timestamp
> @@ -205,6 +207,15 @@ check-qlist: check-qlist.o qlist.o qint.o 
> $(CHECK_PROG_DEPS)
>  check-qfloat: check-qfloat.o qfloat.o $(CHECK_PROG_DEPS)
>  check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o 
> qjson.o json-streamer.o json-lexer.o json-parser.o $(CHECK_PROG_DEPS)
>
> +LIBQMP_OBJS := qmp-types.o libqmp.o error.o libqmp-core.o
> +LIBQMP_OBJS += qmp-marshal-types-core.o qmp-marshal-types.o
> +LIBQMP_OBJS += qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o
> +LIBQMP_OBJS += qerror.o
> +LIBQMP_OBJS += json-streamer.o json-lexer.o json-parser.o
> +LIBQMP_OBJS += $(oslib-obj-y) $(trace-obj-y) qemu-malloc.o
> +
> +test-libqmp: test-libqmp.o $(LIBQMP_OBJS) qemu-timer-common.o
> +
>  clean:
>  # avoid old build problems by removing potentially incorrect old files
>        rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h 
> gen-op-arm.h
> diff --git a/test-libqmp.c b/test-libqmp.c
> new file mode 100644

I'd put this to tests/.

> index 000..9b73987
> --- /dev/null
> +++ b/test-libqmp.c
> @@ -0,0 +1,170 @@
> +/*
> + * QAPI
> + *
> + * Copyright IBM, Corp. 2011
> + *
> + * Authors:
> + *  Anthony Liguori   
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.  See
> + * the COPYING.LIB file in the top-level directory.
> + */
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include "config-host.h"
> +#include "libqmp.h"
> +#include "qerror.h"
> +
> +#define g_assert_noerr(err) g_assert(err == NULL);
> +#define g_assert_anyerr(err) g_assert(err != NULL);
> +#define g_assert_cmperr(err, op, type) do {                   \
> +    g_assert_anyerr(err);                                        \
> +    g_assert_cmpstr(error_get_field(err, "class"), op, type); \
> +} while (0)
> +
> +static pid_t last_qemu_pid = -1;
> +
> +static QmpSession *qemu(const char *fmt, ...)
> +{
> +    char buffer0[4096];
> +    char buffer1[4096];
> +    const char *pid_filename = "/tmp/test-libqmp-qemu.pid";
> +    const char *path = "/tmp/test-libqmp-qemu.sock";

Very insecure filenames.

> +    struct sockaddr_un addr;
> +    va_list ap;
> +    int ret;
> +    int fd;
> +
> +    va_start(ap, fmt);
> +    vsnprintf(buffer0, sizeof(buffer0), fmt, ap);
> +    va_end(ap);
> +
> +    snprintf(buffer1, sizeof(buffer1),
> +             "i386-softmmu/qemu "
> +             "-enable-kvm "
> +             "-name test-libqmp "
> +             "-qmp2 qmp "
> +             "-chardev socket,id=qmp,path=%s,server=on,wait=off "
> +             "-vnc none "
> +             "-daemonize "
> +             "-pidfile %s "
> +             "%s", path, pid_filename, buffer0);
> +    g_test_message("Executing %s\n", buffer1);
> +    ret = system(buffer1);
> +    g_assert(ret != -1);
> +
> +    {
> +        FILE *f;
> +        char buffer[1024];
> +        char *ptr;
> +
> +        f = fopen(pid_filename, "r");
> +        g_assert(f != NULL);
> +
> +        ptr = fgets(buffer, sizeof(buffer), f);
> +        g_assert(ptr != NULL);
> +
> +        fclose(f);
> +
> +        last_qemu_pid = atoi(buffer);
> +    }
> +
> +    fd = socket(PF_UNIX, SOCK_STREAM, 0);
> +    g_assert(fd != -1);
> +
> +    addr.sun_family = AF_UNIX;
> +    snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path);
> +    ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
> +    g_assert(ret != -1);
> +
> +    return qmp_session_new(fd);
> +}
> +
> +static void wait_for_pid_exit(pid_t pid)
> +{
> +    FILE *f = NULL;
> +
> +    /* This is ugly but I don't know of a better way */

man waitpid?

> +    do {
> +        char buffer[1024];
> +
> +        if (f) {
> +            fclose(f);
> +            usleep(1);
> +        }
> +
> +        snprintf(buffer, sizeof(buffer), "/proc/%d/stat", pid);
> +        f = fopen(buffer, "r");
> +    } while (f);
> +}
> +
> +static void qemu_destroy(QmpSession *sess)
> +{
> +    wait_for_pid_exit(last_qemu_pid);
> +    last_qemu_pid = -1;
> +    qmp_session_destroy(sess);
> +}
> +
> +static void test_version(void)
> +{
> +    QmpSession *sess = NULL;
> +    VersionInfo *info;
> +    char version[1024];
> +    char *ptr, *end;
> +    int major, minor, micro;
> +
> +    /* Even though we use the same string as the source input, we do parse it
> +     * a little bit different for no other reason that to make sure we catch
> +     * potential bugs.
> +     */
> +    snprintf(version, sizeof(version), "%s", QEMU_VERSION);
> +    ptr = version;
> +
> +    end = strch

[Qemu-devel] [PATCH 14/15] qapi: add test-libqmp

2011-03-11 Thread Anthony Liguori
This provides a glib-test based testing framework for QMP

Signed-off-by: Anthony Liguori 

diff --git a/Makefile b/Makefile
index 5170675..1d363d7 100644
--- a/Makefile
+++ b/Makefile
@@ -72,6 +72,8 @@ defconfig:
 
 -include config-all-devices.mak
 
+TOOLS += test-libqmp
+
 build-all: $(DOCS) $(TOOLS) recurse-all
 
 config-host.h: config-host.h-timestamp
@@ -205,6 +207,15 @@ check-qlist: check-qlist.o qlist.o qint.o 
$(CHECK_PROG_DEPS)
 check-qfloat: check-qfloat.o qfloat.o $(CHECK_PROG_DEPS)
 check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o 
qjson.o json-streamer.o json-lexer.o json-parser.o $(CHECK_PROG_DEPS)
 
+LIBQMP_OBJS := qmp-types.o libqmp.o error.o libqmp-core.o
+LIBQMP_OBJS += qmp-marshal-types-core.o qmp-marshal-types.o
+LIBQMP_OBJS += qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o
+LIBQMP_OBJS += qerror.o
+LIBQMP_OBJS += json-streamer.o json-lexer.o json-parser.o
+LIBQMP_OBJS += $(oslib-obj-y) $(trace-obj-y) qemu-malloc.o
+
+test-libqmp: test-libqmp.o $(LIBQMP_OBJS) qemu-timer-common.o
+
 clean:
 # avoid old build problems by removing potentially incorrect old files
rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h 
gen-op-arm.h
diff --git a/test-libqmp.c b/test-libqmp.c
new file mode 100644
index 000..9b73987
--- /dev/null
+++ b/test-libqmp.c
@@ -0,0 +1,170 @@
+/*
+ * QAPI
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Anthony Liguori   
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.  See
+ * the COPYING.LIB file in the top-level directory.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "config-host.h"
+#include "libqmp.h"
+#include "qerror.h"
+
+#define g_assert_noerr(err) g_assert(err == NULL);
+#define g_assert_anyerr(err) g_assert(err != NULL);
+#define g_assert_cmperr(err, op, type) do {   \
+g_assert_anyerr(err);\
+g_assert_cmpstr(error_get_field(err, "class"), op, type); \
+} while (0)
+
+static pid_t last_qemu_pid = -1;
+
+static QmpSession *qemu(const char *fmt, ...)
+{
+char buffer0[4096];
+char buffer1[4096];
+const char *pid_filename = "/tmp/test-libqmp-qemu.pid";
+const char *path = "/tmp/test-libqmp-qemu.sock";
+struct sockaddr_un addr;
+va_list ap;
+int ret;
+int fd;
+
+va_start(ap, fmt);
+vsnprintf(buffer0, sizeof(buffer0), fmt, ap);
+va_end(ap);
+
+snprintf(buffer1, sizeof(buffer1),
+ "i386-softmmu/qemu "
+ "-enable-kvm "
+ "-name test-libqmp "
+ "-qmp2 qmp "
+ "-chardev socket,id=qmp,path=%s,server=on,wait=off "
+ "-vnc none "
+ "-daemonize "
+ "-pidfile %s "
+ "%s", path, pid_filename, buffer0);
+g_test_message("Executing %s\n", buffer1);
+ret = system(buffer1);
+g_assert(ret != -1);
+
+{
+FILE *f;
+char buffer[1024];
+char *ptr;
+
+f = fopen(pid_filename, "r");
+g_assert(f != NULL);
+
+ptr = fgets(buffer, sizeof(buffer), f);
+g_assert(ptr != NULL);
+
+fclose(f);
+
+last_qemu_pid = atoi(buffer);
+}
+
+fd = socket(PF_UNIX, SOCK_STREAM, 0);
+g_assert(fd != -1);
+
+addr.sun_family = AF_UNIX;
+snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path);
+ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
+g_assert(ret != -1);
+
+return qmp_session_new(fd);
+}
+
+static void wait_for_pid_exit(pid_t pid)
+{
+FILE *f = NULL;
+
+/* This is ugly but I don't know of a better way */
+do {
+char buffer[1024];
+
+if (f) {
+fclose(f);
+usleep(1);
+}
+
+snprintf(buffer, sizeof(buffer), "/proc/%d/stat", pid);
+f = fopen(buffer, "r");
+} while (f);
+}
+
+static void qemu_destroy(QmpSession *sess)
+{
+wait_for_pid_exit(last_qemu_pid);
+last_qemu_pid = -1;
+qmp_session_destroy(sess);
+}
+
+static void test_version(void)
+{
+QmpSession *sess = NULL;
+VersionInfo *info;
+char version[1024];
+char *ptr, *end;
+int major, minor, micro;
+
+/* Even though we use the same string as the source input, we do parse it
+ * a little bit different for no other reason that to make sure we catch
+ * potential bugs.
+ */
+snprintf(version, sizeof(version), "%s", QEMU_VERSION);
+ptr = version;
+
+end = strchr(ptr, '.');
+g_assert(end != NULL);
+*end = 0;
+major = atoi(ptr);
+ptr = end + 1;
+
+end = strchr(ptr, '.');
+g_assert(end != NULL);
+*end = 0;
+minor = atoi(ptr);
+ptr = end + 1;
+
+micro = atoi(ptr);
+while (g_ascii_isdigit(*ptr)) ptr++;
+
+sess = qemu("-S");
+
+info = libqmp_query_version(sess, NULL);
+
+g_assert_cmpint(major, ==, info->qemu.major);
+g_assert_cmpint(minor, ==, i