1e0493a4af57c1a73376a7bafaed542c01f588196Eric Lifrom autotest_lib.client.common_lib import error
222434d4311581dde7a3bb51eef03a27d757aa263Eric Lifrom autotest_lib.client.virt import kvm_monitor
3861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li
4e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
5e0493a4af57c1a73376a7bafaed542c01f588196Eric Lidef run_qmp_basic(test, params, env):
6e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    """
7e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    QMP Specification test-suite: this checks if the *basic* protocol conforms
8e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    to its specification, which is file QMP/qmp-spec.txt in QEMU's source tree.
9e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
10e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    IMPORTANT NOTES:
11e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
12e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        o Most tests depend heavily on QMP's error information (eg. classes),
13e0493a4af57c1a73376a7bafaed542c01f588196Eric Li          this might have bad implications as the error interface is going to
14e0493a4af57c1a73376a7bafaed542c01f588196Eric Li          change in QMP
15e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
16e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        o Command testing is *not* covered in this suite. Each command has its
17e0493a4af57c1a73376a7bafaed542c01f588196Eric Li          own specification and should be tested separately
18e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
19e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        o We use the same terminology as used by the QMP specification,
20e0493a4af57c1a73376a7bafaed542c01f588196Eric Li          specially with regard to JSON types (eg. a Python dict is called
21e0493a4af57c1a73376a7bafaed542c01f588196Eric Li          a json-object)
22e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
23e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        o This is divided in sub test-suites, please check the bottom of this
24e0493a4af57c1a73376a7bafaed542c01f588196Eric Li          file to check the order in which they are run
25e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
26e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    TODO:
27e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
28e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        o Finding which test failed is not as easy as it should be
29e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
30e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        o Are all those check_*() functions really needed? Wouldn't a
31e0493a4af57c1a73376a7bafaed542c01f588196Eric Li          specialized class (eg. a Response class) do better?
32e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    """
33e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def fail_no_key(qmp_dict, key):
34e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        if not isinstance(qmp_dict, dict):
35e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            raise error.TestFail("qmp_dict is not a dict (it's '%s')" %
36e0493a4af57c1a73376a7bafaed542c01f588196Eric Li                                 type(qmp_dict))
37e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        if not key in qmp_dict:
38e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            raise error.TestFail("'%s' key doesn't exist in dict ('%s')" %
39e0493a4af57c1a73376a7bafaed542c01f588196Eric Li                                 (key, str(qmp_dict)))
40e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
41e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
42e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def check_dict_key(qmp_dict, key, keytype):
43e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
44e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        Performs the following checks on a QMP dict key:
45e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
46e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        1. qmp_dict is a dict
47e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        2. key exists in qmp_dict
48e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        3. key is of type keytype
49e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
50e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        If any of these checks fails, error.TestFail is raised.
51e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
52e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        fail_no_key(qmp_dict, key)
53e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        if not isinstance(qmp_dict[key], keytype):
54e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            raise error.TestFail("'%s' key is not of type '%s', it's '%s'" %
55e0493a4af57c1a73376a7bafaed542c01f588196Eric Li                                 (key, keytype, type(qmp_dict[key])))
56e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
57e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
58e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def check_key_is_dict(qmp_dict, key):
59e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_dict_key(qmp_dict, key, dict)
60e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
61e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
62e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def check_key_is_list(qmp_dict, key):
63e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_dict_key(qmp_dict, key, list)
64e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
65e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
66e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def check_key_is_str(qmp_dict, key):
67e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_dict_key(qmp_dict, key, unicode)
68e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
69e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
70e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def check_str_key(qmp_dict, keyname, value=None):
71e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_dict_key(qmp_dict, keyname, unicode)
72e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        if value and value != qmp_dict[keyname]:
73e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            raise error.TestFail("'%s' key value '%s' should be '%s'" %
74e0493a4af57c1a73376a7bafaed542c01f588196Eric Li                                 (keyname, str(qmp_dict[keyname]), str(value)))
75e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
76e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
77e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def check_key_is_int(qmp_dict, key):
78e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        fail_no_key(qmp_dict, key)
79e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        try:
80e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            value = int(qmp_dict[key])
81e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        except:
82e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            raise error.TestFail("'%s' key is not of type int, it's '%s'" %
83e0493a4af57c1a73376a7bafaed542c01f588196Eric Li                                 (key, type(qmp_dict[key])))
84e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
85e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
86e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def check_bool_key(qmp_dict, keyname, value=None):
87e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_dict_key(qmp_dict, keyname, bool)
88e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        if value and value != qmp_dict[keyname]:
89e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            raise error.TestFail("'%s' key value '%s' should be '%s'" %
90e0493a4af57c1a73376a7bafaed542c01f588196Eric Li                                 (keyname, str(qmp_dict[keyname]), str(value)))
91e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
92e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
93e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def check_success_resp(resp, empty=False):
94e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
95e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        Check QMP OK response.
96e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
97e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        @param resp: QMP response
98e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        @param empty: if True, response should not contain data to return
99e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
100e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_key_is_dict(resp, "return")
101e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        if empty and len(resp["return"]) > 0:
102e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            raise error.TestFail("success response is not empty ('%s')" %
103e0493a4af57c1a73376a7bafaed542c01f588196Eric Li                                 str(resp))
104e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
105e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
106e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def check_error_resp(resp, classname=None, datadict=None):
107e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
108e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        Check QMP error response.
109e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
110e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        @param resp: QMP response
111e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        @param classname: Expected error class name
112e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        @param datadict: Expected error data dictionary
113e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
114e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_key_is_dict(resp, "error")
115e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_key_is_str(resp["error"], "class")
116e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        if classname and resp["error"]["class"] != classname:
117e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            raise error.TestFail("got error class '%s' expected '%s'" %
118e0493a4af57c1a73376a7bafaed542c01f588196Eric Li                                 (resp["error"]["class"], classname))
119e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_key_is_dict(resp["error"], "data")
120e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        if datadict and resp["error"]["data"] != datadict:
121e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            raise error.TestFail("got data dict '%s' expected '%s'" %
122e0493a4af57c1a73376a7bafaed542c01f588196Eric Li                                 (resp["error"]["data"], datadict))
123e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
124e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
125e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def test_version(version):
126e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
127e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        Check the QMP greeting message version key which, according to QMP's
128e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        documentation, should be:
129e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
130e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        { "qemu": { "major": json-int, "minor": json-int, "micro": json-int }
131e0493a4af57c1a73376a7bafaed542c01f588196Eric Li          "package": json-string }
132e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
133e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_key_is_dict(version, "qemu")
134e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        for key in [ "major", "minor", "micro" ]:
135e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            check_key_is_int(version["qemu"], key)
136e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_key_is_str(version, "package")
137e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
138e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
139e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def test_greeting(greeting):
140e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_key_is_dict(greeting, "QMP")
141e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_key_is_dict(greeting["QMP"], "version")
142e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_key_is_list(greeting["QMP"], "capabilities")
143e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
144e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
145e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def greeting_suite(monitor):
146e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
147e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        Check the greeting message format, as described in the QMP
148e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        specfication section '2.2 Server Greeting'.
149e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
150e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        { "QMP": { "version": json-object, "capabilities": json-array } }
151e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
152e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        greeting = monitor.get_greeting()
153e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        test_greeting(greeting)
154e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        test_version(greeting["QMP"]["version"])
155e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
156e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
157e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def json_parsing_errors_suite(monitor):
158e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
159e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        Check that QMP's parser is able to recover from parsing errors, please
160e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check the JSON spec for more info on the JSON syntax (RFC 4627).
161e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
162e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # We're quite simple right now and the focus is on parsing errors that
163e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # have already biten us in the past.
164e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        #
165e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # TODO: The following test-cases are missing:
166e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        #
167e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        #   - JSON numbers, strings and arrays
168e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        #   - More invalid characters or malformed structures
169e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        #   - Valid, but not obvious syntax, like zillion of spaces or
170e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        #     strings with unicode chars (different suite maybe?)
171e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        bad_json = []
172e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
173e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # A JSON value MUST be an object, array, number, string, true, false,
174e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # or null
175e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        #
176e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # NOTE: QMP seems to ignore a number of chars, like: | and ?
177e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        bad_json.append(":")
178e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        bad_json.append(",")
179e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
180e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # Malformed json-objects
181e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        #
182e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # NOTE: sending only "}" seems to break QMP
183e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # NOTE: Duplicate keys are accepted (should it?)
184e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        bad_json.append("{ \"execute\" }")
185e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        bad_json.append("{ \"execute\": \"query-version\", }")
186e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        bad_json.append("{ 1: \"query-version\" }")
187e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        bad_json.append("{ true: \"query-version\" }")
188e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        bad_json.append("{ []: \"query-version\" }")
189e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        bad_json.append("{ {}: \"query-version\" }")
190e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
191e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        for cmd in bad_json:
192e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            resp = monitor.cmd_raw(cmd)
193e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            check_error_resp(resp, "JSONParsing")
194e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
195e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
196e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def test_id_key(monitor):
197e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
198e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        Check that QMP's "id" key is correctly handled.
199e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
200e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # The "id" key must be echoed back in error responses
201861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li        id_key = "kvm-autotest"
202861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li        resp = monitor.cmd_qmp("eject", { "foobar": True }, id=id_key)
203e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_error_resp(resp)
204861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li        check_str_key(resp, "id", id_key)
205e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
206e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # The "id" key must be echoed back in success responses
207861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li        resp = monitor.cmd_qmp("query-status", id=id_key)
208e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_success_resp(resp)
209861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li        check_str_key(resp, "id", id_key)
210e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
211e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # The "id" key can be any json-object
212861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li        for id_key in [ True, 1234, "string again!", [1, [], {}, True, "foo"],
213e0493a4af57c1a73376a7bafaed542c01f588196Eric Li                    { "key": {} } ]:
214861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li            resp = monitor.cmd_qmp("query-status", id=id_key)
215e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            check_success_resp(resp)
216861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li            if resp["id"] != id_key:
217e0493a4af57c1a73376a7bafaed542c01f588196Eric Li                raise error.TestFail("expected id '%s' but got '%s'" %
218861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li                                     (str(id_key), str(resp["id"])))
219e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
220e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
221e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def test_invalid_arg_key(monitor):
222e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
223e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        Currently, the only supported keys in the input object are: "execute",
224e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        "arguments" and "id". Although expansion is supported, invalid key
225e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        names must be detected.
226e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
227e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        resp = monitor.cmd_obj({ "execute": "eject", "foobar": True })
228e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_error_resp(resp, "QMPExtraInputObjectMember",
229e0493a4af57c1a73376a7bafaed542c01f588196Eric Li                         { "member": "foobar" })
230e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
231e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
232e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def test_bad_arguments_key_type(monitor):
233e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
234e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        The "arguments" key must be an json-object.
235e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
236e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        We use the eject command to perform the tests, but that's a random
237e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        choice, any command that accepts arguments will do, as the command
238e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        doesn't get called.
239e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
240e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        for item in [ True, [], 1, "foo" ]:
241e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            resp = monitor.cmd_obj({ "execute": "eject", "arguments": item })
242e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            check_error_resp(resp, "QMPBadInputObjectMember",
243e0493a4af57c1a73376a7bafaed542c01f588196Eric Li                             { "member": "arguments", "expected": "object" })
244e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
245e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
246e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def test_bad_execute_key_type(monitor):
247e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
248e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        The "execute" key must be a json-string.
249e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
250e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        for item in [ False, 1, {}, [] ]:
251e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            resp = monitor.cmd_obj({ "execute": item })
252e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            check_error_resp(resp, "QMPBadInputObjectMember",
253e0493a4af57c1a73376a7bafaed542c01f588196Eric Li                             { "member": "execute", "expected": "string" })
254e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
255e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
256e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def test_no_execute_key(monitor):
257e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
258e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        The "execute" key must exist, we also test for some stupid parsing
259e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        errors.
260e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
261e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        for cmd in [ {}, { "execut": "qmp_capabilities" },
262e0493a4af57c1a73376a7bafaed542c01f588196Eric Li                     { "executee": "qmp_capabilities" }, { "foo": "bar" }]:
263e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            resp = monitor.cmd_obj(cmd)
264e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            check_error_resp(resp) # XXX: check class and data dict?
265e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
266e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
267e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def test_bad_input_obj_type(monitor):
268e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
269e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        The input object must be... an json-object.
270e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
271e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        for cmd in [ "foo", [], True, 1 ]:
272e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            resp = monitor.cmd_obj(cmd)
273e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            check_error_resp(resp, "QMPBadInputObject", { "expected":"object" })
274e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
275e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
276e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def test_good_input_obj(monitor):
277e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
278e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        Basic success tests for issuing QMP commands.
279e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
280e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # NOTE: We don't use the cmd_qmp() method here because the command
281e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # object is in a 'random' order
282e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        resp = monitor.cmd_obj({ "execute": "query-version" })
283e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_success_resp(resp)
284e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
285e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        resp = monitor.cmd_obj({ "arguments": {}, "execute": "query-version" })
286e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_success_resp(resp)
287e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
288e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        id = "1234foo"
289e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        resp = monitor.cmd_obj({ "id": id, "execute": "query-version",
290e0493a4af57c1a73376a7bafaed542c01f588196Eric Li                                 "arguments": {} })
291e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_success_resp(resp)
292e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_str_key(resp, "id", id)
293e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
294e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # TODO: would be good to test simple argument usage, but we don't have
295e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # a read-only command that accepts arguments.
296e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
297e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
298e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def input_object_suite(monitor):
299e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
300e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        Check the input object format, as described in the QMP specfication
301e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        section '2.3 Issuing Commands'.
302e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
303e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        { "execute": json-string, "arguments": json-object, "id": json-value }
304e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
305e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        test_good_input_obj(monitor)
306e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        test_bad_input_obj_type(monitor)
307e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        test_no_execute_key(monitor)
308e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        test_bad_execute_key_type(monitor)
309e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        test_bad_arguments_key_type(monitor)
310e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        test_id_key(monitor)
311e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        test_invalid_arg_key(monitor)
312e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
313e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
314e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def argument_checker_suite(monitor):
315e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
316e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        Check that QMP's argument checker is detecting all possible errors.
317e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
318e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        We use a number of different commands to perform the checks, but the
319e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        command used doesn't matter much as QMP performs argument checking
320e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        _before_ calling the command.
321e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
322e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # stop doesn't take arguments
323e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        resp = monitor.cmd_qmp("stop", { "foo": 1 })
324e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_error_resp(resp, "InvalidParameter", { "name": "foo" })
325e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
326e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # required argument omitted
327e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        resp = monitor.cmd_qmp("screendump")
328e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_error_resp(resp, "MissingParameter", { "name": "filename" })
329e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
330e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # 'bar' is not a valid argument
331e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        resp = monitor.cmd_qmp("screendump", { "filename": "outfile",
332e0493a4af57c1a73376a7bafaed542c01f588196Eric Li                                               "bar": "bar" })
333e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_error_resp(resp, "InvalidParameter", { "name": "bar"})
334e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
335e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # test optional argument: 'force' is omitted, but it's optional, so
336e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # the handler has to be called. Test this happens by checking an
337e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # error that is generated by the handler itself.
338e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        resp = monitor.cmd_qmp("eject", { "device": "foobar" })
339e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_error_resp(resp, "DeviceNotFound")
340e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
341e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # filename argument must be a json-string
342e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        for arg in [ {}, [], 1, True ]:
343e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            resp = monitor.cmd_qmp("screendump", { "filename": arg })
344e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            check_error_resp(resp, "InvalidParameterType",
345e0493a4af57c1a73376a7bafaed542c01f588196Eric Li                             { "name": "filename", "expected": "string" })
346e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
347e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # force argument must be a json-bool
348e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        for arg in [ {}, [], 1, "foo" ]:
349e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            resp = monitor.cmd_qmp("eject", { "force": arg, "device": "foo" })
350e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            check_error_resp(resp, "InvalidParameterType",
351e0493a4af57c1a73376a7bafaed542c01f588196Eric Li                             { "name": "force", "expected": "bool" })
352e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
353e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # val argument must be a json-int
354e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        for arg in [ {}, [], True, "foo" ]:
355e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            resp = monitor.cmd_qmp("memsave", { "val": arg, "filename": "foo",
356e0493a4af57c1a73376a7bafaed542c01f588196Eric Li                                                "size": 10 })
357e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            check_error_resp(resp, "InvalidParameterType",
358e0493a4af57c1a73376a7bafaed542c01f588196Eric Li                             { "name": "val", "expected": "int" })
359e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
360e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # value argument must be a json-number
361e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        for arg in [ {}, [], True, "foo" ]:
362e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            resp = monitor.cmd_qmp("migrate_set_speed", { "value": arg })
363e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            check_error_resp(resp, "InvalidParameterType",
364e0493a4af57c1a73376a7bafaed542c01f588196Eric Li                             { "name": "value", "expected": "number" })
365e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
366e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # qdev-type commands have their own argument checker, all QMP does
367e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # is to skip its checking and pass arguments through. Check this
368e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # works by providing invalid options to device_add and expecting
369e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # an error message from qdev
370861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li        resp = monitor.cmd_qmp("device_add", { "driver": "e1000",
371861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li                                              "foo": "bar" })
372e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        check_error_resp(resp, "PropertyNotFound",
373e0493a4af57c1a73376a7bafaed542c01f588196Eric Li                               {"device": "e1000", "property": "foo"})
374e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
375e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
376e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    def unknown_commands_suite(monitor):
377e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
378e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        Check that QMP handles unknown commands correctly.
379e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        """
380e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        # We also call a HMP-only command, to be sure it will fail as expected
381e0493a4af57c1a73376a7bafaed542c01f588196Eric Li        for cmd in [ "bar", "query-", "query-foo", "q", "help" ]:
382e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            resp = monitor.cmd_qmp(cmd)
383e0493a4af57c1a73376a7bafaed542c01f588196Eric Li            check_error_resp(resp, "CommandNotFound", { "name": cmd })
384e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
385e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
386861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li    vm = env.get_vm(params["main_vm"])
387861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li    vm.verify_alive()
388861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li
389861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li    # Look for the first qmp monitor available, otherwise, fail the test
390861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li    qmp_monitor = None
391861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li    for m in vm.monitors:
392861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li        if isinstance(m, kvm_monitor.QMPMonitor):
393861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li            qmp_monitor = m
394861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li
395861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li    if qmp_monitor is None:
396861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li        raise error.TestError('Could not find a QMP monitor, aborting test')
397e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
398e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    # Run all suites
399861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li    greeting_suite(qmp_monitor)
400861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li    input_object_suite(qmp_monitor)
401861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li    argument_checker_suite(qmp_monitor)
402861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li    unknown_commands_suite(qmp_monitor)
403861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li    json_parsing_errors_suite(qmp_monitor)
404e0493a4af57c1a73376a7bafaed542c01f588196Eric Li
405e0493a4af57c1a73376a7bafaed542c01f588196Eric Li    # check if QMP is still alive
406861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li    if not qmp_monitor.is_responsive():
407861b2d54aec24228cdb3895dbc40062cb40cb2adEric Li        raise error.TestFail('QMP monitor is not responsive after testing')
408