1da668aa1SThomas Huth #include "qemu/osdep.h"
2da668aa1SThomas Huth #include <locale.h>
3da668aa1SThomas Huth #include <glib/gstdio.h>
4da668aa1SThomas Huth #include <sys/socket.h>
5da668aa1SThomas Huth #include <sys/un.h>
6da668aa1SThomas Huth
7907b5105SMarc-André Lureau #include "../qtest/libqtest.h"
8da668aa1SThomas Huth #include "qapi/qmp/qdict.h"
9da668aa1SThomas Huth #include "qapi/qmp/qlist.h"
10da668aa1SThomas Huth
11da668aa1SThomas Huth typedef struct {
12da668aa1SThomas Huth char *test_dir;
13da668aa1SThomas Huth GMainLoop *loop;
14da668aa1SThomas Huth int fd;
15da668aa1SThomas Huth GPid pid;
16da668aa1SThomas Huth } TestFixture;
17da668aa1SThomas Huth
connect_qga(char * path)18da668aa1SThomas Huth static int connect_qga(char *path)
19da668aa1SThomas Huth {
20da668aa1SThomas Huth int s, ret, len, i = 0;
21da668aa1SThomas Huth struct sockaddr_un remote;
22da668aa1SThomas Huth
23da668aa1SThomas Huth s = socket(AF_UNIX, SOCK_STREAM, 0);
24da668aa1SThomas Huth g_assert(s != -1);
25da668aa1SThomas Huth
26da668aa1SThomas Huth remote.sun_family = AF_UNIX;
27da668aa1SThomas Huth do {
28da668aa1SThomas Huth strcpy(remote.sun_path, path);
29da668aa1SThomas Huth len = strlen(remote.sun_path) + sizeof(remote.sun_family);
30da668aa1SThomas Huth ret = connect(s, (struct sockaddr *)&remote, len);
31da668aa1SThomas Huth if (ret == -1) {
32da668aa1SThomas Huth g_usleep(G_USEC_PER_SEC);
33da668aa1SThomas Huth }
34da668aa1SThomas Huth if (i++ == 10) {
355dc51100SPaolo Bonzini close(s);
36da668aa1SThomas Huth return -1;
37da668aa1SThomas Huth }
38da668aa1SThomas Huth } while (ret == -1);
39da668aa1SThomas Huth
40da668aa1SThomas Huth return s;
41da668aa1SThomas Huth }
42da668aa1SThomas Huth
qga_watch(GPid pid,gint status,gpointer user_data)43da668aa1SThomas Huth static void qga_watch(GPid pid, gint status, gpointer user_data)
44da668aa1SThomas Huth {
45da668aa1SThomas Huth TestFixture *fixture = user_data;
46da668aa1SThomas Huth
47da668aa1SThomas Huth g_assert_cmpint(status, ==, 0);
48da668aa1SThomas Huth g_main_loop_quit(fixture->loop);
49da668aa1SThomas Huth }
50da668aa1SThomas Huth
51da668aa1SThomas Huth static void
fixture_setup(TestFixture * fixture,gconstpointer data,gchar ** envp)52da668aa1SThomas Huth fixture_setup(TestFixture *fixture, gconstpointer data, gchar **envp)
53da668aa1SThomas Huth {
54da668aa1SThomas Huth const gchar *extra_arg = data;
55da668aa1SThomas Huth GError *error = NULL;
56bb6960a1SMarc-André Lureau g_autofree char *cwd = NULL;
57bb6960a1SMarc-André Lureau g_autofree char *path = NULL;
58bb6960a1SMarc-André Lureau g_autofree char *cmd = NULL;
59bb6960a1SMarc-André Lureau g_auto(GStrv) argv = NULL;
60da668aa1SThomas Huth
61da668aa1SThomas Huth fixture->loop = g_main_loop_new(NULL, FALSE);
62da668aa1SThomas Huth
635b9f2781SBin Meng fixture->test_dir = g_strdup_printf("%s/qgatest.XXXXXX", g_get_tmp_dir());
643c239aa7SBin Meng g_assert_nonnull(g_mkdtemp(fixture->test_dir));
65da668aa1SThomas Huth
66da668aa1SThomas Huth path = g_build_filename(fixture->test_dir, "sock", NULL);
67da668aa1SThomas Huth cwd = g_get_current_dir();
68da668aa1SThomas Huth cmd = g_strdup_printf("%s%cqga%cqemu-ga -m unix-listen -t %s -p %s %s %s",
69da668aa1SThomas Huth cwd, G_DIR_SEPARATOR, G_DIR_SEPARATOR,
70da668aa1SThomas Huth fixture->test_dir, path,
71da668aa1SThomas Huth getenv("QTEST_LOG") ? "-v" : "",
72da668aa1SThomas Huth extra_arg ?: "");
73da668aa1SThomas Huth g_shell_parse_argv(cmd, NULL, &argv, &error);
74da668aa1SThomas Huth g_assert_no_error(error);
75da668aa1SThomas Huth
76da668aa1SThomas Huth g_spawn_async(fixture->test_dir, argv, envp,
77da668aa1SThomas Huth G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD,
78da668aa1SThomas Huth NULL, NULL, &fixture->pid, &error);
79da668aa1SThomas Huth g_assert_no_error(error);
80da668aa1SThomas Huth
81da668aa1SThomas Huth g_child_watch_add(fixture->pid, qga_watch, fixture);
82da668aa1SThomas Huth
83da668aa1SThomas Huth fixture->fd = connect_qga(path);
84da668aa1SThomas Huth g_assert_cmpint(fixture->fd, !=, -1);
85da668aa1SThomas Huth }
86da668aa1SThomas Huth
87da668aa1SThomas Huth static void
fixture_tear_down(TestFixture * fixture,gconstpointer data)88da668aa1SThomas Huth fixture_tear_down(TestFixture *fixture, gconstpointer data)
89da668aa1SThomas Huth {
90bb6960a1SMarc-André Lureau g_autofree char *tmp = NULL;
91da668aa1SThomas Huth
92da668aa1SThomas Huth kill(fixture->pid, SIGTERM);
93da668aa1SThomas Huth
94da668aa1SThomas Huth g_main_loop_run(fixture->loop);
95da668aa1SThomas Huth g_main_loop_unref(fixture->loop);
96da668aa1SThomas Huth
97da668aa1SThomas Huth g_spawn_close_pid(fixture->pid);
98da668aa1SThomas Huth
99da668aa1SThomas Huth tmp = g_build_filename(fixture->test_dir, "foo", NULL);
100da668aa1SThomas Huth g_unlink(tmp);
101da668aa1SThomas Huth g_free(tmp);
102da668aa1SThomas Huth
103da668aa1SThomas Huth tmp = g_build_filename(fixture->test_dir, "qga.state", NULL);
104da668aa1SThomas Huth g_unlink(tmp);
105da668aa1SThomas Huth g_free(tmp);
106da668aa1SThomas Huth
107da668aa1SThomas Huth tmp = g_build_filename(fixture->test_dir, "sock", NULL);
108da668aa1SThomas Huth g_unlink(tmp);
109da668aa1SThomas Huth
110da668aa1SThomas Huth g_rmdir(fixture->test_dir);
111da668aa1SThomas Huth g_free(fixture->test_dir);
112da668aa1SThomas Huth close(fixture->fd);
113da668aa1SThomas Huth }
114da668aa1SThomas Huth
qmp_assertion_message_error(const char * domain,const char * file,int line,const char * func,const char * expr,QDict * dict)115da668aa1SThomas Huth static void qmp_assertion_message_error(const char *domain,
116da668aa1SThomas Huth const char *file,
117da668aa1SThomas Huth int line,
118da668aa1SThomas Huth const char *func,
119da668aa1SThomas Huth const char *expr,
120da668aa1SThomas Huth QDict *dict)
121da668aa1SThomas Huth {
122da668aa1SThomas Huth const char *class, *desc;
123bb6960a1SMarc-André Lureau g_autofree char *s = NULL;
124da668aa1SThomas Huth QDict *error;
125da668aa1SThomas Huth
126da668aa1SThomas Huth error = qdict_get_qdict(dict, "error");
127da668aa1SThomas Huth class = qdict_get_try_str(error, "class");
128da668aa1SThomas Huth desc = qdict_get_try_str(error, "desc");
129da668aa1SThomas Huth
130da668aa1SThomas Huth s = g_strdup_printf("assertion failed %s: %s %s", expr, class, desc);
131da668aa1SThomas Huth g_assertion_message(domain, file, line, func, s);
132da668aa1SThomas Huth }
133da668aa1SThomas Huth
134da668aa1SThomas Huth #define qmp_assert_no_error(err) do { \
135da668aa1SThomas Huth if (qdict_haskey(err, "error")) { \
136da668aa1SThomas Huth qmp_assertion_message_error(G_LOG_DOMAIN, __FILE__, __LINE__, \
137da668aa1SThomas Huth G_STRFUNC, #err, err); \
138da668aa1SThomas Huth } \
139da668aa1SThomas Huth } while (0)
140da668aa1SThomas Huth
test_qga_sync_delimited(gconstpointer fix)141da668aa1SThomas Huth static void test_qga_sync_delimited(gconstpointer fix)
142da668aa1SThomas Huth {
143da668aa1SThomas Huth const TestFixture *fixture = fix;
144da668aa1SThomas Huth guint32 v, r = g_test_rand_int();
145da668aa1SThomas Huth unsigned char c;
146bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL;
147da668aa1SThomas Huth
148da668aa1SThomas Huth qmp_fd_send_raw(fixture->fd, "\xff");
149da668aa1SThomas Huth qmp_fd_send(fixture->fd,
150da668aa1SThomas Huth "{'execute': 'guest-sync-delimited',"
151da668aa1SThomas Huth " 'arguments': {'id': %u } }",
152da668aa1SThomas Huth r);
153da668aa1SThomas Huth
154da668aa1SThomas Huth /*
155da668aa1SThomas Huth * Read and ignore garbage until resynchronized.
156da668aa1SThomas Huth *
157da668aa1SThomas Huth * Note that the full reset sequence would involve checking the
158da668aa1SThomas Huth * response of guest-sync-delimited and repeating the loop if
159da668aa1SThomas Huth * 'id' field of the response does not match the 'id' field of
160da668aa1SThomas Huth * the request. Testing this fully would require inserting
161da668aa1SThomas Huth * garbage in the response stream and is left as a future test
162da668aa1SThomas Huth * to implement.
163da668aa1SThomas Huth *
164da668aa1SThomas Huth * TODO: The server shouldn't emit so much garbage (among other
165da668aa1SThomas Huth * things, it loudly complains about the client's \xff being
166da668aa1SThomas Huth * invalid JSON, even though it is a documented part of the
167da668aa1SThomas Huth * handshake.
168da668aa1SThomas Huth */
169da668aa1SThomas Huth do {
170da668aa1SThomas Huth v = read(fixture->fd, &c, 1);
171da668aa1SThomas Huth g_assert_cmpint(v, ==, 1);
172da668aa1SThomas Huth } while (c != 0xff);
173da668aa1SThomas Huth
174da668aa1SThomas Huth ret = qmp_fd_receive(fixture->fd);
175da668aa1SThomas Huth g_assert_nonnull(ret);
176da668aa1SThomas Huth qmp_assert_no_error(ret);
177da668aa1SThomas Huth
178da668aa1SThomas Huth v = qdict_get_int(ret, "return");
179da668aa1SThomas Huth g_assert_cmpint(r, ==, v);
180da668aa1SThomas Huth }
181da668aa1SThomas Huth
test_qga_sync(gconstpointer fix)182da668aa1SThomas Huth static void test_qga_sync(gconstpointer fix)
183da668aa1SThomas Huth {
184da668aa1SThomas Huth const TestFixture *fixture = fix;
185da668aa1SThomas Huth guint32 v, r = g_test_rand_int();
186bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL;
187da668aa1SThomas Huth
188da668aa1SThomas Huth /*
189da668aa1SThomas Huth * TODO guest-sync is inherently limited: we cannot distinguish
190da668aa1SThomas Huth * failure caused by reacting to garbage on the wire prior to this
191da668aa1SThomas Huth * command, from failure of this actual command. Clients are
192da668aa1SThomas Huth * supposed to be able to send a raw '\xff' byte to at least
193da668aa1SThomas Huth * re-synchronize the server's parser prior to this command, but
194da668aa1SThomas Huth * we are not in a position to test that here because (at least
195da668aa1SThomas Huth * for now) it causes the server to issue an error message about
196da668aa1SThomas Huth * invalid JSON. Testing of '\xff' handling is done in
197da668aa1SThomas Huth * guest-sync-delimited instead.
198da668aa1SThomas Huth */
199da668aa1SThomas Huth ret = qmp_fd(fixture->fd,
200da668aa1SThomas Huth "{'execute': 'guest-sync', 'arguments': {'id': %u } }",
201da668aa1SThomas Huth r);
202da668aa1SThomas Huth
203da668aa1SThomas Huth g_assert_nonnull(ret);
204da668aa1SThomas Huth qmp_assert_no_error(ret);
205da668aa1SThomas Huth
206da668aa1SThomas Huth v = qdict_get_int(ret, "return");
207da668aa1SThomas Huth g_assert_cmpint(r, ==, v);
208da668aa1SThomas Huth }
209da668aa1SThomas Huth
test_qga_ping(gconstpointer fix)210da668aa1SThomas Huth static void test_qga_ping(gconstpointer fix)
211da668aa1SThomas Huth {
212da668aa1SThomas Huth const TestFixture *fixture = fix;
213bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL;
214da668aa1SThomas Huth
215da668aa1SThomas Huth ret = qmp_fd(fixture->fd, "{'execute': 'guest-ping'}");
216da668aa1SThomas Huth g_assert_nonnull(ret);
217da668aa1SThomas Huth qmp_assert_no_error(ret);
218da668aa1SThomas Huth }
219da668aa1SThomas Huth
test_qga_id(gconstpointer fix)220da668aa1SThomas Huth static void test_qga_id(gconstpointer fix)
221da668aa1SThomas Huth {
222da668aa1SThomas Huth const TestFixture *fixture = fix;
223bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL;
224da668aa1SThomas Huth
225da668aa1SThomas Huth ret = qmp_fd(fixture->fd, "{'execute': 'guest-ping', 'id': 1}");
226da668aa1SThomas Huth g_assert_nonnull(ret);
227da668aa1SThomas Huth qmp_assert_no_error(ret);
228da668aa1SThomas Huth g_assert_cmpint(qdict_get_int(ret, "id"), ==, 1);
229da668aa1SThomas Huth }
230da668aa1SThomas Huth
test_qga_invalid_oob(gconstpointer fix)231da668aa1SThomas Huth static void test_qga_invalid_oob(gconstpointer fix)
232da668aa1SThomas Huth {
233da668aa1SThomas Huth const TestFixture *fixture = fix;
234da668aa1SThomas Huth QDict *ret;
235da668aa1SThomas Huth
236da668aa1SThomas Huth ret = qmp_fd(fixture->fd, "{'exec-oob': 'guest-ping'}");
237da668aa1SThomas Huth g_assert_nonnull(ret);
238da668aa1SThomas Huth
239da668aa1SThomas Huth qmp_expect_error_and_unref(ret, "GenericError");
240da668aa1SThomas Huth }
241da668aa1SThomas Huth
test_qga_invalid_args(gconstpointer fix)242da668aa1SThomas Huth static void test_qga_invalid_args(gconstpointer fix)
243da668aa1SThomas Huth {
244da668aa1SThomas Huth const TestFixture *fixture = fix;
245bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL;
246bb6960a1SMarc-André Lureau QDict *error;
247da668aa1SThomas Huth const gchar *class, *desc;
248da668aa1SThomas Huth
249da668aa1SThomas Huth ret = qmp_fd(fixture->fd, "{'execute': 'guest-ping', "
250da668aa1SThomas Huth "'arguments': {'foo': 42 }}");
251da668aa1SThomas Huth g_assert_nonnull(ret);
252da668aa1SThomas Huth
253da668aa1SThomas Huth error = qdict_get_qdict(ret, "error");
254da668aa1SThomas Huth class = qdict_get_try_str(error, "class");
255da668aa1SThomas Huth desc = qdict_get_try_str(error, "desc");
256da668aa1SThomas Huth
257da668aa1SThomas Huth g_assert_cmpstr(class, ==, "GenericError");
258da668aa1SThomas Huth g_assert_cmpstr(desc, ==, "Parameter 'foo' is unexpected");
259da668aa1SThomas Huth }
260da668aa1SThomas Huth
test_qga_invalid_cmd(gconstpointer fix)261da668aa1SThomas Huth static void test_qga_invalid_cmd(gconstpointer fix)
262da668aa1SThomas Huth {
263da668aa1SThomas Huth const TestFixture *fixture = fix;
264bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL;
265bb6960a1SMarc-André Lureau QDict *error;
266da668aa1SThomas Huth const gchar *class, *desc;
267da668aa1SThomas Huth
268da668aa1SThomas Huth ret = qmp_fd(fixture->fd, "{'execute': 'guest-invalid-cmd'}");
269da668aa1SThomas Huth g_assert_nonnull(ret);
270da668aa1SThomas Huth
271da668aa1SThomas Huth error = qdict_get_qdict(ret, "error");
272da668aa1SThomas Huth class = qdict_get_try_str(error, "class");
273da668aa1SThomas Huth desc = qdict_get_try_str(error, "desc");
274da668aa1SThomas Huth
275da668aa1SThomas Huth g_assert_cmpstr(class, ==, "CommandNotFound");
276da668aa1SThomas Huth g_assert_cmpint(strlen(desc), >, 0);
277da668aa1SThomas Huth }
278da668aa1SThomas Huth
test_qga_info(gconstpointer fix)279da668aa1SThomas Huth static void test_qga_info(gconstpointer fix)
280da668aa1SThomas Huth {
281da668aa1SThomas Huth const TestFixture *fixture = fix;
282bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL;
283bb6960a1SMarc-André Lureau QDict *val;
284da668aa1SThomas Huth const gchar *version;
285da668aa1SThomas Huth
286da668aa1SThomas Huth ret = qmp_fd(fixture->fd, "{'execute': 'guest-info'}");
287da668aa1SThomas Huth g_assert_nonnull(ret);
288da668aa1SThomas Huth qmp_assert_no_error(ret);
289da668aa1SThomas Huth
290da668aa1SThomas Huth val = qdict_get_qdict(ret, "return");
291da668aa1SThomas Huth version = qdict_get_try_str(val, "version");
292da668aa1SThomas Huth g_assert_cmpstr(version, ==, QEMU_VERSION);
293da668aa1SThomas Huth }
294da668aa1SThomas Huth
test_qga_get_vcpus(gconstpointer fix)295da668aa1SThomas Huth static void test_qga_get_vcpus(gconstpointer fix)
296da668aa1SThomas Huth {
297da668aa1SThomas Huth const TestFixture *fixture = fix;
298bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL;
299da668aa1SThomas Huth QList *list;
300da668aa1SThomas Huth const QListEntry *entry;
301da668aa1SThomas Huth
302da668aa1SThomas Huth ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-vcpus'}");
303da668aa1SThomas Huth g_assert_nonnull(ret);
304da668aa1SThomas Huth qmp_assert_no_error(ret);
305da668aa1SThomas Huth
306da668aa1SThomas Huth /* check there is at least a cpu */
307da668aa1SThomas Huth list = qdict_get_qlist(ret, "return");
308da668aa1SThomas Huth entry = qlist_first(list);
309da668aa1SThomas Huth g_assert(qdict_haskey(qobject_to(QDict, entry->value), "online"));
310da668aa1SThomas Huth g_assert(qdict_haskey(qobject_to(QDict, entry->value), "logical-id"));
311da668aa1SThomas Huth }
312da668aa1SThomas Huth
test_qga_get_fsinfo(gconstpointer fix)313da668aa1SThomas Huth static void test_qga_get_fsinfo(gconstpointer fix)
314da668aa1SThomas Huth {
315da668aa1SThomas Huth const TestFixture *fixture = fix;
316bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL;
317da668aa1SThomas Huth QList *list;
318da668aa1SThomas Huth const QListEntry *entry;
319da668aa1SThomas Huth
320da668aa1SThomas Huth ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-fsinfo'}");
321da668aa1SThomas Huth g_assert_nonnull(ret);
322da668aa1SThomas Huth qmp_assert_no_error(ret);
323da668aa1SThomas Huth
324da668aa1SThomas Huth /* sanity-check the response if there are any filesystems */
325da668aa1SThomas Huth list = qdict_get_qlist(ret, "return");
326da668aa1SThomas Huth entry = qlist_first(list);
327da668aa1SThomas Huth if (entry) {
328da668aa1SThomas Huth g_assert(qdict_haskey(qobject_to(QDict, entry->value), "name"));
329da668aa1SThomas Huth g_assert(qdict_haskey(qobject_to(QDict, entry->value), "mountpoint"));
330da668aa1SThomas Huth g_assert(qdict_haskey(qobject_to(QDict, entry->value), "type"));
331da668aa1SThomas Huth g_assert(qdict_haskey(qobject_to(QDict, entry->value), "disk"));
332da668aa1SThomas Huth }
333da668aa1SThomas Huth }
334da668aa1SThomas Huth
test_qga_get_memory_block_info(gconstpointer fix)335da668aa1SThomas Huth static void test_qga_get_memory_block_info(gconstpointer fix)
336da668aa1SThomas Huth {
337da668aa1SThomas Huth const TestFixture *fixture = fix;
338bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL;
339bb6960a1SMarc-André Lureau QDict *val;
340da668aa1SThomas Huth int64_t size;
341da668aa1SThomas Huth
342da668aa1SThomas Huth ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-memory-block-info'}");
343da668aa1SThomas Huth g_assert_nonnull(ret);
344da668aa1SThomas Huth
345da668aa1SThomas Huth /* some systems might not expose memory block info in sysfs */
346da668aa1SThomas Huth if (!qdict_haskey(ret, "error")) {
347da668aa1SThomas Huth /* check there is at least some memory */
348da668aa1SThomas Huth val = qdict_get_qdict(ret, "return");
349da668aa1SThomas Huth size = qdict_get_int(val, "size");
350da668aa1SThomas Huth g_assert_cmpint(size, >, 0);
351da668aa1SThomas Huth }
352da668aa1SThomas Huth }
353da668aa1SThomas Huth
test_qga_get_memory_blocks(gconstpointer fix)354da668aa1SThomas Huth static void test_qga_get_memory_blocks(gconstpointer fix)
355da668aa1SThomas Huth {
356da668aa1SThomas Huth const TestFixture *fixture = fix;
357bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL;
358da668aa1SThomas Huth QList *list;
359da668aa1SThomas Huth const QListEntry *entry;
360da668aa1SThomas Huth
361da668aa1SThomas Huth ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-memory-blocks'}");
362da668aa1SThomas Huth g_assert_nonnull(ret);
363da668aa1SThomas Huth
364da668aa1SThomas Huth /* some systems might not expose memory block info in sysfs */
365da668aa1SThomas Huth if (!qdict_haskey(ret, "error")) {
366da668aa1SThomas Huth list = qdict_get_qlist(ret, "return");
367da668aa1SThomas Huth entry = qlist_first(list);
368da668aa1SThomas Huth /* newer versions of qga may return empty list without error */
369da668aa1SThomas Huth if (entry) {
370da668aa1SThomas Huth g_assert(qdict_haskey(qobject_to(QDict, entry->value),
371da668aa1SThomas Huth "phys-index"));
372da668aa1SThomas Huth g_assert(qdict_haskey(qobject_to(QDict, entry->value), "online"));
373da668aa1SThomas Huth }
374da668aa1SThomas Huth }
375da668aa1SThomas Huth }
376da668aa1SThomas Huth
test_qga_network_get_interfaces(gconstpointer fix)377da668aa1SThomas Huth static void test_qga_network_get_interfaces(gconstpointer fix)
378da668aa1SThomas Huth {
379da668aa1SThomas Huth const TestFixture *fixture = fix;
380bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL;
381da668aa1SThomas Huth QList *list;
382da668aa1SThomas Huth const QListEntry *entry;
383da668aa1SThomas Huth
384da668aa1SThomas Huth ret = qmp_fd(fixture->fd, "{'execute': 'guest-network-get-interfaces'}");
385da668aa1SThomas Huth g_assert_nonnull(ret);
386da668aa1SThomas Huth qmp_assert_no_error(ret);
387da668aa1SThomas Huth
388da668aa1SThomas Huth /* check there is at least an interface */
389da668aa1SThomas Huth list = qdict_get_qlist(ret, "return");
390da668aa1SThomas Huth entry = qlist_first(list);
391da668aa1SThomas Huth g_assert(qdict_haskey(qobject_to(QDict, entry->value), "name"));
392da668aa1SThomas Huth }
393da668aa1SThomas Huth
test_qga_file_ops(gconstpointer fix)394da668aa1SThomas Huth static void test_qga_file_ops(gconstpointer fix)
395da668aa1SThomas Huth {
396da668aa1SThomas Huth const TestFixture *fixture = fix;
397da668aa1SThomas Huth const unsigned char helloworld[] = "Hello World!\n";
398da668aa1SThomas Huth const char *b64;
399da668aa1SThomas Huth gchar *path, *enc;
400da668aa1SThomas Huth unsigned char *dec;
401da668aa1SThomas Huth QDict *ret, *val;
402da668aa1SThomas Huth int64_t id, eof;
403da668aa1SThomas Huth gsize count;
404da668aa1SThomas Huth FILE *f;
405da668aa1SThomas Huth char tmp[100];
406da668aa1SThomas Huth
407da668aa1SThomas Huth /* open */
408da668aa1SThomas Huth ret = qmp_fd(fixture->fd, "{'execute': 'guest-file-open',"
409da668aa1SThomas Huth " 'arguments': { 'path': 'foo', 'mode': 'w+' } }");
410da668aa1SThomas Huth g_assert_nonnull(ret);
411da668aa1SThomas Huth qmp_assert_no_error(ret);
412da668aa1SThomas Huth id = qdict_get_int(ret, "return");
413da668aa1SThomas Huth qobject_unref(ret);
414da668aa1SThomas Huth
415da668aa1SThomas Huth enc = g_base64_encode(helloworld, sizeof(helloworld));
416da668aa1SThomas Huth /* write */
417da668aa1SThomas Huth ret = qmp_fd(fixture->fd,
418da668aa1SThomas Huth "{'execute': 'guest-file-write',"
419da668aa1SThomas Huth " 'arguments': { 'handle': %" PRId64 ", 'buf-b64': %s } }",
420da668aa1SThomas Huth id, enc);
421da668aa1SThomas Huth g_assert_nonnull(ret);
422da668aa1SThomas Huth qmp_assert_no_error(ret);
423da668aa1SThomas Huth
424da668aa1SThomas Huth val = qdict_get_qdict(ret, "return");
425da668aa1SThomas Huth count = qdict_get_int(val, "count");
426da668aa1SThomas Huth eof = qdict_get_bool(val, "eof");
427da668aa1SThomas Huth g_assert_cmpint(count, ==, sizeof(helloworld));
428da668aa1SThomas Huth g_assert_cmpint(eof, ==, 0);
429da668aa1SThomas Huth qobject_unref(ret);
430da668aa1SThomas Huth
431da668aa1SThomas Huth /* flush */
432da668aa1SThomas Huth ret = qmp_fd(fixture->fd,
433da668aa1SThomas Huth "{'execute': 'guest-file-flush',"
434da668aa1SThomas Huth " 'arguments': {'handle': %" PRId64 "} }",
435da668aa1SThomas Huth id);
436da668aa1SThomas Huth qobject_unref(ret);
437da668aa1SThomas Huth
438da668aa1SThomas Huth /* close */
439da668aa1SThomas Huth ret = qmp_fd(fixture->fd,
440da668aa1SThomas Huth "{'execute': 'guest-file-close',"
441da668aa1SThomas Huth " 'arguments': {'handle': %" PRId64 "} }",
442da668aa1SThomas Huth id);
443da668aa1SThomas Huth qobject_unref(ret);
444da668aa1SThomas Huth
445da668aa1SThomas Huth /* check content */
446da668aa1SThomas Huth path = g_build_filename(fixture->test_dir, "foo", NULL);
447da668aa1SThomas Huth f = fopen(path, "r");
448da668aa1SThomas Huth g_free(path);
449da668aa1SThomas Huth g_assert_nonnull(f);
450da668aa1SThomas Huth count = fread(tmp, 1, sizeof(tmp), f);
451da668aa1SThomas Huth g_assert_cmpint(count, ==, sizeof(helloworld));
452da668aa1SThomas Huth tmp[count] = 0;
453da668aa1SThomas Huth g_assert_cmpstr(tmp, ==, (char *)helloworld);
454da668aa1SThomas Huth fclose(f);
455da668aa1SThomas Huth
456da668aa1SThomas Huth /* open */
457da668aa1SThomas Huth ret = qmp_fd(fixture->fd, "{'execute': 'guest-file-open',"
458da668aa1SThomas Huth " 'arguments': { 'path': 'foo', 'mode': 'r' } }");
459da668aa1SThomas Huth g_assert_nonnull(ret);
460da668aa1SThomas Huth qmp_assert_no_error(ret);
461da668aa1SThomas Huth id = qdict_get_int(ret, "return");
462da668aa1SThomas Huth qobject_unref(ret);
463da668aa1SThomas Huth
464da668aa1SThomas Huth /* read */
465da668aa1SThomas Huth ret = qmp_fd(fixture->fd,
466da668aa1SThomas Huth "{'execute': 'guest-file-read',"
467da668aa1SThomas Huth " 'arguments': { 'handle': %" PRId64 "} }",
468da668aa1SThomas Huth id);
469da668aa1SThomas Huth val = qdict_get_qdict(ret, "return");
470da668aa1SThomas Huth count = qdict_get_int(val, "count");
471da668aa1SThomas Huth eof = qdict_get_bool(val, "eof");
472da668aa1SThomas Huth b64 = qdict_get_str(val, "buf-b64");
473da668aa1SThomas Huth g_assert_cmpint(count, ==, sizeof(helloworld));
474da668aa1SThomas Huth g_assert(eof);
475da668aa1SThomas Huth g_assert_cmpstr(b64, ==, enc);
476da668aa1SThomas Huth
477da668aa1SThomas Huth qobject_unref(ret);
478da668aa1SThomas Huth g_free(enc);
479da668aa1SThomas Huth
480da668aa1SThomas Huth /* read eof */
481da668aa1SThomas Huth ret = qmp_fd(fixture->fd,
482da668aa1SThomas Huth "{'execute': 'guest-file-read',"
483da668aa1SThomas Huth " 'arguments': { 'handle': %" PRId64 "} }",
484da668aa1SThomas Huth id);
485da668aa1SThomas Huth val = qdict_get_qdict(ret, "return");
486da668aa1SThomas Huth count = qdict_get_int(val, "count");
487da668aa1SThomas Huth eof = qdict_get_bool(val, "eof");
488da668aa1SThomas Huth b64 = qdict_get_str(val, "buf-b64");
489da668aa1SThomas Huth g_assert_cmpint(count, ==, 0);
490da668aa1SThomas Huth g_assert(eof);
491da668aa1SThomas Huth g_assert_cmpstr(b64, ==, "");
492da668aa1SThomas Huth qobject_unref(ret);
493da668aa1SThomas Huth
494da668aa1SThomas Huth /* seek */
495da668aa1SThomas Huth ret = qmp_fd(fixture->fd,
496da668aa1SThomas Huth "{'execute': 'guest-file-seek',"
497da668aa1SThomas Huth " 'arguments': { 'handle': %" PRId64 ", "
498da668aa1SThomas Huth " 'offset': %d, 'whence': %s } }",
499da668aa1SThomas Huth id, 6, "set");
500da668aa1SThomas Huth qmp_assert_no_error(ret);
501da668aa1SThomas Huth val = qdict_get_qdict(ret, "return");
502da668aa1SThomas Huth count = qdict_get_int(val, "position");
503da668aa1SThomas Huth eof = qdict_get_bool(val, "eof");
504da668aa1SThomas Huth g_assert_cmpint(count, ==, 6);
505da668aa1SThomas Huth g_assert(!eof);
506da668aa1SThomas Huth qobject_unref(ret);
507da668aa1SThomas Huth
508da668aa1SThomas Huth /* partial read */
509da668aa1SThomas Huth ret = qmp_fd(fixture->fd,
510da668aa1SThomas Huth "{'execute': 'guest-file-read',"
511da668aa1SThomas Huth " 'arguments': { 'handle': %" PRId64 "} }",
512da668aa1SThomas Huth id);
513da668aa1SThomas Huth val = qdict_get_qdict(ret, "return");
514da668aa1SThomas Huth count = qdict_get_int(val, "count");
515da668aa1SThomas Huth eof = qdict_get_bool(val, "eof");
516da668aa1SThomas Huth b64 = qdict_get_str(val, "buf-b64");
517da668aa1SThomas Huth g_assert_cmpint(count, ==, sizeof(helloworld) - 6);
518da668aa1SThomas Huth g_assert(eof);
519da668aa1SThomas Huth dec = g_base64_decode(b64, &count);
520da668aa1SThomas Huth g_assert_cmpint(count, ==, sizeof(helloworld) - 6);
521da668aa1SThomas Huth g_assert_cmpmem(dec, count, helloworld + 6, sizeof(helloworld) - 6);
522da668aa1SThomas Huth g_free(dec);
523da668aa1SThomas Huth
524da668aa1SThomas Huth qobject_unref(ret);
525da668aa1SThomas Huth
526da668aa1SThomas Huth /* close */
527da668aa1SThomas Huth ret = qmp_fd(fixture->fd,
528da668aa1SThomas Huth "{'execute': 'guest-file-close',"
529da668aa1SThomas Huth " 'arguments': {'handle': %" PRId64 "} }",
530da668aa1SThomas Huth id);
531da668aa1SThomas Huth qobject_unref(ret);
532da668aa1SThomas Huth }
533da668aa1SThomas Huth
test_qga_file_write_read(gconstpointer fix)534da668aa1SThomas Huth static void test_qga_file_write_read(gconstpointer fix)
535da668aa1SThomas Huth {
536da668aa1SThomas Huth const TestFixture *fixture = fix;
537da668aa1SThomas Huth const unsigned char helloworld[] = "Hello World!\n";
538da668aa1SThomas Huth const char *b64;
539da668aa1SThomas Huth gchar *enc;
540da668aa1SThomas Huth QDict *ret, *val;
541da668aa1SThomas Huth int64_t id, eof;
542da668aa1SThomas Huth gsize count;
543da668aa1SThomas Huth
544da668aa1SThomas Huth /* open */
545da668aa1SThomas Huth ret = qmp_fd(fixture->fd, "{'execute': 'guest-file-open',"
546da668aa1SThomas Huth " 'arguments': { 'path': 'foo', 'mode': 'w+' } }");
547da668aa1SThomas Huth g_assert_nonnull(ret);
548da668aa1SThomas Huth qmp_assert_no_error(ret);
549da668aa1SThomas Huth id = qdict_get_int(ret, "return");
550da668aa1SThomas Huth qobject_unref(ret);
551da668aa1SThomas Huth
552da668aa1SThomas Huth enc = g_base64_encode(helloworld, sizeof(helloworld));
553da668aa1SThomas Huth /* write */
554da668aa1SThomas Huth ret = qmp_fd(fixture->fd,
555da668aa1SThomas Huth "{'execute': 'guest-file-write',"
556da668aa1SThomas Huth " 'arguments': { 'handle': %" PRId64 ","
557da668aa1SThomas Huth " 'buf-b64': %s } }", id, enc);
558da668aa1SThomas Huth g_assert_nonnull(ret);
559da668aa1SThomas Huth qmp_assert_no_error(ret);
560da668aa1SThomas Huth
561da668aa1SThomas Huth val = qdict_get_qdict(ret, "return");
562da668aa1SThomas Huth count = qdict_get_int(val, "count");
563da668aa1SThomas Huth eof = qdict_get_bool(val, "eof");
564da668aa1SThomas Huth g_assert_cmpint(count, ==, sizeof(helloworld));
565da668aa1SThomas Huth g_assert_cmpint(eof, ==, 0);
566da668aa1SThomas Huth qobject_unref(ret);
567da668aa1SThomas Huth
568da668aa1SThomas Huth /* read (check implicit flush) */
569da668aa1SThomas Huth ret = qmp_fd(fixture->fd,
570da668aa1SThomas Huth "{'execute': 'guest-file-read',"
571da668aa1SThomas Huth " 'arguments': { 'handle': %" PRId64 "} }",
572da668aa1SThomas Huth id);
573da668aa1SThomas Huth val = qdict_get_qdict(ret, "return");
574da668aa1SThomas Huth count = qdict_get_int(val, "count");
575da668aa1SThomas Huth eof = qdict_get_bool(val, "eof");
576da668aa1SThomas Huth b64 = qdict_get_str(val, "buf-b64");
577da668aa1SThomas Huth g_assert_cmpint(count, ==, 0);
578da668aa1SThomas Huth g_assert(eof);
579da668aa1SThomas Huth g_assert_cmpstr(b64, ==, "");
580da668aa1SThomas Huth qobject_unref(ret);
581da668aa1SThomas Huth
582da668aa1SThomas Huth /* seek to 0 */
583da668aa1SThomas Huth ret = qmp_fd(fixture->fd,
584da668aa1SThomas Huth "{'execute': 'guest-file-seek',"
585da668aa1SThomas Huth " 'arguments': { 'handle': %" PRId64 ", "
586da668aa1SThomas Huth " 'offset': %d, 'whence': %s } }",
587da668aa1SThomas Huth id, 0, "set");
588da668aa1SThomas Huth qmp_assert_no_error(ret);
589da668aa1SThomas Huth val = qdict_get_qdict(ret, "return");
590da668aa1SThomas Huth count = qdict_get_int(val, "position");
591da668aa1SThomas Huth eof = qdict_get_bool(val, "eof");
592da668aa1SThomas Huth g_assert_cmpint(count, ==, 0);
593da668aa1SThomas Huth g_assert(!eof);
594da668aa1SThomas Huth qobject_unref(ret);
595da668aa1SThomas Huth
596da668aa1SThomas Huth /* read */
597da668aa1SThomas Huth ret = qmp_fd(fixture->fd,
598da668aa1SThomas Huth "{'execute': 'guest-file-read',"
599da668aa1SThomas Huth " 'arguments': { 'handle': %" PRId64 "} }",
600da668aa1SThomas Huth id);
601da668aa1SThomas Huth val = qdict_get_qdict(ret, "return");
602da668aa1SThomas Huth count = qdict_get_int(val, "count");
603da668aa1SThomas Huth eof = qdict_get_bool(val, "eof");
604da668aa1SThomas Huth b64 = qdict_get_str(val, "buf-b64");
605da668aa1SThomas Huth g_assert_cmpint(count, ==, sizeof(helloworld));
606da668aa1SThomas Huth g_assert(eof);
607da668aa1SThomas Huth g_assert_cmpstr(b64, ==, enc);
608da668aa1SThomas Huth qobject_unref(ret);
609da668aa1SThomas Huth g_free(enc);
610da668aa1SThomas Huth
611da668aa1SThomas Huth /* close */
612da668aa1SThomas Huth ret = qmp_fd(fixture->fd,
613da668aa1SThomas Huth "{'execute': 'guest-file-close',"
614da668aa1SThomas Huth " 'arguments': {'handle': %" PRId64 "} }",
615da668aa1SThomas Huth id);
616da668aa1SThomas Huth qobject_unref(ret);
617da668aa1SThomas Huth }
618da668aa1SThomas Huth
test_qga_get_time(gconstpointer fix)619da668aa1SThomas Huth static void test_qga_get_time(gconstpointer fix)
620da668aa1SThomas Huth {
621da668aa1SThomas Huth const TestFixture *fixture = fix;
622bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL;
623da668aa1SThomas Huth int64_t time;
624da668aa1SThomas Huth
625da668aa1SThomas Huth ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-time'}");
626da668aa1SThomas Huth g_assert_nonnull(ret);
627da668aa1SThomas Huth qmp_assert_no_error(ret);
628da668aa1SThomas Huth
629da668aa1SThomas Huth time = qdict_get_int(ret, "return");
630da668aa1SThomas Huth g_assert_cmpint(time, >, 0);
631da668aa1SThomas Huth }
632da668aa1SThomas Huth
test_qga_blockedrpcs(gconstpointer data)633ebf70554SThomas Huth static void test_qga_blockedrpcs(gconstpointer data)
634da668aa1SThomas Huth {
635da668aa1SThomas Huth TestFixture fix;
636da668aa1SThomas Huth QDict *ret, *error;
637da668aa1SThomas Huth const gchar *class, *desc;
638da668aa1SThomas Huth
639da668aa1SThomas Huth fixture_setup(&fix, "-b guest-ping,guest-get-time", NULL);
640da668aa1SThomas Huth
641ebf70554SThomas Huth /* check blocked RPCs */
642da668aa1SThomas Huth ret = qmp_fd(fix.fd, "{'execute': 'guest-ping'}");
643da668aa1SThomas Huth g_assert_nonnull(ret);
644da668aa1SThomas Huth error = qdict_get_qdict(ret, "error");
645da668aa1SThomas Huth class = qdict_get_try_str(error, "class");
646da668aa1SThomas Huth desc = qdict_get_try_str(error, "desc");
647da668aa1SThomas Huth g_assert_cmpstr(class, ==, "CommandNotFound");
648da668aa1SThomas Huth g_assert_nonnull(g_strstr_len(desc, -1, "has been disabled"));
649da668aa1SThomas Huth qobject_unref(ret);
650da668aa1SThomas Huth
651da668aa1SThomas Huth ret = qmp_fd(fix.fd, "{'execute': 'guest-get-time'}");
652da668aa1SThomas Huth g_assert_nonnull(ret);
653da668aa1SThomas Huth error = qdict_get_qdict(ret, "error");
654da668aa1SThomas Huth class = qdict_get_try_str(error, "class");
655da668aa1SThomas Huth desc = qdict_get_try_str(error, "desc");
656da668aa1SThomas Huth g_assert_cmpstr(class, ==, "CommandNotFound");
657da668aa1SThomas Huth g_assert_nonnull(g_strstr_len(desc, -1, "has been disabled"));
658da668aa1SThomas Huth qobject_unref(ret);
659da668aa1SThomas Huth
660da668aa1SThomas Huth /* check something work */
661da668aa1SThomas Huth ret = qmp_fd(fix.fd, "{'execute': 'guest-get-fsinfo'}");
662da668aa1SThomas Huth qmp_assert_no_error(ret);
663da668aa1SThomas Huth qobject_unref(ret);
664da668aa1SThomas Huth
665da668aa1SThomas Huth fixture_tear_down(&fix, NULL);
666da668aa1SThomas Huth }
667da668aa1SThomas Huth
test_qga_allowedrpcs(gconstpointer data)668fcd1ab3aSKonstantin Kostiuk static void test_qga_allowedrpcs(gconstpointer data)
669fcd1ab3aSKonstantin Kostiuk {
670fcd1ab3aSKonstantin Kostiuk TestFixture fix;
671fcd1ab3aSKonstantin Kostiuk QDict *ret, *error;
672fcd1ab3aSKonstantin Kostiuk const gchar *class, *desc;
673fcd1ab3aSKonstantin Kostiuk
674fcd1ab3aSKonstantin Kostiuk fixture_setup(&fix, "-a guest-ping,guest-get-time", NULL);
675fcd1ab3aSKonstantin Kostiuk
676fcd1ab3aSKonstantin Kostiuk /* check allowed RPCs */
677fcd1ab3aSKonstantin Kostiuk ret = qmp_fd(fix.fd, "{'execute': 'guest-ping'}");
678fcd1ab3aSKonstantin Kostiuk qmp_assert_no_error(ret);
679fcd1ab3aSKonstantin Kostiuk qobject_unref(ret);
680fcd1ab3aSKonstantin Kostiuk
681fcd1ab3aSKonstantin Kostiuk ret = qmp_fd(fix.fd, "{'execute': 'guest-get-time'}");
682fcd1ab3aSKonstantin Kostiuk qmp_assert_no_error(ret);
683fcd1ab3aSKonstantin Kostiuk qobject_unref(ret);
684fcd1ab3aSKonstantin Kostiuk
685fcd1ab3aSKonstantin Kostiuk /* check something else */
686fcd1ab3aSKonstantin Kostiuk ret = qmp_fd(fix.fd, "{'execute': 'guest-get-fsinfo'}");
687fcd1ab3aSKonstantin Kostiuk g_assert_nonnull(ret);
688fcd1ab3aSKonstantin Kostiuk error = qdict_get_qdict(ret, "error");
689fcd1ab3aSKonstantin Kostiuk class = qdict_get_try_str(error, "class");
690fcd1ab3aSKonstantin Kostiuk desc = qdict_get_try_str(error, "desc");
691fcd1ab3aSKonstantin Kostiuk g_assert_cmpstr(class, ==, "CommandNotFound");
692fcd1ab3aSKonstantin Kostiuk g_assert_nonnull(g_strstr_len(desc, -1, "has been disabled"));
693fcd1ab3aSKonstantin Kostiuk qobject_unref(ret);
694fcd1ab3aSKonstantin Kostiuk
695fcd1ab3aSKonstantin Kostiuk fixture_tear_down(&fix, NULL);
696fcd1ab3aSKonstantin Kostiuk }
697fcd1ab3aSKonstantin Kostiuk
test_qga_config(gconstpointer data)698da668aa1SThomas Huth static void test_qga_config(gconstpointer data)
699da668aa1SThomas Huth {
700da668aa1SThomas Huth GError *error = NULL;
701bb6960a1SMarc-André Lureau g_autofree char *out = NULL;
702bb6960a1SMarc-André Lureau g_autofree char *err = NULL;
703bb6960a1SMarc-André Lureau g_autofree char *cwd = NULL;
704bb6960a1SMarc-André Lureau g_autofree char *cmd = NULL;
705bb6960a1SMarc-André Lureau g_auto(GStrv) argv = NULL;
706bb6960a1SMarc-André Lureau g_auto(GStrv) strv = NULL;
707bb6960a1SMarc-André Lureau g_autoptr(GKeyFile) kf = NULL;
708bb6960a1SMarc-André Lureau char *str;
709da668aa1SThomas Huth char *env[2];
710da668aa1SThomas Huth int status;
711da668aa1SThomas Huth gsize n;
712da668aa1SThomas Huth
713da668aa1SThomas Huth cwd = g_get_current_dir();
714da668aa1SThomas Huth cmd = g_strdup_printf("%s%cqga%cqemu-ga -D",
715da668aa1SThomas Huth cwd, G_DIR_SEPARATOR, G_DIR_SEPARATOR);
716da668aa1SThomas Huth g_shell_parse_argv(cmd, NULL, &argv, &error);
717da668aa1SThomas Huth g_assert_no_error(error);
718da668aa1SThomas Huth
719da668aa1SThomas Huth env[0] = g_strdup_printf("QGA_CONF=tests%cdata%ctest-qga-config",
720da668aa1SThomas Huth G_DIR_SEPARATOR, G_DIR_SEPARATOR);
721da668aa1SThomas Huth env[1] = NULL;
722da668aa1SThomas Huth g_spawn_sync(NULL, argv, env, 0,
723da668aa1SThomas Huth NULL, NULL, &out, &err, &status, &error);
724da668aa1SThomas Huth
725da668aa1SThomas Huth g_assert_no_error(error);
726da668aa1SThomas Huth g_assert_cmpstr(err, ==, "");
727da668aa1SThomas Huth g_assert_cmpint(status, ==, 0);
728da668aa1SThomas Huth
729da668aa1SThomas Huth kf = g_key_file_new();
730da668aa1SThomas Huth g_key_file_load_from_data(kf, out, -1, G_KEY_FILE_NONE, &error);
731da668aa1SThomas Huth g_assert_no_error(error);
732da668aa1SThomas Huth
733da668aa1SThomas Huth str = g_key_file_get_start_group(kf);
734da668aa1SThomas Huth g_assert_cmpstr(str, ==, "general");
735da668aa1SThomas Huth g_free(str);
736da668aa1SThomas Huth
737da668aa1SThomas Huth g_assert_false(g_key_file_get_boolean(kf, "general", "daemon", &error));
738da668aa1SThomas Huth g_assert_no_error(error);
739da668aa1SThomas Huth
740da668aa1SThomas Huth str = g_key_file_get_string(kf, "general", "method", &error);
741da668aa1SThomas Huth g_assert_no_error(error);
742da668aa1SThomas Huth g_assert_cmpstr(str, ==, "virtio-serial");
743da668aa1SThomas Huth g_free(str);
744da668aa1SThomas Huth
745da668aa1SThomas Huth str = g_key_file_get_string(kf, "general", "path", &error);
746da668aa1SThomas Huth g_assert_no_error(error);
747da668aa1SThomas Huth g_assert_cmpstr(str, ==, "/path/to/org.qemu.guest_agent.0");
748da668aa1SThomas Huth g_free(str);
749da668aa1SThomas Huth
750da668aa1SThomas Huth str = g_key_file_get_string(kf, "general", "pidfile", &error);
751da668aa1SThomas Huth g_assert_no_error(error);
752da668aa1SThomas Huth g_assert_cmpstr(str, ==, "/var/foo/qemu-ga.pid");
753da668aa1SThomas Huth g_free(str);
754da668aa1SThomas Huth
755da668aa1SThomas Huth str = g_key_file_get_string(kf, "general", "statedir", &error);
756da668aa1SThomas Huth g_assert_no_error(error);
757da668aa1SThomas Huth g_assert_cmpstr(str, ==, "/var/state");
758da668aa1SThomas Huth g_free(str);
759da668aa1SThomas Huth
760da668aa1SThomas Huth g_assert_true(g_key_file_get_boolean(kf, "general", "verbose", &error));
761da668aa1SThomas Huth g_assert_no_error(error);
762da668aa1SThomas Huth
763582a098eSThomas Huth strv = g_key_file_get_string_list(kf, "general", "block-rpcs", &n, &error);
764da668aa1SThomas Huth g_assert_cmpint(n, ==, 2);
765da668aa1SThomas Huth g_assert_true(g_strv_contains((const char * const *)strv,
766da668aa1SThomas Huth "guest-ping"));
767da668aa1SThomas Huth g_assert_true(g_strv_contains((const char * const *)strv,
768da668aa1SThomas Huth "guest-get-time"));
769da668aa1SThomas Huth g_assert_no_error(error);
770da668aa1SThomas Huth
771da668aa1SThomas Huth g_free(env[0]);
772da668aa1SThomas Huth }
773da668aa1SThomas Huth
test_qga_fsfreeze_status(gconstpointer fix)774da668aa1SThomas Huth static void test_qga_fsfreeze_status(gconstpointer fix)
775da668aa1SThomas Huth {
776da668aa1SThomas Huth const TestFixture *fixture = fix;
777bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL;
778da668aa1SThomas Huth const gchar *status;
779da668aa1SThomas Huth
780da668aa1SThomas Huth ret = qmp_fd(fixture->fd, "{'execute': 'guest-fsfreeze-status'}");
781da668aa1SThomas Huth g_assert_nonnull(ret);
782da668aa1SThomas Huth qmp_assert_no_error(ret);
783da668aa1SThomas Huth
784da668aa1SThomas Huth status = qdict_get_try_str(ret, "return");
785da668aa1SThomas Huth g_assert_cmpstr(status, ==, "thawed");
786da668aa1SThomas Huth }
787da668aa1SThomas Huth
wait_for_guest_exec_completion(int fd,int64_t pid)788c7d74f27SDaniel Xu static QDict *wait_for_guest_exec_completion(int fd, int64_t pid)
789da668aa1SThomas Huth {
790c7d74f27SDaniel Xu QDict *ret = NULL;
791c7d74f27SDaniel Xu int64_t now;
792da668aa1SThomas Huth bool exited;
793c7d74f27SDaniel Xu QDict *val;
794da668aa1SThomas Huth
795da668aa1SThomas Huth now = g_get_monotonic_time();
796da668aa1SThomas Huth do {
797c7d74f27SDaniel Xu ret = qmp_fd(fd,
798da668aa1SThomas Huth "{'execute': 'guest-exec-status',"
799da668aa1SThomas Huth " 'arguments': { 'pid': %" PRId64 " } }", pid);
800da668aa1SThomas Huth g_assert_nonnull(ret);
801da668aa1SThomas Huth val = qdict_get_qdict(ret, "return");
802da668aa1SThomas Huth exited = qdict_get_bool(val, "exited");
803da668aa1SThomas Huth if (!exited) {
804da668aa1SThomas Huth qobject_unref(ret);
805da668aa1SThomas Huth }
806da668aa1SThomas Huth } while (!exited &&
807da668aa1SThomas Huth g_get_monotonic_time() < now + 5 * G_TIME_SPAN_SECOND);
808da668aa1SThomas Huth g_assert(exited);
809da668aa1SThomas Huth
810c7d74f27SDaniel Xu return ret;
811c7d74f27SDaniel Xu }
812c7d74f27SDaniel Xu
test_qga_guest_exec(gconstpointer fix)813c7d74f27SDaniel Xu static void test_qga_guest_exec(gconstpointer fix)
814c7d74f27SDaniel Xu {
815c7d74f27SDaniel Xu const TestFixture *fixture = fix;
816c7d74f27SDaniel Xu g_autoptr(QDict) ret = NULL;
817c7d74f27SDaniel Xu QDict *val;
818c7d74f27SDaniel Xu const gchar *out;
819c7d74f27SDaniel Xu g_autofree guchar *decoded = NULL;
820c7d74f27SDaniel Xu int64_t pid, exitcode;
821c7d74f27SDaniel Xu gsize len;
822c7d74f27SDaniel Xu
823c7d74f27SDaniel Xu /* exec 'echo foo bar' */
824c7d74f27SDaniel Xu ret = qmp_fd(fixture->fd, "{'execute': 'guest-exec', 'arguments': {"
825*8c72e19bSSamuel Tardieu " 'path': 'echo', 'arg': [ '-n', '\" test_str \"' ],"
826c7d74f27SDaniel Xu " 'capture-output': true } }");
827c7d74f27SDaniel Xu g_assert_nonnull(ret);
828c7d74f27SDaniel Xu qmp_assert_no_error(ret);
829c7d74f27SDaniel Xu val = qdict_get_qdict(ret, "return");
830c7d74f27SDaniel Xu pid = qdict_get_int(val, "pid");
831c7d74f27SDaniel Xu g_assert_cmpint(pid, >, 0);
832c7d74f27SDaniel Xu qobject_unref(ret);
833c7d74f27SDaniel Xu
834c7d74f27SDaniel Xu ret = wait_for_guest_exec_completion(fixture->fd, pid);
835c7d74f27SDaniel Xu
836da668aa1SThomas Huth /* check stdout */
837c7d74f27SDaniel Xu val = qdict_get_qdict(ret, "return");
838da668aa1SThomas Huth exitcode = qdict_get_int(val, "exitcode");
839da668aa1SThomas Huth g_assert_cmpint(exitcode, ==, 0);
840da668aa1SThomas Huth out = qdict_get_str(val, "out-data");
841da668aa1SThomas Huth decoded = g_base64_decode(out, &len);
842da668aa1SThomas Huth g_assert_cmpint(len, ==, 12);
843da668aa1SThomas Huth g_assert_cmpstr((char *)decoded, ==, "\" test_str \"");
844da668aa1SThomas Huth }
845da668aa1SThomas Huth
846c7d74f27SDaniel Xu #if defined(G_OS_WIN32)
test_qga_guest_exec_separated(gconstpointer fix)847c7d74f27SDaniel Xu static void test_qga_guest_exec_separated(gconstpointer fix)
848c7d74f27SDaniel Xu {
849c7d74f27SDaniel Xu }
test_qga_guest_exec_merged(gconstpointer fix)850c7d74f27SDaniel Xu static void test_qga_guest_exec_merged(gconstpointer fix)
851c7d74f27SDaniel Xu {
852c7d74f27SDaniel Xu const TestFixture *fixture = fix;
853c7d74f27SDaniel Xu g_autoptr(QDict) ret = NULL;
854c7d74f27SDaniel Xu QDict *val;
855c7d74f27SDaniel Xu const gchar *class, *desc;
856c7d74f27SDaniel Xu g_autofree guchar *decoded = NULL;
857c7d74f27SDaniel Xu
858c7d74f27SDaniel Xu /* exec 'echo foo bar' */
859c7d74f27SDaniel Xu ret = qmp_fd(fixture->fd, "{'execute': 'guest-exec', 'arguments': {"
860c7d74f27SDaniel Xu " 'path': 'echo',"
861c7d74f27SDaniel Xu " 'arg': [ 'execution never reaches here' ],"
862c7d74f27SDaniel Xu " 'capture-output': 'merged' } }");
863c7d74f27SDaniel Xu
864c7d74f27SDaniel Xu g_assert_nonnull(ret);
865c7d74f27SDaniel Xu val = qdict_get_qdict(ret, "error");
866c7d74f27SDaniel Xu g_assert_nonnull(val);
867c7d74f27SDaniel Xu class = qdict_get_str(val, "class");
868c7d74f27SDaniel Xu desc = qdict_get_str(val, "desc");
869c7d74f27SDaniel Xu g_assert_cmpstr(class, ==, "GenericError");
870c7d74f27SDaniel Xu g_assert_cmpint(strlen(desc), >, 0);
871c7d74f27SDaniel Xu }
872c7d74f27SDaniel Xu #else
test_qga_guest_exec_separated(gconstpointer fix)873c7d74f27SDaniel Xu static void test_qga_guest_exec_separated(gconstpointer fix)
874c7d74f27SDaniel Xu {
875c7d74f27SDaniel Xu const TestFixture *fixture = fix;
876c7d74f27SDaniel Xu g_autoptr(QDict) ret = NULL;
877c7d74f27SDaniel Xu QDict *val;
878c7d74f27SDaniel Xu const gchar *out, *err;
879c7d74f27SDaniel Xu g_autofree guchar *out_decoded = NULL;
880c7d74f27SDaniel Xu g_autofree guchar *err_decoded = NULL;
881c7d74f27SDaniel Xu int64_t pid, exitcode;
882c7d74f27SDaniel Xu gsize len;
883c7d74f27SDaniel Xu
884c7d74f27SDaniel Xu /* exec 'echo foo bar' */
885c7d74f27SDaniel Xu ret = qmp_fd(fixture->fd, "{'execute': 'guest-exec', 'arguments': {"
886*8c72e19bSSamuel Tardieu " 'path': 'bash',"
887c7d74f27SDaniel Xu " 'arg': [ '-c', 'for i in $(seq 4); do if (( $i %% 2 )); then echo stdout; else echo stderr 1>&2; fi; done;' ],"
888c7d74f27SDaniel Xu " 'capture-output': 'separated' } }");
889c7d74f27SDaniel Xu g_assert_nonnull(ret);
890c7d74f27SDaniel Xu qmp_assert_no_error(ret);
891c7d74f27SDaniel Xu val = qdict_get_qdict(ret, "return");
892c7d74f27SDaniel Xu pid = qdict_get_int(val, "pid");
893c7d74f27SDaniel Xu g_assert_cmpint(pid, >, 0);
894c7d74f27SDaniel Xu qobject_unref(ret);
895c7d74f27SDaniel Xu
896c7d74f27SDaniel Xu ret = wait_for_guest_exec_completion(fixture->fd, pid);
897c7d74f27SDaniel Xu
898c7d74f27SDaniel Xu val = qdict_get_qdict(ret, "return");
899c7d74f27SDaniel Xu exitcode = qdict_get_int(val, "exitcode");
900c7d74f27SDaniel Xu g_assert_cmpint(exitcode, ==, 0);
901c7d74f27SDaniel Xu
902c7d74f27SDaniel Xu /* check stdout */
903c7d74f27SDaniel Xu out = qdict_get_str(val, "out-data");
904c7d74f27SDaniel Xu out_decoded = g_base64_decode(out, &len);
905c7d74f27SDaniel Xu g_assert_cmpint(len, ==, 14);
906c7d74f27SDaniel Xu g_assert_cmpstr((char *)out_decoded, ==, "stdout\nstdout\n");
907c7d74f27SDaniel Xu
908c7d74f27SDaniel Xu /* check stderr */
909c7d74f27SDaniel Xu err = qdict_get_try_str(val, "err-data");
910c7d74f27SDaniel Xu err_decoded = g_base64_decode(err, &len);
911c7d74f27SDaniel Xu g_assert_cmpint(len, ==, 14);
912c7d74f27SDaniel Xu g_assert_cmpstr((char *)err_decoded, ==, "stderr\nstderr\n");
913c7d74f27SDaniel Xu }
914c7d74f27SDaniel Xu
test_qga_guest_exec_merged(gconstpointer fix)915c7d74f27SDaniel Xu static void test_qga_guest_exec_merged(gconstpointer fix)
916c7d74f27SDaniel Xu {
917c7d74f27SDaniel Xu const TestFixture *fixture = fix;
918c7d74f27SDaniel Xu g_autoptr(QDict) ret = NULL;
919c7d74f27SDaniel Xu QDict *val;
920c7d74f27SDaniel Xu const gchar *out, *err;
921c7d74f27SDaniel Xu g_autofree guchar *decoded = NULL;
922c7d74f27SDaniel Xu int64_t pid, exitcode;
923c7d74f27SDaniel Xu gsize len;
924c7d74f27SDaniel Xu
925c7d74f27SDaniel Xu /* exec 'echo foo bar' */
926c7d74f27SDaniel Xu ret = qmp_fd(fixture->fd, "{'execute': 'guest-exec', 'arguments': {"
927*8c72e19bSSamuel Tardieu " 'path': 'bash',"
928c7d74f27SDaniel Xu " 'arg': [ '-c', 'for i in $(seq 4); do if (( $i %% 2 )); then echo stdout; else echo stderr 1>&2; fi; done;' ],"
929c7d74f27SDaniel Xu " 'capture-output': 'merged' } }");
930c7d74f27SDaniel Xu g_assert_nonnull(ret);
931c7d74f27SDaniel Xu qmp_assert_no_error(ret);
932c7d74f27SDaniel Xu val = qdict_get_qdict(ret, "return");
933c7d74f27SDaniel Xu pid = qdict_get_int(val, "pid");
934c7d74f27SDaniel Xu g_assert_cmpint(pid, >, 0);
935c7d74f27SDaniel Xu qobject_unref(ret);
936c7d74f27SDaniel Xu
937c7d74f27SDaniel Xu ret = wait_for_guest_exec_completion(fixture->fd, pid);
938c7d74f27SDaniel Xu
939c7d74f27SDaniel Xu val = qdict_get_qdict(ret, "return");
940c7d74f27SDaniel Xu exitcode = qdict_get_int(val, "exitcode");
941c7d74f27SDaniel Xu g_assert_cmpint(exitcode, ==, 0);
942c7d74f27SDaniel Xu
943c7d74f27SDaniel Xu /* check stdout */
944c7d74f27SDaniel Xu out = qdict_get_str(val, "out-data");
945c7d74f27SDaniel Xu decoded = g_base64_decode(out, &len);
946c7d74f27SDaniel Xu g_assert_cmpint(len, ==, 28);
947c7d74f27SDaniel Xu g_assert_cmpstr((char *)decoded, ==, "stdout\nstderr\nstdout\nstderr\n");
948c7d74f27SDaniel Xu
949c7d74f27SDaniel Xu /* check stderr */
950c7d74f27SDaniel Xu err = qdict_get_try_str(val, "err-data");
951c7d74f27SDaniel Xu g_assert_null(err);
952c7d74f27SDaniel Xu }
953c7d74f27SDaniel Xu #endif
954c7d74f27SDaniel Xu
test_qga_guest_exec_invalid(gconstpointer fix)955da668aa1SThomas Huth static void test_qga_guest_exec_invalid(gconstpointer fix)
956da668aa1SThomas Huth {
957da668aa1SThomas Huth const TestFixture *fixture = fix;
958bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL;
959bb6960a1SMarc-André Lureau QDict *error;
960da668aa1SThomas Huth const gchar *class, *desc;
961da668aa1SThomas Huth
962da668aa1SThomas Huth /* invalid command */
963da668aa1SThomas Huth ret = qmp_fd(fixture->fd, "{'execute': 'guest-exec', 'arguments': {"
964da668aa1SThomas Huth " 'path': '/bin/invalid-cmd42' } }");
965da668aa1SThomas Huth g_assert_nonnull(ret);
966da668aa1SThomas Huth error = qdict_get_qdict(ret, "error");
967da668aa1SThomas Huth g_assert_nonnull(error);
968da668aa1SThomas Huth class = qdict_get_str(error, "class");
969da668aa1SThomas Huth desc = qdict_get_str(error, "desc");
970da668aa1SThomas Huth g_assert_cmpstr(class, ==, "GenericError");
971da668aa1SThomas Huth g_assert_cmpint(strlen(desc), >, 0);
972da668aa1SThomas Huth qobject_unref(ret);
973da668aa1SThomas Huth
974da668aa1SThomas Huth /* invalid pid */
975da668aa1SThomas Huth ret = qmp_fd(fixture->fd, "{'execute': 'guest-exec-status',"
976da668aa1SThomas Huth " 'arguments': { 'pid': 0 } }");
977da668aa1SThomas Huth g_assert_nonnull(ret);
978da668aa1SThomas Huth error = qdict_get_qdict(ret, "error");
979da668aa1SThomas Huth g_assert_nonnull(error);
980da668aa1SThomas Huth class = qdict_get_str(error, "class");
981da668aa1SThomas Huth desc = qdict_get_str(error, "desc");
982da668aa1SThomas Huth g_assert_cmpstr(class, ==, "GenericError");
983da668aa1SThomas Huth g_assert_cmpint(strlen(desc), >, 0);
984da668aa1SThomas Huth }
985da668aa1SThomas Huth
test_qga_guest_get_host_name(gconstpointer fix)986da668aa1SThomas Huth static void test_qga_guest_get_host_name(gconstpointer fix)
987da668aa1SThomas Huth {
988da668aa1SThomas Huth const TestFixture *fixture = fix;
989bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL;
990bb6960a1SMarc-André Lureau QDict *val;
991da668aa1SThomas Huth
992da668aa1SThomas Huth ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-host-name'}");
993da668aa1SThomas Huth g_assert_nonnull(ret);
994da668aa1SThomas Huth qmp_assert_no_error(ret);
995da668aa1SThomas Huth
996da668aa1SThomas Huth val = qdict_get_qdict(ret, "return");
997da668aa1SThomas Huth g_assert(qdict_haskey(val, "host-name"));
998da668aa1SThomas Huth }
999da668aa1SThomas Huth
test_qga_guest_get_timezone(gconstpointer fix)1000da668aa1SThomas Huth static void test_qga_guest_get_timezone(gconstpointer fix)
1001da668aa1SThomas Huth {
1002da668aa1SThomas Huth const TestFixture *fixture = fix;
1003bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL;
1004bb6960a1SMarc-André Lureau QDict *val;
1005da668aa1SThomas Huth
1006da668aa1SThomas Huth ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-timezone'}");
1007da668aa1SThomas Huth g_assert_nonnull(ret);
1008da668aa1SThomas Huth qmp_assert_no_error(ret);
1009da668aa1SThomas Huth
1010da668aa1SThomas Huth /* Make sure there's at least offset */
1011da668aa1SThomas Huth val = qdict_get_qdict(ret, "return");
1012da668aa1SThomas Huth g_assert(qdict_haskey(val, "offset"));
1013da668aa1SThomas Huth }
1014da668aa1SThomas Huth
test_qga_guest_get_users(gconstpointer fix)1015da668aa1SThomas Huth static void test_qga_guest_get_users(gconstpointer fix)
1016da668aa1SThomas Huth {
1017da668aa1SThomas Huth const TestFixture *fixture = fix;
1018bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL;
1019da668aa1SThomas Huth QList *val;
1020da668aa1SThomas Huth
1021da668aa1SThomas Huth ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-users'}");
1022da668aa1SThomas Huth g_assert_nonnull(ret);
1023da668aa1SThomas Huth qmp_assert_no_error(ret);
1024da668aa1SThomas Huth
1025da668aa1SThomas Huth /* There is not much to test here */
1026da668aa1SThomas Huth val = qdict_get_qlist(ret, "return");
1027da668aa1SThomas Huth g_assert_nonnull(val);
1028da668aa1SThomas Huth }
1029da668aa1SThomas Huth
test_qga_guest_get_osinfo(gconstpointer data)1030da668aa1SThomas Huth static void test_qga_guest_get_osinfo(gconstpointer data)
1031da668aa1SThomas Huth {
1032da668aa1SThomas Huth TestFixture fixture;
1033da668aa1SThomas Huth const gchar *str;
1034bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL;
1035a85d0926SMarc-André Lureau char *env[2];
1036a85d0926SMarc-André Lureau QDict *val;
1037da668aa1SThomas Huth
1038da668aa1SThomas Huth env[0] = g_strdup_printf(
1039a85d0926SMarc-André Lureau "QGA_OS_RELEASE=%s%c..%cdata%ctest-qga-os-release",
1040a85d0926SMarc-André Lureau g_test_get_dir(G_TEST_DIST), G_DIR_SEPARATOR, G_DIR_SEPARATOR, G_DIR_SEPARATOR);
1041da668aa1SThomas Huth env[1] = NULL;
1042da668aa1SThomas Huth fixture_setup(&fixture, NULL, env);
1043da668aa1SThomas Huth
1044da668aa1SThomas Huth ret = qmp_fd(fixture.fd, "{'execute': 'guest-get-osinfo'}");
1045da668aa1SThomas Huth g_assert_nonnull(ret);
1046da668aa1SThomas Huth qmp_assert_no_error(ret);
1047da668aa1SThomas Huth
1048da668aa1SThomas Huth val = qdict_get_qdict(ret, "return");
1049da668aa1SThomas Huth
1050da668aa1SThomas Huth str = qdict_get_try_str(val, "id");
1051da668aa1SThomas Huth g_assert_nonnull(str);
1052da668aa1SThomas Huth g_assert_cmpstr(str, ==, "qemu-ga-test");
1053da668aa1SThomas Huth
1054da668aa1SThomas Huth str = qdict_get_try_str(val, "name");
1055da668aa1SThomas Huth g_assert_nonnull(str);
1056da668aa1SThomas Huth g_assert_cmpstr(str, ==, "QEMU-GA");
1057da668aa1SThomas Huth
1058da668aa1SThomas Huth str = qdict_get_try_str(val, "pretty-name");
1059da668aa1SThomas Huth g_assert_nonnull(str);
1060da668aa1SThomas Huth g_assert_cmpstr(str, ==, "QEMU Guest Agent test");
1061da668aa1SThomas Huth
1062da668aa1SThomas Huth str = qdict_get_try_str(val, "version");
1063da668aa1SThomas Huth g_assert_nonnull(str);
1064da668aa1SThomas Huth g_assert_cmpstr(str, ==, "Test 1");
1065da668aa1SThomas Huth
1066da668aa1SThomas Huth str = qdict_get_try_str(val, "version-id");
1067da668aa1SThomas Huth g_assert_nonnull(str);
1068da668aa1SThomas Huth g_assert_cmpstr(str, ==, "1");
1069da668aa1SThomas Huth
1070da668aa1SThomas Huth str = qdict_get_try_str(val, "variant");
1071da668aa1SThomas Huth g_assert_nonnull(str);
1072da668aa1SThomas Huth g_assert_cmpstr(str, ==, "Unit test \"'$`\\ and \\\\ etc.");
1073da668aa1SThomas Huth
1074da668aa1SThomas Huth str = qdict_get_try_str(val, "variant-id");
1075da668aa1SThomas Huth g_assert_nonnull(str);
1076da668aa1SThomas Huth g_assert_cmpstr(str, ==, "unit-test");
1077da668aa1SThomas Huth
1078da668aa1SThomas Huth g_free(env[0]);
1079da668aa1SThomas Huth fixture_tear_down(&fixture, NULL);
1080da668aa1SThomas Huth }
1081da668aa1SThomas Huth
main(int argc,char ** argv)1082da668aa1SThomas Huth int main(int argc, char **argv)
1083da668aa1SThomas Huth {
1084da668aa1SThomas Huth TestFixture fix;
1085da668aa1SThomas Huth int ret;
1086da668aa1SThomas Huth
1087a7bd942cSMarc-André Lureau #ifdef QEMU_SANITIZE_THREAD
1088a7bd942cSMarc-André Lureau {
1089a7bd942cSMarc-André Lureau g_test_skip("tsan enabled, https://github.com/google/sanitizers/issues/1116");
1090a7bd942cSMarc-André Lureau return 0;
1091a7bd942cSMarc-André Lureau }
1092a7bd942cSMarc-André Lureau #endif
1093a7bd942cSMarc-André Lureau
1094da668aa1SThomas Huth setlocale (LC_ALL, "");
1095da668aa1SThomas Huth g_test_init(&argc, &argv, NULL);
1096da668aa1SThomas Huth fixture_setup(&fix, NULL, NULL);
1097da668aa1SThomas Huth
1098da668aa1SThomas Huth g_test_add_data_func("/qga/sync-delimited", &fix, test_qga_sync_delimited);
1099da668aa1SThomas Huth g_test_add_data_func("/qga/sync", &fix, test_qga_sync);
1100da668aa1SThomas Huth g_test_add_data_func("/qga/ping", &fix, test_qga_ping);
1101da668aa1SThomas Huth g_test_add_data_func("/qga/info", &fix, test_qga_info);
1102da668aa1SThomas Huth g_test_add_data_func("/qga/network-get-interfaces", &fix,
1103da668aa1SThomas Huth test_qga_network_get_interfaces);
1104da668aa1SThomas Huth if (!access("/sys/devices/system/cpu/cpu0", F_OK)) {
1105da668aa1SThomas Huth g_test_add_data_func("/qga/get-vcpus", &fix, test_qga_get_vcpus);
1106da668aa1SThomas Huth }
1107da668aa1SThomas Huth g_test_add_data_func("/qga/get-fsinfo", &fix, test_qga_get_fsinfo);
1108da668aa1SThomas Huth g_test_add_data_func("/qga/get-memory-block-info", &fix,
1109da668aa1SThomas Huth test_qga_get_memory_block_info);
1110da668aa1SThomas Huth g_test_add_data_func("/qga/get-memory-blocks", &fix,
1111da668aa1SThomas Huth test_qga_get_memory_blocks);
1112da668aa1SThomas Huth g_test_add_data_func("/qga/file-ops", &fix, test_qga_file_ops);
1113da668aa1SThomas Huth g_test_add_data_func("/qga/file-write-read", &fix, test_qga_file_write_read);
1114da668aa1SThomas Huth g_test_add_data_func("/qga/get-time", &fix, test_qga_get_time);
1115da668aa1SThomas Huth g_test_add_data_func("/qga/id", &fix, test_qga_id);
1116da668aa1SThomas Huth g_test_add_data_func("/qga/invalid-oob", &fix, test_qga_invalid_oob);
1117da668aa1SThomas Huth g_test_add_data_func("/qga/invalid-cmd", &fix, test_qga_invalid_cmd);
1118da668aa1SThomas Huth g_test_add_data_func("/qga/invalid-args", &fix, test_qga_invalid_args);
1119da668aa1SThomas Huth g_test_add_data_func("/qga/fsfreeze-status", &fix,
1120da668aa1SThomas Huth test_qga_fsfreeze_status);
1121da668aa1SThomas Huth
1122ebf70554SThomas Huth g_test_add_data_func("/qga/blockedrpcs", NULL, test_qga_blockedrpcs);
1123fcd1ab3aSKonstantin Kostiuk g_test_add_data_func("/qga/allowedrpcs", NULL, test_qga_allowedrpcs);
1124da668aa1SThomas Huth g_test_add_data_func("/qga/config", NULL, test_qga_config);
1125da668aa1SThomas Huth g_test_add_data_func("/qga/guest-exec", &fix, test_qga_guest_exec);
1126c7d74f27SDaniel Xu g_test_add_data_func("/qga/guest-exec-separated", &fix,
1127c7d74f27SDaniel Xu test_qga_guest_exec_separated);
1128c7d74f27SDaniel Xu g_test_add_data_func("/qga/guest-exec-merged", &fix,
1129c7d74f27SDaniel Xu test_qga_guest_exec_merged);
1130da668aa1SThomas Huth g_test_add_data_func("/qga/guest-exec-invalid", &fix,
1131da668aa1SThomas Huth test_qga_guest_exec_invalid);
1132da668aa1SThomas Huth g_test_add_data_func("/qga/guest-get-osinfo", &fix,
1133da668aa1SThomas Huth test_qga_guest_get_osinfo);
1134da668aa1SThomas Huth g_test_add_data_func("/qga/guest-get-host-name", &fix,
1135da668aa1SThomas Huth test_qga_guest_get_host_name);
1136da668aa1SThomas Huth g_test_add_data_func("/qga/guest-get-timezone", &fix,
1137da668aa1SThomas Huth test_qga_guest_get_timezone);
1138da668aa1SThomas Huth g_test_add_data_func("/qga/guest-get-users", &fix,
1139da668aa1SThomas Huth test_qga_guest_get_users);
1140da668aa1SThomas Huth
1141da668aa1SThomas Huth ret = g_test_run();
1142da668aa1SThomas Huth
1143da668aa1SThomas Huth fixture_tear_down(&fix, NULL);
1144da668aa1SThomas Huth
1145da668aa1SThomas Huth return ret;
1146da668aa1SThomas Huth }
1147