summary refs log tree commit diff stats
path: root/tests
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2016-10-24 15:03:09 +0100
committerPeter Maydell <peter.maydell@linaro.org>2016-10-24 15:03:09 +0100
commita3ae21ec3fe036f536dc94cad735931777143103 (patch)
treeb8110b4ad3a2a21f68f9273acfb704c2c49ceb19 /tests
parent4387f5671f9676336c87b68f5e87ba54fbea3714 (diff)
parent8360668e6988736bf621d8f3a3bae5d9f1a30bc5 (diff)
downloadfocaccia-qemu-a3ae21ec3fe036f536dc94cad735931777143103.tar.gz
focaccia-qemu-a3ae21ec3fe036f536dc94cad735931777143103.zip
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* KVM run_on_cpu fix (Alex)
* atomic usage fixes (Emilio, me)
* hugetlbfs alignment fix (Haozhong)
* CharBackend refactoring (Marc-André)
* test-i386 fixes (me)
* MemoryListener optimizations (me)
* Miscellaneous bugfixes (me)
* iSER support (Roy)
* --version formatting (Thomas)

# gpg: Signature made Mon 24 Oct 2016 14:46:19 BST
# gpg:                using RSA key 0xBFFBD25F78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>"
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>"
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4  E2F7 7E15 100C CD36 69B1
#      Subkey fingerprint: F133 3857 4B66 2389 866C  7682 BFFB D25F 78C7 AE83

