migration/rdma: Return -1 instead of negative errno code
[qemu/kevin.git] / tests / qtest / migration-helpers.c
blob0c185db450fead06e44c0ad84e8e1fe0ef6eece3
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 migrate_watch_for_stop(QTestState *who, const char *name,
27 QDict *event, void *opaque)
29 bool *seen = opaque;
31 if (g_str_equal(name, "STOP")) {
32 *seen = true;
33 return true;
36 return false;
39 bool migrate_watch_for_resume(QTestState *who, const char *name,
40 QDict *event, void *opaque)
42 bool *seen = opaque;
44 if (g_str_equal(name, "RESUME")) {
45 *seen = true;
46 return true;
49 return false;
52 void migrate_qmp_fail(QTestState *who, const char *uri, const char *fmt, ...)
54 va_list ap;
55 QDict *args, *err;
57 va_start(ap, fmt);
58 args = qdict_from_vjsonf_nofail(fmt, ap);
59 va_end(ap);
61 g_assert(!qdict_haskey(args, "uri"));
62 qdict_put_str(args, "uri", uri);
64 err = qtest_qmp_assert_failure_ref(
65 who, "{ 'execute': 'migrate', 'arguments': %p}", args);
67 g_assert(qdict_haskey(err, "desc"));
69 qobject_unref(err);
73 * Send QMP command "migrate".
74 * Arguments are built from @fmt... (formatted like
75 * qobject_from_jsonf_nofail()) with "uri": @uri spliced in.
77 void migrate_qmp(QTestState *who, const char *uri, const char *fmt, ...)
79 va_list ap;
80 QDict *args;
82 va_start(ap, fmt);
83 args = qdict_from_vjsonf_nofail(fmt, ap);
84 va_end(ap);
86 g_assert(!qdict_haskey(args, "uri"));
87 qdict_put_str(args, "uri", uri);
89 qtest_qmp_assert_success(who,
90 "{ 'execute': 'migrate', 'arguments': %p}", args);
93 void migrate_set_capability(QTestState *who, const char *capability,
94 bool value)
96 qtest_qmp_assert_success(who,
97 "{ 'execute': 'migrate-set-capabilities',"
98 "'arguments': { "
99 "'capabilities': [ { "
100 "'capability': %s, 'state': %i } ] } }",
101 capability, value);
104 void migrate_incoming_qmp(QTestState *to, const char *uri, const char *fmt, ...)
106 va_list ap;
107 QDict *args, *rsp, *data;
109 va_start(ap, fmt);
110 args = qdict_from_vjsonf_nofail(fmt, ap);
111 va_end(ap);
113 g_assert(!qdict_haskey(args, "uri"));
114 qdict_put_str(args, "uri", uri);
116 migrate_set_capability(to, "events", true);
118 rsp = qtest_qmp(to, "{ 'execute': 'migrate-incoming', 'arguments': %p}",
119 args);
120 g_assert(qdict_haskey(rsp, "return"));
121 qobject_unref(rsp);
123 rsp = qtest_qmp_eventwait_ref(to, "MIGRATION");
124 g_assert(qdict_haskey(rsp, "data"));
126 data = qdict_get_qdict(rsp, "data");
127 g_assert(qdict_haskey(data, "status"));
128 g_assert_cmpstr(qdict_get_str(data, "status"), ==, "setup");
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 qtest_qmp_assert_success_ref(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 = qtest_qmp_assert_success_ref(from,
238 "{ 'execute': 'query-status' }");
239 g_assert(qdict_haskey(rsp_return, "running"));
240 g_assert(qdict_get_bool(rsp_return, "running"));
241 qobject_unref(rsp_return);