9ae3a8
From e1cfab2e4723088d7fb011c1deda763c03682f81 Mon Sep 17 00:00:00 2001
9ae3a8
Message-Id: <e1cfab2e4723088d7fb011c1deda763c03682f81.1387288155.git.minovotn@redhat.com>
9ae3a8
In-Reply-To: <527da6c2ce2c09d0183aa8595fc95f136f61b6df.1387288155.git.minovotn@redhat.com>
9ae3a8
References: <527da6c2ce2c09d0183aa8595fc95f136f61b6df.1387288155.git.minovotn@redhat.com>
9ae3a8
From: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
Date: Thu, 12 Dec 2013 16:21:27 +0100
9ae3a8
Subject: [PATCH 7/8] qdev-monitor-test: add device_add leak test cases
9ae3a8
9ae3a8
RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
Message-id: <1386865288-1575-8-git-send-email-stefanha@redhat.com>
9ae3a8
Patchwork-id: 56261
9ae3a8
O-Subject: [RHEL7 qemu-kvm PATCH 7/8] qdev-monitor-test: add device_add leak test cases
9ae3a8
Bugzilla: 1003773
9ae3a8
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
9ae3a8
RH-Acked-by: Markus Armbruster <armbru@redhat.com>
9ae3a8
9ae3a8
Ensure that the device_add error code path deletes device objects.
9ae3a8
Failure to do so not only leaks the objects but can also keep other
9ae3a8
objects (like drive or netdev) alive due to qdev properties holding
9ae3a8
references.
9ae3a8
9ae3a8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
Reviewed-by: Eric Blake <eblake@redhat.com>
9ae3a8
(cherry picked from commit 43cd209803d6cffb1e1a028c9ff2fd0ff4fce954)
9ae3a8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
9ae3a8
Conflicts:
9ae3a8
	tests/Makefile
9ae3a8
9ae3a8
Makefile diff context conflict.
9ae3a8
---
9ae3a8
 tests/Makefile            |  2 ++
9ae3a8
 tests/qdev-monitor-test.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++
9ae3a8
 2 files changed, 83 insertions(+)
9ae3a8
 create mode 100644 tests/qdev-monitor-test.c
9ae3a8
9ae3a8
Signed-off-by: Michal Novotny <minovotn@redhat.com>
9ae3a8
---
9ae3a8
 tests/Makefile            |  2 ++
9ae3a8
 tests/qdev-monitor-test.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++
9ae3a8
 2 files changed, 83 insertions(+)
9ae3a8
 create mode 100644 tests/qdev-monitor-test.c
9ae3a8
9ae3a8
diff --git a/tests/Makefile b/tests/Makefile
9ae3a8
index 91231e8..2e9093e 100644
9ae3a8
--- a/tests/Makefile
9ae3a8
+++ b/tests/Makefile
9ae3a8
@@ -59,6 +59,7 @@ check-qtest-i386-y += tests/rtc-test$(EXESUF)
9ae3a8
 check-qtest-i386-y += tests/i440fx-test$(EXESUF)
9ae3a8
 check-qtest-i386-y += tests/fw_cfg-test$(EXESUF)
9ae3a8
 check-qtest-i386-y += tests/blockdev-test$(EXESUF)
9ae3a8
+check-qtest-i386-y += tests/qdev-monitor-test$(EXESUF)
9ae3a8
 check-qtest-x86_64-y = $(check-qtest-i386-y)
9ae3a8
 gcov-files-i386-y += i386-softmmu/hw/mc146818rtc.c
9ae3a8
 gcov-files-x86_64-y = $(subst i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y))
9ae3a8
@@ -137,6 +138,7 @@ tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
9ae3a8
 tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
9ae3a8
 tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y)
9ae3a8
 tests/blockdev-test$(EXESUF): tests/blockdev-test.o $(libqos-pc-obj-y)
9ae3a8
+tests/qdev-monitor-test$(EXESUF): tests/qdev-monitor-test.o $(libqos-pc-obj-y)
9ae3a8
 
9ae3a8
 # QTest rules
9ae3a8
 
