target/i386: reimplement 0x0f 0x50-0x5f, add AVX
[qemu.git] / tests / qtest / migration-helpers.c
blobf6f3c6680f57fc47e039f48340d28148365bf614
1 /*
2 * QTest migration helpers
4 * Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates
5 * based on the vhost-user-test.c that is:
6 * Copyright (c) 2014 Virtual Open Systems Sarl.
8 * This work is licensed under the terms of the GNU GPL, version 2 or later.
9 * See the COPYING file in the top-level directory.
13 #include "qemu/osdep.h"
14 #include "qapi/qmp/qjson.h"
16 #include "migration-helpers.h"
19 * Number of seconds we wait when looking for migration
20 * status changes, to avoid test suite hanging forever
21 * when things go wrong. Needs to be higher enough to
22 * avoid false positives on loaded hosts.
24 #define MIGRATION_STATUS_WAIT_TIMEOUT 120
26 bool got_stop;
28 static void check_stop_event(QTestState *who)
30 QDict *event = qtest_qmp_event_ref(who, "STOP");
31 if (event) {
32 got_stop = true;
33 qobject_unref(event);
37 #ifndef _WIN32
39 * Events can get in the way of responses we are actually waiting for.
41 QDict *wait_command_fd(QTestState *who, int fd, const char *command, ...)
43 va_list ap;
44 QDict *resp, *ret;
46 va_start(ap, command);
47 qtest_qmp_vsend_fds(who, &fd, 1, command, ap);
48 va_end(ap);
50 resp = qtest_qmp_receive(who);
51 check_stop_event(who);
53 g_assert(!qdict_haskey(resp, "error"));
54 g_assert(qdict_haskey(resp, "return"));
56 ret = qdict_get_qdict(resp, "return");
57 qobject_ref(ret);
58 qobject_unref(resp);
60 return ret;
62 #endif
65 * Events can get in the way of responses we are actually waiting for.
67 QDict *wait_command(QTestState *who, const char *command, ...)
69 va_list ap;
70 QDict *resp, *ret;
72 va_start(ap, command);
73 resp = qtest_vqmp(who, command, ap);
74 va_end(ap);
76 check_stop_event(who);
78 g_assert(!qdict_haskey(resp, "error"));
79 g_assert(qdict_haskey(resp, "return"));
81 ret = qdict_get_qdict(resp, "return");
82 qobject_ref(ret);
83 qobject_unref(resp);
85 return ret;
89 * Execute the qmp command only
91 QDict *qmp_command(QTestState *who, const char *command, ...)
93 va_list ap;
94 QDict *resp, *ret;
96 va_start(ap, command);
97 resp = qtest_vqmp(who, command, ap);
98 va_end(ap);
100 g_assert(!qdict_haskey(resp, "error"));
101 g_assert(qdict_haskey(resp, "return"));
103 ret = qdict_get_qdict(resp, "return");
104 qobject_ref(ret);
105 qobject_unref(resp);
107 return ret;
111 * Send QMP command "migrate".
112 * Arguments are built from @fmt... (formatted like
113 * qobject_from_jsonf_nofail()) with "uri": @uri spliced in.
115 void migrate_qmp(QTestState *who, const char *uri, const char *fmt, ...)
117 va_list ap;
118 QDict *args, *rsp;
120 va_start(ap, fmt);
121 args = qdict_from_vjsonf_nofail(fmt, ap);
122 va_end(ap);
124 g_assert(!qdict_haskey(args, "uri"));
125 qdict_put_str(args, "uri", uri);
127 rsp = qtest_qmp(who, "{ 'execute': 'migrate', 'arguments': %p}", args);
129 g_assert(qdict_haskey(rsp, "return"));
130 qobject_unref(rsp);
134 * Note: caller is responsible to free the returned object via
135 * qobject_unref() after use
137 QDict *migrate_query(QTestState *who)
139 return wait_command(who, "{ 'execute': 'query-migrate' }");
142 QDict *migrate_query_not_failed(QTestState *who)
144 const char *status;
145 QDict *rsp = migrate_query(who);
146 status = qdict_get_str(rsp, "status");
147 if (g_str_equal(status, "failed")) {
148 g_printerr("query-migrate shows failed migration: %s\n",
149 qdict_get_str(rsp, "error-desc"));
151 g_assert(!g_str_equal(status, "failed"));
152 return rsp;
156 * Note: caller is responsible to free the returned object via
157 * g_free() after use
159 static gchar *migrate_query_status(QTestState *who)
161 QDict *rsp_return = migrate_query(who);
162 gchar *status = g_strdup(qdict_get_str(rsp_return, "status"));
164 g_assert(status);
165 qobject_unref(rsp_return);
167 return status;
170 static bool check_migration_status(QTestState *who, const char *goal,
171 const char **ungoals)
173 bool ready;
174 char *current_status;
175 const char **ungoal;
177 current_status = migrate_query_status(who);
178 ready = strcmp(current_status, goal) == 0;
179 if (!ungoals) {
180 g_assert_cmpstr(current_status, !=, "failed");
182 * If looking for a state other than completed,
183 * completion of migration would cause the test to
184 * hang.
186 if (strcmp(goal, "completed") != 0) {
187 g_assert_cmpstr(current_status, !=, "completed");
189 } else {
190 for (ungoal = ungoals; *ungoal; ungoal++) {
191 g_assert_cmpstr(current_status, !=, *ungoal);
194 g_free(current_status);
195 return ready;
198 void wait_for_migration_status(QTestState *who,
199 const char *goal, const char **ungoals)
201 g_test_timer_start();
202 while (!check_migration_status(who, goal, ungoals)) {
203 usleep(1000);
205 g_assert(g_test_timer_elapsed() < MIGRATION_STATUS_WAIT_TIMEOUT);
209 void wait_for_migration_complete(QTestState *who)
211 wait_for_migration_status(who, "completed", NULL);
214 void wait_for_migration_fail(QTestState *from, bool allow_active)
216 g_test_timer_start();
217 QDict *rsp_return;
218 char *status;
219 bool failed;
221 do {
222 status = migrate_query_status(from);
223 bool result = !strcmp(status, "setup") || !strcmp(status, "failed") ||
224 (allow_active && !strcmp(status, "active"));
225 if (!result) {
226 fprintf(stderr, "%s: unexpected status status=%s allow_active=%d\n",
227 __func__, status, allow_active);
229 g_assert(result);
230 failed = !strcmp(status, "failed");
231 g_free(status);
233 g_assert(g_test_timer_elapsed() < MIGRATION_STATUS_WAIT_TIMEOUT);
234 } while (!failed);
236 /* Is the machine currently running? */
237 rsp_return = wait_command(from, "{ 'execute': 'query-status' }");
238 g_assert(qdict_haskey(rsp_return, "running"));
239 g_assert(qdict_get_bool(rsp_return, "running"));
240 qobject_unref(rsp_return);