summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/Makefile.include15
-rw-r--r--tests/boot-serial-test.c6
-rw-r--r--tests/check-qdict.c20
-rw-r--r--tests/check-qjson.c41
-rw-r--r--tests/check-qlist.c4
-rw-r--r--tests/check-qlit.c30
-rw-r--r--tests/check-qnum.c4
-rw-r--r--tests/check-qobject.c2
-rw-r--r--tests/check-qstring.c2
-rw-r--r--tests/device-introspect-test.c14
-rw-r--r--tests/libqtest.c6
-rw-r--r--tests/machine-none-test.c103
-rw-r--r--tests/numa-test.c8
-rw-r--r--tests/qapi-schema/test-qapi.py2
-rwxr-xr-xtests/qemu-iotests/0306
-rwxr-xr-xtests/qemu-iotests/0331
-rwxr-xr-xtests/qemu-iotests/05517
-rwxr-xr-xtests/qemu-iotests/056187
-rw-r--r--tests/qemu-iotests/056.out4
-rwxr-xr-xtests/qemu-iotests/08920
-rw-r--r--tests/qemu-iotests/089.out8
-rw-r--r--tests/qemu-iotests/109.out24
-rw-r--r--tests/qemu-iotests/146.out2
-rwxr-xr-xtests/qemu-iotests/15312
-rw-r--r--tests/qemu-iotests/153.out5
-rwxr-xr-xtests/qemu-iotests/169156
-rw-r--r--tests/qemu-iotests/169.out5
-rwxr-xr-xtests/qemu-iotests/1812
-rwxr-xr-xtests/qemu-iotests/199118
-rw-r--r--tests/qemu-iotests/199.out5
-rwxr-xr-xtests/qemu-iotests/20855
-rw-r--r--tests/qemu-iotests/208.out9
-rwxr-xr-xtests/qemu-iotests/20934
-rw-r--r--tests/qemu-iotests/209.out2
-rwxr-xr-xtests/qemu-iotests/210210
-rw-r--r--tests/qemu-iotests/210.out136
-rwxr-xr-xtests/qemu-iotests/check13
-rw-r--r--tests/qemu-iotests/common.rc2
-rw-r--r--tests/qemu-iotests/group5
-rw-r--r--tests/qemu-iotests/iotests.py56
-rw-r--r--tests/qmp-test.c102
-rw-r--r--tests/qom-test.c4
-rw-r--r--tests/rcutorture.c4
-rw-r--r--tests/socket-helpers.c149
-rw-r--r--tests/socket-helpers.h42
-rw-r--r--tests/test-bdrv-drain.c5
-rw-r--r--tests/test-blockjob-txn.c27
-rw-r--r--tests/test-blockjob.c233
-rw-r--r--tests/test-char.c50
-rw-r--r--tests/test-cutils.c657
-rw-r--r--tests/test-io-channel-socket.c72
-rw-r--r--tests/test-keyval.c8
-rw-r--r--tests/test-qga.c19
-rw-r--r--tests/test-qmp-cmds.c12
-rw-r--r--tests/test-qmp-event.c16
-rw-r--r--tests/test-qobject-input-visitor.c21
-rw-r--r--tests/test-qobject-output-visitor.c54
-rw-r--r--tests/test-util-sockets.c266
-rw-r--r--tests/test-x86-cpuid-compat.c17
-rw-r--r--tests/virtio-scsi-test.c6
61 files changed, 2836 insertions, 280 deletions
diff --git a/tests/.gitignore b/tests/.gitignore
index 18e58b2183..fb62d2299b 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -86,6 +86,7 @@ test-thread-pool
test-throttle
test-timed-average
test-uuid
+test-util-sockets
test-visitor-serialization
test-vmstate
test-write-threshold
diff --git a/tests/Makefile.include b/tests/Makefile.include
index ef9b88c369..0b277036df 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -146,6 +146,7 @@ ifneq (,$(findstring qemu-ga,$(TOOLS)))
check-unit-$(CONFIG_LINUX) += tests/test-qga$(EXESUF)
endif
check-unit-y += tests/test-timed-average$(EXESUF)
+check-unit-y += tests/test-util-sockets$(EXESUF)
check-unit-y += tests/test-io-task$(EXESUF)
check-unit-y += tests/test-io-channel-socket$(EXESUF)
check-unit-y += tests/test-io-channel-file$(EXESUF)
@@ -399,6 +400,7 @@ check-qtest-s390x-y += tests/virtio-console-test$(EXESUF)
check-qtest-s390x-y += tests/virtio-serial-test$(EXESUF)
check-qtest-s390x-y += tests/cpu-plug-test$(EXESUF)
+check-qtest-generic-y += tests/machine-none-test$(EXESUF)
check-qtest-generic-y += tests/qom-test$(EXESUF)
check-qtest-generic-y += tests/test-hmp$(EXESUF)
@@ -713,9 +715,11 @@ tests/test-crypto-tlscredsx509$(EXESUF): tests/test-crypto-tlscredsx509.o \
tests/test-crypto-tlssession.o-cflags := $(TASN1_CFLAGS)
tests/test-crypto-tlssession$(EXESUF): tests/test-crypto-tlssession.o \
tests/crypto-tls-x509-helpers.o tests/pkix_asn1_tab.o $(test-crypto-obj-y)
+tests/test-util-sockets$(EXESUF): tests/test-util-sockets.o \
+ tests/socket-helpers.o $(test-util-obj-y)
tests/test-io-task$(EXESUF): tests/test-io-task.o $(test-io-obj-y)
tests/test-io-channel-socket$(EXESUF): tests/test-io-channel-socket.o \
- tests/io-channel-helpers.o $(test-io-obj-y)
+ tests/io-channel-helpers.o tests/socket-helpers.o $(test-io-obj-y)
tests/tpm-crb-test$(EXESUF): tests/tpm-crb-test.o tests/tpm-emu.o $(test-io-obj-y)
tests/tpm-tis-test$(EXESUF): tests/tpm-tis-test.o tests/tpm-emu.o $(test-io-obj-y)
tests/test-io-channel-file$(EXESUF): tests/test-io-channel-file.o \
@@ -794,6 +798,7 @@ tests/display-vga-test$(EXESUF): tests/display-vga-test.o
tests/ipoctal232-test$(EXESUF): tests/ipoctal232-test.o
tests/qom-test$(EXESUF): tests/qom-test.o
tests/test-hmp$(EXESUF): tests/test-hmp.o
+tests/machine-none-test$(EXESUF): tests/machine-none-test.o
tests/drive_del-test$(EXESUF): tests/drive_del-test.o $(libqos-virtio-obj-y)
tests/qdev-monitor-test$(EXESUF): tests/qdev-monitor-test.o $(libqos-pc-obj-y)
tests/nvme-test$(EXESUF): tests/nvme-test.o
@@ -926,14 +931,14 @@ $(patsubst %, check-%, $(check-qapi-schema-y)): check-%.json: $(SRC_PATH)/%.json
$^ >$*.test.out 2>$*.test.err; \
echo $$? >$*.test.exit, \
"TEST","$*.out")
- @diff $(SRC_PATH)/$*.out $*.test.out
@# Sanitize error messages (make them independent of build directory)
- @perl -p -e 's|\Q$(SRC_PATH)\E/||g' $*.test.err | diff $(SRC_PATH)/$*.err -
- @diff $(SRC_PATH)/$*.exit $*.test.exit
+ @perl -p -e 's|\Q$(SRC_PATH)\E/||g' $*.test.err | diff -u $(SRC_PATH)/$*.err -
+ @diff -u $(SRC_PATH)/$*.out $*.test.out
+ @diff -u $(SRC_PATH)/$*.exit $*.test.exit
.PHONY: check-tests/qapi-schema/doc-good.texi
check-tests/qapi-schema/doc-good.texi: tests/qapi-schema/doc-good.test.texi
- @diff -q $(SRC_PATH)/tests/qapi-schema/doc-good.texi $<
+ @diff -u $(SRC_PATH)/tests/qapi-schema/doc-good.texi $<
.PHONY: check-decodetree
check-decodetree:
diff --git a/tests/boot-serial-test.c b/tests/boot-serial-test.c
index ece25c694f..5b24cd26c1 100644
--- a/tests/boot-serial-test.c
+++ b/tests/boot-serial-test.c
@@ -75,11 +75,13 @@ typedef struct testdef {
static testdef_t tests[] = {
{ "alpha", "clipper", "", "PCI:" },
{ "ppc", "ppce500", "", "U-Boot" },
- { "ppc", "prep", "", "Open Hack'Ware BIOS" },
+ { "ppc", "prep", "-m 96", "Memory size: 96 MB" },
+ { "ppc", "40p", "-boot d", "Booting from device d" },
{ "ppc", "g3beige", "", "PowerPC,750" },
{ "ppc", "mac99", "", "PowerPC,G4" },
{ "ppc64", "ppce500", "", "U-Boot" },
- { "ppc64", "prep", "", "Open Hack'Ware BIOS" },
+ { "ppc64", "prep", "-boot e", "Booting from device e" },
+ { "ppc64", "40p", "-m 192", "Memory size: 192 MB" },
{ "ppc64", "mac99", "", "PowerPC,970FX" },
{ "ppc64", "pseries", "", "Open Firmware" },
{ "ppc64", "powernv", "-cpu POWER8", "OPAL" },
diff --git a/tests/check-qdict.c b/tests/check-qdict.c
index a3faea8bfc..2e73c2f86e 100644
--- a/tests/check-qdict.c
+++ b/tests/check-qdict.c
@@ -51,7 +51,7 @@ static void qdict_put_obj_test(void)
g_assert(qdict_size(qdict) == 1);
ent = QLIST_FIRST(&qdict->table[12345 % QDICT_BUCKET_MAX]);
- qn = qobject_to_qnum(ent->value);
+ qn = qobject_to(QNum, ent->value);
g_assert_cmpint(qnum_get_int(qn), ==, num);
QDECREF(qdict);
@@ -81,7 +81,7 @@ static void qdict_get_test(void)
obj = qdict_get(tests_dict, key);
g_assert(obj != NULL);
- qn = qobject_to_qnum(obj);
+ qn = qobject_to(QNum, obj);
g_assert_cmpint(qnum_get_int(qn), ==, value);
QDECREF(tests_dict);
@@ -216,7 +216,7 @@ static void qdict_del_test(void)
static void qobject_to_qdict_test(void)
{
QDict *tests_dict = qdict_new();
- g_assert(qobject_to_qdict(QOBJECT(tests_dict)) == tests_dict);
+ g_assert(qobject_to(QDict, QOBJECT(tests_dict)) == tests_dict);
QDECREF(tests_dict);
}
@@ -381,9 +381,9 @@ static void qdict_array_split_test(void)
qdict_array_split(test_dict, &test_list);
- dict1 = qobject_to_qdict(qlist_pop(test_list));
- dict2 = qobject_to_qdict(qlist_pop(test_list));
- int1 = qobject_to_qnum(qlist_pop(test_list));
+ dict1 = qobject_to(QDict, qlist_pop(test_list));
+ dict2 = qobject_to(QDict, qlist_pop(test_list));
+ int1 = qobject_to(QNum, qlist_pop(test_list));
g_assert(dict1);
g_assert(dict2);
@@ -450,7 +450,7 @@ static void qdict_array_split_test(void)
qdict_array_split(test_dict, &test_list);
- int1 = qobject_to_qnum(qlist_pop(test_list));
+ int1 = qobject_to(QNum, qlist_pop(test_list));
g_assert(int1);
g_assert(qlist_empty(test_list));
@@ -607,7 +607,7 @@ static void qdict_crumple_test_recursive(void)
qdict_put_str(src, "vnc.acl..name", "acl0");
qdict_put_str(src, "vnc.acl.rule..name", "acl0");
- dst = qobject_to_qdict(qdict_crumple(src, &error_abort));
+ dst = qobject_to(QDict, qdict_crumple(src, &error_abort));
g_assert(dst);
g_assert_cmpint(qdict_size(dst), ==, 1);
@@ -629,14 +629,14 @@ static void qdict_crumple_test_recursive(void)
g_assert(rules);
g_assert_cmpint(qlist_size(rules), ==, 2);
- rule = qobject_to_qdict(qlist_pop(rules));
+ rule = qobject_to(QDict, qlist_pop(rules));
g_assert(rule);
g_assert_cmpint(qdict_size(rule), ==, 2);
g_assert_cmpstr("fred", ==, qdict_get_str(rule, "match"));
g_assert_cmpstr("allow", ==, qdict_get_str(rule, "policy"));
QDECREF(rule);
- rule = qobject_to_qdict(qlist_pop(rules));
+ rule = qobject_to(QDict, qlist_pop(rules));
g_assert(rule);
g_assert_cmpint(qdict_size(rule), ==, 2);
g_assert_cmpstr("bob", ==, qdict_get_str(rule, "match"));
diff --git a/tests/check-qjson.c b/tests/check-qjson.c
index a18ea47cb7..997f4d3d2c 100644
--- a/tests/check-qjson.c
+++ b/tests/check-qjson.c
@@ -60,7 +60,7 @@ static void escaped_string(void)
QString *str;
obj = qobject_from_json(test_cases[i].encoded, &error_abort);
- str = qobject_to_qstring(obj);
+ str = qobject_to(QString, obj);
g_assert(str);
g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].decoded);
@@ -92,7 +92,7 @@ static void simple_string(void)
QString *str;
obj = qobject_from_json(test_cases[i].encoded, &error_abort);
- str = qobject_to_qstring(obj);
+ str = qobject_to(QString, obj);
g_assert(str);
g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
@@ -123,7 +123,7 @@ static void single_quote_string(void)
QString *str;
obj = qobject_from_json(test_cases[i].encoded, &error_abort);
- str = qobject_to_qstring(obj);
+ str = qobject_to(QString, obj);
g_assert(str);
g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
@@ -817,7 +817,7 @@ static void utf8_string(void)
obj = qobject_from_json(json_in, utf8_out ? &error_abort : NULL);
if (utf8_out) {
- str = qobject_to_qstring(obj);
+ str = qobject_to(QString, obj);
g_assert(str);
g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
} else {
@@ -843,7 +843,7 @@ static void utf8_string(void)
*/
if (0 && json_out != json_in) {
obj = qobject_from_json(json_out, &error_abort);
- str = qobject_to_qstring(obj);
+ str = qobject_to(QString, obj);
g_assert(str);
g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
}
@@ -864,8 +864,8 @@ static void vararg_string(void)
for (i = 0; test_cases[i].decoded; i++) {
QString *str;
- str = qobject_to_qstring(qobject_from_jsonf("%s",
- test_cases[i].decoded));
+ str = qobject_to(QString,
+ qobject_from_jsonf("%s", test_cases[i].decoded));
g_assert(str);
g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
@@ -893,8 +893,9 @@ static void simple_number(void)
QNum *qnum;
int64_t val;
- qnum = qobject_to_qnum(qobject_from_json(test_cases[i].encoded,
- &error_abort));
+ qnum = qobject_to(QNum,
+ qobject_from_json(test_cases[i].encoded,
+ &error_abort));
g_assert(qnum);
g_assert(qnum_get_try_int(qnum, &val));
g_assert_cmpint(val, ==, test_cases[i].decoded);
@@ -920,7 +921,7 @@ static void large_number(void)
uint64_t val;
int64_t ival;
- qnum = qobject_to_qnum(qobject_from_json(maxu64, &error_abort));
+ qnum = qobject_to(QNum, qobject_from_json(maxu64, &error_abort));
g_assert(qnum);
g_assert_cmpuint(qnum_get_uint(qnum), ==, 18446744073709551615U);
g_assert(!qnum_get_try_int(qnum, &ival));
@@ -930,7 +931,7 @@ static void large_number(void)
QDECREF(str);
QDECREF(qnum);
- qnum = qobject_to_qnum(qobject_from_json(gtu64, &error_abort));
+ qnum = qobject_to(QNum, qobject_from_json(gtu64, &error_abort));
g_assert(qnum);
g_assert_cmpfloat(qnum_get_double(qnum), ==, 18446744073709552e3);
g_assert(!qnum_get_try_uint(qnum, &val));
@@ -941,7 +942,7 @@ static void large_number(void)
QDECREF(str);
QDECREF(qnum);
- qnum = qobject_to_qnum(qobject_from_json(lti64, &error_abort));
+ qnum = qobject_to(QNum, qobject_from_json(lti64, &error_abort));
g_assert(qnum);
g_assert_cmpfloat(qnum_get_double(qnum), ==, -92233720368547758e2);
g_assert(!qnum_get_try_uint(qnum, &val));
@@ -973,7 +974,7 @@ static void float_number(void)
QNum *qnum;
obj = qobject_from_json(test_cases[i].encoded, &error_abort);
- qnum = qobject_to_qnum(obj);
+ qnum = qobject_to(QNum, obj);
g_assert(qnum);
g_assert(qnum_get_double(qnum) == test_cases[i].decoded);
@@ -997,17 +998,17 @@ static void vararg_number(void)
double valuef = 2.323423423;
int64_t val;
- qnum = qobject_to_qnum(qobject_from_jsonf("%d", value));
+ qnum = qobject_to(QNum, qobject_from_jsonf("%d", value));
g_assert(qnum_get_try_int(qnum, &val));
g_assert_cmpint(val, ==, value);
QDECREF(qnum);
- qnum = qobject_to_qnum(qobject_from_jsonf("%lld", value_ll));
+ qnum = qobject_to(QNum, qobject_from_jsonf("%lld", value_ll));
g_assert(qnum_get_try_int(qnum, &val));
g_assert_cmpint(val, ==, value_ll);
QDECREF(qnum);
- qnum = qobject_to_qnum(qobject_from_jsonf("%f", valuef));
+ qnum = qobject_to(QNum, qobject_from_jsonf("%f", valuef));
g_assert(qnum_get_double(qnum) == valuef);
QDECREF(qnum);
}
@@ -1020,7 +1021,7 @@ static void keyword_literal(void)
QString *str;
obj = qobject_from_json("true", &error_abort);
- qbool = qobject_to_qbool(obj);
+ qbool = qobject_to(QBool, obj);
g_assert(qbool);
g_assert(qbool_get_bool(qbool) == true);
@@ -1031,7 +1032,7 @@ static void keyword_literal(void)
QDECREF(qbool);
obj = qobject_from_json("false", &error_abort);
- qbool = qobject_to_qbool(obj);
+ qbool = qobject_to(QBool, obj);
g_assert(qbool);
g_assert(qbool_get_bool(qbool) == false);
@@ -1041,13 +1042,13 @@ static void keyword_literal(void)
QDECREF(qbool);
- qbool = qobject_to_qbool(qobject_from_jsonf("%i", false));
+ qbool = qobject_to(QBool, qobject_from_jsonf("%i", false));
g_assert(qbool);
g_assert(qbool_get_bool(qbool) == false);
QDECREF(qbool);
/* Test that non-zero values other than 1 get collapsed to true */
- qbool = qobject_to_qbool(qobject_from_jsonf("%i", 2));
+ qbool = qobject_to(QBool, qobject_from_jsonf("%i", 2));
g_assert(qbool);
g_assert(qbool_get_bool(qbool) == true);
QDECREF(qbool);
diff --git a/tests/check-qlist.c b/tests/check-qlist.c
index 259980d523..a1c69ed648 100644
--- a/tests/check-qlist.c
+++ b/tests/check-qlist.c
@@ -56,7 +56,7 @@ static void qobject_to_qlist_test(void)
qlist = qlist_new();
- g_assert(qobject_to_qlist(QOBJECT(qlist)) == qlist);
+ g_assert(qobject_to(QList, QOBJECT(qlist)) == qlist);
QDECREF(qlist);
}
@@ -71,7 +71,7 @@ static void iter_func(QObject *obj, void *opaque)
g_assert(opaque == NULL);
- qi = qobject_to_qnum(obj);
+ qi = qobject_to(QNum, obj);
g_assert(qi != NULL);
g_assert(qnum_get_try_int(qi, &val));
diff --git a/tests/check-qlit.c b/tests/check-qlit.c
index 5d0f65b9c7..96bbb06f2c 100644
--- a/tests/check-qlit.c
+++ b/tests/check-qlit.c
@@ -9,9 +9,11 @@
#include "qemu/osdep.h"
+#include "qapi/qmp/qbool.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qlist.h"
#include "qapi/qmp/qlit.h"
+#include "qapi/qmp/qnum.h"
#include "qapi/qmp/qstring.h"
static QLitObject qlit = QLIT_QDICT(((QLitDictEntry[]) {
@@ -57,17 +59,43 @@ static void qlit_equal_qobject_test(void)
g_assert(!qlit_equal_qobject(&qlit_foo, qobj));
- qdict_put(qobject_to_qdict(qobj), "bee", qlist_new());
+ qdict_put(qobject_to(QDict, qobj), "bee", qlist_new());
g_assert(!qlit_equal_qobject(&qlit, qobj));
qobject_decref(qobj);
}
+static void qobject_from_qlit_test(void)
+{
+ QObject *obj, *qobj = qobject_from_qlit(&qlit);
+ QDict *qdict;
+ QList *bee;
+
+ qdict = qobject_to(QDict, qobj);
+ g_assert_cmpint(qdict_get_int(qdict, "foo"), ==, 42);
+ g_assert_cmpstr(qdict_get_str(qdict, "bar"), ==, "hello world");
+ g_assert(qobject_type(qdict_get(qdict, "baz")) == QTYPE_QNULL);
+
+ bee = qdict_get_qlist(qdict, "bee");
+ obj = qlist_pop(bee);
+ g_assert_cmpint(qnum_get_int(qobject_to(QNum, obj)), ==, 43);
+ qobject_decref(obj);
+ obj = qlist_pop(bee);
+ g_assert_cmpint(qnum_get_int(qobject_to(QNum, obj)), ==, 44);
+ qobject_decref(obj);
+ obj = qlist_pop(bee);
+ g_assert(qbool_get_bool(qobject_to(QBool, obj)));
+ qobject_decref(obj);
+
+ qobject_decref(qobj);
+}
+
int main(int argc, char **argv)
{
g_test_init(&argc, &argv, NULL);
g_test_add_func("/qlit/equal_qobject", qlit_equal_qobject_test);
+ g_test_add_func("/qlit/qobject_from_qlit", qobject_from_qlit_test);
return g_test_run();
}
diff --git a/tests/check-qnum.c b/tests/check-qnum.c
index 2b667f7ad7..9187da734b 100644
--- a/tests/check-qnum.c
+++ b/tests/check-qnum.c
@@ -126,11 +126,11 @@ static void qobject_to_qnum_test(void)
QNum *qn;
qn = qnum_from_int(0);
- g_assert(qobject_to_qnum(QOBJECT(qn)) == qn);
+ g_assert(qobject_to(QNum, QOBJECT(qn)) == qn);
QDECREF(qn);
qn = qnum_from_double(0);
- g_assert(qobject_to_qnum(QOBJECT(qn)) == qn);
+ g_assert(qobject_to(QNum, QOBJECT(qn)) == qn);
QDECREF(qn);
}
diff --git a/tests/check-qobject.c b/tests/check-qobject.c
index 7a3670643c..7629b8071b 100644
--- a/tests/check-qobject.c
+++ b/tests/check-qobject.c
@@ -275,7 +275,7 @@ static void qobject_is_equal_dict_test(void)
dict_different_null_key, dict_longer, dict_shorter,
dict_nested);
- dict_crumpled = qobject_to_qdict(qdict_crumple(dict_1, &local_err));
+ dict_crumpled = qobject_to(QDict, qdict_crumple(dict_1, &local_err));
g_assert(!local_err);
check_equal(dict_crumpled, dict_nested);
diff --git a/tests/check-qstring.c b/tests/check-qstring.c
index 112ec08967..9c4dd3f94f 100644
--- a/tests/check-qstring.c
+++ b/tests/check-qstring.c
@@ -79,7 +79,7 @@ static void qobject_to_qstring_test(void)
QString *qstring;
qstring = qstring_from_str("foo");
- g_assert(qobject_to_qstring(QOBJECT(qstring)) == qstring);
+ g_assert(qobject_to(QString, QOBJECT(qstring)) == qstring);
QDECREF(qstring);
}
diff --git a/tests/device-introspect-test.c b/tests/device-introspect-test.c
index b80058fe98..a01321aced 100644
--- a/tests/device-introspect-test.c
+++ b/tests/device-introspect-test.c
@@ -52,7 +52,7 @@ static QDict *qom_type_index(QList *types)
QListEntry *e;
QLIST_FOREACH_ENTRY(types, e) {
- QDict *d = qobject_to_qdict(qlist_entry_obj(e));
+ QDict *d = qobject_to(QDict, qlist_entry_obj(e));
const char *name = qdict_get_str(d, "name");
QINCREF(d);
qdict_put(index, name, d);
@@ -85,7 +85,7 @@ static QDict *type_list_find(QList *types, const char *name)
QListEntry *e;
QLIST_FOREACH_ENTRY(types, e) {
- QDict *d = qobject_to_qdict(qlist_entry_obj(e));
+ QDict *d = qobject_to(QDict, qlist_entry_obj(e));
const char *ename = qdict_get_str(d, "name");
if (!strcmp(ename, name)) {
return d;
@@ -151,7 +151,7 @@ static void test_qom_list_parents(const char *parent)
index = qom_type_index(types);
QLIST_FOREACH_ENTRY(types, e) {
- QDict *d = qobject_to_qdict(qlist_entry_obj(e));
+ QDict *d = qobject_to(QDict, qlist_entry_obj(e));
const char *name = qdict_get_str(d, "name");
g_assert(qom_has_parent(index, name, parent));
@@ -173,7 +173,7 @@ static void test_qom_list_fields(void)
non_abstract = qom_list_types(NULL, false);
QLIST_FOREACH_ENTRY(all_types, e) {
- QDict *d = qobject_to_qdict(qlist_entry_obj(e));
+ QDict *d = qobject_to(QDict, qlist_entry_obj(e));
const char *name = qdict_get_str(d, "name");
bool abstract = qdict_haskey(d, "abstract") ?
qdict_get_bool(d, "abstract") :
@@ -216,8 +216,8 @@ static void test_device_intro_concrete(void)
types = device_type_list(false);
QLIST_FOREACH_ENTRY(types, entry) {
- type = qdict_get_try_str(qobject_to_qdict(qlist_entry_obj(entry)),
- "name");
+ type = qdict_get_try_str(qobject_to(QDict, qlist_entry_obj(entry)),
+ "name");
g_assert(type);
test_one_device(type);
}
@@ -238,7 +238,7 @@ static void test_abstract_interfaces(void)
index = qom_type_index(all_types);
QLIST_FOREACH_ENTRY(all_types, e) {
- QDict *d = qobject_to_qdict(qlist_entry_obj(e));
+ QDict *d = qobject_to(QDict, qlist_entry_obj(e));
const char *name = qdict_get_str(d, "name");
/*
diff --git a/tests/libqtest.c b/tests/libqtest.c
index 13c910069b..200b2b9e92 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -430,7 +430,7 @@ static void qmp_response(JSONMessageParser *parser, GQueue *tokens)
}
g_assert(!qmp->response);
- qmp->response = qobject_to_qdict(obj);
+ qmp->response = qobject_to(QDict, obj);
g_assert(qmp->response);
}
@@ -1008,11 +1008,11 @@ void qtest_cb_for_every_machine(void (*cb)(const char *machine))
g_assert(list);
for (p = qlist_first(list); p; p = qlist_next(p)) {
- minfo = qobject_to_qdict(qlist_entry_obj(p));
+ minfo = qobject_to(QDict, qlist_entry_obj(p));
g_assert(minfo);
qobj = qdict_get(minfo, "name");
g_assert(qobj);
- qstr = qobject_to_qstring(qobj);
+ qstr = qobject_to(QString, qobj);
g_assert(qstr);
mname = qstring_get_str(qstr);
cb(mname);
diff --git a/tests/machine-none-test.c b/tests/machine-none-test.c
new file mode 100644
index 0000000000..efdd4be986
--- /dev/null
+++ b/tests/machine-none-test.c
@@ -0,0 +1,103 @@
+/*
+ * Machine 'none' tests.
+ *
+ * Copyright (c) 2018 Red Hat Inc.
+ *
+ * Authors:
+ * Igor Mammedov <imammedo@redhat.com>,
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+
+#include "qemu-common.h"
+#include "qemu/cutils.h"
+#include "libqtest.h"
+#include "qapi/qmp/qdict.h"
+
+
+struct arch2cpu {
+ const char *arch;
+ const char *cpu_model;
+};
+
+static struct arch2cpu cpus_map[] = {
+ /* tested targets list */
+ { "arm", "cortex-a15" },
+ { "aarch64", "cortex-a57" },
+ { "x86_64", "qemu64,apic-id=0" },
+ { "i386", "qemu32,apic-id=0" },
+ { "alpha", "ev67" },
+ { "cris", "crisv32" },
+ { "lm32", "lm32-full" },
+ { "m68k", "m5206" },
+ /* FIXME: { "microblaze", "any" }, doesn't work with -M none -cpu any */
+ /* FIXME: { "microblazeel", "any" }, doesn't work with -M none -cpu any */
+ { "mips", "4Kc" },
+ { "mipsel", "4Kc" },
+ { "mips64", "20Kc" },
+ { "mips64el", "20Kc" },
+ { "moxie", "MoxieLite" },
+ { "nios2", "FIXME" },
+ { "or1k", "or1200" },
+ { "ppc", "604" },
+ { "ppc64", "power8e_v2.1" },
+ { "ppcemb", "440epb" },
+ { "s390x", "qemu" },
+ { "sh4", "sh7750r" },
+ { "sh4eb", "sh7751r" },
+ { "sparc", "LEON2" },
+ { "sparc64", "Fujitsu Sparc64" },
+ { "tricore", "tc1796" },
+ { "unicore32", "UniCore-II" },
+ { "xtensa", "dc233c" },
+ { "xtensaeb", "fsf" },
+ { "hppa", "hppa" },
+ { "riscv64", "rv64gcsu-v1.10.0" },
+ { "riscv32", "rv32gcsu-v1.9.1" },
+};
+
+static const char *get_cpu_model_by_arch(const char *arch)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cpus_map); i++) {
+ if (!strcmp(arch, cpus_map[i].arch)) {
+ return cpus_map[i].cpu_model;
+ }
+ }
+ return NULL;
+}
+
+static void test_machine_cpu_cli(void)
+{
+ QDict *response;
+ const char *arch = qtest_get_arch();
+ const char *cpu_model = get_cpu_model_by_arch(arch);
+
+ if (!cpu_model) {
+ if (!(!strcmp(arch, "microblaze") || !strcmp(arch, "microblazeel"))) {
+ fprintf(stderr, "WARNING: cpu name for target '%s' isn't defined,"
+ " add it to cpus_map\n", arch);
+ }
+ return; /* TODO: die here to force all targets have a test */
+ }
+ global_qtest = qtest_startf("-machine none -cpu '%s'", cpu_model);
+
+ response = qmp("{ 'execute': 'quit' }");
+ g_assert(qdict_haskey(response, "return"));
+ QDECREF(response);
+
+ qtest_quit(global_qtest);
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ qtest_add_func("machine/none/cpu_option", test_machine_cpu_cli);
+
+ return g_test_run();
+}
diff --git a/tests/numa-test.c b/tests/numa-test.c
index 68aca9cb38..0f861d8176 100644
--- a/tests/numa-test.c
+++ b/tests/numa-test.c
@@ -98,7 +98,7 @@ static void test_query_cpus(const void *data)
QDict *cpu, *props;
int64_t cpu_idx, node;
- cpu = qobject_to_qdict(e);
+ cpu = qobject_to(QDict, e);
g_assert(qdict_haskey(cpu, "CPU"));
g_assert(qdict_haskey(cpu, "props"));
@@ -140,7 +140,7 @@ static void pc_numa_cpu(const void *data)
QDict *cpu, *props;
int64_t socket, core, thread, node;
- cpu = qobject_to_qdict(e);
+ cpu = qobject_to(QDict, e);
g_assert(qdict_haskey(cpu, "props"));
props = qdict_get_qdict(cpu, "props");
@@ -193,7 +193,7 @@ static void spapr_numa_cpu(const void *data)
QDict *cpu, *props;
int64_t core, node;
- cpu = qobject_to_qdict(e);
+ cpu = qobject_to(QDict, e);
g_assert(qdict_haskey(cpu, "props"));
props = qdict_get_qdict(cpu, "props");
@@ -236,7 +236,7 @@ static void aarch64_numa_cpu(const void *data)
QDict *cpu, *props;
int64_t thread, node;
- cpu = qobject_to_qdict(e);
+ cpu = qobject_to(QDict, e);
g_assert(qdict_haskey(cpu, "props"));
props = qdict_get_qdict(cpu, "props");
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index 67e417e298..10e68b01d9 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -42,7 +42,7 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
self._print_variants(variants)
def visit_command(self, name, info, arg_type, ret_type,
- gen, success_response, boxed):
+ gen, success_response, boxed, allow_oob):
print('command %s %s -> %s' % \
(name, arg_type and arg_type.name, ret_type and ret_type.name))
print(' gen=%s success_response=%s boxed=%s' % \
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
index b5f88959aa..640a6dfd10 100755
--- a/tests/qemu-iotests/030
+++ b/tests/qemu-iotests/030
@@ -86,11 +86,9 @@ class TestSingleDrive(iotests.QMPTestCase):
result = self.vm.qmp('block-stream', device='drive0')
self.assert_qmp(result, 'return', {})
- result = self.vm.qmp('block-job-pause', device='drive0')
- self.assert_qmp(result, 'return', {})
-
+ self.pause_job('drive0', wait=False)
self.vm.resume_drive('drive0')
- self.pause_job('drive0')
+ self.pause_wait('drive0')
result = self.vm.qmp('query-block-jobs')
offset = self.dictpath(result, 'return[0]/offset')
diff --git a/tests/qemu-iotests/033 b/tests/qemu-iotests/033
index a1d8357331..ee8a1338bb 100755
--- a/tests/qemu-iotests/033
+++ b/tests/qemu-iotests/033
@@ -105,6 +105,7 @@ for align in 512 4k; do
done
done
+_cleanup_test_img
# Trigger truncate that would shrink qcow2 L1 table, which is done by
# clearing one entry (8 bytes) with bdrv_co_pwrite_zeroes()
diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055
index 8a5d9fd269..3437c11507 100755
--- a/tests/qemu-iotests/055
+++ b/tests/qemu-iotests/055
@@ -86,11 +86,9 @@ class TestSingleDrive(iotests.QMPTestCase):
target=target, sync='full')
self.assert_qmp(result, 'return', {})
- result = self.vm.qmp('block-job-pause', device='drive0')
- self.assert_qmp(result, 'return', {})
-
+ self.pause_job('drive0', wait=False)
self.vm.resume_drive('drive0')
- self.pause_job('drive0')
+ self.pause_wait('drive0')
result = self.vm.qmp('query-block-jobs')
offset = self.dictpath(result, 'return[0]/offset')
@@ -303,13 +301,12 @@ class TestSingleTransaction(iotests.QMPTestCase):
])
self.assert_qmp(result, 'return', {})
- result = self.vm.qmp('block-job-pause', device='drive0')
- self.assert_qmp(result, 'return', {})
+ self.pause_job('drive0', wait=False)
result = self.vm.qmp('block-job-set-speed', device='drive0', speed=0)
self.assert_qmp(result, 'return', {})
- self.pause_job('drive0')
+ self.pause_wait('drive0')
result = self.vm.qmp('query-block-jobs')
offset = self.dictpath(result, 'return[0]/offset')
@@ -534,11 +531,9 @@ class TestDriveCompression(iotests.QMPTestCase):
result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args)
self.assert_qmp(result, 'return', {})
- result = self.vm.qmp('block-job-pause', device='drive0')
- self.assert_qmp(result, 'return', {})
-
+ self.pause_job('drive0', wait=False)
self.vm.resume_drive('drive0')
- self.pause_job('drive0')
+ self.pause_wait('drive0')
result = self.vm.qmp('query-block-jobs')
offset = self.dictpath(result, 'return[0]/offset')
diff --git a/tests/qemu-iotests/056 b/tests/qemu-iotests/056
index 04f2c3c841..223292175a 100755
--- a/tests/qemu-iotests/056
+++ b/tests/qemu-iotests/056
@@ -29,6 +29,26 @@ backing_img = os.path.join(iotests.test_dir, 'backing.img')
test_img = os.path.join(iotests.test_dir, 'test.img')
target_img = os.path.join(iotests.test_dir, 'target.img')
+def img_create(img, fmt=iotests.imgfmt, size='64M', **kwargs):
+ fullname = os.path.join(iotests.test_dir, '%s.%s' % (img, fmt))
+ optargs = []
+ for k,v in kwargs.iteritems():
+ optargs = optargs + ['-o', '%s=%s' % (k,v)]
+ args = ['create', '-f', fmt] + optargs + [fullname, size]
+ iotests.qemu_img(*args)
+ return fullname
+
+def try_remove(img):
+ try:
+ os.remove(img)
+ except OSError:
+ pass
+
+def io_write_patterns(img, patterns):
+ for pattern in patterns:
+ iotests.qemu_io('-c', 'write -P%s %s %s' % pattern, img)
+
+
class TestSyncModesNoneAndTop(iotests.QMPTestCase):
image_len = 64 * 1024 * 1024 # MB
@@ -108,5 +128,172 @@ class TestBeforeWriteNotifier(iotests.QMPTestCase):
event = self.cancel_and_wait()
self.assert_qmp(event, 'data/type', 'backup')
+class BackupTest(iotests.QMPTestCase):
+ def setUp(self):
+ self.vm = iotests.VM()
+ self.test_img = img_create('test')
+ self.dest_img = img_create('dest')
+ self.vm.add_drive(self.test_img)
+ self.vm.launch()
+
+ def tearDown(self):
+ self.vm.shutdown()
+ try_remove(self.test_img)
+ try_remove(self.dest_img)
+
+ def hmp_io_writes(self, drive, patterns):
+ for pattern in patterns:
+ self.vm.hmp_qemu_io(drive, 'write -P%s %s %s' % pattern)
+ self.vm.hmp_qemu_io(drive, 'flush')
+
+ def qmp_backup_and_wait(self, cmd='drive-backup', serror=None,
+ aerror=None, **kwargs):
+ if not self.qmp_backup(cmd, serror, **kwargs):
+ return False
+ return self.qmp_backup_wait(kwargs['device'], aerror)
+
+ def qmp_backup(self, cmd='drive-backup',
+ error=None, **kwargs):
+ self.assertTrue('device' in kwargs)
+ res = self.vm.qmp(cmd, **kwargs)
+ if error:
+ self.assert_qmp(res, 'error/desc', error)
+ return False
+ self.assert_qmp(res, 'return', {})
+ return True
+
+ def qmp_backup_wait(self, device, error=None):
+ event = self.vm.event_wait(name="BLOCK_JOB_COMPLETED",
+ match={'data': {'device': device}})
+ self.assertNotEqual(event, None)
+ try:
+ failure = self.dictpath(event, 'data/error')
+ except AssertionError:
+ # Backup succeeded.
+ self.assert_qmp(event, 'data/offset', event['data']['len'])
+ return True
+ else:
+ # Failure.
+ self.assert_qmp(event, 'data/error', qerror)
+ return False
+
+ def test_dismiss_false(self):
+ res = self.vm.qmp('query-block-jobs')
+ self.assert_qmp(res, 'return', [])
+ self.qmp_backup_and_wait(device='drive0', format=iotests.imgfmt,
+ sync='full', target=self.dest_img,
+ auto_dismiss=True)
+ res = self.vm.qmp('query-block-jobs')
+ self.assert_qmp(res, 'return', [])
+
+ def test_dismiss_true(self):
+ res = self.vm.qmp('query-block-jobs')
+ self.assert_qmp(res, 'return', [])
+ self.qmp_backup_and_wait(device='drive0', format=iotests.imgfmt,
+ sync='full', target=self.dest_img,
+ auto_dismiss=False)
+ res = self.vm.qmp('query-block-jobs')
+ self.assert_qmp(res, 'return[0]/status', 'concluded')
+ res = self.vm.qmp('block-job-dismiss', id='drive0')
+ self.assert_qmp(res, 'return', {})
+ res = self.vm.qmp('query-block-jobs')
+ self.assert_qmp(res, 'return', [])
+
+ def test_dismiss_bad_id(self):
+ res = self.vm.qmp('query-block-jobs')
+ self.assert_qmp(res, 'return', [])
+ res = self.vm.qmp('block-job-dismiss', id='foobar')
+ self.assert_qmp(res, 'error/class', 'DeviceNotActive')
+
+ def test_dismiss_collision(self):
+ res = self.vm.qmp('query-block-jobs')
+ self.assert_qmp(res, 'return', [])
+ self.qmp_backup_and_wait(device='drive0', format=iotests.imgfmt,
+ sync='full', target=self.dest_img,
+ auto_dismiss=False)
+ res = self.vm.qmp('query-block-jobs')
+ self.assert_qmp(res, 'return[0]/status', 'concluded')
+ # Leave zombie job un-dismissed, observe a failure:
+ res = self.qmp_backup_and_wait(serror='Need a root block node',
+ device='drive0', format=iotests.imgfmt,
+ sync='full', target=self.dest_img,
+ auto_dismiss=False)
+ self.assertEqual(res, False)
+ # OK, dismiss the zombie.
+ res = self.vm.qmp('block-job-dismiss', id='drive0')
+ self.assert_qmp(res, 'return', {})
+ res = self.vm.qmp('query-block-jobs')
+ self.assert_qmp(res, 'return', [])
+ # Ensure it's really gone.
+ self.qmp_backup_and_wait(device='drive0', format=iotests.imgfmt,
+ sync='full', target=self.dest_img,
+ auto_dismiss=False)
+
+ def dismissal_failure(self, dismissal_opt):
+ res = self.vm.qmp('query-block-jobs')
+ self.assert_qmp(res, 'return', [])
+ # Give blkdebug something to chew on
+ self.hmp_io_writes('drive0',
+ (('0x9a', 0, 512),
+ ('0x55', '8M', '352k'),
+ ('0x78', '15872k', '1M')))
+ # Add destination node via blkdebug
+ res = self.vm.qmp('blockdev-add',
+ node_name='target0',
+ driver=iotests.imgfmt,
+ file={
+ 'driver': 'blkdebug',
+ 'image': {
+ 'driver': 'file',
+ 'filename': self.dest_img
+ },
+ 'inject-error': [{
+ 'event': 'write_aio',
+ 'errno': 5,
+ 'immediately': False,
+ 'once': True
+ }],
+ })
+ self.assert_qmp(res, 'return', {})
+
+ res = self.qmp_backup(cmd='blockdev-backup',
+ device='drive0', target='target0',
+ on_target_error='stop',
+ sync='full',
+ auto_dismiss=dismissal_opt)
+ self.assertTrue(res)
+ event = self.vm.event_wait(name="BLOCK_JOB_ERROR",
+ match={'data': {'device': 'drive0'}})
+ self.assertNotEqual(event, None)
+ # OK, job should be wedged
+ res = self.vm.qmp('query-block-jobs')
+ self.assert_qmp(res, 'return[0]/status', 'paused')
+ res = self.vm.qmp('block-job-dismiss', id='drive0')
+ self.assert_qmp(res, 'error/desc',
+ "Job 'drive0' in state 'paused' cannot accept"
+ " command verb 'dismiss'")
+ res = self.vm.qmp('query-block-jobs')
+ self.assert_qmp(res, 'return[0]/status', 'paused')
+ # OK, unstick job and move forward.
+ res = self.vm.qmp('block-job-resume', device='drive0')
+ self.assert_qmp(res, 'return', {})
+ # And now we need to wait for it to conclude;
+ res = self.qmp_backup_wait(device='drive0')
+ self.assertTrue(res)
+ if not dismissal_opt:
+ # Job should now be languishing:
+ res = self.vm.qmp('query-block-jobs')
+ self.assert_qmp(res, 'return[0]/status', 'concluded')
+ res = self.vm.qmp('block-job-dismiss', id='drive0')
+ self.assert_qmp(res, 'return', {})
+ res = self.vm.qmp('query-block-jobs')
+ self.assert_qmp(res, 'return', [])
+
+ def test_dismiss_premature(self):
+ self.dismissal_failure(False)
+
+ def test_dismiss_erroneous(self):
+ self.dismissal_failure(True)
+
if __name__ == '__main__':
iotests.main(supported_fmts=['qcow2', 'qed'])
diff --git a/tests/qemu-iotests/056.out b/tests/qemu-iotests/056.out
index 8d7e996700..dae404e278 100644
--- a/tests/qemu-iotests/056.out
+++ b/tests/qemu-iotests/056.out
@@ -1,5 +1,5 @@
-...
+.........
----------------------------------------------------------------------
-Ran 3 tests
+Ran 9 tests
OK
diff --git a/tests/qemu-iotests/089 b/tests/qemu-iotests/089
index 0b059aba90..aa1ba4a98e 100755
--- a/tests/qemu-iotests/089
+++ b/tests/qemu-iotests/089
@@ -82,6 +82,26 @@ $QEMU_IO_PROG --cache $CACHEMODE \
$QEMU_IO -c 'read -P 42 0 512' "$TEST_IMG" | _filter_qemu_io
+echo
+echo "=== Testing correct handling of 'backing':null ==="
+echo
+
+_make_test_img -b "$TEST_IMG.base" $IMG_SIZE
+
+# This should read 42
+$QEMU_IO -c 'read -P 42 0 512' "$TEST_IMG" | _filter_qemu_io
+
+# This should read 0
+$QEMU_IO -c 'read -P 0 0 512' "json:{\
+ 'driver': '$IMGFMT',
+ 'file': {
+ 'driver': 'file',
+ 'filename': '$TEST_IMG'
+ },
+ 'backing': null
+}" | _filter_qemu_io
+
+
# Taken from test 071
echo
echo "=== Testing blkdebug ==="
diff --git a/tests/qemu-iotests/089.out b/tests/qemu-iotests/089.out
index 0bf5a13ec1..89e3e4340a 100644
--- a/tests/qemu-iotests/089.out
+++ b/tests/qemu-iotests/089.out
@@ -19,6 +19,14 @@ Pattern verification failed at offset 0, 512 bytes
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+=== Testing correct handling of 'backing':null ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
=== Testing blkdebug ===
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
diff --git a/tests/qemu-iotests/109.out b/tests/qemu-iotests/109.out
index c189e2833d..8a9b93672b 100644
--- a/tests/qemu-iotests/109.out
+++ b/tests/qemu-iotests/109.out
@@ -19,7 +19,7 @@ read 65536/65536 bytes at offset 0
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
-{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 1024, "offset": 1024, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 1024, "offset": 1024, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
@@ -45,7 +45,7 @@ read 65536/65536 bytes at offset 0
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 197120, "offset": 197120, "speed": 0, "type": "mirror"}}
-{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 197120, "offset": 197120, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 197120, "offset": 197120, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 197120, "offset": 197120, "speed": 0, "type": "mirror"}}
@@ -71,7 +71,7 @@ read 65536/65536 bytes at offset 0
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
-{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 327680, "offset": 327680, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 327680, "offset": 327680, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
@@ -97,7 +97,7 @@ read 65536/65536 bytes at offset 0
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
-{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 1024, "offset": 1024, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 1024, "offset": 1024, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
@@ -123,7 +123,7 @@ read 65536/65536 bytes at offset 0
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
-{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 65536, "offset": 65536, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 65536, "offset": 65536, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
@@ -149,7 +149,7 @@ read 65536/65536 bytes at offset 0
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
-{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 2560, "offset": 2560, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 2560, "offset": 2560, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
@@ -174,7 +174,7 @@ read 65536/65536 bytes at offset 0
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
-{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 2560, "offset": 2560, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 2560, "offset": 2560, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
@@ -199,7 +199,7 @@ read 65536/65536 bytes at offset 0
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 31457280, "offset": 31457280, "speed": 0, "type": "mirror"}}
-{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 31457280, "offset": 31457280, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 31457280, "offset": 31457280, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 31457280, "offset": 31457280, "speed": 0, "type": "mirror"}}
@@ -224,7 +224,7 @@ read 65536/65536 bytes at offset 0
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
-{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 327680, "offset": 327680, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 327680, "offset": 327680, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
@@ -249,7 +249,7 @@ read 65536/65536 bytes at offset 0
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2048, "offset": 2048, "speed": 0, "type": "mirror"}}
-{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 2048, "offset": 2048, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 2048, "offset": 2048, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2048, "offset": 2048, "speed": 0, "type": "mirror"}}
@@ -265,7 +265,7 @@ Automatically detecting the format is dangerous for raw images, write operations
Specify the 'raw' format explicitly to remove the restrictions.
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
-{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 512, "offset": 512, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 512, "offset": 512, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
@@ -274,7 +274,7 @@ Images are identical.
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
-{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 512, "offset": 512, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+{"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 512, "offset": 512, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
diff --git a/tests/qemu-iotests/146.out b/tests/qemu-iotests/146.out
index db6b296b9e..1332189d87 100644
--- a/tests/qemu-iotests/146.out
+++ b/tests/qemu-iotests/146.out
@@ -54,7 +54,7 @@ Formatting 'TEST_DIR/IMGFMT-create-test.IMGFMT', fmt=IMGFMT size=4294967296
=== Testing Image create, force_size ===
-Formatting 'TEST_DIR/IMGFMT-create-test.IMGFMT', fmt=IMGFMT size=4294967296 force_size=on
+Formatting 'TEST_DIR/IMGFMT-create-test.IMGFMT', fmt=IMGFMT size=4294967296
=== Read created image, default opts ====
diff --git a/tests/qemu-iotests/153 b/tests/qemu-iotests/153
index adfd02695b..a0fd815483 100755
--- a/tests/qemu-iotests/153
+++ b/tests/qemu-iotests/153
@@ -178,6 +178,18 @@ rm -f "${TEST_IMG}.lnk" &>/dev/null
ln -s ${TEST_IMG} "${TEST_IMG}.lnk" || echo "Failed to create link"
_run_qemu_with_images "${TEST_IMG}.lnk" "${TEST_IMG}"
+echo
+echo "== Active commit to intermediate layer should work when base in use =="
+_launch_qemu -drive format=$IMGFMT,file="${TEST_IMG}.a",id=drive0,if=none \
+ -device virtio-blk,drive=drive0
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'qmp_capabilities' }" \
+ 'return'
+_run_cmd $QEMU_IMG commit -b "${TEST_IMG}.b" "${TEST_IMG}.c"
+
+_cleanup_qemu
+
_launch_qemu
_send_qemu_cmd $QEMU_HANDLE \
diff --git a/tests/qemu-iotests/153.out b/tests/qemu-iotests/153.out
index 34309cfb20..bb721cb747 100644
--- a/tests/qemu-iotests/153.out
+++ b/tests/qemu-iotests/153.out
@@ -372,6 +372,11 @@ Is another process using the image?
== Symbolic link ==
QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2: Failed to get "write" lock
Is another process using the image?
+
+== Active commit to intermediate layer should work when base in use ==
+{"return": {}}
+
+_qemu_img_wrapper commit -b TEST_DIR/t.qcow2.b TEST_DIR/t.qcow2.c
{"return": {}}
Adding drive
diff --git a/tests/qemu-iotests/169 b/tests/qemu-iotests/169
new file mode 100755
index 0000000000..3a8db91f6f
--- /dev/null
+++ b/tests/qemu-iotests/169
@@ -0,0 +1,156 @@
+#!/usr/bin/env python
+#
+# Tests for dirty bitmaps migration.
+#
+# Copyright (c) 2016-2017 Virtuozzo International GmbH. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import os
+import iotests
+import time
+import itertools
+import operator
+import new
+from iotests import qemu_img
+
+
+disk_a = os.path.join(iotests.test_dir, 'disk_a')
+disk_b = os.path.join(iotests.test_dir, 'disk_b')
+size = '1M'
+mig_file = os.path.join(iotests.test_dir, 'mig_file')
+
+
+class TestDirtyBitmapMigration(iotests.QMPTestCase):
+ def tearDown(self):
+ self.vm_a.shutdown()
+ self.vm_b.shutdown()
+ os.remove(disk_a)
+ os.remove(disk_b)
+ os.remove(mig_file)
+
+ def setUp(self):
+ qemu_img('create', '-f', iotests.imgfmt, disk_a, size)
+ qemu_img('create', '-f', iotests.imgfmt, disk_b, size)
+
+ self.vm_a = iotests.VM(path_suffix='a').add_drive(disk_a)
+ self.vm_a.launch()
+
+ self.vm_b = iotests.VM(path_suffix='b')
+ self.vm_b.add_incoming("exec: cat '" + mig_file + "'")
+
+ def add_bitmap(self, vm, granularity, persistent):
+ params = {'node': 'drive0',
+ 'name': 'bitmap0',
+ 'granularity': granularity}
+ if persistent:
+ params['persistent'] = True
+ params['autoload'] = True
+
+ result = vm.qmp('block-dirty-bitmap-add', **params)
+ self.assert_qmp(result, 'return', {});
+
+ def get_bitmap_hash(self, vm):
+ result = vm.qmp('x-debug-block-dirty-bitmap-sha256',
+ node='drive0', name='bitmap0')
+ return result['return']['sha256']
+
+ def check_bitmap(self, vm, sha256):
+ result = vm.qmp('x-debug-block-dirty-bitmap-sha256',
+ node='drive0', name='bitmap0')
+ if sha256:
+ self.assert_qmp(result, 'return/sha256', sha256);
+ else:
+ self.assert_qmp(result, 'error/desc',
+ "Dirty bitmap 'bitmap0' not found");
+
+ def do_test_migration(self, persistent, migrate_bitmaps, online,
+ shared_storage):
+ granularity = 512
+
+ # regions = ((start, count), ...)
+ regions = ((0, 0x10000),
+ (0xf0000, 0x10000),
+ (0xa0201, 0x1000))
+
+ should_migrate = migrate_bitmaps or persistent and shared_storage
+
+ self.vm_b.add_drive(disk_a if shared_storage else disk_b)
+
+ if online:
+ os.mkfifo(mig_file)
+ self.vm_b.launch()
+
+ self.add_bitmap(self.vm_a, granularity, persistent)
+ for r in regions:
+ self.vm_a.hmp_qemu_io('drive0', 'write %d %d' % r)
+ sha256 = self.get_bitmap_hash(self.vm_a)
+
+ if migrate_bitmaps:
+ capabilities = [{'capability': 'dirty-bitmaps', 'state': True}]
+
+ result = self.vm_a.qmp('migrate-set-capabilities',
+ capabilities=capabilities)
+ self.assert_qmp(result, 'return', {})
+
+ if online:
+ result = self.vm_b.qmp('migrate-set-capabilities',
+ capabilities=capabilities)
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm_a.qmp('migrate-set-capabilities',
+ capabilities=[{'capability': 'events',
+ 'state': True}])
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm_a.qmp('migrate', uri='exec:cat>' + mig_file)
+ while True:
+ event = self.vm_a.event_wait('MIGRATION')
+ if event['data']['status'] == 'completed':
+ break
+
+ if not online:
+ self.vm_a.shutdown()
+ self.vm_b.launch()
+ # TODO enable bitmap capability for vm_b in this case
+
+ self.vm_b.event_wait("RESUME", timeout=10.0)
+
+ self.check_bitmap(self.vm_b, sha256 if should_migrate else False)
+
+ if should_migrate:
+ self.vm_b.shutdown()
+ self.vm_b.launch()
+ self.check_bitmap(self.vm_b, sha256 if persistent else False)
+
+
+def inject_test_case(klass, name, method, *args, **kwargs):
+ mc = operator.methodcaller(method, *args, **kwargs)
+ setattr(klass, 'test_' + name, new.instancemethod(mc, None, klass))
+
+for cmb in list(itertools.product((True, False), repeat=3)):
+ name = ('_' if cmb[0] else '_not_') + 'persistent_'
+ name += ('_' if cmb[1] else '_not_') + 'migbitmap_'
+ name += '_online' if cmb[2] else '_offline'
+
+ # TODO fix shared-storage bitmap migration and enable cases for it
+ args = list(cmb) + [False]
+
+ inject_test_case(TestDirtyBitmapMigration, name, 'do_test_migration',
+ *args)
+
+
+if __name__ == '__main__':
+ iotests.main(supported_fmts=['qcow2'])
diff --git a/tests/qemu-iotests/169.out b/tests/qemu-iotests/169.out
new file mode 100644
index 0000000000..594c16f49f
--- /dev/null
+++ b/tests/qemu-iotests/169.out
@@ -0,0 +1,5 @@
+........
+----------------------------------------------------------------------
+Ran 8 tests
+
+OK
diff --git a/tests/qemu-iotests/181 b/tests/qemu-iotests/181
index 0c91e8f9de..5e767c6195 100755
--- a/tests/qemu-iotests/181
+++ b/tests/qemu-iotests/181
@@ -44,7 +44,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt generic
# Formats that do not support live migration
-_unsupported_fmt qcow vdi vhdx vmdk vpc vvfat
+_unsupported_fmt qcow vdi vhdx vmdk vpc vvfat parallels
_supported_proto generic
_supported_os Linux
diff --git a/tests/qemu-iotests/199 b/tests/qemu-iotests/199
new file mode 100755
index 0000000000..651e8df5d9
--- /dev/null
+++ b/tests/qemu-iotests/199
@@ -0,0 +1,118 @@
+#!/usr/bin/env python
+#
+# Tests for dirty bitmaps postcopy migration.
+#
+# Copyright (c) 2016-2017 Virtuozzo International GmbH. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import os
+import iotests
+import time
+from iotests import qemu_img
+
+disk_a = os.path.join(iotests.test_dir, 'disk_a')
+disk_b = os.path.join(iotests.test_dir, 'disk_b')
+size = '256G'
+fifo = os.path.join(iotests.test_dir, 'mig_fifo')
+
+class TestDirtyBitmapPostcopyMigration(iotests.QMPTestCase):
+
+ def tearDown(self):
+ self.vm_a.shutdown()
+ self.vm_b.shutdown()
+ os.remove(disk_a)
+ os.remove(disk_b)
+ os.remove(fifo)
+
+ def setUp(self):
+ os.mkfifo(fifo)
+ qemu_img('create', '-f', iotests.imgfmt, disk_a, size)
+ qemu_img('create', '-f', iotests.imgfmt, disk_b, size)
+ self.vm_a = iotests.VM(path_suffix='a').add_drive(disk_a)
+ self.vm_b = iotests.VM(path_suffix='b').add_drive(disk_b)
+ self.vm_b.add_incoming("exec: cat '" + fifo + "'")
+ self.vm_a.launch()
+ self.vm_b.launch()
+
+ def test_postcopy(self):
+ write_size = 0x40000000
+ granularity = 512
+ chunk = 4096
+
+ result = self.vm_a.qmp('block-dirty-bitmap-add', node='drive0',
+ name='bitmap', granularity=granularity)
+ self.assert_qmp(result, 'return', {});
+
+ s = 0
+ while s < write_size:
+ self.vm_a.hmp_qemu_io('drive0', 'write %d %d' % (s, chunk))
+ s += 0x10000
+ s = 0x8000
+ while s < write_size:
+ self.vm_a.hmp_qemu_io('drive0', 'write %d %d' % (s, chunk))
+ s += 0x10000
+
+ result = self.vm_a.qmp('x-debug-block-dirty-bitmap-sha256',
+ node='drive0', name='bitmap')
+ sha256 = result['return']['sha256']
+
+ result = self.vm_a.qmp('block-dirty-bitmap-clear', node='drive0',
+ name='bitmap')
+ self.assert_qmp(result, 'return', {});
+ s = 0
+ while s < write_size:
+ self.vm_a.hmp_qemu_io('drive0', 'write %d %d' % (s, chunk))
+ s += 0x10000
+
+ bitmaps_cap = {'capability': 'dirty-bitmaps', 'state': True}
+ events_cap = {'capability': 'events', 'state': True}
+
+ result = self.vm_a.qmp('migrate-set-capabilities',
+ capabilities=[bitmaps_cap, events_cap])
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm_b.qmp('migrate-set-capabilities',
+ capabilities=[bitmaps_cap])
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm_a.qmp('migrate', uri='exec:cat>' + fifo)
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm_a.qmp('migrate-start-postcopy')
+ self.assert_qmp(result, 'return', {})
+
+ while True:
+ event = self.vm_a.event_wait('MIGRATION')
+ if event['data']['status'] == 'completed':
+ break
+
+ s = 0x8000
+ while s < write_size:
+ self.vm_b.hmp_qemu_io('drive0', 'write %d %d' % (s, chunk))
+ s += 0x10000
+
+ result = self.vm_b.qmp('query-block');
+ while len(result['return'][0]['dirty-bitmaps']) > 1:
+ time.sleep(2)
+ result = self.vm_b.qmp('query-block');
+
+ result = self.vm_b.qmp('x-debug-block-dirty-bitmap-sha256',
+ node='drive0', name='bitmap')
+
+ self.assert_qmp(result, 'return/sha256', sha256);
+
+if __name__ == '__main__':
+ iotests.main(supported_fmts=['qcow2'], supported_cache_modes=['none'])
diff --git a/tests/qemu-iotests/199.out b/tests/qemu-iotests/199.out
new file mode 100644
index 0000000000..ae1213e6f8
--- /dev/null
+++ b/tests/qemu-iotests/199.out
@@ -0,0 +1,5 @@
+.
+----------------------------------------------------------------------
+Ran 1 tests
+
+OK
diff --git a/tests/qemu-iotests/208 b/tests/qemu-iotests/208
new file mode 100755
index 0000000000..4e82b96c82
--- /dev/null
+++ b/tests/qemu-iotests/208
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2018 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Creator/Owner: Stefan Hajnoczi <stefanha@redhat.com>
+#
+# Check that the runtime NBD server does not crash when stopped after
+# blockdev-snapshot-sync.
+
+import iotests
+
+with iotests.FilePath('disk.img') as disk_img_path, \
+ iotests.FilePath('disk-snapshot.img') as disk_snapshot_img_path, \
+ iotests.FilePath('nbd.sock') as nbd_sock_path, \
+ iotests.VM() as vm:
+
+ img_size = '10M'
+ iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, disk_img_path, img_size)
+
+ iotests.log('Launching VM...')
+ (vm.add_drive(disk_img_path, 'node-name=drive0-node', interface='none')
+ .launch())
+
+ iotests.log('Starting NBD server...')
+ iotests.log(vm.qmp('nbd-server-start', addr={
+ "type": "unix",
+ "data": {
+ "path": nbd_sock_path,
+ }
+ }))
+
+ iotests.log('Adding NBD export...')
+ iotests.log(vm.qmp('nbd-server-add', device='drive0-node', writable=True))
+
+ iotests.log('Creating external snapshot...')
+ iotests.log(vm.qmp('blockdev-snapshot-sync',
+ node_name='drive0-node',
+ snapshot_node_name='drive0-snapshot-node',
+ snapshot_file=disk_snapshot_img_path))
+
+ iotests.log('Stopping NBD server...')
+ iotests.log(vm.qmp('nbd-server-stop'))
diff --git a/tests/qemu-iotests/208.out b/tests/qemu-iotests/208.out
new file mode 100644
index 0000000000..3687e9d0dd
--- /dev/null
+++ b/tests/qemu-iotests/208.out
@@ -0,0 +1,9 @@
+Launching VM...
+Starting NBD server...
+{u'return': {}}
+Adding NBD export...
+{u'return': {}}
+Creating external snapshot...
+{u'return': {}}
+Stopping NBD server...
+{u'return': {}}
diff --git a/tests/qemu-iotests/209 b/tests/qemu-iotests/209
new file mode 100755
index 0000000000..259e991ec6
--- /dev/null
+++ b/tests/qemu-iotests/209
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+#
+# Tests for NBD BLOCK_STATUS extension
+#
+# Copyright (c) 2018 Virtuozzo International GmbH
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import iotests
+from iotests import qemu_img_create, qemu_io, qemu_img_verbose, qemu_nbd, \
+ file_path
+
+iotests.verify_image_format(supported_fmts=['qcow2'])
+
+disk, nbd_sock = file_path('disk', 'nbd-sock')
+nbd_uri = 'nbd+unix:///exp?socket=' + nbd_sock
+
+qemu_img_create('-f', iotests.imgfmt, disk, '1M')
+qemu_io('-f', iotests.imgfmt, '-c', 'write 0 512K', disk)
+
+qemu_nbd('-k', nbd_sock, '-x', 'exp', '-f', iotests.imgfmt, disk)
+qemu_img_verbose('map', '-f', 'raw', '--output=json', nbd_uri)
diff --git a/tests/qemu-iotests/209.out b/tests/qemu-iotests/209.out
new file mode 100644
index 0000000000..0d29724e84
--- /dev/null
+++ b/tests/qemu-iotests/209.out
@@ -0,0 +1,2 @@
+[{ "start": 0, "length": 524288, "depth": 0, "zero": false, "data": true},
+{ "start": 524288, "length": 524288, "depth": 0, "zero": true, "data": false}]
diff --git a/tests/qemu-iotests/210 b/tests/qemu-iotests/210
new file mode 100755
index 0000000000..96a5213e77
--- /dev/null
+++ b/tests/qemu-iotests/210
@@ -0,0 +1,210 @@
+#!/bin/bash
+#
+# Test luks and file image creation
+#
+# Copyright (C) 2018 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=kwolf@redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+status=1 # failure is the default!
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt luks
+_supported_proto file
+_supported_os Linux
+
+function do_run_qemu()
+{
+ echo Testing: "$@"
+ $QEMU -nographic -qmp stdio -serial none "$@"
+ echo
+}
+
+function run_qemu()
+{
+ do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \
+ | _filter_qemu | _filter_imgfmt \
+ | _filter_actual_image_size
+}
+
+echo
+echo "=== Successful image creation (defaults) ==="
+echo
+
+size=$((128 * 1024 * 1024))
+
+run_qemu -object secret,id=keysec0,data="foo" <<EOF
+{ "execute": "qmp_capabilities" }
+{ "execute": "x-blockdev-create",
+ "arguments": {
+ "driver": "file",
+ "filename": "$TEST_IMG_FILE",
+ "size": 0
+ }
+}
+{ "execute": "blockdev-add",
+ "arguments": {
+ "driver": "file",
+ "node-name": "imgfile",
+ "filename": "$TEST_IMG_FILE"
+ }
+}
+{ "execute": "x-blockdev-create",
+ "arguments": {
+ "driver": "$IMGFMT",
+ "file": "imgfile",
+ "key-secret": "keysec0",
+ "size": $size,
+ "iter-time": 10
+ }
+}
+{ "execute": "quit" }
+EOF
+
+_img_info --format-specific | _filter_img_info --format-specific
+
+echo
+echo "=== Successful image creation (with non-default options) ==="
+echo
+
+# Choose a different size to show that we got a new image
+size=$((64 * 1024 * 1024))
+
+run_qemu -object secret,id=keysec0,data="foo" <<EOF
+{ "execute": "qmp_capabilities" }
+{ "execute": "x-blockdev-create",
+ "arguments": {
+ "driver": "file",
+ "filename": "$TEST_IMG_FILE",
+ "size": 0
+ }
+}
+{ "execute": "x-blockdev-create",
+ "arguments": {
+ "driver": "$IMGFMT",
+ "file": {
+ "driver": "file",
+ "filename": "$TEST_IMG_FILE"
+ },
+ "size": $size,
+ "key-secret": "keysec0",
+ "cipher-alg": "twofish-128",
+ "cipher-mode": "ctr",
+ "ivgen-alg": "plain64",
+ "ivgen-hash-alg": "md5",
+ "hash-alg": "sha1",
+ "iter-time": 10
+ }
+}
+{ "execute": "quit" }
+EOF
+
+_img_info --format-specific | _filter_img_info --format-specific
+
+echo
+echo "=== Invalid BlockdevRef ==="
+echo
+
+run_qemu <<EOF
+{ "execute": "qmp_capabilities" }
+{ "execute": "x-blockdev-create",
+ "arguments": {
+ "driver": "$IMGFMT",
+ "file": "this doesn't exist",
+ "size": $size
+ }
+}
+{ "execute": "quit" }
+EOF
+
+echo
+echo "=== Zero size ==="
+echo
+
+run_qemu -blockdev driver=file,filename="$TEST_IMG_FILE",node-name=node0 \
+ -object secret,id=keysec0,data="foo" <<EOF
+{ "execute": "qmp_capabilities" }
+{ "execute": "x-blockdev-create",
+ "arguments": {
+ "driver": "$IMGFMT",
+ "file": "node0",
+ "key-secret": "keysec0",
+ "size": 0,
+ "iter-time": 10
+ }
+}
+{ "execute": "quit" }
+EOF
+
+_img_info | _filter_img_info
+
+
+echo
+echo "=== Invalid sizes ==="
+echo
+
+# TODO Negative image sizes aren't handled correctly, but this is a problem
+# with QAPI's implementation of the 'size' type and affects other commands as
+# well. Once this is fixed, we may want to add a test case here.
+
+# 1. 2^64 - 512
+# 2. 2^63 = 8 EB (qemu-img enforces image sizes less than this)
+# 3. 2^63 - 512 (generally valid, but with the crypto header the file will
+# exceed 63 bits)
+
+run_qemu -blockdev driver=file,filename="$TEST_IMG_FILE",node-name=node0 \
+ -object secret,id=keysec0,data="foo" <<EOF
+{ "execute": "qmp_capabilities" }
+{ "execute": "x-blockdev-create",
+ "arguments": {
+ "driver": "$IMGFMT",
+ "file": "node0",
+ "key-secret": "keysec0",
+ "size": 18446744073709551104
+ }
+}
+{ "execute": "x-blockdev-create",
+ "arguments": {
+ "driver": "$IMGFMT",
+ "file": "node0",
+ "key-secret": "keysec0",
+ "size": 9223372036854775808
+ }
+}
+{ "execute": "x-blockdev-create",
+ "arguments": {
+ "driver": "$IMGFMT",
+ "file": "node0",
+ "key-secret": "keysec0",
+ "size": 9223372036854775296
+ }
+}
+{ "execute": "quit" }
+EOF
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/210.out b/tests/qemu-iotests/210.out
new file mode 100644
index 0000000000..8fcab65909
--- /dev/null
+++ b/tests/qemu-iotests/210.out
@@ -0,0 +1,136 @@
+QA output created by 210
+
+=== Successful image creation (defaults) ===
+
+Testing: -object secret,id=keysec0,data=foo
+QMP_VERSION
+{"return": {}}
+{"return": {}}
+{"return": {}}
+{"return": {}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+
+image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "key-secret": "keysec0"}
+file format: IMGFMT
+virtual size: 128M (134217728 bytes)
+Format specific information:
+ ivgen alg: plain64
+ hash alg: sha256
+ cipher alg: aes-256
+ uuid: 00000000-0000-0000-0000-000000000000
+ cipher mode: xts
+ slots:
+ [0]:
+ active: true
+ iters: 1024
+ key offset: 4096
+ stripes: 4000
+ [1]:
+ active: false
+ key offset: 262144
+ [2]:
+ active: false
+ key offset: 520192
+ [3]:
+ active: false
+ key offset: 778240
+ [4]:
+ active: false
+ key offset: 1036288
+ [5]:
+ active: false
+ key offset: 1294336
+ [6]:
+ active: false
+ key offset: 1552384
+ [7]:
+ active: false
+ key offset: 1810432
+ payload offset: 2068480
+ master key iters: 1024
+
+=== Successful image creation (with non-default options) ===
+
+Testing: -object secret,id=keysec0,data=foo
+QMP_VERSION
+{"return": {}}
+{"return": {}}
+{"return": {}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+
+image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "key-secret": "keysec0"}
+file format: IMGFMT
+virtual size: 64M (67108864 bytes)
+Format specific information:
+ ivgen alg: plain64
+ hash alg: sha1
+ cipher alg: twofish-128
+ uuid: 00000000-0000-0000-0000-000000000000
+ cipher mode: ctr
+ slots:
+ [0]:
+ active: true
+ iters: 1024
+ key offset: 4096
+ stripes: 4000
+ [1]:
+ active: false
+ key offset: 69632
+ [2]:
+ active: false
+ key offset: 135168
+ [3]:
+ active: false
+ key offset: 200704
+ [4]:
+ active: false
+ key offset: 266240
+ [5]:
+ active: false
+ key offset: 331776
+ [6]:
+ active: false
+ key offset: 397312
+ [7]:
+ active: false
+ key offset: 462848
+ payload offset: 528384
+ master key iters: 1024
+
+=== Invalid BlockdevRef ===
+
+Testing:
+QMP_VERSION
+{"return": {}}
+{"error": {"class": "GenericError", "desc": "Cannot find device=this doesn't exist nor node_name=this doesn't exist"}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+
+
+=== Zero size ===
+
+Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -object secret,id=keysec0,data=foo
+QMP_VERSION
+{"return": {}}
+{"return": {}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+
+image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "key-secret": "keysec0"}
+file format: IMGFMT
+virtual size: 0 (0 bytes)
+
+=== Invalid sizes ===
+
+Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -object secret,id=keysec0,data=foo
+QMP_VERSION
+{"return": {}}
+{"error": {"class": "GenericError", "desc": "The requested file size is too large"}}
+{"error": {"class": "GenericError", "desc": "The requested file size is too large"}}
+{"error": {"class": "GenericError", "desc": "The requested file size is too large"}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+
+*** done
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
index e6b6ff7a04..ec8033350d 100755
--- a/tests/qemu-iotests/check
+++ b/tests/qemu-iotests/check
@@ -92,7 +92,7 @@ set_prog_path()
{
p=`command -v $1 2> /dev/null`
if [ -n "$p" -a -x "$p" ]; then
- realpath -- "$(type -p "$p")"
+ type -p "$p"
else
return 1
fi
@@ -284,7 +284,6 @@ testlist options
-parallels)
IMGFMT=parallels
- IMGFMT_GENERIC=false
xpand=false
;;
@@ -555,7 +554,7 @@ then
[ "$QEMU_PROG" = "" ] && _init_error "qemu not found"
fi
fi
-export QEMU_PROG=$(realpath -- "$(type -p "$QEMU_PROG")")
+export QEMU_PROG="$(type -p "$QEMU_PROG")"
if [ -z "$QEMU_IMG_PROG" ]; then
if [ -x "$build_iotests/qemu-img" ]; then
@@ -566,7 +565,7 @@ if [ -z "$QEMU_IMG_PROG" ]; then
_init_error "qemu-img not found"
fi
fi
-export QEMU_IMG_PROG=$(realpath -- "$(type -p "$QEMU_IMG_PROG")")
+export QEMU_IMG_PROG="$(type -p "$QEMU_IMG_PROG")"
if [ -z "$QEMU_IO_PROG" ]; then
if [ -x "$build_iotests/qemu-io" ]; then
@@ -577,7 +576,7 @@ if [ -z "$QEMU_IO_PROG" ]; then
_init_error "qemu-io not found"
fi
fi
-export QEMU_IO_PROG=$(realpath -- "$(type -p "$QEMU_IO_PROG")")
+export QEMU_IO_PROG="$(type -p "$QEMU_IO_PROG")"
if [ -z $QEMU_NBD_PROG ]; then
if [ -x "$build_iotests/qemu-nbd" ]; then
@@ -588,7 +587,7 @@ if [ -z $QEMU_NBD_PROG ]; then
_init_error "qemu-nbd not found"
fi
fi
-export QEMU_NBD_PROG=$(realpath -- "$(type -p "$QEMU_NBD_PROG")")
+export QEMU_NBD_PROG="$(type -p "$QEMU_NBD_PROG")"
if [ -z "$QEMU_VXHS_PROG" ]; then
export QEMU_VXHS_PROG="`set_prog_path qnio_server`"
@@ -812,7 +811,7 @@ do
else
echo " - output mismatch (see $seq.out.bad)"
mv $tmp.out $seq.out.bad
- $diff -w "$reference" $(realpath $seq.out.bad)
+ $diff -w "$reference" "$PWD"/$seq.out.bad
err=true
fi
fi
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index 6fa0495e10..9a65a11026 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -332,7 +332,7 @@ _img_info()
discard=0
regex_json_spec_start='^ *"format-specific": \{'
- $QEMU_IMG info "$@" "$TEST_IMG" 2>&1 | \
+ $QEMU_IMG info $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" 2>&1 | \
sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
-e "s#$TEST_DIR#TEST_DIR#g" \
-e "s#$IMGFMT#IMGFMT#g" \
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index c401791fcd..efe0e958f2 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -169,6 +169,7 @@
162 auto quick
163 rw auto quick
165 rw auto quick
+169 rw auto quick
170 rw auto quick
171 rw auto quick
172 auto
@@ -196,6 +197,7 @@
196 rw auto quick
197 rw auto quick
198 rw auto
+199 rw auto
200 rw auto
201 rw auto migration
202 rw auto quick
@@ -204,3 +206,6 @@
205 rw auto quick
206 rw auto
207 rw auto
+208 rw auto quick
+209 rw auto quick
+210 rw auto
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 1bcc9ca57d..b5d7945af8 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -23,12 +23,14 @@ import subprocess
import string
import unittest
import sys
-sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'scripts'))
-import qtest
import struct
import json
import signal
import logging
+import atexit
+
+sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'scripts'))
+import qtest
# This will not work if arguments contain spaces but is necessary if we
@@ -249,6 +251,37 @@ class FilePath(object):
return False
+def file_path_remover():
+ for path in reversed(file_path_remover.paths):
+ try:
+ os.remove(path)
+ except OSError:
+ pass
+
+
+def file_path(*names):
+ ''' Another way to get auto-generated filename that cleans itself up.
+
+ Use is as simple as:
+
+ img_a, img_b = file_path('a.img', 'b.img')
+ sock = file_path('socket')
+ '''
+
+ if not hasattr(file_path_remover, 'paths'):
+ file_path_remover.paths = []
+ atexit.register(file_path_remover)
+
+ paths = []
+ for name in names:
+ filename = '{0}-{1}'.format(os.getpid(), name)
+ path = os.path.join(test_dir, filename)
+ file_path_remover.paths.append(path)
+ paths.append(path)
+
+ return paths[0] if len(paths) == 1 else paths
+
+
class VM(qtest.QEMUQtestMachine):
'''A QEMU VM'''
@@ -473,10 +506,7 @@ class QMPTestCase(unittest.TestCase):
event = self.wait_until_completed(drive=drive)
self.assert_qmp(event, 'data/type', 'mirror')
- def pause_job(self, job_id='job0'):
- result = self.vm.qmp('block-job-pause', device=job_id)
- self.assert_qmp(result, 'return', {})
-
+ def pause_wait(self, job_id='job0'):
with Timeout(1, "Timeout waiting for job to pause"):
while True:
result = self.vm.qmp('query-block-jobs')
@@ -484,6 +514,13 @@ class QMPTestCase(unittest.TestCase):
if job['device'] == job_id and job['paused'] == True and job['busy'] == False:
return job
+ def pause_job(self, job_id='job0', wait=True):
+ result = self.vm.qmp('block-job-pause', device=job_id)
+ self.assert_qmp(result, 'return', {})
+ if wait:
+ return self.pause_wait(job_id)
+ return result
+
def notrun(reason):
'''Skip this test suite'''
@@ -504,6 +541,10 @@ def verify_platform(supported_oses=['linux']):
if True not in [sys.platform.startswith(x) for x in supported_oses]:
notrun('not suitable for this OS: %s' % sys.platform)
+def verify_cache_mode(supported_cache_modes=[]):
+ if supported_cache_modes and (cachemode not in supported_cache_modes):
+ notrun('not suitable for this cache mode: %s' % cachemode)
+
def supports_quorum():
return 'quorum' in qemu_img_pipe('--help')
@@ -512,7 +553,7 @@ def verify_quorum():
if not supports_quorum():
notrun('quorum support missing')
-def main(supported_fmts=[], supported_oses=['linux']):
+def main(supported_fmts=[], supported_oses=['linux'], supported_cache_modes=[]):
'''Run tests'''
global debug
@@ -529,6 +570,7 @@ def main(supported_fmts=[], supported_oses=['linux']):
verbosity = 1
verify_image_format(supported_fmts)
verify_platform(supported_oses)
+ verify_cache_mode(supported_cache_modes)
# We need to filter out the time taken from the output so that qemu-iotest
# can reliably diff the results against master output.
diff --git a/tests/qmp-test.c b/tests/qmp-test.c
index 22445d9ec2..07c0b87e27 100644
--- a/tests/qmp-test.c
+++ b/tests/qmp-test.c
@@ -20,6 +20,7 @@
#include "qapi/qobject-input-visitor.h"
#include "qapi/util.h"
#include "qapi/visitor.h"
+#include "qapi/qmp/qstring.h"
const char common_args[] = "-nodefaults -machine none";
@@ -79,6 +80,9 @@ static void test_qmp_protocol(void)
QDict *resp, *q, *ret;
QList *capabilities;
QTestState *qts;
+ const QListEntry *entry;
+ QString *qstr;
+ int i;
qts = qtest_init_without_qmp_handshake(common_args);
@@ -88,7 +92,12 @@ static void test_qmp_protocol(void)
g_assert(q);
test_version(qdict_get(q, "version"));
capabilities = qdict_get_qlist(q, "capabilities");
- g_assert(capabilities && qlist_empty(capabilities));
+ g_assert(capabilities);
+ entry = qlist_first(capabilities);
+ g_assert(entry);
+ qstr = qobject_to(QString, entry->value);
+ g_assert(qstr);
+ g_assert_cmpstr(qstring_get_str(qstr), ==, "oob");
QDECREF(resp);
/* Test valid command before handshake */
@@ -131,9 +140,94 @@ static void test_qmp_protocol(void)
g_assert_cmpint(qdict_get_int(resp, "id"), ==, 2);
QDECREF(resp);
+ /*
+ * Test command batching. In current test OOB is not enabled, we
+ * should be able to run as many commands in batch as we like.
+ * Using 16 (>8, which is OOB queue length) to make sure OOB won't
+ * break existing clients. Note: this test does not control the
+ * scheduling of QEMU's QMP command processing threads so it may
+ * not really trigger batching inside QEMU. This is just a
+ * best-effort test.
+ */
+ for (i = 0; i < 16; i++) {
+ qtest_async_qmp(qts, "{ 'execute': 'query-version' }");
+ }
+ /* Verify the replies to make sure no command is dropped. */
+ for (i = 0; i < 16; i++) {
+ resp = qtest_qmp_receive(qts);
+ /* It should never be dropped. Each of them should be a reply. */
+ g_assert(qdict_haskey(resp, "return"));
+ g_assert(!qdict_haskey(resp, "event"));
+ QDECREF(resp);
+ }
+
qtest_quit(qts);
}
+/* Tests for Out-Of-Band support. */
+static void test_qmp_oob(void)
+{
+ QDict *resp;
+ int acks = 0;
+ const char *cmd_id;
+
+ global_qtest = qtest_init_without_qmp_handshake(common_args);
+
+ /* Ignore the greeting message. */
+ resp = qmp_receive();
+ g_assert(qdict_get_qdict(resp, "QMP"));
+ QDECREF(resp);
+
+ /* Try a fake capability, it should fail. */
+ resp = qmp("{ 'execute': 'qmp_capabilities', "
+ " 'arguments': { 'enable': [ 'cap-does-not-exist' ] } }");
+ g_assert(qdict_haskey(resp, "error"));
+ QDECREF(resp);
+
+ /* Now, enable OOB in current QMP session, it should succeed. */
+ resp = qmp("{ 'execute': 'qmp_capabilities', "
+ " 'arguments': { 'enable': [ 'oob' ] } }");
+ g_assert(qdict_haskey(resp, "return"));
+ QDECREF(resp);
+
+ /*
+ * Try any command that does not support OOB but with OOB flag. We
+ * should get failure.
+ */
+ resp = qmp("{ 'execute': 'query-cpus',"
+ " 'control': { 'run-oob': true } }");
+ g_assert(qdict_haskey(resp, "error"));
+ QDECREF(resp);
+
+ /*
+ * First send the "x-oob-test" command with lock=true and
+ * oob=false, it should hang the dispatcher and main thread;
+ * later, we send another lock=false with oob=true to continue
+ * that thread processing. Finally we should receive replies from
+ * both commands.
+ */
+ qmp_async("{ 'execute': 'x-oob-test',"
+ " 'arguments': { 'lock': true }, "
+ " 'id': 'lock-cmd'}");
+ qmp_async("{ 'execute': 'x-oob-test', "
+ " 'arguments': { 'lock': false }, "
+ " 'control': { 'run-oob': true }, "
+ " 'id': 'unlock-cmd' }");
+
+ /* Ignore all events. Wait for 2 acks */
+ while (acks < 2) {
+ resp = qmp_receive();
+ cmd_id = qdict_get_str(resp, "id");
+ if (!g_strcmp0(cmd_id, "lock-cmd") ||
+ !g_strcmp0(cmd_id, "unlock-cmd")) {
+ acks++;
+ }
+ QDECREF(resp);
+ }
+
+ qtest_end();
+}
+
static int query_error_class(const char *cmd)
{
static struct {
@@ -204,6 +298,11 @@ static bool query_is_blacklisted(const char *cmd)
"query-gic-capabilities", /* arm */
/* Success depends on target-specific build configuration: */
"query-pci", /* CONFIG_PCI */
+ /* Success depends on launching SEV guest */
+ "query-sev-launch-measure",
+ /* Success depends on Host or Hypervisor SEV support */
+ "query-sev",
+ "query-sev-capabilities",
NULL
};
int i;
@@ -313,6 +412,7 @@ int main(int argc, char *argv[])
g_test_init(&argc, &argv, NULL);
qtest_add_func("qmp/protocol", test_qmp_protocol);
+ qtest_add_func("qmp/oob", test_qmp_oob);
qmp_schema_init(&schema);
add_query_tests(&schema);
diff --git a/tests/qom-test.c b/tests/qom-test.c
index 9dab7ac61e..a34ff6ba53 100644
--- a/tests/qom-test.c
+++ b/tests/qom-test.c
@@ -62,9 +62,9 @@ static void test_properties(const char *path, bool recurse)
}
g_assert(qdict_haskey(response, "return"));
- list = qobject_to_qlist(qdict_get(response, "return"));
+ list = qobject_to(QList, qdict_get(response, "return"));
QLIST_FOREACH_ENTRY(list, entry) {
- tuple = qobject_to_qdict(qlist_entry_obj(entry));
+ tuple = qobject_to(QDict, qlist_entry_obj(entry));
bool is_child = strstart(qdict_get_str(tuple, "type"), "child<", NULL);
bool is_link = strstart(qdict_get_str(tuple, "type"), "link<", NULL);
diff --git a/tests/rcutorture.c b/tests/rcutorture.c
index 4002ecf123..49311c82ea 100644
--- a/tests/rcutorture.c
+++ b/tests/rcutorture.c
@@ -238,7 +238,6 @@ long long rcu_stress_count[RCU_STRESS_PIPE_LEN + 1];
static void *rcu_read_stress_test(void *arg)
{
int i;
- int itercnt = 0;
struct rcu_stress *p;
int pc;
long long n_reads_local = 0;
@@ -269,9 +268,6 @@ static void *rcu_read_stress_test(void *arg)
}
rcu_stress_local[pc]++;
n_reads_local++;
- if ((++itercnt % 0x1000) == 0) {
- synchronize_rcu();
- }
}
qemu_mutex_lock(&counts_mutex);
n_reads += n_reads_local;
diff --git a/tests/socket-helpers.c b/tests/socket-helpers.c
new file mode 100644
index 0000000000..8112763f5b
--- /dev/null
+++ b/tests/socket-helpers.c
@@ -0,0 +1,149 @@
+/*
+ * Helper functions for tests using sockets
+ *
+ * Copyright 2015-2018 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu/sockets.h"
+#include "socket-helpers.h"
+
+#ifndef AI_ADDRCONFIG
+# define AI_ADDRCONFIG 0
+#endif
+#ifndef EAI_ADDRFAMILY
+# define EAI_ADDRFAMILY 0
+#endif
+
+int socket_can_bind_connect(const char *hostname)
+{
+ int lfd = -1, cfd = -1, afd = -1;
+ struct addrinfo ai, *res = NULL;
+ struct sockaddr_storage ss;
+ socklen_t sslen = sizeof(ss);
+ int soerr;
+ socklen_t soerrlen = sizeof(soerr);
+ bool check_soerr = false;
+ int rc;
+ int ret = -1;
+
+ memset(&ai, 0, sizeof(ai));
+ ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
+ ai.ai_family = AF_UNSPEC;
+ ai.ai_socktype = SOCK_STREAM;
+
+ /* lookup */
+ rc = getaddrinfo(hostname, NULL, &ai, &res);
+ if (rc != 0) {
+ if (rc == EAI_ADDRFAMILY ||
+ rc == EAI_FAMILY) {
+ errno = EADDRNOTAVAIL;
+ } else {
+ errno = EINVAL;
+ }
+ goto cleanup;
+ }
+
+ lfd = qemu_socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if (lfd < 0) {
+ goto cleanup;
+ }
+
+ cfd = qemu_socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if (cfd < 0) {
+ goto cleanup;
+ }
+
+ if (bind(lfd, res->ai_addr, res->ai_addrlen) < 0) {
+ goto cleanup;
+ }
+
+ if (listen(lfd, 1) < 0) {
+ goto cleanup;
+ }
+
+ if (getsockname(lfd, (struct sockaddr *)&ss, &sslen) < 0) {
+ goto cleanup;
+ }
+
+ qemu_set_nonblock(cfd);
+ if (connect(cfd, (struct sockaddr *)&ss, sslen) < 0) {
+ if (errno == EINPROGRESS) {
+ check_soerr = true;
+ } else {
+ goto cleanup;
+ }
+ }
+
+ sslen = sizeof(ss);
+ afd = accept(lfd, (struct sockaddr *)&ss, &sslen);
+ if (afd < 0) {
+ goto cleanup;
+ }
+
+ if (check_soerr) {
+ if (qemu_getsockopt(cfd, SOL_SOCKET, SO_ERROR, &soerr, &soerrlen) < 0) {
+ goto cleanup;
+ }
+ if (soerr) {
+ errno = soerr;
+ goto cleanup;
+ }
+ }
+
+ ret = 0;
+
+ cleanup:
+ if (afd != -1) {
+ close(afd);
+ }
+ if (cfd != -1) {
+ close(cfd);
+ }
+ if (lfd != -1) {
+ close(lfd);
+ }
+ if (res) {
+ freeaddrinfo(res);
+ }
+ return ret;
+}
+
+
+int socket_check_protocol_support(bool *has_ipv4, bool *has_ipv6)
+{
+ *has_ipv4 = *has_ipv6 = false;
+
+ if (socket_can_bind_connect("127.0.0.1") < 0) {
+ if (errno != EADDRNOTAVAIL) {
+ return -1;
+ }
+ } else {
+ *has_ipv4 = true;
+ }
+
+ if (socket_can_bind_connect("::1") < 0) {
+ if (errno != EADDRNOTAVAIL) {
+ return -1;
+ }
+ } else {
+ *has_ipv6 = true;
+ }
+
+ return 0;
+}
diff --git a/tests/socket-helpers.h b/tests/socket-helpers.h
new file mode 100644
index 0000000000..1c07d6d656
--- /dev/null
+++ b/tests/socket-helpers.h
@@ -0,0 +1,42 @@
+/*
+ * Helper functions for tests using sockets
+ *
+ * Copyright 2015-2018 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*
+ * @hostname: a DNS name or numeric IP address
+ *
+ * Check whether it is possible to bind & connect to ports
+ * on the DNS name or IP address @hostname. If an IP address
+ * is used, it must not be a wildcard address.
+ *
+ * Returns 0 on success, -1 on error with errno set
+ */
+int socket_can_bind_connect(const char *hostname);
+
+/*
+ * @has_ipv4: set to true on return if IPv4 is available
+ * @has_ipv6: set to true on return if IPv6 is available
+ *
+ * Check whether IPv4 and/or IPv6 are available for use.
+ * On success, @has_ipv4 and @has_ipv6 will be set to
+ * indicate whether the respective protocols are available.
+ *
+ * Returns 0 on success, -1 on fatal error
+ */
+int socket_check_protocol_support(bool *has_ipv4, bool *has_ipv6);
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
index d760e2b243..7673de1062 100644
--- a/tests/test-bdrv-drain.c
+++ b/tests/test-bdrv-drain.c
@@ -505,6 +505,7 @@ static void coroutine_fn test_job_start(void *opaque)
{
TestBlockJob *s = opaque;
+ block_job_event_ready(&s->common);
while (!s->should_complete) {
block_job_sleep_ns(&s->common, 100000);
}
@@ -541,8 +542,8 @@ static void test_blockjob_common(enum drain_type drain_type)
blk_target = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
blk_insert_bs(blk_target, target, &error_abort);
- job = block_job_create("job0", &test_job_driver, src, 0, BLK_PERM_ALL, 0,
- 0, NULL, NULL, &error_abort);
+ job = block_job_create("job0", &test_job_driver, NULL, src, 0, BLK_PERM_ALL,
+ 0, 0, NULL, NULL, &error_abort);
block_job_add_bdrv(job, "target", target, 0, BLK_PERM_ALL, &error_abort);
block_job_start(job);
diff --git a/tests/test-blockjob-txn.c b/tests/test-blockjob-txn.c
index 3591c9617f..5789893dda 100644
--- a/tests/test-blockjob-txn.c
+++ b/tests/test-blockjob-txn.c
@@ -87,7 +87,7 @@ static const BlockJobDriver test_block_job_driver = {
*/
static BlockJob *test_block_job_start(unsigned int iterations,
bool use_timer,
- int rc, int *result)
+ int rc, int *result, BlockJobTxn *txn)
{
BlockDriverState *bs;
TestBlockJob *s;
@@ -101,7 +101,7 @@ static BlockJob *test_block_job_start(unsigned int iterations,
g_assert_nonnull(bs);
snprintf(job_id, sizeof(job_id), "job%u", counter++);
- s = block_job_create(job_id, &test_block_job_driver, bs,
+ s = block_job_create(job_id, &test_block_job_driver, txn, bs,
0, BLK_PERM_ALL, 0, BLOCK_JOB_DEFAULT,
test_block_job_cb, data, &error_abort);
s->iterations = iterations;
@@ -120,12 +120,11 @@ static void test_single_job(int expected)
int result = -EINPROGRESS;
txn = block_job_txn_new();
- job = test_block_job_start(1, true, expected, &result);
- block_job_txn_add_job(txn, job);
+ job = test_block_job_start(1, true, expected, &result, txn);
block_job_start(job);
if (expected == -ECANCELED) {
- block_job_cancel(job);
+ block_job_cancel(job, false);
}
while (result == -EINPROGRESS) {
@@ -160,10 +159,8 @@ static void test_pair_jobs(int expected1, int expected2)
int result2 = -EINPROGRESS;
txn = block_job_txn_new();
- job1 = test_block_job_start(1, true, expected1, &result1);
- block_job_txn_add_job(txn, job1);
- job2 = test_block_job_start(2, true, expected2, &result2);
- block_job_txn_add_job(txn, job2);
+ job1 = test_block_job_start(1, true, expected1, &result1, txn);
+ job2 = test_block_job_start(2, true, expected2, &result2, txn);
block_job_start(job1);
block_job_start(job2);
@@ -173,10 +170,10 @@ static void test_pair_jobs(int expected1, int expected2)
block_job_txn_unref(txn);
if (expected1 == -ECANCELED) {
- block_job_cancel(job1);
+ block_job_cancel(job1, false);
}
if (expected2 == -ECANCELED) {
- block_job_cancel(job2);
+ block_job_cancel(job2, false);
}
while (result1 == -EINPROGRESS || result2 == -EINPROGRESS) {
@@ -224,14 +221,12 @@ static void test_pair_jobs_fail_cancel_race(void)
int result2 = -EINPROGRESS;
txn = block_job_txn_new();
- job1 = test_block_job_start(1, true, -ECANCELED, &result1);
- block_job_txn_add_job(txn, job1);
- job2 = test_block_job_start(2, false, 0, &result2);
- block_job_txn_add_job(txn, job2);
+ job1 = test_block_job_start(1, true, -ECANCELED, &result1, txn);
+ job2 = test_block_job_start(2, false, 0, &result2, txn);
block_job_start(job1);
block_job_start(job2);
- block_job_cancel(job1);
+ block_job_cancel(job1, false);
/* Now make job2 finish before the main loop kicks jobs. This simulates
* the race between a pending kick and another job completing.
diff --git a/tests/test-blockjob.c b/tests/test-blockjob.c
index 23bdf1a932..8946bfd37b 100644
--- a/tests/test-blockjob.c
+++ b/tests/test-blockjob.c
@@ -24,14 +24,15 @@ static void block_job_cb(void *opaque, int ret)
{
}
-static BlockJob *do_test_id(BlockBackend *blk, const char *id,
- bool should_succeed)
+static BlockJob *mk_job(BlockBackend *blk, const char *id,
+ const BlockJobDriver *drv, bool should_succeed,
+ int flags)
{
BlockJob *job;
Error *errp = NULL;
- job = block_job_create(id, &test_block_job_driver, blk_bs(blk),
- 0, BLK_PERM_ALL, 0, BLOCK_JOB_DEFAULT, block_job_cb,
+ job = block_job_create(id, drv, NULL, blk_bs(blk),
+ 0, BLK_PERM_ALL, 0, flags, block_job_cb,
NULL, &errp);
if (should_succeed) {
g_assert_null(errp);
@@ -50,6 +51,13 @@ static BlockJob *do_test_id(BlockBackend *blk, const char *id,
return job;
}
+static BlockJob *do_test_id(BlockBackend *blk, const char *id,
+ bool should_succeed)
+{
+ return mk_job(blk, id, &test_block_job_driver,
+ should_succeed, BLOCK_JOB_DEFAULT);
+}
+
/* This creates a BlockBackend (optionally with a name) with a
* BlockDriverState inserted. */
static BlockBackend *create_blk(const char *name)
@@ -142,6 +150,216 @@ static void test_job_ids(void)
destroy_blk(blk[2]);
}
+typedef struct CancelJob {
+ BlockJob common;
+ BlockBackend *blk;
+ bool should_converge;
+ bool should_complete;
+ bool completed;
+} CancelJob;
+
+static void cancel_job_completed(BlockJob *job, void *opaque)
+{
+ CancelJob *s = opaque;
+ s->completed = true;
+ block_job_completed(job, 0);
+}
+
+static void cancel_job_complete(BlockJob *job, Error **errp)
+{
+ CancelJob *s = container_of(job, CancelJob, common);
+ s->should_complete = true;
+}
+
+static void coroutine_fn cancel_job_start(void *opaque)
+{
+ CancelJob *s = opaque;
+
+ while (!s->should_complete) {
+ if (block_job_is_cancelled(&s->common)) {
+ goto defer;
+ }
+
+ if (!s->common.ready && s->should_converge) {
+ block_job_event_ready(&s->common);
+ }
+
+ block_job_sleep_ns(&s->common, 100000);
+ }
+
+ defer:
+ block_job_defer_to_main_loop(&s->common, cancel_job_completed, s);
+}
+
+static const BlockJobDriver test_cancel_driver = {
+ .instance_size = sizeof(CancelJob),
+ .start = cancel_job_start,
+ .complete = cancel_job_complete,
+};
+
+static CancelJob *create_common(BlockJob **pjob)
+{
+ BlockBackend *blk;
+ BlockJob *job;
+ CancelJob *s;
+
+ blk = create_blk(NULL);
+ job = mk_job(blk, "Steve", &test_cancel_driver, true,
+ BLOCK_JOB_MANUAL_FINALIZE | BLOCK_JOB_MANUAL_DISMISS);
+ block_job_ref(job);
+ assert(job->status == BLOCK_JOB_STATUS_CREATED);
+ s = container_of(job, CancelJob, common);
+ s->blk = blk;
+
+ *pjob = job;
+ return s;
+}
+
+static void cancel_common(CancelJob *s)
+{
+ BlockJob *job = &s->common;
+ BlockBackend *blk = s->blk;
+ BlockJobStatus sts = job->status;
+
+ block_job_cancel_sync(job);
+ if ((sts != BLOCK_JOB_STATUS_CREATED) &&
+ (sts != BLOCK_JOB_STATUS_CONCLUDED)) {
+ BlockJob *dummy = job;
+ block_job_dismiss(&dummy, &error_abort);
+ }
+ assert(job->status == BLOCK_JOB_STATUS_NULL);
+ block_job_unref(job);
+ destroy_blk(blk);
+}
+
+static void test_cancel_created(void)
+{
+ BlockJob *job;
+ CancelJob *s;
+
+ s = create_common(&job);
+ cancel_common(s);
+}
+
+static void test_cancel_running(void)
+{
+ BlockJob *job;
+ CancelJob *s;
+
+ s = create_common(&job);
+
+ block_job_start(job);
+ assert(job->status == BLOCK_JOB_STATUS_RUNNING);
+
+ cancel_common(s);
+}
+
+static void test_cancel_paused(void)
+{
+ BlockJob *job;
+ CancelJob *s;
+
+ s = create_common(&job);
+
+ block_job_start(job);
+ assert(job->status == BLOCK_JOB_STATUS_RUNNING);
+
+ block_job_user_pause(job, &error_abort);
+ block_job_enter(job);
+ assert(job->status == BLOCK_JOB_STATUS_PAUSED);
+
+ cancel_common(s);
+}
+
+static void test_cancel_ready(void)
+{
+ BlockJob *job;
+ CancelJob *s;
+
+ s = create_common(&job);
+
+ block_job_start(job);
+ assert(job->status == BLOCK_JOB_STATUS_RUNNING);
+
+ s->should_converge = true;
+ block_job_enter(job);
+ assert(job->status == BLOCK_JOB_STATUS_READY);
+
+ cancel_common(s);
+}
+
+static void test_cancel_standby(void)
+{
+ BlockJob *job;
+ CancelJob *s;
+
+ s = create_common(&job);
+
+ block_job_start(job);
+ assert(job->status == BLOCK_JOB_STATUS_RUNNING);
+
+ s->should_converge = true;
+ block_job_enter(job);
+ assert(job->status == BLOCK_JOB_STATUS_READY);
+
+ block_job_user_pause(job, &error_abort);
+ block_job_enter(job);
+ assert(job->status == BLOCK_JOB_STATUS_STANDBY);
+
+ cancel_common(s);
+}
+
+static void test_cancel_pending(void)
+{
+ BlockJob *job;
+ CancelJob *s;
+
+ s = create_common(&job);
+
+ block_job_start(job);
+ assert(job->status == BLOCK_JOB_STATUS_RUNNING);
+
+ s->should_converge = true;
+ block_job_enter(job);
+ assert(job->status == BLOCK_JOB_STATUS_READY);
+
+ block_job_complete(job, &error_abort);
+ block_job_enter(job);
+ while (!s->completed) {
+ aio_poll(qemu_get_aio_context(), true);
+ }
+ assert(job->status == BLOCK_JOB_STATUS_PENDING);
+
+ cancel_common(s);
+}
+
+static void test_cancel_concluded(void)
+{
+ BlockJob *job;
+ CancelJob *s;
+
+ s = create_common(&job);
+
+ block_job_start(job);
+ assert(job->status == BLOCK_JOB_STATUS_RUNNING);
+
+ s->should_converge = true;
+ block_job_enter(job);
+ assert(job->status == BLOCK_JOB_STATUS_READY);
+
+ block_job_complete(job, &error_abort);
+ block_job_enter(job);
+ while (!s->completed) {
+ aio_poll(qemu_get_aio_context(), true);
+ }
+ assert(job->status == BLOCK_JOB_STATUS_PENDING);
+
+ block_job_finalize(job, &error_abort);
+ assert(job->status == BLOCK_JOB_STATUS_CONCLUDED);
+
+ cancel_common(s);
+}
+
int main(int argc, char **argv)
{
qemu_init_main_loop(&error_abort);
@@ -149,5 +367,12 @@ int main(int argc, char **argv)
g_test_init(&argc, &argv, NULL);
g_test_add_func("/blockjob/ids", test_job_ids);
+ g_test_add_func("/blockjob/cancel/created", test_cancel_created);
+ g_test_add_func("/blockjob/cancel/running", test_cancel_running);
+ g_test_add_func("/blockjob/cancel/paused", test_cancel_paused);
+ g_test_add_func("/blockjob/cancel/ready", test_cancel_ready);
+ g_test_add_func("/blockjob/cancel/standby", test_cancel_standby);
+ g_test_add_func("/blockjob/cancel/pending", test_cancel_pending);
+ g_test_add_func("/blockjob/cancel/concluded", test_cancel_concluded);
return g_test_run();
}
diff --git a/tests/test-char.c b/tests/test-char.c
index b3a77af085..306c728335 100644
--- a/tests/test-char.c
+++ b/tests/test-char.c
@@ -166,7 +166,6 @@ static void char_mux_test(void)
FeHandler h1 = { 0, }, h2 = { 0, };
CharBackend chr_be1, chr_be2;
- muxes_realized = true; /* done after machine init */
opts = qemu_opts_create(qemu_find_opts("chardev"), "mux-label",
1, &error_abort);
qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
@@ -302,9 +301,8 @@ static int socket_can_read_hello(void *opaque)
return 10;
}
-static void char_socket_test(void)
+static void char_socket_test_common(Chardev *chr)
{
- Chardev *chr = qemu_chr_new("server", "tcp:127.0.0.1:0,server,nowait");
Chardev *chr_client;
QObject *addr;
QDict *qdict;
@@ -321,7 +319,7 @@ static void char_socket_test(void)
g_assert(!object_property_get_bool(OBJECT(chr), "connected", &error_abort));
addr = object_property_get_qobject(OBJECT(chr), "addr", &error_abort);
- qdict = qobject_to_qdict(addr);
+ qdict = qobject_to(QDict, addr);
port = qdict_get_str(qdict, "port");
tmp = g_strdup_printf("tcp:127.0.0.1:%s", port);
QDECREF(qdict);
@@ -359,6 +357,47 @@ static void char_socket_test(void)
object_unparent(OBJECT(chr));
}
+
+static void char_socket_basic_test(void)
+{
+ Chardev *chr = qemu_chr_new("server", "tcp:127.0.0.1:0,server,nowait");
+
+ char_socket_test_common(chr);
+}
+
+
+static void char_socket_fdpass_test(void)
+{
+ Chardev *chr;
+ char *optstr;
+ QemuOpts *opts;
+ int fd;
+ SocketAddress *addr = g_new0(SocketAddress, 1);
+
+ addr->type = SOCKET_ADDRESS_TYPE_INET;
+ addr->u.inet.host = g_strdup("127.0.0.1");
+ addr->u.inet.port = g_strdup("0");
+
+ fd = socket_listen(addr, &error_abort);
+ g_assert(fd >= 0);
+
+ qapi_free_SocketAddress(addr);
+
+ optstr = g_strdup_printf("socket,id=cdev,fd=%d,server,nowait", fd);
+
+ opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"),
+ optstr, true);
+ g_free(optstr);
+ g_assert_nonnull(opts);
+
+ chr = qemu_chr_new_from_opts(opts, &error_abort);
+
+ qemu_opts_del(opts);
+
+ char_socket_test_common(chr);
+}
+
+
#ifndef _WIN32
static void char_pipe_test(void)
{
@@ -775,7 +814,8 @@ int main(int argc, char **argv)
#ifndef _WIN32
g_test_add_func("/char/file-fifo", char_file_fifo_test);
#endif
- g_test_add_func("/char/socket", char_socket_test);
+ g_test_add_func("/char/socket/basic", char_socket_basic_test);
+ g_test_add_func("/char/socket/fdpass", char_socket_fdpass_test);
g_test_add_func("/char/udp", char_udp_test);
#ifdef HAVE_CHARDEV_SERIAL
g_test_add_func("/char/serial", char_serial_test);
diff --git a/tests/test-cutils.c b/tests/test-cutils.c
index f64a49b7fb..64a489c2e9 100644
--- a/tests/test-cutils.c
+++ b/tests/test-cutils.c
@@ -223,6 +223,583 @@ static void test_parse_uint_full_correct(void)
g_assert_cmpint(i, ==, 123);
}
+static void test_qemu_strtoi_correct(void)
+{
+ const char *str = "12345 foo";
+ char f = 'X';
+ const char *endptr = &f;
+ int res = 999;
+ int err;
+
+ err = qemu_strtoi(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 12345);
+ g_assert(endptr == str + 5);
+}
+
+static void test_qemu_strtoi_null(void)
+{
+ char f = 'X';
+ const char *endptr = &f;
+ int res = 999;
+ int err;
+
+ err = qemu_strtoi(NULL, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+ g_assert(endptr == NULL);
+}
+
+static void test_qemu_strtoi_empty(void)
+{
+ const char *str = "";
+ char f = 'X';
+ const char *endptr = &f;
+ int res = 999;
+ int err;
+
+ err = qemu_strtoi(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+ g_assert(endptr == str);
+}
+
+static void test_qemu_strtoi_whitespace(void)
+{
+ const char *str = " \t ";
+ char f = 'X';
+ const char *endptr = &f;
+ int res = 999;
+ int err;
+
+ err = qemu_strtoi(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+ g_assert(endptr == str);
+}
+
+static void test_qemu_strtoi_invalid(void)
+{
+ const char *str = " xxxx \t abc";
+ char f = 'X';
+ const char *endptr = &f;
+ int res = 999;
+ int err;
+
+ err = qemu_strtoi(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+ g_assert(endptr == str);
+}
+
+static void test_qemu_strtoi_trailing(void)
+{
+ const char *str = "123xxx";
+ char f = 'X';
+ const char *endptr = &f;
+ int res = 999;
+ int err;
+
+ err = qemu_strtoi(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 123);
+ g_assert(endptr == str + 3);
+}
+
+static void test_qemu_strtoi_octal(void)
+{
+ const char *str = "0123";
+ char f = 'X';
+ const char *endptr = &f;
+ int res = 999;
+ int err;
+
+ err = qemu_strtoi(str, &endptr, 8, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0123);
+ g_assert(endptr == str + strlen(str));
+
+ res = 999;
+ endptr = &f;
+ err = qemu_strtoi(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0123);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoi_decimal(void)
+{
+ const char *str = "0123";
+ char f = 'X';
+ const char *endptr = &f;
+ int res = 999;
+ int err;
+
+ err = qemu_strtoi(str, &endptr, 10, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 123);
+ g_assert(endptr == str + strlen(str));
+
+ str = "123";
+ res = 999;
+ endptr = &f;
+ err = qemu_strtoi(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 123);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoi_hex(void)
+{
+ const char *str = "0123";
+ char f = 'X';
+ const char *endptr = &f;
+ int res = 999;
+ int err;
+
+ err = qemu_strtoi(str, &endptr, 16, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0x123);
+ g_assert(endptr == str + strlen(str));
+
+ str = "0x123";
+ res = 999;
+ endptr = &f;
+ err = qemu_strtoi(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0x123);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoi_max(void)
+{
+ char *str = g_strdup_printf("%d", INT_MAX);
+ char f = 'X';
+ const char *endptr = &f;
+ int res = 999;
+ int err;
+
+ err = qemu_strtoi(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, INT_MAX);
+ g_assert(endptr == str + strlen(str));
+ g_free(str);
+}
+
+static void test_qemu_strtoi_overflow(void)
+{
+ char *str = g_strdup_printf("%lld", (long long)INT_MAX + 1ll);
+ char f = 'X';
+ const char *endptr = &f;
+ int res = 999;
+ int err;
+
+ err = qemu_strtoi(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -ERANGE);
+ g_assert_cmpint(res, ==, INT_MAX);
+ g_assert(endptr == str + strlen(str));
+ g_free(str);
+}
+
+static void test_qemu_strtoi_underflow(void)
+{
+ char *str = g_strdup_printf("%lld", (long long)INT_MIN - 1ll);
+ char f = 'X';
+ const char *endptr = &f;
+ int res = 999;
+ int err;
+
+ err = qemu_strtoi(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -ERANGE);
+ g_assert_cmpint(res, ==, INT_MIN);
+ g_assert(endptr == str + strlen(str));
+ g_free(str);
+}
+
+static void test_qemu_strtoi_negative(void)
+{
+ const char *str = " \t -321";
+ char f = 'X';
+ const char *endptr = &f;
+ int res = 999;
+ int err;
+
+ err = qemu_strtoi(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, -321);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoi_full_correct(void)
+{
+ const char *str = "123";
+ int res = 999;
+ int err;
+
+ err = qemu_strtoi(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 123);
+}
+
+static void test_qemu_strtoi_full_null(void)
+{
+ char f = 'X';
+ const char *endptr = &f;
+ int res = 999;
+ int err;
+
+ err = qemu_strtoi(NULL, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+ g_assert(endptr == NULL);
+}
+
+static void test_qemu_strtoi_full_empty(void)
+{
+ const char *str = "";
+ int res = 999L;
+ int err;
+
+ err = qemu_strtoi(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtoi_full_negative(void)
+{
+ const char *str = " \t -321";
+ int res = 999;
+ int err;
+
+ err = qemu_strtoi(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, -321);
+}
+
+static void test_qemu_strtoi_full_trailing(void)
+{
+ const char *str = "123xxx";
+ int res;
+ int err;
+
+ err = qemu_strtoi(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtoi_full_max(void)
+{
+ char *str = g_strdup_printf("%d", INT_MAX);
+ int res;
+ int err;
+
+ err = qemu_strtoi(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, INT_MAX);
+ g_free(str);
+}
+
+static void test_qemu_strtoui_correct(void)
+{
+ const char *str = "12345 foo";
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned int res = 999;
+ int err;
+
+ err = qemu_strtoui(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpuint(res, ==, 12345);
+ g_assert(endptr == str + 5);
+}
+
+static void test_qemu_strtoui_null(void)
+{
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned int res = 999;
+ int err;
+
+ err = qemu_strtoui(NULL, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+ g_assert(endptr == NULL);
+}
+
+static void test_qemu_strtoui_empty(void)
+{
+ const char *str = "";
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned int res = 999;
+ int err;
+
+ err = qemu_strtoui(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+ g_assert(endptr == str);
+}
+
+static void test_qemu_strtoui_whitespace(void)
+{
+ const char *str = " \t ";
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned int res = 999;
+ int err;
+
+ err = qemu_strtoui(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+ g_assert(endptr == str);
+}
+
+static void test_qemu_strtoui_invalid(void)
+{
+ const char *str = " xxxx \t abc";
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned int res = 999;
+ int err;
+
+ err = qemu_strtoui(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+ g_assert(endptr == str);
+}
+
+static void test_qemu_strtoui_trailing(void)
+{
+ const char *str = "123xxx";
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned int res = 999;
+ int err;
+
+ err = qemu_strtoui(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpuint(res, ==, 123);
+ g_assert(endptr == str + 3);
+}
+
+static void test_qemu_strtoui_octal(void)
+{
+ const char *str = "0123";
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned int res = 999;
+ int err;
+
+ err = qemu_strtoui(str, &endptr, 8, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpuint(res, ==, 0123);
+ g_assert(endptr == str + strlen(str));
+
+ res = 999;
+ endptr = &f;
+ err = qemu_strtoui(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpuint(res, ==, 0123);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoui_decimal(void)
+{
+ const char *str = "0123";
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned int res = 999;
+ int err;
+
+ err = qemu_strtoui(str, &endptr, 10, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpuint(res, ==, 123);
+ g_assert(endptr == str + strlen(str));
+
+ str = "123";
+ res = 999;
+ endptr = &f;
+ err = qemu_strtoui(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpuint(res, ==, 123);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoui_hex(void)
+{
+ const char *str = "0123";
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned int res = 999;
+ int err;
+
+ err = qemu_strtoui(str, &endptr, 16, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmphex(res, ==, 0x123);
+ g_assert(endptr == str + strlen(str));
+
+ str = "0x123";
+ res = 999;
+ endptr = &f;
+ err = qemu_strtoui(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmphex(res, ==, 0x123);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoui_max(void)
+{
+ char *str = g_strdup_printf("%u", UINT_MAX);
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned int res = 999;
+ int err;
+
+ err = qemu_strtoui(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmphex(res, ==, UINT_MAX);
+ g_assert(endptr == str + strlen(str));
+ g_free(str);
+}
+
+static void test_qemu_strtoui_overflow(void)
+{
+ char *str = g_strdup_printf("%lld", (long long)UINT_MAX + 1ll);
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned int res = 999;
+ int err;
+
+ err = qemu_strtoui(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -ERANGE);
+ g_assert_cmphex(res, ==, UINT_MAX);
+ g_assert(endptr == str + strlen(str));
+ g_free(str);
+}
+
+static void test_qemu_strtoui_underflow(void)
+{
+ char *str = g_strdup_printf("%lld", (long long)INT_MIN - 1ll);
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned int res = 999;
+ int err;
+
+ err = qemu_strtoui(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -ERANGE);
+ g_assert_cmpuint(res, ==, (unsigned int)-1);
+ g_assert(endptr == str + strlen(str));
+ g_free(str);
+}
+
+static void test_qemu_strtoui_negative(void)
+{
+ const char *str = " \t -321";
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned int res = 999;
+ int err;
+
+ err = qemu_strtoui(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpuint(res, ==, (unsigned int)-321);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoui_full_correct(void)
+{
+ const char *str = "123";
+ unsigned int res = 999;
+ int err;
+
+ err = qemu_strtoui(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpuint(res, ==, 123);
+}
+
+static void test_qemu_strtoui_full_null(void)
+{
+ unsigned int res = 999;
+ int err;
+
+ err = qemu_strtoui(NULL, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtoui_full_empty(void)
+{
+ const char *str = "";
+ unsigned int res = 999;
+ int err;
+
+ err = qemu_strtoui(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+static void test_qemu_strtoui_full_negative(void)
+{
+ const char *str = " \t -321";
+ unsigned int res = 999;
+ int err;
+
+ err = qemu_strtoui(str, NULL, 0, &res);
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpuint(res, ==, (unsigned int)-321);
+}
+
+static void test_qemu_strtoui_full_trailing(void)
+{
+ const char *str = "123xxx";
+ unsigned int res;
+ int err;
+
+ err = qemu_strtoui(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtoui_full_max(void)
+{
+ char *str = g_strdup_printf("%u", UINT_MAX);
+ unsigned int res = 999;
+ int err;
+
+ err = qemu_strtoui(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmphex(res, ==, UINT_MAX);
+ g_free(str);
+}
+
static void test_qemu_strtol_correct(void)
{
const char *str = "12345 foo";
@@ -1612,6 +2189,86 @@ int main(int argc, char **argv)
g_test_add_func("/cutils/parse_uint_full/correct",
test_parse_uint_full_correct);
+ /* qemu_strtoi() tests */
+ g_test_add_func("/cutils/qemu_strtoi/correct",
+ test_qemu_strtoi_correct);
+ g_test_add_func("/cutils/qemu_strtoi/null",
+ test_qemu_strtoi_null);
+ g_test_add_func("/cutils/qemu_strtoi/empty",
+ test_qemu_strtoi_empty);
+ g_test_add_func("/cutils/qemu_strtoi/whitespace",
+ test_qemu_strtoi_whitespace);
+ g_test_add_func("/cutils/qemu_strtoi/invalid",
+ test_qemu_strtoi_invalid);
+ g_test_add_func("/cutils/qemu_strtoi/trailing",
+ test_qemu_strtoi_trailing);
+ g_test_add_func("/cutils/qemu_strtoi/octal",
+ test_qemu_strtoi_octal);
+ g_test_add_func("/cutils/qemu_strtoi/decimal",
+ test_qemu_strtoi_decimal);
+ g_test_add_func("/cutils/qemu_strtoi/hex",
+ test_qemu_strtoi_hex);
+ g_test_add_func("/cutils/qemu_strtoi/max",
+ test_qemu_strtoi_max);
+ g_test_add_func("/cutils/qemu_strtoi/overflow",
+ test_qemu_strtoi_overflow);
+ g_test_add_func("/cutils/qemu_strtoi/underflow",
+ test_qemu_strtoi_underflow);
+ g_test_add_func("/cutils/qemu_strtoi/negative",
+ test_qemu_strtoi_negative);
+ g_test_add_func("/cutils/qemu_strtoi_full/correct",
+ test_qemu_strtoi_full_correct);
+ g_test_add_func("/cutils/qemu_strtoi_full/null",
+ test_qemu_strtoi_full_null);
+ g_test_add_func("/cutils/qemu_strtoi_full/empty",
+ test_qemu_strtoi_full_empty);
+ g_test_add_func("/cutils/qemu_strtoi_full/negative",
+ test_qemu_strtoi_full_negative);
+ g_test_add_func("/cutils/qemu_strtoi_full/trailing",
+ test_qemu_strtoi_full_trailing);
+ g_test_add_func("/cutils/qemu_strtoi_full/max",
+ test_qemu_strtoi_full_max);
+
+ /* qemu_strtoui() tests */
+ g_test_add_func("/cutils/qemu_strtoui/correct",
+ test_qemu_strtoui_correct);
+ g_test_add_func("/cutils/qemu_strtoui/null",
+ test_qemu_strtoui_null);
+ g_test_add_func("/cutils/qemu_strtoui/empty",
+ test_qemu_strtoui_empty);
+ g_test_add_func("/cutils/qemu_strtoui/whitespace",
+ test_qemu_strtoui_whitespace);
+ g_test_add_func("/cutils/qemu_strtoui/invalid",
+ test_qemu_strtoui_invalid);
+ g_test_add_func("/cutils/qemu_strtoui/trailing",
+ test_qemu_strtoui_trailing);
+ g_test_add_func("/cutils/qemu_strtoui/octal",
+ test_qemu_strtoui_octal);
+ g_test_add_func("/cutils/qemu_strtoui/decimal",
+ test_qemu_strtoui_decimal);
+ g_test_add_func("/cutils/qemu_strtoui/hex",
+ test_qemu_strtoui_hex);
+ g_test_add_func("/cutils/qemu_strtoui/max",
+ test_qemu_strtoui_max);
+ g_test_add_func("/cutils/qemu_strtoui/overflow",
+ test_qemu_strtoui_overflow);
+ g_test_add_func("/cutils/qemu_strtoui/underflow",
+ test_qemu_strtoui_underflow);
+ g_test_add_func("/cutils/qemu_strtoui/negative",
+ test_qemu_strtoui_negative);
+ g_test_add_func("/cutils/qemu_strtoui_full/correct",
+ test_qemu_strtoui_full_correct);
+ g_test_add_func("/cutils/qemu_strtoui_full/null",
+ test_qemu_strtoui_full_null);
+ g_test_add_func("/cutils/qemu_strtoui_full/empty",
+ test_qemu_strtoui_full_empty);
+ g_test_add_func("/cutils/qemu_strtoui_full/negative",
+ test_qemu_strtoui_full_negative);
+ g_test_add_func("/cutils/qemu_strtoui_full/trailing",
+ test_qemu_strtoui_full_trailing);
+ g_test_add_func("/cutils/qemu_strtoui_full/max",
+ test_qemu_strtoui_full_max);
+
/* qemu_strtol() tests */
g_test_add_func("/cutils/qemu_strtol/correct",
test_qemu_strtol_correct);
diff --git a/tests/test-io-channel-socket.c b/tests/test-io-channel-socket.c
index b273fd3ba2..0597213f93 100644
--- a/tests/test-io-channel-socket.c
+++ b/tests/test-io-channel-socket.c
@@ -22,77 +22,9 @@
#include "io/channel-socket.h"
#include "io/channel-util.h"
#include "io-channel-helpers.h"
+#include "socket-helpers.h"
#include "qapi/error.h"
-#ifndef AI_ADDRCONFIG
-# define AI_ADDRCONFIG 0
-#endif
-#ifndef EAI_ADDRFAMILY
-# define EAI_ADDRFAMILY 0
-#endif
-
-static int check_bind(const char *hostname, bool *has_proto)
-{
- int fd = -1;
- struct addrinfo ai, *res = NULL;
- int rc;
- int ret = -1;
-
- memset(&ai, 0, sizeof(ai));
- ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
- ai.ai_family = AF_UNSPEC;
- ai.ai_socktype = SOCK_STREAM;
-
- /* lookup */
- rc = getaddrinfo(hostname, NULL, &ai, &res);
- if (rc != 0) {
- if (rc == EAI_ADDRFAMILY ||
- rc == EAI_FAMILY) {
- *has_proto = false;
- goto done;
- }
- goto cleanup;
- }
-
- fd = qemu_socket(res->ai_family, res->ai_socktype, res->ai_protocol);
- if (fd < 0) {
- goto cleanup;
- }
-
- if (bind(fd, res->ai_addr, res->ai_addrlen) < 0) {
- if (errno == EADDRNOTAVAIL) {
- *has_proto = false;
- goto done;
- }
- goto cleanup;
- }
-
- *has_proto = true;
- done:
- ret = 0;
-
- cleanup:
- if (fd != -1) {
- close(fd);
- }
- if (res) {
- freeaddrinfo(res);
- }
- return ret;
-}
-
-static int check_protocol_support(bool *has_ipv4, bool *has_ipv6)
-{
- if (check_bind("127.0.0.1", has_ipv4) < 0) {
- return -1;
- }
- if (check_bind("::1", has_ipv6) < 0) {
- return -1;
- }
-
- return 0;
-}
-
static void test_io_channel_set_socket_bufs(QIOChannel *src,
QIOChannel *dst)
@@ -566,7 +498,7 @@ int main(int argc, char **argv)
* each protocol to avoid breaking tests on machines
* with either IPv4 or IPv6 disabled.
*/
- if (check_protocol_support(&has_ipv4, &has_ipv6) < 0) {
+ if (socket_check_protocol_support(&has_ipv4, &has_ipv6) < 0) {
return 1;
}
diff --git a/tests/test-keyval.c b/tests/test-keyval.c
index 94eb4df28d..029f05202a 100644
--- a/tests/test-keyval.c
+++ b/tests/test-keyval.c
@@ -195,7 +195,7 @@ static void check_list012(QList *qlist)
g_assert(qlist);
for (i = 0; i < ARRAY_SIZE(expected); i++) {
- qstr = qobject_to_qstring(qlist_pop(qlist));
+ qstr = qobject_to(QString, qlist_pop(qlist));
g_assert(qstr);
g_assert_cmpstr(qstring_get_str(qstr), ==, expected[i]);
QDECREF(qstr);
@@ -654,12 +654,12 @@ static void test_keyval_visit_any(void)
QDECREF(qdict);
visit_start_struct(v, NULL, NULL, 0, &error_abort);
visit_type_any(v, "a", &any, &error_abort);
- qlist = qobject_to_qlist(any);
+ qlist = qobject_to(QList, any);
g_assert(qlist);
- qstr = qobject_to_qstring(qlist_pop(qlist));
+ qstr = qobject_to(QString, qlist_pop(qlist));
g_assert_cmpstr(qstring_get_str(qstr), ==, "null");
QDECREF(qstr);
- qstr = qobject_to_qstring(qlist_pop(qlist));
+ qstr = qobject_to(QString, qlist_pop(qlist));
g_assert_cmpstr(qstring_get_str(qstr), ==, "1");
g_assert(qlist_empty(qlist));
QDECREF(qstr);
diff --git a/tests/test-qga.c b/tests/test-qga.c
index 5c5b661f8a..e6ab788f31 100644
--- a/tests/test-qga.c
+++ b/tests/test-qga.c
@@ -297,8 +297,8 @@ static void test_qga_get_vcpus(gconstpointer fix)
/* check there is at least a cpu */
list = qdict_get_qlist(ret, "return");
entry = qlist_first(list);
- g_assert(qdict_haskey(qobject_to_qdict(entry->value), "online"));
- g_assert(qdict_haskey(qobject_to_qdict(entry->value), "logical-id"));
+ g_assert(qdict_haskey(qobject_to(QDict, entry->value), "online"));
+ g_assert(qdict_haskey(qobject_to(QDict, entry->value), "logical-id"));
QDECREF(ret);
}
@@ -318,10 +318,10 @@ static void test_qga_get_fsinfo(gconstpointer fix)
list = qdict_get_qlist(ret, "return");
entry = qlist_first(list);
if (entry) {
- g_assert(qdict_haskey(qobject_to_qdict(entry->value), "name"));
- g_assert(qdict_haskey(qobject_to_qdict(entry->value), "mountpoint"));
- g_assert(qdict_haskey(qobject_to_qdict(entry->value), "type"));
- g_assert(qdict_haskey(qobject_to_qdict(entry->value), "disk"));
+ g_assert(qdict_haskey(qobject_to(QDict, entry->value), "name"));
+ g_assert(qdict_haskey(qobject_to(QDict, entry->value), "mountpoint"));
+ g_assert(qdict_haskey(qobject_to(QDict, entry->value), "type"));
+ g_assert(qdict_haskey(qobject_to(QDict, entry->value), "disk"));
}
QDECREF(ret);
@@ -363,8 +363,9 @@ static void test_qga_get_memory_blocks(gconstpointer fix)
entry = qlist_first(list);
/* newer versions of qga may return empty list without error */
if (entry) {
- g_assert(qdict_haskey(qobject_to_qdict(entry->value), "phys-index"));
- g_assert(qdict_haskey(qobject_to_qdict(entry->value), "online"));
+ g_assert(qdict_haskey(qobject_to(QDict, entry->value),
+ "phys-index"));
+ g_assert(qdict_haskey(qobject_to(QDict, entry->value), "online"));
}
}
@@ -385,7 +386,7 @@ static void test_qga_network_get_interfaces(gconstpointer fix)
/* check there is at least an interface */
list = qdict_get_qlist(ret, "return");
entry = qlist_first(list);
- g_assert(qdict_haskey(qobject_to_qdict(entry->value), "name"));
+ g_assert(qdict_haskey(qobject_to(QDict, entry->value), "name"));
QDECREF(ret);
}
diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c
index 5b1cee6912..93fbbb1b73 100644
--- a/tests/test-qmp-cmds.c
+++ b/tests/test-qmp-cmds.c
@@ -100,7 +100,7 @@ static void test_dispatch_cmd(void)
resp = qmp_dispatch(&qmp_commands, QOBJECT(req));
assert(resp != NULL);
- assert(!qdict_haskey(qobject_to_qdict(resp), "error"));
+ assert(!qdict_haskey(qobject_to(QDict, resp), "error"));
qobject_decref(resp);
QDECREF(req);
@@ -117,7 +117,7 @@ static void test_dispatch_cmd_failure(void)
resp = qmp_dispatch(&qmp_commands, QOBJECT(req));
assert(resp != NULL);
- assert(qdict_haskey(qobject_to_qdict(resp), "error"));
+ assert(qdict_haskey(qobject_to(QDict, resp), "error"));
qobject_decref(resp);
QDECREF(req);
@@ -131,7 +131,7 @@ static void test_dispatch_cmd_failure(void)
resp = qmp_dispatch(&qmp_commands, QOBJECT(req));
assert(resp != NULL);
- assert(qdict_haskey(qobject_to_qdict(resp), "error"));
+ assert(qdict_haskey(qobject_to(QDict, resp), "error"));
qobject_decref(resp);
QDECREF(req);
@@ -145,7 +145,7 @@ static QObject *test_qmp_dispatch(QDict *req)
resp_obj = qmp_dispatch(&qmp_commands, QOBJECT(req));
assert(resp_obj);
- resp = qobject_to_qdict(resp_obj);
+ resp = qobject_to(QDict, resp_obj);
assert(resp && !qdict_haskey(resp, "error"));
ret = qdict_get(resp, "return");
assert(ret);
@@ -176,7 +176,7 @@ static void test_dispatch_cmd_io(void)
qdict_put(req, "arguments", args);
qdict_put_str(req, "execute", "user_def_cmd2");
- ret = qobject_to_qdict(test_qmp_dispatch(req));
+ ret = qobject_to(QDict, test_qmp_dispatch(req));
assert(!strcmp(qdict_get_str(ret, "string0"), "blah1"));
ret_dict = qdict_get_qdict(ret, "dict1");
@@ -197,7 +197,7 @@ static void test_dispatch_cmd_io(void)
qdict_put(req, "arguments", args3);
qdict_put_str(req, "execute", "guest-get-time");
- ret3 = qobject_to_qnum(test_qmp_dispatch(req));
+ ret3 = qobject_to(QNum, test_qmp_dispatch(req));
g_assert(qnum_get_try_int(ret3, &val));
g_assert_cmpint(val, ==, 66);
QDECREF(ret3);
diff --git a/tests/test-qmp-event.c b/tests/test-qmp-event.c
index 31f35b3e66..bb1036615f 100644
--- a/tests/test-qmp-event.c
+++ b/tests/test-qmp-event.c
@@ -60,22 +60,22 @@ void qdict_cmp_do_simple(const char *key, QObject *obj1, void *opaque)
switch (qobject_type(obj1)) {
case QTYPE_QBOOL:
- d->result = (qbool_get_bool(qobject_to_qbool(obj1)) ==
- qbool_get_bool(qobject_to_qbool(obj2)));
+ d->result = (qbool_get_bool(qobject_to(QBool, obj1)) ==
+ qbool_get_bool(qobject_to(QBool, obj2)));
return;
case QTYPE_QNUM:
- g_assert(qnum_get_try_int(qobject_to_qnum(obj1), &val1));
- g_assert(qnum_get_try_int(qobject_to_qnum(obj2), &val2));
+ g_assert(qnum_get_try_int(qobject_to(QNum, obj1), &val1));
+ g_assert(qnum_get_try_int(qobject_to(QNum, obj2), &val2));
d->result = val1 == val2;
return;
case QTYPE_QSTRING:
- d->result = g_strcmp0(qstring_get_str(qobject_to_qstring(obj1)),
- qstring_get_str(qobject_to_qstring(obj2))) == 0;
+ d->result = g_strcmp0(qstring_get_str(qobject_to(QString, obj1)),
+ qstring_get_str(qobject_to(QString, obj2))) == 0;
return;
case QTYPE_QDICT:
- d_new.expect = qobject_to_qdict(obj2);
+ d_new.expect = qobject_to(QDict, obj2);
d_new.result = true;
- qdict_iter(qobject_to_qdict(obj1), qdict_cmp_do_simple, &d_new);
+ qdict_iter(qobject_to(QDict, obj1), qdict_cmp_do_simple, &d_new);
d->result = d_new.result;
return;
default:
diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
index 79b1a8cb17..6dc59c6211 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -479,7 +479,7 @@ static void test_visitor_in_any(TestInputVisitorData *data,
v = visitor_input_test_init(data, "-42");
visit_type_any(v, NULL, &res, &error_abort);
- qnum = qobject_to_qnum(res);
+ qnum = qobject_to(QNum, res);
g_assert(qnum);
g_assert(qnum_get_try_int(qnum, &val));
g_assert_cmpint(val, ==, -42);
@@ -487,22 +487,22 @@ static void test_visitor_in_any(TestInputVisitorData *data,
v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
visit_type_any(v, NULL, &res, &error_abort);
- qdict = qobject_to_qdict(res);
+ qdict = qobject_to(QDict, res);
g_assert(qdict && qdict_size(qdict) == 3);
qobj = qdict_get(qdict, "integer");
g_assert(qobj);
- qnum = qobject_to_qnum(qobj);
+ qnum = qobject_to(QNum, qobj);
g_assert(qnum);
g_assert(qnum_get_try_int(qnum, &val));
g_assert_cmpint(val, ==, -42);
qobj = qdict_get(qdict, "boolean");
g_assert(qobj);
- qbool = qobject_to_qbool(qobj);
+ qbool = qobject_to(QBool, qobj);
g_assert(qbool);
g_assert(qbool_get_bool(qbool) == true);
qobj = qdict_get(qdict, "string");
g_assert(qobj);
- qstring = qobject_to_qstring(qobj);
+ qstring = qobject_to(QString, qobj);
g_assert(qstring);
g_assert_cmpstr(qstring_get_str(qstring), ==, "foo");
qobject_decref(res);
@@ -1250,24 +1250,27 @@ static void test_visitor_in_fail_alternate(TestInputVisitorData *data,
}
static void do_test_visitor_in_qmp_introspect(TestInputVisitorData *data,
- const char *schema_json)
+ const QLitObject *qlit)
{
SchemaInfoList *schema = NULL;
+ QObject *obj = qobject_from_qlit(qlit);
Visitor *v;
- v = visitor_input_test_init_raw(data, schema_json);
+ v = qobject_input_visitor_new(obj);
visit_type_SchemaInfoList(v, NULL, &schema, &error_abort);
g_assert(schema);
qapi_free_SchemaInfoList(schema);
+ qobject_decref(obj);
+ visit_free(v);
}
static void test_visitor_in_qmp_introspect(TestInputVisitorData *data,
const void *unused)
{
- do_test_visitor_in_qmp_introspect(data, test_qmp_schema_json);
- do_test_visitor_in_qmp_introspect(data, qmp_schema_json);
+ do_test_visitor_in_qmp_introspect(data, &test_qmp_schema_qlit);
+ do_test_visitor_in_qmp_introspect(data, &qmp_schema_qlit);
}
int main(int argc, char **argv)
diff --git a/tests/test-qobject-output-visitor.c b/tests/test-qobject-output-visitor.c
index 11e8c5aa40..ecf21c0f31 100644
--- a/tests/test-qobject-output-visitor.c
+++ b/tests/test-qobject-output-visitor.c
@@ -66,7 +66,7 @@ static void test_visitor_out_int(TestOutputVisitorData *data,
visit_type_int(data->ov, NULL, &value, &error_abort);
- qnum = qobject_to_qnum(visitor_get(data));
+ qnum = qobject_to(QNum, visitor_get(data));
g_assert(qnum);
g_assert(qnum_get_try_int(qnum, &val));
g_assert_cmpint(val, ==, value);
@@ -80,7 +80,7 @@ static void test_visitor_out_bool(TestOutputVisitorData *data,
visit_type_bool(data->ov, NULL, &value, &error_abort);
- qbool = qobject_to_qbool(visitor_get(data));
+ qbool = qobject_to(QBool, visitor_get(data));
g_assert(qbool);
g_assert(qbool_get_bool(qbool) == value);
}
@@ -93,7 +93,7 @@ static void test_visitor_out_number(TestOutputVisitorData *data,
visit_type_number(data->ov, NULL, &value, &error_abort);
- qnum = qobject_to_qnum(visitor_get(data));
+ qnum = qobject_to(QNum, visitor_get(data));
g_assert(qnum);
g_assert(qnum_get_double(qnum) == value);
}
@@ -106,7 +106,7 @@ static void test_visitor_out_string(TestOutputVisitorData *data,
visit_type_str(data->ov, NULL, &string, &error_abort);
- qstr = qobject_to_qstring(visitor_get(data));
+ qstr = qobject_to(QString, visitor_get(data));
g_assert(qstr);
g_assert_cmpstr(qstring_get_str(qstr), ==, string);
}
@@ -120,7 +120,7 @@ static void test_visitor_out_no_string(TestOutputVisitorData *data,
/* A null string should return "" */
visit_type_str(data->ov, NULL, &string, &error_abort);
- qstr = qobject_to_qstring(visitor_get(data));
+ qstr = qobject_to(QString, visitor_get(data));
g_assert(qstr);
g_assert_cmpstr(qstring_get_str(qstr), ==, "");
}
@@ -134,7 +134,7 @@ static void test_visitor_out_enum(TestOutputVisitorData *data,
for (i = 0; i < ENUM_ONE__MAX; i++) {
visit_type_EnumOne(data->ov, "unused", &i, &error_abort);
- qstr = qobject_to_qstring(visitor_get(data));
+ qstr = qobject_to(QString, visitor_get(data));
g_assert(qstr);
g_assert_cmpstr(qstring_get_str(qstr), ==, EnumOne_str(i));
visitor_reset(data);
@@ -167,7 +167,7 @@ static void test_visitor_out_struct(TestOutputVisitorData *data,
visit_type_TestStruct(data->ov, NULL, &p, &error_abort);
- qdict = qobject_to_qdict(visitor_get(data));
+ qdict = qobject_to(QDict, visitor_get(data));
g_assert(qdict);
g_assert_cmpint(qdict_size(qdict), ==, 3);
g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 42);
@@ -206,7 +206,7 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
visit_type_UserDefTwo(data->ov, "unused", &ud2, &error_abort);
- qdict = qobject_to_qdict(visitor_get(data));
+ qdict = qobject_to(QDict, visitor_get(data));
g_assert(qdict);
g_assert_cmpint(qdict_size(qdict), ==, 2);
g_assert_cmpstr(qdict_get_str(qdict, "string0"), ==, strings[0]);
@@ -280,7 +280,7 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
visit_type_TestStructList(data->ov, NULL, &head, &error_abort);
- qlist = qobject_to_qlist(visitor_get(data));
+ qlist = qobject_to(QList, visitor_get(data));
g_assert(qlist);
g_assert(!qlist_empty(qlist));
@@ -289,7 +289,7 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
QLIST_FOREACH_ENTRY(qlist, entry) {
QDict *qdict;
- qdict = qobject_to_qdict(entry->value);
+ qdict = qobject_to(QDict, entry->value);
g_assert(qdict);
g_assert_cmpint(qdict_size(qdict), ==, 3);
g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, value_int + i);
@@ -342,7 +342,7 @@ static void test_visitor_out_any(TestOutputVisitorData *data,
qobj = QOBJECT(qnum_from_int(-42));
visit_type_any(data->ov, NULL, &qobj, &error_abort);
- qnum = qobject_to_qnum(visitor_get(data));
+ qnum = qobject_to(QNum, visitor_get(data));
g_assert(qnum);
g_assert(qnum_get_try_int(qnum, &val));
g_assert_cmpint(val, ==, -42);
@@ -356,16 +356,16 @@ static void test_visitor_out_any(TestOutputVisitorData *data,
qobj = QOBJECT(qdict);
visit_type_any(data->ov, NULL, &qobj, &error_abort);
qobject_decref(qobj);
- qdict = qobject_to_qdict(visitor_get(data));
+ qdict = qobject_to(QDict, visitor_get(data));
g_assert(qdict);
- qnum = qobject_to_qnum(qdict_get(qdict, "integer"));
+ qnum = qobject_to(QNum, qdict_get(qdict, "integer"));
g_assert(qnum);
g_assert(qnum_get_try_int(qnum, &val));
g_assert_cmpint(val, ==, -42);
- qbool = qobject_to_qbool(qdict_get(qdict, "boolean"));
+ qbool = qobject_to(QBool, qdict_get(qdict, "boolean"));
g_assert(qbool);
g_assert(qbool_get_bool(qbool) == true);
- qstring = qobject_to_qstring(qdict_get(qdict, "string"));
+ qstring = qobject_to(QString, qdict_get(qdict, "string"));
g_assert(qstring);
g_assert_cmpstr(qstring_get_str(qstring), ==, "foo");
}
@@ -382,7 +382,7 @@ static void test_visitor_out_union_flat(TestOutputVisitorData *data,
tmp->u.value1.boolean = true;
visit_type_UserDefFlatUnion(data->ov, NULL, &tmp, &error_abort);
- qdict = qobject_to_qdict(visitor_get(data));
+ qdict = qobject_to(QDict, visitor_get(data));
g_assert(qdict);
g_assert_cmpstr(qdict_get_str(qdict, "enum1"), ==, "value1");
g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "str");
@@ -406,7 +406,7 @@ static void test_visitor_out_alternate(TestOutputVisitorData *data,
tmp->u.i = 42;
visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
- qnum = qobject_to_qnum(visitor_get(data));
+ qnum = qobject_to(QNum, visitor_get(data));
g_assert(qnum);
g_assert(qnum_get_try_int(qnum, &val));
g_assert_cmpint(val, ==, 42);
@@ -419,7 +419,7 @@ static void test_visitor_out_alternate(TestOutputVisitorData *data,
tmp->u.e = ENUM_ONE_VALUE1;
visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
- qstr = qobject_to_qstring(visitor_get(data));
+ qstr = qobject_to(QString, visitor_get(data));
g_assert(qstr);
g_assert_cmpstr(qstring_get_str(qstr), ==, "value1");
@@ -444,7 +444,7 @@ static void test_visitor_out_alternate(TestOutputVisitorData *data,
tmp->u.udfu.u.value1.boolean = true;
visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
- qdict = qobject_to_qdict(visitor_get(data));
+ qdict = qobject_to(QDict, visitor_get(data));
g_assert(qdict);
g_assert_cmpint(qdict_size(qdict), ==, 4);
g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 1);
@@ -466,7 +466,7 @@ static void test_visitor_out_null(TestOutputVisitorData *data,
visit_type_null(data->ov, "a", &null, &error_abort);
visit_check_struct(data->ov, &error_abort);
visit_end_struct(data->ov, NULL);
- qdict = qobject_to_qdict(visitor_get(data));
+ qdict = qobject_to(QDict, visitor_get(data));
g_assert(qdict);
g_assert_cmpint(qdict_size(qdict), ==, 1);
nil = qdict_get(qdict, "a");
@@ -610,10 +610,10 @@ static void check_native_list(QObject *qobj,
QList *qlist;
int i;
- qdict = qobject_to_qdict(qobj);
+ qdict = qobject_to(QDict, qobj);
g_assert(qdict);
g_assert(qdict_haskey(qdict, "data"));
- qlist = qlist_copy(qobject_to_qlist(qdict_get(qdict, "data")));
+ qlist = qlist_copy(qobject_to(QList, qdict_get(qdict, "data")));
switch (kind) {
case USER_DEF_NATIVE_LIST_UNION_KIND_U8:
@@ -627,7 +627,7 @@ static void check_native_list(QObject *qobj,
tmp = qlist_peek(qlist);
g_assert(tmp);
- qvalue = qobject_to_qnum(tmp);
+ qvalue = qobject_to(QNum, tmp);
g_assert(qnum_get_try_uint(qvalue, &val));
g_assert_cmpint(val, ==, i);
qobject_decref(qlist_pop(qlist));
@@ -651,7 +651,7 @@ static void check_native_list(QObject *qobj,
tmp = qlist_peek(qlist);
g_assert(tmp);
- qvalue = qobject_to_qnum(tmp);
+ qvalue = qobject_to(QNum, tmp);
g_assert(qnum_get_try_int(qvalue, &val));
g_assert_cmpint(val, ==, i);
qobject_decref(qlist_pop(qlist));
@@ -663,7 +663,7 @@ static void check_native_list(QObject *qobj,
QBool *qvalue;
tmp = qlist_peek(qlist);
g_assert(tmp);
- qvalue = qobject_to_qbool(tmp);
+ qvalue = qobject_to(QBool, tmp);
g_assert_cmpint(qbool_get_bool(qvalue), ==, i % 3 == 0);
qobject_decref(qlist_pop(qlist));
}
@@ -675,7 +675,7 @@ static void check_native_list(QObject *qobj,
gchar str[8];
tmp = qlist_peek(qlist);
g_assert(tmp);
- qvalue = qobject_to_qstring(tmp);
+ qvalue = qobject_to(QString, tmp);
sprintf(str, "%d", i);
g_assert_cmpstr(qstring_get_str(qvalue), ==, str);
qobject_decref(qlist_pop(qlist));
@@ -690,7 +690,7 @@ static void check_native_list(QObject *qobj,
tmp = qlist_peek(qlist);
g_assert(tmp);
- qvalue = qobject_to_qnum(tmp);
+ qvalue = qobject_to(QNum, tmp);
g_string_printf(double_expected, "%.6f", (double)i / 3);
g_string_printf(double_actual, "%.6f", qnum_get_double(qvalue));
g_assert_cmpstr(double_actual->str, ==, double_expected->str);
diff --git a/tests/test-util-sockets.c b/tests/test-util-sockets.c
new file mode 100644
index 0000000000..acadd85e8f
--- /dev/null
+++ b/tests/test-util-sockets.c
@@ -0,0 +1,266 @@
+/*
+ * Tests for util/qemu-sockets.c
+ *
+ * Copyright 2018 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu/sockets.h"
+#include "qapi/error.h"
+#include "socket-helpers.h"
+#include "monitor/monitor.h"
+
+static void test_fd_is_socket_bad(void)
+{
+ char *tmp = g_strdup("qemu-test-util-sockets-XXXXXX");
+ int fd = mkstemp(tmp);
+ if (fd != 0) {
+ unlink(tmp);
+ }
+ g_free(tmp);
+
+ g_assert(fd >= 0);
+
+ g_assert(!fd_is_socket(fd));
+ close(fd);
+}
+
+static void test_fd_is_socket_good(void)
+{
+ int fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
+
+ g_assert(fd >= 0);
+
+ g_assert(fd_is_socket(fd));
+ close(fd);
+}
+
+static int mon_fd = -1;
+static const char *mon_fdname;
+
+int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp)
+{
+ g_assert(cur_mon);
+ g_assert(mon == cur_mon);
+ if (mon_fd == -1 || !g_str_equal(mon_fdname, fdname)) {
+ error_setg(errp, "No fd named %s", fdname);
+ return -1;
+ }
+ return dup(mon_fd);
+}
+
+/* Syms in libqemustub.a are discarded at .o file granularity.
+ * To replace monitor_get_fd() we must ensure everything in
+ * stubs/monitor.c is defined, to make sure monitor.o is discarded
+ * otherwise we get duplicate syms at link time.
+ */
+Monitor *cur_mon;
+void monitor_init(Chardev *chr, int flags) {}
+
+
+static void test_socket_fd_pass_name_good(void)
+{
+ SocketAddress addr;
+ int fd;
+
+ cur_mon = g_malloc(1); /* Fake a monitor */
+ mon_fdname = "myfd";
+ mon_fd = qemu_socket(AF_INET, SOCK_STREAM, 0);
+ g_assert_cmpint(mon_fd, >, STDERR_FILENO);
+
+ addr.type = SOCKET_ADDRESS_TYPE_FD;
+ addr.u.fd.str = g_strdup(mon_fdname);
+
+ fd = socket_connect(&addr, &error_abort);
+ g_assert_cmpint(fd, !=, -1);
+ g_assert_cmpint(fd, !=, mon_fd);
+ close(fd);
+
+ fd = socket_listen(&addr, &error_abort);
+ g_assert_cmpint(fd, !=, -1);
+ g_assert_cmpint(fd, !=, mon_fd);
+ close(fd);
+
+ g_free(addr.u.fd.str);
+ mon_fdname = NULL;
+ close(mon_fd);
+ mon_fd = -1;
+ g_free(cur_mon);
+ cur_mon = NULL;
+}
+
+static void test_socket_fd_pass_name_bad(void)
+{
+ SocketAddress addr;
+ Error *err = NULL;
+ int fd;
+
+ cur_mon = g_malloc(1); /* Fake a monitor */
+ mon_fdname = "myfd";
+ mon_fd = dup(STDOUT_FILENO);
+ g_assert_cmpint(mon_fd, >, STDERR_FILENO);
+
+ addr.type = SOCKET_ADDRESS_TYPE_FD;
+ addr.u.fd.str = g_strdup(mon_fdname);
+
+ fd = socket_connect(&addr, &err);
+ g_assert_cmpint(fd, ==, -1);
+ error_free_or_abort(&err);
+
+ fd = socket_listen(&addr, &err);
+ g_assert_cmpint(fd, ==, -1);
+ error_free_or_abort(&err);
+
+ g_free(addr.u.fd.str);
+ mon_fdname = NULL;
+ close(mon_fd);
+ mon_fd = -1;
+ g_free(cur_mon);
+ cur_mon = NULL;
+}
+
+static void test_socket_fd_pass_name_nomon(void)
+{
+ SocketAddress addr;
+ Error *err = NULL;
+ int fd;
+
+ g_assert(cur_mon == NULL);
+
+ addr.type = SOCKET_ADDRESS_TYPE_FD;
+ addr.u.fd.str = g_strdup("myfd");
+
+ fd = socket_connect(&addr, &err);
+ g_assert_cmpint(fd, ==, -1);
+ error_free_or_abort(&err);
+
+ fd = socket_listen(&addr, &err);
+ g_assert_cmpint(fd, ==, -1);
+ error_free_or_abort(&err);
+
+ g_free(addr.u.fd.str);
+}
+
+
+static void test_socket_fd_pass_num_good(void)
+{
+ SocketAddress addr;
+ int fd, sfd;
+
+ g_assert(cur_mon == NULL);
+ sfd = qemu_socket(AF_INET, SOCK_STREAM, 0);
+ g_assert_cmpint(sfd, >, STDERR_FILENO);
+
+ addr.type = SOCKET_ADDRESS_TYPE_FD;
+ addr.u.fd.str = g_strdup_printf("%d", sfd);
+
+ fd = socket_connect(&addr, &error_abort);
+ g_assert_cmpint(fd, ==, sfd);
+
+ fd = socket_listen(&addr, &error_abort);
+ g_assert_cmpint(fd, ==, sfd);
+
+ g_free(addr.u.fd.str);
+ close(sfd);
+}
+
+static void test_socket_fd_pass_num_bad(void)
+{
+ SocketAddress addr;
+ Error *err = NULL;
+ int fd, sfd;
+
+ g_assert(cur_mon == NULL);
+ sfd = dup(STDOUT_FILENO);
+
+ addr.type = SOCKET_ADDRESS_TYPE_FD;
+ addr.u.fd.str = g_strdup_printf("%d", sfd);
+
+ fd = socket_connect(&addr, &err);
+ g_assert_cmpint(fd, ==, -1);
+ error_free_or_abort(&err);
+
+ fd = socket_listen(&addr, &err);
+ g_assert_cmpint(fd, ==, -1);
+ error_free_or_abort(&err);
+
+ g_free(addr.u.fd.str);
+ close(sfd);
+}
+
+static void test_socket_fd_pass_num_nocli(void)
+{
+ SocketAddress addr;
+ Error *err = NULL;
+ int fd;
+
+ cur_mon = g_malloc(1); /* Fake a monitor */
+
+ addr.type = SOCKET_ADDRESS_TYPE_FD;
+ addr.u.fd.str = g_strdup_printf("%d", STDOUT_FILENO);
+
+ fd = socket_connect(&addr, &err);
+ g_assert_cmpint(fd, ==, -1);
+ error_free_or_abort(&err);
+
+ fd = socket_listen(&addr, &err);
+ g_assert_cmpint(fd, ==, -1);
+ error_free_or_abort(&err);
+
+ g_free(addr.u.fd.str);
+}
+
+
+int main(int argc, char **argv)
+{
+ bool has_ipv4, has_ipv6;
+
+ socket_init();
+
+ g_test_init(&argc, &argv, NULL);
+
+ /* We're creating actual IPv4/6 sockets, so we should
+ * check if the host running tests actually supports
+ * each protocol to avoid breaking tests on machines
+ * with either IPv4 or IPv6 disabled.
+ */
+ if (socket_check_protocol_support(&has_ipv4, &has_ipv6) < 0) {
+ return 1;
+ }
+
+ if (has_ipv4) {
+ g_test_add_func("/util/socket/is-socket/bad",
+ test_fd_is_socket_bad);
+ g_test_add_func("/util/socket/is-socket/good",
+ test_fd_is_socket_good);
+ g_test_add_func("/socket/fd-pass/name/good",
+ test_socket_fd_pass_name_good);
+ g_test_add_func("/socket/fd-pass/name/bad",
+ test_socket_fd_pass_name_bad);
+ g_test_add_func("/socket/fd-pass/name/nomon",
+ test_socket_fd_pass_name_nomon);
+ g_test_add_func("/socket/fd-pass/num/good",
+ test_socket_fd_pass_num_good);
+ g_test_add_func("/socket/fd-pass/num/bad",
+ test_socket_fd_pass_num_bad);
+ g_test_add_func("/socket/fd-pass/num/nocli",
+ test_socket_fd_pass_num_nocli);
+ }
+
+ return g_test_run();
+}
diff --git a/tests/test-x86-cpuid-compat.c b/tests/test-x86-cpuid-compat.c
index 495dd1e7ef..02e41843fc 100644
--- a/tests/test-x86-cpuid-compat.c
+++ b/tests/test-x86-cpuid-compat.c
@@ -17,7 +17,7 @@ static char *get_cpu0_qom_path(void)
g_assert(qdict_haskey(resp, "return"));
ret = qdict_get_qlist(resp, "return");
- cpu0 = qobject_to_qdict(qlist_peek(ret));
+ cpu0 = qobject_to(QDict, qlist_peek(ret));
path = g_strdup(qdict_get_str(cpu0, "qom_path"));
QDECREF(resp);
return path;
@@ -38,7 +38,7 @@ static QObject *qom_get(const char *path, const char *prop)
#ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS
static bool qom_get_bool(const char *path, const char *prop)
{
- QBool *value = qobject_to_qbool(qom_get(path, prop));
+ QBool *value = qobject_to(QBool, qom_get(path, prop));
bool b = qbool_get_bool(value);
QDECREF(value);
@@ -61,7 +61,7 @@ static void test_cpuid_prop(const void *data)
qtest_start(args->cmdline);
path = get_cpu0_qom_path();
- value = qobject_to_qnum(qom_get(path, args->property));
+ value = qobject_to(QNum, qom_get(path, args->property));
g_assert(qnum_get_try_int(value, &val));
g_assert_cmpint(val, ==, args->expected_value);
qtest_end();
@@ -105,7 +105,7 @@ static uint32_t get_feature_word(QList *features, uint32_t eax, uint32_t ecx,
const QListEntry *e;
for (e = qlist_first(features); e; e = qlist_next(e)) {
- QDict *w = qobject_to_qdict(qlist_entry_obj(e));
+ QDict *w = qobject_to(QDict, qlist_entry_obj(e));
const char *rreg = qdict_get_str(w, "cpuid-register");
uint32_t reax = qdict_get_int(w, "cpuid-input-eax");
bool has_ecx = qdict_haskey(w, "cpuid-input-ecx");
@@ -116,8 +116,9 @@ static uint32_t get_feature_word(QList *features, uint32_t eax, uint32_t ecx,
recx = qdict_get_int(w, "cpuid-input-ecx");
}
if (eax == reax && (!has_ecx || ecx == recx) && !strcmp(rreg, reg)) {
- g_assert(qnum_get_try_int(qobject_to_qnum(qdict_get(w, "features")),
- &val));
+ g_assert(qnum_get_try_int(qobject_to(QNum,
+ qdict_get(w, "features")),
+ &val));
return val;
}
}
@@ -133,8 +134,8 @@ static void test_feature_flag(const void *data)
qtest_start(args->cmdline);
path = get_cpu0_qom_path();
- present = qobject_to_qlist(qom_get(path, "feature-words"));
- filtered = qobject_to_qlist(qom_get(path, "filtered-features"));
+ present = qobject_to(QList, qom_get(path, "feature-words"));
+ filtered = qobject_to(QList, qom_get(path, "filtered-features"));
value = get_feature_word(present, args->in_eax, args->in_ecx, args->reg);
value |= get_feature_word(filtered, args->in_eax, args->in_ecx, args->reg);
qtest_end();
diff --git a/tests/virtio-scsi-test.c b/tests/virtio-scsi-test.c
index 7393d69bb2..037872bb98 100644
--- a/tests/virtio-scsi-test.c
+++ b/tests/virtio-scsi-test.c
@@ -216,6 +216,9 @@ static void test_unaligned_write_same(void)
const uint8_t write_same_cdb_2[VIRTIO_SCSI_CDB_SIZE] = {
0x41, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x33, 0x00, 0x00
};
+ const uint8_t write_same_cdb_ndob[VIRTIO_SCSI_CDB_SIZE] = {
+ 0x41, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x33, 0x00, 0x00
+ };
vs = qvirtio_scsi_pci_init(PCI_SLOT);
@@ -225,6 +228,9 @@ static void test_unaligned_write_same(void)
g_assert_cmphex(0, ==,
virtio_scsi_do_command(vs, write_same_cdb_2, NULL, 0, buf2, 512, NULL));
+ g_assert_cmphex(0, ==,
+ virtio_scsi_do_command(vs, write_same_cdb_ndob, NULL, 0, NULL, 0, NULL));
+
qvirtio_scsi_pci_free(vs);
}