diff mbox series

hw/virtio: added virtio-serial test cases

Message ID 20221112063241.2190502-1-dhoff749@gmail.com
State New
Headers show
Series hw/virtio: added virtio-serial test cases | expand

Commit Message

Daniel Hoffman Nov. 12, 2022, 6:32 a.m. UTC
The previous test cases for virtio-serial only tested initialization of
the device. I've included four new test cases: rx for virtconsole, tx
for virtconsole, rx for virtserialport, tx for virtserialport. It
follows the general pattern of virtio-net (i.e. chardev file descriptor
backend with a socketpair connected via fork-exec).

Signed-off-by: Daniel Hoffman <dhoff749@gmail.com>
---
 tests/qtest/libqos/virtio-serial.c |  51 +++++++++
 tests/qtest/libqos/virtio-serial.h |   2 +
 tests/qtest/virtio-serial-test.c   | 177 ++++++++++++++++++++++++++++-
 3 files changed, 228 insertions(+), 2 deletions(-)

Comments

Daniel Hoffman Feb. 23, 2023, 6:41 a.m. UTC | #1
Is there interest in this?


On Fri, Nov 11, 2022 at 10:33 PM Daniel Hoffman <dhoff749@gmail.com> wrote:
>
> The previous test cases for virtio-serial only tested initialization of
> the device. I've included four new test cases: rx for virtconsole, tx
> for virtconsole, rx for virtserialport, tx for virtserialport. It
> follows the general pattern of virtio-net (i.e. chardev file descriptor
> backend with a socketpair connected via fork-exec).
>
> Signed-off-by: Daniel Hoffman <dhoff749@gmail.com>
> ---
>  tests/qtest/libqos/virtio-serial.c |  51 +++++++++
>  tests/qtest/libqos/virtio-serial.h |   2 +
>  tests/qtest/virtio-serial-test.c   | 177 ++++++++++++++++++++++++++++-
>  3 files changed, 228 insertions(+), 2 deletions(-)
>
> diff --git a/tests/qtest/libqos/virtio-serial.c b/tests/qtest/libqos/virtio-serial.c
> index 1d689c3e38..8723bffe1b 100644
> --- a/tests/qtest/libqos/virtio-serial.c
> +++ b/tests/qtest/libqos/virtio-serial.c
> @@ -22,6 +22,10 @@
>  #include "qgraph.h"
>  #include "virtio-serial.h"
>
> +#include "qemu/iov.h"
> +
> +static QGuestAllocator *alloc;
> +
>  static void *qvirtio_serial_get_driver(QVirtioSerial *v_serial,
>                                         const char *interface)
>  {
> @@ -43,6 +47,33 @@ static void *qvirtio_serial_device_get_driver(void *object,
>      return qvirtio_serial_get_driver(&v_serial->serial, interface);
>  }
>
> +static void virtio_serial_setup(QVirtioSerial *interface)
> +{
> +    QVirtioDevice *vdev = interface->vdev;
> +    qvirtio_set_features(vdev, (1ULL << 1) | (1ULL << 32));
> +
> +    interface->n_queues = 6;
> +    interface->queues = g_new(QVirtQueue*, interface->n_queues);
> +
> +    for (int i = 0; i < interface->n_queues; i++) {
> +        interface->queues[i] = qvirtqueue_setup(interface->vdev, alloc, i);
> +    }
> +
> +    qvirtio_set_driver_ok(vdev);
> +}
> +
> +static void qvirtio_serial_device_destructor(QOSGraphObject *obj)
> +{
> +}
> +
> +static void qvirtio_serial_device_start_hw(QOSGraphObject *obj)
> +{
> +    QVirtioSerialDevice *v_serial = (QVirtioSerialDevice *)obj;
> +    QVirtioSerial *interface = &v_serial->serial;
> +
> +    virtio_serial_setup(interface);
> +}
> +
>  static void *virtio_serial_device_create(void *virtio_dev,
>                                           QGuestAllocator *t_alloc,
>                                           void *addr)
> @@ -51,13 +82,30 @@ static void *virtio_serial_device_create(void *virtio_dev,
>      QVirtioSerial *interface = &virtio_device->serial;
>
>      interface->vdev = virtio_dev;
> +    alloc = t_alloc;
>
> +    virtio_device->obj.destructor = qvirtio_serial_device_destructor;
> +    virtio_device->obj.start_hw = qvirtio_serial_device_start_hw;
>      virtio_device->obj.get_driver = qvirtio_serial_device_get_driver;
>
>      return &virtio_device->obj;
>  }
>
>  /* virtio-serial-pci */
> +static void qvirtio_serial_pci_destructor(QOSGraphObject *obj)
> +{
> +}
> +
> +static void qvirtio_serial_pci_start_hw(QOSGraphObject *obj)
> +{
> +    QVirtioSerialPCI *v_serial = (QVirtioSerialPCI *) obj;
> +    QVirtioSerial *interface = &v_serial->serial;
> +    QOSGraphObject *pci_vobj = &v_serial->pci_vdev.obj;
> +
> +    qvirtio_pci_start_hw(pci_vobj);
> +    virtio_serial_setup(interface);
> +}
> +
>  static void *qvirtio_serial_pci_get_driver(void *object, const char *interface)
>  {
>      QVirtioSerialPCI *v_serial = object;
> @@ -76,7 +124,10 @@ static void *virtio_serial_pci_create(void *pci_bus, QGuestAllocator *t_alloc,
>
>      virtio_pci_init(&virtio_spci->pci_vdev, pci_bus, addr);
>      interface->vdev = &virtio_spci->pci_vdev.vdev;
> +    alloc = t_alloc;
>
> +    obj->destructor = qvirtio_serial_pci_destructor;
> +    obj->start_hw = qvirtio_serial_pci_start_hw;
>      obj->get_driver = qvirtio_serial_pci_get_driver;
>
>      return obj;
> diff --git a/tests/qtest/libqos/virtio-serial.h b/tests/qtest/libqos/virtio-serial.h
> index 3db43b2bb8..ce6ae164cb 100644
> --- a/tests/qtest/libqos/virtio-serial.h
> +++ b/tests/qtest/libqos/virtio-serial.h
> @@ -29,6 +29,8 @@ typedef struct QVirtioSerialDevice QVirtioSerialDevice;
>
>  struct QVirtioSerial {
>      QVirtioDevice *vdev;
> +    int n_queues;
> +    QVirtQueue **queues;
>  };
>
>  struct QVirtioSerialPCI {
> diff --git a/tests/qtest/virtio-serial-test.c b/tests/qtest/virtio-serial-test.c
> index 2541034822..190075d6f5 100644
> --- a/tests/qtest/virtio-serial-test.c
> +++ b/tests/qtest/virtio-serial-test.c
> @@ -11,6 +11,36 @@
>  #include "libqtest-single.h"
>  #include "qemu/module.h"
>  #include "libqos/virtio-serial.h"
> +#include "standard-headers/linux/virtio_console.h"
> +#include "qemu/iov.h"
> +
> +static void virtio_serial_test_cleanup(void *sockets)
> +{
> +    int *sv = sockets;
> +
> +    close(sv[0]);
> +    qos_invalidate_command_line();
> +    close(sv[1]);
> +    g_free(sv);
> +}
> +
> +static void *virtio_serial_test_setup(GString *cmd_line, void *arg)
> +{
> +    int ret;
> +    int *sv = g_new(int, 3);
> +
> +    ret = socketpair(PF_UNIX, SOCK_STREAM, 0, sv);
> +    g_assert_cmpint(ret, !=, -1);
> +
> +    g_string_append_printf(
> +        cmd_line,
> +        " -chardev socket,fd=%d,id=virtioserial0",
> +        sv[1]);
> +
> +    sv[2] = arg ? 1 : 0;
> +    g_test_queue_destroy(virtio_serial_test_cleanup, sv);
> +    return sv;
> +}
>
>  /* Tests only initialization so far. TODO: Replace with functional tests */
>  static void virtio_serial_nop(void *obj, void *data, QGuestAllocator *alloc)
> @@ -18,6 +48,132 @@ static void virtio_serial_nop(void *obj, void *data, QGuestAllocator *alloc)
>      /* no operation */
>  }
>
> +static void tx_test(
> +    QVirtioDevice *dev,
> +    QGuestAllocator *alloc,
> +    QVirtQueue *vq,
> +    int socket)
> +{
> +    QTestState *qts = global_qtest;
> +    uint64_t req_addr;
> +    uint64_t free_head;
> +    char test[] = "TEST";
> +    char buffer[5];
> +    struct iovec iov[] = {
> +        {
> +            .iov_base = buffer,
> +            .iov_len = strlen(test)
> +        }
> +    };
> +    int ret;
> +
> +    req_addr = guest_alloc(alloc, 4);
> +    qtest_memwrite(qts, req_addr, test, strlen(test));
> +
> +    free_head = qvirtqueue_add(qts, vq, req_addr, 4, false, false);
> +    qvirtqueue_kick(qts, dev, vq, free_head);
> +
> +    ret = iov_recv(socket, iov, 1, 0, strlen(test));
> +    g_assert_cmpint(ret, ==, strlen(test));
> +
> +    buffer[strlen(test)] = '\0';
> +    g_assert_cmpstr(buffer, ==, test);
> +
> +    guest_free(alloc, req_addr);
> +}
> +
> +static void rx_test(
> +    QVirtioDevice *dev,
> +    QGuestAllocator *alloc,
> +    QVirtQueue *vq,
> +    int socket)
> +{
> +    QTestState *qts = global_qtest;
> +    uint64_t req_addr;
> +    uint64_t free_head;
> +    char test[] = "TEST";
> +    char buffer[5];
> +    struct iovec iov[] = {
> +        {
> +            .iov_base = test,
> +            .iov_len = strlen(test)
> +        }
> +    };
> +    int ret;
> +
> +    req_addr = guest_alloc(alloc, 4);
> +
> +    free_head = qvirtqueue_add(qts, vq, req_addr, 4, true, false);
> +    qvirtqueue_kick(qts, dev, vq, free_head);
> +
> +    ret = iov_send(socket, iov, 1, 0, strlen(test));
> +    g_assert_cmpint(ret, ==, strlen(test));
> +
> +    qvirtio_wait_used_elem(qts, dev, vq, free_head, NULL, 5 * 1000 * 1000);
> +    qtest_memread(qts, req_addr, buffer, strlen(test));
> +
> +    buffer[strlen(test)] = '\0';
> +    g_assert_cmpstr(buffer, ==, test);
> +
> +    guest_free(alloc, req_addr);
> +}
> +
> +static void send_recv_test(void *obj, void *data, QGuestAllocator *alloc)
> +{
> +    QVirtioSerial *serial_if = obj;
> +    QVirtioDevice *dev = serial_if->vdev;
> +    uint32_t port_open_addr, port_open_free_head;
> +    int *sv = data;
> +
> +    /*
> +     * the first port is always virtconsole due to backwards compatibility
> +     * consideraitons so we must use the multiport feature to add the correct
> +     * port
> +     */
> +    QVirtQueue *rx = serial_if->queues[sv[2] == 0 ? 0 : 4];
> +    QVirtQueue *tx = serial_if->queues[sv[2] == 0 ? 1 : 5];
> +    QVirtQueue *control_tx = serial_if->queues[3];
> +
> +    port_open_addr = guest_alloc(alloc, 8);
> +
> +    qtest_writel(global_qtest, port_open_addr + 0, sv[2]);
> +    qtest_writew(global_qtest, port_open_addr + 4, VIRTIO_CONSOLE_PORT_READY);
> +    qtest_writew(global_qtest, port_open_addr + 6, 1);
> +    port_open_free_head = qvirtqueue_add(
> +        global_qtest,
> +        control_tx,
> +        port_open_addr,
> +        8,
> +        false,
> +        false);
> +    qvirtqueue_kick(
> +        global_qtest,
> +        dev,
> +        control_tx,
> +        port_open_free_head);
> +
> +    qtest_writel(global_qtest, port_open_addr + 0, sv[2]);
> +    qtest_writew(global_qtest, port_open_addr + 4, VIRTIO_CONSOLE_PORT_OPEN);
> +    qtest_writew(global_qtest, port_open_addr + 6, 1);
> +    port_open_free_head = qvirtqueue_add(
> +        global_qtest,
> +        control_tx,
> +        port_open_addr,
> +        8,
> +        false,
> +        false);
> +    qvirtqueue_kick(
> +        global_qtest,
> +        dev,
> +        control_tx,
> +        port_open_free_head);
> +
> +    guest_free(alloc, port_open_addr);
> +
> +    tx_test(dev, alloc, tx, sv[0]);
> +    rx_test(dev, alloc, rx, sv[0]);
> +}
> +
>  static void serial_hotplug(void *obj, void *data, QGuestAllocator *alloc)
>  {
>      qtest_qmp_device_add(global_qtest, "virtserialport", "hp-port", "{}");
> @@ -28,12 +184,29 @@ static void register_virtio_serial_test(void)
>  {
>      QOSGraphTestOptions opts = { };
>
> -    opts.edge.before_cmd_line = "-device virtconsole,bus=vser0.0";
> +    opts.before = virtio_serial_test_setup;
> +
> +    opts.arg = (gpointer)0;
> +    opts.edge.before_cmd_line =
> +        "-device virtconsole,bus=vser0.0,chardev=virtioserial0";
>      qos_add_test("console-nop", "virtio-serial", virtio_serial_nop, &opts);
> +    qos_add_test(
> +        "console-send-recv",
> +        "virtio-serial",
> +        send_recv_test,
> +        &opts);
>
> -    opts.edge.before_cmd_line = "-device virtserialport,bus=vser0.0";
> +    opts.arg = (gpointer)1;
> +    opts.edge.before_cmd_line =
> +        "-device virtserialport,bus=vser0.0,chardev=virtioserial0";
>      qos_add_test("serialport-nop", "virtio-serial", virtio_serial_nop, &opts);
>
> +    qos_add_test(
> +        "serialport-send-recv",
> +        "virtio-serial",
> +        send_recv_test,
> +        &opts);
> +
>      qos_add_test("hotplug", "virtio-serial", serial_hotplug, NULL);
>  }
>  libqos_init(register_virtio_serial_test);
> --
> 2.34.1
>
diff mbox series

Patch

diff --git a/tests/qtest/libqos/virtio-serial.c b/tests/qtest/libqos/virtio-serial.c
index 1d689c3e38..8723bffe1b 100644
--- a/tests/qtest/libqos/virtio-serial.c
+++ b/tests/qtest/libqos/virtio-serial.c
@@ -22,6 +22,10 @@ 
 #include "qgraph.h"
 #include "virtio-serial.h"
 
+#include "qemu/iov.h"
+
+static QGuestAllocator *alloc;
+
 static void *qvirtio_serial_get_driver(QVirtioSerial *v_serial,
                                        const char *interface)
 {
@@ -43,6 +47,33 @@  static void *qvirtio_serial_device_get_driver(void *object,
     return qvirtio_serial_get_driver(&v_serial->serial, interface);
 }
 
+static void virtio_serial_setup(QVirtioSerial *interface)
+{
+    QVirtioDevice *vdev = interface->vdev;
+    qvirtio_set_features(vdev, (1ULL << 1) | (1ULL << 32));
+
+    interface->n_queues = 6;
+    interface->queues = g_new(QVirtQueue*, interface->n_queues);
+
+    for (int i = 0; i < interface->n_queues; i++) {
+        interface->queues[i] = qvirtqueue_setup(interface->vdev, alloc, i);
+    }
+
+    qvirtio_set_driver_ok(vdev);
+}
+
+static void qvirtio_serial_device_destructor(QOSGraphObject *obj)
+{
+}
+
+static void qvirtio_serial_device_start_hw(QOSGraphObject *obj)
+{
+    QVirtioSerialDevice *v_serial = (QVirtioSerialDevice *)obj;
+    QVirtioSerial *interface = &v_serial->serial;
+
+    virtio_serial_setup(interface);
+}
+
 static void *virtio_serial_device_create(void *virtio_dev,
                                          QGuestAllocator *t_alloc,
                                          void *addr)
@@ -51,13 +82,30 @@  static void *virtio_serial_device_create(void *virtio_dev,
     QVirtioSerial *interface = &virtio_device->serial;
 
     interface->vdev = virtio_dev;
+    alloc = t_alloc;
 
+    virtio_device->obj.destructor = qvirtio_serial_device_destructor;
+    virtio_device->obj.start_hw = qvirtio_serial_device_start_hw;
     virtio_device->obj.get_driver = qvirtio_serial_device_get_driver;
 
     return &virtio_device->obj;
 }
 
 /* virtio-serial-pci */
+static void qvirtio_serial_pci_destructor(QOSGraphObject *obj)
+{
+}
+
+static void qvirtio_serial_pci_start_hw(QOSGraphObject *obj)
+{
+    QVirtioSerialPCI *v_serial = (QVirtioSerialPCI *) obj;
+    QVirtioSerial *interface = &v_serial->serial;
+    QOSGraphObject *pci_vobj = &v_serial->pci_vdev.obj;
+
+    qvirtio_pci_start_hw(pci_vobj);
+    virtio_serial_setup(interface);
+}
+
 static void *qvirtio_serial_pci_get_driver(void *object, const char *interface)
 {
     QVirtioSerialPCI *v_serial = object;
@@ -76,7 +124,10 @@  static void *virtio_serial_pci_create(void *pci_bus, QGuestAllocator *t_alloc,
 
     virtio_pci_init(&virtio_spci->pci_vdev, pci_bus, addr);
     interface->vdev = &virtio_spci->pci_vdev.vdev;
+    alloc = t_alloc;
 
+    obj->destructor = qvirtio_serial_pci_destructor;
+    obj->start_hw = qvirtio_serial_pci_start_hw;
     obj->get_driver = qvirtio_serial_pci_get_driver;
 
     return obj;
diff --git a/tests/qtest/libqos/virtio-serial.h b/tests/qtest/libqos/virtio-serial.h
index 3db43b2bb8..ce6ae164cb 100644
--- a/tests/qtest/libqos/virtio-serial.h
+++ b/tests/qtest/libqos/virtio-serial.h
@@ -29,6 +29,8 @@  typedef struct QVirtioSerialDevice QVirtioSerialDevice;
 
 struct QVirtioSerial {
     QVirtioDevice *vdev;
+    int n_queues;
+    QVirtQueue **queues;
 };
 
 struct QVirtioSerialPCI {
diff --git a/tests/qtest/virtio-serial-test.c b/tests/qtest/virtio-serial-test.c
index 2541034822..190075d6f5 100644
--- a/tests/qtest/virtio-serial-test.c
+++ b/tests/qtest/virtio-serial-test.c
@@ -11,6 +11,36 @@ 
 #include "libqtest-single.h"
 #include "qemu/module.h"
 #include "libqos/virtio-serial.h"
+#include "standard-headers/linux/virtio_console.h"
+#include "qemu/iov.h"
+
+static void virtio_serial_test_cleanup(void *sockets)
+{
+    int *sv = sockets;
+
+    close(sv[0]);
+    qos_invalidate_command_line();
+    close(sv[1]);
+    g_free(sv);
+}
+
+static void *virtio_serial_test_setup(GString *cmd_line, void *arg)
+{
+    int ret;
+    int *sv = g_new(int, 3);
+
+    ret = socketpair(PF_UNIX, SOCK_STREAM, 0, sv);
+    g_assert_cmpint(ret, !=, -1);
+
+    g_string_append_printf(
+        cmd_line,
+        " -chardev socket,fd=%d,id=virtioserial0",
+        sv[1]);
+
+    sv[2] = arg ? 1 : 0;
+    g_test_queue_destroy(virtio_serial_test_cleanup, sv);
+    return sv;
+}
 
 /* Tests only initialization so far. TODO: Replace with functional tests */
 static void virtio_serial_nop(void *obj, void *data, QGuestAllocator *alloc)
@@ -18,6 +48,132 @@  static void virtio_serial_nop(void *obj, void *data, QGuestAllocator *alloc)
     /* no operation */
 }
 
+static void tx_test(
+    QVirtioDevice *dev,
+    QGuestAllocator *alloc,
+    QVirtQueue *vq,
+    int socket)
+{
+    QTestState *qts = global_qtest;
+    uint64_t req_addr;
+    uint64_t free_head;
+    char test[] = "TEST";
+    char buffer[5];
+    struct iovec iov[] = {
+        {
+            .iov_base = buffer,
+            .iov_len = strlen(test)
+        }
+    };
+    int ret;
+
+    req_addr = guest_alloc(alloc, 4);
+    qtest_memwrite(qts, req_addr, test, strlen(test));
+
+    free_head = qvirtqueue_add(qts, vq, req_addr, 4, false, false);
+    qvirtqueue_kick(qts, dev, vq, free_head);
+
+    ret = iov_recv(socket, iov, 1, 0, strlen(test));
+    g_assert_cmpint(ret, ==, strlen(test));
+
+    buffer[strlen(test)] = '\0';
+    g_assert_cmpstr(buffer, ==, test);
+
+    guest_free(alloc, req_addr);
+}
+
+static void rx_test(
+    QVirtioDevice *dev,
+    QGuestAllocator *alloc,
+    QVirtQueue *vq,
+    int socket)
+{
+    QTestState *qts = global_qtest;
+    uint64_t req_addr;
+    uint64_t free_head;
+    char test[] = "TEST";
+    char buffer[5];
+    struct iovec iov[] = {
+        {
+            .iov_base = test,
+            .iov_len = strlen(test)
+        }
+    };
+    int ret;
+
+    req_addr = guest_alloc(alloc, 4);
+
+    free_head = qvirtqueue_add(qts, vq, req_addr, 4, true, false);
+    qvirtqueue_kick(qts, dev, vq, free_head);
+
+    ret = iov_send(socket, iov, 1, 0, strlen(test));
+    g_assert_cmpint(ret, ==, strlen(test));
+
+    qvirtio_wait_used_elem(qts, dev, vq, free_head, NULL, 5 * 1000 * 1000);
+    qtest_memread(qts, req_addr, buffer, strlen(test));
+
+    buffer[strlen(test)] = '\0';
+    g_assert_cmpstr(buffer, ==, test);
+
+    guest_free(alloc, req_addr);
+}
+
+static void send_recv_test(void *obj, void *data, QGuestAllocator *alloc)
+{
+    QVirtioSerial *serial_if = obj;
+    QVirtioDevice *dev = serial_if->vdev;
+    uint32_t port_open_addr, port_open_free_head;
+    int *sv = data;
+
+    /*
+     * the first port is always virtconsole due to backwards compatibility
+     * consideraitons so we must use the multiport feature to add the correct
+     * port
+     */
+    QVirtQueue *rx = serial_if->queues[sv[2] == 0 ? 0 : 4];
+    QVirtQueue *tx = serial_if->queues[sv[2] == 0 ? 1 : 5];
+    QVirtQueue *control_tx = serial_if->queues[3];
+
+    port_open_addr = guest_alloc(alloc, 8);
+
+    qtest_writel(global_qtest, port_open_addr + 0, sv[2]);
+    qtest_writew(global_qtest, port_open_addr + 4, VIRTIO_CONSOLE_PORT_READY);
+    qtest_writew(global_qtest, port_open_addr + 6, 1);
+    port_open_free_head = qvirtqueue_add(
+        global_qtest,
+        control_tx,
+        port_open_addr,
+        8,
+        false,
+        false);
+    qvirtqueue_kick(
+        global_qtest,
+        dev,
+        control_tx,
+        port_open_free_head);
+
+    qtest_writel(global_qtest, port_open_addr + 0, sv[2]);
+    qtest_writew(global_qtest, port_open_addr + 4, VIRTIO_CONSOLE_PORT_OPEN);
+    qtest_writew(global_qtest, port_open_addr + 6, 1);
+    port_open_free_head = qvirtqueue_add(
+        global_qtest,
+        control_tx,
+        port_open_addr,
+        8,
+        false,
+        false);
+    qvirtqueue_kick(
+        global_qtest,
+        dev,
+        control_tx,
+        port_open_free_head);
+
+    guest_free(alloc, port_open_addr);
+
+    tx_test(dev, alloc, tx, sv[0]);
+    rx_test(dev, alloc, rx, sv[0]);
+}
+
 static void serial_hotplug(void *obj, void *data, QGuestAllocator *alloc)
 {
     qtest_qmp_device_add(global_qtest, "virtserialport", "hp-port", "{}");
@@ -28,12 +184,29 @@  static void register_virtio_serial_test(void)
 {
     QOSGraphTestOptions opts = { };
 
-    opts.edge.before_cmd_line = "-device virtconsole,bus=vser0.0";
+    opts.before = virtio_serial_test_setup;
+
+    opts.arg = (gpointer)0;
+    opts.edge.before_cmd_line =
+        "-device virtconsole,bus=vser0.0,chardev=virtioserial0";
     qos_add_test("console-nop", "virtio-serial", virtio_serial_nop, &opts);
+    qos_add_test(
+        "console-send-recv",
+        "virtio-serial",
+        send_recv_test,
+        &opts);
 
-    opts.edge.before_cmd_line = "-device virtserialport,bus=vser0.0";
+    opts.arg = (gpointer)1;
+    opts.edge.before_cmd_line =
+        "-device virtserialport,bus=vser0.0,chardev=virtioserial0";
     qos_add_test("serialport-nop", "virtio-serial", virtio_serial_nop, &opts);
 
+    qos_add_test(
+        "serialport-send-recv",
+        "virtio-serial",
+        send_recv_test,
+        &opts);
+
     qos_add_test("hotplug", "virtio-serial", serial_hotplug, NULL);
 }
 libqos_init(register_virtio_serial_test);