|
|
7711c0 |
From c455d2804d7ef6c379b815b6787baf69d3cb760a Mon Sep 17 00:00:00 2001
|
|
|
7711c0 |
From: John Snow <jsnow@redhat.com>
|
|
|
7711c0 |
Date: Wed, 20 Mar 2019 16:16:20 +0100
|
|
|
7711c0 |
Subject: [PATCH 022/163] iotests: add qmp recursive sorting function
|
|
|
7711c0 |
|
|
|
7711c0 |
RH-Author: John Snow <jsnow@redhat.com>
|
|
|
7711c0 |
Message-id: <20190320161631.14841-9-jsnow@redhat.com>
|
|
|
7711c0 |
Patchwork-id: 84944
|
|
|
7711c0 |
O-Subject: [RHEL-7.7 qemu-kvm-rhev PATCH 08/19] iotests: add qmp recursive sorting function
|
|
|
7711c0 |
Bugzilla: 1668956
|
|
|
7711c0 |
RH-Acked-by: Max Reitz <mreitz@redhat.com>
|
|
|
7711c0 |
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
7711c0 |
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
7711c0 |
|
|
|
7711c0 |
Python before 3.6 does not sort dictionaries (including kwargs).
|
|
|
7711c0 |
Therefore, printing QMP objects involves sorting the keys to have
|
|
|
7711c0 |
a predictable ordering in the iotests output. This means that
|
|
|
7711c0 |
iotests output will sometimes show arguments in an order not
|
|
|
7711c0 |
specified by the test author.
|
|
|
7711c0 |
|
|
|
7711c0 |
Presently, we accomplish this by using json.dumps' sort_keys argument,
|
|
|
7711c0 |
where we only serialize the arguments dictionary, but not the command.
|
|
|
7711c0 |
|
|
|
7711c0 |
However, if we want to pretty-print QMP objects being sent to the
|
|
|
7711c0 |
QEMU process, we need to build the entire command before logging it.
|
|
|
7711c0 |
Ordinarily, this would then involve "arguments" being sorted above
|
|
|
7711c0 |
"execute", which would necessitate a rather ugly and harder-to-read
|
|
|
7711c0 |
change to many iotests outputs.
|
|
|
7711c0 |
|
|
|
7711c0 |
To facilitate pretty-printing AND maintaining predictable output AND
|
|
|
7711c0 |
having "arguments" sort after "execute", add a custom sort function
|
|
|
7711c0 |
that takes a dictionary and recursively builds an OrderedDict that
|
|
|
7711c0 |
maintains the specific key order we wish to see in iotests output.
|
|
|
7711c0 |
|
|
|
7711c0 |
The qmp_log function uses this to build a QMP object that keeps
|
|
|
7711c0 |
"execute" above "arguments", but sorts all keys and keys in any
|
|
|
7711c0 |
subdicts in "arguments" lexicographically to maintain consistent
|
|
|
7711c0 |
iotests output, with no incompatible changes to any current test.
|
|
|
7711c0 |
|
|
|
7711c0 |
Signed-off-by: John Snow <jsnow@redhat.com>
|
|
|
7711c0 |
Reviewed-by: Eric Blake <eblake@redhat.com>
|
|
|
7711c0 |
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
|
7711c0 |
Message-Id: <20181221093529.23855-8-jsnow@redhat.com>
|
|
|
7711c0 |
Signed-off-by: Eric Blake <eblake@redhat.com>
|
|
|
7711c0 |
(cherry picked from commit 0706e87d72b02f28bfa04400388f9c9df1b9c943)
|
|
|
7711c0 |
Signed-off-by: John Snow <jsnow@redhat.com>
|
|
|
7711c0 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
7711c0 |
---
|
|
|
7711c0 |
tests/qemu-iotests/iotests.py | 24 ++++++++++++++++++++----
|
|
|
7711c0 |
1 file changed, 20 insertions(+), 4 deletions(-)
|
|
|
7711c0 |
|
|
|
7711c0 |
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
|
|
|
7711c0 |
index 5334ff4..bd508be 100644
|
|
|
7711c0 |
--- a/tests/qemu-iotests/iotests.py
|
|
|
7711c0 |
+++ b/tests/qemu-iotests/iotests.py
|
|
|
7711c0 |
@@ -28,6 +28,7 @@ import json
|
|
|
7711c0 |
import signal
|
|
|
7711c0 |
import logging
|
|
|
7711c0 |
import atexit
|
|
|
7711c0 |
+from collections import OrderedDict
|
|
|
7711c0 |
|
|
|
7711c0 |
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'scripts'))
|
|
|
7711c0 |
import qtest
|
|
|
7711c0 |
@@ -73,6 +74,16 @@ def qemu_img(*args):
|
|
|
7711c0 |
sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args))))
|
|
|
7711c0 |
return exitcode
|
|
|
7711c0 |
|
|
|
7711c0 |
+def ordered_kwargs(kwargs):
|
|
|
7711c0 |
+ # kwargs prior to 3.6 are not ordered, so:
|
|
|
7711c0 |
+ od = OrderedDict()
|
|
|
7711c0 |
+ for k, v in sorted(kwargs.items()):
|
|
|
7711c0 |
+ if isinstance(v, dict):
|
|
|
7711c0 |
+ od[k] = ordered_kwargs(v)
|
|
|
7711c0 |
+ else:
|
|
|
7711c0 |
+ od[k] = v
|
|
|
7711c0 |
+ return od
|
|
|
7711c0 |
+
|
|
|
7711c0 |
def qemu_img_create(*args):
|
|
|
7711c0 |
args = list(args)
|
|
|
7711c0 |
|
|
|
7711c0 |
@@ -251,8 +262,10 @@ def filter_img_info(output, filename):
|
|
|
7711c0 |
def log(msg, filters=[]):
|
|
|
7711c0 |
for flt in filters:
|
|
|
7711c0 |
msg = flt(msg)
|
|
|
7711c0 |
- if type(msg) is dict or type(msg) is list:
|
|
|
7711c0 |
- print(json.dumps(msg, sort_keys=True))
|
|
|
7711c0 |
+ if isinstance(msg, dict) or isinstance(msg, list):
|
|
|
7711c0 |
+ # Don't sort if it's already sorted
|
|
|
7711c0 |
+ do_sort = not isinstance(msg, OrderedDict)
|
|
|
7711c0 |
+ print(json.dumps(msg, sort_keys=do_sort))
|
|
|
7711c0 |
else:
|
|
|
7711c0 |
print(msg)
|
|
|
7711c0 |
|
|
|
7711c0 |
@@ -442,8 +455,11 @@ class VM(qtest.QEMUQtestMachine):
|
|
|
7711c0 |
return result
|
|
|
7711c0 |
|
|
|
7711c0 |
def qmp_log(self, cmd, filters=[filter_testfiles], **kwargs):
|
|
|
7711c0 |
- logmsg = '{"execute": "%s", "arguments": %s}' % \
|
|
|
7711c0 |
- (cmd, json.dumps(kwargs, sort_keys=True))
|
|
|
7711c0 |
+ full_cmd = OrderedDict((
|
|
|
7711c0 |
+ ("execute", cmd),
|
|
|
7711c0 |
+ ("arguments", ordered_kwargs(kwargs))
|
|
|
7711c0 |
+ ))
|
|
|
7711c0 |
+ logmsg = json.dumps(full_cmd)
|
|
|
7711c0 |
log(logmsg, filters)
|
|
|
7711c0 |
result = self.qmp(cmd, **kwargs)
|
|
|
7711c0 |
log(json.dumps(result, sort_keys=True), filters)
|
|
|
7711c0 |
--
|
|
|
7711c0 |
1.8.3.1
|
|
|
7711c0 |
|