* remotes/bonzini/tags/for-upstream: (50 commits)
  exec.c: workaround regression caused by alignment change in d2f39ad
  char: remove explicit_be_open from CharDriverState
  char: use common error path in qmp_chardev_add
  char: replace avail_connections
  char: remove unused qemu_chr_fe_event
  char: use an enum for CHR_EVENT
  char: remove unused CHR_EVENT_FOCUS
  char: move fe_open in CharBackend
  char: remove explicit_fe_open, use a set_handlers argument
  char: rename chr_close/chr_free
  char: move front end handlers in CharBackend
  tests: start chardev unit tests
  char: make some qemu_chr_fe skip if no driver
  char: replace qemu_chr_claim/release with qemu_chr_fe_init/deinit
  vhost-user: only initialize queue 0 CharBackend
  char: fold qemu_chr_set_handlers in qemu_chr_fe_set_handlers
  char: use qemu_chr_fe* functions with CharBackend argument
  colo: claim in find_and_check_chardev
  char: rename some frontend functions
  char: remaining switch to CharBackend in frontend
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests')
-rw-r--r--tests/Makefile.include4
-rw-r--r--tests/qht-bench.c6
-rw-r--r--tests/tcg/test-i386.c4
-rw-r--r--tests/test-char.c253
-rw-r--r--tests/vhost-user-test.c27
5 files changed, 279 insertions, 15 deletions
diff --git a/tests/Makefile.include b/tests/Makefile.include
index cbe38adc32..e65e9f7819 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -8,6 +8,8 @@ SYSEMU_TARGET_LIST := $(subst -softmmu.mak,,$(notdir \
 
 check-unit-y = tests/check-qdict$(EXESUF)
 gcov-files-check-qdict-y = qobject/qdict.c
+check-unit-y = tests/test-char$(EXESUF)
+gcov-files-check-qdict-y = qemu-char.c
 check-unit-y += tests/check-qfloat$(EXESUF)
 gcov-files-check-qfloat-y = qobject/qfloat.c
 check-unit-y += tests/check-qint$(EXESUF)
@@ -481,6 +483,8 @@ tests/check-qnull$(EXESUF): tests/check-qnull.o $(test-util-obj-y)
 tests/check-qjson$(EXESUF): tests/check-qjson.o $(test-util-obj-y)
 tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(test-qom-obj-y)
 tests/check-qom-proplist$(EXESUF): tests/check-qom-proplist.o $(test-qom-obj-y)
+
+tests/test-char$(EXESUF): tests/test-char.o qemu-char.o qemu-timer.o $(test-util-obj-y) $(qtest-obj-y) $(test-io-obj-y)
 tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(test-block-obj-y)
 tests/test-aio$(EXESUF): tests/test-aio.o $(test-block-obj-y)
 tests/test-rfifolock$(EXESUF): tests/test-rfifolock.o $(test-util-obj-y)
diff --git a/tests/qht-bench.c b/tests/qht-bench.c
index 76360a0cf5..2afa09d859 100644
--- a/tests/qht-bench.c
+++ b/tests/qht-bench.c
@@ -193,7 +193,7 @@ static void *thread_func(void *p)
     rcu_register_thread();
 
     atomic_inc(&n_ready_threads);
-    while (!atomic_mb_read(&test_start)) {
+    while (!atomic_read(&test_start)) {
         cpu_relax();
     }
 
@@ -393,11 +393,11 @@ static void run_test(void)
     while (atomic_read(&n_ready_threads) != n_rw_threads + n_rz_threads) {
         cpu_relax();
     }
-    atomic_mb_set(&test_start, true);
+    atomic_set(&test_start, true);
     do {
         remaining = sleep(duration);
     } while (remaining);
-    atomic_mb_set(&test_stop, true);
+    atomic_set(&test_stop, true);
 
     for (i = 0; i < n_rw_threads; i++) {
         qemu_thread_join(&rw_threads[i]);
diff --git a/tests/tcg/test-i386.c b/tests/tcg/test-i386.c
index b05572b734..0f7b943b0c 100644
--- a/tests/tcg/test-i386.c
+++ b/tests/tcg/test-i386.c
@@ -2250,14 +2250,14 @@ SSE_OP(a ## sd);
 
 #define SSE_COMI(op, field)\
 {\
-    unsigned int eflags;\
+    unsigned long eflags;\
     XMMReg a, b;\
     a.field[0] = a1;\
     b.field[0] = b1;\
     asm volatile (#op " %2, %1\n"\
         "pushf\n"\
         "pop %0\n"\
-        : "=m" (eflags)\
+        : "=rm" (eflags)\
         : "x" (a.dq), "x" (b.dq));\
     printf("%-9s: a=%f b=%f cc=%04x\n",\
            #op, a1, b1,\
diff --git a/tests/test-char.c b/tests/test-char.c
new file mode 100644
index 0000000000..241685afbb
--- /dev/null
+++ b/tests/test-char.c
@@ -0,0 +1,253 @@
+#include "qemu/osdep.h"
+
+#include "qemu-common.h"
+#include "qemu/config-file.h"
+#include "sysemu/char.h"
+#include "sysemu/sysemu.h"
+#include "qapi/error.h"
+#include "qmp-commands.h"
+
+typedef struct FeHandler {
+    int read_count;
+    int last_event;
+    char read_buf[128];
+} FeHandler;
+
+static int fe_can_read(void *opaque)
+{
+    FeHandler *h = opaque;
+
+    return sizeof(h->read_buf) - h->read_count;
+}
+
+static void fe_read(void *opaque, const uint8_t *buf, int size)
+{
+    FeHandler *h = opaque;
+
+    g_assert_cmpint(size, <=, fe_can_read(opaque));
+
+    memcpy(h->read_buf + h->read_count, buf, size);
+    h->read_count += size;
+}
+
+static void fe_event(void *opaque, int event)
+{
+    FeHandler *h = opaque;
+
+    h->last_event = event;
+}
+
+#ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS
+static void char_stdio_test_subprocess(void)
+{
+    CharDriverState *chr;
+    CharBackend be;
+    int ret;
+
+    chr = qemu_chr_new("label", "stdio");
+    g_assert_nonnull(chr);
+
+    qemu_chr_fe_init(&be, chr, &error_abort);
+    qemu_chr_fe_set_open(&be, true);
+    ret = qemu_chr_fe_write(&be, (void *)"buf", 4);
+    g_assert_cmpint(ret, ==, 4);
+
+    qemu_chr_fe_deinit(&be);
+    qemu_chr_delete(chr);
+}
+
+static void char_stdio_test(void)
+{
+    g_test_trap_subprocess("/char/stdio/subprocess", 0, 0);
+    g_test_trap_assert_passed();
+    g_test_trap_assert_stdout("buf");
+}
+#endif
+
+
+static void char_ringbuf_test(void)
+{
+    QemuOpts *opts;
+    CharDriverState *chr;
+    CharBackend be;
+    char *data;
+    int ret;
+
+    opts = qemu_opts_create(qemu_find_opts("chardev"), "ringbuf-label",
+                            1, &error_abort);
+    qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
+
+    qemu_opt_set(opts, "size", "5", &error_abort);
+    chr = qemu_chr_new_from_opts(opts, NULL);
+    g_assert_null(chr);
+    qemu_opts_del(opts);
+
+    opts = qemu_opts_create(qemu_find_opts("chardev"), "ringbuf-label",
+                            1, &error_abort);
+    qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
+    qemu_opt_set(opts, "size", "2", &error_abort);
+    chr = qemu_chr_new_from_opts(opts, &error_abort);
+    g_assert_nonnull(chr);
+    qemu_opts_del(opts);
+
+    qemu_chr_fe_init(&be, chr, &error_abort);
+    ret = qemu_chr_fe_write(&be, (void *)"buff", 4);
+    g_assert_cmpint(ret, ==, 4);
+
+    data = qmp_ringbuf_read("ringbuf-label", 4, false, 0, &error_abort);
+    g_assert_cmpstr(data, ==, "ff");
+    g_free(data);
+
+    data = qmp_ringbuf_read("ringbuf-label", 4, false, 0, &error_abort);
+    g_assert_cmpstr(data, ==, "");
+    g_free(data);
+
+    qemu_chr_fe_deinit(&be);
+    qemu_chr_delete(chr);
+}
+
+static void char_mux_test(void)
+{
+    QemuOpts *opts;
+    CharDriverState *chr, *base;
+    char *data;
+    FeHandler h1 = { 0, }, h2 = { 0, };
+    CharBackend chr_be1, chr_be2;
+
+    opts = qemu_opts_create(qemu_find_opts("chardev"), "mux-label",
+                            1, &error_abort);
+    qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
+    qemu_opt_set(opts, "size", "128", &error_abort);
+    qemu_opt_set(opts, "mux", "on", &error_abort);
+    chr = qemu_chr_new_from_opts(opts, &error_abort);
+    g_assert_nonnull(chr);
+    qemu_opts_del(opts);
+
+    qemu_chr_fe_init(&chr_be1, chr, &error_abort);
+    qemu_chr_fe_set_handlers(&chr_be1,
+                             fe_can_read,
+                             fe_read,
+                             fe_event,
+                             &h1,
+                             NULL, true);
+
+    qemu_chr_fe_init(&chr_be2, chr, &error_abort);
+    qemu_chr_fe_set_handlers(&chr_be2,
+                             fe_can_read,
+                             fe_read,
+                             fe_event,
+                             &h2,
+                             NULL, true);
+    qemu_chr_fe_take_focus(&chr_be2);
+
+    base = qemu_chr_find("mux-label-base");
+    g_assert_cmpint(qemu_chr_be_can_write(base), !=, 0);
+
+    qemu_chr_be_write(base, (void *)"hello", 6);
+    g_assert_cmpint(h1.read_count, ==, 0);
+    g_assert_cmpint(h2.read_count, ==, 6);
+    g_assert_cmpstr(h2.read_buf, ==, "hello");
+    h2.read_count = 0;
+
+    /* switch focus */
+    qemu_chr_be_write(base, (void *)"\1c", 2);
+
+    qemu_chr_be_write(base, (void *)"hello", 6);
+    g_assert_cmpint(h2.read_count, ==, 0);
+    g_assert_cmpint(h1.read_count, ==, 6);
+    g_assert_cmpstr(h1.read_buf, ==, "hello");
+    h1.read_count = 0;
+
+    /* remove first handler */
+    qemu_chr_fe_set_handlers(&chr_be1, NULL, NULL, NULL, NULL, NULL, true);
+    qemu_chr_be_write(base, (void *)"hello", 6);
+    g_assert_cmpint(h1.read_count, ==, 0);
+    g_assert_cmpint(h2.read_count, ==, 0);
+
+    qemu_chr_be_write(base, (void *)"\1c", 2);
+    qemu_chr_be_write(base, (void *)"hello", 6);
+    g_assert_cmpint(h1.read_count, ==, 0);
+    g_assert_cmpint(h2.read_count, ==, 6);
+    g_assert_cmpstr(h2.read_buf, ==, "hello");
+    h2.read_count = 0;
+
+    /* print help */
+    qemu_chr_be_write(base, (void *)"\1?", 2);
+    data = qmp_ringbuf_read("mux-label-base", 128, false, 0, &error_abort);
+    g_assert_cmpint(strlen(data), !=, 0);
+    g_free(data);
+
+    qemu_chr_fe_deinit(&chr_be1);
+    qemu_chr_fe_deinit(&chr_be2);
+    qemu_chr_delete(chr);
+}
+
+static void char_null_test(void)
+{
+    Error *err = NULL;
+    CharDriverState *chr;
+    CharBackend be;
+    int ret;
+
+    chr = qemu_chr_find("label-null");
+    g_assert_null(chr);
+
+    chr = qemu_chr_new("label-null", "null");
+    chr = qemu_chr_find("label-null");
+    g_assert_nonnull(chr);
+
+    g_assert(qemu_chr_has_feature(chr,
+                 QEMU_CHAR_FEATURE_FD_PASS) == false);
+    g_assert(qemu_chr_has_feature(chr,
+                 QEMU_CHAR_FEATURE_RECONNECTABLE) == false);
+
+    /* check max avail */
+    qemu_chr_fe_init(&be, chr, &error_abort);
+    qemu_chr_fe_init(&be, chr, &err);
+    error_free_or_abort(&err);
+
+    /* deinit & reinit */
+    qemu_chr_fe_deinit(&be);
+    qemu_chr_fe_init(&be, chr, &error_abort);
+
+    qemu_chr_fe_set_open(&be, true);
+
+    qemu_chr_fe_set_handlers(&be,
+                             fe_can_read,
+                             fe_read,
+                             fe_event,
+                             NULL, NULL, true);
+
+    ret = qemu_chr_fe_write(&be, (void *)"buf", 4);
+    g_assert_cmpint(ret, ==, 4);
+
+    qemu_chr_fe_deinit(&be);
+    qemu_chr_delete(chr);
+}
+
+static void char_invalid_test(void)
+{
+    CharDriverState *chr;
+
+    chr = qemu_chr_new("label-invalid", "invalid");
+    g_assert_null(chr);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    module_call_init(MODULE_INIT_QOM);
+    qemu_add_opts(&qemu_chardev_opts);
+
+    g_test_add_func("/char/null", char_null_test);
+    g_test_add_func("/char/invalid", char_invalid_test);
+    g_test_add_func("/char/ringbuf", char_ringbuf_test);
+    g_test_add_func("/char/mux", char_mux_test);
+#ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS
+    g_test_add_func("/char/stdio/subprocess", char_stdio_test_subprocess);
+    g_test_add_func("/char/stdio", char_stdio_test);
+#endif
+
+    return g_test_run();
+}
diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index d7c48c589a..a7f06291cb 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -11,6 +11,7 @@
 #include "qemu/osdep.h"
 
 #include "libqtest.h"
+#include "qapi/error.h"
 #include "qemu/option.h"
 #include "qemu/range.h"
 #include "qemu/sockets.h"
@@ -19,6 +20,7 @@
 #include "libqos/libqos.h"
 #include "libqos/pci-pc.h"
 #include "libqos/virtio-pci.h"
+#include "qapi/error.h"
 
 #include "libqos/pci-pc.h"
 #include "libqos/virtio-pci.h"
@@ -141,7 +143,7 @@ typedef struct TestServer {
     gchar *socket_path;
     gchar *mig_path;
     gchar *chr_name;
-    CharDriverState *chr;
+    CharBackend chr;
     int fds_num;
     int fds[VHOST_MEMORY_MAX_NREGIONS];
     VhostUserMemory memory;
@@ -261,13 +263,13 @@ static int chr_can_read(void *opaque)
 static void chr_read(void *opaque, const uint8_t *buf, int size)
 {
     TestServer *s = opaque;
-    CharDriverState *chr = s->chr;
+    CharBackend *chr = &s->chr;
     VhostUserMsg msg;
     uint8_t *p = (uint8_t *) &msg;
     int fd;
 
     if (s->test_fail) {
-        qemu_chr_disconnect(chr);
+        qemu_chr_fe_disconnect(chr);
         /* now switch to non-failure */
         s->test_fail = false;
     }
@@ -312,7 +314,7 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
 	g_assert_cmpint(msg.payload.u64 & (0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES),
 			!=, 0ULL);
         if (s->test_flags == TEST_FLAGS_DISCONNECT) {
-            qemu_chr_disconnect(chr);
+            qemu_chr_fe_disconnect(chr);
             s->test_flags = TEST_FLAGS_BAD;
         }
         break;
@@ -344,7 +346,8 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
     case VHOST_USER_SET_MEM_TABLE:
         /* received the mem table */
         memcpy(&s->memory, &msg.payload.memory, sizeof(msg.payload.memory));
-        s->fds_num = qemu_chr_fe_get_msgfds(chr, s->fds, G_N_ELEMENTS(s->fds));
+        s->fds_num = qemu_chr_fe_get_msgfds(chr, s->fds,
+                                            G_N_ELEMENTS(s->fds));
 
         /* signal the test that it can continue */
         g_cond_signal(&s->data_cond);
@@ -453,13 +456,15 @@ static void chr_event(void *opaque, int event)
 static void test_server_create_chr(TestServer *server, const gchar *opt)
 {
     gchar *chr_path;
+    CharDriverState *chr;
 
     chr_path = g_strdup_printf("unix:%s%s", server->socket_path, opt);
-    server->chr = qemu_chr_new(server->chr_name, chr_path, NULL);
+    chr = qemu_chr_new(server->chr_name, chr_path);
     g_free(chr_path);
 
-    qemu_chr_add_handlers(server->chr, chr_can_read, chr_read,
-                          chr_event, server);
+    qemu_chr_fe_init(&server->chr, chr, &error_abort);
+    qemu_chr_fe_set_handlers(&server->chr, chr_can_read, chr_read,
+                             chr_event, server, NULL, true);
 }
 
 static void test_server_listen(TestServer *server)
@@ -483,8 +488,10 @@ static inline void test_server_connect(TestServer *server)
 static gboolean _test_server_free(TestServer *server)
 {
     int i;
+    CharDriverState *chr = qemu_chr_fe_get_driver(&server->chr);
 
-    qemu_chr_delete(server->chr);
+    qemu_chr_fe_deinit(&server->chr);
+    qemu_chr_delete(chr);
 
     for (i = 0; i < server->fds_num; i++) {
         close(server->fds[i]);
@@ -721,7 +728,7 @@ reconnect_cb(gpointer user_data)
 {
     TestServer *s = user_data;
 
-    qemu_chr_disconnect(s->chr);
+    qemu_chr_fe_disconnect(&s->chr);
 
     return FALSE;
 }