This covers the simple common case with no surprises: A serial that is
shorter than 20 characters and can fit in the request buffer.

Signed-off-by: Kevin Wolf <[email protected]>
---
 tests/qtest/virtio-blk-test.c | 69 +++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/tests/qtest/virtio-blk-test.c b/tests/qtest/virtio-blk-test.c
index 98c906ebb4a..14fadcb4009 100644
--- a/tests/qtest/virtio-blk-test.c
+++ b/tests/qtest/virtio-blk-test.c
@@ -95,6 +95,8 @@ static uint64_t virtio_blk_request(QGuestAllocator *alloc, 
QVirtioDevice *d,
         g_assert_cmpuint(data_size %
                          sizeof(struct virtio_blk_discard_write_zeroes), ==, 
0);
         break;
+    case VIRTIO_BLK_T_GET_ID:
+        break;
     default:
         g_assert_cmpuint(data_size, ==, 0);
     }
@@ -771,6 +773,68 @@ static void resize(void *obj, void *data, QGuestAllocator 
*t_alloc)
 
 }
 
+static QVirtQueue *get_id_setup(QVirtioDevice *dev, QGuestAllocator *t_alloc)
+{
+    QVirtQueue *vq;
+    uint64_t features = qvirtio_get_features(dev);
+
+    features = features & (1ull << VIRTIO_F_VERSION_1);
+    qvirtio_set_features(dev, features);
+
+    vq = qvirtqueue_setup(dev, t_alloc, 0);
+    qvirtio_set_driver_ok(dev);
+    return vq;
+}
+
+static uint8_t get_id_request(QVirtioDevice *dev, QVirtQueue *vq,
+                              char *buf, size_t buf_len,
+                              QGuestAllocator *t_alloc)
+{
+    QTestState *qts = global_qtest;
+    uint64_t req_addr;
+    uint32_t free_head;
+    uint8_t status;
+
+    QVirtioBlkReq req = {
+        .type = VIRTIO_BLK_T_GET_ID,
+        .data = buf,
+    };
+
+    req_addr = virtio_blk_request(t_alloc, dev, &req, buf_len);
+
+    memset(req.data, 0xa5, buf_len);
+    memwrite(req_addr + 16, req.data, buf_len);
+
+    free_head = qvirtqueue_add(qts, vq, req_addr, 16, false, true);
+    qvirtqueue_add(qts, vq, req_addr + 16, buf_len, true, true);
+    qvirtqueue_add(qts, vq, req_addr + 16 + buf_len, 1, true, false);
+
+    qvirtqueue_kick(qts, dev, vq, free_head);
+
+    qvirtio_wait_used_elem(qts, dev, vq, free_head, NULL,
+                           QVIRTIO_BLK_TIMEOUT_US);
+    status = readb(req_addr + 16 + buf_len);
+    memread(req_addr + 16, buf, buf_len);
+    return status;
+}
+
+static void get_id_serial_short(void *obj, void *data, QGuestAllocator 
*t_alloc)
+{
+    QVirtioBlk *blk_if = obj;
+    QVirtioDevice *dev = blk_if->vdev;
+    QVirtQueue *vq;
+    uint8_t status;
+    const char expected[20] = "abc";
+    char buf[20];
+
+    vq = get_id_setup(dev, t_alloc);
+    status = get_id_request(dev, vq, buf, 20, t_alloc);
+    g_assert_cmpint(status, ==, 0);
+    g_assert_cmpmem(buf, 20, expected, sizeof(expected));
+
+    qvirtqueue_cleanup(blk_if->vdev->bus, vq, t_alloc);
+}
+
 static void *virtio_blk_test_setup(GString *cmd_line, void *arg)
 {
     char *tmp_path = drive_create();
@@ -802,6 +866,11 @@ static void register_virtio_blk_test(void)
     qos_add_test("nxvirtq", "virtio-blk-pci",
                       test_nonexistent_virtqueue, &opts);
     qos_add_test("hotplug", "virtio-blk-pci", pci_hotplug, &opts);
+
+    /* serial number tests */
+    opts.edge.extra_device_opts = "serial=abc";
+    qos_add_test("get_id/serial_short", "virtio-blk",
+                 get_id_serial_short, &opts);
 }
 
 libqos_init(register_virtio_blk_test);
-- 
2.56.0

Reply via email to