9ae3a8
diff --git a/tests/qdev-monitor-test.c b/tests/qdev-monitor-test.c
9ae3a8
new file mode 100644
9ae3a8
index 0000000..33a8ea4
9ae3a8
--- /dev/null
9ae3a8
+++ b/tests/qdev-monitor-test.c
9ae3a8
@@ -0,0 +1,81 @@
9ae3a8
+/*
9ae3a8
+ * qdev-monitor.c test cases
9ae3a8
+ *
9ae3a8
+ * Copyright (C) 2013 Red Hat Inc.
9ae3a8
+ *
9ae3a8
+ * Authors:
9ae3a8
+ *  Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
+ *
9ae3a8
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
9ae3a8
+ * See the COPYING.LIB file in the top-level directory.
9ae3a8
+ */
9ae3a8
+
9ae3a8
+#include <string.h>
9ae3a8
+#include <glib.h>
9ae3a8
+#include "libqtest.h"
9ae3a8
+#include "qapi/qmp/qjson.h"
9ae3a8
+
9ae3a8
+static void test_device_add(void)
9ae3a8
+{
9ae3a8
+    QDict *response;
9ae3a8
+    QDict *error;
9ae3a8
+
9ae3a8
+    qtest_start("-drive if=none,id=drive0");
9ae3a8
+
9ae3a8
+    /* Make device_add fail.  If this leaks the virtio-blk-pci device then a
9ae3a8
+     * reference to drive0 will also be held (via qdev properties).
9ae3a8
+     */
9ae3a8
+    response = qmp("{\"execute\": \"device_add\","
9ae3a8
+                   " \"arguments\": {"
9ae3a8
+                   "   \"driver\": \"virtio-blk-pci\","
9ae3a8
+                   "   \"drive\": \"drive0\""
9ae3a8
+                   "}}");
9ae3a8
+    g_assert(response);
9ae3a8
+    error = qdict_get_qdict(response, "error");
9ae3a8
+    g_assert(!strcmp(qdict_get_try_str(error, "class") ?: "",
9ae3a8
+                     "GenericError"));
9ae3a8
+    g_assert(!strcmp(qdict_get_try_str(error, "desc") ?: "",
9ae3a8
+                     "Device initialization failed."));
9ae3a8
+    QDECREF(response);
9ae3a8
+
9ae3a8
+    /* Delete the drive */
9ae3a8
+    response = qmp("{\"execute\": \"human-monitor-command\","
9ae3a8
+                   " \"arguments\": {"
9ae3a8
+                   "   \"command-line\": \"drive_del drive0\""
9ae3a8
+                   "}}");
9ae3a8
+    g_assert(response);
9ae3a8
+    g_assert(!strcmp(qdict_get_try_str(response, "return") ?: "(null)", ""));
9ae3a8
+    QDECREF(response);
9ae3a8
+
9ae3a8
+    /* Try to re-add the drive.  This fails with duplicate IDs if a leaked
9ae3a8
+     * virtio-blk-pci exists that holds a reference to the old drive0.
9ae3a8
+     */
9ae3a8
+    response = qmp("{\"execute\": \"human-monitor-command\","
9ae3a8
+                   " \"arguments\": {"
9ae3a8
+                   "   \"command-line\": \"drive_add pci-addr=auto if=none,id=drive0\""
9ae3a8
+                   "}}");
9ae3a8
+    g_assert(response);
9ae3a8
+    g_assert(!strcmp(qdict_get_try_str(response, "return") ?: "",
9ae3a8
+                     "OK\r\n"));
9ae3a8
+    QDECREF(response);
9ae3a8
+
9ae3a8
+    qtest_end();
9ae3a8
+}
9ae3a8
+
9ae3a8
+int main(int argc, char **argv)
9ae3a8
+{
9ae3a8
+    const char *arch = qtest_get_arch();
9ae3a8
+
9ae3a8
+    /* Check architecture */
9ae3a8
+    if (strcmp(arch, "i386") && strcmp(arch, "x86_64")) {
9ae3a8
+        g_test_message("Skipping test for non-x86\n");
9ae3a8
+        return 0;
9ae3a8
+    }
9ae3a8
+
9ae3a8
+    /* Run the tests */
9ae3a8
+    g_test_init(&argc, &argv, NULL);
9ae3a8
+
9ae3a8
+    qtest_add_func("/qmp/device_add", test_device_add);
9ae3a8
+
9ae3a8
+    return g_test_run();
9ae3a8
+}
9ae3a8
-- 
9ae3a8
1.7.11.7
9ae3a8